Matrix/0000755000175100001440000000000014577245211011544 5ustar hornikusersMatrix/NAMESPACE0000644000175100001440000002476614575137654013013 0ustar hornikusersuseDynLib(Matrix, .registration = TRUE) ## ==== IMPORTS ======================================================== ## Try to import all of the functions that we need ## (including generic functions for which we define methods), ## but not more ... importFrom("grDevices", colorRampPalette, grey) importFrom("graphics", image, par) importFrom("grid", convertHeight, convertWidth, current.viewport, gpar, grid.rect) importFrom("lattice", levelplot, panel.levelplot.raster) importFrom("methods", .hasSlot, .selectSuperClasses, .slotNames, Arith, Compare, Complex, Logic, Math, Math2, Ops, Summary, as, callGeneric, callNextMethod, canCoerce, cbind2, coerce, extends, getClassDef, getGroupMembers, is, isClassDef, kronecker, new, rbind2, setAs, setClass, setClassUnion, setGeneric, setMethod, setOldClass, show, slot, "slot<-", slotNames, validObject) importFrom("stats", contr.SAS, contr.helmert, contr.poly, contr.sum, contr.treatment, "contrasts<-", cov2cor , diffinv, model.frame, rnorm, runif, symnum, terms, toeplitz, update) importFrom("utils", capture.output, head, head.matrix, str, tail, tail.matrix) ## ==== EXPORTS ======================================================== ## ---- Non-generic functions ------------------------------------------ export(.M2C, .M2R, .M2T, .M2V, .M2diag, .M2gen, .M2kind, .M2m, .M2packed, .M2sym, .M2tri, .M2unpacked, .M2v, .bdiag, .dense2sparse, .diag.dsC, .diag2dense, .diag2sparse, .diagN2U, .diagU2N, .ind2dense, .ind2sparse, .formatSparseSimple, .m2V, .m2dense, .m2sparse, .sparse2dense, .sparseDiagonal, .symDiagonal, .trDiagonal, .solve.dgC.chol, .solve.dgC.lu, .solve.dgC.qr, .tCRT, .updateCHMfactor, .validateCsparse, Diagonal, Hilbert, KhatriRao, Matrix, Matrix.Version, MatrixClass, T2graph, abIseq, abIseq1, aggregateT, anyDuplicatedT, asPerm, asUniqueT, bandSparse, bdiag, ## 'c' dispatches on first argument only, so allow direct method calls : ## c.Matrix, # not yet (see below) c.sparseVector, colScale, condest, det, diagN2U, diagU2N, dimScale, dmperm, drop0, fac2Sparse, fac2sparse, formatSpMatrix, formatSparseM, graph2T, invPerm, invertPerm, is.null.DN, isLDL, isPerm, isUniqueT, mat2triplet, nearPD, onenormest, qr2rankMatrix, qrR, printSpMatrix, printSpMatrix2, rankMatrix, readHB, readMM, rep2abI, rowScale, rsparsematrix, signPerm, spMatrix, sparse.model.matrix, sparseMatrix, sparseVector) ## Deprecated since Matrix 1.5-4 {Apr 2023} export(..2dge, .C2nC, .T2Cmat, .asmatrix, .dense2sy, .diag2mat, .diag2sT, .diag2tT, .dsy2dsp, .dsy2mat, .dxC2mat, .m2dgC, .m2lgC, .m2ngC, .m2ngCn, .m2ngTn, .n2dgT, .nC2d, .nC2l) ## Defunct since Matrix 1.3-3 {May 2021} export(cBind, rBind) ## Redundant now but not yet deprecated ... export(.CR2RC, .CR2T, .SuiteSparse_version, .T2CR, .dense2g, .dense2kind, .dense2m, .dense2v, .sparse2g, .sparse2kind, .sparse2m, .sparse2v, .tCR2RC, uniqTsparse) ## ---- S3 generic functions ------------------------------------------- ## export() # {probably none ever} ## ---- S3 methods ----------------------------------------------------- ## So that dispatch also happens inside of 'base' functions: S3method(as.matrix, Matrix) S3method(as.matrix, sparseVector) S3method(as.array, Matrix) S3method(as.array, sparseVector) ## Because S4 dispatch is "hard" for c(): ## S3method(c, Matrix) # breaks 7 rev. dep. {2023-09-08} S3method(c, sparseVector) S3method(c, abIndex) ## For printing return values of our summary() methods: S3method(print, diagSummary) S3method(print, sparseSummary) ## ---- S4 generic functions, methods ---------------------------------- export(crossprod, tcrossprod) # *necessary* (once .Primitive in base) ## MJ: why these and not also export(dim, ...) which are also primitive ?? ## From 'Matrix' {no need to also export(); see WRE} exportMethods("%&%", BunchKaufman, Cholesky, Schur, band, expand, expand1, expand2, expm, facmul, forceSymmetric, isDiagonal, isTriangular, lu, nnzero, pack, skewpart, symmpart, tril, triu, unpack, updown, writeMM) ## From 'base' exportMethods("!", "%*%", "+", all.equal, as.array, as.complex, as.integer, as.logical, as.matrix, as.numeric, as.vector, chol, chol2inv, colMeans, colSums, crossprod, determinant, diag, "diag<-", diff, dim, "dim<-", dimnames, "dimnames<-", drop, format, is.finite, is.infinite, is.na, isSymmetric, kronecker, length, mean, norm, print, qr, qr.Q, qr.R, qr.X, qr.coef, qr.fitted, qr.resid, qr.qty, qr.qy, rcond, rep, rowMeans, rowSums, solve, summary, t, tcrossprod, unname, which, zapsmall) ## From 'graphics' exportMethods(image) ## From 'methods' exportMethods(Arith, Compare, Logic, Math, Math2, Ops, Summary, cbind2, coerce, rbind2, show) ## From 'stats' exportMethods(cov2cor, toeplitz, update) ## From 'utils' exportMethods(head, tail) ## ---- S4 CLASSES ----------------------------------------------------- exportClasses(Matrix, # and its subclasses ............................. generalMatrix, symmetricMatrix, triangularMatrix, diagonalMatrix, denseMatrix, unpackedMatrix, packedMatrix, sparseMatrix, CsparseMatrix, RsparseMatrix, TsparseMatrix, nMatrix, ndenseMatrix, ngeMatrix, nsyMatrix, nspMatrix, ntrMatrix, ntpMatrix, nsparseMatrix, ngCMatrix, ngRMatrix, ngTMatrix, nsCMatrix, nsRMatrix, nsTMatrix, ntCMatrix, ntRMatrix, ntTMatrix, ndiMatrix, lMatrix, ldenseMatrix, lgeMatrix, lsyMatrix, lspMatrix, ltrMatrix, ltpMatrix, lsparseMatrix, lgCMatrix, lgRMatrix, lgTMatrix, lsCMatrix, lsRMatrix, lsTMatrix, ltCMatrix, ltRMatrix, ltTMatrix, ldiMatrix, iMatrix, ## idenseMatrix, ## igeMatrix, ## isyMatrix, ## ispMatrix, ## itrMatrix, ## itpMatrix, ## isparseMatrix, ## igCMatrix, ## igRMatrix, ## igTMatrix, ## isCMatrix, ## isRMatrix, ## isTMatrix, ## itCMatrix, ## itRMatrix, ## itTMatrix, ## idiMatrix, dMatrix, ddenseMatrix, dgeMatrix, dsyMatrix, dspMatrix, dpoMatrix, dppMatrix, corMatrix, copMatrix, dtrMatrix, dtpMatrix, dsparseMatrix, dgCMatrix, dgRMatrix, dgTMatrix, dsCMatrix, dsRMatrix, dsTMatrix, dtCMatrix, dtRMatrix, dtTMatrix, ddiMatrix, zMatrix, ## zdenseMatrix, ## zgeMatrix, ## zsyMatrix, ## zspMatrix, ## ztrMatrix, ## ztpMatrix, ## zsparseMatrix, ## zgCMatrix, ## zgRMatrix, ## zgTMatrix, ## zsCMatrix, ## zsRMatrix, ## zsTMatrix, ## ztCMatrix, ## ztRMatrix, ## ztTMatrix, ## zdiMatrix, indMatrix, pMatrix, MatrixFactorization, # and its subclasses ................ LU, denseLU, sparseLU, QR, ## denseQR, sparseQR, SchurFactorization, Schur, BunchKaufmanFactorization, BunchKaufman, pBunchKaufman, CholeskyFactorization, Cholesky, pCholesky, CHMfactor, CHMsuper, dCHMsuper, nCHMsuper, # unused CHMsimpl, dCHMsimpl, nCHMsimpl, # unused sparseVector, # and its subclasses ....................... nsparseVector, lsparseVector, isparseVector, dsparseVector, zsparseVector, ## MJ: aim to deprecate and eventually remove these ## (except perhaps 'index') abIndex, atomicVector, compMatrix, index, number, replValue, rleDiff) Matrix/.Rinstignore0000644000175100001440000000002414444344620014041 0ustar hornikusers## currently unused Matrix/LICENCE0000644000175100001440000010753714561103552012540 0ustar hornikusersR package Matrix is developed on R-Forge and released on CRAN. It has two components: 1. The source code of Matrix, excluding external libraries, is contained primarily in R/*.R, src/*.[ch], man/*.Rd, tests/*.R, vignettes/*.Rnw, inst/*.R, and inst/include/*. It is licensed under the GNU GPL, version 3, pasted below. The files were created and are maintained by Douglas Bates, Martin Maechler, and Mikael Jagan, hence they are: Copyright (C) 1999-2020 Douglas Bates, Martin Maechler Copyright (C) 2021-2024 Douglas Bates, Martin Maechler, Mikael Jagan 2. Matrix contains patched versions of external libraries CXSparse, AMD, COLAMD, CCAMD, CCOLAMD, and CHOLMOD, all from the SuiteSparse collection of Timothy A. Davis. AMD, COLAMD, CAMD, and CCOLAMD use the BSD 3-clause licence. CXSparse and CHOLMOD modules Check, Cholesky, Partition, and Utility use the GNU LGPL licence, version 2.1 or greater. CHOLMOD modules MatrixOps, Modify, and Supernodal use the GNU GPL licence, version 2 or greater. Compiled into CHOLMOD is the METIS library, which uses the Apache licence, version 2.0. Licence files and copyrights are copied under inst/doc/SuiteSparse. Douglas M. Bates University of Wisconsin-Madison bates@stat.wisc.edu Martin Maechler ETH Zurich maechler@stat.math.ethz.ch | maechler@r-project.org Mikael Jagan McMaster University jaganmn@mcmaster.ca The following is obtained from http://www.gnu.org/licenses/gpl-3.0.txt : --------------------------------------- GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 3 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, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . Matrix/data/0000755000175100001440000000000014576343415012461 5ustar hornikusersMatrix/data/USCounties.R0000644000175100001440000000073513612521507014640 0ustar hornikusersstopifnot(requireNamespace("Matrix" , quietly = TRUE)) # includes 'methods' USCounties <- local({ load(system.file(file.path("external", "USCounties_slots.rda"), package = "Matrix")) ## -> 'L' r <- methods::new("dsCMatrix") `slot<-` <- methods::`slot<-` for (n in c("Dim", "i","p","x")) slot(r, n) <- L[[n]] r }) ## The reverse: if(FALSE) { L <- list() for (n in c("Dim", "i","p","x")) L[[n]] <- slot(USCounties, n) } Matrix/data/datalist0000644000175100001440000000003713517134750014203 0ustar hornikusersCAex KNex USCounties wrld_1deg Matrix/data/KNex.R0000644000175100001440000000057513612521507013446 0ustar hornikusersstopifnot(requireNamespace("Matrix" , quietly = TRUE)) # includes 'methods' KNex <- local({ load(system.file(file.path("external", "KNex_slots.rda"), package = "Matrix")) ## -> 'L' r <- list(mm = methods::new("dgCMatrix"), y = L[["y"]]) `slot<-` <- methods::`slot<-` for (n in c("Dim", "i","p","x")) ## needs methods::slot<- slot(r$mm, n) <- L[[n]] r }) Matrix/data/CAex.R0000644000175100001440000000102013612521507013403 0ustar hornikusersstopifnot(requireNamespace("Matrix" , quietly = TRUE)) # includes 'methods' CAex <- local({ load(system.file(file.path("external", "CAex_slots.rda"), package = "Matrix")) ## -> 'L' r <- methods::new("dgCMatrix") for (n in c("Dim", "i","p","x")) methods::slot(r, n) <- L[[n]] r }) ## The reverse { CAex |--> L } is if(FALSE) { sNms <- c("Dim", "i", "p", "x") L <- lapply(sNms, function(N) slot(CAex, N)); names(L) <- sNms save(L, file = "/u/maechler/R/Pkgs/Matrix/inst/external/CAex_slots.rda") } Matrix/data/wrld_1deg.R0000644000175100001440000000067313612521507014450 0ustar hornikusersstopifnot(requireNamespace("Matrix" , quietly = TRUE)) # includes 'methods' wrld_1deg <- local({ load(system.file(file.path("external", "wrld_1deg_slots.rda"), package = "Matrix")) ## -> 'L' r <- methods::new("dsCMatrix") for (n in c("Dim", "i","p","x")) methods::slot(r, n) <- L[[n]] r }) if(FALSE) {## The reverse: L <- list() for (n in c("Dim", "i","p","x")) L[[n]] <- slot(wrld_1deg, n) } Matrix/man/0000755000175100001440000000000014576343415012323 5ustar hornikusersMatrix/man/cbind2-methods.Rd0000644000175100001440000000615614575137654015431 0ustar hornikusers\name{cbind2-methods} \title{'cbind()' and 'rbind()' recursively built on cbind2/rbind2} % \docType{methods} \keyword{array} \keyword{manip} \keyword{methods} % \alias{cbind2} \alias{cbind2-methods} \alias{rbind2} \alias{rbind2-methods} % \alias{cbind2,Matrix,Matrix-method} \alias{cbind2,Matrix,NULL-method} \alias{cbind2,Matrix,matrix-method} \alias{cbind2,Matrix,missing-method} \alias{cbind2,Matrix,vector-method} \alias{cbind2,NULL,Matrix-method} \alias{cbind2,matrix,Matrix-method} \alias{cbind2,vector,Matrix-method} % \alias{rbind2,Matrix,Matrix-method} \alias{rbind2,Matrix,NULL-method} \alias{rbind2,Matrix,matrix-method} \alias{rbind2,Matrix,missing-method} \alias{rbind2,Matrix,vector-method} \alias{rbind2,NULL,Matrix-method} \alias{rbind2,matrix,Matrix-method} \alias{rbind2,vector,Matrix-method} % \description{ The base functions \code{\link{cbind}} and \code{\link{rbind}} are defined for an arbitrary number of arguments and hence have the first formal argument \code{...}. Now, when S4 objects are found among the arguments, base \code{cbind()} and \code{rbind()} internally \dQuote{dispatch} \emph{recursively}, calling \code{\link{cbind2}} or \code{\link{rbind2}} respectively, where these have methods defined and so should dispatch appropriately. \code{\link{cbind2}()} and \code{\link{rbind2}()} are from the \pkg{methods} package, i.e., standard \R, and have been provided for binding together \emph{two} matrices, where in \pkg{Matrix}, we have defined methods for these and the \code{'Matrix'} matrices. } \usage{ ## cbind(..., deparse.level = 1) ## rbind(..., deparse.level = 1) \S4method{cbind2}{Matrix,Matrix}(x, y, \dots) \S4method{rbind2}{Matrix,Matrix}(x, y, \dots) } \arguments{ \item{\dots}{for \code{[cr]bind}, vector- or matrix-like \R objects to be bound together; for \code{[cr]bind2}, further arguments passed to or from methods; see \code{\link{cbind}} and \code{\link[methods]{cbind2}}.} \item{deparse.level}{integer controlling the construction of labels in the case of non-matrix-like arguments; see \code{\link{cbind}}.} \item{x, y}{vector- or matrix-like \R objects to be bound together.} } \value{ typically a \sQuote{matrix-like} object of a similar \code{\link{class}} as the first argument in \code{\dots}. Note that sometimes by default, the result is a \code{\linkS4class{sparseMatrix}} if one of the arguments is (even in the case where this is not efficient). In other cases, the result is chosen to be sparse when there are more zero entries is than non-zero ones (as the default \code{sparse} in \code{\link{Matrix}()}). } \author{Martin Maechler} \seealso{\code{\link{cbind}}, \code{\link[methods]{cbind2}}. Our class definition help pages mentioning \code{cbind2()} and \code{rbind2()} methods: \code{"\linkS4class{denseMatrix}"}, \code{"\linkS4class{diagonalMatrix}"}, \code{"\linkS4class{indMatrix}"}. } \examples{ (a <- matrix(c(2:1,1:2), 2,2)) (M1 <- cbind(0, rbind(a, 7))) # a traditional matrix D <- Diagonal(2) (M2 <- cbind(4, a, D, -1, D, 0)) # a sparse Matrix stopifnot(validObject(M2), inherits(M2, "sparseMatrix"), dim(M2) == c(2,9)) } Matrix/man/printSpMatrix.Rd0000644000175100001440000001535314561342731015437 0ustar hornikusers\name{printSpMatrix} \title{Format and Print Sparse Matrices Flexibly} % \keyword{character} \keyword{print} \keyword{utilities} % \alias{formatSpMatrix} \alias{printSpMatrix} \alias{printSpMatrix2} % \description{ Format and print sparse matrices flexibly. These are the \dQuote{workhorses} used by the \code{\link{format}}, \code{\link{show}} and \code{\link{print}} methods for sparse matrices. If \code{x} is large, \code{printSpMatrix2(x)} calls \code{printSpMatrix()} twice, namely, for the first and the last few rows, suppressing those in between, and also suppresses columns when \code{x} is too wide. \code{printSpMatrix()} basically prints the result of \code{formatSpMatrix()}. } \usage{ formatSpMatrix(x, digits = NULL, maxp = 1e9, cld = getClassDef(class(x)), zero.print = ".", col.names, note.dropping.colnames = TRUE, uniDiag = TRUE, align = c("fancy", "right"), \dots) printSpMatrix(x, digits = NULL, maxp = max(100L, getOption("max.print")), cld = getClassDef(class(x)), zero.print = ".", col.names, note.dropping.colnames = TRUE, uniDiag = TRUE, col.trailer = "", align = c("fancy", "right"), \dots) printSpMatrix2(x, digits = NULL, maxp = max(100L, getOption("max.print")), zero.print = ".", col.names, note.dropping.colnames = TRUE, uniDiag = TRUE, suppRows = NULL, suppCols = NULL, col.trailer = if(suppCols) "......" else "", align = c("fancy", "right"), width = getOption("width"), fitWidth = TRUE, \dots) } \arguments{ \item{x}{an \R object inheriting from class \code{\linkS4class{sparseMatrix}}.} \item{digits}{significant digits to use for printing, see \code{\link{print.default}}, the default, \code{\link{NULL}}, corresponds to using \code{\link{getOption}("digits")}.} \item{maxp}{integer, default from \code{\link{options}(max.print)}, influences how many entries of large matrices are printed at all. Typically should not be smaller than around 1000; values smaller than 100 are silently \dQuote{rounded up} to 100.}% for now \item{cld}{the class definition of \code{x}; must be equivalent to \code{\link{getClassDef}(class(x))} and exists mainly for possible speedup.} \item{zero.print}{character which should be printed for \emph{structural} zeroes. The default \code{"."} may occasionally be replaced by \code{" "} (blank); using \code{"0"} would look almost like \code{print()}ing of non-sparse matrices.} \item{col.names}{logical or string specifying if and how column names of \code{x} should be printed, possibly abbreviated. The default is taken from \code{\link{options}("sparse.colnames")} if that is set, otherwise \code{FALSE} unless there are less than ten columns. When \code{TRUE} the full column names are printed.\cr When \code{col.names} is a string beginning with \code{"abb"} or \code{"sub"} and ending with an integer \code{n} (i.e., of the form \code{"abb... "}), the column names are \code{\link{abbreviate}()}d or \code{\link{substring}()}ed to (target) length \code{n}, see the examples. } \item{note.dropping.colnames}{logical specifying, when \code{col.names} is \code{FALSE} if the dropping of the column names should be noted, \code{TRUE} by default.} \item{uniDiag}{logical indicating if the diagonal entries of a sparse unit triangular or unit-diagonal matrix should be formatted as \code{"I"} instead of \code{"1"} (to emphasize that the 1's are \dQuote{structural}).} \item{col.trailer}{a string to be appended to the right of each column; this is typically made use of by \code{\link{show}()} only, when suppressing columns.} \item{suppRows, suppCols}{logicals or \code{NULL}, for \code{printSpMatrix2()} specifying if rows or columns should be suppressed in printing. If \code{NULL}, sensible defaults are determined from \code{\link{dim}(x)} and \code{\link{options}(c("width", "max.print"))}. Setting both to \code{FALSE} may be a very bad idea.} \item{align}{a string specifying how the \code{zero.print} codes should be aligned, i.e., padded as strings. The default, \code{"fancy"}, takes some effort to align the typical \code{zero.print = "."} with the position of \code{0}, i.e., the first decimal (one left of decimal point) of the numbers printed, whereas \code{align = "right"} just makes use of \code{\link{print}(*, right = TRUE)}.} \item{width}{number, a positive integer, indicating the approximately desired (line) width of the output, see also \code{fitWidth}.} \item{fitWidth}{logical indicating if some effort should be made to match the desired \code{width} or temporarily enlarge that if deemed necessary.} \item{\dots}{unused optional arguments.} } \details{ \describe{ \item{formatSpMatrix:}{ If \code{x} is large, only the first rows making up the approximately first \code{maxp} entries is used, otherwise all of \code{x}. \code{\link{.formatSparseSimple}()} is applied to (a dense version of) the matrix. Then, \code{\link{formatSparseM}} is used, unless in trivial cases or for sparse matrices without \code{x} slot.} } } \value{ \item{formatSpMatrix()}{returns a character matrix with possibly empty column names, depending on \code{col.names} etc, see above.} \item{printSpMatrix*()}{return \code{x} \emph{invisibly}, see \code{\link{invisible}}.} } \author{Martin Maechler} \seealso{the virtual class \code{\linkS4class{sparseMatrix}} and the classes extending it; maybe \code{\link{sparseMatrix}} or \code{\link{spMatrix}} as simple constructors of such matrices. The underlying utilities \code{\link{formatSparseM}} and \code{.formatSparseSimple()} (on the same page). } \examples{ f1 <- gl(5, 3, labels = LETTERS[1:5]) X <- as(f1, "sparseMatrix") X ## <==> show(X) <==> print(X) t(X) ## shows column names, since only 5 columns X2 <- as(gl(12, 3, labels = paste(LETTERS[1:12],"c",sep=".")), "sparseMatrix") X2 ## less nice, but possible: print(X2, col.names = TRUE) # use [,1] [,2] .. => does not fit ## Possibilities with column names printing: t(X2) # suppressing column names print(t(X2), col.names=TRUE) print(t(X2), zero.print = "", col.names="abbr. 1") print(t(X2), zero.print = "-", col.names="substring 2") \dontshow{% show() was slow in 0.9975-8 because of slow adjust="fancy" op <- options(max.print = 25000, width = 80) sink(print(tempfile())) M <- Matrix(0, 10000, 100) M[1,1] <- M[2,3] <- 3.14 st <- system.time(show(M)) sink() st if(interactive() || nzchar(Sys.getenv("R_MATRIX_CHECK_EXTRA"))) ## valgrind (2023-07-26) gave 10.5 sec! stopifnot(st[1] < 1.0) # only 0.09 on cmath-3 options(op) } } Matrix/man/externalFormats.Rd0000644000175100001440000000737614446607050015777 0ustar hornikusers\name{externalFormats} \title{Read and write external matrix formats} % \docType{methods} \keyword{connection} \keyword{file} \keyword{methods} \keyword{utilities} % \alias{readHB} \alias{readMM} %\alias{writeHB} \alias{writeMM} % \alias{writeMM,CsparseMatrix-method} \alias{writeMM,sparseMatrix-method} % \description{ Read matrices stored in the Harwell-Boeing or MatrixMarket formats or write \code{\linkS4class{sparseMatrix}} objects to one of these formats. } \usage{ readHB(file) readMM(file) writeMM(obj, file, \dots) } \arguments{ \item{obj}{a real sparse matrix} \item{file}{for \code{writeMM} - the name of the file to be written. For \code{readHB} and \code{readMM} the name of the file to read, as a character scalar. The names of files storing matrices in the Harwell-Boeing format usually end in \code{".rua"} or \code{".rsa"}. Those storing matrices in the MatrixMarket format usually end in \code{".mtx"}. Alternatively, \code{readHB} and \code{readMM} accept connection objects.} \item{\dots}{optional additional arguments. Currently none are used in any methods.} } \value{ The \code{readHB} and \code{readMM} functions return an object that inherits from the \code{"\linkS4class{Matrix}"} class. Methods for the \code{writeMM} generic functions usually return \code{\link{NULL}} and, as a side effect, the matrix \code{obj} is written to \code{file} in the MatrixMarket format (writeMM). } \note{ The Harwell-Boeing format is older and less flexible than the MatrixMarket format. The function \code{writeHB} was deprecated and has now been removed. Please use \code{writeMM} instead. Note that these formats do \emph{not} know anything about \code{\link{dimnames}}, hence these are dropped by \code{writeMM()}. A very simple way to export small sparse matrices \code{S}, is to use \code{summary(S)} which returns a \code{\link{data.frame}} with columns \code{i}, \code{j}, and possibly \code{x}, see \code{summary} in \code{\link{sparseMatrix-class}}, and an example below. } \references{ \url{https://math.nist.gov/MatrixMarket/} \url{https://sparse.tamu.edu/}% was https://www.cise.ufl.edu/research/sparse/matrices/ } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } str(pores <- readMM(system.file("external/pores_1.mtx", package = "Matrix"))) str(utm <- readHB(system.file("external/utm300.rua" , package = "Matrix"))) str(lundA <- readMM(system.file("external/lund_a.mtx" , package = "Matrix"))) str(lundA <- readHB(system.file("external/lund_a.rsa" , package = "Matrix"))) ## https://math.nist.gov/MatrixMarket/data/Harwell-Boeing/counterx/counterx.htm str(jgl <- readMM(system.file("external/jgl009.mtx" , package = "Matrix"))) ## NOTE: The following examples take quite some time ## ---- even on a fast internet connection: if(FALSE) { ## The URL has been corrected, but we need an untar step: u. <- url("https://www.cise.ufl.edu/research/sparse/RB/Boeing/msc00726.tar.gz") str(sm <- readHB(gzcon(u.))) } data(KNex, package = "Matrix") ## Store as MatrixMarket (".mtx") file, here inside temporary dir./folder: (MMfile <- file.path(tempdir(), "mmMM.mtx")) writeMM(KNex$mm, file=MMfile) file.info(MMfile)[,c("size", "ctime")] # (some confirmation of the file's) ## very simple export - in triplet format - to text file: data(CAex, package = "Matrix") s.CA <- summary(CAex) s.CA # shows (i, j, x) [columns of a data frame] message("writing to ", outf <- tempfile()) write.table(s.CA, file = outf, row.names=FALSE) ## and read it back -- showing off sparseMatrix(): str(dd <- read.table(outf, header=TRUE)) ## has columns (i, j, x) -> we can use via do.call() as arguments to sparseMatrix(): mm <- do.call(sparseMatrix, dd) stopifnot(all.equal(mm, CAex, tolerance=1e-15)) } Matrix/man/chol-methods.Rd0000644000175100001440000001766714575137654015226 0ustar hornikusers\name{chol-methods} \title{Compute the Cholesky Factor of a Matrix} \docType{methods} % \keyword{algebra} \keyword{array} \keyword{methods} % \alias{chol} \alias{chol-methods} % \alias{chol,ddiMatrix-method} \alias{chol,diagonalMatrix-method} \alias{chol,dsCMatrix-method} \alias{chol,dsRMatrix-method} \alias{chol,dsTMatrix-method} \alias{chol,dspMatrix-method} \alias{chol,dsyMatrix-method} \alias{chol,generalMatrix-method} \alias{chol,symmetricMatrix-method} \alias{chol,triangularMatrix-method} % \description{ Computes the upper triangular Cholesky factor of an \eqn{n \times n}{n-by-n} real, symmetric, positive semidefinite matrix \eqn{A}, optionally after pivoting. That is the factor \eqn{L'} in \deqn{P_{1} A P_{1}' = L L'}{P1 * A * P1' = L * L'} or (equivalently) \deqn{A = P_{1}' L L' P_{1}}{A = P1' * L * L' * P1} where \eqn{P_{1}}{P1} is a permutation matrix. Methods for \code{\linkS4class{denseMatrix}} are built on LAPACK routines \code{dpstrf}, \code{dpotrf}, and \code{dpptrf}, The latter two do not permute rows or columns, so that \eqn{P_{1}}{P1} is an identity matrix. Methods for \code{\linkS4class{sparseMatrix}} are built on CHOLMOD routines \code{cholmod_analyze} and \code{cholmod_factorize_p}. } \usage{ chol(x, \dots) \S4method{chol}{dsyMatrix}(x, pivot = FALSE, tol = -1, \dots) \S4method{chol}{dspMatrix}(x, \dots) \S4method{chol}{dsCMatrix}(x, pivot = FALSE, \dots) \S4method{chol}{ddiMatrix}(x, \dots) \S4method{chol}{generalMatrix}(x, uplo = "U", \dots) \S4method{chol}{triangularMatrix}(x, uplo = "U", \dots) } \arguments{ \item{x}{a \link[=is.finite]{finite}, symmetric, positive semidefinite matrix or \code{\linkS4class{Matrix}} to be factorized. If \code{x} is square but not symmetric, then it will be \emph{treated} as symmetric; see \code{uplo}. Methods for dense \code{x} require positive definiteness when \code{pivot = FALSE}. Methods for sparse (but not diagonal) \code{x} require positive definiteness unconditionally.} \item{pivot}{a logical indicating if the rows and columns of \eqn{x} should be pivoted. Methods for sparse \code{x} employ the approximate minimum degree (AMD) algorithm in order to reduce fill-in, i.e., without regard for numerical stability.} \item{tol}{a \link[=is.finite]{finite} numeric tolerance, used only if \code{pivot = TRUE}. The factorization algorithm stops if the pivot is less than or equal to \code{tol}. Negative \code{tol} is equivalent to \code{nrow(x) * .Machine$double.eps * max(diag(x))}.} \item{uplo}{a string, either \code{"U"} or \code{"L"}, indicating which triangle of \code{x} should be used to compute the factorization. The default is \code{"U"}, even for lower triangular \code{x}, to be consistent with \code{\link[base]{chol}} from \pkg{base}.} \item{\dots}{further arguments passed to or from methods.} } \value{ A matrix, \code{\linkS4class{triangularMatrix}}, or \code{\linkS4class{diagonalMatrix}} representing the upper triangular Cholesky factor \eqn{L'}. The result is a traditional matrix if \code{x} is a traditional matrix, dense if \code{x} is dense, and sparse if \code{x} is sparse. } \details{ For \code{x} inheriting from \code{\linkS4class{diagonalMatrix}}, the diagonal result is computed directly and without pivoting, i.e., bypassing CHOLMOD. For all other \code{x}, \code{chol(x, pivot = value)} calls \code{\link{Cholesky}(x, perm = value, \dots)} under the hood. If you must know the permutation \eqn{P_{1}}{P1} in addition to the Cholesky factor \eqn{L'}, then call \code{\link{Cholesky}} directly, as the result of \code{chol(x, pivot = TRUE)} specifies \eqn{L'} but not \eqn{P_{1}}{P1}. } \seealso{ The default method from \pkg{base}, \code{\link[base]{chol}}, called for traditional matrices \code{x}. Generic function \code{\link{Cholesky}}, for more flexibility notably when computing the Cholesky \emph{factorization} and not only the \emph{factor} \eqn{L'}. } \references{ The LAPACK source code, including documentation; see \url{https://netlib.org/lapack/double/dpstrf.f}, \url{https://netlib.org/lapack/double/dpotrf.f}, and \url{https://netlib.org/lapack/double/dpptrf.f}. The CHOLMOD source code; see \url{https://github.com/DrTimothyAldenDavis/SuiteSparse}, notably the header file \file{CHOLMOD/Include/cholmod.h} defining \code{cholmod_factor_struct}. Chen, Y., Davis, T. A., Hager, W. W., & Rajamanickam, S. (2008). Algorithm 887: CHOLMOD, supernodal sparse Cholesky factorization and update/downdate. \emph{ACM Transactions on Mathematical Software}, \emph{35}(3), Article 22, 1-14. \doi{10.1145/1391989.1391995} Amestoy, P. R., Davis, T. A., & Duff, I. S. (2004). Algorithm 837: AMD, an approximate minimum degree ordering algorithm. \emph{ACM Transactions on Mathematical Software}, \emph{17}(4), 886-905. \doi{10.1145/1024074.1024081} Golub, G. H., & Van Loan, C. F. (2013). \emph{Matrix computations} (4th ed.). Johns Hopkins University Press. \doi{10.56021/9781421407944} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) } showMethods("chol", inherited = FALSE) set.seed(0) ## ---- Dense ---------------------------------------------------------- ## chol(x, pivot = value) wrapping Cholesky(x, perm = value) selectMethod("chol", "dsyMatrix") ## Except in packed cases where pivoting is not yet available selectMethod("chol", "dspMatrix") ## .... Positive definite .............................................. (A1 <- new("dsyMatrix", Dim = c(2L, 2L), x = c(1, 2, 2, 5))) (R1.nopivot <- chol(A1)) (R1 <- chol(A1, pivot = TRUE)) ## In 2-by-2 cases, we know that the permutation is 1:2 or 2:1, ## even if in general 'chol' does not say ... stopifnot(exprs = { all.equal( A1 , as(crossprod(R1.nopivot), "dsyMatrix")) all.equal(t(A1[2:1, 2:1]), as(crossprod(R1 ), "dsyMatrix")) identical(Cholesky(A1)@perm, 2:1) # because 5 > 1 }) ## .... Positive semidefinite but not positive definite ................ (A2 <- new("dpoMatrix", Dim = c(2L, 2L), x = c(1, 2, 2, 4))) try(R2.nopivot <- chol(A2)) # fails as not positive definite (R2 <- chol(A2, pivot = TRUE)) # returns, with a warning and ... stopifnot(exprs = { all.equal(t(A2[2:1, 2:1]), as(crossprod(R2), "dsyMatrix")) identical(Cholesky(A2)@perm, 2:1) # because 4 > 1 }) ## .... Not positive semidefinite ...................................... (A3 <- new("dsyMatrix", Dim = c(2L, 2L), x = c(1, 2, 2, 3))) try(R3.nopivot <- chol(A3)) # fails as not positive definite (R3 <- chol(A3, pivot = TRUE)) # returns, with a warning and ... ## _Not_ equal: see details and examples in help("Cholesky") all.equal(t(A3[2:1, 2:1]), as(crossprod(R3), "dsyMatrix")) ## ---- Sparse --------------------------------------------------------- ## chol(x, pivot = value) wrapping ## Cholesky(x, perm = value, LDL = FALSE, super = FALSE) selectMethod("chol", "dsCMatrix") ## Except in diagonal cases which are handled "directly" selectMethod("chol", "ddiMatrix") (A4 <- toeplitz(as(c(10, 0, 1, 0, 3), "sparseVector"))) (ch.A4.nopivot <- Cholesky(A4, perm = FALSE, LDL = FALSE, super = FALSE)) (ch.A4 <- Cholesky(A4, perm = TRUE, LDL = FALSE, super = FALSE)) (R4.nopivot <- chol(A4)) (R4 <- chol(A4, pivot = TRUE)) det4 <- det(A4) b4 <- rnorm(5L) x4 <- solve(A4, b4) stopifnot(exprs = { identical(R4.nopivot, expand1(ch.A4.nopivot, "L.")) identical(R4, expand1(ch.A4, "L.")) all.equal(A4, crossprod(R4.nopivot)) all.equal(A4[ch.A4@perm + 1L, ch.A4@perm + 1L], crossprod(R4)) all.equal(diag(R4.nopivot), sqrt(diag(ch.A4.nopivot))) all.equal(diag(R4), sqrt(diag(ch.A4))) all.equal(sqrt(det4), det(R4.nopivot)) all.equal(sqrt(det4), det(R4)) all.equal(det4, det(ch.A4.nopivot, sqrt = FALSE)) all.equal(det4, det(ch.A4, sqrt = FALSE)) all.equal(x4, solve(R4.nopivot, solve(t(R4.nopivot), b4))) all.equal(x4, solve(ch.A4.nopivot, b4)) all.equal(x4, solve(ch.A4, b4)) }) } Matrix/man/denseLU-class.Rd0000644000175100001440000001155114575137654015264 0ustar hornikusers\name{denseLU-class} \title{Dense LU Factorizations} % \docType{class} \keyword{algebra} \keyword{array} \keyword{classes} % \alias{denseLU-class} % \alias{coerce,denseLU,dgeMatrix-method} \alias{determinant,denseLU,logical-method} % \description{ \code{denseLU} is the class of dense, row-pivoted LU factorizations of \eqn{m \times n}{m-by-n} real matrices \eqn{A}, having the general form \deqn{P_{1} A = L U}{P1 * A = L * U} or (equivalently) \deqn{A = P_{1}' L U}{A = P1' * L * U} where \eqn{P_{1}}{P1} is an \eqn{m \times m}{m-by-m} permutation matrix, \eqn{L} is an \eqn{m \times \min(m,n)}{m-by-min(m,n)} unit lower trapezoidal matrix, and \eqn{U} is a \eqn{\min(m,n) \times n}{min(m,n)-by-n} upper trapezoidal matrix. If \eqn{m = n}, then the factors \eqn{L} and \eqn{U} are triangular. } \section{Slots}{ \describe{ \item{\code{Dim}, \code{Dimnames}}{inherited from virtual class \code{\linkS4class{MatrixFactorization}}.} \item{\code{x}}{a numeric vector of length \code{prod(Dim)} storing the triangular \eqn{L} and \eqn{U} factors together in a packed format. The details of the representation are specified by the manual for LAPACK routine \code{dgetrf}.} \item{\code{perm}}{an integer vector of length \code{min(Dim)} specifying the permutation \eqn{P_{1}}{P1} as a product of transpositions. The corresponding permutation vector can be obtained as \code{\link{asPerm}(perm)}.} } } \section{Extends}{ Class \code{\linkS4class{LU}}, directly. Class \code{\linkS4class{MatrixFactorization}}, by class \code{\linkS4class{LU}}, distance 2. } \section{Instantiation}{ Objects can be generated directly by calls of the form \code{new("denseLU", ...)}, but they are more typically obtained as the value of \code{\link{lu}(x)} for \code{x} inheriting from \code{\linkS4class{denseMatrix}} (often \code{\linkS4class{dgeMatrix}}). } \section{Methods}{ \describe{ \item{\code{coerce}}{\code{signature(from = "denseLU", to = "dgeMatrix")}: returns a \code{\linkS4class{dgeMatrix}} with the dimensions of the factorized matrix \eqn{A}, equal to \eqn{L} below the diagonal and equal to \eqn{U} on and above the diagonal.} \item{\code{determinant}}{\code{signature(from = "denseLU", logarithm = "logical")}: computes the determinant of the factorized matrix \eqn{A} or its logarithm.} \item{\code{expand}}{\code{signature(x = "denseLU")}: see \code{\link{expand-methods}}.} \item{\code{expand1}}{\code{signature(x = "denseLU")}: see \code{\link{expand1-methods}}.} \item{\code{expand2}}{\code{signature(x = "denseLU")}: see \code{\link{expand2-methods}}.} \item{\code{solve}}{\code{signature(a = "denseLU", b = "missing")}: see \code{\link{solve-methods}}.} } } \seealso{ Class \code{\linkS4class{sparseLU}} for sparse LU factorizations. Class \code{\linkS4class{dgeMatrix}}. Generic functions \code{\link{lu}}, \code{\link{expand1}} and \code{\link{expand2}}. } \references{ The LAPACK source code, including documentation; see \url{https://netlib.org/lapack/double/dgetrf.f}. Golub, G. H., & Van Loan, C. F. (2013). \emph{Matrix computations} (4th ed.). Johns Hopkins University Press. \doi{10.56021/9781421407944} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } showClass("denseLU") set.seed(1) n <- 3L (A <- Matrix(round(rnorm(n * n), 2L), n, n)) ## With dimnames, to see that they are propagated : dimnames(A) <- dn <- list(paste0("r", seq_len(n)), paste0("c", seq_len(n))) (lu.A <- lu(A)) str(e.lu.A <- expand2(lu.A), max.level = 2L) ## Underlying LAPACK representation (m.lu.A <- as(lu.A, "dgeMatrix")) # which is L and U interlaced stopifnot(identical(as(m.lu.A, "matrix"), `dim<-`(lu.A@x, lu.A@Dim))) ae1 <- function(a, b, ...) all.equal(as(a, "matrix"), as(b, "matrix"), ...) ae2 <- function(a, b, ...) ae1(unname(a), unname(b), ...) ## A ~ P1' L U in floating point stopifnot(exprs = { identical(names(e.lu.A), c("P1.", "L", "U")) identical(e.lu.A[["P1."]], new( "pMatrix", Dim = c(n, n), Dimnames = c(dn[1L], list(NULL)), margin = 1L, perm = invertPerm(asPerm(lu.A@perm)))) identical(e.lu.A[["L"]], new("dtrMatrix", Dim = c(n, n), Dimnames = list(NULL, NULL), uplo = "L", diag = "U", x = lu.A@x)) identical(e.lu.A[["U"]], new("dtrMatrix", Dim = c(n, n), Dimnames = c(list(NULL), dn[2L]), uplo = "U", diag = "N", x = lu.A@x)) ae1(A, with(e.lu.A, P1. \%*\% L \%*\% U)) ae2(A[asPerm(lu.A@perm), ], with(e.lu.A, L \%*\% U)) }) ## Factorization handled as factorized matrix b <- rnorm(n) stopifnot(identical(det(A), det(lu.A)), identical(solve(A, b), solve(lu.A, b))) } Matrix/man/all.equal-methods.Rd0000644000175100001440000000332714467060443016132 0ustar hornikusers\name{all.equal-methods} \title{Matrix Package Methods for Function all.equal()} % \docType{methods} \keyword{arith} \keyword{logic} \keyword{methods} \keyword{programming} % \alias{all.equal} \alias{all.equal-methods} % \alias{all.equal,Matrix,Matrix-method} \alias{all.equal,Matrix,sparseVector-method} \alias{all.equal,Matrix,vector-method} \alias{all.equal,abIndex,abIndex-method} \alias{all.equal,abIndex,numLike-method} \alias{all.equal,numLike,abIndex-method} \alias{all.equal,sparseVector,Matrix-method} \alias{all.equal,sparseVector,sparseVector-method} \alias{all.equal,sparseVector,vector-method} \alias{all.equal,vector,Matrix-method} \alias{all.equal,vector,sparseVector-method} % \description{ Methods for function \code{\link{all.equal}()} (from \R package \pkg{base}) are defined for all \code{\linkS4class{Matrix}} classes. } \section{Methods}{ \describe{ \item{target = "Matrix", current = "Matrix"}{\ } \item{target = "ANY", current = "Matrix"}{\ } \item{target = "Matrix", current = "ANY"}{these three methods are simply using \code{\link{all.equal.numeric}} directly and work via \code{\link{as.vector}()}.} } There are more methods, notably also for \code{"\linkS4class{sparseVector}"}'s, see \code{showMethods("all.equal")}. } \examples{ showMethods("all.equal") (A <- spMatrix(3,3, i= c(1:3,2:1), j=c(3:1,1:2), x = 1:5)) ex <- expand(lu. <- lu(A)) stopifnot( all.equal(as(A[lu.@p + 1L, lu.@q + 1L], "CsparseMatrix"), lu.@L \%*\% lu.@U), with(ex, all.equal(as(P \%*\% A \%*\% t(Q), "CsparseMatrix"), L \%*\% U)), with(ex, all.equal(as(A, "CsparseMatrix"), t(P) \%*\% L \%*\% U \%*\% Q))) } Matrix/man/Matrix-class.Rd0000644000175100001440000002021614574054462015161 0ustar hornikusers\name{Matrix-class} \title{Virtual Class "Matrix" of Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{Matrix-class} % \alias{!,Matrix-method} \alias{&,Matrix,ddiMatrix-method} \alias{&,Matrix,ldiMatrix-method} \alias{&,Matrix,ndiMatrix-method} \alias{*,Matrix,ddiMatrix-method} \alias{*,Matrix,ldiMatrix-method} \alias{*,Matrix,ndiMatrix-method} \alias{+,Matrix,missing-method} \alias{-,Matrix,missing-method} \alias{Arith,Matrix,Matrix-method} \alias{Arith,Matrix,lsparseMatrix-method} \alias{Arith,Matrix,nsparseMatrix-method} \alias{Logic,ANY,Matrix-method} \alias{Logic,Matrix,ANY-method} \alias{Logic,Matrix,nMatrix-method} \alias{Math2,Matrix-method} \alias{Ops,ANY,Matrix-method} \alias{Ops,Matrix,ANY-method} \alias{Ops,Matrix,NULL-method} \alias{Ops,Matrix,ddiMatrix-method} \alias{Ops,Matrix,ldiMatrix-method} \alias{Ops,Matrix,matrix-method} \alias{Ops,Matrix,sparseVector-method} \alias{Ops,NULL,Matrix-method} \alias{Ops,matrix,Matrix-method} \alias{^,Matrix,ddiMatrix-method} \alias{^,Matrix,ldiMatrix-method} \alias{^,Matrix,ndiMatrix-method} \alias{as.array,Matrix-method} \alias{as.complex,Matrix-method} \alias{as.integer,Matrix-method} \alias{as.logical,Matrix-method} \alias{as.matrix,Matrix-method} \alias{as.numeric,Matrix-method} \alias{as.vector,Matrix-method} \alias{coerce,ANY,Matrix-method} \alias{coerce,Matrix,CsparseMatrix-method} \alias{coerce,Matrix,RsparseMatrix-method} \alias{coerce,Matrix,TsparseMatrix-method} \alias{coerce,Matrix,copMatrix-method} \alias{coerce,Matrix,corMatrix-method} \alias{coerce,Matrix,dMatrix-method} \alias{coerce,Matrix,ddenseMatrix-method} \alias{coerce,Matrix,denseMatrix-method} \alias{coerce,Matrix,diagonalMatrix-method} \alias{coerce,Matrix,dpoMatrix-method} \alias{coerce,Matrix,dppMatrix-method} \alias{coerce,Matrix,dsparseMatrix-method} \alias{coerce,Matrix,generalMatrix-method} \alias{coerce,Matrix,indMatrix-method} \alias{coerce,Matrix,lMatrix-method} \alias{coerce,Matrix,ldenseMatrix-method} \alias{coerce,Matrix,lsparseMatrix-method} \alias{coerce,Matrix,matrix-method} \alias{coerce,Matrix,nMatrix-method} \alias{coerce,Matrix,ndenseMatrix-method} \alias{coerce,Matrix,nsparseMatrix-method} \alias{coerce,Matrix,pMatrix-method} \alias{coerce,Matrix,packedMatrix-method} \alias{coerce,Matrix,sparseMatrix-method} \alias{coerce,Matrix,sparseVector-method} \alias{coerce,Matrix,symmetricMatrix-method} \alias{coerce,Matrix,triangularMatrix-method} \alias{coerce,Matrix,unpackedMatrix-method} \alias{coerce,matrix,Matrix-method} \alias{coerce,vector,Matrix-method} \alias{determinant,Matrix,missing-method} \alias{determinant,Matrix,logical-method} \alias{dim,Matrix-method} \alias{dimnames,Matrix-method} \alias{dimnames<-,Matrix,NULL-method} \alias{dimnames<-,Matrix,list-method} \alias{drop,Matrix-method} \alias{head,Matrix-method} \alias{initialize,Matrix-method} \alias{length,Matrix-method} \alias{tail,Matrix-method} \alias{unname,Matrix-method} \alias{zapsmall,Matrix-method} % \alias{c.Matrix} % \alias{Matrix.Version} % FIXME: belongs in non-existent Matrix-package.Rd \alias{det} % FIXME: ditto % \description{ The \code{Matrix} class is a class contained by all actual classes in the \pkg{Matrix} package. It is a \dQuote{virtual} class. } \section{Slots}{ \describe{ \item{\code{Dim}}{an integer vector of length 2 giving the dimensions of the matrix.} \item{\code{Dimnames}}{a list of length 2. Each element must be \code{NULL} or a character vector of length equal to the corresponding element of \code{Dim}.} } } \section{Methods}{ \describe{ \item{determinant}{\code{signature(x = "Matrix", logarithm = "missing")}: and} \item{determinant}{\code{signature(x = "Matrix", logarithm = "logical")}: compute the (\eqn{\log}) determinant of \code{x}. The method chosen depends on the actual Matrix class of \code{x}. Note that \code{\link[base]{det}} also works for all our matrices, calling the appropriate \code{determinant()} method. The \code{Matrix::det} is an exact copy of \code{base::det}, but in the correct namespace, and hence calling the S4-aware version of \code{determinant()}.).} \item{diff}{\code{signature(x = "Matrix")}: As \code{\link{diff}()} for traditional matrices, i.e., applying \code{diff()} to each column.} \item{dim}{\code{signature(x = "Matrix")}: extract matrix dimensions \code{\link{dim}}.} \item{dim<-}{\code{signature(x = "Matrix", value = "ANY")}: where \code{value} is integer of length 2. Allows to \emph{reshape} Matrix objects, but only when \code{prod(value) == prod(dim(x))}.} \item{dimnames}{\code{signature(x = "Matrix")}: extract \code{\link{dimnames}}.} \item{dimnames<-}{\code{signature(x = "Matrix", value = "list")}: set the \code{dimnames} to a \code{\link{list}} of length 2, see \code{\link{dimnames<-}}.} \item{length}{\code{signature(x = "Matrix")}: simply defined as \code{prod(dim(x))} (and hence of mode \code{"double"}).} \item{show}{\code{signature(object = "Matrix")}: \code{\link{show}} method for \code{\link{print}}ing. For printing \emph{sparse} matrices, see \code{\link{printSpMatrix}}.} \item{zapsmall}{\code{signature(x = "Matrix")}: typically used for \code{"\linkS4class{dMatrix}"}: \code{\link{round}()} matrix entries such that (relatively) very small entries become zero exactly.} \item{image}{\code{signature(object = "Matrix")}: draws an \code{\link{image}} of the matrix entries, using \code{\link[lattice]{levelplot}()} from package \pkg{lattice}.} \item{head}{\code{signature(object = "Matrix")}: return only the \emph{\dQuote{head}}, i.e., the first few rows.} \item{tail}{\code{signature(object = "Matrix")}: return only the \emph{\dQuote{tail}}, i.e., the last few rows of the respective matrix.} \cr %------------------------------------ \item{as.matrix, as.array}{\code{signature(x = "Matrix")}: the same as \code{as(x, "matrix")}; see also the note below.} \item{as.vector}{\code{signature(x = "Matrix", mode = "missing")}: \code{as.vector(m)} should be identical to \code{as.vector(as(m, "matrix"))}, implemented more efficiently for some subclasses.} \item{as(x, "vector"), as(x, "numeric")}{etc, similarly.} \item{coerce}{\code{signature(from = "ANY", to = "Matrix")}: This relies on a correct \code{\link{as.matrix}()} method for \code{from}.} } There are many more methods that (conceptually should) work for all \code{"Matrix"} objects, e.g., \code{\link{colSums}}, \code{\link{rowMeans}}. Even \pkg{base} functions may work automagically (if they first call \code{\link{as.matrix}()} on their principal argument), e.g., \code{\link{apply}}, \code{\link{eigen}}, \code{\link{svd}} or \code{\link{kappa}} all do work via coercion to a \dQuote{traditional} (dense) \code{\link{matrix}}. %% --> ../tests/base-matrix-fun.R } \note{ Loading the \code{Matrix} namespace \dQuote{overloads} \code{\link{as.matrix}} and \code{\link{as.array}} in the \pkg{base} namespace by the equivalent of \code{function(x) as(x, "matrix")}. Consequently, \code{as.matrix(m)} or \code{as.array(m)} will properly work when \code{m} inherits from the \code{"Matrix"} class --- \emph{also} for functions in package \pkg{base} and other packages. E.g., \code{\link{apply}} or \code{\link{outer}} can therefore be applied to \code{"Matrix"} matrices. } \author{Douglas Bates \email{bates@stat.wisc.edu} and Martin Maechler} \seealso{ the classes \code{\linkS4class{dgeMatrix}}, \code{\linkS4class{dgCMatrix}}, and function \code{\link{Matrix}} for construction (and examples). Methods, e.g., for \code{\link[=kronecker-methods]{kronecker}}. } \examples{ slotNames("Matrix") cl <- getClass("Matrix") names(cl@subclasses) # more than 40 .. showClass("Matrix")#> output with slots and all subclasses (M <- Matrix(c(0,1,0,0), 6, 4)) dim(M) diag(M) cm <- M[1:4,] + 10*Diagonal(4) diff(M) ## can reshape it even : dim(M) <- c(2, 12) M stopifnot(identical(M, Matrix(c(0,1,0,0), 2,12)), all.equal(det(cm), determinant(as(cm,"matrix"), log=FALSE)$modulus, check.attributes=FALSE)) } Matrix/man/lsyMatrix-class.Rd0000644000175100001440000000400114467516513015704 0ustar hornikusers\name{lsyMatrix-class} \title{Symmetric Dense Logical Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{lsyMatrix-class} \alias{lspMatrix-class} % \description{ The \code{"lsyMatrix"} class is the class of symmetric, dense logical matrices in non-packed storage and \code{"lspMatrix"} is the class of of these in packed storage. In the packed form, only the upper triangle or the lower triangle is stored. } \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("lsyMatrix", ...)}. } \section{Slots}{ \describe{ \item{\code{uplo}:}{Object of class \code{"character"}. Must be either "U", for upper triangular, and "L", for lower triangular.} \item{\code{x}:}{Object of class \code{"logical"}. The logical values that constitute the matrix, stored in column-major order.} \item{\code{Dim},\code{Dimnames}:}{The dimension (a length-2 \code{"integer"}) and corresponding names (or \code{NULL}), see the \code{\linkS4class{Matrix}} class.} \item{\code{factors}:}{Object of class \code{"list"}. A named list of factorizations that have been computed for the matrix.} } } \section{Extends}{ Both extend classes \code{"\linkS4class{ldenseMatrix}"} and \code{"\linkS4class{symmetricMatrix}"}, directly; further, class \code{"Matrix"} and others, \emph{in}directly. Use \code{\link{showClass}("lsyMatrix")}, e.g., for details. } \section{Methods}{ Currently, mainly \code{\link{t}()} and coercion methods (for \code{\link{as}(.)}; use, e.g., \code{\link{showMethods}(class="lsyMatrix")} for details. } %\references{} %\author{} \seealso{ \code{\linkS4class{lgeMatrix}}, \code{\linkS4class{Matrix}}, \code{\link[base]{t}} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } (M2 <- Matrix(c(TRUE, NA, FALSE, FALSE), 2, 2)) # logical dense (ltr) str(M2) # can (sM <- M2 | t(M2)) # "lge" as(sM, "symmetricMatrix") str(sM <- as(sM, "packedMatrix")) # packed symmetric } Matrix/man/Hilbert.Rd0000644000175100001440000000110014422605232014157 0ustar hornikusers\name{Hilbert} \title{Generate a Hilbert matrix} % \keyword{array} \keyword{utilities} % \alias{Hilbert} % \description{ Generate the \code{n} by \code{n} symmetric Hilbert matrix. Because these matrices are ill-conditioned for moderate to large \code{n}, they are often used for testing numerical linear algebra code. } \usage{ Hilbert(n) } \arguments{ \item{n}{a non-negative integer.} } \value{ the \code{n} by \code{n} symmetric Hilbert matrix as a \code{"dpoMatrix"} object. } \seealso{the class \code{\linkS4class{dpoMatrix}}} \examples{ Hilbert(6) } Matrix/man/ldenseMatrix-class.Rd0000644000175100001440000000346314500644730016351 0ustar hornikusers\name{ldenseMatrix-class} \title{Virtual Class "ldenseMatrix" of Dense Logical Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{ldenseMatrix-class} % \alias{!,ldenseMatrix-method} \alias{&,ldenseMatrix,ddiMatrix-method} \alias{&,ldenseMatrix,ldiMatrix-method} \alias{&,ldenseMatrix,ndiMatrix-method} \alias{*,ldenseMatrix,ddiMatrix-method} \alias{*,ldenseMatrix,ldiMatrix-method} \alias{*,ldenseMatrix,ndiMatrix-method} \alias{Logic,ldenseMatrix,lsparseMatrix-method} \alias{Ops,ldenseMatrix,ldenseMatrix-method} \alias{^,ldenseMatrix,ddiMatrix-method} \alias{^,ldenseMatrix,ldiMatrix-method} \alias{^,ldenseMatrix,ndiMatrix-method} \alias{coerce,matrix,ldenseMatrix-method} \alias{coerce,vector,ldenseMatrix-method} \alias{which,ldenseMatrix-method} % \description{ \code{ldenseMatrix} is the virtual class of all dense \bold{l}ogical (S4) matrices. It extends both \code{\linkS4class{denseMatrix}} and \code{\linkS4class{lMatrix}} directly. } \section{Slots}{ \describe{ \item{\code{x}:}{logical vector containing the entries of the matrix.} \item{\code{Dim}, \code{Dimnames}:}{see \code{\linkS4class{Matrix}}.} } } \section{Extends}{ Class \code{"lMatrix"}, directly. Class \code{"denseMatrix"}, directly. Class \code{"Matrix"}, by class \code{"lMatrix"}. Class \code{"Matrix"}, by class \code{"denseMatrix"}. } \section{Methods}{ \describe{ \item{as.vector}{\code{signature(x = "ldenseMatrix", mode = "missing")}: ...} \item{which}{\code{signature(x = "ndenseMatrix")}, semantically equivalent to \pkg{base} function \code{\link{which}(x, arr.ind)}; for details, see the \code{\linkS4class{lMatrix}} class documentation.} } } \seealso{ Class \code{\linkS4class{lgeMatrix}} and the other subclasses. } \examples{ showClass("ldenseMatrix") as(diag(3) > 0, "ldenseMatrix") } Matrix/man/dmperm.Rd0000644000175100001440000000664314446607050014101 0ustar hornikusers\name{dmperm} \title{Dulmage-Mendelsohn Permutation / Decomposition} % \keyword{algebra} \keyword{array} \keyword{utilities} % \alias{dmperm} % \description{ For any \eqn{n \times m}{n * m} (typically) sparse matrix \code{x} compute the Dulmage-Mendelsohn row and columns permutations which at first splits the \eqn{n} rows and \code{m} columns into coarse partitions each; and then a finer one, reordering rows and columns such that the permutated matrix is \dQuote{as upper triangular} as possible. } \usage{ dmperm(x, nAns = 6L, seed = 0L) } \arguments{ \item{x}{a typically sparse matrix; internally coerced to either \code{"\linkS4class{dgCMatrix}"} or \code{"\linkS4class{dtCMatrix}"}.} \item{nAns}{an integer specifying the \code{\link{length}} of the resulting \code{\link{list}}. Must be 2, 4, or 6. %% FIXME: more } \item{seed}{an integer code in -1,0,1; determining the (initial) permutation; by default, \code{seed = 0}, no (or the identity) permutation; \code{seed = -1} uses the \dQuote{reverse} permutation \code{k:1}; for \code{seed = 1}, it is a \emph{random} permutation (using R's RNG, seed, etc).} } \details{ See the book section by Tim Davis; page 122--127, in the References. } \value{ a named \code{\link{list}} with (by default) 6 components, \item{p}{integer vector with the permutation \code{p}, of length \code{nrow(x)}.} \item{q}{integer vector with the permutation \code{q}, of length \code{ncol(x)}.} %% FIXME: give __examples__ below, showing the blocks !! \item{r}{integer vector of length \code{nb+1}, where block k is rows r[k] to r[k+1]-1 in A[p,q].} \item{s}{integer vector of length \code{nb+1}, where block k is cols s[k] to s[k+1]-1 in A[p,q].} \item{rr5}{integer vector of length 5, defining the coarse row decomposition.}% FIXME: more specifically ? \item{cc5}{integer vector of length 5, defining the coarse column decomposition.} } \references{ Section 7.4 \emph{Dulmage-Mendelsohn decomposition}, pp. 122 ff of \cr Timothy A. Davis (2006) \emph{Direct Methods for Sparse Linear Systems}, SIAM Series \dQuote{Fundamentals of Algorithms}. } \author{Martin Maechler, with a lot of \dQuote{encouragement} by Mauricio Vargas. } %% \note{ %% %% } \seealso{ \code{\link{Schur}}, the class of permutation matrices; \code{"\linkS4class{pMatrix}"}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } set.seed(17) (S9 <- rsparsematrix(9, 9, nnz = 10, symmetric=TRUE)) # dsCMatrix str( dm9 <- dmperm(S9) ) (S9p <- with(dm9, S9[p, q])) ## looks good, but *not* quite upper triangular; these, too: str( dm9.0 <- dmperm(S9, seed=-1)) # non-random too. str( dm9_1 <- dmperm(S9, seed= 1)) # a random one ## The last two permutations differ, but have the same effect! (S9p0 <- with(dm9.0, S9[p, q])) # .. hmm .. stopifnot(all.equal(S9p0, S9p))# same as as default, but different from the random one set.seed(11) (M <- triu(rsparsematrix(9,11, 1/4))) dM <- dmperm(M); with(dM, M[p, q]) (Mp <- M[sample.int(nrow(M)), sample.int(ncol(M))]) dMp <- dmperm(Mp); with(dMp, Mp[p, q]) set.seed(7) (n7 <- rsparsematrix(5, 12, nnz = 10, rand.x = NULL)) str( dm.7 <- dmperm(n7) ) stopifnot(exprs = { lengths(dm.7[1:2]) == dim(n7) identical(dm.7, dmperm(as(n7, "dMatrix"))) identical(dm.7[1:4], dmperm(n7, nAns=4)) identical(dm.7[1:2], dmperm(n7, nAns=2)) }) %% FIXME: Check permutations / blocks etc -- does it work ??? } Matrix/man/solve-methods.Rd0000644000175100001440000002720514552026002015371 0ustar hornikusers\name{solve-methods} \title{Methods in Package \pkg{Matrix} for Function \code{solve}} % \docType{methods} \keyword{algebra} \keyword{array} \keyword{methods} % \alias{solve} \alias{solve-methods} % \alias{solve,ANY,ANY-method} \alias{solve,BunchKaufman,missing-method} \alias{solve,BunchKaufman,dgeMatrix-method} \alias{solve,CHMfactor,missing-method} \alias{solve,CHMfactor,dgeMatrix-method} \alias{solve,CHMfactor,dgCMatrix-method} \alias{solve,Cholesky,missing-method} \alias{solve,Cholesky,dgeMatrix-method} \alias{solve,CsparseMatrix,ANY-method} \alias{solve,Matrix,sparseVector-method} \alias{solve,MatrixFactorization,CsparseMatrix-method} \alias{solve,MatrixFactorization,RsparseMatrix-method} \alias{solve,MatrixFactorization,TsparseMatrix-method} \alias{solve,MatrixFactorization,denseMatrix-method} \alias{solve,MatrixFactorization,dgCMatrix-method} \alias{solve,MatrixFactorization,dgeMatrix-method} \alias{solve,MatrixFactorization,diagonalMatrix-method} \alias{solve,MatrixFactorization,indMatrix-method} \alias{solve,MatrixFactorization,matrix-method} \alias{solve,MatrixFactorization,sparseVector-method} \alias{solve,MatrixFactorization,vector-method} \alias{solve,RsparseMatrix,ANY-method} \alias{solve,Schur,ANY-method} \alias{solve,TsparseMatrix,ANY-method} \alias{solve,ddiMatrix,Matrix-method} \alias{solve,ddiMatrix,matrix-method} \alias{solve,ddiMatrix,missing-method} \alias{solve,ddiMatrix,vector-method} \alias{solve,denseLU,missing-method} \alias{solve,denseLU,dgeMatrix-method} \alias{solve,denseMatrix,ANY-method} \alias{solve,dgCMatrix,denseMatrix-method} \alias{solve,dgCMatrix,matrix-method} \alias{solve,dgCMatrix,missing-method} \alias{solve,dgCMatrix,sparseMatrix-method} \alias{solve,dgCMatrix,vector-method} \alias{solve,dgeMatrix,ANY-method} \alias{solve,diagonalMatrix,ANY-method} \alias{solve,dpoMatrix,ANY-method} \alias{solve,dppMatrix,ANY-method} \alias{solve,dsCMatrix,denseMatrix-method} \alias{solve,dsCMatrix,matrix-method} \alias{solve,dsCMatrix,missing-method} \alias{solve,dsCMatrix,sparseMatrix-method} \alias{solve,dsCMatrix,vector-method} \alias{solve,dspMatrix,ANY-method} \alias{solve,dsyMatrix,ANY-method} \alias{solve,dtCMatrix,dgCMatrix-method} \alias{solve,dtCMatrix,dgeMatrix-method} \alias{solve,dtCMatrix,missing-method} \alias{solve,dtCMatrix,triangularMatrix-method} \alias{solve,dtpMatrix,dgeMatrix-method} \alias{solve,dtpMatrix,missing-method} \alias{solve,dtpMatrix,triangularMatrix-method} \alias{solve,dtrMatrix,dgeMatrix-method} \alias{solve,dtrMatrix,missing-method} \alias{solve,dtrMatrix,triangularMatrix-method} \alias{solve,indMatrix,ANY-method} \alias{solve,matrix,Matrix-method} \alias{solve,matrix,sparseVector-method} \alias{solve,pBunchKaufman,missing-method} \alias{solve,pBunchKaufman,dgeMatrix-method} \alias{solve,pCholesky,missing-method} \alias{solve,pCholesky,dgeMatrix-method} \alias{solve,pMatrix,Matrix-method} \alias{solve,pMatrix,matrix-method} \alias{solve,pMatrix,missing-method} \alias{solve,pMatrix,vector-method} \alias{solve,sparseLU,missing-method} \alias{solve,sparseLU,dgeMatrix-method} \alias{solve,sparseLU,dgCMatrix-method} \alias{solve,sparseQR,missing-method} \alias{solve,sparseQR,dgeMatrix-method} \alias{solve,sparseQR,dgCMatrix-method} \alias{solve,triangularMatrix,CsparseMatrix-method} \alias{solve,triangularMatrix,RsparseMatrix-method} \alias{solve,triangularMatrix,TsparseMatrix-method} \alias{solve,triangularMatrix,denseMatrix-method} \alias{solve,triangularMatrix,dgCMatrix-method} \alias{solve,triangularMatrix,dgeMatrix-method} \alias{solve,triangularMatrix,diagonalMatrix-method} \alias{solve,triangularMatrix,indMatrix-method} \alias{solve,triangularMatrix,matrix-method} \alias{solve,triangularMatrix,vector-method} % \description{ Methods for generic function \code{\link[base]{solve}} for solving linear systems of equations, i.e., for \eqn{X} in \eqn{A X = B}{A * X = B}, where \eqn{A} is a square matrix and \eqn{X} and \eqn{B} are matrices with dimensions consistent with \eqn{A}. } \usage{ solve(a, b, ...) \S4method{solve}{dgeMatrix,ANY}(a, b, tol = .Machine$double.eps, \dots) \S4method{solve}{dgCMatrix,missing}(a, b, sparse = TRUE, \dots) \S4method{solve}{dgCMatrix,matrix}(a, b, sparse = FALSE, \dots) \S4method{solve}{dgCMatrix,denseMatrix}(a, b, sparse = FALSE, \dots) \S4method{solve}{dgCMatrix,sparseMatrix}(a, b, sparse = TRUE, \dots) \S4method{solve}{denseLU,dgeMatrix}(a, b, \dots) \S4method{solve}{BunchKaufman,dgeMatrix}(a, b, \dots) \S4method{solve}{Cholesky,dgeMatrix}(a, b, \dots) \S4method{solve}{sparseLU,dgCMatrix}(a, b, tol = .Machine$double.eps, \dots) \S4method{solve}{sparseQR,dgCMatrix}(a, b, \dots) \S4method{solve}{CHMfactor,dgCMatrix}(a, b, system = c("A", "LDLt", "LD", "DLt", "L", "Lt", "D", "P", "Pt"), \dots) } \arguments{ \item{a}{a \link[=is.finite]{finite} square matrix or \code{\linkS4class{Matrix}} containing the coefficients of the linear system, or otherwise a \code{\linkS4class{MatrixFactorization}}, in which case methods behave (by default) as if the factorized matrix were specified.} \item{b}{a vector, \code{\linkS4class{sparseVector}}, matrix, or \code{\linkS4class{Matrix}} satisfying \code{NROW(b) == nrow(a)}, giving the right-hand side(s) of the linear system. Vectors \code{b} are treated as \code{length(b)}-by-1 matrices. If \code{b} is missing, then methods take \code{b} to be an identity matrix.} \item{tol}{a non-negative number. For \code{a} inheriting from \code{\linkS4class{denseMatrix}}, an error is signaled if the reciprocal one-norm condition number (see \code{\link[base]{rcond}}) of \code{a} is less than \code{tol}, indicating that \code{a} is near-singular. For \code{a} of class \code{\linkS4class{sparseLU}}, an error is signaled if the ratio \code{min(d)/max(d)} is less than \code{tol}, where \code{d = abs(diag(a@U))}. (Interpret with care, as this ratio is a cheap heuristic and \emph{not} in general equal to or even proportional to the reciprocal one-norm condition number.) Setting \code{tol = 0} disables the test.} \item{sparse}{a logical indicating if the result should be formally sparse, i.e., if the result should inherit from virtual class \code{\linkS4class{sparseMatrix}}. Only methods for sparse \code{a} and missing or matrix \code{b} have this argument. Methods for missing or sparse \code{b} use \code{sparse = TRUE} by default. Methods for dense \code{b} use \code{sparse = FALSE} by default.} \item{system}{a string specifying a linear system to be solved. Only methods for \code{a} inheriting from \code{\linkS4class{CHMfactor}} have this argument. See \sQuote{Details}.} \item{\dots}{further arguments passed to or from methods.} } \details{ Methods for general and symmetric matrices \code{a} compute a triangular factorization (LU, Bunch-Kaufman, or Cholesky) and call the method for the corresponding factorization class. The factorization is sparse if \code{a} is. Methods for sparse, symmetric matrices \code{a} attempt a Cholesky factorization and perform an LU factorization only if that fails (typically because \code{a} is not positive definite). Triangular, diagonal, and permutation matrices do not require factorization (they are already \dQuote{factors}), hence methods for those are implemented directly. For triangular \code{a}, solutions are obtained by forward or backward substitution; for diagonal \code{a}, they are obtained by scaling the rows of \code{b}; and for permutations \code{a}, they are obtained by permuting the rows of \code{b}. Methods for dense \code{a} are built on 14 LAPACK routines: class \code{d..Matrix}, where \code{..=(ge|tr|tp|sy|sp|po|pp)}, uses routines \code{d..tri} and \code{d..trs} for missing and non-missing \code{b}, respectively. A corollary is that these methods always give a dense result. Methods for sparse \code{a} are built on CXSparse routines \code{cs_lsolve}, \code{cs_usolve}, and \code{cs_spsolve} and CHOLMOD routines \code{cholmod_solve} and \code{cholmod_spsolve}. By default, these methods give a vector result if \code{b} is a vector, a sparse matrix result if \code{b} is missing or a sparse matrix, and a dense matrix result if \code{b} is a dense matrix. One can override this behaviour by setting the \code{sparse} argument, where available, but that should be done with care. Note that a sparse result may be sparse only in the formal sense and not at all in the mathematical sense, depending on the nonzero patterns of \code{a} and \code{b}. Furthermore, whereas dense results are fully preallocated, sparse results must be \dQuote{grown} in a loop over the columns of \code{b}. Methods for \code{a} of class \code{\linkS4class{sparseQR}} are simple wrappers around \code{\link{qr.coef}}, giving the \emph{least squares} solution in overdetermined cases. Methods for \code{a} inheriting from \code{\linkS4class{CHMfactor}} can solve systems other than the default one \eqn{A X = B}{A * X = B}. The correspondence between its \code{system} argument the system actually solved is outlined in the table below. See \code{\link{CHMfactor-class}} for a definition of notation. \tabular{rrr}{ \code{system} \tab \code{\link{isLDL}(a)=TRUE} \tab \code{\link{isLDL}(a)=FALSE}\cr \code{"A"} \tab \eqn{A X = B}{A * X = B} \tab \eqn{A X = B}{A * X = B}\cr \code{"LDLt"} \tab \eqn{L_{1} D L_{1}' X = B}{L1 * D * L1' * X = B} \tab \eqn{L L' X = B}{L * L' * X = B}\cr \code{"LD"} \tab \eqn{L_{1} D X = B}{L1 * D * X = B} \tab \eqn{L X = B}{L * X = B}\cr \code{"DLt"} \tab \eqn{D L_{1}' X = B}{D * L1' * X = B} \tab \eqn{L' X = B}{L' * X = B}\cr \code{"L"} \tab \eqn{L_{1} X = B}{L1 * X = B} \tab \eqn{L X = B}{L * X = B}\cr \code{"Lt"} \tab \eqn{L_{1}' X = B}{L1' * X = B} \tab \eqn{L' X = B}{L' * X = B}\cr \code{"D"} \tab \eqn{D X = B}{D * X = B} \tab \eqn{X = B}{X = B}\cr \code{"P"} \tab \eqn{X = P_{1} B}{X = P1 * B} \tab \eqn{X = P_{1} B}{X = P1 * B}\cr \code{"Pt"} \tab \eqn{X = P_{1}' B}{X = P1' * B} \tab \eqn{X = P_{1}' B}{X = P1' * B} } } \seealso{ Virtual class \code{\linkS4class{MatrixFactorization}} and its subclasses. Generic functions \code{\link{Cholesky}}, \code{\link{BunchKaufman}}, \code{\link{Schur}}, \code{\link{lu}}, and \code{\link{qr}} for \emph{computing} factorizations. Generic function \code{\link[base]{solve}} from \pkg{base}. Function \code{\link{qr.coef}} from \pkg{base} for computing least squares solutions of overdetermined linear systems. } \examples{ ## A close to symmetric example with "quite sparse" inverse: n1 <- 7; n2 <- 3 dd <- data.frame(a = gl(n1,n2), b = gl(n2,1,n1*n2))# balanced 2-way X <- sparse.model.matrix(~ -1+ a + b, dd)# no intercept --> even sparser XXt <- tcrossprod(X) diag(XXt) <- rep(c(0,0,1,0), length.out = nrow(XXt)) n <- nrow(ZZ <- kronecker(XXt, Diagonal(x=c(4,1)))) image(a <- 2*Diagonal(n) + ZZ \%*\% Diagonal(x=c(10, rep(1, n-1)))) isSymmetric(a) # FALSE image(drop0(skewpart(a))) image(ia0 <- solve(a, tol = 0)) # checker board, dense [but really, a is singular!] try(solve(a, sparse=TRUE))##-> error [ TODO: assertError ] ia. <- solve(a, sparse=TRUE, tol = 1e-19)##-> *no* error if(R.version$arch == "x86_64") ## Fails on 32-bit [Fedora 19, R 3.0.2] from Matrix 1.1-0 on [FIXME ??] only stopifnot(all.equal(as.matrix(ia.), as.matrix(ia0))) a <- a + Diagonal(n) iad <- solve(a) ias <- solve(a, sparse=FALSE) stopifnot(all.equal(as(iad,"denseMatrix"), ias, tolerance=1e-14)) I. <- iad \%*\% a ; image(I.) I0 <- drop0(zapsmall(I.)); image(I0) .I <- a \%*\% iad .I0 <- drop0(zapsmall(.I)) stopifnot( all.equal(as(I0, "diagonalMatrix"), Diagonal(n)), all.equal(as(.I0,"diagonalMatrix"), Diagonal(n)) ) } Matrix/man/ddenseMatrix-class.Rd0000644000175100001440000000346214500644730016340 0ustar hornikusers\name{ddenseMatrix-class} \title{Virtual Class "ddenseMatrix" of Numeric Dense Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{ddenseMatrix-class} % \alias{&,ddenseMatrix,ddiMatrix-method} \alias{&,ddenseMatrix,ldiMatrix-method} \alias{&,ddenseMatrix,ndiMatrix-method} \alias{*,ddenseMatrix,ddiMatrix-method} \alias{*,ddenseMatrix,ldiMatrix-method} \alias{*,ddenseMatrix,ndiMatrix-method} \alias{Arith,ddenseMatrix,logical-method} \alias{Arith,ddenseMatrix,numeric-method} \alias{Arith,ddenseMatrix,sparseVector-method} \alias{Arith,logical,ddenseMatrix-method} \alias{Arith,numeric,ddenseMatrix-method} \alias{^,ddenseMatrix,ddiMatrix-method} \alias{^,ddenseMatrix,ldiMatrix-method} \alias{^,ddenseMatrix,ndiMatrix-method} \alias{coerce,matrix,ddenseMatrix-method} \alias{coerce,vector,ddenseMatrix-method} % \description{This is the virtual class of all dense numeric (i.e., \bold{d}ouble, hence \emph{\dQuote{ddense}}) S4 matrices. Its most important subclass is the \code{\linkS4class{dgeMatrix}} class. %% and now say what the difference is ! __ FIXME __ } \section{Extends}{ Class \code{"dMatrix"} directly; class \code{"Matrix"}, by the above. } \section{Slots}{ the same slots at its subclass \code{\linkS4class{dgeMatrix}}, see there. } \section{Methods}{ Most methods are implemented via \code{as(*, "generalMatrix")} and are mainly used as \dQuote{fallbacks} when the subclass doesn't need its own specialized method. Use \code{\link{showMethods}(class = "ddenseMatrix", where = "package:Matrix")} for an overview. } %\references{} %\note{} \seealso{ The virtual classes \code{\linkS4class{Matrix}}, \code{\linkS4class{dMatrix}}, and \code{\linkS4class{dsparseMatrix}}. } \examples{ showClass("ddenseMatrix") showMethods(class = "ddenseMatrix", where = "package:Matrix") } Matrix/man/drop0.Rd0000644000175100001440000000522114462010167013623 0ustar hornikusers\name{drop0} \title{Drop Non-Structural Zeros from a Sparse Matrix} % \keyword{array} \keyword{manip} \keyword{utilities} % \alias{drop0} % \description{ Deletes \dQuote{non-structural} zeros (i.e., zeros stored explicitly, in memory) from a sparse matrix and returns the result. } \usage{ drop0(x, tol = 0, is.Csparse = NA, give.Csparse = TRUE) } \arguments{ \item{x}{a \code{\linkS4class{Matrix}}, typically inheriting from virtual class \code{\linkS4class{sparseMatrix}}. \code{\linkS4class{denseMatrix}} and traditional vectors and matrices are coerced to \code{\linkS4class{CsparseMatrix}}, with zeros dropped automatically, hence users passing such \code{x} should consider \code{as(x, "CsparseMatrix")} instead, notably in the \code{tol = 0} case.} \item{tol}{a non-negative number. If \code{x} is numeric, then entries less than or equal to \code{tol} in absolute value are deleted.} \item{is.Csparse}{a logical used only if \code{give.Csparse} is \code{TRUE}, indicating if \code{x} already inherits from virtual class \code{\linkS4class{CsparseMatrix}}, in which case coercion is not attempted, permitting some (typically small) speed-up.} \item{give.Csparse}{a logical indicating if the result must inherit from virtual class \code{\linkS4class{CsparseMatrix}}. If \code{FALSE} and \code{x} inherits from \code{\linkS4class{RsparseMatrix}}, \code{\linkS4class{TsparseMatrix}}, or \code{\linkS4class{indMatrix}}, then the result preserves the class of \code{x}. The default value is \code{TRUE} only for backwards compatibility.} } \value{ A \code{\linkS4class{sparseMatrix}}, the result of deleting non-structural zeros from \code{x}, possibly after coercion. } \note{ \code{drop0} is sometimes called in conjunction with \code{\link{zapsmall}}, e.g., when dealing with sparse matrix products; see the example. } \seealso{ Function \code{\link{sparseMatrix}}, for constructing objects inheriting from virtual class \code{\linkS4class{sparseMatrix}}; \code{\link{nnzero}}. } \examples{ (m <- sparseMatrix(i = 1:8, j = 2:9, x = c(0:2, 3:-1), dims = c(10L, 20L))) drop0(m) ## A larger example: t5 <- new("dtCMatrix", Dim = c(5L, 5L), uplo = "L", x = c(10, 1, 3, 10, 1, 10, 1, 10, 10), i = c(0L,2L,4L, 1L, 3L,2L,4L, 3L, 4L), p = c(0L, 3L, 5L, 7:9)) TT <- kronecker(t5, kronecker(kronecker(t5, t5), t5)) IT <- solve(TT) I. <- TT \%*\% IT ; nnzero(I.) # 697 ( == 625 + 72 ) I.0 <- drop0(zapsmall(I.)) ## which actually can be more efficiently achieved by I.. <- drop0(I., tol = 1e-15) stopifnot(all(I.0 == Diagonal(625)), nnzero(I..) == 625) } Matrix/man/dtrMatrix-class-dense.Rd0000644000175100001440000000561314575137654017001 0ustar hornikusers\name{dtrMatrix-class} \title{Triangular, dense, numeric matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{dtrMatrix-class} % \description{ The \code{"dtrMatrix"} class is the class of triangular, dense, numeric matrices in nonpacked storage. The \code{"dtpMatrix"} class is the same except in packed storage, see \code{\link{pack}()}. } \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("dtrMatrix", ...)}. } \section{Slots}{ \describe{ \item{\code{uplo}:}{Object of class \code{"character"}. Must be either "U", for upper triangular, and "L", for lower triangular.} \item{\code{diag}:}{Object of class \code{"character"}. Must be either \code{"U"}, for unit triangular (diagonal is all ones), or \code{"N"}; see \code{\linkS4class{triangularMatrix}}.} \item{\code{x}:}{Object of class \code{"numeric"}. The numeric values that constitute the matrix, stored in column-major order.} \item{\code{Dim}:}{Object of class \code{"integer"}. The dimensions of the matrix which must be a two-element vector of non-negative integers.} } } \section{Extends}{ Class \code{"ddenseMatrix"}, directly. Class \code{"triangularMatrix"}, directly. Class \code{"Matrix"} and others, by class \code{"ddenseMatrix"}. } \section{Methods}{ Among others (such as matrix products, e.g. \code{?\link{crossprod-methods}}), \describe{ \item{norm}{\code{signature(x = "dtrMatrix", type = "character")}: ..} \item{rcond}{\code{signature(x = "dtrMatrix", norm = "character")}: ..} \item{solve}{\code{signature(a = "dtrMatrix", b = "....")}: efficiently use a \dQuote{forwardsolve} or \code{backsolve} for a lower or upper triangular matrix, respectively, see also \code{\link{solve-methods}}.} \item{+, -, *, \dots, ==, >=, \dots}{ all the \code{\link{Ops}} group methods are available. When applied to two triangular matrices, these return a triangular matrix when easily possible.} } } %\references{} %\author{} \seealso{ Classes \code{\linkS4class{ddenseMatrix}}, \code{\linkS4class{dtpMatrix}}, \code{\linkS4class{triangularMatrix}} } \examples{%% this is used from ./dtpMatrix-class.Rd (change with care!) \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } (m <- rbind(2:3, 0:-1)) (M <- as(m, "generalMatrix")) (T <- as(M, "triangularMatrix")) # formally upper triangular (T2 <- as(t(M), "triangularMatrix")) stopifnot(T@uplo == "U", T2@uplo == "L", identical(T2, t(T))) m <- matrix(0,4,4); m[upper.tri(m)] <- 1:6 (t1 <- Matrix(m+diag(,4))) str(t1p <- pack(t1)) (t1pu <- diagN2U(t1p)) stopifnot(exprs = { inherits(t1 , "dtrMatrix"); validObject(t1) inherits(t1p, "dtpMatrix"); validObject(t1p) inherits(t1pu,"dtCMatrix"); validObject(t1pu) t1pu@x == 1:6 all(t1pu == t1p) identical((t1pu - t1)@x, numeric())# sparse all-0 }) } Matrix/man/pack-methods.Rd0000644000175100001440000000761214575137654015204 0ustar hornikusers\name{pack-methods} \title{Representation of Packed and Unpacked Dense Matrices} % \docType{methods} \keyword{array} \keyword{methods} % \alias{pack} \alias{pack-methods} \alias{unpack} \alias{unpack-methods} % \alias{pack,dgeMatrix-method} \alias{pack,lgeMatrix-method} \alias{pack,matrix-method} \alias{pack,ngeMatrix-method} \alias{pack,packedMatrix-method} \alias{pack,sparseMatrix-method} \alias{pack,unpackedMatrix-method} % \alias{unpack,matrix-method} \alias{unpack,packedMatrix-method} \alias{unpack,sparseMatrix-method} \alias{unpack,unpackedMatrix-method} % \description{ \code{pack()} coerces dense symmetric and dense triangular matrices from unpacked format (storing the full matrix) to packed format (storing only one of the upper and lower triangles). \code{unpack()} performs the reverse coercion. The two formats are formalized by the virtual classes \code{"\linkS4class{packedMatrix}"} and \code{"\linkS4class{unpackedMatrix}"}. } \usage{ pack(x, \dots) \S4method{pack}{dgeMatrix}(x, symmetric = NA, upperTri = NA, \dots) \S4method{pack}{lgeMatrix}(x, symmetric = NA, upperTri = NA, \dots) \S4method{pack}{ngeMatrix}(x, symmetric = NA, upperTri = NA, \dots) \S4method{pack}{matrix}(x, symmetric = NA, upperTri = NA, \dots) unpack(x, \dots) } \arguments{ \item{x}{A dense symmetric or dense triangular matrix. \describe{ \item{For \code{pack()}:}{typically an \code{"unpackedMatrix"} or a standard \code{"matrix"}, though \code{"packedMatrix"} are allowed and returned unchanged.} \item{For \code{unpack()}:}{typically a \code{"packedMatrix"}, though \code{"unpackedMatrix"} are allowed and returned unchanged.} } } \item{symmetric}{logical (including \code{NA}) optionally indicating whether \code{x} is symmetric (or triangular).} \item{upperTri}{(for triangular \code{x} only) logical (including \code{NA}) indicating whether \code{x} is upper (or lower) triangular.} \item{\dots}{further arguments passed to or from other methods.} } \value{ \describe{ \item{For \code{pack()}:}{a \code{"packedMatrix"} giving the condensed representation of \code{x}.} \item{For \code{unpack()}:}{an \code{"unpackedMatrix"} giving the full storage representation of \code{x}.} } } \details{ \code{pack(x)} checks matrices \code{x} \emph{not} inheriting from one of the virtual classes \code{"\linkS4class{symmetricMatrix}"} \code{"\linkS4class{triangularMatrix}"} for symmetry (via \code{\link[=isSymmetric-methods]{isSymmetric}()}) then for upper and lower triangularity (via \code{\link{isTriangular}()}) in order to identify a suitable coercion. Setting one or both of \code{symmetric} and \code{upperTri} to \code{TRUE} or \code{FALSE} rather than \code{NA} allows skipping of irrelevant tests for large matrices known to be symmetric or (upper or lower) triangular. Users should \emph{not} assume that \code{pack()} and \code{unpack()} are inverse operations. Specifically, \code{y <- unpack(pack(x))} may not reproduce an \code{"unpackedMatrix"} \code{x} in the sense of \code{\link{identical}()}. See the examples. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } showMethods("pack") (s <- crossprod(matrix(sample(15), 5,3))) # traditional symmetric matrix (sp <- pack(s)) mt <- as.matrix(tt <- tril(s)) (pt <- pack(mt)) stopifnot(identical(pt, pack(tt)), dim(s ) == dim(sp), all(s == sp), dim(mt) == dim(pt), all(mt == pt), all(mt == tt)) showMethods("unpack") (cp4 <- chol(Hilbert(4))) # is triangular tp4 <- pack(cp4) # [t]riangular [p]acked str(tp4) (unpack(tp4)) stopifnot(identical(tp4, pack(unpack(tp4)))) z1 <- new("dsyMatrix", Dim = c(2L, 2L), x = as.double(1:4), uplo = "U") z2 <- unpack(pack(z1)) stopifnot(!identical(z1, z2), # _not_ identical all(z1 == z2)) # but mathematically equal cbind(z1@x, z2@x) # (unused!) lower triangle is "lost" in translation } Matrix/man/chol2inv-methods.Rd0000644000175100001440000000570614516234475016006 0ustar hornikusers\name{chol2inv-methods} \title{Inverse from Cholesky Factor} % \docType{methods} \keyword{algebra} \keyword{array} \keyword{methods} % \alias{chol2inv} \alias{chol2inv-methods} % \alias{chol2inv,ANY-method} \alias{chol2inv,ddiMatrix-method} \alias{chol2inv,diagonalMatrix-method} \alias{chol2inv,dtCMatrix-method} \alias{chol2inv,dtRMatrix-method} \alias{chol2inv,dtTMatrix-method} \alias{chol2inv,dtrMatrix-method} \alias{chol2inv,dtpMatrix-method} \alias{chol2inv,generalMatrix-method} \alias{chol2inv,symmetricMatrix-method} \alias{chol2inv,triangularMatrix-method} % \description{ Given \emph{formally} upper and lower triangular matrices \eqn{U} and \eqn{L}, compute \eqn{(U' U)^{-1}}{(U' U)^(-1)} and \eqn{(L L')^{-1}}{(L L')^(-1)}, respectively. This function can be seen as way to compute the inverse of a symmetric positive definite matrix given its Cholesky factor. Equivalently, it can be seen as a way to compute \eqn{(X' X)^{-1}}{(X' X)^(-1)} given the \eqn{R} part of the QR factorization of \eqn{X}, if \eqn{R} is constrained to have positive diagonal entries. } \usage{ chol2inv(x, \dots) \S4method{chol2inv}{dtrMatrix}(x, \dots) \S4method{chol2inv}{dtCMatrix}(x, \dots) \S4method{chol2inv}{generalMatrix}(x, uplo = "U", \dots) } \arguments{ \item{x}{a square matrix or \code{\linkS4class{Matrix}}, typically the result of a call to \code{\link{chol}}. If \code{x} is square but not (formally) triangular, then only the upper or lower triangle is considered, depending on optional argument \code{uplo} if \code{x} is a \code{\linkS4class{Matrix}}.} \item{uplo}{a string, either \code{"U"} or \code{"L"}, indicating which triangle of \code{x} contains the Cholesky factor. The default is \code{"U"}, to be consistent with \code{\link[base]{chol2inv}} from \pkg{base}.} \item{\dots}{further arguments passed to or from methods.} } \value{ A matrix, \code{\linkS4class{symmetricMatrix}}, or \code{\linkS4class{diagonalMatrix}} representing the inverse of the positive definite matrix whose Cholesky factor is \code{x}. The result is a traditional matrix if \code{x} is a traditional matrix, dense if \code{x} is dense, and sparse if \code{x} is sparse. } \seealso{ The default method from \pkg{base}, \code{\link[base]{chol2inv}}, called for traditional matrices \code{x}. Generic function \code{\link{chol}}, for computing the upper triangular Cholesky factor \eqn{L'} of a symmetric positive semidefinite matrix. Generic function \code{\link{solve}}, for solving linear systems and (as a corollary) for computing inverses more generally. } \examples{ (A <- Matrix(cbind(c(1, 1, 1), c(1, 2, 4), c(1, 4, 16)))) (R <- chol(A)) (L <- t(R)) (R2i <- chol2inv(R)) (L2i <- chol2inv(R)) stopifnot(exprs = { all.equal(R2i, tcrossprod(solve(R))) all.equal(L2i, crossprod(solve(L))) all.equal(as(R2i \%*\% A, "matrix"), diag(3L)) # the identity all.equal(as(L2i \%*\% A, "matrix"), diag(3L)) # ditto }) } Matrix/man/forceSymmetric-methods.Rd0000644000175100001440000000450014575137654017252 0ustar hornikusers\name{forceSymmetric-methods} \title{Force a Matrix to 'symmetricMatrix' Without Symmetry Checks} % \docType{methods} \keyword{array} \keyword{methods} % \alias{forceSymmetric} \alias{forceSymmetric-methods} % \alias{forceSymmetric,CsparseMatrix,character-method} \alias{forceSymmetric,CsparseMatrix,missing-method} \alias{forceSymmetric,RsparseMatrix,character-method} \alias{forceSymmetric,RsparseMatrix,missing-method} \alias{forceSymmetric,TsparseMatrix,character-method} \alias{forceSymmetric,TsparseMatrix,missing-method} \alias{forceSymmetric,denseMatrix,character-method} \alias{forceSymmetric,denseMatrix,missing-method} \alias{forceSymmetric,diagonalMatrix,character-method} \alias{forceSymmetric,diagonalMatrix,missing-method} \alias{forceSymmetric,indMatrix,character-method} \alias{forceSymmetric,indMatrix,missing-method} \alias{forceSymmetric,matrix,character-method} \alias{forceSymmetric,matrix,missing-method} % \description{ Force a square matrix \code{x} to a \code{\linkS4class{symmetricMatrix}}, \bold{without} a symmetry check as it would be applied for \code{as(x, "symmetricMatrix")}. } \usage{ forceSymmetric(x, uplo) } \arguments{ \item{x}{any square matrix (of numbers), either \dQuote{"traditional"} (\code{\link{matrix}}) or inheriting from \code{\linkS4class{Matrix}}.} \item{uplo}{optional string, \code{"U"} or \code{"L"} indicating which \dQuote{triangle} half of \code{x} should determine the result. The default is \code{"U"} unless \code{x} already has a \code{uplo} slot (i.e., when it is \code{\linkS4class{symmetricMatrix}}, or \code{\linkS4class{triangularMatrix}}), where the default will be \code{x@uplo}.} } % \details{ % % } \value{ a square matrix inheriting from class \code{\linkS4class{symmetricMatrix}}. } \seealso{\code{\link{symmpart}} for the symmetric part of a matrix, or the coercions \code{as(x, )}. } \examples{ ## Hilbert matrix i <- 1:6 h6 <- 1/outer(i - 1L, i, "+") sd <- sqrt(diag(h6)) hh <- t(h6/sd)/sd # theoretically symmetric isSymmetric(hh, tol=0) # FALSE; hence try( as(hh, "symmetricMatrix") ) # fails, but this works fine: H6 <- forceSymmetric(hh) ## result can be pretty surprising: (M <- Matrix(1:36, 6)) forceSymmetric(M) # symmetric, hence very different in lower triangle (tm <- tril(M)) forceSymmetric(tm) } Matrix/man/rep2abI.Rd0000644000175100001440000000130414422605232014060 0ustar hornikusers\name{rep2abI} \title{Replicate Vectors into 'abIndex' Result} % \keyword{manip} \keyword{utilities} % \alias{rep2abI} % \description{ \code{rep2abI(x, times)} conceptually computes \code{\link{rep.int}(x, times)} but with an \code{\linkS4class{abIndex}} class result. } \usage{ rep2abI(x, times) } \arguments{ \item{x}{numeric vector} \item{times}{integer (valued) scalar: the number of repetitions} } % \details{ % } \value{ a vector of \code{\link{class}} \code{\linkS4class{abIndex}} } \seealso{ \code{\link{rep.int}()}, the base function; \code{\link{abIseq}}, \code{\linkS4class{abIndex}}. } \examples{ (ab <- rep2abI(2:7, 4)) stopifnot(identical(as(ab, "numeric"), rep(2:7, 4))) } Matrix/man/dtRMatrix-class-sparse.Rd0000644000175100001440000000536114575137654017140 0ustar hornikusers\name{dtRMatrix-class} \title{Triangular Sparse Compressed Row Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{dtRMatrix-class} % \description{The \code{dtRMatrix} class is a class of triangular, sparse matrices in the compressed, row-oriented format. In this implementation the non-zero elements in the rows are sorted into increasing columnd order. } \section{Objects from the Class}{ This class is currently still mostly unimplemented! Objects can be created by calls of the form \code{new("dtRMatrix", ...)}. } \section{Slots}{ \describe{ \item{\code{uplo}:}{Object of class \code{"character"}. Must be either "U", for upper triangular, and "L", for lower triangular. At present only the lower triangle form is allowed.} \item{\code{diag}:}{Object of class \code{"character"}. Must be either \code{"U"}, for unit triangular (diagonal is all ones), or \code{"N"}; see \code{\linkS4class{triangularMatrix}}.} \item{\code{j}:}{Object of class \code{"integer"} of length \code{\link{nnzero}(.)} (number of non-zero elements). These are the row numbers for each non-zero element in the matrix.} \item{\code{p}:}{Object of class \code{"integer"} of pointers, one for each row, to the initial (zero-based) index of elements in the row. (Only present in the \code{dsRMatrix} class.)} \item{\code{x}:}{Object of class \code{"numeric"} - the non-zero elements of the matrix.} \item{\code{Dim}:}{The dimension (a length-2 \code{"integer"})} \item{\code{Dimnames}:}{corresponding names (or \code{NULL}), inherited from the \code{\linkS4class{Matrix}}, see there.} } } \section{Extends}{ Class \code{"dgRMatrix"}, directly. Class \code{"dsparseMatrix"}, by class \code{"dgRMatrix"}. Class \code{"dMatrix"}, by class \code{"dgRMatrix"}. Class \code{"sparseMatrix"}, by class \code{"dgRMatrix"}. Class \code{"Matrix"}, by class \code{"dgRMatrix"}. } \section{Methods}{ No methods currently with class "dsRMatrix" in the signature. % \describe{ % \item{solve}{\code{signature(a = "dsRMatrix", b = "matrix")}: Solve % a linear system of equations defined by \code{x} using a Cholesky % decomposition.} % ...... % \item{coerce}{\code{signature(from = "dsRMatrix", to = "dgTMatrix")}} % ...... % } } %\references{} %\author{} %\note{} \seealso{ Classes \code{\linkS4class{dgCMatrix}}, \code{\linkS4class{dgTMatrix}}, \code{\linkS4class{dgeMatrix}} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } (m0 <- new("dtRMatrix")) (m2 <- new("dtRMatrix", Dim = c(2L,2L), x = c(5, 1:2), p = c(0L,2:3), j= c(0:1,1L))) str(m2) (m3 <- as(Diagonal(2), "RsparseMatrix"))# --> dtRMatrix } Matrix/man/dMatrix-class.Rd0000644000175100001440000001143314574054462015326 0ustar hornikusers\name{dMatrix-class} \title{(Virtual) Class "dMatrix" of "double" Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{dMatrix-class} \alias{lMatrix-class} % \alias{Compare,dMatrix,logical-method} \alias{Compare,dMatrix,numeric-method} \alias{Compare,logical,dMatrix-method} \alias{Compare,numeric,dMatrix-method} \alias{Logic,dMatrix,logical-method} \alias{Logic,dMatrix,numeric-method} \alias{Logic,dMatrix,sparseVector-method} \alias{Logic,logical,dMatrix-method} \alias{Logic,numeric,dMatrix-method} \alias{Ops,dMatrix,dMatrix-method} \alias{Ops,dMatrix,ddiMatrix-method} \alias{Ops,dMatrix,lMatrix-method} \alias{Ops,dMatrix,ldiMatrix-method} \alias{Ops,dMatrix,nMatrix-method} \alias{coerce,matrix,dMatrix-method} \alias{coerce,vector,dMatrix-method} % \alias{Arith,lMatrix,numeric-method} \alias{Arith,lMatrix,logical-method} \alias{Arith,logical,lMatrix-method} \alias{Arith,numeric,lMatrix-method} \alias{Compare,lMatrix,logical-method} \alias{Compare,lMatrix,numeric-method} \alias{Compare,logical,lMatrix-method} \alias{Compare,numeric,lMatrix-method} \alias{Logic,lMatrix,logical-method} \alias{Logic,lMatrix,numeric-method} \alias{Logic,lMatrix,sparseVector-method} \alias{Logic,logical,lMatrix-method} \alias{Logic,numeric,lMatrix-method} \alias{Ops,lMatrix,dMatrix-method} \alias{Ops,lMatrix,lMatrix-method} \alias{Ops,lMatrix,nMatrix-method} \alias{Ops,lMatrix,numeric-method} \alias{Ops,numeric,lMatrix-method} \alias{coerce,matrix,lMatrix-method} \alias{coerce,vector,lMatrix-method} % \description{ The \code{dMatrix} class is a virtual class contained by all actual classes of numeric matrices in the \pkg{Matrix} package. Similarly, all the actual classes of logical matrices inherit from the \code{lMatrix} class. } %\section{Objects from the Class}{A virtual Class: No objects may be % created from it. %} \section{Slots}{ Common to \emph{all} matrix object in the package: \describe{ \item{\code{Dim}:}{Object of class \code{"integer"} - the dimensions of the matrix - must be an integer vector with exactly two non-negative values.} \item{\code{Dimnames}:}{list of length two; each component containing NULL or a \code{\link{character}} vector length equal the corresponding \code{Dim} element.} } } \section{Methods}{ There are (relatively simple) group methods (see, e.g., \code{\link{Arith}}) \describe{ \item{Arith}{\code{signature(e1 = "dMatrix", e2 = "dMatrix")}: ... } \item{Arith}{\code{signature(e1 = "dMatrix", e2 = "numeric")}: ... } \item{Arith}{\code{signature(e1 = "numeric", e2 = "dMatrix")}: ... } \item{Math}{\code{signature(x = "dMatrix")}: ... } \item{Math2}{\code{signature(x = "dMatrix", digits = "numeric")}: this group contains \code{\link{round}()} and \code{\link{signif}()}.} \item{Compare}{\code{signature(e1 = "numeric", e2 = "dMatrix")}: ... } \item{Compare}{\code{signature(e1 = "dMatrix", e2 = "numeric")}: ... } \item{Compare}{\code{signature(e1 = "dMatrix", e2 = "dMatrix")}: ... } \item{Summary}{\code{signature(x = "dMatrix")}: The \code{"Summary"} group contains the seven functions \code{\link{max}()}, \code{\link{min}()}, \code{\link{range}()}, \code{\link{prod}()}, \code{\link{sum}()}, \code{\link{any}()}, and \code{\link{all}()}.} } The following methods are also defined for all double matrices: \describe{ \item{expm}{\code{signature(x = "dMatrix")}: computes the \emph{\dQuote{Matrix Exponential}}, see \code{\link{expm}}.} } The following methods are defined for all logical matrices: \describe{ \item{which}{\code{signature(x = "lsparseMatrix")} and many other subclasses of \code{"lMatrix"}: as the \pkg{base} function \code{\link{which}(x, arr.ind)} returns the indices of the \code{\link{TRUE}} entries in \code{x}; if \code{arr.ind} is true, as a 2-column matrix of row and column indices. Since \pkg{Matrix} version 1.2-9, if \code{useNames} is true, as by default, with \code{\link{dimnames}}, the same as \code{base::which}.} } } %\references{} % Martin + Doug\author{Douglas Bates \email{bates@stat.wisc.edu}} \seealso{ The nonzero-pattern matrix class \code{\linkS4class{nMatrix}}, which can be used to store non-\code{\link{NA}} \code{\link{logical}} matrices even more compactly. The numeric matrix classes \code{\linkS4class{dgeMatrix}}, \code{\linkS4class{dgCMatrix}}, and \code{\linkS4class{Matrix}}. \code{\link{drop0}(x, tol=1e-10)} is sometimes preferable to (and more efficient than) \code{zapsmall(x, digits=10)}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) } showClass("dMatrix") set.seed(101) round(Matrix(rnorm(28), 4,7), 2) M <- Matrix(rlnorm(56, sd=10), 4,14) (M. <- zapsmall(M)) table(as.logical(M. == 0)) } Matrix/man/Cholesky-class.Rd0000644000175100001440000001735414446607050015502 0ustar hornikusers\name{Cholesky-class} \title{Dense Cholesky Factorizations} % \docType{class} \keyword{algebra} \keyword{array} \keyword{classes} % \alias{Cholesky-class} \alias{pCholesky-class} % \alias{coerce,Cholesky,dtrMatrix-method} \alias{coerce,pCholesky,dtpMatrix-method} \alias{determinant,Cholesky,logical-method} \alias{determinant,pCholesky,logical-method} \alias{diag,Cholesky-method} \alias{diag,pCholesky-method} % \description{ Classes \code{Cholesky} and \code{pCholesky} represent dense, pivoted Cholesky factorizations of \eqn{n \times n}{n-by-n} real, symmetric, positive semidefinite matrices \eqn{A}, having the general form \deqn{P_{1} A P_{1}' = L_{1} D L_{1}' = L L'}{P1 * A * P1' = L1 * D * L1' = L * L'} or (equivalently) \deqn{A = P_{1}' L_{1} D L_{1}' P_{1} = P_{1}' L L' P_{1}}{A = P1' * L1 * D * L1' * P1 = P1' * L * L' * P1} where \eqn{P_{1}}{P1} is a permutation matrix, \eqn{L_{1}}{L1} is a unit lower triangular matrix, \eqn{D} is a non-negative diagonal matrix, and \eqn{L = L_{1} \sqrt{D}}{L = L1 * sqrt(D)}. These classes store the entries of the Cholesky factor \eqn{L} or its transpose \eqn{L'} in a dense format as a vector of length \eqn{nn}{n*n} (\code{Cholesky}) or \eqn{n(n+1)/2}{n*(n+1)/2} (\code{pCholesky}), the latter giving the \dQuote{packed} representation. } \section{Slots}{ \describe{ \item{\code{Dim}, \code{Dimnames}}{inherited from virtual class \code{\linkS4class{MatrixFactorization}}.} \item{\code{uplo}}{a string, either \code{"U"} or \code{"L"}, indicating which triangle (upper or lower) of the factorized symmetric matrix was used to compute the factorization and in turn whether \code{x} stores \eqn{L'} or \eqn{L}.} \item{\code{x}}{a numeric vector of length \code{n*n} (\code{Cholesky}) or \code{n*(n+1)/2} (\code{pCholesky}), where \code{n=Dim[1]}, listing the entries of the Cholesky factor \eqn{L} or its transpose \eqn{L'} in column-major order.} \item{\code{perm}}{a 1-based integer vector of length \code{Dim[1]} specifying the permutation applied to the rows and columns of the factorized matrix. \code{perm} of length 0 is valid and equivalent to the identity permutation, implying no pivoting.} } } \section{Extends}{ Class \code{\linkS4class{CholeskyFactorization}}, directly. Class \code{\linkS4class{MatrixFactorization}}, by class \code{\linkS4class{CholeskyFactorization}}, distance 2. } \section{Instantiation}{ Objects can be generated directly by calls of the form \code{new("Cholesky", ...)} or \code{new("pCholesky", ...)}, but they are more typically obtained as the value of \code{\link{Cholesky}(x)} for \code{x} inheriting from \code{\linkS4class{dsyMatrix}} or \code{\linkS4class{dspMatrix}} (often the subclasses of those reserved for positive semidefinite matrices, namely \code{\linkS4class{dpoMatrix}} and \code{\linkS4class{dppMatrix}}). } \section{Methods}{ \describe{ \item{\code{coerce}}{\code{signature(from = "Cholesky", to = "dtrMatrix")}: returns a \code{\linkS4class{dtrMatrix}} representing the Cholesky factor \eqn{L} or its transpose \eqn{L'}; see \sQuote{Note}.} \item{\code{coerce}}{\code{signature(from = "pCholesky", to = "dtpMatrix")}: returns a \code{\linkS4class{dtpMatrix}} representing the Cholesky factor \eqn{L} or its transpose \eqn{L'}; see \sQuote{Note}.} \item{\code{determinant}}{\code{signature(from = "p?Cholesky", logarithm = "logical")}: computes the determinant of the factorized matrix \eqn{A} or its logarithm.} \item{\code{diag}}{\code{signature(x = "p?Cholesky")}: returns a numeric vector of length \eqn{n} containing the diagonal elements of \eqn{D}, which are the squared diagonal elements of \eqn{L}.} \item{\code{expand1}}{\code{signature(x = "p?Cholesky")}: see \code{\link{expand1-methods}}.} \item{\code{expand2}}{\code{signature(x = "p?Cholesky")}: see \code{\link{expand2-methods}}.} \item{\code{solve}}{\code{signature(a = "p?Cholesky", b = .)}: see \code{\link{solve-methods}}.} } } \note{ In \pkg{Matrix} \code{< 1.6-0}, class \code{Cholesky} extended \code{\linkS4class{dtrMatrix}} and class \code{pCholesky} extended \code{\linkS4class{dtpMatrix}}, reflecting the fact that the factor \eqn{L} is indeed a triangular matrix. \pkg{Matrix} \code{1.6-0} removed these extensions so that methods would no longer be inherited from \code{dtrMatrix} and \code{dtpMatrix}. The availability of such methods gave the wrong impression that \code{Cholesky} and \code{pCholesky} represent a (singular) matrix, when in fact they represent an ordered set of matrix factors. The coercions \code{as(., "dtrMatrix")} and \code{as(., "dtpMatrix")} are provided for users who understand the caveats. } \seealso{ Class \code{\linkS4class{CHMfactor}} for sparse Cholesky factorizations. Classes \code{\linkS4class{dpoMatrix}} and \code{\linkS4class{dppMatrix}}. Generic functions \code{\link{Cholesky}}, \code{\link{expand1}} and \code{\link{expand2}}. } \references{ The LAPACK source code, including documentation; see \url{https://netlib.org/lapack/double/dpstrf.f}, \url{https://netlib.org/lapack/double/dpotrf.f}, and \url{https://netlib.org/lapack/double/dpptrf.f}. Lucas, C. (2004). \emph{LAPACK-style codes for level 2 and 3 pivoted Cholesky factorizations}. LAPACK Working Note, Number 161. \url{https://www.netlib.org/lapack/lawnspdf/lawn161.pdf} Golub, G. H., & Van Loan, C. F. (2013). \emph{Matrix computations} (4th ed.). Johns Hopkins University Press. \doi{10.56021/9781421407944} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } showClass("Cholesky") set.seed(1) m <- 30L n <- 6L (A <- crossprod(Matrix(rnorm(m * n), m, n))) ## With dimnames, to see that they are propagated : dimnames(A) <- dn <- rep.int(list(paste0("x", seq_len(n))), 2L) (ch.A <- Cholesky(A)) # pivoted, by default str(e.ch.A <- expand2(ch.A, LDL = TRUE), max.level = 2L) str(E.ch.A <- expand2(ch.A, LDL = FALSE), max.level = 2L) ## Underlying LAPACK representation (m.ch.A <- as(ch.A, "dtrMatrix")) # which is L', not L, because A@uplo == "U" stopifnot(identical(as(m.ch.A, "matrix"), `dim<-`(ch.A@x, ch.A@Dim))) ae1 <- function(a, b, ...) all.equal(as(a, "matrix"), as(b, "matrix"), ...) ae2 <- function(a, b, ...) ae1(unname(a), unname(b), ...) ## A ~ P1' L1 D L1' P1 ~ P1' L L' P1 in floating point stopifnot(exprs = { identical(names(e.ch.A), c("P1.", "L1", "D", "L1.", "P1")) identical(names(E.ch.A), c("P1.", "L" , "L." , "P1")) identical(e.ch.A[["P1"]], new("pMatrix", Dim = c(n, n), Dimnames = c(list(NULL), dn[2L]), margin = 2L, perm = invertPerm(ch.A@perm))) identical(e.ch.A[["P1."]], t(e.ch.A[["P1"]])) identical(e.ch.A[["L1."]], t(e.ch.A[["L1"]])) identical(E.ch.A[["L." ]], t(E.ch.A[["L" ]])) identical(e.ch.A[["D"]], Diagonal(x = diag(ch.A))) all.equal(E.ch.A[["L"]], with(e.ch.A, L1 \%*\% sqrt(D))) ae1(A, with(e.ch.A, P1. \%*\% L1 \%*\% D \%*\% L1. \%*\% P1)) ae1(A, with(E.ch.A, P1. \%*\% L \%*\% L. \%*\% P1)) ae2(A[ch.A@perm, ch.A@perm], with(e.ch.A, L1 \%*\% D \%*\% L1.)) ae2(A[ch.A@perm, ch.A@perm], with(E.ch.A, L \%*\% L. )) }) ## Factorization handled as factorized matrix b <- rnorm(n) all.equal(det(A), det(ch.A), tolerance = 0) all.equal(solve(A, b), solve(ch.A, b), tolerance = 0) ## For identical results, we need the _unpivoted_ factorization ## computed by det(A) and solve(A, b) (ch.A.nopivot <- Cholesky(A, perm = FALSE)) stopifnot(identical(det(A), det(ch.A.nopivot)), identical(solve(A, b), solve(ch.A.nopivot, b))) } Matrix/man/Matrix.Rd0000644000175100001440000001147714446607050014062 0ustar hornikusers\name{Matrix} \title{Construct a Classed Matrix} % \keyword{array} \keyword{utilities} % \alias{Matrix} \description{ Construct a Matrix of a class that inherits from \code{Matrix}. } \usage{ Matrix(data=NA, nrow=1, ncol=1, byrow=FALSE, dimnames=NULL, sparse = NULL, doDiag = TRUE, forceCheck = FALSE) } \arguments{ \item{data}{an optional numeric data vector or matrix.} \item{nrow}{when \code{data} is not a matrix, the desired number of rows} \item{ncol}{when \code{data} is not a matrix, the desired number of columns} \item{byrow}{logical. If \code{FALSE} (the default) the matrix is filled by columns, otherwise the matrix is filled by rows.} \item{dimnames}{a \code{\link{dimnames}} attribute for the matrix: a \code{list} of two character components. They are set if not \code{\link{NULL}} (as per default).} \item{sparse}{logical or \code{NULL}, specifying if the result should be sparse or not. By default, it is made sparse when more than half of the entries are 0.} \item{doDiag}{logical indicating if a \code{\linkS4class{diagonalMatrix}} object should be returned when the resulting matrix is diagonal (\emph{mathematically}). As class \code{\linkS4class{diagonalMatrix}} \code{\link{extends}} \code{\linkS4class{sparseMatrix}}, this is a natural default for all values of \code{sparse}. Otherwise, if \code{doDiag} is false, a dense or sparse (depending on \code{sparse}) \emph{symmetric} matrix will be returned.} % MJ: not quite ... if 'dimnames' is asymmetric then the result % is a triangularMatrix, not a symmetricMatrix ... \item{forceCheck}{logical indicating if the checks for structure should even happen when \code{data} is already a \code{"Matrix"} object.} } \value{ Returns matrix of a class that inherits from \code{"Matrix"}. Only if \code{data} is not a \code{\link{matrix}} and does not already inherit from class \code{\linkS4class{Matrix}} are the arguments \code{nrow}, \code{ncol} and \code{byrow} made use of. } \details{ If either of \code{nrow} or \code{ncol} is not given, an attempt is made to infer it from the length of \code{data} and the other parameter. Further, \code{Matrix()} makes efforts to keep \code{\link{logical}} matrices logical, i.e., inheriting from class \code{\linkS4class{lMatrix}}, and to determine specially structured matrices such as symmetric, triangular or diagonal ones. Note that a \emph{symmetric} matrix also needs symmetric \code{\link{dimnames}}, e.g., by specifying \code{dimnames = list(NULL,NULL)}, see the examples. Most of the time, the function works via a traditional (\emph{full}) \code{\link{matrix}}. However, \code{Matrix(0, nrow,ncol)} directly constructs an \dQuote{empty} \linkS4class{sparseMatrix}, as does \code{Matrix(FALSE, *)}. Although it is sometime possible to mix unclassed matrices (created with \code{matrix}) with ones of class \code{"Matrix"}, it is much safer to always use carefully constructed ones of class \code{"Matrix"}. } \seealso{ The classes \code{\linkS4class{Matrix}}, \code{\linkS4class{symmetricMatrix}}, \code{\linkS4class{triangularMatrix}}, and \code{\linkS4class{diagonalMatrix}}; further, \code{\link{matrix}}. Special matrices can be constructed, e.g., via \code{\link{sparseMatrix}} (sparse), \code{\link{bdiag}} (block-diagonal), \code{\link{bandSparse}} (banded sparse), or \code{\link{Diagonal}}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } Matrix(0, 3, 2) # 3 by 2 matrix of zeros -> sparse Matrix(0, 3, 2, sparse=FALSE)# -> 'dense' ## 4 cases - 3 different results : Matrix(0, 2, 2) # diagonal ! Matrix(0, 2, 2, sparse=FALSE)# (ditto) Matrix(0, 2, 2, doDiag=FALSE)# -> sparse symm. "dsCMatrix" Matrix(0, 2, 2, sparse=FALSE, doDiag=FALSE)# -> dense symm. "dsyMatrix" Matrix(1:6, 3, 2) # a 3 by 2 matrix (+ integer warning) Matrix(1:6 + 1, nrow=3) ## logical ones: Matrix(diag(4) > 0) # -> "ldiMatrix" with diag = "U" Matrix(diag(4) > 0, sparse=TRUE) # (ditto) Matrix(diag(4) >= 0) # -> "lsyMatrix" (of all 'TRUE') ## triangular l3 <- upper.tri(matrix(,3,3)) (M <- Matrix(l3)) # -> "ltCMatrix" Matrix(! l3) # -> "ltrMatrix" as(l3, "CsparseMatrix")# "lgCMatrix" Matrix(1:9, nrow=3, dimnames = list(c("a", "b", "c"), c("A", "B", "C"))) (I3 <- Matrix(diag(3)))# identity, i.e., unit "diagonalMatrix" str(I3) # note 'diag = "U"' and the empty 'x' slot (A <- cbind(a=c(2,1), b=1:2))# symmetric *apart* from dimnames Matrix(A) # hence 'dgeMatrix' (As <- Matrix(A, dimnames = list(NULL,NULL)))# -> symmetric forceSymmetric(A) # also symmetric, w/ symm. dimnames stopifnot(is(As, "symmetricMatrix"), is(Matrix(0, 3,3), "sparseMatrix"), is(Matrix(FALSE, 1,1), "sparseMatrix")) } Matrix/man/Matrix-notyet.Rd0000644000175100001440000000104714575137654015405 0ustar hornikusers\name{Matrix-notyet} \title{Virtual Classes Not Yet Really Implemented and Used} % \docType{class} \keyword{array} \keyword{classes} % \alias{Matrix-notyet} % \alias{iMatrix-class} \alias{zMatrix-class} % \description{ \code{iMatrix} is the virtual class of all integer (S4) matrices. It extends the \code{\linkS4class{Matrix}} class directly. \code{zMatrix} is the virtual class of all \code{\link{complex}} (S4) matrices. It extends the \code{\linkS4class{Matrix}} class directly. } \examples{ showClass("iMatrix") showClass("zMatrix") } Matrix/man/bandSparse.Rd0000644000175100001440000000714414446607050014674 0ustar hornikusers\name{bandSparse} \title{Construct Sparse Banded Matrix from (Sup-/Super-) Diagonals} % \keyword{array} \keyword{utilities} % \alias{bandSparse} % \description{ Construct a sparse banded matrix by specifying its non-zero sup- and super-diagonals. } \usage{ bandSparse(n, m = n, k, diagonals, symmetric = FALSE, repr = "C", giveCsparse = (repr == "C")) } \arguments{ \item{n,m}{the matrix dimension \eqn{(n,m) = (nrow, ncol)}.} \item{k}{integer vector of \dQuote{diagonal numbers}, with identical meaning as in \code{\link{band}(*, k)}, i.e., relative to the main diagonal, which is \code{k=0}.} \item{diagonals}{optional list of sub-/super- diagonals; if missing, the result will be a patter\bold{n} matrix, i.e., inheriting from class \code{\linkS4class{nMatrix}}. \code{diagonals} can also be \eqn{n' \times d}{n' x d} matrix, where \code{d <- length(k)} and \eqn{n' >= min(n,m)}. In that case, the sub-/super- diagonals are taken from the columns of \code{diagonals}, where only the first several rows will be used (typically) for off-diagonals. } \item{symmetric}{logical; if true the result will be symmetric (inheriting from class \code{\linkS4class{symmetricMatrix}}) and only the upper or lower triangle must be specified (via \code{k} and \code{diagonals}).} \item{repr}{\code{\link{character}} string, one of \code{"C"}, \code{"T"}, or \code{"R"}, specifying the sparse \emph{repr}esentation to be used for the result, i.e., one from the super classes \code{\linkS4class{CsparseMatrix}}, \code{\linkS4class{TsparseMatrix}}, or \code{\linkS4class{RsparseMatrix}}.} \item{giveCsparse}{(\bold{deprecated}, replaced with \code{repr}): logical indicating if the result should be a \code{\linkS4class{CsparseMatrix}} or a \code{\linkS4class{TsparseMatrix}}, where the default was \code{TRUE}, and now is determined from \code{repr}; very often Csparse matrices are more efficient subsequently, but not always.} } % \details{ __needed ?__ % % } \value{ a sparse matrix (of \code{\link{class}} \code{\linkS4class{CsparseMatrix}}) of dimension \eqn{n \times m}{n x m} with diagonal \dQuote{bands} as specified. } %\author{Martin Maechler} \seealso{ \code{\link{band}}, for \emph{extraction} of matrix bands; \code{\link{bdiag}}, \code{\link{diag}}, \code{\link{sparseMatrix}}, \code{\link{Matrix}}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) } diags <- list(1:30, 10*(1:20), 100*(1:20)) s1 <- bandSparse(13, k = -c(0:2, 6), diag = c(diags, diags[2]), symm=TRUE) s1 s2 <- bandSparse(13, k = c(0:2, 6), diag = c(diags, diags[2]), symm=TRUE) stopifnot(identical(s1, t(s2)), is(s1,"dsCMatrix")) ## a pattern Matrix of *full* (sub-)diagonals: bk <- c(0:4, 7,9) (s3 <- bandSparse(30, k = bk, symm = TRUE)) ## If you want a pattern matrix, but with "sparse"-diagonals, ## you currently need to go via logical sparse: lLis <- lapply(list(rpois(20, 2), rpois(20, 1), rpois(20, 3))[c(1:3, 2:3, 3:2)], as.logical) (s4 <- bandSparse(20, k = bk, symm = TRUE, diag = lLis)) (s4. <- as(drop0(s4), "nsparseMatrix")) n <- 1e4 bk <- c(0:5, 7,11) bMat <- matrix(1:8, n, 8, byrow=TRUE) bLis <- as.data.frame(bMat) B <- bandSparse(n, k = bk, diag = bLis) Bs <- bandSparse(n, k = bk, diag = bLis, symmetric=TRUE) B [1:15, 1:30] Bs[1:15, 1:30] ## can use a list *or* a matrix for specifying the diagonals: stopifnot(identical(B, bandSparse(n, k = bk, diag = bMat)), identical(Bs, bandSparse(n, k = bk, diag = bMat, symmetric=TRUE)) , inherits(B, "dtCMatrix") # triangular! ) } Matrix/man/dtpMatrix-class.Rd0000644000175100001440000000634214446607050015670 0ustar hornikusers\name{dtpMatrix-class} \title{Packed Triangular Dense Matrices - "dtpMatrix"} % \docType{class} \keyword{array} \keyword{classes} % \alias{dtpMatrix-class} % \description{The \code{"dtpMatrix"} class is the class of triangular, dense, numeric matrices in packed storage. The \code{"dtrMatrix"} class is the same except in nonpacked storage.} \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("dtpMatrix", ...)} or by coercion from other classes of matrices. } \section{Slots}{ \describe{ \item{\code{uplo}:}{Object of class \code{"character"}. Must be either "U", for upper triangular, and "L", for lower triangular.} \item{\code{diag}:}{Object of class \code{"character"}. Must be either \code{"U"}, for unit triangular (diagonal is all ones), or \code{"N"}; see \code{\linkS4class{triangularMatrix}}.} \item{\code{x}:}{Object of class \code{"numeric"}. The numeric values that constitute the matrix, stored in column-major order. For a packed square matrix of dimension \eqn{d \times d}{d * d}, \code{length(x)} is of length \eqn{d(d+1)/2} (also when \code{diag == "U"}!).} \item{\code{Dim},\code{Dimnames}:}{The dimension (a length-2 \code{"integer"}) and corresponding names (or \code{NULL}), inherited from the \code{\linkS4class{Matrix}}, see there.} } } \section{Extends}{ Class \code{"ddenseMatrix"}, directly. Class \code{"triangularMatrix"}, directly. Class \code{"dMatrix"} and more by class \code{"ddenseMatrix"} etc, see the examples. } \section{Methods}{ \describe{ \item{\%*\%}{\code{signature(x = "dtpMatrix", y = "dgeMatrix")}: Matrix multiplication; ditto for several other signature combinations, see \code{showMethods("\%*\%", class = "dtpMatrix")}.} \item{determinant}{\code{signature(x = "dtpMatrix", logarithm = "logical")}: the \code{\link{determinant}(x)} trivially is \code{prod(diag(x))}, but computed on log scale to prevent over- and underflow.} \item{diag}{\code{signature(x = "dtpMatrix")}: ... } \item{norm}{\code{signature(x = "dtpMatrix", type = "character")}: ... } \item{rcond}{\code{signature(x = "dtpMatrix", norm = "character")}: ... } \item{solve}{\code{signature(a = "dtpMatrix", b = "...")}: efficiently using internal backsolve or forwardsolve, see \code{\link{solve-methods}}.} \item{t}{\code{signature(x = "dtpMatrix")}: \code{t(x)} remains a \code{"dtpMatrix"}, lower triangular if \code{x} is upper triangular, and vice versa.} } } \seealso{ Class \code{\linkS4class{dtrMatrix}} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } showClass("dtrMatrix") example("dtrMatrix-class", echo=FALSE) (p1 <- pack(T2)) str(p1) (pp <- pack(T)) ip1 <- solve(p1) stopifnot(length(p1@x) == 3, length(pp@x) == 3, p1 @ uplo == T2 @ uplo, pp @ uplo == T @ uplo, identical(t(pp), p1), identical(t(p1), pp), all((l.d <- p1 - T2) == 0), is(l.d, "dtpMatrix"), all((u.d <- pp - T ) == 0), is(u.d, "dtpMatrix"), l.d@uplo == T2@uplo, u.d@uplo == T@uplo, identical(t(ip1), solve(pp)), is(ip1, "dtpMatrix"), all.equal(as(solve(p1,p1), "diagonalMatrix"), Diagonal(2))) } Matrix/man/sparseMatrix.Rd0000644000175100001440000002404214446607050015270 0ustar hornikusers\name{sparseMatrix} \title{General Sparse Matrix Construction from Nonzero Entries} % \keyword{array} \keyword{utilities} % \alias{sparseMatrix} % \description{ User-friendly construction of sparse matrices (inheriting from virtual \code{\link{class}} \code{\linkS4class{CsparseMatrix}}, \code{\linkS4class{RsparseMatrix}}, or \code{\linkS4class{TsparseMatrix}}) from the positions and values of their nonzero entries. This interface is recommended over direct construction via calls such as \code{\link{new}("..[CRT]Matrix", ...)}. } \usage{ sparseMatrix(i, j, p, x, dims, dimnames, symmetric = FALSE, triangular = FALSE, index1 = TRUE, repr = c("C", "R", "T"), giveCsparse, check = TRUE, use.last.ij = FALSE) } \arguments{ \item{i,j}{integer vectors of equal length specifying the positions (row and column indices) of the nonzero (or non-\code{TRUE}) entries of the matrix. Note that, when \code{x} is non-missing, the \eqn{x_k} corresponding to \emph{repeated} pairs \eqn{(i_k,j_k)} are \emph{added}, for consistency with the definition of class \code{\linkS4class{TsparseMatrix}}, unless \code{use.last.ij} is \code{TRUE}, in which case only the \emph{last} such \eqn{x_k} is used.} \item{p}{integer vector of pointers, one for each column (or row), to the initial (zero-based) index of elements in the column (or row). Exactly one of \code{i}, \code{j}, and \code{p} must be missing.} \item{x}{optional, typically nonzero values for the matrix entries. If specified, then the length must equal that of \code{i} (or \code{j}) or equal 1, in which case \code{x} is recycled as necessary. If missing, then the result is a \bold{n}onzero pattern matrix, i.e., inheriting from class \code{\linkS4class{nsparseMatrix}}.} \item{dims}{optional length-2 integer vector of matrix dimensions. If missing, then \code{!index1+c(max(i),max(j))} is used.} \item{dimnames}{optional list of \code{\link{dimnames}}; if missing, then \code{\link{NULL}} ones are used.} \item{symmetric}{logical indicating if the resulting matrix should be symmetric. In that case, \eqn{(i,j,p)} should specify only one triangle (upper or lower).} \item{triangular}{logical indicating if the resulting matrix should be triangular. In that case, \eqn{(i,j,p)} should specify only one triangle (upper or lower).} \item{index1}{logical. If \code{TRUE} (the default), then \code{i} and \code{j} are interpreted as 1-based indices, following the \R convention. That is, counting of rows and columns starts at 1. If \code{FALSE}, then they are interpreted as 0-based indices.} \item{repr}{\code{\link{character}} string, one of \code{"C"}, \code{"R"}, and \code{"T"}, specifying the \bold{repr}esentation of the sparse matrix result, i.e., specifying one of the virtual classes \code{\linkS4class{CsparseMatrix}}, \code{\linkS4class{RsparseMatrix}}, and \code{\linkS4class{TsparseMatrix}}.} \item{giveCsparse}{(\bold{deprecated}, replaced by \code{repr}) logical indicating if the result should inherit from \code{\linkS4class{CsparseMatrix}} or \code{\linkS4class{TsparseMatrix}}. Note that operations involving \code{CsparseMatrix} are very often (but not always) more efficient.} \item{check}{logical indicating whether to check that the result is formally valid before returning. Do not set to \code{FALSE} unless you know what you are doing!} \item{use.last.ij}{logical indicating if, in the case of repeated (duplicated) pairs \eqn{(i_k,j_k)}, only the last pair should be used. \code{FALSE} (the default) is consistent with the definiton of class \code{\linkS4class{TsparseMatrix}}.} } \value{ A sparse matrix, by default in compressed sparse column format and (formally) without symmetric or triangular structure, i.e., by default inheriting from both \code{\linkS4class{CsparseMatrix}} and \code{\linkS4class{generalMatrix}}. } \details{ % FIXME: quite a bit of repetition here (and below) ... Exactly one of the arguments \code{i}, \code{j} and \code{p} must be missing. In typical usage, \code{p} is missing, \code{i} and \code{j} are vectors of positive integers and \code{x} is a numeric vector. These three vectors, which must have the same length, form the triplet representation of the sparse matrix. If \code{i} or \code{j} is missing then \code{p} must be a non-decreasing integer vector whose first element is zero. It provides the compressed, or \dQuote{pointer} representation of the row or column indices, whichever is missing. The expanded form of \code{p}, \code{rep(seq_along(dp),dp)} where \code{dp <- diff(p)}, is used as the (1-based) row or column indices. You cannot set both \code{singular} and \code{triangular} to true; rather use \code{\link{Diagonal}()} (or its alternatives, see there). The values of \code{i}, \code{j}, \code{p} and \code{index1} are used to create 1-based index vectors \code{i} and \code{j} from which a \code{\linkS4class{TsparseMatrix}} is constructed, with numerical values given by \code{x}, if non-missing. Note that in that case, when some pairs \eqn{(i_k,j_k)} are repeated (aka \dQuote{duplicated}), the corresponding \eqn{x_k} are \emph{added}, in consistency with the definition of the \code{\linkS4class{TsparseMatrix}} class, unless \code{use.last.ij} is set to true. By default, when \code{repr = "C"}, the \code{\linkS4class{CsparseMatrix}} derived from this triplet form is returned, where \code{repr = "R"} now allows to directly get an \code{\linkS4class{RsparseMatrix}} and \code{repr = "T"} leaves the result as \code{\linkS4class{TsparseMatrix}}. The reason for returning a \code{\linkS4class{CsparseMatrix}} object instead of the triplet format by default is that the compressed column form is easier to work with when performing matrix operations. In particular, if there are no zeros in \code{x} then a \code{\linkS4class{CsparseMatrix}} is a unique representation of the sparse matrix. } \note{% We say so above (-> {index1}), but some do not read that You \emph{do} need to use \code{index1 = FALSE} (or add \code{+ 1} to \code{i} and \code{j}) if you want use the 0-based \code{i} (and \code{j}) slots from existing sparse matrices. } \seealso{\code{\link{Matrix}(*, sparse=TRUE)} for the constructor of such matrices from a \emph{dense} matrix. That is easier in small sample, but much less efficient (or impossible) for large matrices, where something like \code{sparseMatrix()} is needed. Further \code{\link{bdiag}} and \code{\link{Diagonal}} for (block-)diagonal and \code{\link{bandSparse}} for banded sparse matrix constructors. Random sparse matrices via \code{\link{rsparsematrix}()}. The standard \R \code{\link{xtabs}(*, sparse=TRUE)}, for sparse tables and \code{\link{sparse.model.matrix}()} for building sparse model matrices. Consider \code{\linkS4class{CsparseMatrix}} and similar class definition help files. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } ## simple example i <- c(1,3:8); j <- c(2,9,6:10); x <- 7 * (1:7) (A <- sparseMatrix(i, j, x = x)) ## 8 x 10 "dgCMatrix" summary(A) str(A) # note that *internally* 0-based row indices are used (sA <- sparseMatrix(i, j, x = x, symmetric = TRUE)) ## 10 x 10 "dsCMatrix" (tA <- sparseMatrix(i, j, x = x, triangular= TRUE)) ## 10 x 10 "dtCMatrix" stopifnot( all(sA == tA + t(tA)) , identical(sA, as(tA + t(tA), "symmetricMatrix"))) ## dims can be larger than the maximum row or column indices (AA <- sparseMatrix(c(1,3:8), c(2,9,6:10), x = 7 * (1:7), dims = c(10,20))) summary(AA) ## i, j and x can be in an arbitrary order, as long as they are consistent set.seed(1); (perm <- sample(1:7)) (A1 <- sparseMatrix(i[perm], j[perm], x = x[perm])) stopifnot(identical(A, A1)) ## The slots are 0-index based, so try( sparseMatrix(i=A@i, p=A@p, x= seq_along(A@x)) ) ## fails and you should say so: 1-indexing is FALSE: sparseMatrix(i=A@i, p=A@p, x= seq_along(A@x), index1 = FALSE) ## the (i,j) pairs can be repeated, in which case the x's are summed (args <- data.frame(i = c(i, 1), j = c(j, 2), x = c(x, 2))) (Aa <- do.call(sparseMatrix, args)) ## explicitly ask for elimination of such duplicates, so ## that the last one is used: (A. <- do.call(sparseMatrix, c(args, list(use.last.ij = TRUE)))) stopifnot(Aa[1,2] == 9, # 2+7 == 9 A.[1,2] == 2) # 2 was *after* 7 ## for a pattern matrix, of course there is no "summing": (nA <- do.call(sparseMatrix, args[c("i","j")])) dn <- list(LETTERS[1:3], letters[1:5]) ## pointer vectors can be used, and the (i,x) slots are sorted if necessary: m <- sparseMatrix(i = c(3,1, 3:2, 2:1), p= c(0:2, 4,4,6), x = 1:6, dimnames = dn) m str(m) stopifnot(identical(dimnames(m), dn)) sparseMatrix(x = 2.72, i=1:3, j=2:4) # recycling x sparseMatrix(x = TRUE, i=1:3, j=2:4) # recycling x, |--> "lgCMatrix" ## no 'x' --> patter*n* matrix: (n <- sparseMatrix(i=1:6, j=rev(2:7)))# -> ngCMatrix ## an empty sparse matrix: (e <- sparseMatrix(dims = c(4,6), i={}, j={})) ## a symmetric one: (sy <- sparseMatrix(i= c(2,4,3:5), j= c(4,7:5,5), x = 1:5, dims = c(7,7), symmetric=TRUE)) stopifnot(isSymmetric(sy), identical(sy, ## switch i <-> j {and transpose } t( sparseMatrix(j= c(2,4,3:5), i= c(4,7:5,5), x = 1:5, dims = c(7,7), symmetric=TRUE)))) ## rsparsematrix() calls sparseMatrix() : M1 <- rsparsematrix(1000, 20, nnz = 200) summary(M1) ## pointers example in converting from other sparse matrix representations. if(requireNamespace("SparseM") && packageVersion("SparseM") >= "0.87" && nzchar(dfil <- system.file("extdata", "rua_32_ax.rua", package = "SparseM"))) { X <- SparseM::model.matrix(SparseM::read.matrix.hb(dfil)) XX <- sparseMatrix(j = X@ja, p = X@ia - 1L, x = X@ra, dims = X@dimension) validObject(XX) ## Alternatively, and even more user friendly : X. <- as(X, "Matrix") # or also X2 <- as(X, "sparseMatrix") stopifnot(identical(XX, X.), identical(X., X2)) }% if }% example Matrix/man/coerce-methods-graph.Rd0000644000175100001440000000704014575137654016620 0ustar hornikusers\name{coerce-methods-graph} \title{Conversions "graph" <--> (sparse) Matrix} % \docType{methods} \keyword{methods} \keyword{utilities} % \alias{coerce-methods-graph} % \alias{coerce,Matrix,graph-method} \alias{coerce,Matrix,graphNEL-method} \alias{coerce,TsparseMatrix,graphNEL-method} \alias{coerce,graph,CsparseMatrix-method} \alias{coerce,graph,Matrix-method} \alias{coerce,graph,RsparseMatrix-method} \alias{coerce,graph,TsparseMatrix-method} \alias{coerce,graph,sparseMatrix-method} \alias{coerce,graphAM,TsparseMatrix-method} \alias{coerce,graphNEL,TsparseMatrix-method} % \alias{T2graph} \alias{graph2T} % \description{ Since 2005, package \pkg{Matrix} has supported coercions to and from class \code{\link[graph:graph-class]{graph}} from package \href{https://bioconductor.org/packages/graph/}{\pkg{graph}}. Since 2013, this functionality has been exposed via functions \code{T2graph} and \code{graph2T}, which, unlike methods for \code{\link{as}(from, "")}, support optional arguments. } \usage{ graph2T(from, use.weights = ) T2graph(from, need.uniq = !isUniqueT(from), edgemode = NULL) } \arguments{ \item{from}{for \code{graph2T()}, an \R object of class \code{"graph"}; \cr for \code{T2graph()}, a sparse matrix inheriting from \code{"\linkS4class{TsparseMatrix}"}.} \item{use.weights}{logical indicating if weights should be used, i.e., equivalently the result will be numeric, i.e. of class \code{\linkS4class{dgTMatrix}}; otherwise the result will be \code{\linkS4class{ngTMatrix}} or \code{\linkS4class{nsTMatrix}}, the latter if the graph is undirected. The default looks if there are weights in the graph, and if any differ from \code{1}, weights are used.} \item{need.uniq}{a logical indicating if \code{from} may need to be internally \dQuote{uniqified}; do not set this and hence rather use the default, unless you know what you are doing!} \item{edgemode}{one of \code{NULL}, \code{"directed"}, or \code{"undirected"}. The default \code{NULL} looks if the matrix is symmetric and assumes \code{"undirected"} in that case.} } \value{ For \code{graph2T()}, a sparse matrix inheriting from \code{"\linkS4class{TsparseMatrix}"}. For \code{T2graph()} an \R object of class \code{"graph"}. } \seealso{ Package \CRANpkg{igraph}, which provides similar coercions to and from its class \code{igraph} via functions \code{graph_from_adjacency_matrix} and \code{as_adjacency_matrix}. } \examples{ if(requireNamespace("graph")) { n4 <- LETTERS[1:4]; dns <- list(n4,n4) show(a1 <- sparseMatrix(i= c(1:4), j=c(2:4,1), x = 2, dimnames=dns)) show(g1 <- as(a1, "graph")) # directed unlist(graph::edgeWeights(g1)) # all '2' show(a2 <- sparseMatrix(i= c(1:4,4), j=c(2:4,1:2), x = TRUE, dimnames=dns)) show(g2 <- as(a2, "graph")) # directed # now if you want it undirected: show(g3 <- T2graph(as(a2,"TsparseMatrix"), edgemode="undirected")) show(m3 <- as(g3,"Matrix")) show( graph2T(g3) ) # a "pattern Matrix" (nsTMatrix) \dontshow{ stopifnot( identical(as(g3,"Matrix"), as(as(a2 + t(a2), "nMatrix"),"symmetricMatrix")) , identical(tg3 <- graph2T(g3), graph2T(g3, use.weights=FALSE)) , identical(as(m3,"TsparseMatrix"), asUniqueT(tg3)) ) } a. <- sparseMatrix(i=4:1, j=1:4, dimnames=list(n4, n4), repr="T") # no 'x' show(a.) # "ngTMatrix" show(g. <- as(a., "graph")) \dontshow{ stopifnot(graph::edgemode(g.) == "undirected", graph::numEdges(g.) == 2, all.equal(as(g., "TsparseMatrix"), as(a., "symmetricMatrix")) ) } } } Matrix/man/condest.Rd0000644000175100001440000001042714521202214014232 0ustar hornikusers\name{condest} \title{Compute Approximate CONDition number and 1-Norm of (Large) Matrices} % \keyword{algebra} \keyword{math} \keyword{utilities} % \alias{condest} \alias{onenormest} % \description{ \dQuote{Estimate}, i.e. compute approximately the CONDition number of a (potentially large, often sparse) matrix \code{A}. It works by apply a fast \emph{randomized} approximation of the 1-norm, \code{norm(A,"1")}, through \code{onenormest(.)}. } \usage{ condest(A, t = min(n, 5), normA = norm(A, "1"), silent = FALSE, quiet = TRUE) onenormest(A, t = min(n, 5), A.x, At.x, n, silent = FALSE, quiet = silent, iter.max = 10, eps = 4 * .Machine$double.eps) } \arguments{ \item{A}{a square matrix, optional for \code{onenormest()}, where instead of \code{A}, \code{A.x} and \code{At.x} can be specified, see there.} \item{t}{number of columns to use in the iterations.} \item{normA}{number; (an estimate of) the 1-norm of \code{A}, by default \code{\link{norm}(A, "1")}; may be replaced by an estimate.} \item{silent}{logical indicating if warning and (by default) convergence messages should be displayed.} \item{quiet}{logical indicating if convergence messages should be displayed.} \item{A.x, At.x}{when \code{A} is missing, these two must be given as functions which compute \code{A \%\% x}, or \code{t(A) \%\% x}, respectively.} \item{n}{\code{ == nrow(A)}, only needed when \code{A} is not specified.} \item{iter.max}{maximal number of iterations for the 1-norm estimator.} \item{eps}{the relative change that is deemed irrelevant.} } \details{ \code{\link{condest}()} calls \code{\link{lu}(A)}, and subsequently \code{onenormest(A.x = , At.x = )} to compute an approximate norm of the \emph{inverse} of \code{A}, \eqn{A^{-1}}, in a way which keeps using sparse matrices efficiently when \code{A} is sparse. Note that \code{onenormest()} uses random vectors and hence \emph{both} functions' results are random, i.e., depend on the random seed, see, e.g., \code{\link{set.seed}()}. } \value{Both functions return a \code{\link{list}}; \code{condest()} with components, \item{est}{a number \eqn{> 0}, the estimated (1-norm) condition number \eqn{\hat\kappa}{k.}; when \eqn{r :=}\code{rcond(A)}, \eqn{1/\hat\kappa \approx r}{1/k. ~= r}.} \item{v}{the maximal \eqn{A x} column, scaled to norm(v) = 1. Consequently, \eqn{norm(A v) = norm(A) / est}; when \code{est} is large, \code{v} is an approximate null vector.} The function \code{onenormest()} returns a list with components, \item{est}{a number \eqn{> 0}, the estimated \code{norm(A, "1")}.} \item{v}{0-1 integer vector length \code{n}, with an \code{1} at the index \code{j} with maximal column \code{A[,j]} in \eqn{A}.} \item{w}{numeric vector, the largest \eqn{A x} found.} \item{iter}{the number of iterations used.} } \references{ %% See also Tim Davis(2006, p.96): Nicholas J. Higham and \enc{Françoise}{Francoise} Tisseur (2000). A Block Algorithm for Matrix 1-Norm Estimation, with an Application to 1-Norm Pseudospectra. \emph{SIAM J. Matrix Anal. Appl.} \bold{21}, 4, 1185--1201. %% OK for ETH, etc., but not free: \doi{10.1137/S0895479899356080} %% broken on 2022-10-20: \url{https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.7.9804} William W. Hager (1984). Condition Estimates. \emph{SIAM J. Sci. Stat. Comput.} \bold{5}, 311--316. } \author{This is based on octave's \code{condest()} and \code{onenormest()} implementations with original author Jason Riedy, U Berkeley; translation to \R and adaption by Martin Maechler. } \seealso{ \code{\link{norm}}, \code{\link{rcond}}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } data(KNex, package = "Matrix") mtm <- with(KNex, crossprod(mm)) system.time(ce <- condest(mtm)) sum(abs(ce$v)) ## || v ||_1 == 1 ## Prove that || A v || = || A || / est (as ||v|| = 1): stopifnot(all.equal(norm(mtm \%*\% ce$v), norm(mtm) / ce$est)) ## reciprocal 1 / ce$est system.time(rc <- rcond(mtm)) # takes ca 3 x longer rc all.equal(rc, 1/ce$est) # TRUE -- the approximation was good one <- onenormest(mtm) str(one) ## est = 12.3 ## the maximal column: which(one$v == 1) # mostly 4, rarely 1, depending on random seed } Matrix/man/ngeMatrix-class.Rd0000644000175100001440000000316014467516513015653 0ustar hornikusers\name{ngeMatrix-class} \title{Class "ngeMatrix" of General Dense Nonzero-pattern Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{ngeMatrix-class} % \alias{Arith,ngeMatrix,ngeMatrix-method} \alias{Compare,ngeMatrix,ngeMatrix-method} \alias{Logic,ngeMatrix,ngeMatrix-method} % \description{This is the class of general dense nonzero-pattern matrices, see \code{\linkS4class{nMatrix}}. } \section{Slots}{ \describe{ \item{\code{x}:}{Object of class \code{"logical"}. The logical values that constitute the matrix, stored in column-major order.} \item{\code{Dim},\code{Dimnames}:}{The dimension (a length-2 \code{"integer"}) and corresponding names (or \code{NULL}), see the \code{\linkS4class{Matrix}} class.} \item{\code{factors}:}{Object of class \code{"list"}. A named list of factorizations that have been computed for the matrix.} } } \section{Extends}{ Class \code{"ndenseMatrix"}, directly. Class \code{"lMatrix"}, by class \code{"ndenseMatrix"}. Class \code{"denseMatrix"}, by class \code{"ndenseMatrix"}. Class \code{"Matrix"}, by class \code{"ndenseMatrix"}. Class \code{"Matrix"}, by class \code{"ndenseMatrix"}. } \section{Methods}{ Currently, mainly \code{\link{t}()} and coercion methods (for \code{\link{as}(.)}); use, e.g., \code{\link{showMethods}(class="ngeMatrix")} for details. } \seealso{ Non-general logical dense matrix classes such as \code{\linkS4class{ntrMatrix}}, or \code{\linkS4class{nsyMatrix}}; \emph{sparse} logical classes such as \code{\linkS4class{ngCMatrix}}. } \examples{ showClass("ngeMatrix") ## "lgeMatrix" is really more relevant } Matrix/man/isTriangular-methods.Rd0000644000175100001440000000601414575137654016725 0ustar hornikusers\name{isTriangular-methods} \title{Test whether a Matrix is Triangular or Diagonal} % \docType{methods} \keyword{array} \keyword{programming} \keyword{methods} % \alias{isTriangular} \alias{isTriangular-methods} \alias{isDiagonal} \alias{isDiagonal-methods} % \alias{isTriangular,CsparseMatrix-method} \alias{isTriangular,RsparseMatrix-method} \alias{isTriangular,TsparseMatrix-method} \alias{isTriangular,denseMatrix-method} \alias{isTriangular,diagonalMatrix-method} \alias{isTriangular,indMatrix-method} \alias{isTriangular,matrix-method} % \alias{isDiagonal,CsparseMatrix-method} \alias{isDiagonal,RsparseMatrix-method} \alias{isDiagonal,TsparseMatrix-method} \alias{isDiagonal,denseMatrix-method} \alias{isDiagonal,diagonalMatrix-method} \alias{isDiagonal,indMatrix-method} \alias{isDiagonal,matrix-method} % \description{ \code{isTriangular} and \code{isDiagonal} test whether their argument is a triangular or diagonal matrix, respectively. Unlike the analogous \code{\link{isSymmetric}}, these two functions are generically from \pkg{Matrix} rather than \code{base}. Hence \pkg{Matrix} defines methods for traditional matrices of implicit \link{class} \code{"\link{matrix}"} in addition to matrices inheriting from virtual class \code{"\linkS4class{Matrix}"}. By our definition, triangular and diagonal matrices are \emph{square}, i.e., they have the same number of rows and columns. } \usage{ isTriangular(object, upper = NA, \dots) isDiagonal(object) } \arguments{ \item{object}{an \R object, typically a matrix.} \item{upper}{a \link{logical}, either \code{TRUE} or \code{FALSE}, in which case \code{TRUE} is returned only for upper or lower triangular \code{object}; or otherwise \code{\link{NA}} (the default), in which case \code{TRUE} is returned for any triangular \code{object}.} \item{\dots}{further arguments passed to methods (currently unused by \pkg{Matrix}).} } \value{ A \link{logical}, either \code{TRUE} or \code{FALSE} (never \code{\link{NA}}). If \code{object} is triangular and \code{upper} is \code{NA}, then \code{isTriangular} returns \code{TRUE} with an \link[=attr]{attribute} \code{kind}, either \code{"U"} or \code{"L"}, indicating that \code{object} is \bold{u}pper or \bold{l}ower triangular, respectively. Users should not rely on how \code{kind} is determined for diagonal matrices, which are both upper and lower triangular. } \seealso{ \code{\link{isSymmetric}}; virtual classes \code{"\linkS4class{triangularMatrix}"} and \code{"\linkS4class{diagonalMatrix}"} and their subclasses. } \examples{ isTriangular(Diagonal(4)) ## is TRUE: a diagonal matrix is also (both upper and lower) triangular (M <- Matrix(c(1,2,0,1), 2,2)) isTriangular(M) # TRUE (*and* of formal class "dtrMatrix") isTriangular(as(M, "generalMatrix")) # still triangular, even if not "formally" isTriangular(crossprod(M)) # FALSE isDiagonal(matrix(c(2,0,0,1), 2,2)) # TRUE ## Look at implementations: showMethods("isTriangular", includeDefs = TRUE) showMethods("isDiagonal", includeDefs = TRUE) } Matrix/man/fastMisc.Rd0000644000175100001440000002624514503343553014365 0ustar hornikusers\name{fastMisc} \title{\dQuote{Low Level} Coercions and Methods} % \keyword{utilities} % \alias{fastMisc} % coercions: \alias{.M2kind} \alias{.M2gen} \alias{.M2sym} \alias{.M2tri} \alias{.M2diag} \alias{.M2v} \alias{.M2m} \alias{.M2unpacked} \alias{.M2packed} \alias{.M2C} \alias{.M2R} \alias{.M2T} \alias{.M2V} \alias{.m2V} \alias{.sparse2dense} \alias{.diag2dense} \alias{.ind2dense} \alias{.m2dense} \alias{.dense2sparse} \alias{.diag2sparse} \alias{.ind2sparse} \alias{.m2sparse} \alias{.tCRT} % coercions, predating API finalization, hence no longer documented: \alias{.CR2RC} \alias{.CR2T} \alias{.T2CR} \alias{.dense2g} \alias{.dense2kind} \alias{.dense2m} \alias{.dense2v} \alias{.sparse2g} \alias{.sparse2kind} \alias{.sparse2m} \alias{.sparse2v} \alias{.tCR2RC} % other direct methods: \alias{.diag.dsC} \alias{.solve.dgC.lu} \alias{.solve.dgC.qr} \alias{.solve.dgC.chol} \alias{.updateCHMfactor} % \description{ \dQuote{Semi-API} functions used internally by \pkg{Matrix}, often to bypass S4 dispatch and avoid the associated overhead. These are exported to provide this capability to expert users. Typical users should continue to rely on S4 generic functions to dispatch suitable methods, by calling, e.g., \code{as(., )} for coercions. } \usage{ .M2kind(from, kind = ".", sparse = NA) .M2gen(from, kind = ".") .M2sym(from, \dots) .M2tri(from, \dots) .M2diag(from) .M2v(from) .M2m(from) .M2unpacked(from) .M2packed(from) .M2C(from) .M2R(from) .M2T(from) .M2V(from) .m2V(from, kind = ".") .sparse2dense(from, packed = FALSE) .diag2dense(from, kind = ".", shape = "t", packed = FALSE, uplo = "U") .ind2dense(from, kind = "n") .m2dense(from, class = ".ge", uplo = "U", diag = "N", trans = FALSE) .dense2sparse(from, repr = "C") .diag2sparse(from, kind = ".", shape = "t", repr = "C", uplo = "U") .ind2sparse(from, kind = "n", repr = ".") .m2sparse(from, class = ".gC", uplo = "U", diag = "N", trans = FALSE) .tCRT(x, lazy = TRUE) .diag.dsC(x, Chx = Cholesky(x, LDL = TRUE), res.kind = "diag") .solve.dgC.lu (a, b, tol = .Machine$double.eps, check = TRUE) .solve.dgC.qr (a, b, order = 3L, check = TRUE) .solve.dgC.chol(a, b, check = TRUE) .updateCHMfactor(object, parent, mult = 0) } \arguments{ \item{from, x, a, b}{a \code{\linkS4class{Matrix}}, matrix, or vector.} \item{kind}{a string (\code{"."}, \code{","}, \code{"n"}, \code{"l"}, or \code{"d"}) specifying the \dQuote{kind} of the result. \code{"."} indicates that the kind of \code{from} should be preserved. \code{","} is equivalent to \code{"z"} if \code{from} is complex and to \code{"d"} otherwise. \code{"n"} indicates that the result should inherit from \code{\linkS4class{nMatrix}} or \code{\linkS4class{nsparseVector}} (and so on).} \item{shape}{a string (\code{"."}, \code{"g"}, \code{"s"}, or \code{"t"}) specifying the \dQuote{shape} of the result. \code{"."} indicates that the shape of \code{from} should be preserved. \code{"g"} indicates that the result should inherit from \code{\linkS4class{generalMatrix}} (and so on).} \item{repr}{a string (\code{"."}, \code{"C"}, \code{"R"}, or \code{"T"}) specifying the sparse representation of the result. \code{"."} is accepted only by \code{.ind2sparse} and indicates the most efficient representation, which is \code{"C"} (\code{"R"}) for \code{margin = 2} (\code{1}). \code{"C"} indicates that the result should inherit from \code{\linkS4class{CsparseMatrix}} (and so on).} \item{packed}{a logical indicating if the result should inherit from \code{\linkS4class{packedMatrix}} rather than from \code{\linkS4class{unpackedMatrix}}. It is ignored for \code{from} inheriting from \code{\linkS4class{generalMatrix}}.} \item{sparse}{a logical indicating if the result should inherit from \code{\linkS4class{sparseMatrix}} rather than from \code{\linkS4class{denseMatrix}}. If \code{NA}, then the result will be formally sparse if and only if \code{from} is.} \item{uplo}{a string (\code{"U"} or \code{"L"}) indicating whether the result (if symmetric or triangular) should store the upper or lower triangle of \code{from}. The elements of \code{from} in the opposite triangle are ignored.} \item{diag}{a string (\code{"N"} or \code{"U"}) indicating whether the result (if triangular) should be formally nonunit or unit triangular. In the unit triangular case, the diagonal elements of \code{from} are ignored.} \item{trans}{a logical indicating if the result should be a 1-row matrix rather than a 1-column matrix where \code{from} is a vector but not a matrix.} \item{class}{a string whose first three characters specify the class of the result. It should match the pattern \code{"^[.nld](ge|sy|tr|sp|tp)"} for \code{.m2dense} and \code{"^[.nld][gst][CRT]"} for \code{.m2sparse}, where \code{"."} in the first position is equivalent to \code{"l"} for logical arguments and \code{"d"} for numeric arguments.} \item{\dots}{optional arguments passed to \code{\link{isSymmetric}} or \code{\link{isTriangular}}.} %% .tCRT : \item{lazy}{a logical indicating if the transpose should be constructed with minimal allocation, but possibly \emph{without} preserving representation.} %% .diag.dsC : \item{Chx}{optionally, the \code{\link{Cholesky}(x, \dots)} factorization of \code{x}. If supplied, then \code{x} is unused.} \item{res.kind}{a string in \code{c("trace", "sumLog", "prod", "min", "max", "range", "diag", "diagBack")}.} %% .solve.dgC.* : \item{tol}{see \code{\link{lu-methods}}.} \item{order}{see \code{\link{qr-methods}}.} \item{check}{a logical indicating if the first argument should be tested for inheritance from \code{\linkS4class{dgCMatrix}} and coerced if necessary. Set to \code{FALSE} for speed only if it is known to already inherit from \code{\linkS4class{dgCMatrix}}.} %% .updateCHMfactor : \item{object}{a Cholesky factorization inheriting from virtual class \code{CHMfactor}, almost always the result of a call to generic function \code{\link{Cholesky}}.} \item{parent}{an object of class \code{\linkS4class{dsCMatrix}} or class \code{\linkS4class{dgCMatrix}}.} \item{mult}{a numeric vector of postive length. Only the first element is used, and that must be finite.} } \details{ Functions with names of the form \code{.2} implement coercions from virtual class A to the \dQuote{nearest} non-virtual subclass of virtual class B, where the virtual classes are abbreviated as follows: \describe{ \item{\code{M}}{\code{\linkS4class{Matrix}}} \item{\code{V}}{\code{\linkS4class{sparseVector}}} \item{\code{m}}{matrix} \item{\code{v}}{vector} \item{\code{dense}}{\code{\linkS4class{denseMatrix}}} \item{\code{unpacked}}{\code{\linkS4class{unpackedMatrix}}} \item{\code{packed}}{\code{\linkS4class{packedMatrix}}} \item{\code{sparse}}{% \code{\linkS4class{CsparseMatrix}}, \code{\linkS4class{RsparseMatrix}}, or \code{\linkS4class{TsparseMatrix}}} \item{\code{C}}{\code{\linkS4class{CsparseMatrix}}} \item{\code{R}}{\code{\linkS4class{RsparseMatrix}}} \item{\code{T}}{\code{\linkS4class{TsparseMatrix}}} \item{\code{gen}}{\code{\linkS4class{generalMatrix}}} \item{\code{sym}}{\code{\linkS4class{symmetricMatrix}}} \item{\code{tri}}{\code{\linkS4class{triangularMatrix}}} \item{\code{diag}}{\code{\linkS4class{diagonalMatrix}}} \item{\code{ind}}{\code{\linkS4class{indMatrix}}} } Abbreviations should be seen as a guide, rather than as an exact description of behaviour. Notably, \code{.m2dense}, \code{.m2sparse}, and \code{.m2V} accept vectors that are not matrices. \subsection{\code{.tCRT(x)}}{ If \code{lazy = TRUE}, then \code{.tCRT} constructs the transpose of \code{x} using the most efficient representation, which for \samp{CRT} is \samp{RCT}. If \code{lazy = FALSE}, then \code{.tCRT} preserves the representation of \code{x}, behaving as the corresponding methods for generic function \code{t}. } \subsection{\code{.diag.dsC(x)}}{ \code{.diag.dsC} computes (or uses if \code{Chx} is supplied) the Cholesky factorization of \code{x} as \eqn{L D L'} in order to calculate one of several possible statistics from the diagonal entries of \eqn{D}. See \code{res.kind} under \sQuote{Arguments}. } \subsection{\code{.solve.dgC.*(a, b)}}{ \code{.solve.dgC.lu(a, b)} needs a square matrix \code{a}. \code{.solve.dgC.qr(a, b)} needs a \dQuote{long} matrix \code{a}, with \code{nrow(a) >= ncol(a)}. \code{.solve.dgC.chol(a, b)} needs a \dQuote{wide} matrix \code{a}, with \code{nrow(a) <= ncol(a)}. All three may be used to solve sparse linear systems directly. Only \code{.solve.dgC.qr} and \code{.solve.dgC.chol} be used to solve sparse \emph{least squares} problems. } \subsection{\code{.updateCHMfactor(object, parent, mult)}}{ \code{.updateCHMfactor} updates \code{object} with the result of Cholesky factorizing \code{F(parent) + mult[1] * diag(nrow(parent))}, i.e., \code{F(parent)} plus \code{mult[1]} times the identity matrix, where \code{F = identity} if \code{parent} is a \code{dsCMatrix} and \code{F = tcrossprod} if \code{parent} is a \code{dgCMatrix}. The nonzero pattern of \code{F(parent)} must match that of \code{S} if \code{object = Cholesky(S, \dots)}. } } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } D. <- diag(x = c(1, 1, 2, 3, 5, 8)) D.0 <- Diagonal(x = c(0, 0, 0, 3, 5, 8)) S. <- toeplitz(as.double(1:6)) C. <- new("dgCMatrix", Dim = c(3L, 4L), p = c(0L, 1L, 1L, 1L, 3L), i = c(1L, 0L, 2L), x = c(-8, 2, 3)) stopifnot(exprs = { identical(.M2tri (D.), as(D., "triangularMatrix")) identical(.M2sym (D.), as(D., "symmetricMatrix")) identical(.M2diag(D.), as(D., "diagonalMatrix")) identical(.M2kind(C., "l"), as(C., "lMatrix")) identical(.M2kind(.sparse2dense(C.), "l"), as(as(C., "denseMatrix"), "lMatrix")) identical(.diag2sparse(D.0, ".", "t", "C"), .dense2sparse(.diag2dense(D.0, ".", "t", TRUE), "C")) identical(.M2gen(.diag2dense(D.0, ".", "s", FALSE)), .sparse2dense(.M2gen(.diag2sparse(D.0, ".", "s", "T")))) identical(S., .M2m(.m2sparse(S., ".sR"))) identical(S. * lower.tri(S.) + diag(1, 6L), .M2m(.m2dense (S., ".tr", "L", "U"))) identical(.M2R(C.), .M2R(.M2T(C.))) identical(.tCRT(C.), .M2R(t(C.))) }) A <- tcrossprod(C.)/6 + Diagonal(3, 1/3); A[1,2] <- 3; A stopifnot(exprs = { is.numeric( x. <- c(2.2, 0, -1.2) ) all.equal(x., .solve.dgC.lu(A, c(1,0,0), check=FALSE)) all.equal(x., .solve.dgC.qr(A, c(1,0,0), check=FALSE)) }) ## Solving sparse least squares: X <- rbind(A, Diagonal(3)) # design matrix X (for L.S.) Xt <- t(X) # *transposed* X (for L.S.) (y <- drop(crossprod(Xt, 1:3)) + c(-1,1)/1000) # small rand.err. str(solveCh <- .solve.dgC.chol(Xt, y, check=FALSE)) # Xt *is* dgC.. stopifnot(exprs = { all.equal(solveCh$coef, 1:3, tol = 1e-3)# rel.err ~ 1e-4 all.equal(solveCh$coef, drop(solve(tcrossprod(Xt), Xt \%*\% y))) all.equal(solveCh$coef, .solve.dgC.qr(X, y, check=FALSE)) }) } Matrix/man/BunchKaufman-methods.Rd0000644000175100001440000000735714446607050016623 0ustar hornikusers\name{BunchKaufman-methods} \title{Methods for Bunch-Kaufman Factorization} % \docType{methods} \keyword{algebra} \keyword{array} \keyword{methods} % \alias{BunchKaufman} \alias{BunchKaufman-methods} % \alias{BunchKaufman,dspMatrix-method} \alias{BunchKaufman,dsyMatrix-method} \alias{BunchKaufman,matrix-method} % \description{ Computes the Bunch-Kaufman factorization of an \eqn{n \times n}{n-by-n} real, symmetric matrix \eqn{A}, which has the general form \deqn{A = U D_{U} U' = L D_{L} L'}{A = U * DU * U' = L * DL * L'} where \eqn{D_{U}}{DU} and \eqn{D_{L}}{DL} are symmetric, block diagonal matrices composed of \eqn{b_{U}}{bU} and \eqn{b_{L}}{bL} \eqn{1 \times 1}{1-by-1} or \eqn{2 \times 2}{2-by-2} diagonal blocks; \eqn{U = \prod_{k = 1}^{b_{U}} P_{k} U_{k}}{U = prod(Pk * Uk : k = 1,...,bU)} is the product of \eqn{b_{U}}{bU} row-permuted unit upper triangular matrices, each having nonzero entries above the diagonal in 1 or 2 columns; and \eqn{L = \prod_{k = 1}^{b_{L}} P_{k} L_{k}}{L = prod(Pk * Lk : k = 1,...,bL)} is the product of \eqn{b_{L}}{bL} row-permuted unit lower triangular matrices, each having nonzero entries below the diagonal in 1 or 2 columns. Methods are built on LAPACK routines \code{dsytrf} and \code{dsptrf}. } \usage{ BunchKaufman(x, \dots) \S4method{BunchKaufman}{dsyMatrix}(x, warnSing = TRUE, \dots) \S4method{BunchKaufman}{dspMatrix}(x, warnSing = TRUE, \dots) \S4method{BunchKaufman}{matrix}(x, uplo = "U", \dots) } \arguments{ \item{x}{a \link[=is.finite]{finite} symmetric matrix or \code{\linkS4class{Matrix}} to be factorized. If \code{x} is square but not symmetric, then it will be \emph{treated} as symmetric; see \code{uplo}.} \item{warnSing}{a logical indicating if a \link{warning} should be signaled for singular \code{x}.} \item{uplo}{a string, either \code{"U"} or \code{"L"}, indicating which triangle of \code{x} should be used to compute the factorization.} \item{\dots}{further arguments passed to or from methods.} } \value{ An object representing the factorization, inheriting from virtual class \code{\linkS4class{BunchKaufmanFactorization}}. The specific class is \code{\linkS4class{BunchKaufman}} unless \code{x} inherits from virtual class \code{\linkS4class{packedMatrix}}, in which case it is \code{\linkS4class{pBunchKaufman}}. } \seealso{ Classes \code{\linkS4class{BunchKaufman}} and \code{\linkS4class{pBunchKaufman}} and their methods. Classes \code{\linkS4class{dsyMatrix}} and \code{\linkS4class{dspMatrix}}. Generic functions \code{\link{expand1}} and \code{\link{expand2}}, for constructing matrix factors from the result. Generic functions \code{\link{Cholesky}}, \code{\link{Schur}}, \code{\link{lu}}, and \code{\link{qr}}, for computing other factorizations. } \references{ The LAPACK source code, including documentation; see \url{https://netlib.org/lapack/double/dsytrf.f} and \url{https://netlib.org/lapack/double/dsptrf.f}. Golub, G. H., & Van Loan, C. F. (2013). \emph{Matrix computations} (4th ed.). Johns Hopkins University Press. \doi{10.56021/9781421407944} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } showMethods("BunchKaufman", inherited = FALSE) set.seed(0) data(CAex, package = "Matrix") class(CAex) # dgCMatrix isSymmetric(CAex) # symmetric, but not formally A <- as(CAex, "symmetricMatrix") class(A) # dsCMatrix ## Have methods for denseMatrix (unpacked and packed), ## but not yet sparseMatrix ... \dontrun{ (bk.A <- BunchKaufman(A)) } (bk.A <- BunchKaufman(as(A, "unpackedMatrix"))) ## A ~ U DU U' in floating point str(e.bk.A <- expand2(bk.A), max.level = 2L) stopifnot(all.equal(as(A, "matrix"), as(Reduce(`\%*\%`, e.bk.A), "matrix"))) } Matrix/man/symmetricMatrix-class.Rd0000644000175100001440000000677314575137654017140 0ustar hornikusers\name{symmetricMatrix-class} \title{Virtual Class of Symmetric Matrices in Package Matrix} % \docType{class} \keyword{array} \keyword{classes} % \alias{symmetricMatrix-class} % \alias{coerce,matrix,symmetricMatrix-method} \alias{dimnames,symmetricMatrix-method} \alias{dimnames<-,symmetricMatrix,NULL-method} \alias{dimnames<-,symmetricMatrix,list-method} % \description{ The virtual class of symmetric matrices, \code{"symmetricMatrix"}, from the package \pkg{Matrix} contains numeric and logical, dense and sparse matrices, e.g., see the examples with the \dQuote{actual} subclasses. The main use is in methods (and C functions) that can deal with all symmetric matrices, and in \code{as(*, "symmetricMatrix")}. } % \section{Objects from the Class}{A virtual Class: No objects may be created from it.} \section{Slots}{ \describe{ \item{\code{Dim, Dimnames}}{inherited from virtual class \code{\linkS4class{Matrix}}. See comments below about symmetry of \code{Dimnames}.} \item{\code{factors}}{a list of \code{\linkS4class{MatrixFactorization}} objects caching factorizations of the matrix. Typically, it is initialized as an empty list and updated \dQuote{automagically} whenever a factorization is computed.} \item{\code{uplo}}{a character string, either \code{"U"} or \code{"L"} indicating that only entries in the upper or lower triangle are referenced.} } } \section{Extends}{ Class \code{"Matrix"}, directly. } \section{Methods}{ \describe{ \item{dimnames}{\code{signature(object = "symmetricMatrix")}: returns \emph{symmetric} \code{\link{dimnames}}, even when the \code{Dimnames} slot only has row or column names. This allows to save storage for large (typically sparse) symmetric matrices.} \item{isSymmetric}{\code{signature(object = "symmetricMatrix")}: returns \code{TRUE} trivially.} } There's a C function \code{symmetricMatrix_validate()}% in ../src/dsyMatrix.c called by the internal validity checking functions, and also from \code{\link{getValidity}(getClass("symmetricMatrix"))}. } \section{Validity and \code{\link{dimnames}}}{ The validity checks do not require a symmetric \code{Dimnames} slot, so it can be \code{list(NULL, )}, e.g., for efficiency. However, \code{\link{dimnames}()} and other functions and methods should behave as if the dimnames were symmetric, i.e., with both list components identical. } \seealso{ \code{\link{isSymmetric}} which has efficient methods (\link{isSymmetric-methods}) for the \pkg{Matrix} classes. Classes \code{\linkS4class{triangularMatrix}}, and, e.g., \code{\linkS4class{dsyMatrix}} for numeric \emph{dense} matrices, or \code{\linkS4class{lsCMatrix}} for a logical \emph{sparse} matrix class. } \examples{ ## An example about the symmetric Dimnames: sy <- sparseMatrix(i= c(2,4,3:5), j= c(4,7:5,5), x = 1:5, dims = c(7,7), symmetric=TRUE, dimnames = list(NULL, letters[1:7])) sy # shows symmetrical dimnames sy@Dimnames # internally only one part is stored dimnames(sy) # both parts - as sy *is* symmetrical \dontshow{ local({ nm <- letters[1:7] stopifnot(identical(dimnames(sy), list( nm, nm)), identical(sy@Dimnames , list(NULL, nm))) }) }%dont showClass("symmetricMatrix") ## The names of direct subclasses: scl <- getClass("symmetricMatrix")@subclasses directly <- sapply(lapply(scl, slot, "by"), length) == 0 names(scl)[directly] ## Methods -- applicaple to all subclasses above: showMethods(classes = "symmetricMatrix") } Matrix/man/ldiMatrix-class.Rd0000644000175100001440000000754414500644730015653 0ustar hornikusers\name{ldiMatrix-class} \title{Class "ldiMatrix" of Diagonal Logical Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{ldiMatrix-class} \alias{ndiMatrix-class} % for now % \alias{!,ldiMatrix-method} \alias{\%\%,ldiMatrix,Matrix-method} \alias{\%\%,ldiMatrix,ddenseMatrix-method} \alias{\%\%,ldiMatrix,ldenseMatrix-method} \alias{\%\%,ldiMatrix,ndenseMatrix-method} \alias{\%/\%,ldiMatrix,Matrix-method} \alias{\%/\%,ldiMatrix,ddenseMatrix-method} \alias{\%/\%,ldiMatrix,ldenseMatrix-method} \alias{\%/\%,ldiMatrix,ndenseMatrix-method} \alias{&,ldiMatrix,Matrix-method} \alias{&,ldiMatrix,ddenseMatrix-method} \alias{&,ldiMatrix,ldenseMatrix-method} \alias{&,ldiMatrix,ndenseMatrix-method} \alias{*,ldiMatrix,Matrix-method} \alias{*,ldiMatrix,ddenseMatrix-method} \alias{*,ldiMatrix,ldenseMatrix-method} \alias{*,ldiMatrix,ndenseMatrix-method} \alias{/,ldiMatrix,Matrix-method} \alias{/,ldiMatrix,ddenseMatrix-method} \alias{/,ldiMatrix,ldenseMatrix-method} \alias{/,ldiMatrix,ndenseMatrix-method} \alias{Arith,ldiMatrix,logical-method} \alias{Arith,ldiMatrix,numeric-method} \alias{Arith,logical,ldiMatrix-method} \alias{Arith,numeric,ldiMatrix-method} \alias{Ops,ANY,ldiMatrix-method} \alias{Ops,ldiMatrix,ANY-method} \alias{Ops,ldiMatrix,Matrix-method} \alias{Ops,ldiMatrix,dMatrix-method} \alias{Ops,ldiMatrix,ddiMatrix-method} \alias{Ops,ldiMatrix,ldiMatrix-method} \alias{Ops,ldiMatrix,ndiMatrix-method} \alias{Ops,ldiMatrix,logical-method} \alias{Ops,ldiMatrix,numeric-method} \alias{Ops,ldiMatrix,sparseMatrix-method} \alias{which,ldiMatrix-method} % \alias{!,ndiMatrix-method} \alias{\%\%,ndiMatrix,Matrix-method} \alias{\%\%,ndiMatrix,ddenseMatrix-method} \alias{\%\%,ndiMatrix,ldenseMatrix-method} \alias{\%\%,ndiMatrix,ndenseMatrix-method} \alias{\%/\%,ndiMatrix,Matrix-method} \alias{\%/\%,ndiMatrix,ddenseMatrix-method} \alias{\%/\%,ndiMatrix,ldenseMatrix-method} \alias{\%/\%,ndiMatrix,ndenseMatrix-method} \alias{&,ndiMatrix,Matrix-method} \alias{&,ndiMatrix,ddenseMatrix-method} \alias{&,ndiMatrix,ldenseMatrix-method} \alias{&,ndiMatrix,ndenseMatrix-method} \alias{*,ndiMatrix,Matrix-method} \alias{*,ndiMatrix,Matrix-method} \alias{*,ndiMatrix,ddenseMatrix-method} \alias{*,ndiMatrix,ldenseMatrix-method} \alias{*,ndiMatrix,ndenseMatrix-method} \alias{/,ndiMatrix,Matrix-method} \alias{/,ndiMatrix,ddenseMatrix-method} \alias{/,ndiMatrix,ldenseMatrix-method} \alias{/,ndiMatrix,ndenseMatrix-method} \alias{Ops,ndiMatrix,ddiMatrix-method} \alias{Ops,ndiMatrix,ldiMatrix-method} \alias{Ops,ndiMatrix,ndiMatrix-method} \alias{which,ndiMatrix-method} % \description{The class \code{"ldiMatrix"} of logical diagonal matrices. %% FIXME add more } \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("ldiMatrix", ...)} but typically rather via \code{\link{Diagonal}}. } \section{Slots}{ \describe{ \item{\code{x}:}{\code{"logical"} vector.} \item{\code{diag}:}{\code{"character"} string, either "U" or "N", see \code{\linkS4class{ddiMatrix}}.} \item{\code{Dim},\code{Dimnames}:}{matrix dimension and \code{\link{dimnames}}, see the \code{\linkS4class{Matrix}} class description.} } } \section{Extends}{ Class \code{"\linkS4class{diagonalMatrix}"} and class \code{"\linkS4class{lMatrix}"}, directly. Class \code{"\linkS4class{sparseMatrix}"}, by class \code{"diagonalMatrix"}. } % \section{Methods}{ % No methods defined with class "ldiMatrix" in the signature. % } % \references{ ~put references to the literature/web site here ~ } \seealso{ Classes \code{\linkS4class{ddiMatrix}} and \code{\linkS4class{diagonalMatrix}}; function \code{\link{Diagonal}}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } (lM <- Diagonal(x = c(TRUE,FALSE,FALSE))) str(lM)#> gory details (slots) crossprod(lM) # numeric (nM <- as(lM, "nMatrix")) crossprod(nM) # pattern sparse } Matrix/man/lsparseMatrix-class.Rd0000644000175100001440000001515414575324114016553 0ustar hornikusers\name{lsparseMatrix-class} \title{Sparse logical matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{lsparseMatrix-class} \alias{lsparseMatrix-classes} % used by package 'enhancerHomologSearch' \alias{lgCMatrix-class} \alias{lgRMatrix-class} \alias{lgTMatrix-class} \alias{ltCMatrix-class} \alias{ltRMatrix-class} \alias{ltTMatrix-class} \alias{lsCMatrix-class} \alias{lsRMatrix-class} \alias{lsTMatrix-class} % lsparse \alias{!,lsparseMatrix-method} \alias{Arith,lsparseMatrix,Matrix-method} \alias{Logic,lsparseMatrix,ldenseMatrix-method} \alias{Logic,lsparseMatrix,lsparseMatrix-method} \alias{Ops,lsparseMatrix,lsparseMatrix-method} \alias{Ops,lsparseMatrix,nsparseMatrix-method} \alias{coerce,matrix,lsparseMatrix-method} \alias{coerce,vector,lsparseMatrix-method} \alias{which,lsparseMatrix-method} % lgC \alias{Arith,lgCMatrix,lgCMatrix-method} \alias{Logic,lgCMatrix,lgCMatrix-method} % lgR % lgT \alias{Arith,lgTMatrix,lgTMatrix-method} \alias{Logic,lgTMatrix,lgTMatrix-method} % ltC \alias{Logic,ltCMatrix,ltCMatrix-method} % ltR % ltT % lsC \alias{Logic,lsCMatrix,lsCMatrix-method} % lsR % lsT % \description{The \code{lsparseMatrix} class is a virtual class of logical sparse matrices, i.e., sparse matrices with entries \code{TRUE}, \code{FALSE}, or \code{NA}. These can be stored in the \dQuote{triplet} form (class \code{\linkS4class{TsparseMatrix}}, subclasses \code{lgTMatrix}, \code{lsTMatrix}, and \code{ltTMatrix}) or in compressed column-oriented form (class \code{\linkS4class{CsparseMatrix}}, subclasses \code{lgCMatrix}, \code{lsCMatrix}, and \code{ltCMatrix}) or--\emph{rarely}--in compressed row-oriented form (class \code{\linkS4class{RsparseMatrix}}, subclasses \code{lgRMatrix}, \code{lsRMatrix}, and \code{ltRMatrix}). The second letter in the name of these non-virtual classes indicates \code{g}eneral, \code{s}ymmetric, or \code{t}riangular. } \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("lgCMatrix", ...)} and so on. More frequently objects are created by coercion of a numeric sparse matrix to the logical form, e.g. in an expression \code{x != 0}. The logical form is also used in the symbolic analysis phase of an algorithm involving sparse matrices. Such algorithms often involve two phases: a symbolic phase wherein the positions of the non-zeros in the result are determined and a numeric phase wherein the actual results are calculated. During the symbolic phase only the positions of the non-zero elements in any operands are of interest, hence any numeric sparse matrices can be treated as logical sparse matrices. } \details{ Note that triplet stored (\code{\linkS4class{TsparseMatrix}}) matrices such as \code{lgTMatrix} may contain duplicated pairs of indices \eqn{(i,j)} as for the corresponding numeric class \code{\linkS4class{dgTMatrix}} where for such pairs, the corresponding \code{x} slot entries are added. For logical matrices, the \code{x} entries corresponding to duplicated index pairs \eqn{(i,j)} are \dQuote{added} as well if the addition is defined as logical \eqn{or}, i.e., \dQuote{\code{TRUE + TRUE |-> TRUE}} and \dQuote{\code{TRUE + FALSE |-> TRUE}}. Note the use of \code{\link{asUniqueT}()} for getting an internally unique representation without duplicated \eqn{(i,j)} entries. } \section{Slots}{ \describe{ \item{\code{x}:}{Object of class \code{"logical"}, i.e., either \code{TRUE}, \code{\link{NA}}, or \code{FALSE}.} \item{\code{uplo}:}{Object of class \code{"character"}. Must be either "U", for upper triangular, and "L", for lower triangular. Present in the triangular and symmetric classes but not in the general class.} \item{\code{diag}:}{Object of class \code{"character"}. Must be either \code{"U"}, for unit triangular (diagonal is all ones), or \code{"N"} for non-unit. The implicit diagonal elements are not explicitly stored when \code{diag} is \code{"U"}. Present in the triangular classes only.} \item{\code{p}:}{Object of class \code{"integer"} of pointers, one for each column (row), to the initial (zero-based) index of elements in the column. Present in compressed column-oriented and compressed row-oriented forms only.} \item{\code{i}:}{Object of class \code{"integer"} of length nnzero (number of non-zero elements). These are the row numbers for each TRUE element in the matrix. All other elements are FALSE. Present in triplet and compressed column-oriented forms only.} \item{\code{j}:}{Object of class \code{"integer"} of length nnzero (number of non-zero elements). These are the column numbers for each TRUE element in the matrix. All other elements are FALSE. Present in triplet and compressed row-oriented forms only.} \item{\code{Dim}:}{Object of class \code{"integer"} - the dimensions of the matrix.} } } \section{Methods}{ \describe{ \item{coerce}{\code{signature(from = "dgCMatrix", to = "lgCMatrix")}} \item{t}{\code{signature(x = "lgCMatrix")}: returns the transpose of \code{x}} \item{which}{\code{signature(x = "lsparseMatrix")}, semantically equivalent to \pkg{base} function \code{\link{which}(x, arr.ind)}; for details, see the \code{\linkS4class{lMatrix}} class documentation.} } } \seealso{ the class \code{\linkS4class{dgCMatrix}} and \code{\linkS4class{dgTMatrix}} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } (m <- Matrix(c(0,0,2:0), 3,5, dimnames=list(LETTERS[1:3],NULL))) (lm <- (m > 1)) # lgC !lm # no longer sparse stopifnot(is(lm,"lsparseMatrix"), identical(!lm, m <= 1)) data(KNex, package = "Matrix") str(mmG.1 <- (KNex $ mm) > 0.1)# "lgC..." table(mmG.1@x)# however with many ``non-structural zeros'' ## from logical to nz_pattern -- okay when there are no NA's : nmG.1 <- as(mmG.1, "nMatrix") # <<< has "TRUE" also where mmG.1 had FALSE ## from logical to "double" dmG.1 <- as(mmG.1, "dMatrix") # has '0' and back: lmG.1 <- as(dmG.1, "lMatrix") stopifnot(identical(nmG.1, as((KNex $ mm) != 0,"nMatrix")), validObject(lmG.1), identical(lmG.1, mmG.1)) class(xnx <- crossprod(nmG.1))# "nsC.." class(xlx <- crossprod(mmG.1))# "dsC.." : numeric is0 <- (xlx == 0) mean(as.vector(is0))# 99.3\% zeros: quite sparse, but table(xlx@x == 0)# more than half of the entries are (non-structural!) 0 stopifnot(isSymmetric(xlx), isSymmetric(xnx), ## compare xnx and xlx : have the *same* non-structural 0s : sapply(slotNames(xnx), function(n) identical(slot(xnx, n), slot(xlx, n)))) } Matrix/man/expand-methods.Rd0000644000175100001440000002364314575137654015547 0ustar hornikusers\name{expand-methods} \title{Expand Matrix Factorizations} % \docType{methods} \keyword{algebra} \keyword{array} \keyword{methods} % \alias{expand} \alias{expand-methods} \alias{expand1} \alias{expand1-methods} \alias{expand2} \alias{expand2-methods} % \alias{expand,CHMfactor-method} \alias{expand,denseLU-method} \alias{expand,sparseLU-method} % \alias{expand1,BunchKaufman-method} \alias{expand1,CHMsimpl-method} \alias{expand1,CHMsuper-method} \alias{expand1,Cholesky-method} \alias{expand1,Schur-method} \alias{expand1,denseLU-method} \alias{expand1,pBunchKaufman-method} \alias{expand1,pCholesky-method} \alias{expand1,sparseLU-method} \alias{expand1,sparseQR-method} % \alias{expand2,BunchKaufman-method} \alias{expand2,CHMsimpl-method} \alias{expand2,CHMsuper-method} \alias{expand2,Cholesky-method} \alias{expand2,Schur-method} \alias{expand2,denseLU-method} \alias{expand2,pBunchKaufman-method} \alias{expand2,pCholesky-method} \alias{expand2,sparseLU-method} \alias{expand2,sparseQR-method} % \description{ \code{expand1} and \code{expand2} construct matrix factors from objects specifying matrix factorizations. Such objects typically do not store the factors explicitly, employing instead a compact representation to save memory. } \usage{ expand1(x, which, \dots) expand2(x, \dots) expand (x, \dots) } \arguments{ \item{x}{a matrix factorization, typically inheriting from virtual class \code{\linkS4class{MatrixFactorization}}.} \item{which}{a character string indicating a matrix factor.} \item{\dots}{further arguments passed to or from methods.} } \value{ \code{expand1} returns an object inheriting from virtual class \code{\linkS4class{Matrix}}, representing the factor indicated by \code{which}, always without row and column names. \code{expand2} returns a list of factors, typically with names using conventional notation, as in \code{list(L=, U=)}. The first and last factors get the row and column names of the factorized matrix, which are preserved in the \code{Dimnames} slot of \code{x}. } \details{ Methods for \code{expand} are retained only for backwards compatibility with \pkg{Matrix} \code{< 1.6-0}. New code should use \code{expand1} and \code{expand2}, whose methods provide more control and behave more consistently. Notably, \code{expand2} obeys the rule that the product of the matrix factors in the returned list should reproduce (within some tolerance) the factorized matrix, \emph{including} its \code{dimnames}. Hence if \code{x} is a matrix and \code{y} is its factorization, then \preformatted{ all.equal(as(x, "matrix"), as(Reduce(`\%*\%`, expand2(y)), "matrix"))} should in most cases return \code{TRUE}. } \section{Methods}{ The following table lists methods for \code{expand1} together with allowed values of argument \code{which}. \tabular{rl}{ \code{class(x)} \tab \code{which}\cr \code{\linkS4class{Schur}} \tab \code{c("Q", "T", "Q.")}\cr \code{\linkS4class{denseLU}} \tab \code{c("P1", "P1.", "L", "U")}\cr \code{\linkS4class{sparseLU}} \tab \code{c("P1", "P1.", "P2", "P2.", "L", "U")}\cr \code{\linkS4class{sparseQR}} \tab \code{c("P1", "P1.", "P2", "P2.", "Q", "Q1", "R", "R1")}\cr \code{\linkS4class{BunchKaufman}}, \code{\linkS4class{pBunchKaufman}} \tab \code{c("U", "DU", "U.", "L", "DL", "L.")}\cr \code{\linkS4class{Cholesky}}, \code{\linkS4class{pCholesky}} \tab \code{c("P1", "P1.", "L1", "D", "L1.", "L", "L.")}\cr \code{\linkS4class{CHMsimpl}}, \code{\linkS4class{CHMsimpl}} \tab \code{c("P1", "P1.", "L1", "D", "L1.", "L", "L.")} } Methods for \code{expand2} and \code{expand} are described below. Factor names and classes apply also to \code{expand1}. \describe{ \item{\code{expand2}}{\code{signature(x = "CHMsimpl")}: expands the factorization \eqn{A = P_{1}' L_{1} D L_{1}' P_{1} = P_{1}' L L' P_{1}}{A = P1' * L1 * D * L1' * P1 = P1' * L * L' * P1} as \code{list(P1., L1, D, L1., P1)} (the default) or as \code{list(P1., L, L., P1)}, depending on optional logical argument \code{LDL}. \code{P1} and \code{P1.} are \code{\linkS4class{pMatrix}}, \code{L1}, \code{L1.}, \code{L}, and \code{L.} are \code{\linkS4class{dtCMatrix}}, and \code{D} is a \code{\linkS4class{ddiMatrix}}.} \item{\code{expand2}}{\code{signature(x = "CHMsuper")}: as \code{CHMsimpl}, but the triangular factors are stored as \code{\linkS4class{dgCMatrix}}.} \item{\code{expand2}}{\code{signature(x = "p?Cholesky")}: expands the factorization \eqn{A = L_{1} D L_{1}' = L L'}{A = L1 * D * L1' = L * L'} as \code{list(L1, D, L1.)} (the default) or as \code{list(L, L.)}, depending on optional logical argument \code{LDL}. \code{L1}, \code{L1.}, \code{L}, and \code{L.} are \code{\linkS4class{dtrMatrix}} or \code{\linkS4class{dtpMatrix}}, and \code{D} is a \code{\linkS4class{ddiMatrix}}.} \item{\code{expand2}}{\code{signature(x = "p?BunchKaufman")}: expands the factorization \eqn{A = U D_{U} U' = L D_{L} L'}{A = U * DU * U' = L * DL * L'} where \eqn{U = \prod_{k = 1}^{b_{U}} P_{k} U_{k}}{U = prod(Pk * Uk : k = 1,...,bU)} and \eqn{L = \prod_{k = 1}^{b_{L}} P_{k} L_{k}}{L = prod(Pk * Lk : k = 1,...,bL)} as \code{list(U, DU, U.)} or \code{list(L, DL, L.)}, depending on \code{x@uplo}. If optional argument \code{complete} is \code{TRUE}, then an unnamed list giving the full expansion with \eqn{2 b_{U} + 1}{2*bU+1} or \eqn{2 b_{L} + 1}{2*bL+1} matrix factors is returned instead. \eqn{P_{k}}{Pk} are represented as \code{\linkS4class{pMatrix}}, \eqn{U_{k}}{Uk} and \eqn{L_{k}}{Lk} are represented as \code{\linkS4class{dtCMatrix}}, and \eqn{D_{U}}{DU} and \eqn{D_{L}}{DL} are represented as \code{\linkS4class{dsCMatrix}}.} \item{\code{expand2}}{\code{signature(x = "Schur")}: expands the factorization \eqn{A = Q T Q'}{A = Q * T * Q'} as \code{list(Q, T, Q.)}. \code{Q} and \code{Q.} are \code{x@Q} and \code{t(x@Q)} modulo \code{Dimnames}, and \code{T} is \code{x@T}.} \item{\code{expand2}}{\code{signature(x = "sparseLU")}: expands the factorization \eqn{A = P_{1}' L U P_{2}'}{A = P1' * L * U * P2'} as \code{list(P1., L, U, P2.)}. \code{P1.} and \code{P2.} are \code{\linkS4class{pMatrix}}, and \code{L} and \code{U} are \code{\linkS4class{dtCMatrix}}.} \item{\code{expand2}}{\code{signature(x = "denseLU")}: expands the factorization \eqn{A = P_{1}' L U}{A = P1' * L * U} as \code{list(P1., L, U)}. \code{P1.} is a \code{\linkS4class{pMatrix}}, and \code{L} and \code{U} are \code{\linkS4class{dtrMatrix}} if square and \code{\linkS4class{dgeMatrix}} otherwise.} \item{\code{expand2}}{\code{signature(x = "sparseQR")}: expands the factorization \eqn{A = P_{1}' Q R P_{2}' = P_{1}' Q_{1} R_{1} P_{2}'}{A = P1' * Q * R * P2' = P1' * Q1 * R1 * P2'} as \code{list(P1., Q, R, P2.)} or \code{list(P1., Q1, R1, P2.)}, depending on optional logical argument \code{complete}. \code{P1.} and \code{P2.} are \code{\linkS4class{pMatrix}}, \code{Q} and \code{Q1} are \code{\linkS4class{dgeMatrix}}, \code{R} is a \code{\linkS4class{dgCMatrix}}, and \code{R1} is a \code{\linkS4class{dtCMatrix}}.} \item{\code{expand}}{\code{signature(x = "CHMfactor")}: as \code{expand2}, but returning \code{list(P, L)}. \code{expand(x)[["P"]]} and \code{expand2(x)[["P1"]]} represent the same permutation matrix \eqn{P_{1}}{P1} but have opposite \code{margin} slots and inverted \code{perm} slots. The components of \code{expand(x)} do not preserve \code{x@Dimnames}.} \item{\code{expand}}{\code{signature(x = "sparseLU")}: as \code{expand2}, but returning \code{list(P, L, U, Q)}. \code{expand(x)[["Q"]]} and \code{expand2(x)[["P2."]]} represent the same permutation matrix \eqn{P_{2}'}{P2'} but have opposite \code{margin} slots and inverted \code{perm} slots. \code{expand(x)[["P"]]} represents the permutation matrix \eqn{P_{1}}{P1} rather than its transpose \eqn{P_{1}'}{P1'}; it is \code{expand2(x)[["P1."]]} with an inverted \code{perm} slot. \code{expand(x)[["L"]]} and \code{expand2(x)[["L"]]} represent the same unit lower triangular matrix \eqn{L}, but with \code{diag} slot equal to \code{"N"} and \code{"U"}, respectively. \code{expand(x)[["L"]]} and \code{expand(x)[["U"]]} store the \emph{permuted} first and second components of \code{x@Dimnames} in their \code{Dimnames} slots.} \item{\code{expand}}{\code{signature(x = "denseLU")}: as \code{expand2}, but returning \code{list(L, U, P)}. \code{expand(x)[["P"]]} and \code{expand2(x)[["P1."]]} are identical modulo \code{Dimnames}. The components of \code{expand(x)} do not preserve \code{x@Dimnames}.} } } \seealso{ The virtual class \code{\linkS4class{MatrixFactorization}} of matrix factorizations. Generic functions \code{\link{Cholesky}}, \code{\link{BunchKaufman}}, \code{\link{Schur}}, \code{\link{lu}}, and \code{\link{qr}} for \emph{computing} factorizations. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) } showMethods("expand1", inherited = FALSE) showMethods("expand2", inherited = FALSE) set.seed(0) (A <- Matrix(rnorm(9L, 0, 10), 3L, 3L)) (lu.A <- lu(A)) (e.lu.A <- expand2(lu.A)) stopifnot(exprs = { is.list(e.lu.A) identical(names(e.lu.A), c("P1.", "L", "U")) all(sapply(e.lu.A, is, "Matrix")) all.equal(as(A, "matrix"), as(Reduce(`\%*\%`, e.lu.A), "matrix")) }) ## 'expand1' and 'expand2' give equivalent results modulo ## dimnames and representation of permutation matrices; ## see also function 'alt' in example("Cholesky-methods") (a1 <- sapply(names(e.lu.A), expand1, x = lu.A, simplify = FALSE)) all.equal(a1, e.lu.A) ## see help("denseLU-class") and others for more examples } Matrix/man/sparseVector.Rd0000644000175100001440000000312514446607050015265 0ustar hornikusers\name{sparseVector} \title{Sparse Vector Construction from Nonzero Entries} % \keyword{utilities} % \alias{sparseVector} % \description{ User friendly construction of sparse vectors, i.e., objects inheriting from \code{\link{class}} \code{\linkS4class{sparseVector}}, from indices and values of its non-zero entries. } \details{ zero entries in \code{x} are dropped automatically, analogously as \code{\link{drop0}()} acts on sparse matrices. } \usage{ sparseVector(x, i, length) } \arguments{ \item{x}{vector of the non zero entries; may be missing in which case a \code{"nsparseVector"} will be returned.} \item{i}{integer vector (of the same length as \code{x}) specifying the indices of the non-zero (or non-\code{TRUE}) entries of the sparse vector.} \item{length}{length of the sparse vector.} } \value{ a sparse vector, i.e., inheriting from \code{\link{class}} \code{\linkS4class{sparseVector}}. } \author{Martin Maechler} \seealso{ \code{\link{sparseMatrix}()} constructor for sparse matrices; the class \code{\linkS4class{sparseVector}}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } str(sv <- sparseVector(x = 1:10, i = sample(999, 10), length=1000)) sx <- c(0,0,3, 3.2, 0,0,0,-3:1,0,0,2,0,0,5,0,0) ss <- as(sx, "sparseVector") stopifnot(identical(ss, sparseVector(x = c(2, -1, -2, 3, 1, -3, 5, 3.2), i = c(15L, 10:9, 3L,12L,8L,18L, 4L), length = 20L))) (ns <- sparseVector(i= c(7, 3, 2), length = 10)) stopifnot(identical(ns, new("nsparseVector", length = 10, i = c(2, 3, 7)))) } Matrix/man/Matrix-deprecated.Rd0000644000175100001440000005301614576343374016165 0ustar hornikusers\name{Matrix-deprecated} \title{Deprecated Functions in Package \pkg{Matrix}} \alias{Matrix-deprecated} % \alias{..2dge} \alias{.C2nC} \alias{.SuiteSparse_version} \alias{.T2Cmat} \alias{.asmatrix} \alias{.dense2sy} \alias{.diag2mat} \alias{.diag2sT} \alias{.diag2tT} \alias{.dsy2dsp} \alias{.dsy2mat} \alias{.dxC2mat} \alias{.m2dgC} \alias{.m2lgC} \alias{.m2ngCn} \alias{.m2ngC} \alias{.m2ngTn} \alias{.n2dgT} \alias{.nC2d} \alias{.nC2l} % \alias{atomicVector-class} \alias{compMatrix-class} \alias{number-class} \alias{replValue-class} % \alias{chol2inv,CHMfactor-method} \alias{coerce,CHMfactor,Matrix-method} \alias{coerce,CHMfactor,CsparseMatrix-method} \alias{coerce,CHMfactor,RsparseMatrix-method} \alias{coerce,CHMfactor,TsparseMatrix-method} \alias{coerce,CHMfactor,dMatrix-method} \alias{coerce,CHMfactor,dsparseMatrix-method} \alias{coerce,CHMfactor,pMatrix-method} \alias{coerce,CHMfactor,sparseMatrix-method} \alias{coerce,CHMfactor,triangularMatrix-method} \alias{coerce,RsparseMatrix,dgeMatrix-method} \alias{coerce,ddenseMatrix,dgeMatrix-method} \alias{coerce,ddiMatrix,dgCMatrix-method} \alias{coerce,ddiMatrix,dgeMatrix-method} \alias{coerce,ddiMatrix,dtCMatrix-method} \alias{coerce,dgCMatrix,dgTMatrix-method} \alias{coerce,dgCMatrix,dgeMatrix-method} \alias{coerce,dgCMatrix,dsCMatrix-method} \alias{coerce,dgCMatrix,dtCMatrix-method} \alias{coerce,dgCMatrix,lgCMatrix-method} \alias{coerce,dgCMatrix,ngCMatrix-method} \alias{coerce,dgTMatrix,dgCMatrix-method} \alias{coerce,dgTMatrix,dgeMatrix-method} \alias{coerce,dgTMatrix,dsTMatrix-method} \alias{coerce,dgTMatrix,dtCMatrix-method} \alias{coerce,dgTMatrix,dtTMatrix-method} \alias{coerce,dgeMatrix,dgCMatrix-method} \alias{coerce,dgeMatrix,dgTMatrix-method} \alias{coerce,dgeMatrix,dsTMatrix-method} \alias{coerce,dgeMatrix,dspMatrix-method} \alias{coerce,dgeMatrix,dsyMatrix-method} \alias{coerce,dgeMatrix,dtrMatrix-method} \alias{coerce,dgeMatrix,lgeMatrix-method} \alias{coerce,dsCMatrix,dgCMatrix-method} \alias{coerce,dsCMatrix,dgTMatrix-method} \alias{coerce,dsCMatrix,dgeMatrix-method} \alias{coerce,dsCMatrix,dsRMatrix-method} \alias{coerce,dsCMatrix,dsTMatrix-method} \alias{coerce,dsCMatrix,dsyMatrix-method} \alias{coerce,dsCMatrix,lsCMatrix-method} \alias{coerce,dsCMatrix,nsCMatrix-method} \alias{coerce,dsTMatrix,dgTMatrix-method} \alias{coerce,dsTMatrix,dgeMatrix-method} \alias{coerce,dsTMatrix,dsCMatrix-method} \alias{coerce,dsTMatrix,dsyMatrix-method} \alias{coerce,dsTMatrix,lsTMatrix-method} \alias{coerce,dspMatrix,dsyMatrix-method} \alias{coerce,dspMatrix,lspMatrix-method} \alias{coerce,dsyMatrix,dsCMatrix-method} \alias{coerce,dsyMatrix,dsTMatrix-method} \alias{coerce,dsyMatrix,dspMatrix-method} \alias{coerce,dsyMatrix,lsyMatrix-method} \alias{coerce,dtCMatrix,dgCMatrix-method} \alias{coerce,dtCMatrix,dgTMatrix-method} \alias{coerce,dtCMatrix,dgeMatrix-method} \alias{coerce,dtCMatrix,dsCMatrix-method} \alias{coerce,dtCMatrix,dtTMatrix-method} \alias{coerce,dtCMatrix,dtrMatrix-method} \alias{coerce,dtCMatrix,ltCMatrix-method} \alias{coerce,dtCMatrix,ntCMatrix-method} \alias{coerce,dtTMatrix,dgTMatrix-method} \alias{coerce,dtTMatrix,dgeMatrix-method} \alias{coerce,dtTMatrix,dtCMatrix-method} \alias{coerce,dtTMatrix,dtrMatrix-method} \alias{coerce,dtpMatrix,dtTMatrix-method} \alias{coerce,dtpMatrix,dtrMatrix-method} \alias{coerce,dtpMatrix,ltpMatrix-method} \alias{coerce,dtrMatrix,dtpMatrix-method} \alias{coerce,dtrMatrix,ltrMatrix-method} \alias{coerce,indMatrix,ngTMatrix-method} \alias{coerce,indMatrix,ngeMatrix-method} \alias{coerce,lMatrix,dgCMatrix-method} \alias{coerce,lgCMatrix,dgCMatrix-method} \alias{coerce,lgCMatrix,lgTMatrix-method} \alias{coerce,lgCMatrix,lgeMatrix-method} \alias{coerce,lgCMatrix,ltCMatrix-method} \alias{coerce,lgTMatrix,dgTMatrix-method} \alias{coerce,lgTMatrix,lgCMatrix-method} \alias{coerce,lgTMatrix,lgeMatrix-method} \alias{coerce,lgTMatrix,lsCMatrix-method} \alias{coerce,lgTMatrix,ltTMatrix-method} \alias{coerce,lgeMatrix,dgeMatrix-method} \alias{coerce,lgeMatrix,lgCMatrix-method} \alias{coerce,lgeMatrix,lgTMatrix-method} \alias{coerce,lgeMatrix,lspMatrix-method} \alias{coerce,lgeMatrix,lsyMatrix-method} \alias{coerce,lgeMatrix,ltpMatrix-method} \alias{coerce,lgeMatrix,ltrMatrix-method} \alias{coerce,lsCMatrix,dsCMatrix-method} \alias{coerce,lsCMatrix,lgCMatrix-method} \alias{coerce,lsCMatrix,lgTMatrix-method} \alias{coerce,lsCMatrix,lsTMatrix-method} \alias{coerce,lsTMatrix,lgCMatrix-method} \alias{coerce,lsTMatrix,lgTMatrix-method} \alias{coerce,lsTMatrix,lsCMatrix-method} \alias{coerce,lsTMatrix,lsyMatrix-method} \alias{coerce,lspMatrix,dspMatrix-method} \alias{coerce,lspMatrix,lgeMatrix-method} \alias{coerce,lspMatrix,lsyMatrix-method} \alias{coerce,lsyMatrix,dsyMatrix-method} \alias{coerce,lsyMatrix,lgeMatrix-method} \alias{coerce,lsyMatrix,lspMatrix-method} \alias{coerce,ltCMatrix,lgCMatrix-method} \alias{coerce,ltCMatrix,ltTMatrix-method} \alias{coerce,ltTMatrix,dtTMatrix-method} \alias{coerce,ltTMatrix,lgCMatrix-method} \alias{coerce,ltTMatrix,lgTMatrix-method} \alias{coerce,ltTMatrix,ltCMatrix-method} \alias{coerce,ltTMatrix,ltrMatrix-method} \alias{coerce,ltpMatrix,dtpMatrix-method} \alias{coerce,ltpMatrix,lgeMatrix-method} \alias{coerce,ltpMatrix,ltrMatrix-method} \alias{coerce,ltrMatrix,dtrMatrix-method} \alias{coerce,ltrMatrix,lgeMatrix-method} \alias{coerce,ltrMatrix,ltpMatrix-method} \alias{coerce,matrix,dgRMatrix-method} \alias{coerce,matrix,dgTMatrix-method} \alias{coerce,matrix,dgeMatrix-method} \alias{coerce,matrix,dsCMatrix-method} \alias{coerce,matrix,dsTMatrix-method} \alias{coerce,matrix,dspMatrix-method} \alias{coerce,matrix,dsyMatrix-method} \alias{coerce,matrix,dtCMatrix-method} \alias{coerce,matrix,dtTMatrix-method} \alias{coerce,matrix,dtpMatrix-method} \alias{coerce,matrix,dtrMatrix-method} \alias{coerce,matrix,lgCMatrix-method} \alias{coerce,matrix,lgTMatrix-method} \alias{coerce,matrix,lgeMatrix-method} \alias{coerce,matrix,lsCMatrix-method} \alias{coerce,matrix,lspMatrix-method} \alias{coerce,matrix,lsyMatrix-method} \alias{coerce,matrix,ltCMatrix-method} \alias{coerce,matrix,ltTMatrix-method} \alias{coerce,matrix,ltpMatrix-method} \alias{coerce,matrix,ltrMatrix-method} \alias{coerce,matrix,ngCMatrix-method} \alias{coerce,matrix,ngTMatrix-method} \alias{coerce,matrix,ngeMatrix-method} \alias{coerce,matrix,nspMatrix-method} \alias{coerce,matrix,nsyMatrix-method} \alias{coerce,matrix,ntCMatrix-method} \alias{coerce,matrix,ntTMatrix-method} \alias{coerce,matrix,ntpMatrix-method} \alias{coerce,matrix,ntrMatrix-method} \alias{coerce,ngCMatrix,dgCMatrix-method} \alias{coerce,ngCMatrix,lgCMatrix-method} \alias{coerce,ngCMatrix,ntCMatrix-method} \alias{coerce,ngTMatrix,dgTMatrix-method} \alias{coerce,ngTMatrix,lgTMatrix-method} \alias{coerce,ngTMatrix,lgeMatrix-method} \alias{coerce,ngTMatrix,ngCMatrix-method} \alias{coerce,ngTMatrix,ngeMatrix-method} \alias{coerce,ngTMatrix,ntTMatrix-method} \alias{coerce,ngeMatrix,dgeMatrix-method} \alias{coerce,ngeMatrix,lgeMatrix-method} \alias{coerce,ngeMatrix,ngCMatrix-method} \alias{coerce,ngeMatrix,ngTMatrix-method} \alias{coerce,ngeMatrix,nspMatrix-method} \alias{coerce,ngeMatrix,nsyMatrix-method} \alias{coerce,ngeMatrix,ntpMatrix-method} \alias{coerce,ngeMatrix,ntrMatrix-method} \alias{coerce,nsCMatrix,dsCMatrix-method} \alias{coerce,nsCMatrix,lsCMatrix-method} \alias{coerce,nsCMatrix,ngCMatrix-method} \alias{coerce,nsCMatrix,nsTMatrix-method} \alias{coerce,nsTMatrix,dsTMatrix-method} \alias{coerce,nsTMatrix,ngCMatrix-method} \alias{coerce,nsTMatrix,ngTMatrix-method} \alias{coerce,nsTMatrix,nsCMatrix-method} \alias{coerce,nsTMatrix,nsyMatrix-method} \alias{coerce,nspMatrix,dspMatrix-method} \alias{coerce,nspMatrix,lspMatrix-method} \alias{coerce,nspMatrix,ngeMatrix-method} \alias{coerce,nspMatrix,nsyMatrix-method} \alias{coerce,nsyMatrix,dsyMatrix-method} \alias{coerce,nsyMatrix,lsyMatrix-method} \alias{coerce,nsyMatrix,ngeMatrix-method} \alias{coerce,nsyMatrix,nspMatrix-method} \alias{coerce,ntCMatrix,dtCMatrix-method} \alias{coerce,ntCMatrix,ltCMatrix-method} \alias{coerce,ntCMatrix,ngCMatrix-method} \alias{coerce,ntTMatrix,dtTMatrix-method} \alias{coerce,ntTMatrix,ngCMatrix-method} \alias{coerce,ntTMatrix,ngTMatrix-method} \alias{coerce,ntTMatrix,ntCMatrix-method} \alias{coerce,ntTMatrix,ntrMatrix-method} \alias{coerce,ntpMatrix,dtpMatrix-method} \alias{coerce,ntpMatrix,ltpMatrix-method} \alias{coerce,ntpMatrix,ngeMatrix-method} \alias{coerce,ntpMatrix,ntrMatrix-method} \alias{coerce,ntrMatrix,dtrMatrix-method} \alias{coerce,ntrMatrix,ltrMatrix-method} \alias{coerce,ntrMatrix,ngeMatrix-method} \alias{coerce,ntrMatrix,ntpMatrix-method} \alias{coerce,numLike,dgeMatrix-method} % \description{ These functions are provided for compatibility with older versions of \pkg{Matrix} only and may be defunct as soon as the next release. } \usage{ %% ## Deprecated in 1.6-0 ... on second thought, perhaps not yet %% \S4method{chol2inv}{CHMfactor}(x, ...) %% \S4method{coerce}{CHMfactor,Matrix}(from, to, strict = TRUE) %% \S4method{coerce}{CHMfactor,CsparseMatrix}(from, to, strict = TRUE) %% \S4method{coerce}{CHMfactor,RsparseMatrix}(from, to, strict = TRUE) %% \S4method{coerce}{CHMfactor,TsparseMatrix}(from, to, strict = TRUE) %% \S4method{coerce}{CHMfactor,dMatrix}(from, to, strict = TRUE) %% \S4method{coerce}{CHMfactor,dsparseMatrix}(from, to, strict = TRUE) %% \S4method{coerce}{CHMfactor,pMatrix}(from, to, strict = TRUE) %% \S4method{coerce}{CHMfactor,sparseMatrix}(from, to, strict = TRUE) %% \S4method{coerce}{CHMfactor,triangularMatrix}(from, to, strict = TRUE) %% ## Deprecated in 1.5-4 ..2dge(from) .C2nC(from, isTri) .T2Cmat(from, isTri) .asmatrix(x) .dense2sy(from, ...) .diag2mat(from) .diag2sT(from, uplo = "U", kind = ".", drop0 = TRUE) .diag2tT(from, uplo = "U", kind = ".", drop0 = TRUE) .dsy2dsp(from) .dsy2mat(from, keep.dimnames = TRUE) .dxC2mat(from, chkUdiag) .m2dgC(from) .m2lgC(from) .m2ngC(from) .m2ngCn(from, na.is.not.0 = FALSE) .m2ngTn(from, na.is.not.0 = FALSE) .n2dgT(from) .nC2d(from) .nC2l(from) ## Deprecated in 1.5-0 \S4method{coerce}{RsparseMatrix,dgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{ddenseMatrix,dgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{ddiMatrix,dgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{ddiMatrix,dgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{ddiMatrix,dtCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgCMatrix,dgTMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgCMatrix,dgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgCMatrix,dsCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgCMatrix,dtCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgCMatrix,lgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgCMatrix,ngCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgTMatrix,dgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgTMatrix,dgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgTMatrix,dsTMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgTMatrix,dtCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgTMatrix,dtTMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgeMatrix,dgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgeMatrix,dgTMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgeMatrix,dsTMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgeMatrix,dspMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgeMatrix,dsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgeMatrix,dtrMatrix}(from, to, strict = TRUE) \S4method{coerce}{dgeMatrix,lgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsCMatrix,dgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsCMatrix,dgTMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsCMatrix,dgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsCMatrix,dsRMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsCMatrix,dsTMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsCMatrix,dsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsCMatrix,lsCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsCMatrix,nsCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsTMatrix,dgTMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsTMatrix,dgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsTMatrix,dsCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsTMatrix,dsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsTMatrix,lsTMatrix}(from, to, strict = TRUE) \S4method{coerce}{dspMatrix,dsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{dspMatrix,lspMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsyMatrix,dsCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsyMatrix,dsTMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsyMatrix,dspMatrix}(from, to, strict = TRUE) \S4method{coerce}{dsyMatrix,lsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtCMatrix,dgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtCMatrix,dgTMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtCMatrix,dgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtCMatrix,dsCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtCMatrix,dtTMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtCMatrix,dtrMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtCMatrix,ltCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtCMatrix,ntCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtTMatrix,dgTMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtTMatrix,dgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtTMatrix,dtCMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtTMatrix,dtrMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtpMatrix,dtTMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtpMatrix,dtrMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtpMatrix,ltpMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtrMatrix,dtpMatrix}(from, to, strict = TRUE) \S4method{coerce}{dtrMatrix,ltrMatrix}(from, to, strict = TRUE) \S4method{coerce}{indMatrix,ngTMatrix}(from, to, strict = TRUE) \S4method{coerce}{indMatrix,ngeMatrix}(from, to, strict = TRUE) \S4method{coerce}{lMatrix,dgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{lgCMatrix,dgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{lgCMatrix,lgTMatrix}(from, to, strict = TRUE) \S4method{coerce}{lgCMatrix,lgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{lgCMatrix,ltCMatrix}(from, to, strict = TRUE) \S4method{coerce}{lgTMatrix,dgTMatrix}(from, to, strict = TRUE) \S4method{coerce}{lgTMatrix,lgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{lgTMatrix,lgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{lgTMatrix,lsCMatrix}(from, to, strict = TRUE) \S4method{coerce}{lgTMatrix,ltTMatrix}(from, to, strict = TRUE) \S4method{coerce}{lgeMatrix,dgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{lgeMatrix,lgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{lgeMatrix,lgTMatrix}(from, to, strict = TRUE) \S4method{coerce}{lgeMatrix,lspMatrix}(from, to, strict = TRUE) \S4method{coerce}{lgeMatrix,lsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{lgeMatrix,ltpMatrix}(from, to, strict = TRUE) \S4method{coerce}{lgeMatrix,ltrMatrix}(from, to, strict = TRUE) \S4method{coerce}{lsCMatrix,dsCMatrix}(from, to, strict = TRUE) \S4method{coerce}{lsCMatrix,lgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{lsCMatrix,lgTMatrix}(from, to, strict = TRUE) \S4method{coerce}{lsCMatrix,lsTMatrix}(from, to, strict = TRUE) \S4method{coerce}{lsTMatrix,lgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{lsTMatrix,lgTMatrix}(from, to, strict = TRUE) \S4method{coerce}{lsTMatrix,lsCMatrix}(from, to, strict = TRUE) \S4method{coerce}{lsTMatrix,lsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{lspMatrix,dspMatrix}(from, to, strict = TRUE) \S4method{coerce}{lspMatrix,lgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{lspMatrix,lsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{lsyMatrix,dsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{lsyMatrix,lgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{lsyMatrix,lspMatrix}(from, to, strict = TRUE) \S4method{coerce}{ltCMatrix,lgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{ltCMatrix,ltTMatrix}(from, to, strict = TRUE) \S4method{coerce}{ltTMatrix,dtTMatrix}(from, to, strict = TRUE) \S4method{coerce}{ltTMatrix,lgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{ltTMatrix,lgTMatrix}(from, to, strict = TRUE) \S4method{coerce}{ltTMatrix,ltCMatrix}(from, to, strict = TRUE) \S4method{coerce}{ltTMatrix,ltrMatrix}(from, to, strict = TRUE) \S4method{coerce}{ltpMatrix,dtpMatrix}(from, to, strict = TRUE) \S4method{coerce}{ltpMatrix,lgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{ltpMatrix,ltrMatrix}(from, to, strict = TRUE) \S4method{coerce}{ltrMatrix,dtrMatrix}(from, to, strict = TRUE) \S4method{coerce}{ltrMatrix,lgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{ltrMatrix,ltpMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,dgRMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,dgTMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,dgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,dsCMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,dsTMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,dspMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,dsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,dtCMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,dtTMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,dtpMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,dtrMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,lgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,lgTMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,lgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,lsCMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,lspMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,lsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,ltCMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,ltTMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,ltpMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,ltrMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,ngCMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,ngTMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,ngeMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,nspMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,nsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,ntCMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,ntTMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,ntpMatrix}(from, to, strict = TRUE) \S4method{coerce}{matrix,ntrMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngCMatrix,dgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngCMatrix,lgCMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngCMatrix,ntCMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngTMatrix,dgTMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngTMatrix,lgTMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngTMatrix,lgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngTMatrix,ngCMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngTMatrix,ngeMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngTMatrix,ntTMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngeMatrix,dgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngeMatrix,lgeMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngeMatrix,ngCMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngeMatrix,ngTMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngeMatrix,nspMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngeMatrix,nsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngeMatrix,ntpMatrix}(from, to, strict = TRUE) \S4method{coerce}{ngeMatrix,ntrMatrix}(from, to, strict = TRUE) \S4method{coerce}{nsCMatrix,dsCMatrix}(from, to, strict = TRUE) \S4method{coerce}{nsCMatrix,lsCMatrix}(from, to, strict = TRUE) \S4method{coerce}{nsCMatrix,ngCMatrix}(from, to, strict = TRUE) \S4method{coerce}{nsCMatrix,nsTMatrix}(from, to, strict = TRUE) \S4method{coerce}{nsTMatrix,dsTMatrix}(from, to, strict = TRUE) \S4method{coerce}{nsTMatrix,ngCMatrix}(from, to, strict = TRUE) \S4method{coerce}{nsTMatrix,ngTMatrix}(from, to, strict = TRUE) \S4method{coerce}{nsTMatrix,nsCMatrix}(from, to, strict = TRUE) \S4method{coerce}{nsTMatrix,nsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{nspMatrix,dspMatrix}(from, to, strict = TRUE) \S4method{coerce}{nspMatrix,lspMatrix}(from, to, strict = TRUE) \S4method{coerce}{nspMatrix,ngeMatrix}(from, to, strict = TRUE) \S4method{coerce}{nspMatrix,nsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{nsyMatrix,dsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{nsyMatrix,lsyMatrix}(from, to, strict = TRUE) \S4method{coerce}{nsyMatrix,ngeMatrix}(from, to, strict = TRUE) \S4method{coerce}{nsyMatrix,nspMatrix}(from, to, strict = TRUE) \S4method{coerce}{ntCMatrix,dtCMatrix}(from, to, strict = TRUE) \S4method{coerce}{ntCMatrix,ltCMatrix}(from, to, strict = TRUE) \S4method{coerce}{ntCMatrix,ngCMatrix}(from, to, strict = TRUE) \S4method{coerce}{ntTMatrix,dtTMatrix}(from, to, strict = TRUE) \S4method{coerce}{ntTMatrix,ngCMatrix}(from, to, strict = TRUE) \S4method{coerce}{ntTMatrix,ngTMatrix}(from, to, strict = TRUE) \S4method{coerce}{ntTMatrix,ntCMatrix}(from, to, strict = TRUE) \S4method{coerce}{ntTMatrix,ntrMatrix}(from, to, strict = TRUE) \S4method{coerce}{ntpMatrix,dtpMatrix}(from, to, strict = TRUE) \S4method{coerce}{ntpMatrix,ltpMatrix}(from, to, strict = TRUE) \S4method{coerce}{ntpMatrix,ngeMatrix}(from, to, strict = TRUE) \S4method{coerce}{ntpMatrix,ntrMatrix}(from, to, strict = TRUE) \S4method{coerce}{ntrMatrix,dtrMatrix}(from, to, strict = TRUE) \S4method{coerce}{ntrMatrix,ltrMatrix}(from, to, strict = TRUE) \S4method{coerce}{ntrMatrix,ngeMatrix}(from, to, strict = TRUE) \S4method{coerce}{ntrMatrix,ntpMatrix}(from, to, strict = TRUE) \S4method{coerce}{numLike,dgeMatrix}(from, to, strict = TRUE) } \seealso{ \code{\link{Deprecated}}, \code{\link{base-deprecated}}, \code{\link{Matrix-defunct}} } \keyword{internal} \keyword{misc} Matrix/man/kronecker-methods.Rd0000644000175100001440000000562514422605232016232 0ustar hornikusers\name{kronecker-methods} \title{Methods for Function 'kronecker()' in Package 'Matrix'} % \docType{methods} \keyword{algebra} \keyword{arith} \keyword{array} \keyword{methods} % \alias{kronecker} \alias{kronecker-methods} % \alias{kronecker,CsparseMatrix,CsparseMatrix-method} \alias{kronecker,CsparseMatrix,Matrix-method} \alias{kronecker,CsparseMatrix,diagonalMatrix-method} \alias{kronecker,Matrix,matrix-method} \alias{kronecker,Matrix,vector-method} \alias{kronecker,RsparseMatrix,Matrix-method} \alias{kronecker,RsparseMatrix,RsparseMatrix-method} \alias{kronecker,RsparseMatrix,diagonalMatrix-method} \alias{kronecker,TsparseMatrix,Matrix-method} \alias{kronecker,TsparseMatrix,TsparseMatrix-method} \alias{kronecker,TsparseMatrix,diagonalMatrix-method} \alias{kronecker,denseMatrix,Matrix-method} \alias{kronecker,denseMatrix,denseMatrix-method} \alias{kronecker,diagonalMatrix,CsparseMatrix-method} \alias{kronecker,diagonalMatrix,Matrix-method} \alias{kronecker,diagonalMatrix,RsparseMatrix-method} \alias{kronecker,diagonalMatrix,TsparseMatrix-method} \alias{kronecker,diagonalMatrix,diagonalMatrix-method} \alias{kronecker,diagonalMatrix,indMatrix-method} \alias{kronecker,indMatrix,Matrix-method} \alias{kronecker,indMatrix,diagonalMatrix-method} \alias{kronecker,indMatrix,indMatrix-method} \alias{kronecker,matrix,Matrix-method} \alias{kronecker,vector,Matrix-method} % \description{ Computes Kronecker products for objects inheriting from \code{"\linkS4class{Matrix}"}. In order to preserver sparseness, we treat \code{0 * NA} as \code{0}, not as \code{\link{NA}} as usually in \R (and as used for the \pkg{base} function \code{\link[base]{kronecker}}). } \section{Methods}{ \describe{ \item{kronecker}{\code{signature(X = "Matrix", Y = "ANY")} .......} \item{kronecker}{\code{signature(X = "ANY", Y = "Matrix")} .......} \item{kronecker}{\code{signature(X = "diagonalMatrix", Y = "ANY")} .......} \item{kronecker}{\code{signature(X = "sparseMatrix", Y = "ANY")} .......} \item{kronecker}{\code{signature(X = "TsparseMatrix", Y = "TsparseMatrix")} .......} \item{kronecker}{\code{signature(X = "dgTMatrix", Y = "dgTMatrix")} .......} \item{kronecker}{\code{signature(X = "dtTMatrix", Y = "dtTMatrix")} .......} \item{kronecker}{\code{signature(X = "indMatrix", Y = "indMatrix")} .......} } } \examples{ (t1 <- spMatrix(5,4, x= c(3,2,-7,11), i= 1:4, j=4:1)) # 5 x 4 (t2 <- kronecker(Diagonal(3, 2:4), t1)) # 15 x 12 ## should also work with special-cased logical matrices l3 <- upper.tri(matrix(,3,3)) M <- Matrix(l3) (N <- as(M, "nsparseMatrix")) # "ntCMatrix" (upper triangular) N2 <- as(N, "generalMatrix") # (lost "t"riangularity) MM <- kronecker(M,M) NN <- kronecker(N,N) # "dtTMatrix" i.e. did keep NN2 <- kronecker(N2,N2) stopifnot(identical(NN,MM), is(NN2, "sparseMatrix"), all(NN2 == NN), is(NN, "triangularMatrix")) } \keyword{methods} \keyword{array} Matrix/man/bdiag.Rd0000644000175100001440000000767614446607050013672 0ustar hornikusers\name{bdiag} \title{Construct a Block Diagonal Matrix} % \keyword{array} \keyword{utilities} % \alias{bdiag} \alias{.bdiag} \description{ Build a block diagonal matrix given several building block matrices. } \usage{ bdiag(\dots) .bdiag(lst) } \arguments{ \item{\dots}{individual matrices or a \code{\link{list}} of matrices.} \item{lst}{non-empty \code{\link{list}} of matrices.} } \details{ For non-trivial argument list, \code{bdiag()} calls \code{.bdiag()}. The latter maybe useful to programmers. } \note{This function has been written and is efficient for the case of relatively few block matrices which are typically sparse themselves. It is currently \emph{inefficient} for the case of many small dense block matrices. For the case of \emph{many} dense \eqn{k \times k}{k * k} matrices, the \code{bdiag_m()} function in the \sQuote{Examples} is an order of magnitude faster. } \value{ A \emph{sparse} matrix obtained by combining the arguments into a block diagonal matrix. The value of \code{bdiag()} inherits from class \code{\linkS4class{CsparseMatrix}}, whereas \code{.bdiag()} returns a \code{\linkS4class{TsparseMatrix}}. } \author{Martin Maechler, built on a version posted by Berton Gunter to R-help; earlier versions have been posted by other authors, notably Scott Chasalow to S-news. Doug Bates's faster implementation builds on \code{\linkS4class{TsparseMatrix}} objects. } \seealso{\code{\link{Diagonal}} for constructing matrices of class \code{\linkS4class{diagonalMatrix}}, or \code{\link{kronecker}} which also works for \code{"Matrix"} inheriting matrices. \code{\link{bandSparse}} constructs a \emph{banded} sparse matrix from its non-zero sub-/super - diagonals. Note that other CRAN \R packages have own versions of \code{bdiag()} which return traditional matrices. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) } bdiag(matrix(1:4, 2), diag(3)) ## combine "Matrix" class and traditional matrices: bdiag(Diagonal(2), matrix(1:3, 3,4), diag(3:2)) mlist <- list(1, 2:3, diag(x=5:3), 27, cbind(1,3:6), 100:101) bdiag(mlist) stopifnot(identical(bdiag(mlist), % <- used to fail in earlier versions bdiag(lapply(mlist, as.matrix)))) ml <- c(as(matrix((1:24)\%\% 11 == 0, 6,4),"nMatrix"), rep(list(Diagonal(2, x=TRUE)), 3)) mln <- c(ml, Diagonal(x = 1:3)) stopifnot(is(bdiag(ml), "lsparseMatrix"),% failed in Matrix <= 1.0-2 is(bdiag(mln),"dsparseMatrix") ) ## random (diagonal-)block-triangular matrices: rblockTri <- function(nb, max.ni, lambda = 3) { .bdiag(replicate(nb, { n <- sample.int(max.ni, 1) tril(Matrix(rpois(n * n, lambda = lambda), n, n)) })) } (T4 <- rblockTri(4, 10, lambda = 1)) image(T1 <- rblockTri(12, 20)) ##' Fast version of Matrix :: .bdiag() -- for the case of *many* (k x k) matrices: ##' @param lmat list(, , ....., ) where each mat_j is a k x k 'matrix' ##' @return a sparse (N*k x N*k) matrix of class \code{"\linkS4class{dgCMatrix}"}. bdiag_m <- function(lmat) { ## Copyright (C) 2016 Martin Maechler, ETH Zurich if(!length(lmat)) return(new("dgCMatrix")) stopifnot(is.list(lmat), is.matrix(lmat[[1]]), (k <- (d <- dim(lmat[[1]]))[1]) == d[2], # k x k all(vapply(lmat, dim, integer(2)) == k)) # all of them N <- length(lmat) if(N * k > .Machine$integer.max) stop("resulting matrix too large; would be M x M, with M=", N*k) M <- as.integer(N * k) ## result: an M x M matrix new("dgCMatrix", Dim = c(M,M), ## 'i :' maybe there's a faster way (w/o matrix indexing), but elegant? i = as.vector(matrix(0L:(M-1L), nrow=k)[, rep(seq_len(N), each=k)]), p = k * 0L:M, x = as.double(unlist(lmat, recursive=FALSE, use.names=FALSE))) } l12 <- replicate(12, matrix(rpois(16, lambda = 6.4), 4, 4), simplify=FALSE) dim(T12 <- bdiag_m(l12))# 48 x 48 T12[1:20, 1:20] } Matrix/man/KNex.Rd0000644000175100001440000000226514446607050013456 0ustar hornikusers\name{KNex} \title{Koenker-Ng Example Sparse Model Matrix and Response Vector} % \docType{data} \keyword{datasets} % \alias{KNex} % \description{ A model matrix \code{mm} and corresponding response vector \code{y} used in an example by Koenker and Ng. The matrix \code{mm} is a sparse matrix with 1850 rows and 712 columns but only 8758 non-zero entries. It is a \code{"dgCMatrix"} object. The vector \code{y} is just \code{\link{numeric}} of length 1850. } \usage{data(KNex)} %\details{} %\source{} \references{ Roger Koenker and Pin Ng (2003). SparseM: A sparse matrix package for R; \emph{J. of Statistical Software}, \bold{8} (6), \doi{10.18637/jss.v008.i06} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } data(KNex, package = "Matrix") class(KNex$mm) dim(KNex$mm) image(KNex$mm) str(KNex) system.time( # a fraction of a second sparse.sol <- with(KNex, solve(crossprod(mm), crossprod(mm, y)))) head(round(sparse.sol,3)) ## Compare with QR-based solution ("more accurate, but slightly slower"): system.time( sp.sol2 <- with(KNex, qr.coef(qr(mm), y) )) all.equal(sparse.sol, sp.sol2, tolerance = 1e-13) # TRUE } Matrix/man/ntrMatrix-class.Rd0000644000175100001440000000433114467516513015706 0ustar hornikusers\name{ntrMatrix-class} \title{Triangular Dense Logical Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{ntrMatrix-class} \alias{ntpMatrix-class} % \description{ The \code{"ntrMatrix"} class is the class of triangular, dense, logical matrices in nonpacked storage. The \code{"ntpMatrix"} class is the same except in packed storage. } \section{Slots}{ \describe{ \item{\code{x}:}{Object of class \code{"logical"}. The logical values that constitute the matrix, stored in column-major order.} \item{\code{uplo}:}{Object of class \code{"character"}. Must be either "U", for upper triangular, and "L", for lower triangular.} \item{\code{diag}:}{Object of class \code{"character"}. Must be either \code{"U"}, for unit triangular (diagonal is all ones), or \code{"N"}; see \code{\linkS4class{triangularMatrix}}.} \item{\code{Dim},\code{Dimnames}:}{The dimension (a length-2 \code{"integer"}) and corresponding names (or \code{NULL}), see the \code{\linkS4class{Matrix}} class.} \item{\code{factors}:}{Object of class \code{"list"}. A named list of factorizations that have been computed for the matrix.} } } \section{Extends}{ \code{"ntrMatrix"} extends class \code{"ngeMatrix"}, directly, whereas\cr \code{"ntpMatrix"} extends class \code{"ndenseMatrix"}, directly. Both extend Class \code{"triangularMatrix"}, directly, and class \code{"denseMatrix"}, \code{"lMatrix"} and others, \emph{in}directly, use \code{\link{showClass}("nsyMatrix")}, e.g., for details. } \section{Methods}{ Currently, mainly \code{\link{t}()} and coercion methods (for \code{\link{as}(.)}; use, e.g., \code{\link{showMethods}(class="ntrMatrix")} for details. } \seealso{ Classes \code{\linkS4class{ngeMatrix}}, \code{\linkS4class{Matrix}}; function \code{\link[base]{t}} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } showClass("ntrMatrix") str(new("ntpMatrix")) (nutr <- as(upper.tri(matrix(, 4, 4)), "ndenseMatrix")) str(nutp <- pack(nutr)) # packed matrix: only 10 = 4*(4+1)/2 entries !nutp # the logical negation (is *not* logical triangular !) ## but this one is: stopifnot(all.equal(nutp, pack(!!nutp))) } Matrix/man/dsyMatrix-class.Rd0000644000175100001440000001014314565737512015703 0ustar hornikusers\name{dsyMatrix-class} \title{Symmetric Dense (Packed or Unpacked) Numeric Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{dsyMatrix-class} \alias{dspMatrix-class} % \alias{coerce,dsyMatrix,corMatrix-method} \alias{coerce,dsyMatrix,dpoMatrix-method} \alias{determinant,dsyMatrix,logical-method} % \alias{coerce,dspMatrix,copMatrix-method} \alias{coerce,dspMatrix,dppMatrix-method} \alias{determinant,dspMatrix,logical-method} % \description{ \itemize{ \item The \code{"dsyMatrix"} class is the class of symmetric, dense matrices in \emph{non-packed} storage and \item \code{"dspMatrix"} is the class of symmetric dense matrices in \emph{packed} storage, see \code{\link{pack}()}. Only the upper triangle or the lower triangle is stored. } } \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("dsyMatrix", ...)} or \code{new("dspMatrix", ...)}, respectively. } \section{Slots}{ \describe{ \item{\code{uplo}:}{Object of class \code{"character"}. Must be either "U", for upper triangular, and "L", for lower triangular.} \item{\code{x}:}{Object of class \code{"numeric"}. The numeric values that constitute the matrix, stored in column-major order.} \item{\code{Dim},\code{Dimnames}:}{The dimension (a length-2 \code{"integer"}) and corresponding names (or \code{NULL}), see the \code{\linkS4class{Matrix}}.} \item{\code{factors}:}{Object of class \code{"list"}. A named list of factorizations that have been computed for the matrix.} } } \section{Extends}{ \code{"dsyMatrix"} extends class \code{"dgeMatrix"}, directly, whereas\cr \code{"dspMatrix"} extends class \code{"ddenseMatrix"}, directly. Both extend class \code{"symmetricMatrix"}, directly, and class \code{"Matrix"} and others, \emph{in}directly, use \code{\link{showClass}("dsyMatrix")}, e.g., for details. } \section{Methods}{ \describe{ \item{norm}{\code{signature(x = "dspMatrix", type = "character")}, or \code{x = "dsyMatrix"} or \code{type = "missing"}: Computes the matrix norm of the desired type, see, \code{\link{norm}}.} \item{rcond}{\code{signature(x = "dspMatrix", type = "character")}, or \code{x = "dsyMatrix"} or \code{type = "missing"}: Computes the reciprocal condition number, \code{\link{rcond}()}.} \item{solve}{\code{signature(a = "dspMatrix", b = "....")}, and} \item{solve}{\code{signature(a = "dsyMatrix", b = "....")}: \code{x <- solve(a,b)} solves \eqn{A x = b} for \eqn{x}; see \code{\link{solve-methods}}.} \item{t}{\code{signature(x = "dsyMatrix")}: Transpose; swaps from upper triangular to lower triangular storage, i.e., the uplo slot from \code{"U"} to \code{"L"} or vice versa, the same as for all symmetric matrices.} } } %\references{} \seealso{ The \emph{positive (Semi-)definite} dense (packed or non-packed numeric matrix classes \code{\linkS4class{dpoMatrix}}, \code{\linkS4class{dppMatrix}} and \code{\linkS4class{corMatrix}}, Classes \code{\linkS4class{dgeMatrix}} and \code{\linkS4class{Matrix}}; \code{\link[base]{solve}}, \code{\link{norm}}, \code{\link{rcond}}, \code{\link[base]{t}} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } ## Only upper triangular part matters (when uplo == "U" as per default) (sy2 <- new("dsyMatrix", Dim = as.integer(c(2,2)), x = c(14, NA,32,77))) str(t(sy2)) # uplo = "L", and the lower tri. (i.e. NA is replaced). chol(sy2) #-> "Cholesky" matrix (sp2 <- pack(sy2)) # a "dspMatrix" ## Coercing to dpoMatrix gives invalid object: sy3 <- new("dsyMatrix", Dim = as.integer(c(2,2)), x = c(14, -1, 2, -7)) try(as(sy3, "dpoMatrix")) # -> error: not positive definite \dontshow{ tr <- try(as(sy3, "dpoMatrix"), silent=TRUE) stopifnot(1 == grep("not a positive definite matrix", as.character(tr)), is(sp2, "dspMatrix")) } ## 4x4 example m <- matrix(0,4,4); m[upper.tri(m)] <- 1:6 (sym <- m+t(m)+diag(11:14, 4)) (S1 <- pack(sym)) (S2 <- t(S1)) stopifnot(all(S1 == S2)) # equal "seen as matrix", but differ internally : str(S1) S2@x } Matrix/man/facmul-methods.Rd0000644000175100001440000000373514575137654015537 0ustar hornikusers\name{facmul-methods} \title{Multiplication by Factors from Matrix Factorizations} % \docType{methods} \keyword{arith} \keyword{array} \keyword{methods} % \alias{facmul} \alias{facmul-methods} % \description{ Multiplies a matrix or vector on the left or right by a factor from a matrix factorization or its transpose. } \usage{ facmul(x, factor, y, trans = FALSE, left = TRUE, \dots) } \arguments{ \item{x}{a \code{\linkS4class{MatrixFactorization}} object.} \item{factor}{a character string indicating a factor in the factorization represented by \code{x}, typically an element of \code{names(\link{expand2}(x, \dots))}.} \item{y}{a matrix or vector to be multiplied on the left or right by the factor or its transpose.} \item{trans}{a logical indicating if the transpose of the factor should be used, rather than the factor itself.} \item{left}{a logical indicating if the \code{y} should be multiplied on the left by the factor, rather than on the right.} \item{\dots}{further arguments passed to or from methods.} } \value{ The value of \code{op(M) \%*\% y} or \code{y \%*\% op(M)}, depending on \code{left}, where \code{M} is the factor (always \emph{without} \code{dimnames}) and \code{op(M)} is \code{M} or \code{t(M)}, depending on \code{trans}. } \details{ \code{facmul} is experimental and currently no methods are exported from \pkg{Matrix}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) } ## Conceptually, methods for 'facmul' _would_ behave as follows ... \dontrun{ n <- 3L x <- lu(Matrix(rnorm(n * n), n, n)) y <- rnorm(n) L <- unname(expand2(x)[[nm <- "L"]]) stopifnot(exprs = { all.equal(facmul(x, nm, y, trans = FALSE, left = TRUE), L \%*\% y) all.equal(facmul(x, nm, y, trans = FALSE, left = FALSE), y \%*\% L) all.equal(facmul(x, nm, y, trans = TRUE, left = TRUE), crossprod(L, y)) all.equal(facmul(x, nm, y, trans = TRUE, left = FALSE), tcrossprod(y, L)) }) } } Matrix/man/norm-methods.Rd0000644000175100001440000000620414575137654015235 0ustar hornikusers\name{norm-methods} \title{Matrix Norms} % \docType{methods} \keyword{algebra} \keyword{math} \keyword{methods} % \alias{norm} \alias{norm-methods} % \alias{norm,ANY,missing-method} \alias{norm,denseMatrix,character-method} \alias{norm,diagonalMatrix,character-method} \alias{norm,indMatrix,character-method} \alias{norm,pMatrix,character-method} \alias{norm,sparseMatrix,character-method} % \description{ Computes a matrix norm of \code{x}, using Lapack for dense matrices. The norm can be the one (\code{"O"}, or \code{"1"}) norm, the infinity (\code{"I"}) norm, the Frobenius (\code{"F"}) norm, the maximum modulus (\code{"M"}) among elements of a matrix, or the spectral norm or 2-norm (\code{"2"}), as determined by the value of \code{type}. } \usage{ norm(x, type, \dots) } \arguments{ \item{x}{ a real or complex matrix. } \item{type}{ A character indicating the type of norm desired. \describe{ \item{\code{"O"}, \code{"o"} or \code{"1"}}{specifies the one norm, (maximum absolute column sum);} \item{\code{"I"} or \code{"i"}}{specifies the infinity norm (maximum absolute row sum);} \item{\code{"F"} or \code{"f"}}{specifies the Frobenius norm (the Euclidean norm of \code{x} treated as if it were a vector);} \item{\code{"M"} or \code{"m"}}{specifies the maximum modulus of all the elements in \code{x}; and} \item{\code{"2"}}{specifies the \dQuote{spectral norm} aka \dQuote{2-norm}, which is the largest singular value (\code{\link{svd}}) of \code{x}.} } The default is \code{"O"}. Only the first character of \code{type[1]} is used. } \item{\dots}{further arguments passed to or from other methods.} } \value{ A numeric value of class \code{"norm"}, representing the quantity chosen according to \code{type}. } \details{ For dense matrices, the methods eventually call the Lapack functions \code{dlange}, \code{dlansy}, \code{dlantr}, \code{zlange}, \code{zlansy}, and \code{zlantr}. } \seealso{ \code{\link{onenormest}()}, an \emph{approximate} randomized estimate of the 1-norm condition number, efficient for large sparse matrices. The \code{\link[base]{norm}()} function from \R's \pkg{base} package. } \references{ Anderson, E., et al. (1994). \emph{LAPACK User's Guide,} 2nd edition, SIAM, Philadelphia. } \examples{ x <- Hilbert(9) norm(x)# = "O" = "1" stopifnot(identical(norm(x), norm(x, "1"))) norm(x, "I")# the same, because 'x' is symmetric allnorms <- function(x) { ## norm(NA, "2") did not work until R 4.0.0 do2 <- getRversion() >= "4.0.0" || !anyNA(x) vapply(c("1", "I", "F", "M", if(do2) "2"), norm, 0, x = x) } allnorms(x) allnorms(Hilbert(10)) i <- c(1,3:8); j <- c(2,9,6:10); x <- 7 * (1:7) A <- sparseMatrix(i, j, x = x) ## 8 x 10 "dgCMatrix" (sA <- sparseMatrix(i, j, x = x, symmetric = TRUE)) ## 10 x 10 "dsCMatrix" (tA <- sparseMatrix(i, j, x = x, triangular= TRUE)) ## 10 x 10 "dtCMatrix" (allnorms(A) -> nA) allnorms(sA) allnorms(tA) stopifnot(all.equal(nA, allnorms(as(A, "matrix"))), all.equal(nA, allnorms(tA))) # because tA == rbind(A, 0, 0) A. <- A; A.[1,3] <- NA stopifnot(is.na(allnorms(A.))) # gave error } Matrix/man/dimScale.Rd0000644000175100001440000000365114422605232014324 0ustar hornikusers\name{dimScale} \title{Scale the Rows and Columns of a Matrix} % \keyword{algebra} \keyword{arith} \keyword{array} \keyword{utilities} % \alias{dimScale} \alias{rowScale} \alias{colScale} % \description{ \code{dimScale}, \code{rowScale}, and \code{colScale} implement \code{D1 \%*\% x \%*\% D2}, \code{D \%*\% x}, and \code{x \%*\% D} for diagonal matrices \code{D1}, \code{D2}, and \code{D} with diagonal entries \code{d1}, \code{d2}, and \code{d}, respectively. Unlike the explicit products, these functions preserve \code{dimnames(x)} and symmetry where appropriate. } \usage{ dimScale(x, d1 = sqrt(1/diag(x, names = FALSE)), d2 = d1) rowScale(x, d) colScale(x, d) } \arguments{ \item{x}{a matrix, possibly inheriting from virtual class \code{\linkS4class{Matrix}}.} \item{d1,d2,d}{numeric vectors giving factors by which to scale the rows or columns of \code{x}; they are recycled as necessary.} } \details{ \code{dimScale(x)} (with \code{d1} and \code{d2} unset) is only roughly equivalent to \code{\link{cov2cor}(x)}. \code{cov2cor} sets the diagonal entries of the result to 1 (exactly); \code{dimScale} does not. } \value{ The result of scaling \code{x}, currently always inheriting from virtual class \code{\linkS4class{dMatrix}}. It inherits from \code{\linkS4class{triangularMatrix}} if and only if \code{x} does. In the special case of \code{dimScale(x, d1, d2)} with identical \code{d1} and \code{d2}, it inherits from \code{\linkS4class{symmetricMatrix}} if and only if \code{x} does. } \author{Mikael Jagan} \seealso{\code{\link{cov2cor}}} \examples{ n <- 6L (x <- forceSymmetric(matrix(1, n, n))) dimnames(x) <- rep.int(list(letters[seq_len(n)]), 2L) d <- seq_len(n) (D <- Diagonal(x = d)) (scx <- dimScale(x, d)) # symmetry and 'dimnames' kept (mmx <- D \%*\% x \%*\% D) # symmetry and 'dimnames' lost stopifnot(identical(unname(as(scx, "generalMatrix")), mmx)) rowScale(x, d) colScale(x, d) } Matrix/man/qr-methods.Rd0000644000175100001440000001550414575234535014703 0ustar hornikusers\name{qr-methods} \title{Methods for QR Factorization} % \docType{methods} \keyword{algebra} \keyword{array} \keyword{methods} % \alias{qr} \alias{qr-methods} % \alias{qr,dgCMatrix-method} \alias{qr,sparseMatrix-method} % \description{ Computes the pivoted QR factorization of an \eqn{m \times n}{m-by-n} real matrix \eqn{A}, which has the general form \deqn{P_{1} A P_{2} = Q R}{P1 * A * P2 = Q * R} or (equivalently) \deqn{A = P_{1}' Q R P_{2}'}{A = P1' * Q * R * P2'} where \eqn{P_{1}}{P1} and \eqn{P_{2}}{P2} are permutation matrices, \eqn{Q = \prod_{j = 1}^{n} H_{j}}{Q = prod(Hj : j = 1,...,n)} is an \eqn{m \times m}{m-by-m} orthogonal matrix equal to the product of \eqn{n} Householder matrices \eqn{H_{j}}{Hj}, and \eqn{R} is an \eqn{m \times n}{m-by-n} upper trapezoidal matrix. \code{\linkS4class{denseMatrix}} use the default method implemented in \pkg{base}, namely \code{\link{qr.default}}. It is built on LINPACK routine \code{dqrdc} and LAPACK routine \code{dgeqp3}, which do not pivot rows, so that \eqn{P_{1}}{P1} is an identity matrix. Methods for \code{\linkS4class{sparseMatrix}} are built on CXSparse routines \code{cs_sqr} and \code{cs_qr}, which require \eqn{m \ge n}{m >= n}. } \usage{ qr(x, \dots) \S4method{qr}{dgCMatrix}(x, order = 3L, \dots) } \arguments{ \item{x}{a \link[=is.finite]{finite} matrix or \code{\linkS4class{Matrix}} to be factorized, satisfying \code{nrow(x) >= ncol(x)} if sparse.} \item{order}{an integer in \code{0:3} passed to CXSparse routine \code{cs_sqr}, indicating a strategy for choosing the column permutation \eqn{P_{2}}{P2}. 0 means no column permutation. 1, 2, and 3 indicate a fill-reducing ordering of \eqn{A + A'}, \eqn{\tilde{A}' \tilde{A}}{A~' * A~}, and \eqn{A' A}{A' * A}, where \eqn{\tilde{A}}{A~} is \eqn{A} with \dQuote{dense} rows removed. Do not set to 0 unless you know that the column order of \eqn{A} is already sensible.} \item{\dots}{further arguments passed to or from methods.} } \value{ An object representing the factorization, inheriting from virtual S4 class \code{\linkS4class{QR}} or S3 class \code{\link[base]{qr}}. The specific class is \code{qr} unless \code{x} inherits from virtual class \code{\linkS4class{sparseMatrix}}, in which case it is \code{\linkS4class{sparseQR}}. } \details{ If \code{x} is sparse and structurally rank deficient, having structural rank \eqn{r < n}, then \code{x} is augmented with \eqn{(n-r)} rows of (partly non-structural) zeros, such that the augmented matrix has structural rank \eqn{n}. This augmented matrix is factorized as described above: \deqn{P_1 A P_2 = P_1 \begin{bmatrix} A_{0} \\ 0 \end{bmatrix} P_2 = Q R}{P1 * A * P2 = P1 * [A0; 0] * P2 = Q * R} where \eqn{A_0}{A0} denotes the original, user-supplied \eqn{(m-(n-r)) \times n}{(m-(n-r))-by-n} matrix. } \seealso{ Class \code{\linkS4class{sparseQR}} and its methods. Class \code{\linkS4class{dgCMatrix}}. Generic function \code{\link[base]{qr}} from \pkg{base}, whose default method \code{qr.default} \dQuote{defines} the S3 class \code{qr} of dense QR factorizations. Generic functions \code{\link{expand1}} and \code{\link{expand2}}, for constructing matrix factors from the result. Generic functions \code{\link{Cholesky}}, \code{\link{BunchKaufman}}, \code{\link{Schur}}, and \code{\link{lu}}, for computing other factorizations. } \references{ Davis, T. A. (2006). \emph{Direct methods for sparse linear systems}. Society for Industrial and Applied Mathematics. \doi{10.1137/1.9780898718881} Golub, G. H., & Van Loan, C. F. (2013). \emph{Matrix computations} (4th ed.). Johns Hopkins University Press. \doi{10.56021/9781421407944} } \examples{ showMethods("qr", inherited = FALSE) ## Rank deficient: columns 3 {b2} and 6 {c3} are "extra" M <- as(cbind(a1 = 1, b1 = rep(c(1, 0), each = 3L), b2 = rep(c(0, 1), each = 3L), c1 = rep(c(1, 0, 0), 2L), c2 = rep(c(0, 1, 0), 2L), c3 = rep(c(0, 0, 1), 2L)), "CsparseMatrix") rownames(M) <- paste0("r", seq_len(nrow(M))) b <- 1:6 eps <- .Machine$double.eps ## .... [1] full rank .................................................. ## ===> a least squares solution of A x = b exists ## and is unique _in exact arithmetic_ (A1 <- M[, -c(3L, 6L)]) (qr.A1 <- qr(A1)) stopifnot(exprs = { rankMatrix(A1) == ncol(A1) { d1 <- abs(diag(qr.A1@R)); sum(d1 < max(d1) * eps) == 0L } rcond(crossprod(A1)) >= eps all.equal(qr.coef(qr.A1, b), drop(solve(crossprod(A1), crossprod(A1, b)))) all.equal(qr.fitted(qr.A1, b) + qr.resid(qr.A1, b), b) }) ## .... [2] numerically rank deficient with full structural rank ....... ## ===> a least squares solution of A x = b does not ## exist or is not unique _in exact arithmetic_ (A2 <- M) (qr.A2 <- qr(A2)) stopifnot(exprs = { rankMatrix(A2) == ncol(A2) - 2L { d2 <- abs(diag(qr.A2@R)); sum(d2 < max(d2) * eps) == 2L } rcond(crossprod(A2)) < eps ## 'qr.coef' computes unique least squares solution of "nearby" problem ## Z x = b for some full rank Z ~ A, currently without warning {FIXME} ! tryCatch({ qr.coef(qr.A2, b); TRUE }, condition = function(x) FALSE) all.equal(qr.fitted(qr.A2, b) + qr.resid(qr.A2, b), b) }) ## .... [3] numerically and structurally rank deficient ................ ## ===> factorization of _augmented_ matrix with ## full structural rank proceeds as in [2] ## NB: implementation details are subject to change; see (*) below A3 <- M A3[, c(3L, 6L)] <- 0 A3 (qr.A3 <- qr(A3)) # with a warning ... "additional 2 row(s) of zeros" stopifnot(exprs = { ## sparseQR object preserves the unaugmented dimensions (*) dim(qr.A3 ) == dim(A3) dim(qr.A3@V) == dim(A3) + c(2L, 0L) dim(qr.A3@R) == dim(A3) + c(2L, 0L) ## The augmented matrix remains numerically rank deficient rankMatrix(A3) == ncol(A3) - 2L { d3 <- abs(diag(qr.A3@R)); sum(d3 < max(d3) * eps) == 2L } rcond(crossprod(A3)) < eps }) ## Auxiliary functions accept and return a vector or matrix ## with dimensions corresponding to the unaugmented matrix (*), ## in all cases with a warning qr.coef (qr.A3, b) qr.fitted(qr.A3, b) qr.resid (qr.A3, b) ## .... [4] yet more examples .......................................... ## By disabling column pivoting, one gets the "vanilla" factorization ## A = Q~ R, where Q~ := P1' Q is orthogonal because P1 and Q are (qr.A1.pp <- qr(A1, order = 0L)) # partial pivoting ae1 <- function(a, b, ...) all.equal(as(a, "matrix"), as(b, "matrix"), ...) ae2 <- function(a, b, ...) ae1(unname(a), unname(b), ...) stopifnot(exprs = { length(qr.A1 @q) == ncol(A1) length(qr.A1.pp@q) == 0L # indicating no column pivoting ae2(A1[, qr.A1@q + 1L], qr.Q(qr.A1 ) \%*\% qr.R(qr.A1 )) ae2(A1 , qr.Q(qr.A1.pp) \%*\% qr.R(qr.A1.pp)) }) } Matrix/man/dsRMatrix-class.Rd0000644000175100001440000000536214575137654015645 0ustar hornikusers\name{dsRMatrix-class} \title{Symmetric Sparse Compressed Row Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{dsRMatrix-class} % \alias{determinant,dsRMatrix,logical-method} % \description{The \code{dsRMatrix} class is a class of symmetric, sparse matrices in the compressed, row-oriented format. In this implementation the non-zero elements in the rows are sorted into increasing column order. } \section{Objects from the Class}{ These \code{"..RMatrix"} classes are currently still mostly unimplemented! Objects can be created by calls of the form \code{new("dsRMatrix", ...)}. } \section{Slots}{ \describe{ \item{\code{uplo}:}{A character object indicating if the upper triangle (\code{"U"}) or the lower triangle (\code{"L"}) is stored. At present only the lower triangle form is allowed.} \item{\code{j}:}{Object of class \code{"integer"} of length \code{nnzero} (number of non-zero elements). These are the row numbers for each non-zero element in the matrix.} \item{\code{p}:}{Object of class \code{"integer"} of pointers, one for each row, to the initial (zero-based) index of elements in the row.} \item{\code{factors}:}{Object of class \code{"list"} - a list of factorizations of the matrix.} \item{\code{x}:}{Object of class \code{"numeric"} - the non-zero elements of the matrix.} \item{\code{Dim}:}{Object of class \code{"integer"} - the dimensions of the matrix - must be an integer vector with exactly two non-negative values.} \item{\code{Dimnames}:}{List of length two, see \code{\link{Matrix}}.} } } \section{Extends}{ Classes \code{\linkS4class{dsparseMatrix}}, \code{\linkS4class{symmetricMatrix}}, and \code{\linkS4class{RsparseMatrix}}, directly. Class \code{"dMatrix"}, by class \code{"dsparseMatrix"}; class \code{"sparseMatrix"}, by classes \code{"dsparseMatrix"} and \code{"RsparseMatrix"}. } \section{Methods}{ \describe{ \item{forceSymmetric}{\code{signature(x = "dsRMatrix", uplo = "missing")}: a trivial method just returning \code{x}} \item{forceSymmetric}{\code{signature(x = "dsRMatrix", uplo = "character")}: if \code{uplo == x@uplo}, this trivially returns \code{x}; otherwise \code{t(x)}.} } } \seealso{ the classes \code{\linkS4class{dgCMatrix}}, \code{\linkS4class{dgTMatrix}}, and \code{\linkS4class{dgeMatrix}}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } (m0 <- new("dsRMatrix")) m2 <- new("dsRMatrix", Dim = c(2L,2L), x = c(3,1), j = c(1L,1L), p = 0:2) m2 stopifnot(colSums(as(m2, "TsparseMatrix")) == 3:4) str(m2) (ds2 <- forceSymmetric(diag(2))) # dsy* dR <- as(ds2, "RsparseMatrix") dR # dsRMatrix } Matrix/man/wrld_1deg.Rd0000644000175100001440000000531214447626522014463 0ustar hornikusers\name{wrld_1deg} \title{Contiguity Matrix of World One-Degree Grid Cells} % \docType{data} \keyword{datasets} % \alias{wrld_1deg} % \description{ This matrix gives the contiguities of 15260 one-degree grid cells of world land areas, using a criterion based on the great-circle distance between centers. } \usage{data(wrld_1deg)} \format{ A \eqn{15260 \times 15260}{15260-by-15260} sparse, symmetric matrix of class \code{\linkS4class{dsCMatrix}}, with 55973 nonzero entries. } \source{ Shoreline data were read into \R{} from the GSHHS database using function \code{Rgshhs} from package \CRANpkg{maptools}. Antarctica was excluded. An approximately one-degree grid was generated using function \code{Sobj_SpatialGrid}, also from \CRANpkg{maptools}. Grid cells with centers on land were identified using the \code{over} method for classes \code{SpatialPolygons} and \code{SpatialGrid}, defined in package \CRANpkg{sp}. Neighbours of these were identified by passing the resulting \code{SpatialPixels} object to function \code{dnearneigh} from package \CRANpkg{spdep}, using as a cut-off a great-circle distance of \code{sqrt(2)} kilometers between centers. Neighbour lists were augmented with row-standardized (and then symmetrized) spatial weights, using functions \code{nb2listw} and \code{similar.listw} from packages \CRANpkg{spdep} and \CRANpkg{spatialreg}. The resulting \code{listw} object was coerced to class \code{\linkS4class{dsTMatrix}} using \code{as_dsTMatrix_listw} from \CRANpkg{spatialreg}, and subsequently to class \code{\linkS4class{dsCMatrix}}. } \references{ Ord, J. K. (1975). Estimation methods for models of spatial interaction. \emph{Journal of the American Statistical Association}, \emph{70}(349), 120-126. \doi{10.2307/2285387} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } data(wrld_1deg, package = "Matrix") (n <- ncol(wrld_1deg)) I <- .symDiagonal(n) doExtras <- interactive() || nzchar(Sys.getenv("R_MATRIX_CHECK_EXTRA")) set.seed(1) r <- if(doExtras) 20L else 3L rho <- 1 / runif(r, 0, 0.5) system.time(MJ0 <- sapply(rho, function(mult) determinant(wrld_1deg + mult * I, logarithm = TRUE)$modulus)) ## Can be done faster by updating the Cholesky factor: C1 <- Cholesky(wrld_1deg, Imult = 2) system.time(MJ1 <- sapply(rho, function(mult) determinant(update(C1, wrld_1deg, mult), sqrt = FALSE)$modulus)) stopifnot(all.equal(MJ0, MJ1)) C2 <- Cholesky(wrld_1deg, super = TRUE, Imult = 2) system.time(MJ2 <- sapply(rho, function(mult) determinant(update(C2, wrld_1deg, mult), sqrt = FALSE)$modulus)) stopifnot(all.equal(MJ0, MJ2)) } Matrix/man/sparseLU-class.Rd0000644000175100001440000001076614446607050015457 0ustar hornikusers\name{sparseLU-class} \title{Sparse LU Factorizations} % \docType{class} \keyword{algebra} \keyword{array} \keyword{classes} % \alias{sparseLU-class} % \alias{determinant,sparseLU,logical-method} % \description{ \code{sparseLU} is the class of sparse, row- and column-pivoted LU factorizations of \eqn{n \times n}{n-by-n} real matrices \eqn{A}, having the general form \deqn{P_{1} A P_{2} = L U}{P1 * A * P2 = L * U} or (equivalently) \deqn{A = P_{1}' L U P_{2}'}{A = P1' * L * U * P2'} where \eqn{P_{1}}{P1} and \eqn{P_{2}}{P2} are permutation matrices, \eqn{L} is a unit lower triangular matrix, and \eqn{U} is an upper triangular matrix. } \section{Slots}{ \describe{ \item{\code{Dim}, \code{Dimnames}}{inherited from virtual class \code{\linkS4class{MatrixFactorization}}.} \item{\code{L}}{an object of class \code{\linkS4class{dtCMatrix}}, the unit lower triangular \eqn{L} factor.} \item{\code{U}}{an object of class \code{\linkS4class{dtCMatrix}}, the upper triangular \eqn{U} factor.} \item{\code{p}, \code{q}}{0-based integer vectors of length \code{Dim[1]}, specifying the permutations applied to the rows and columns of the factorized matrix. \code{q} of length 0 is valid and equivalent to the identity permutation, implying no column pivoting. Using \R{} syntax, the matrix \eqn{P_{1} A P_{2}}{P1 * A * P2} is precisely \code{A[p+1, q+1]} (\code{A[p+1, ]} when \code{q} has length 0).} } } \section{Extends}{ Class \code{\linkS4class{LU}}, directly. Class \code{\linkS4class{MatrixFactorization}}, by class \code{\linkS4class{LU}}, distance 2. } \section{Instantiation}{ Objects can be generated directly by calls of the form \code{new("sparseLU", ...)}, but they are more typically obtained as the value of \code{\link{lu}(x)} for \code{x} inheriting from \code{\linkS4class{sparseMatrix}} (often \code{\linkS4class{dgCMatrix}}). } \section{Methods}{ \describe{ \item{\code{determinant}}{\code{signature(from = "sparseLU", logarithm = "logical")}: computes the determinant of the factorized matrix \eqn{A} or its logarithm.} \item{\code{expand}}{\code{signature(x = "sparseLU")}: see \code{\link{expand-methods}}.} \item{\code{expand1}}{\code{signature(x = "sparseLU")}: see \code{\link{expand1-methods}}.} \item{\code{expand2}}{\code{signature(x = "sparseLU")}: see \code{\link{expand2-methods}}.} \item{\code{solve}}{\code{signature(a = "sparseLU", b = .)}: see \code{\link{solve-methods}}.} } } \seealso{ Class \code{\linkS4class{denseLU}} for dense LU factorizations. Class \code{\linkS4class{dgCMatrix}}. Generic functions \code{\link{lu}}, \code{\link{expand1}} and \code{\link{expand2}}. } \references{ Davis, T. A. (2006). \emph{Direct methods for sparse linear systems}. Society for Industrial and Applied Mathematics. \doi{10.1137/1.9780898718881} Golub, G. H., & Van Loan, C. F. (2013). \emph{Matrix computations} (4th ed.). Johns Hopkins University Press. \doi{10.56021/9781421407944} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } showClass("sparseLU") set.seed(2) A <- as(readMM(system.file("external", "pores_1.mtx", package = "Matrix")), "CsparseMatrix") (n <- A@Dim[1L]) ## With dimnames, to see that they are propagated : dimnames(A) <- dn <- list(paste0("r", seq_len(n)), paste0("c", seq_len(n))) (lu.A <- lu(A)) str(e.lu.A <- expand2(lu.A), max.level = 2L) ae1 <- function(a, b, ...) all.equal(as(a, "matrix"), as(b, "matrix"), ...) ae2 <- function(a, b, ...) ae1(unname(a), unname(b), ...) ## A ~ P1' L U P2' in floating point stopifnot(exprs = { identical(names(e.lu.A), c("P1.", "L", "U", "P2.")) identical(e.lu.A[["P1."]], new("pMatrix", Dim = c(n, n), Dimnames = c(dn[1L], list(NULL)), margin = 1L, perm = invertPerm(lu.A@p, 0L, 1L))) identical(e.lu.A[["P2."]], new("pMatrix", Dim = c(n, n), Dimnames = c(list(NULL), dn[2L]), margin = 2L, perm = invertPerm(lu.A@q, 0L, 1L))) identical(e.lu.A[["L"]], lu.A@L) identical(e.lu.A[["U"]], lu.A@U) ae1(A, with(e.lu.A, P1. \%*\% L \%*\% U \%*\% P2.)) ae2(A[lu.A@p + 1L, lu.A@q + 1L], with(e.lu.A, L \%*\% U)) }) ## Factorization handled as factorized matrix b <- rnorm(n) stopifnot(identical(det(A), det(lu.A)), identical(solve(A, b), solve(lu.A, b))) } Matrix/man/formatSparseM.Rd0000644000175100001440000000673114422605232015370 0ustar hornikusers\name{formatSparseM} \title{Formatting Sparse Numeric Matrices Utilities} % \keyword{character} \keyword{print} \keyword{utilities} % \alias{formatSparseM} \alias{.formatSparseSimple} % \description{ Utilities for formatting sparse numeric matrices in a flexible way. These functions are used by the \code{\link{format}} and \code{print} methods for sparse matrices and can be applied as well to standard \R matrices. Note that \emph{all} arguments but the first are optional. \code{formatSparseM()} is the main \dQuote{workhorse} of \code{\link{formatSpMatrix}}, the \code{format} method for sparse matrices. \code{.formatSparseSimple()} is a simple helper function, also dealing with (short/empty) column names construction. } \usage{ formatSparseM(x, zero.print = ".", align = c("fancy", "right"), m = as(x,"matrix"), asLogical=NULL, uniDiag=NULL, digits=NULL, cx, iN0, dn = dimnames(m)) .formatSparseSimple(m, asLogical=FALSE, digits=NULL, col.names, note.dropping.colnames = TRUE, dn=dimnames(m)) } \arguments{ \item{x}{an \R object inheriting from class \code{\linkS4class{sparseMatrix}}.} \item{zero.print}{character which should be used for \emph{structural} zeroes. The default \code{"."} may occasionally be replaced by \code{" "} (blank); using \code{"0"} would look almost like \code{print()}ing of non-sparse matrices.} \item{align}{a string specifying how the \code{zero.print} codes should be aligned, see \code{\link{formatSpMatrix}}.} \item{m}{(optional) a (standard \R) \code{\link{matrix}} version of \code{x}.} \item{asLogical}{should the matrix be formatted as a logical matrix (or rather as a numeric one); mostly for \code{formatSparseM()}.} \item{uniDiag}{logical indicating if the diagonal entries of a sparse unit triangular or unit-diagonal matrix should be formatted as \code{"I"} instead of \code{"1"} (to emphasize that the 1's are \dQuote{structural}).} \item{digits}{significant digits to use for printing, see \code{\link{print.default}}.} \item{cx}{(optional) character matrix; a formatted version of \code{x}, still with strings such as \code{"0.00"} for the zeros.} \item{iN0}{(optional) integer vector, specifying the location of the \emph{non}-zeroes of \code{x}.} \item{col.names, note.dropping.colnames}{see \code{\link{formatSpMatrix}}.} \item{dn}{\code{\link{dimnames}} to be used; a list (of length two) with row and column names (or \code{\link{NULL}}).} } \seealso{ \code{\link{formatSpMatrix}} which calls \code{formatSparseM()} and is the \code{\link{format}} method for sparse matrices.\cr \code{\link{printSpMatrix}} which is used by the (typically implicitly called) \code{\link{show}} and \code{\link{print}} methods for sparse matrices. } \value{ a character matrix like \code{cx}, where the zeros have been replaced with (padded versions of) \code{zero.print}. As this is a \emph{dense} matrix, do not use these functions for really large (really) sparse matrices! } \author{Martin Maechler} \examples{ m <- suppressWarnings(matrix(c(0, 3.2, 0,0, 11,0,0,0,0,-7,0), 4,9)) fm <- formatSparseM(m) noquote(fm) ## nice, but this is nicer {with "units" vertically aligned}: print(fm, quote=FALSE, right=TRUE) ## and "the same" as : Matrix(m) ## align = "right" is cheaper --> the "." are not aligned: noquote(f2 <- formatSparseM(m,align="r")) stopifnot(f2 == fm | m == 0, dim(f2) == dim(m), (f2 == ".") == (m == 0)) } Matrix/man/updown-methods.Rd0000644000175100001440000000523714575137654015603 0ustar hornikusers\name{updown-methods} \title{Updating and Downdating Sparse Cholesky Factorizations} % \docType{methods} \keyword{algebra} \keyword{array} \keyword{methods} % \alias{updown} \alias{updown-methods} % \alias{updown,character,ANY,ANY-method} \alias{updown,logical,Matrix,CHMfactor-method} \alias{updown,logical,dgCMatrix,CHMfactor-method} \alias{updown,logical,dsCMatrix,CHMfactor-method} \alias{updown,logical,dtCMatrix,CHMfactor-method} \alias{updown,logical,matrix,CHMfactor-method} % \description{ Computes a rank-\eqn{k} update or downdate of a sparse Cholesky factorization \deqn{P_{1} A P_{1}' = L_{1} D L_{1}' = L L'}{P1 * A * P1' = L1 * D * L1' = L * L'} which for some \eqn{k}-column matrix \eqn{C} is the factorization \deqn{P_{1} (A + s C C') P_{1}' = \tilde{L}_{1} \tilde{D} \tilde{L}_{1}' = \tilde{L} \tilde{L}'}{P1 * (A + s * C * C') * P1' = L~1 * D~ * L~1' = L~ * L~'} Here, \eqn{s = 1} for an update and \eqn{s = -1} for a downdate. } \usage{ updown(update, C, L) } \arguments{ \item{update}{a logical (\code{TRUE} or \code{FALSE}) or character (\code{"+"} or \code{"-"}) indicating if \code{L} should be updated (or otherwise downdated).} \item{C}{a \link[=is.finite]{finite} matrix or \code{\linkS4class{Matrix}} such that \code{\link{tcrossprod}(C)} has the dimensions of \code{L}.} \item{L}{an object of class \code{\linkS4class{dCHMsimpl}} or \code{\linkS4class{dCHMsuper}} specifying a sparse Cholesky factorization.} } \value{ A sparse Cholesky factorization with dimensions matching \code{L}, typically of class \code{\linkS4class{dCHMsimpl}}. } \seealso{ Classes \code{\linkS4class{dCHMsimpl}} and \code{\linkS4class{dCHMsuper}} and their methods, notably for generic function \code{\link{update}}, which is \emph{not} equivalent to \code{updown(update = TRUE)}. Generic function \code{\link{Cholesky}}. } \author{Initial implementation by Nicholas Nagle, University of Tennessee.} \references{ Davis, T. A., Hager, W. W. (2001). Multiple-rank modifications of a sparse Cholesky factorization. \emph{SIAM Journal on Matrix Analysis and Applications}, \emph{22}(4), 997-1013. \doi{10.1137/S0895479899357346} } \examples{ m <- sparseMatrix(i = c(3, 1, 3:2, 2:1), p = c(0:2, 4, 4, 6), x = 1:6, dimnames = list(LETTERS[1:3], letters[1:5])) uc0 <- Cholesky(A <- crossprod(m) + Diagonal(5)) uc1 <- updown("+", Diagonal(5, 1), uc0) uc2 <- updown("-", Diagonal(5, 1), uc1) stopifnot(all.equal(uc0, uc2)) \dontshow{ if(FALSE) { ## Hmm: this loses positive definiteness: uc2 <- updown("-", Diagonal(5, 2), uc0) image(show(as(uc0, "CsparseMatrix"))) image(show(as(uc2, "CsparseMatrix"))) # severely negative entries } } } Matrix/man/diagU2N.Rd0000644000175100001440000000546714446607050014051 0ustar hornikusers\name{diagU2N} \title{Transform Triangular Matrices from Unit Triangular to General Triangular and Back} % \keyword{array} \keyword{attribute} \keyword{utilities} % \alias{diagU2N} \alias{diagN2U} \alias{.diagU2N} \alias{.diagN2U} % \description{ Transform a triangular matrix \code{x}, i.e., of \code{\link{class}} \code{\linkS4class{triangularMatrix}}, from (internally!) unit triangular (\dQuote{unitriangular}) to \dQuote{general} triangular (\code{diagU2N(x)}) or back (\code{diagN2U(x)}). Note that the latter, \code{diagN2U(x)}, also sets the diagonal to one in cases where \code{diag(x)} was not all one. \code{.diagU2N(x)} and \code{.diagN2U(x)} assume \emph{without} checking that \code{x} is a \code{\linkS4class{triangularMatrix}} with suitable \code{diag} slot (\code{"U"} and \code{"N"}, respectively), hence they should be used with care. } \usage{ diagU2N(x, cl = getClassDef(class(x)), checkDense = FALSE) diagN2U(x, cl = getClassDef(class(x)), checkDense = FALSE) .diagU2N(x, cl = getClassDef(class(x)), checkDense = FALSE) .diagN2U(x, cl = getClassDef(class(x)), checkDense = FALSE) } \arguments{ \item{x}{a \code{\linkS4class{triangularMatrix}}, often sparse.} \item{cl}{(optional, for speedup only:) class (definition) of \code{x}.} \item{checkDense}{logical indicating if dense (see \code{\linkS4class{denseMatrix}}) matrices should be considered at all; i.e., when false, as per default, the result will be sparse even when \code{x} is dense.} } \details{ The concept of unit triangular matrices with a \code{diag} slot of \code{"U"} stems from LAPACK. } \note{Such internal storage details should rarely be of relevance to the user. Hence, these functions really are rather \emph{internal} utilities. } \value{ a triangular matrix of the same \code{\link{class}} but with a different \code{diag} slot. For \code{diagU2N} (semantically) with identical entries as \code{x}, whereas in \code{diagN2U(x)}, the off-diagonal entries are unchanged and the diagonal is set to all \code{1} even if it was not previously. } \seealso{ \code{"\linkS4class{triangularMatrix}"}, \code{"\linkS4class{dtCMatrix}"}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) } (T <- Diagonal(7) + triu(Matrix(rpois(49, 1/4), 7, 7), k = 1)) (uT <- diagN2U(T)) # "unitriangular" (t.u <- diagN2U(10*T))# changes the diagonal! stopifnot(all(T == uT), diag(t.u) == 1, identical(T, diagU2N(uT))) T[upper.tri(T)] <- 5 # still "dtC" T <- diagN2U(as(T,"triangularMatrix")) dT <- as(T, "denseMatrix") # (unitriangular) dT.n <- diagU2N(dT, checkDense = TRUE) sT.n <- diagU2N(dT) stopifnot(is(dT.n, "denseMatrix"), is(sT.n, "sparseMatrix"), dT@diag == "U", dT.n@diag == "N", sT.n@diag == "N", all(dT == dT.n), all(dT == sT.n)) } Matrix/man/boolmatmult-methods.Rd0000644000175100001440000001575114575137654016630 0ustar hornikusers\name{boolmatmult-methods} \title{Boolean Arithmetic Matrix Products: \code{\%&\%} and Methods} % \docType{methods} \keyword{algebra} \keyword{array} \keyword{logic} \keyword{methods} % \alias{\%&\%} \alias{\%&\%-methods} \alias{boolmatmult-methods} % \alias{\%&\%,ANY,ANY-method} \alias{\%&\%,ANY,Matrix-method} \alias{\%&\%,ANY,matrix-method} \alias{\%&\%,ANY,sparseVector-method} \alias{\%&\%,ANY,vector-method} \alias{\%&\%,CsparseMatrix,CsparseMatrix-method} \alias{\%&\%,CsparseMatrix,RsparseMatrix-method} \alias{\%&\%,CsparseMatrix,TsparseMatrix-method} \alias{\%&\%,CsparseMatrix,denseMatrix-method} \alias{\%&\%,CsparseMatrix,diagonalMatrix-method} \alias{\%&\%,CsparseMatrix,matrix-method} \alias{\%&\%,CsparseMatrix,vector-method} \alias{\%&\%,Matrix,ANY-method} \alias{\%&\%,Matrix,indMatrix-method} \alias{\%&\%,Matrix,pMatrix-method} \alias{\%&\%,Matrix,sparseVector-method} \alias{\%&\%,RsparseMatrix,CsparseMatrix-method} \alias{\%&\%,RsparseMatrix,RsparseMatrix-method} \alias{\%&\%,RsparseMatrix,TsparseMatrix-method} \alias{\%&\%,RsparseMatrix,denseMatrix-method} \alias{\%&\%,RsparseMatrix,diagonalMatrix-method} \alias{\%&\%,RsparseMatrix,matrix-method} \alias{\%&\%,RsparseMatrix,vector-method} \alias{\%&\%,TsparseMatrix,CsparseMatrix-method} \alias{\%&\%,TsparseMatrix,RsparseMatrix-method} \alias{\%&\%,TsparseMatrix,TsparseMatrix-method} \alias{\%&\%,TsparseMatrix,denseMatrix-method} \alias{\%&\%,TsparseMatrix,diagonalMatrix-method} \alias{\%&\%,TsparseMatrix,matrix-method} \alias{\%&\%,TsparseMatrix,vector-method} \alias{\%&\%,denseMatrix,CsparseMatrix-method} \alias{\%&\%,denseMatrix,RsparseMatrix-method} \alias{\%&\%,denseMatrix,TsparseMatrix-method} \alias{\%&\%,denseMatrix,denseMatrix-method} \alias{\%&\%,denseMatrix,diagonalMatrix-method} \alias{\%&\%,denseMatrix,matrix-method} \alias{\%&\%,denseMatrix,vector-method} \alias{\%&\%,diagonalMatrix,CsparseMatrix-method} \alias{\%&\%,diagonalMatrix,RsparseMatrix-method} \alias{\%&\%,diagonalMatrix,TsparseMatrix-method} \alias{\%&\%,diagonalMatrix,denseMatrix-method} \alias{\%&\%,diagonalMatrix,diagonalMatrix-method} \alias{\%&\%,diagonalMatrix,matrix-method} \alias{\%&\%,diagonalMatrix,vector-method} \alias{\%&\%,indMatrix,Matrix-method} \alias{\%&\%,indMatrix,indMatrix-method} \alias{\%&\%,indMatrix,matrix-method} \alias{\%&\%,indMatrix,pMatrix-method} \alias{\%&\%,indMatrix,vector-method} \alias{\%&\%,matrix,ANY-method} \alias{\%&\%,matrix,CsparseMatrix-method} \alias{\%&\%,matrix,RsparseMatrix-method} \alias{\%&\%,matrix,TsparseMatrix-method} \alias{\%&\%,matrix,denseMatrix-method} \alias{\%&\%,matrix,diagonalMatrix-method} \alias{\%&\%,matrix,indMatrix-method} \alias{\%&\%,matrix,matrix-method} \alias{\%&\%,matrix,pMatrix-method} \alias{\%&\%,matrix,sparseVector-method} \alias{\%&\%,matrix,vector-method} \alias{\%&\%,pMatrix,Matrix-method} \alias{\%&\%,pMatrix,indMatrix-method} \alias{\%&\%,pMatrix,matrix-method} \alias{\%&\%,pMatrix,pMatrix-method} \alias{\%&\%,pMatrix,vector-method} \alias{\%&\%,sparseVector,ANY-method} \alias{\%&\%,sparseVector,Matrix-method} \alias{\%&\%,sparseVector,matrix-method} \alias{\%&\%,sparseVector,sparseVector-method} \alias{\%&\%,sparseVector,vector-method} \alias{\%&\%,vector,ANY-method} \alias{\%&\%,vector,CsparseMatrix-method} \alias{\%&\%,vector,RsparseMatrix-method} \alias{\%&\%,vector,TsparseMatrix-method} \alias{\%&\%,vector,denseMatrix-method} \alias{\%&\%,vector,diagonalMatrix-method} \alias{\%&\%,vector,indMatrix-method} \alias{\%&\%,vector,matrix-method} \alias{\%&\%,vector,pMatrix-method} \alias{\%&\%,vector,sparseVector-method} \alias{\%&\%,vector,vector-method} % \description{ For boolean or \dQuote{patter\bold{n}} matrices, i.e., \R objects of class \code{\linkS4class{nMatrix}}, it is natural to allow matrix products using boolean instead of numerical arithmetic. In package \pkg{Matrix}, we use the binary operator \code{\%&\%} (aka \dQuote{infix}) function) for this and provide methods for all our matrices and the traditional \R matrices (see \code{\link{matrix}}). } \section{Methods}{ We provide methods for both the \dQuote{traditional} (\R base) matrices and numeric vectors and conceptually all matrices and \code{\linkS4class{sparseVector}}s in package \pkg{Matrix}. \describe{ \item{\code{signature(x = "ANY", y = "ANY")}}{ } \item{\code{signature(x = "ANY", y = "Matrix")}}{ } \item{\code{signature(x = "Matrix", y = "ANY")}}{ } \item{\code{signature(x = "nMatrix", y = "nMatrix")}}{ } \item{\code{signature(x = "nMatrix", y = "nsparseMatrix")}}{ } \item{\code{signature(x = "nsparseMatrix", y = "nMatrix")}}{ } \item{\code{signature(x = "nsparseMatrix", y = "nsparseMatrix")}}{ } \item{\code{signature(x = "sparseVector", y = "sparseVector")}}{ } }% {describe} }% {Methods} \note{ These boolean arithmetic matrix products had been newly introduced for \pkg{Matrix} 1.2.0 (March 2015). Its implementation has still not been tested extensively. Originally, it was left unspecified how non-structural zeros, i.e., \code{0}'s as part of the \code{M@x} slot should be treated for numeric (\code{"\linkS4class{dMatrix}"}) and logical (\code{"\linkS4class{lMatrix}"}) sparse matrices. We now specify that boolean matrix products should behave as if applied to \code{\link{drop0}(M)}, i.e., as if dropping such zeros from the matrix before using it. \cr Equivalently, for all matrices \code{M}, boolean arithmetic should work as if applied to \code{M != 0} (or \code{M != FALSE}). The current implementation ends up coercing both \code{x} and \code{y} to (virtual) class \code{\linkS4class{nsparseMatrix}} which may be quite inefficient for dense matrices. A future implementation may well return a matrix with \bold{different} class, but the \dQuote{same} content, i.e., the same matrix entries \eqn{m_ij}{m[i,j]}. } \seealso{ \code{\link{\%*\%}}, \code{crossprod()}, or \code{\link{tcrossprod}()}, for (regular) matrix product methods. } \value{ a pattern matrix, i.e., inheriting from \code{"\linkS4class{nMatrix}"}, or an \code{"\linkS4class{ldiMatrix}"} in case of a diagonal matrix. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) } set.seed(7) L <- Matrix(rnorm(20) > 1, 4,5) (N <- as(L, "nMatrix")) L. <- L; L.[1:2,1] <- TRUE; L.@x[1:2] <- FALSE; L. # has "zeros" to drop0() D <- Matrix(round(rnorm(30)), 5,6) # -> values in -1:1 (for this seed) L \%&\% D stopifnot(identical(L \%&\% D, N \%&\% D), all(L \%&\% D == as((L \%*\% abs(D)) > 0, "sparseMatrix"))) ## cross products , possibly with boolArith = TRUE : crossprod(N) # -> sparse patter'n' (TRUE/FALSE : boolean arithmetic) crossprod(N +0) # -> numeric Matrix (with same "pattern") stopifnot(all(crossprod(N) == t(N) \%&\% N), identical(crossprod(N), crossprod(N +0, boolArith=TRUE)), identical(crossprod(L), crossprod(N , boolArith=FALSE))) crossprod(D, boolArith = TRUE) # pattern: "nsCMatrix" crossprod(L, boolArith = TRUE) # ditto crossprod(L, boolArith = FALSE) # numeric: "dsCMatrix" } Matrix/man/macros/0000755000175100001440000000000014576343415013607 5ustar hornikusersMatrix/man/macros/local.Rd0000644000175100001440000000126714520515200015154 0ustar hornikusers%% amsmath commands supported since 4.2.2 (PDF), 4.2.0 (HTML) %% unfortunately commands in #1 really do need 8 escapes ... \newcommand{\Seqn}{\ifelse{latex}{\Sexpr[results=rd]{if (getRversion() >= "4.2.2") "\\\\\\\\eqn{#1}" else "\\\\\\\\verb{#2}"}}{\ifelse{html}{\Sexpr[results=rd]{if (getRversion() >= "4.2.0") "\\\\\\\\eqn{#1}" else "\\\\\\\\verb{#2}"}}{\Sexpr[results=rd]{"\\\\\\\\eqn{#2}"}}}} \newcommand{\Sdeqn}{\ifelse{latex}{\Sexpr[results=rd]{if (getRversion() >= "4.2.2") "\\\\\\\\deqn{#1}" else "\\\\\\\\preformatted{#2}"}}{\ifelse{html}{\Sexpr[results=rd]{if (getRversion() >= "4.2.0") "\\\\\\\\deqn{#1}" else "\\\\\\\\preformatted{#2}"}}{\Sexpr[results=rd]{"\\\\\\\\deqn{#2}"}}}} Matrix/man/colSums-methods.Rd0000644000175100001440000001043014575137654015703 0ustar hornikusers\name{colSums-methods} \title{Form Row and Column Sums and Means} % \docType{methods} \keyword{algebra} \keyword{arith} \keyword{array} \keyword{methods} % \alias{colSums} \alias{colSums-methods} \alias{colMeans} \alias{colMeans-methods} \alias{rowSums} \alias{rowSums-methods} \alias{rowMeans} \alias{rowMeans-methods} % \alias{colSums,CsparseMatrix-method} \alias{colSums,RsparseMatrix-method} \alias{colSums,TsparseMatrix-method} \alias{colSums,denseMatrix-method} \alias{colSums,diagonalMatrix-method} \alias{colSums,indMatrix-method} % \alias{colMeans,CsparseMatrix-method} \alias{colMeans,RsparseMatrix-method} \alias{colMeans,TsparseMatrix-method} \alias{colMeans,denseMatrix-method} \alias{colMeans,diagonalMatrix-method} \alias{colMeans,indMatrix-method} % \alias{rowSums,CsparseMatrix-method} \alias{rowSums,RsparseMatrix-method} \alias{rowSums,TsparseMatrix-method} \alias{rowSums,denseMatrix-method} \alias{rowSums,diagonalMatrix-method} \alias{rowSums,indMatrix-method} % \alias{rowMeans,CsparseMatrix-method} \alias{rowMeans,RsparseMatrix-method} \alias{rowMeans,TsparseMatrix-method} \alias{rowMeans,denseMatrix-method} \alias{rowMeans,diagonalMatrix-method} \alias{rowMeans,indMatrix-method} % \description{ Form row and column sums and means for objects, for \code{\linkS4class{sparseMatrix}} the result may optionally be sparse (\code{\linkS4class{sparseVector}}), too. Row or column names are kept respectively as for \pkg{base} matrices and \code{\link{colSums}} methods, when the result is \code{\link{numeric}} vector. } \usage{ colSums(x, na.rm = FALSE, dims = 1L, \dots) rowSums(x, na.rm = FALSE, dims = 1L, \dots) colMeans(x, na.rm = FALSE, dims = 1L, \dots) rowMeans(x, na.rm = FALSE, dims = 1L, \dots) \S4method{colSums}{CsparseMatrix} (x, na.rm = FALSE, dims = 1L, sparseResult = FALSE, \dots) \S4method{rowSums}{CsparseMatrix} (x, na.rm = FALSE, dims = 1L, sparseResult = FALSE, \dots) \S4method{colMeans}{CsparseMatrix}(x, na.rm = FALSE, dims = 1L, sparseResult = FALSE, \dots) \S4method{rowMeans}{CsparseMatrix}(x, na.rm = FALSE, dims = 1L, sparseResult = FALSE, \dots) } \arguments{ \item{x}{a Matrix, i.e., inheriting from \code{\linkS4class{Matrix}}.} \item{na.rm}{logical. Should missing values (including \code{NaN}) be omitted from the calculations?} \item{dims}{completely ignored by the \code{Matrix} methods.} \item{\dots}{potentially further arguments, for method \code{<->} generic compatibility.} \item{sparseResult}{logical indicating if the result should be sparse, i.e., inheriting from class \code{\linkS4class{sparseVector}}. Only applicable when \code{x} is inheriting from a \code{\linkS4class{sparseMatrix}} class.} } % \details{ % ~~ If necessary, more details than the description above ~~ % } \value{ returns a numeric vector if \code{sparseResult} is \code{FALSE} as per default. Otherwise, returns a \code{\linkS4class{sparseVector}}. \code{\link{dimnames}(x)} are only kept (as \code{\link{names}(v)}) when the resulting \code{v} is \code{\link{numeric}}, since \code{\link{sparseVector}}s do not have names. } %\author{Martin} \seealso{\code{\link[base]{colSums}} and the \code{\linkS4class{sparseVector}} classes. } \examples{ (M <- bdiag(Diagonal(2), matrix(1:3, 3,4), diag(3:2))) # 7 x 8 colSums(M) d <- Diagonal(10, c(0,0,10,0,2,rep(0,5))) MM <- kronecker(d, M) dim(MM) # 70 80 length(MM@x) # 160, but many are '0' ; drop those: MM <- drop0(MM) length(MM@x) # 32 cm <- colSums(MM) (scm <- colSums(MM, sparseResult = TRUE)) stopifnot(is(scm, "sparseVector"), identical(cm, as.numeric(scm))) rowSums (MM, sparseResult = TRUE) # 14 of 70 are not zero colMeans(MM, sparseResult = TRUE) # 16 of 80 are not zero ## Since we have no 'NA's, these two are equivalent : stopifnot(identical(rowMeans(MM, sparseResult = TRUE), rowMeans(MM, sparseResult = TRUE, na.rm = TRUE)), rowMeans(Diagonal(16)) == 1/16, colSums(Diagonal(7)) == 1) ## dimnames(x) --> names( ) : dimnames(M) <- list(paste0("r", 1:7), paste0("V",1:8)) M colSums(M) rowMeans(M) ## Assertions : stopifnot(exprs = { all.equal(colSums(M), structure(c(1,1,6,6,6,6,3,2), names = colnames(M))) all.equal(rowMeans(M), structure(c(1,1,4,8,12,3,2)/8, names = paste0("r", 1:7))) }) } Matrix/man/CsparseMatrix-class.Rd0000644000175100001440000001150614500445405016472 0ustar hornikusers\name{CsparseMatrix-class} \title{Class "CsparseMatrix" of Sparse Matrices in Column-compressed Form} % \docType{class} \keyword{array} \keyword{classes} % \alias{CsparseMatrix-class} % \alias{Arith,CsparseMatrix,CsparseMatrix-method} \alias{Arith,CsparseMatrix,numeric-method} \alias{Arith,numeric,CsparseMatrix-method} \alias{Compare,CsparseMatrix,CsparseMatrix-method} \alias{Logic,CsparseMatrix,CsparseMatrix-method} \alias{coerce,matrix,CsparseMatrix-method} \alias{coerce,vector,CsparseMatrix-method} \alias{diag,CsparseMatrix-method} \alias{diag<-,CsparseMatrix-method} \alias{t,CsparseMatrix-method} % \alias{.validateCsparse} % \description{The \code{"CsparseMatrix"} class is the virtual class of all sparse matrices coded in sorted compressed column-oriented form. Since it is a virtual class, no objects may be created from it. See \code{showClass("CsparseMatrix")} for its subclasses. } \section{Slots}{ \describe{ \item{\code{i}:}{Object of class \code{"integer"} of length nnzero (number of non-zero elements). These are the \emph{0-based} row numbers for each non-zero element in the matrix, i.e., \code{i} must be in \code{0:(nrow(.)-1)}.} \item{\code{p}:}{\code{\link{integer}} vector for providing pointers, one for each column, to the initial (zero-based) index of elements in the column. \code{.@p} is of length \code{ncol(.) + 1}, with \code{p[1] == 0} and \code{p[length(p)] == nnzero}, such that in fact, \code{diff(.@p)} are the number of non-zero elements for each column. In other words, \code{m@p[1:ncol(m)]} contains the indices of those elements in \code{m@x} that are the first elements in the respective column of \code{m}. } \item{\code{Dim}, \code{Dimnames}:}{inherited from the superclass, see the \code{\linkS4class{sparseMatrix}} class.} } } \section{Extends}{ Class \code{"sparseMatrix"}, directly. Class \code{"Matrix"}, by class \code{"sparseMatrix"}. } \section{Methods}{ \describe{ matrix products \code{\link[=crossprod-methods]{\%*\%}}, \code{\link[=crossprod-methods]{crossprod}()} and \code{tcrossprod()}, several \code{\link{solve}} methods, and other matrix methods available: %% The following is generated by promptClass(..) -- %% FIXME: write a script that update all the *-class.Rd files \item{Arith}{\code{signature(e1 = "CsparseMatrix", e2 = "numeric")}: ... } \item{Arith}{\code{signature(e1 = "numeric", e2 = "CsparseMatrix")}: ... } \item{Math}{\code{signature(x = "CsparseMatrix")}: ... } \item{band}{\code{signature(x = "CsparseMatrix")}: ... } \item{-}{\code{signature(e1 = "CsparseMatrix", e2 = "numeric")}: ... } \item{-}{\code{signature(e1 = "numeric", e2 = "CsparseMatrix")}: ... } \item{+}{\code{signature(e1 = "CsparseMatrix", e2 = "numeric")}: ... } \item{+}{\code{signature(e1 = "numeric", e2 = "CsparseMatrix")}: ... } \item{coerce}{\code{signature(from = "CsparseMatrix", to = "TsparseMatrix")}: ... } \item{coerce}{\code{signature(from = "CsparseMatrix", to = "denseMatrix")}: ... } \item{coerce}{\code{signature(from = "CsparseMatrix", to = "matrix")}: ... } \item{coerce}{\code{signature(from = "TsparseMatrix", to = "CsparseMatrix")}: ... } \item{coerce}{\code{signature(from = "denseMatrix", to = "CsparseMatrix")}: ... } \item{diag}{\code{signature(x = "CsparseMatrix")}: ... } \item{gamma}{\code{signature(x = "CsparseMatrix")}: ... } \item{lgamma}{\code{signature(x = "CsparseMatrix")}: ... } \item{log}{\code{signature(x = "CsparseMatrix")}: ... } \item{t}{\code{signature(x = "CsparseMatrix")}: ... } \item{tril}{\code{signature(x = "CsparseMatrix")}: ... } \item{triu}{\code{signature(x = "CsparseMatrix")}: ... } } } \note{ All classes extending \code{CsparseMatrix} have a common validity (see \code{\link{validObject}}) check function. That function additionally checks the \code{i} slot for each column to contain increasing row numbers. \cr In earlier versions of \pkg{Matrix} (\code{<= 0.999375-16}), \code{\link{validObject}} automatically re-sorted the entries when necessary, and hence \code{new()} calls with somewhat permuted \code{i} and \code{x} slots worked, as \code{\link{new}(...)} (\emph{with} slot arguments) automatically checks the validity. Now, you have to use \code{\link{sparseMatrix}} to achieve the same functionality or know how to use \code{.validateCsparse()} to do so. } \seealso{ \code{\link{colSums}}, \code{\link{kronecker}}, and other such methods with own help pages. Further, the super class of \code{CsparseMatrix}, \code{\linkS4class{sparseMatrix}}, and, e.g., class \code{\linkS4class{dgCMatrix}} for the links to other classes. } \examples{ getClass("CsparseMatrix") ## The common validity check function (based on C code): getValidity(getClass("CsparseMatrix")) } Matrix/man/dsCMatrix-class.Rd0000644000175100001440000001151314461513642015606 0ustar hornikusers\name{dsCMatrix-class} \title{Numeric Symmetric Sparse (column compressed) Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{dsCMatrix-class} \alias{dsTMatrix-class} % \alias{Arith,dsCMatrix,dsCMatrix-method} \alias{determinant,dsCMatrix,logical-method} % \alias{determinant,dsTMatrix,logical-method} % \description{The \code{dsCMatrix} class is a class of symmetric, sparse numeric matrices in the compressed, \bold{c}olumn-oriented format. In this implementation the non-zero elements in the columns are sorted into increasing row order. The \code{dsTMatrix} class is the class of symmetric, sparse numeric matrices in \bold{t}riplet format. } \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("dsCMatrix", ...)} or \code{new("dsTMatrix", ...)}, or automatically via e.g., \code{as(*, "symmetricMatrix")}, or (for \code{dsCMatrix}) also from \code{\link{Matrix}(.)}. Creation \dQuote{from scratch} most efficiently happens via \code{\link{sparseMatrix}(*, symmetric=TRUE)}. } \section{Slots}{ \describe{ \item{\code{uplo}:}{A character object indicating if the upper triangle (\code{"U"}) or the lower triangle (\code{"L"}) is stored.} \item{\code{i}:}{Object of class \code{"integer"} of length nnZ (\emph{half} number of non-zero elements). These are the row numbers for each non-zero element in the lower triangle of the matrix.} \item{\code{p}:}{(only in class \code{"dsCMatrix"}:) an \code{\link{integer}} vector for providing pointers, one for each column, see the detailed description in \code{\linkS4class{CsparseMatrix}}.} \item{\code{j}:}{(only in class \code{"dsTMatrix"}:) Object of class \code{"integer"} of length nnZ (as \code{i}). These are the column numbers for each non-zero element in the lower triangle of the matrix.} \item{\code{x}:}{Object of class \code{"numeric"} of length nnZ -- the non-zero elements of the matrix (to be duplicated for full matrix).} \item{\code{factors}:}{Object of class \code{"list"} - a list of factorizations of the matrix. } \item{\code{Dim}:}{Object of class \code{"integer"} - the dimensions of the matrix - must be an integer vector with exactly two non-negative values.} } } \section{Extends}{ Both classes extend classes and \code{\linkS4class{symmetricMatrix}} \code{\linkS4class{dsparseMatrix}} directly; \code{dsCMatrix} further directly extends \code{\linkS4class{CsparseMatrix}}, where \code{dsTMatrix} does \code{\linkS4class{TsparseMatrix}}. } \section{Methods}{ \describe{ \item{solve}{\code{signature(a = "dsCMatrix", b = "....")}: \code{x <- solve(a,b)} solves \eqn{A x = b} for \eqn{x}; see \code{\link{solve-methods}}.} \item{chol}{\code{signature(x = "dsCMatrix", pivot = "logical")}: Returns (and stores) the Cholesky decomposition of \code{x}, see \code{\link{chol}}.} \item{Cholesky}{\code{signature(A = "dsCMatrix",...)}: Computes more flexibly Cholesky decompositions, see \code{\link{Cholesky}}.} \item{determinant}{\code{signature(x = "dsCMatrix", logarithm = "missing")}: Evaluate the determinant of \code{x} on the logarithm scale. This creates and stores the Cholesky factorization.} \item{determinant}{\code{signature(x = "dsCMatrix", logarithm = "logical")}: Evaluate the determinant of \code{x} on the logarithm scale or not, according to the \code{logarithm} argument. This creates and stores the Cholesky factorization.} \item{t}{\code{signature(x = "dsCMatrix")}: Transpose. As for all symmetric matrices, a matrix for which the upper triangle is stored produces a matrix for which the lower triangle is stored and vice versa, i.e., the \code{uplo} slot is swapped, and the row and column indices are interchanged.} \item{t}{\code{signature(x = "dsTMatrix")}: Transpose. The \code{uplo} slot is swapped from \code{"U"} to \code{"L"} or vice versa, as for a \code{"dsCMatrix"}, see above.} } } %\references{} %\author{} %\note{} \seealso{ Classes \code{\linkS4class{dgCMatrix}}, \code{\linkS4class{dgTMatrix}}, \code{\linkS4class{dgeMatrix}} and those mentioned above. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } mm <- Matrix(toeplitz(c(10, 0, 1, 0, 3)), sparse = TRUE) mm # automatically dsCMatrix str(mm) mT <- as(as(mm, "generalMatrix"), "TsparseMatrix") ## Either (symM <- as(mT, "symmetricMatrix")) # dsT (symC <- as(symM, "CsparseMatrix")) # dsC ## or sT <- Matrix(mT, sparse=TRUE, forceCheck=TRUE) # dsT sym2 <- as(symC, "TsparseMatrix") ## --> the same as 'symM', a "dsTMatrix" \dontshow{ stopifnot(identical(sT, symM), identical(sym2, symM), class(sym2) == "dsTMatrix", identical(sym2[1,], sT[1,]), identical(sym2[,2], sT[,2])) } } Matrix/man/KhatriRao.Rd0000644000175100001440000001056114435451016014470 0ustar hornikusers\name{KhatriRao} \title{Khatri-Rao Matrix Product} % \keyword{algebra} \keyword{arith} \keyword{array} \keyword{utilities} % \alias{KhatriRao} % \description{ Computes Khatri-Rao products for any kind of matrices. The Khatri-Rao product is a column-wise Kronecker product. Originally introduced by Khatri and Rao (1968), it has many different applications, see Liu and Trenkler (2008) for a survey. Notably, it is used in higher-dimensional tensor decompositions, see Bader and Kolda (2008). } \usage{ KhatriRao(X, Y = X, FUN = "*", sparseY = TRUE, make.dimnames = FALSE) } \arguments{ \item{X,Y}{matrices of with the same number of columns.} \item{FUN}{the (name of the) \code{\link{function}} to be used for the column-wise Kronecker products, see \code{\link{kronecker}}, defaulting to the usual multiplication.} \item{sparseY}{logical specifying if \code{Y} should be coerced and treated as \code{\linkS4class{sparseMatrix}}. Set this to \code{FALSE}, e.g., to distinguish structural zeros from zero entries.} \item{make.dimnames}{logical indicating if the result should inherit \code{\link{dimnames}} from \code{X} and \code{Y} in a simple way.} } %\details{} \value{ a \code{"\linkS4class{CsparseMatrix}"}, say \code{R}, the Khatri-Rao product of \code{X} (\eqn{n \times k}{n x k}) and \code{Y} (\eqn{m \times k}{m x k}), is of dimension \eqn{(n\cdot m) \times k}{(n*m) x k}, where the j-th column, \code{R[,j]} is the kronecker product \code{\link{kronecker}(X[,j], Y[,j])}. } \note{%% TODO? Could make it generic, and have dense and sparse methods The current implementation is efficient for large sparse matrices. } \references{ Khatri, C. G., and Rao, C. Radhakrishna (1968) Solutions to Some Functional Equations and Their Applications to Characterization of Probability Distributions. \emph{Sankhya: Indian J. Statistics, Series A} \bold{30}, 167--180. Bader, Brett W, and Tamara G Kolda (2008) Efficient MATLAB Computations with Sparse and Factored Tensors. \emph{SIAM J. Scientific Computing} \bold{30}, 205--231. } \author{ Original by Michael Cysouw, Univ. Marburg; minor tweaks, bug fixes etc, by Martin Maechler. } \seealso{ \code{\link{kronecker}}. } \examples{ ## Example with very small matrices: m <- matrix(1:12,3,4) d <- diag(1:4) KhatriRao(m,d) KhatriRao(d,m) dimnames(m) <- list(LETTERS[1:3], letters[1:4]) KhatriRao(m,d, make.dimnames=TRUE) KhatriRao(d,m, make.dimnames=TRUE) dimnames(d) <- list(NULL, paste0("D", 1:4)) KhatriRao(m,d, make.dimnames=TRUE) KhatriRao(d,m, make.dimnames=TRUE) dimnames(d) <- list(paste0("d", 10*1:4), paste0("D", 1:4)) (Kmd <- KhatriRao(m,d, make.dimnames=TRUE)) (Kdm <- KhatriRao(d,m, make.dimnames=TRUE)) nm <- as(m, "nsparseMatrix") nd <- as(d, "nsparseMatrix") KhatriRao(nm,nd, make.dimnames=TRUE) KhatriRao(nd,nm, make.dimnames=TRUE) stopifnot(dim(KhatriRao(m,d)) == c(nrow(m)*nrow(d), ncol(d))) ## border cases / checks: zm <- nm; zm[] <- FALSE # all FALSE matrix stopifnot(all(K1 <- KhatriRao(nd, zm) == 0), identical(dim(K1), c(12L, 4L)), all(K2 <- KhatriRao(zm, nd) == 0), identical(dim(K2), c(12L, 4L))) d0 <- d; d0[] <- 0; m0 <- Matrix(d0[-1,]) stopifnot(all(K3 <- KhatriRao(d0, m) == 0), identical(dim(K3), dim(Kdm)), all(K4 <- KhatriRao(m, d0) == 0), identical(dim(K4), dim(Kmd)), all(KhatriRao(d0, d0) == 0), all(KhatriRao(m0, d0) == 0), all(KhatriRao(d0, m0) == 0), all(KhatriRao(m0, m0) == 0), identical(dimnames(KhatriRao(m, d0, make.dimnames=TRUE)), dimnames(Kmd))) ## a matrix with "structural" and non-structural zeros: m01 <- new("dgCMatrix", i = c(0L, 2L, 0L, 1L), p = c(0L, 0L, 0L, 2L, 4L), Dim = 3:4, x = c(1, 0, 1, 0)) D4 <- Diagonal(4, x=1:4) # "as" d DU <- Diagonal(4)# unit-diagonal: uplo="U" (K5 <- KhatriRao( d, m01)) K5d <- KhatriRao( d, m01, sparseY=FALSE) K5Dd <- KhatriRao(D4, m01, sparseY=FALSE) K5Ud <- KhatriRao(DU, m01, sparseY=FALSE) (K6 <- KhatriRao(diag(3), t(m01))) K6D <- KhatriRao(Diagonal(3), t(m01)) K6d <- KhatriRao(diag(3), t(m01), sparseY=FALSE) K6Dd <- KhatriRao(Diagonal(3), t(m01), sparseY=FALSE) stopifnot(exprs = { all(K5 == K5d) identical(cbind(c(7L, 10L), c(3L, 4L)), which(K5 != 0, arr.ind = TRUE, useNames=FALSE)) identical(K5d, K5Dd) identical(K6, K6D) all(K6 == K6d) identical(cbind(3:4, 1L), which(K6 != 0, arr.ind = TRUE, useNames=FALSE)) identical(K6d, K6Dd) }) } Matrix/man/nsparseMatrix-class.Rd0000644000175100001440000001341314575324114016551 0ustar hornikusers\name{nsparseMatrix-class} \title{Sparse "pattern" Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{nsparseMatrix-class} \alias{nsparseMatrix-classes} % used by package 'arules' \alias{ngCMatrix-class} \alias{ngRMatrix-class} \alias{ngTMatrix-class} \alias{ntCMatrix-class} \alias{ntRMatrix-class} \alias{ntTMatrix-class} \alias{nsCMatrix-class} \alias{nsRMatrix-class} \alias{nsTMatrix-class} % nsparse \alias{!,nsparseMatrix-method} \alias{-,nsparseMatrix,missing-method} \alias{Arith,nsparseMatrix,Matrix-method} \alias{Arith,dsparseMatrix,nsparseMatrix-method} \alias{Arith,lsparseMatrix,nsparseMatrix-method} \alias{Arith,nsparseMatrix,dsparseMatrix-method} \alias{Arith,nsparseMatrix,lsparseMatrix-method} \alias{Ops,nsparseMatrix,dsparseMatrix-method} \alias{Ops,nsparseMatrix,lsparseMatrix-method} \alias{Ops,nsparseMatrix,sparseMatrix-method} \alias{coerce,matrix,nsparseMatrix-method} \alias{coerce,nsparseMatrix,indMatrix-method} \alias{coerce,nsparseMatrix,pMatrix-method} \alias{coerce,vector,nsparseMatrix-method} \alias{which,nsparseMatrix-method} % ngC % ngR % ngT % ntC % ntR % ntT % nsC % nsR % nsT % \description{The \code{nsparseMatrix} class is a virtual class of sparse \emph{\dQuote{pattern}} matrices, i.e., binary matrices conceptually with \code{TRUE}/\code{FALSE} entries. Only the positions of the elements that are \code{TRUE} are stored. These can be stored in the \dQuote{triplet} form (\code{\linkS4class{TsparseMatrix}}, subclasses \code{ngTMatrix}, \code{nsTMatrix}, and \code{ntTMatrix} which really contain pairs, not triplets) or in compressed column-oriented form (class \code{\linkS4class{CsparseMatrix}}, subclasses \code{ngCMatrix}, \code{nsCMatrix}, and \code{ntCMatrix}) or--\emph{rarely}--in compressed row-oriented form (class \code{\linkS4class{RsparseMatrix}}, subclasses \code{ngRMatrix}, \code{nsRMatrix}, and \code{ntRMatrix}). The second letter in the name of these non-virtual classes indicates \code{g}eneral, \code{s}ymmetric, or \code{t}riangular. } \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("ngCMatrix", ...)} and so on. More frequently objects are created by coercion of a numeric sparse matrix to the pattern form for use in the symbolic analysis phase of an algorithm involving sparse matrices. Such algorithms often involve two phases: a symbolic phase wherein the positions of the non-zeros in the result are determined and a numeric phase wherein the actual results are calculated. During the symbolic phase only the positions of the non-zero elements in any operands are of interest, hence numeric sparse matrices can be treated as sparse pattern matrices. } \section{Slots}{ \describe{ \item{\code{uplo}:}{Object of class \code{"character"}. Must be either "U", for upper triangular, and "L", for lower triangular. Present in the triangular and symmetric classes but not in the general class.} \item{\code{diag}:}{Object of class \code{"character"}. Must be either \code{"U"}, for unit triangular (diagonal is all ones), or \code{"N"} for non-unit. The implicit diagonal elements are not explicitly stored when \code{diag} is \code{"U"}. Present in the triangular classes only.} \item{\code{p}:}{Object of class \code{"integer"} of pointers, one for each column (row), to the initial (zero-based) index of elements in the column. Present in compressed column-oriented and compressed row-oriented forms only.} \item{\code{i}:}{Object of class \code{"integer"} of length nnzero (number of non-zero elements). These are the row numbers for each TRUE element in the matrix. All other elements are FALSE. Present in triplet and compressed column-oriented forms only.} \item{\code{j}:}{Object of class \code{"integer"} of length nnzero (number of non-zero elements). These are the column numbers for each TRUE element in the matrix. All other elements are FALSE. Present in triplet and compressed row-oriented forms only.} \item{\code{Dim}:}{Object of class \code{"integer"} - the dimensions of the matrix.} } } \section{Methods}{ \describe{ \item{coerce}{\code{signature(from = "dgCMatrix", to = "ngCMatrix")}, and many similar ones; typically you should coerce to \code{"nsparseMatrix"} (or \code{"nMatrix"}). Note that coercion to a sparse pattern matrix records all the potential non-zero entries, i.e., explicit (\dQuote{non-structural}) zeroes are coerced to \code{TRUE}, not \code{FALSE}, see the example. } \item{t}{\code{signature(x = "ngCMatrix")}: returns the transpose of \code{x}} \item{which}{\code{signature(x = "lsparseMatrix")}, semantically equivalent to \pkg{base} function \code{\link{which}(x, arr.ind)}; for details, see the \code{\linkS4class{lMatrix}} class documentation.} } } %\references{} %\author{} %\note{} \seealso{ the class \code{\linkS4class{dgCMatrix}} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } (m <- Matrix(c(0,0,2:0), 3,5, dimnames=list(LETTERS[1:3],NULL))) ## ``extract the nonzero-pattern of (m) into an nMatrix'': nm <- as(m, "nsparseMatrix") ## -> will be a "ngCMatrix" str(nm) # no 'x' slot nnm <- !nm # no longer sparse ## consistency check: stopifnot(xor(as( nm, "matrix"), as(nnm, "matrix"))) ## low-level way of adding "non-structural zeros" : nnm <- as(nnm, "lsparseMatrix") # "lgCMatrix" nnm@x[2:4] <- c(FALSE, NA, NA) nnm as(nnm, "nMatrix") # NAs *and* non-structural 0 |---> 'TRUE' data(KNex, package = "Matrix") nmm <- as(KNex $ mm, "nMatrix") str(xlx <- crossprod(nmm))# "nsCMatrix" stopifnot(isSymmetric(xlx)) image(xlx, main=paste("crossprod(nmm) : Sparse", class(xlx))) } Matrix/man/rsparsematrix.Rd0000644000175100001440000000623114446607050015512 0ustar hornikusers\name{rsparsematrix} \title{Random Sparse Matrix} % \keyword{array} \keyword{distribution} \keyword{utilities} % \alias{rsparsematrix} % \description{ Generate a random sparse matrix efficiently. The default has rounded gaussian non-zero entries, and \code{rand.x = NULL} generates random patter\bold{n} matrices, i.e. inheriting from \code{\linkS4class{nsparseMatrix}}. } \usage{ rsparsematrix(nrow, ncol, density, nnz = round(density * maxE), symmetric = FALSE, rand.x = function(n) signif(rnorm(n), 2), \dots) } \arguments{ \item{nrow, ncol}{number of rows and columns, i.e., the matrix dimension (\code{\link{dim}}).} \item{density}{optional number in \eqn{[0,1]}, the density is the proportion of non-zero entries among all matrix entries. If specified it determines the default for \code{nnz}, otherwise \code{nnz} needs to be specified.} \item{nnz}{number of non-zero entries, for a sparse matrix typically considerably smaller than \code{nrow*ncol}. Must be specified if \code{density} is not.} \item{symmetric}{logical indicating if result should be a matrix of class \code{\linkS4class{symmetricMatrix}}. Note that in the symmetric case, \code{nnz} denotes the number of non zero entries of the upper (or lower) part of the matrix, including the diagonal.} \item{rand.x}{\code{\link{NULL}} or the random number generator for the \code{x} slot, a \code{\link{function}} such that \code{rand.x(n)} generates a numeric vector of length \code{n}. Typical examples are \code{rand.x = rnorm}, or \code{rand.x = runif}; the default is nice for didactical purposes.} \item{\dots}{optionally further arguments passed to \code{\link{sparseMatrix}()}, notably \code{repr}.} } \details{ The algorithm first samples \dQuote{encoded} \eqn{(i,j)}s without replacement, via one dimensional indices, if not \code{symmetric} \code{\link{sample.int}(nrow*ncol, nnz)}, then---if \code{rand.x} is not \code{NULL}---gets \code{x <- rand.x(nnz)} and calls \code{\link{sparseMatrix}(i=i, j=j, x=x, ..)}. When \code{rand.x=NULL}, \code{\link{sparseMatrix}(i=i, j=j, ..)} will return a patter\bold{n} matrix (i.e., inheriting from \code{\linkS4class{nsparseMatrix}}). } \value{ a \code{\linkS4class{sparseMatrix}}, say \code{M} of dimension (nrow, ncol), i.e., with \code{dim(M) == c(nrow, ncol)}, if \code{symmetric} is not true, with \code{nzM <- \link{nnzero}(M)} fulfilling \code{nzM <= nnz} and typically, \code{nzM == nnz}. } \author{Martin Maechler} \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) } set.seed(17)# to be reproducible M <- rsparsematrix(8, 12, nnz = 30) # small example, not very sparse M M1 <- rsparsematrix(1000, 20, nnz = 123, rand.x = runif) summary(M1) ## a random *symmetric* Matrix (S9 <- rsparsematrix(9, 9, nnz = 10, symmetric=TRUE)) # dsCMatrix nnzero(S9)# ~ 20: as 'nnz' only counts one "triangle" ## a random patter*n* aka boolean Matrix (no 'x' slot): (n7 <- rsparsematrix(5, 12, nnz = 10, rand.x = NULL)) ## a [T]riplet representation sparseMatrix: T2 <- rsparsematrix(40, 12, nnz = 99, repr = "T") head(T2) } Matrix/man/Matrix-defunct.Rd0000644000175100001440000000172714576343374015517 0ustar hornikusers\name{Matrix-defunct} \title{Defunct Functions in Package \pkg{Matrix}} \alias{Matrix-defunct} % \alias{cBind} \alias{rBind} % \description{ The functions or variables listed here are no longer part of \pkg{Matrix} as they are no longer needed. } \usage{ ## Defunct in 1.3-3 rBind(..., deparse.level = 1) cBind(..., deparse.level = 1) } \details{ These either are stubs reporting that they are defunct, or have been removed completely (apart from being documented here). \code{rBind} and \code{cBind} were provided for \R{} versions older than 3.2.0 as substitutes for the \pkg{base} analogues \code{rbind} and \code{cbind}, which at that time were not \dQuote{S4-aware} and so could not be used to vertically or horizontally concatenate \code{"\linkS4class{Matrix}"} objects together with traditional matrices and vectors. } \seealso{ \code{\link{Defunct}}, \code{\link{base-defunct}}, \code{\link{Matrix-deprecated}} } \keyword{internal} \keyword{misc} Matrix/man/spMatrix.Rd0000644000175100001440000000572714467047212014427 0ustar hornikusers\name{spMatrix} \title{Sparse Matrix Constructor From Triplet} % \keyword{array} \keyword{utilities} % \alias{spMatrix} % \description{ User friendly construction of a sparse matrix (inheriting from class \code{\linkS4class{TsparseMatrix}}) from the triplet representation. This is much less flexible than \code{\link{sparseMatrix}()} and hence somewhat \emph{deprecated}. } \usage{ spMatrix(nrow, ncol, i = integer(0L), j = integer(0L), x = double(0L)) } \arguments{ \item{nrow, ncol}{integers specifying the desired number of rows and columns.} \item{i,j}{integer vectors of the same length specifying the locations of the non-zero (or non-\code{TRUE}) entries of the matrix.} \item{x}{atomic vector of the same length as \code{i} and \code{j}, specifying the values of the non-zero entries.} } \value{ A sparse matrix in triplet form, as an \R object inheriting from both \code{\linkS4class{TsparseMatrix}} and \code{\linkS4class{generalMatrix}}. The matrix \eqn{M} will have \code{M[i[k], j[k]] == x[k]}, for \eqn{k = 1,2,\ldots, n}, where \code{n = length(i)} and \code{M[ i', j' ] == 0} for all other pairs \eqn{(i',j')}. } \seealso{\code{\link{Matrix}(*, sparse=TRUE)} for the more usual constructor of such matrices. Then, \code{\link{sparseMatrix}} is more general and flexible than \code{spMatrix()} and by default returns a \code{\linkS4class{CsparseMatrix}} which is often slightly more desirable. Further, \code{\link{bdiag}} and \code{\link{Diagonal}} for (block-)diagonal matrix constructors. Consider \code{\linkS4class{TsparseMatrix}} and similar class definition help files. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } ## simple example A <- spMatrix(10,20, i = c(1,3:8), j = c(2,9,6:10), x = 7 * (1:7)) A # a "dgTMatrix" summary(A) str(A) # note that *internally* 0-based indices (i,j) are used L <- spMatrix(9, 30, i = rep(1:9, 3), 1:27, (1:27) \%\% 4 != 1) L # an "lgTMatrix" ## A simplified predecessor of Matrix' rsparsematrix() function : rSpMatrix <- function(nrow, ncol, nnz, rand.x = function(n) round(rnorm(nnz), 2)) { ## Purpose: random sparse matrix ## -------------------------------------------------------------- ## Arguments: (nrow,ncol): dimension ## nnz : number of non-zero entries ## rand.x: random number generator for 'x' slot ## -------------------------------------------------------------- ## Author: Martin Maechler, Date: 14.-16. May 2007 stopifnot((nnz <- as.integer(nnz)) >= 0, nrow >= 0, ncol >= 0, nnz <= nrow * ncol) spMatrix(nrow, ncol, i = sample(nrow, nnz, replace = TRUE), j = sample(ncol, nnz, replace = TRUE), x = rand.x(nnz)) } M1 <- rSpMatrix(100000, 20, nnz = 200) summary(M1) } Matrix/man/is.na-methods.Rd0000644000175100001440000000553314473267633015274 0ustar hornikusers\name{is.na-methods} \title{is.na(), is.finite() Methods for 'Matrix' Objects} % \docType{methods} \keyword{NA} \keyword{math} \keyword{programming} \keyword{methods} % \alias{anyNA} \alias{anyNA-methods} \alias{is.na} \alias{is.na-methods} \alias{is.nan} \alias{is.nan-methods} \alias{is.infinite} \alias{is.infinite-methods} \alias{is.finite} \alias{is.finite-methods} % \alias{anyNA,denseMatrix-method} \alias{anyNA,diagonalMatrix-method} \alias{anyNA,indMatrix-method} \alias{anyNA,sparseMatrix-method} \alias{anyNA,sparseVector-method} % \alias{is.na,abIndex-method} \alias{is.na,denseMatrix-method} \alias{is.na,diagonalMatrix-method} \alias{is.na,indMatrix-method} \alias{is.na,sparseMatrix-method} \alias{is.na,sparseVector-method} % \alias{is.nan,denseMatrix-method} \alias{is.nan,diagonalMatrix-method} \alias{is.nan,indMatrix-method} \alias{is.nan,sparseMatrix-method} \alias{is.nan,sparseVector-method} % \alias{is.infinite,abIndex-method} \alias{is.infinite,denseMatrix-method} \alias{is.infinite,diagonalMatrix-method} \alias{is.infinite,indMatrix-method} \alias{is.infinite,sparseMatrix-method} \alias{is.infinite,sparseVector-method} % \alias{is.finite,abIndex-method} \alias{is.finite,denseMatrix-method} \alias{is.finite,diagonalMatrix-method} \alias{is.finite,indMatrix-method} \alias{is.finite,sparseMatrix-method} \alias{is.finite,sparseVector-method} % \description{ Methods for generic functions \code{\link{anyNA}()}, \code{\link{is.na}()}, \code{\link{is.nan}()}, \code{\link{is.infinite}()}, and \code{\link{is.finite}()}, for objects inheriting from virtual class \code{\linkS4class{Matrix}} or \code{\linkS4class{sparseVector}}. } \usage{ \S4method{is.na}{denseMatrix}(x) \S4method{is.na}{sparseMatrix}(x) \S4method{is.na}{diagonalMatrix}(x) \S4method{is.na}{indMatrix}(x) \S4method{is.na}{sparseVector}(x) ## ... ## and likewise for anyNA, is.nan, is.infinite, is.finite } \arguments{ \item{x}{an \R object, here a sparse or dense matrix or vector.} } \value{ For \code{is.*()}, an \code{\linkS4class{nMatrix}} or \code{\linkS4class{nsparseVector}} matching the dimensions of \code{x} and specifying the positions in \code{x} of (some subset of) \code{\link{NA}}, \code{\link{NaN}}, \code{\link{Inf}}, and \code{-Inf}. For \code{anyNA}(), \code{TRUE} if \code{x} contains \code{NA} or \code{NaN} and \code{FALSE} otherwise. } \seealso{ \code{\link{NA}}, \code{\link{NaN}}, \code{\link{Inf}} } \examples{ (M <- Matrix(1:6, nrow = 4, ncol = 3, dimnames = list(letters[1:4], LETTERS[1:3]))) stopifnot(!anyNA(M), !any(is.na(M))) M[2:3, 2] <- NA (inM <- is.na(M)) stopifnot(anyNA(M), sum(inM) == 2) (A <- spMatrix(nrow = 10, ncol = 20, i = c(1, 3:8), j = c(2, 9, 6:10), x = 7 * (1:7))) stopifnot(!anyNA(A), !any(is.na(A))) A[2, 3] <- A[1, 2] <- A[5, 5:9] <- NA (inA <- is.na(A)) stopifnot(anyNA(A), sum(inA) == 1 + 1 + 5) } Matrix/man/symmpart-methods.Rd0000644000175100001440000000505614575137654016142 0ustar hornikusers\name{symmpart-methods} \title{Symmetric Part and Skew(symmetric) Part of a Matrix} % \docType{methods} \keyword{algebra} \keyword{arith} \keyword{array} \keyword{methods} % \alias{symmpart} \alias{symmpart-methods} \alias{skewpart} \alias{skewpart-methods} % \alias{symmpart,CsparseMatrix-method} \alias{symmpart,RsparseMatrix-method} \alias{symmpart,TsparseMatrix-method} \alias{symmpart,denseMatrix-method} \alias{symmpart,diagonalMatrix-method} \alias{symmpart,indMatrix-method} \alias{symmpart,matrix-method} % \alias{skewpart,CsparseMatrix-method} \alias{skewpart,RsparseMatrix-method} \alias{skewpart,TsparseMatrix-method} \alias{skewpart,denseMatrix-method} \alias{skewpart,diagonalMatrix-method} \alias{skewpart,indMatrix-method} \alias{skewpart,matrix-method} % \description{ \code{symmpart(x)} computes the symmetric part \code{(x + t(x))/2} and \code{skewpart(x)} the skew symmetric part \code{(x - t(x))/2} of a square matrix \code{x}, more efficiently for specific Matrix classes. Note that \code{x == symmpart(x) + skewpart(x)} for all square matrices -- apart from extraneous \code{\link{NA}} values in the RHS. } \usage{ symmpart(x) skewpart(x) } \arguments{ \item{x}{a \emph{square} matrix; either \dQuote{traditional} of class \code{"matrix"}, or typically, inheriting from the \code{\linkS4class{Matrix}} class.} } \details{ These are generic functions with several methods for different matrix classes, use e.g., \code{\link{showMethods}(symmpart)} to see them. If the row and column names differ, the result will use the column names unless they are (partly) \code{NULL} where the row names are non-\code{NULL} (see also the examples). } \value{ \code{symmpart(x)} returns a symmetric matrix, inheriting from \code{\linkS4class{symmetricMatrix}} or \code{\linkS4class{diagonalMatrix}} if \code{x} inherits from \code{Matrix}. \code{skewpart(x)} returns a skew-symmetric matrix, inheriting from \code{\linkS4class{generalMatrix}}, \code{\linkS4class{symmetricMatrix}} or \code{\linkS4class{diagonalMatrix}} if \code{x} inherits from \code{Matrix}. } \seealso{\code{\link{isSymmetric}}.} \examples{ m <- Matrix(1:4, 2,2) symmpart(m) skewpart(m) stopifnot(all(m == symmpart(m) + skewpart(m))) dn <- dimnames(m) <- list(row = c("r1", "r2"), col = c("var.1", "var.2")) stopifnot(all(m == symmpart(m) + skewpart(m))) colnames(m) <- NULL stopifnot(all(m == symmpart(m) + skewpart(m))) dimnames(m) <- unname(dn) stopifnot(all(m == symmpart(m) + skewpart(m))) ## investigate the current methods: showMethods(skewpart, include = TRUE) } Matrix/man/generalMatrix-class.Rd0000644000175100001440000000256714575137654016536 0ustar hornikusers\name{generalMatrix-class} \title{Class "generalMatrix" of General Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{generalMatrix-class} % \alias{coerce,generalMatrix,packedMatrix-method} \alias{coerce,matrix,generalMatrix-method} \alias{coerce,vector,generalMatrix-method} \alias{dimnames<-,generalMatrix,NULL-method} \alias{dimnames<-,generalMatrix,list-method} % \description{ Virtual class of \dQuote{general} matrices; i.e., matrices that do not have a known property such as symmetric, triangular, or diagonal. } \section{Objects from the Class}{A virtual Class: No objects may be created from it.} \section{Slots}{ \describe{ \item{\code{Dim, Dimnames}}{inherited from virtual class \code{\linkS4class{Matrix}}.} \item{\code{factors}}{a list of \code{\linkS4class{MatrixFactorization}} objects caching factorizations of the matrix. Typically, it is initialized as an empty list and updated \dQuote{automagically} whenever a factorization is computed.} } } \section{Extends}{ Class \code{"Matrix"}, directly. } % \section{Methods}{ % No methods defined with class "generalMatrix" in the signature. % } \seealso{ Virtual classes \code{\linkS4class{symmetricMatrix}}, \code{\linkS4class{triangularMatrix}}, and \code{\linkS4class{diagonalMatrix}}. } % \examples{ % ##---- Should be DIRECTLY executable !! ---- % } Matrix/man/packedMatrix-class.Rd0000644000175100001440000000407014574651323016330 0ustar hornikusers\name{packedMatrix-class} \title{Virtual Class \code{"packedMatrix"} of Packed Dense Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{packedMatrix-class} % \alias{coerce,matrix,packedMatrix-method} \alias{cov2cor,packedMatrix-method} % \description{ Class \code{"packedMatrix"} is the \emph{virtual} class of dense symmetric or triangular matrices in "packed" format, storing only the \code{choose(n+1,2) == n*(n+1)/2} elements of the upper or lower triangle of an \code{n}-by-\code{n} matrix. It is used to define common methods for efficient subsetting, transposing, etc. of its \emph{proper} subclasses: currently \code{"[dln]spMatrix"} (packed symmetric), \code{"[dln]tpMatrix"} (packed triangular), and subclasses of these, such as \code{"\linkS4class{dppMatrix}"}. } \section{Slots}{ \describe{ \item{\code{uplo}:}{\code{"character"}; either "U", for upper triangular, and "L", for lower.} \item{\code{Dim}, \code{Dimnames}:}{as all \code{\linkS4class{Matrix}} objects.} } } \section{Extends}{ Class \code{"\linkS4class{denseMatrix}"}, directly. Class \code{"\linkS4class{Matrix}"}, by class \code{"denseMatrix"}, distance 2. } \section{Methods}{ \describe{ \item{pack}{\code{signature(x = "packedMatrix")}: ... } \item{unpack}{\code{signature(x = "packedMatrix")}: ... } \item{isSymmetric}{\code{signature(object = "packedMatrix")}: ... } \item{isTriangular}{\code{signature(object = "packedMatrix")}: ... } \item{isDiagonal}{\code{signature(object = "packedMatrix")}: ... } \item{t}{\code{signature(x = "packedMatrix")}: ... } \item{diag}{\code{signature(x = "packedMatrix")}: ... } \item{diag<-}{\code{signature(x = "packedMatrix")}: ... } } } %% \references{ %% } \author{Mikael Jagan} %% \note{ %% } \seealso{ \code{\link{pack}} and \code{\link{unpack}}; its virtual "complement" \code{"\linkS4class{unpackedMatrix}"}; its proper subclasses \code{"\linkS4class{dspMatrix}"}, \code{"\linkS4class{ltpMatrix}"}, etc. } \examples{ showClass("packedMatrix") showMethods(classes = "packedMatrix") } Matrix/man/is.null.DN.Rd0000644000175100001440000000407314446607050014474 0ustar hornikusers\name{is.null.DN} \title{Are the Dimnames \code{dn} NULL-like ?} % \keyword{array} \keyword{attribute} \keyword{programming} \keyword{utilities} % \alias{is.null.DN} % \description{ Are the \code{\link{dimnames}} \code{dn} \code{\link{NULL}}-like? \code{is.null.DN(dn)} is less strict than \code{\link{is.null}(dn)}, because it is also true (\code{\link{TRUE}}) when the dimnames \code{dn} are \dQuote{like} \code{NULL}, or \code{list(NULL,NULL)}, as they can easily be for the traditional \R matrices (\code{\link{matrix}}) which have no formal \code{\link{class}} definition, and hence much freedom in how their \code{\link{dimnames}} look like. } \usage{ is.null.DN(dn) } \arguments{ \item{dn}{\code{\link{dimnames}()} of a \code{\link{matrix}}-like \R object. } } \note{ This function is really to be used on \dQuote{traditional} matrices rather than those inheriting from \code{\linkS4class{Matrix}}, as the latter will always have dimnames \code{list(NULL,NULL)} exactly, in such a case. } \value{ \code{\link{logical}} \code{\link{TRUE}} or \code{\link{FALSE}}. } %% \details{ %% } \author{Martin Maechler} \seealso{ \code{\link{is.null}}, \code{\link{dimnames}}, \code{\link{matrix}}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } m1 <- m2 <- m3 <- m4 <- m <- matrix(round(100 * rnorm(6)), 2, 3) dimnames(m1) <- list(NULL, NULL) dimnames(m2) <- list(NULL, character()) dimnames(m3) <- rev(dimnames(m2)) dimnames(m4) <- rep(list(character()),2) m4 # prints absolutely identically to m c.o <- capture.output cm <- c.o(m) stopifnot(exprs = { m == m1; m == m2; m == m3; m == m4 identical(cm, c.o(m1)); identical(cm, c.o(m2)) identical(cm, c.o(m3)); identical(cm, c.o(m4)) }) hasNoDimnames <- function(.) is.null.DN(dimnames(.)) stopifnot(exprs = { hasNoDimnames(m) hasNoDimnames(m1); hasNoDimnames(m2) hasNoDimnames(m3); hasNoDimnames(m4) hasNoDimnames(Matrix(m) -> M) hasNoDimnames(as(M, "sparseMatrix")) }) } Matrix/man/RsparseMatrix-class.Rd0000644000175100001440000000416514467224234016523 0ustar hornikusers\name{RsparseMatrix-class} \title{Class "RsparseMatrix" of Sparse Matrices in Row-compressed Form} % \docType{class} \keyword{array} \keyword{classes} % \alias{RsparseMatrix-class} % \alias{coerce,matrix,RsparseMatrix-method} \alias{coerce,vector,RsparseMatrix-method} \alias{diag,RsparseMatrix-method} \alias{diag<-,RsparseMatrix-method} \alias{t,RsparseMatrix-method} % \description{The \code{"RsparseMatrix"} class is the virtual class of all sparse matrices coded in sorted compressed row-oriented form. Since it is a virtual class, no objects may be created from it. See \code{showClass("RsparseMatrix")} for its subclasses. } \section{Slots}{ \describe{ \item{\code{j}:}{Object of class \code{"integer"} of length \code{nnzero} (number of non-zero elements). These are the row numbers for each non-zero element in the matrix.} \item{\code{p}:}{Object of class \code{"integer"} of pointers, one for each row, to the initial (zero-based) index of elements in the row.} \item{\code{Dim}, \code{Dimnames}:}{inherited from the superclass, see \code{\linkS4class{sparseMatrix}}.} } } \section{Extends}{ Class \code{"sparseMatrix"}, directly. Class \code{"Matrix"}, by class \code{"sparseMatrix"}. } \section{Methods}{ Originally, \bold{few} methods were defined on purpose, as we rather use the \code{\linkS4class{CsparseMatrix}} in \pkg{Matrix}. Then, more methods were added but \emph{beware} that these typically do \emph{not} return \code{"RsparseMatrix"} results, but rather Csparse* or Tsparse* ones; e.g., \code{R[i, j] <- v} for an \code{"RsparseMatrix"} \code{R} works, but after the assignment, \code{R} is a (triplet) \code{"TsparseMatrix"}. \describe{ \item{t}{\code{signature(x = "RsparseMatrix")}: ... } \item{coerce}{\code{signature(from = "RsparseMatrix", to = "CsparseMatrix")}: ... } \item{coerce}{\code{signature(from = "RsparseMatrix", to = "TsparseMatrix")}: ... } } } \seealso{ its superclass, \code{\linkS4class{sparseMatrix}}, and, e.g., class \code{\linkS4class{dgRMatrix}} for the links to other classes. } \examples{ showClass("RsparseMatrix") } Matrix/man/rankMatrix.Rd0000644000175100001440000002103614516234475014733 0ustar hornikusers\name{rankMatrix} \title{Rank of a Matrix} % \keyword{algebra} \keyword{utilities} % \alias{rankMatrix} \alias{qr2rankMatrix} % \description{ Compute \sQuote{the} matrix rank, a well-defined functional in theory(*), somewhat ambiguous in practice. We provide several methods, the default corresponding to Matlab's definition. (*) The rank of a \eqn{n \times m}{n x m} matrix \eqn{A}, \eqn{rk(A)}, is the maximal number of linearly independent columns (or rows); hence \eqn{rk(A) \le min(n,m)}{rk(A) <= min(n,m)}. } \usage{ rankMatrix(x, tol = NULL, method = c("tolNorm2", "qr.R", "qrLINPACK", "qr", "useGrad", "maybeGrad"), sval = svd(x, 0, 0)$d, warn.t = TRUE, warn.qr = TRUE) qr2rankMatrix(qr, tol = NULL, isBqr = is.qr(qr), do.warn = TRUE) } \arguments{ \item{x}{numeric matrix, of dimension \eqn{n \times m}{n x m}, say.} \item{tol}{nonnegative number specifying a (relative, \dQuote{scalefree}) tolerance for testing of \dQuote{practically zero} with specific meaning depending on \code{method}; by default, \code{max(dim(x)) * \link{.Machine}$double.eps} is according to Matlab's default (for its only method which is our \code{method="tolNorm2"}).} \item{method}{a character string specifying the computational method for the rank, can be abbreviated: \describe{ \item{\code{"tolNorm2"}:}{the number of singular values \code{>= tol * max(sval)};} \item{\code{"qrLINPACK"}:}{for a dense matrix, this is the rank of \code{\link[base]{qr}(x, tol, LAPACK=FALSE)} (which is \code{qr(...)$rank}); \cr This ("qr*", dense) version used to be \emph{the} recommended way to compute a matrix rank for a while in the past. For sparse \code{x}, this is equivalent to \code{"qr.R"}. } \item{\code{"qr.R"}:}{this is the rank of triangular matrix \eqn{R}, where \code{qr()} uses LAPACK or a "sparseQR" method (see \code{\link{qr-methods}}) to compute the decomposition \eqn{QR}. The rank of \eqn{R} is then defined as the number of \dQuote{non-zero} diagonal entries \eqn{d_i} of \eqn{R}, and \dQuote{non-zero}s fulfill \eqn{|d_i| \ge \mathrm{tol}\cdot\max(|d_i|)}{|d_i| >= tol * max(|d_i|)}. } \item{\code{"qr"}:}{is for back compatibility; for dense \code{x}, it corresponds to \code{"qrLINPACK"}, whereas for sparse \code{x}, it uses \code{"qr.R"}. For all the "qr*" methods, singular values \code{sval} are not used, which may be crucially important for a large sparse matrix \code{x}, as in that case, when \code{sval} is not specified, the default, computing \code{\link{svd}()} currently coerces \code{x} to a dense matrix. } \item{\code{"useGrad"}:}{considering the \dQuote{gradient} of the (decreasing) singular values, the index of the \emph{smallest} gap.} \item{\code{"maybeGrad"}:}{choosing method \code{"useGrad"} only when that seems \emph{reasonable}; otherwise using \code{"tolNorm2"}.} %% FIXME say more } } \item{sval}{numeric vector of non-increasing singular values of \code{x}; typically unspecified and computed from \code{x} when needed, i.e., unless \code{method = "qr"}.} \item{warn.t}{logical indicating if \code{rankMatrix()} should warn when it needs \code{\link{t}(x)} instead of \code{x}. Currently, for \code{method = "qr"} only, gives a warning by default because the caller often could have passed \code{t(x)} directly, more efficiently.} \item{warn.qr}{in the \eqn{QR} cases (i.e., if \code{method} starts with \code{"qr"}), \code{rankMatrix()} calls \code{qr2rankMarix(.., do.warn = warn.qr)}, see below.} %% qr2rankMatrix(): \item{qr}{an \R object resulting from \code{\link{qr}(x,..)}, i.e., typically inheriting from \code{\link{class}} \code{"\link{qr}"} or \code{"\linkS4class{sparseQR}"}.} \item{isBqr}{\code{\link{logical}} indicating if \code{qr} is resulting from \pkg{base} \code{\link[base]{qr}()}. (Otherwise, it is typically from \pkg{Matrix} package sparse \code{\link[Matrix]{qr}}.)} \item{do.warn}{logical; if true, warn about non-finite diagonal entries in the \eqn{R} matrix of the \eqn{QR} decomposition. Do not change lightly!} } \details{ \code{qr2rankMatrix()} is typically called from \code{rankMatrix()} for the \code{"qr"}* \code{method}s, but can be used directly - much more efficiently in case the \code{qr}-decomposition is available anyway. } \note{For large sparse matrices \code{x}, unless you can specify \code{sval} yourself, currently \code{method = "qr"} may be the only feasible one, as the others need \code{sval} and call \code{\link{svd}()} which currently coerces \code{x} to a \code{\linkS4class{denseMatrix}} which may be very slow or impossible, depending on the matrix dimensions. Note that in the case of sparse \code{x}, \code{method = "qr"}, all non-strictly zero diagonal entries \eqn{d_i} where counted, up to including \pkg{Matrix} version 1.1-0, i.e., that method implicitly used \code{tol = 0}, see also the \code{set.seed(42)} example below. } \value{ If \code{x} is a matrix of all \code{0} (or of zero dimension), the rank is zero; otherwise, typically a positive integer in \code{1:min(dim(x))} with attributes detailing the method used. There are rare cases where the sparse \eqn{QR} decomposition \dQuote{fails} in so far as the diagonal entries of \eqn{R}, the \eqn{d_i} (see above), end with non-finite, typically \code{\link{NaN}} entries. Then, a warning is signalled (unless \code{warn.qr} / \code{do.warn} is not true) and \code{NA} (specifically, \code{\link{NA_integer_}}) is returned. } % \references{ % %% ~put references to the literature/web site here ~ % } \author{Martin Maechler; for the "*Grad" methods building on suggestions by Ravi Varadhan. } \seealso{ \code{\link{qr}}, \code{\link{svd}}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) } rankMatrix(cbind(1, 0, 1:3)) # 2 (meths <- eval(formals(rankMatrix)$method)) ## a "border" case: H12 <- Hilbert(12) rankMatrix(H12, tol = 1e-20) # 12; but 11 with default method & tol. sapply(meths, function(.m.) rankMatrix(H12, method = .m.)) ## tolNorm2 qr.R qrLINPACK qr useGrad maybeGrad ## 11 11 12 12 11 11 ## The meaning of 'tol' for method="qrLINPACK" and *dense* x is not entirely "scale free" rMQL <- function(ex, M) rankMatrix(M, method="qrLINPACK",tol = 10^-ex) rMQR <- function(ex, M) rankMatrix(M, method="qr.R", tol = 10^-ex) sapply(5:15, rMQL, M = H12) # result is platform dependent ## 7 7 8 10 10 11 11 11 12 12 12 {x86_64} sapply(5:15, rMQL, M = 1000 * H12) # not identical unfortunately ## 7 7 8 10 11 11 12 12 12 12 12 sapply(5:15, rMQR, M = H12) ## 5 6 7 8 8 9 9 10 10 11 11 sapply(5:15, rMQR, M = 1000 * H12) # the *same* \dontshow{ (r12 <- sapply(5:15, rMQR, M = H12)) stopifnot(identical(r12, sapply(5:15, rMQR, M = H12 / 100)), identical(r12, sapply(5:15, rMQR, M = H12 * 1e5))) rM1 <- function(ex, M) rankMatrix(M, tol = 10^-ex) (r12 <- sapply(5:15, rM1, M = H12)) stopifnot(identical(r12, sapply(5:15, rM1, M = H12 / 100)), identical(r12, sapply(5:15, rM1, M = H12 * 1e5))) } ## "sparse" case: M15 <- kronecker(diag(x=c(100,1,10)), Hilbert(5)) sapply(meths, function(.m.) rankMatrix(M15, method = .m.)) #--> all 15, but 'useGrad' has 14. sapply(meths, function(.m.) rankMatrix(M15, method = .m., tol = 1e-7)) # all 14 ## "large" sparse n <- 250000; p <- 33; nnz <- 10000 L <- sparseMatrix(i = sample.int(n, nnz, replace=TRUE), j = sample.int(p, nnz, replace=TRUE), x = rnorm(nnz)) (st1 <- system.time(r1 <- rankMatrix(L))) # warning+ ~1.5 sec (2013) (st2 <- system.time(r2 <- rankMatrix(L, method = "qr"))) # considerably faster! r1[[1]] == print(r2[[1]]) ## --> ( 33 TRUE ) \dontshow{ stopifnot(r1[[1]] == 33, 33 == r2[[1]]) if(interactive() || nzchar(Sys.getenv("R_MATRIX_CHECK_EXTRA"))) stopifnot(st2[[1]] < 0.2) # seeing 0.03 (on ~ 2010-hardware; R 3.0.2) } ## another sparse-"qr" one, which ``failed'' till 2013-11-23: set.seed(42) f1 <- factor(sample(50, 1000, replace=TRUE)) f2 <- factor(sample(50, 1000, replace=TRUE)) f3 <- factor(sample(50, 1000, replace=TRUE)) D <- t(do.call(rbind, lapply(list(f1,f2,f3), as, 'sparseMatrix'))) dim(D); nnzero(D) ## 1000 x 150 // 3000 non-zeros (= 2\%) stopifnot(rankMatrix(D, method='qr') == 148, rankMatrix(crossprod(D),method='qr') == 148) ## zero matrix has rank 0 : stopifnot(sapply(meths, function(.m.) rankMatrix(matrix(0, 2, 2), method = .m.)) == 0) } Matrix/man/MatrixFactorization-class.Rd0000644000175100001440000001066714575137654017735 0ustar hornikusers\name{MatrixFactorization-class} \title{Virtual Class "MatrixFactorization" of Matrix Factorizations} % \docType{class} \keyword{algebra} \keyword{array} \keyword{classes} % \alias{MatrixFactorization-class} % \alias{BunchKaufmanFactorization-class} \alias{CholeskyFactorization-class} \alias{SchurFactorization-class} \alias{LU-class} \alias{QR-class} % \alias{determinant,MatrixFactorization,missing-method} \alias{dim,MatrixFactorization-method} \alias{dimnames,MatrixFactorization-method} \alias{dimnames<-,MatrixFactorization,NULL-method} \alias{dimnames<-,MatrixFactorization,list-method} \alias{length,MatrixFactorization-method} \alias{show,MatrixFactorization-method} \alias{unname,MatrixFactorization-method} % \alias{show,BunchKaufmanFactorization-method} \alias{show,CholeskyFactorization-method} \alias{show,SchurFactorization-method} \alias{show,LU-method} \alias{show,QR-method} % \description{ \code{MatrixFactorization} is the virtual class of factorizations of \eqn{m \times n}{m-by-n} matrices \eqn{A}, having the general form \deqn{P_{1} A P_{2} = A_{1} \cdots A_{p}}{P1 * A * P2 = A1 * ... * Ap} or (equivalently) \deqn{A = P_{1}' A_{1} \cdots A_{p} P_{2}'}{A = P1' * A1 * ... * Ap * P2'} where \eqn{P_{1}}{P1} and \eqn{P_{2}}{P2} are permutation matrices. Factorizations requiring symmetric \eqn{A} have the constraint \eqn{P_{2} = P_{1}'}{P2 = P1'}, and factorizations without row or column pivoting have the constraints \eqn{P_{1} = I_{m}}{P1 = Im} and \eqn{P_{2} = I_{n}}{P2 = In}, where \eqn{I_{m}}{Im} and \eqn{I_{n}}{In} are the \eqn{m \times m}{m-by-m} and \eqn{n \times n}{n-by-n} identity matrices. \code{CholeskyFactorization}, \code{BunchKaufmanFactorization}, \code{SchurFactorization}, \code{LU}, and \code{QR} are the virtual subclasses of \code{MatrixFactorization} containing all Cholesky, Bunch-Kaufman, Schur, LU, and QR factorizations, respectively. } \section{Slots}{ \describe{ \item{\code{Dim}}{an integer vector of length 2 giving the dimensions of the factorized matrix.} \item{\code{Dimnames}}{a list of length 2 preserving the \code{dimnames} of the factorized matrix. Each element must be \code{NULL} or a character vector of length equal to the corresponding element of \code{Dim}.} } } \section{Methods}{ \describe{ \item{\code{determinant}}{\code{signature(x = "MatrixFactorization", logarithm = "missing")}: sets \code{logarithm = TRUE} and recalls the generic function.} \item{\code{dim}}{\code{signature(x = "MatrixFactorization")}: returns \code{x@Dim}.} \item{\code{dimnames}}{\code{signature(x = "MatrixFactorization")}: returns \code{x@Dimnames}.} \item{\code{dimnames<-}}{\code{signature(x = "MatrixFactorization", value = "NULL")}: returns \code{x} with \code{x@Dimnames} set to \code{list(NULL, NULL)}.} \item{\code{dimnames<-}}{\code{signature(x = "MatrixFactorization", value = "list")}: returns \code{x} with \code{x@Dimnames} set to \code{value}.} \item{\code{length}}{\code{signature(x = "MatrixFactorization")}: returns \code{prod(x@Dim)}.} \item{\code{show}}{\code{signature(object = "MatrixFactorization")}: prints the internal representation of the factorization using \code{\link{str}}.} \item{\code{solve}}{\code{signature(a = "MatrixFactorization", b = .)}: see \code{\link{solve-methods}}.} \item{\code{unname}}{\code{signature(obj = "MatrixFactorization")}: returns \code{obj} with \code{obj@Dimnames} set to \code{list(NULL, NULL)}.} } } \seealso{ Classes extending \code{CholeskyFactorization}, namely \code{\linkS4class{Cholesky}}, \code{\linkS4class{pCholesky}}, and \code{\linkS4class{CHMfactor}}. Classes extending \code{BunchKaufmanFactorization}, namely \code{\linkS4class{BunchKaufman}} and \code{\linkS4class{pBunchKaufman}}. Classes extending \code{SchurFactorization}, namely \code{\linkS4class{Schur}}. Classes extending \code{LU}, namely \code{\linkS4class{denseLU}} and \code{\linkS4class{sparseLU}}. Classes extending \code{QR}, namely \code{\linkS4class{sparseQR}}. Generic functions \code{\link{Cholesky}}, \code{\link{BunchKaufman}}, \code{\link{Schur}}, \code{\link{lu}}, and \code{\link{qr}} for \emph{computing} factorizations. Generic functions \code{\link{expand1}} and \code{\link{expand2}} for constructing matrix factors from \code{MatrixFactorization} objects. } \examples{ showClass("MatrixFactorization") } Matrix/man/Schur-class.Rd0000644000175100001440000000760114446607050014777 0ustar hornikusers\name{Schur-class} \title{Schur Factorizations} % \docType{class} \keyword{algebra} \keyword{array} \keyword{classes} % \alias{Schur-class} % \alias{determinant,Schur,logical-method} % \description{ \code{Schur} is the class of Schur factorizations of \eqn{n \times n}{n-by-n} real matrices \eqn{A}, having the general form \deqn{A = Q T Q'}{A = Q * T * Q'} where \eqn{Q} is an orthogonal matrix and \eqn{T} is a block upper triangular matrix with \eqn{1 \times 1}{1-by-1} or \eqn{2 \times 2}{2-by-2} diagonal blocks specifying the real and complex conjugate eigenvalues of \eqn{A}. The column vectors of \eqn{Q} are the Schur vectors of \eqn{A}, and \eqn{T} is the Schur form of \eqn{A}. The Schur factorization generalizes the spectral decomposition of normal matrices \eqn{A}, whose Schur form is block diagonal, to arbitrary square matrices. } \section{Slots}{ \describe{ \item{\code{Dim}, \code{Dimnames}}{inherited from virtual class \code{\linkS4class{MatrixFactorization}}.} \item{\code{Q}}{an orthogonal matrix, inheriting from virtual class \code{\linkS4class{Matrix}}.} \item{\code{T}}{a block upper triangular matrix, inheriting from virtual class \code{\linkS4class{Matrix}}. The diagonal blocks have dimensions 1-by-1 or 2-by-2.} \item{\code{EValues}}{a numeric or complex vector containing the eigenvalues of the diagonal blocks of \code{T}, which are the eigenvalues of \code{T} and consequently of the factorized matrix.} } } \section{Extends}{ Class \code{\linkS4class{SchurFactorization}}, directly. Class \code{\linkS4class{MatrixFactorization}}, by class \code{\linkS4class{SchurFactorization}}, distance 2. } \section{Instantiation}{ Objects can be generated directly by calls of the form \code{new("Schur", ...)}, but they are more typically obtained as the value of \code{\link{Schur}(x)} for \code{x} inheriting from \code{\linkS4class{Matrix}} (often \code{\linkS4class{dgeMatrix}}). } \section{Methods}{ \describe{ \item{\code{determinant}}{\code{signature(from = "Schur", logarithm = "logical")}: computes the determinant of the factorized matrix \eqn{A} or its logarithm.} \item{\code{expand1}}{\code{signature(x = "Schur")}: see \code{\link{expand1-methods}}.} \item{\code{expand2}}{\code{signature(x = "Schur")}: see \code{\link{expand2-methods}}.} \item{\code{solve}}{\code{signature(a = "Schur", b = .)}: see \code{\link{solve-methods}}.} } } \details{ The matrix \eqn{A} and its Schur form \eqn{T} are \emph{similar} and thus have the same spectrum. The eigenvalues are computed trivially as the eigenvalues of the diagonal blocks of \eqn{T}. } \seealso{ Class \code{\linkS4class{dgeMatrix}}. Generic functions \code{\link{Schur}}, \code{\link{expand1}} and \code{\link{expand2}}. } \references{ The LAPACK source code, including documentation; see \url{https://netlib.org/lapack/double/dgees.f}. Golub, G. H., & Van Loan, C. F. (2013). \emph{Matrix computations} (4th ed.). Johns Hopkins University Press. \doi{10.56021/9781421407944} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } showClass("Schur") set.seed(0) n <- 4L (A <- Matrix(rnorm(n * n), n, n)) ## With dimnames, to see that they are propagated : dimnames(A) <- list(paste0("r", seq_len(n)), paste0("c", seq_len(n))) (sch.A <- Schur(A)) str(e.sch.A <- expand2(sch.A), max.level = 2L) ## A ~ Q T Q' in floating point stopifnot(exprs = { identical(names(e.sch.A), c("Q", "T", "Q.")) all.equal(A, with(e.sch.A, Q \%*\% T \%*\% Q.)) }) ## Factorization handled as factorized matrix b <- rnorm(n) stopifnot(all.equal(det(A), det(sch.A)), all.equal(solve(A, b), solve(sch.A, b))) ## One of the non-general cases: Schur(Diagonal(6L)) } Matrix/man/subscript-methods.Rd0000644000175100001440000000473514575137654016307 0ustar hornikusers\name{subscript-methods} \title{Methods for "[": Extraction or Subsetting in Package 'Matrix'} % \docType{methods} \keyword{array} \keyword{methods} % \alias{[} \alias{[-methods} \alias{subscript-methods} % \alias{[,Matrix,ANY,NULL,ANY-method} \alias{[,Matrix,NULL,ANY,ANY-method} \alias{[,Matrix,NULL,NULL,ANY-method} \alias{[,Matrix,index,index,logical-method} \alias{[,Matrix,index,index,missing-method} \alias{[,Matrix,index,missing,logical-method} \alias{[,Matrix,index,missing,missing-method} \alias{[,Matrix,lMatrix,missing,missing-method} \alias{[,Matrix,matrix,missing,missing-method} \alias{[,Matrix,missing,index,logical-method} \alias{[,Matrix,missing,index,missing-method} \alias{[,Matrix,missing,missing,logical-method} \alias{[,Matrix,missing,missing,missing-method} \alias{[,Matrix,nMatrix,missing,missing-method} \alias{[,abIndex,index,ANY,ANY-method} \alias{[,sparseVector,NULL,ANY,ANY-method} \alias{[,sparseVector,index,missing,missing-method} \alias{[,sparseVector,lsparseVector,missing,missing-method} \alias{[,sparseVector,missing,missing,missing-method} \alias{[,sparseVector,nsparseVector,missing,missing-method} % \description{ Methods for \code{"["}, i.e., extraction or subsetting mostly of matrices, in package \pkg{Matrix}. } \section{Methods}{ There are more than these: \describe{ \item{x = "Matrix", i = "missing", j = "missing", drop= "ANY"}{ ... } \item{x = "Matrix", i = "numeric", j = "missing", drop= "missing"}{ ... } \item{x = "Matrix", i = "missing", j = "numeric", drop= "missing"}{ ... } \item{x = "dsparseMatrix", i = "missing", j = "numeric", drop= "logical"}{ ... } \item{x = "dsparseMatrix", i = "numeric", j = "missing", drop= "logical"}{ ... } \item{x = "dsparseMatrix", i = "numeric", j = "numeric", drop= "logical"}{ ... } } } \seealso{ \code{\link{[<--methods}} for sub\emph{assign}ment to \code{"Matrix"} objects. \code{\link{Extract}} about the standard extraction. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } % regression tests are in ../tests/indexing.R str(m <- Matrix(round(rnorm(7*4),2), nrow = 7)) stopifnot(identical(m, m[])) m[2, 3] # simple number m[2, 3:4] # simple numeric of length 2 m[2, 3:4, drop=FALSE] # sub matrix of class 'dgeMatrix' ## rows or columns only: m[1,] # first row, as simple numeric vector m[,1:2] # sub matrix of first two columns showMethods("[", inherited = FALSE) } Matrix/man/rleDiff-class.Rd0000644000175100001440000000263714422605232015264 0ustar hornikusers\name{rleDiff-class} \title{Class "rleDiff" of rle(diff(.)) Stored Vectors} % \docType{class} \keyword{classes} % \alias{rleDiff-class} \alias{show,rleDiff-method} % \description{ Class \code{"rleDiff"} is for compactly storing long vectors which mainly consist of \emph{linear} stretches. For such a vector \code{x}, \code{\link{diff}(x)} consists of \emph{constant} stretches and is hence well compressable via \code{\link{rle}()}. } \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("rleDiff", ...)}. Currently experimental, see below. } \section{Slots}{ \describe{ \item{\code{first}:}{A single number (of class \code{"numLike"}, a class union of \code{"numeric"} and \code{"logical"}).} \item{\code{rle}:}{Object of class \code{"rle"}, basically a \code{\link{list}} with components \code{"lengths"} and \code{"values"}, see \code{\link{rle}()}. As this is used to encode potentially huge index vectors, \code{lengths} may be of type \code{\link{double}} here.} } } \section{Methods}{ There is a simple \code{\link{show}} method only.% currently } \note{ This is currently an \emph{experimental} auxiliary class for the class \code{\linkS4class{abIndex}}, see there. } \seealso{ \code{\link{rle}}, \code{\linkS4class{abIndex}}. } \examples{ showClass("rleDiff") ab <- c(abIseq(2, 100), abIseq(20, -2)) ab@rleD # is "rleDiff" } Matrix/man/triangularMatrix-class.Rd0000644000175100001440000000513014422605232017235 0ustar hornikusers\name{triangularMatrix-class} \title{Virtual Class of Triangular Matrices in Package Matrix} % \docType{class} \keyword{array} \keyword{classes} % \alias{triangularMatrix-class} % \alias{Arith,triangularMatrix,diagonalMatrix-method} \alias{Compare,triangularMatrix,diagonalMatrix-method} \alias{Logic,triangularMatrix,diagonalMatrix-method} \alias{coerce,matrix,triangularMatrix-method} \alias{determinant,triangularMatrix,logical-method} % \description{ The virtual class of triangular matrices,\code{"triangularMatrix"}, the package \pkg{Matrix} contains \emph{square} (\code{\link{nrow} == \link{ncol}}) numeric and logical, dense and sparse matrices, e.g., see the examples. A main use of the virtual class is in methods (and C functions) that can deal with all triangular matrices. } % \section{Objects from the Class}{A virtual Class: No objects may be created from it.} \section{Slots}{ \describe{ \item{\code{uplo}:}{String (of class \code{"character"}). Must be either "U", for upper triangular, and "L", for lower triangular.} \item{\code{diag}:}{String (of class \code{"character"}). Must be either \code{"U"}, for unit triangular (diagonal is all ones), or \code{"N"} for non-unit. The diagonal elements are not accessed internally when \code{diag} is \code{"U"}. For \code{\linkS4class{denseMatrix}} classes, they need to be allocated though, such that the length of the \code{x} slot does not depend on \code{diag}.} \item{\code{Dim}, \code{Dimnames}:}{The dimension (a length-2 \code{"integer"}) and corresponding names (or \code{NULL}), inherited from the \code{\linkS4class{Matrix}}, see there.} } } \section{Extends}{ Class \code{"Matrix"}, directly. } \section{Methods}{ There's a C function \code{triangularMatrix_validity()} called by the internal validity checking functions. Currently, \code{\link{Schur}}, \code{\link{isSymmetric}} and \code{as()} (i.e. \code{\link{coerce}}) have methods with \code{triangularMatrix} in their signature. } \seealso{ \code{\link{isTriangular}()} for testing any matrix for triangularity; classes \code{\linkS4class{symmetricMatrix}}, and, e.g., \code{\linkS4class{dtrMatrix}} for numeric \emph{dense} matrices, or \code{\linkS4class{ltCMatrix}} for a logical \emph{sparse} matrix subclass of \code{"triangularMatrix"}. } \examples{ showClass("triangularMatrix") ## The names of direct subclasses: scl <- getClass("triangularMatrix")@subclasses directly <- sapply(lapply(scl, slot, "by"), length) == 0 names(scl)[directly] (m <- matrix(c(5,1,0,3), 2)) as(m, "triangularMatrix") } Matrix/man/invertPerm.Rd0000644000175100001440000000720114575137654014752 0ustar hornikusers\name{invertPerm} \title{Utilities for Permutation Vectors} % \keyword{utilities} % \alias{invertPerm} \alias{signPerm} \alias{isPerm} \alias{asPerm} \alias{invPerm} % \description{ \code{invertPerm} and \code{signPerm} compute the inverse and sign of a length-\code{n} permutation vector. \code{isPerm} tests if a length-\code{n} integer vector is a valid permutation vector. \code{asPerm} coerces a length-\code{m} transposition vector to a length-\code{n} permutation vector, where \code{m <= n}. } \usage{ invertPerm(p, off = 1L, ioff = 1L) signPerm(p, off = 1L) isPerm(p, off = 1L) asPerm(pivot, off = 1L, ioff = 1L, n = length(pivot)) invPerm(p, zero.p = FALSE, zero.res = FALSE) } \arguments{ \item{p}{an integer vector of length \code{n}.} \item{pivot}{an integer vector of length \code{m}.} \item{off}{an integer offset, indicating that \code{p} is a permutation of \code{off+0:(n-1)} or that \code{pivot} contains \code{m} values sampled with replacement from \code{off+0:(n-1)}.} \item{ioff}{an integer offset, indicating that the result should be a permutation of \code{ioff+0:(n-1)}.} \item{n}{a integer greater than or equal to \code{m}, indicating the length of the result. Transpositions are applied to a permutation vector vector initialized as \code{seq_len(n)}.} \item{zero.p}{a logical. Equivalent to \code{off=0} if \code{TRUE} and \code{off=1} if \code{FALSE}.} \item{zero.res}{a logical. Equivalent to \code{ioff=0} if \code{TRUE} and \code{ioff=1} if \code{FALSE}.} } \details{ \code{invertPerm(p, off, ioff=1)} is equivalent to \code{\link{order}(p)} or \code{\link{sort.list}(p)} for all values of \code{off}. For the default value \code{off=1}, it returns the value of \code{p} after \code{p[p] <- seq_along(p)}. \code{invPerm} is a simple wrapper around \code{invertPerm}, retained for backwards compatibility. } \value{ By default, i.e., with \code{off=1} and \code{ioff=1}: \code{invertPerm(p)} returns an integer vector of length \code{length(p)} such that \code{p[invertPerm(p)]} and \code{invertPerm(p)[p]} are both \code{seq_along(p)}, i.e., the identity permutation. \code{signPerm(p)} returns 1 if \code{p} is an even permutation and \code{-1} otherwise (i.e., if \code{p} is odd). \code{isPerm(p)} returns \code{TRUE} if \code{p} is a permutation of \code{seq_along(p)} and \code{FALSE} otherwise. \code{asPerm(pivot)} returns the result of transposing elements \code{i} and \code{pivot[i]} of a permutation vector initialized as \code{seq_len(n)}, for \code{i} in \code{seq_along(pivot)}. } \seealso{ Class \code{\linkS4class{pMatrix}} of permutation matrices. } \examples{ p <- sample(10L) # a random permutation vector ip <- invertPerm(p) s <- signPerm(p) ## 'p' and 'ip' are indeed inverses: stopifnot(exprs = { isPerm(p) isPerm(ip) identical(s, 1L) || identical(s, -1L) identical(s, signPerm(ip)) identical(p[ip], 1:10) identical(ip[p], 1:10) identical(invertPerm(ip), p) }) ## Product of transpositions (1 2)(2 1)(4 3)(6 8)(10 1) = (3 4)(6 8)(1 10) pivot <- c(2L, 1L, 3L, 3L, 5L, 8L, 7L, 8L, 9L, 1L) q <- asPerm(pivot) stopifnot(exprs = { identical(q, c(10L, 2L, 4L, 3L, 5L, 8L, 7L, 6L, 9L, 1L)) identical(q[q], seq_len(10L)) # because the permutation is odd: signPerm(q) == -1L }) invPerm # a less general version of 'invertPerm' \dontshow{ stopifnot(exprs = { identical(isPerm(0L), FALSE) identical(signPerm(1:2), 1L) identical(signPerm(2:1), -1L) identical(invertPerm(c(3, 1:2)), c(2:3, 1L)) # 'p' of type "double", tryCatch(invPerm(NA), error = function(e) TRUE) # was a segfault }) } } Matrix/man/BunchKaufman-class.Rd0000644000175100001440000001535614446607050016263 0ustar hornikusers\name{BunchKaufman-class} \title{Dense Bunch-Kaufman Factorizations} % \docType{class} \keyword{algebra} \keyword{array} \keyword{classes} % \alias{BunchKaufman-class} \alias{pBunchKaufman-class} % \alias{coerce,BunchKaufman,dtrMatrix-method} \alias{coerce,pBunchKaufman,dtpMatrix-method} \alias{determinant,BunchKaufman,logical-method} \alias{determinant,pBunchKaufman,logical-method} % \description{ Classes \code{BunchKaufman} and \code{pBunchKaufman} represent Bunch-Kaufman factorizations of \eqn{n \times n}{n-by-n} real, symmetric matrices \eqn{A}, having the general form \deqn{A = U D_{U} U' = L D_{L} L'}{A = U * DU * U' = L * DL * L'} where \eqn{D_{U}}{DU} and \eqn{D_{L}}{DL} are symmetric, block diagonal matrices composed of \eqn{b_{U}}{bU} and \eqn{b_{L}}{bL} \eqn{1 \times 1}{1-by-1} or \eqn{2 \times 2}{2-by-2} diagonal blocks; \eqn{U = \prod_{k = 1}^{b_{U}} P_{k} U_{k}}{U = prod(Pk * Uk : k = 1,...,bU)} is the product of \eqn{b_{U}}{bU} row-permuted unit upper triangular matrices, each having nonzero entries above the diagonal in 1 or 2 columns; and \eqn{L = \prod_{k = 1}^{b_{L}} P_{k} L_{k}}{L = prod(Pk * Lk : k = 1,...,bL)} is the product of \eqn{b_{L}}{bL} row-permuted unit lower triangular matrices, each having nonzero entries below the diagonal in 1 or 2 columns. These classes store the nonzero entries of the \eqn{2 b_{U} + 1}{2*bU+1} or \eqn{2 b_{L} + 1}{2*bL+1} factors, which are individually sparse, in a dense format as a vector of length \eqn{nn}{n*n} (\code{BunchKaufman}) or \eqn{n(n+1)/2}{n*(n+1)/2} (\code{pBunchKaufman}), the latter giving the \dQuote{packed} representation. } \section{Slots}{ \describe{ \item{\code{Dim}, \code{Dimnames}}{inherited from virtual class \code{\linkS4class{MatrixFactorization}}.} \item{\code{uplo}}{a string, either \code{"U"} or \code{"L"}, indicating which triangle (upper or lower) of the factorized symmetric matrix was used to compute the factorization and in turn how the \code{x} slot is partitioned.} \item{\code{x}}{a numeric vector of length \code{n*n} (\code{BunchKaufman}) or \code{n*(n+1)/2} (\code{pBunchKaufman}), where \code{n=Dim[1]}. The details of the representation are specified by the manual for LAPACK routines \code{dsytrf} and \code{dsptrf}.} \item{\code{perm}}{an integer vector of length \code{n=Dim[1]} specifying row and column interchanges as described in the manual for LAPACK routines \code{dsytrf} and \code{dsptrf}.} } } \section{Extends}{ Class \code{\linkS4class{BunchKaufmanFactorization}}, directly. Class \code{\linkS4class{MatrixFactorization}}, by class \code{\linkS4class{BunchKaufmanFactorization}}, distance 2. } \section{Instantiation}{ Objects can be generated directly by calls of the form \code{new("BunchKaufman", ...)} or \code{new("pBunchKaufman", ...)}, but they are more typically obtained as the value of \code{\link{BunchKaufman}(x)} for \code{x} inheriting from \code{\linkS4class{dsyMatrix}} or \code{\linkS4class{dspMatrix}}. } \section{Methods}{ \describe{ \item{\code{coerce}}{\code{signature(from = "BunchKaufman", to = "dtrMatrix")}: returns a \code{\linkS4class{dtrMatrix}}, useful for inspecting the internal representation of the factorization; see \sQuote{Note}.} \item{\code{coerce}}{\code{signature(from = "pBunchKaufman", to = "dtpMatrix")}: returns a \code{\linkS4class{dtpMatrix}}, useful for inspecting the internal representation of the factorization; see \sQuote{Note}.} \item{\code{determinant}}{\code{signature(from = "p?BunchKaufman", logarithm = "logical")}: computes the determinant of the factorized matrix \eqn{A} or its logarithm.} \item{\code{expand1}}{\code{signature(x = "p?BunchKaufman")}: see \code{\link{expand1-methods}}.} \item{\code{expand2}}{\code{signature(x = "p?BunchKaufman")}: see \code{\link{expand2-methods}}.} \item{\code{solve}}{\code{signature(a = "p?BunchKaufman", b = .)}: see \code{\link{solve-methods}}.} } } \note{ In \pkg{Matrix} \code{< 1.6-0}, class \code{BunchKaufman} extended \code{\linkS4class{dtrMatrix}} and class \code{pBunchKaufman} extended \code{\linkS4class{dtpMatrix}}, reflecting the fact that the internal representation of the factorization is fundamentally triangular: there are \eqn{n(n+1)/2}{n*(n+1)/2} \dQuote{parameters}, and these can be arranged systematically to form an \eqn{n \times n}{n-by-n} triangular matrix. \pkg{Matrix} \code{1.6-0} removed these extensions so that methods would no longer be inherited from \code{dtrMatrix} and \code{dtpMatrix}. The availability of such methods gave the wrong impression that \code{BunchKaufman} and \code{pBunchKaufman} represent a (singular) matrix, when in fact they represent an ordered set of matrix factors. The coercions \code{as(., "dtrMatrix")} and \code{as(., "dtpMatrix")} are provided for users who understand the caveats. } \seealso{ Class \code{\linkS4class{dsyMatrix}} and its packed counterpart. Generic functions \code{\link{BunchKaufman}}, \code{\link{expand1}}, and \code{\link{expand2}}. } \references{ The LAPACK source code, including documentation; see \url{https://netlib.org/lapack/double/dsytrf.f} and \url{https://netlib.org/lapack/double/dsptrf.f}. Golub, G. H., & Van Loan, C. F. (2013). \emph{Matrix computations} (4th ed.). Johns Hopkins University Press. \doi{10.56021/9781421407944} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } showClass("BunchKaufman") set.seed(1) n <- 6L (A <- forceSymmetric(Matrix(rnorm(n * n), n, n))) ## With dimnames, to see that they are propagated : dimnames(A) <- rep.int(list(paste0("x", seq_len(n))), 2L) (bk.A <- BunchKaufman(A)) str(e.bk.A <- expand2(bk.A, complete = FALSE), max.level = 2L) str(E.bk.A <- expand2(bk.A, complete = TRUE), max.level = 2L) ## Underlying LAPACK representation (m.bk.A <- as(bk.A, "dtrMatrix")) stopifnot(identical(as(m.bk.A, "matrix"), `dim<-`(bk.A@x, bk.A@Dim))) ## Number of factors is 2*b+1, b <= n, which can be nontrivial ... (b <- (length(E.bk.A) - 1L) \%/\% 2L) ae1 <- function(a, b, ...) all.equal(as(a, "matrix"), as(b, "matrix"), ...) ae2 <- function(a, b, ...) ae1(unname(a), unname(b), ...) ## A ~ U DU U', U := prod(Pk Uk) in floating point stopifnot(exprs = { identical(names(e.bk.A), c("U", "DU", "U.")) identical(e.bk.A[["U" ]], Reduce(`\%*\%`, E.bk.A[seq_len(b)])) identical(e.bk.A[["U."]], t(e.bk.A[["U"]])) ae1(A, with(e.bk.A, U \%*\% DU \%*\% U.)) }) ## Factorization handled as factorized matrix b <- rnorm(n) stopifnot(identical(det(A), det(bk.A)), identical(solve(A, b), solve(bk.A, b))) } Matrix/man/sparseQR-class.Rd0000644000175100001440000003155214575234535015464 0ustar hornikusers\name{sparseQR-class} \title{Sparse QR Factorizations} % \docType{class} \keyword{algebra} \keyword{array} \keyword{classes} \keyword{utilities} % \alias{sparseQR-class} % \alias{determinant,sparseQR,logical-method} \alias{qr.Q,sparseQR-method} \alias{qr.R,sparseQR-method} \alias{qr.X,sparseQR-method} \alias{qr.coef,sparseQR,Matrix-method} \alias{qr.coef,sparseQR,dgeMatrix-method} \alias{qr.coef,sparseQR,matrix-method} \alias{qr.coef,sparseQR,vector-method} \alias{qr.fitted,sparseQR,Matrix-method} \alias{qr.fitted,sparseQR,dgeMatrix-method} \alias{qr.fitted,sparseQR,matrix-method} \alias{qr.fitted,sparseQR,vector-method} \alias{qr.qty,sparseQR,Matrix-method} \alias{qr.qty,sparseQR,dgeMatrix-method} \alias{qr.qty,sparseQR,matrix-method} \alias{qr.qty,sparseQR,vector-method} \alias{qr.qy,sparseQR,Matrix-method} \alias{qr.qy,sparseQR,dgeMatrix-method} \alias{qr.qy,sparseQR,matrix-method} \alias{qr.qy,sparseQR,vector-method} \alias{qr.resid,sparseQR,Matrix-method} \alias{qr.resid,sparseQR,dgeMatrix-method} \alias{qr.resid,sparseQR,matrix-method} \alias{qr.resid,sparseQR,vector-method} % \alias{qrR} % \description{ \code{sparseQR} is the class of sparse, row- and column-pivoted QR factorizations of \eqn{m \times n}{m-by-n} (\eqn{m \ge n}{m >= n}) real matrices, having the general form \deqn{P_1 A P_2 = Q R = \begin{bmatrix} Q_1 & Q_2 \end{bmatrix} \begin{bmatrix} R_1 \\ 0 \end{bmatrix} = Q_1 R_1}{P1 * A * P2 = Q * R = [Q1, Q2] * [R1; 0] = Q1 * R1} or (equivalently) \deqn{A = P_1' Q R P_2' = P_1' \begin{bmatrix} Q_1 & Q_2 \end{bmatrix} \begin{bmatrix} R_1 \\ 0 \end{bmatrix} P_2' = P_1' Q_1 R_1 P_2'}{A = P1' * Q * R * P2' = P1' * [Q1, Q2] * [R1; 0] * P2' = P1' * Q1 * R1 * P2'} where \eqn{P_1}{P1} and \eqn{P_2}{P2} are permutation matrices, \eqn{Q = \prod_{j = 1}^{n} H_j}{Q = prod(Hj : j = 1,...,n)} is an \eqn{m \times m}{m-by-m} orthogonal matrix (\eqn{Q_1}{Q1} contains the first \eqn{n} column vectors) equal to the product of \eqn{n} Householder matrices \eqn{H_j}{Hj}, and \eqn{R} is an \eqn{m \times n}{m-by-n} upper trapezoidal matrix (\eqn{R_1}{R1} contains the first \eqn{n} row vectors and is upper \emph{triangular}). } \usage{ qrR(qr, complete = FALSE, backPermute = TRUE, row.names = TRUE) } \arguments{ \item{qr}{an object of class \code{\linkS4class{sparseQR}}, almost always the result of a call to generic function \code{qr} with sparse \code{x}.} \item{complete}{a logical indicating if \eqn{R} should be returned instead of \eqn{R_1}{R1}.} \item{backPermute}{a logical indicating if \eqn{R} or \eqn{R_1}{R1} should be multiplied on the right by \eqn{P_2'}{P2'}.} \item{row.names}{a logical indicating if \code{dimnames(qr)[1]} should be propagated unpermuted to the result. If \code{complete = FALSE}, then only the first \eqn{n} names are kept.} } \section{Slots}{ \describe{ \item{\code{Dim}, \code{Dimnames}}{inherited from virtual class \code{\linkS4class{MatrixFactorization}}.} \item{\code{beta}}{a numeric vector of length \code{Dim[2]}, used to construct Householder matrices; see \code{V} below.} \item{\code{V}}{an object of class \code{\linkS4class{dgCMatrix}} with \code{Dim[2]} columns. The number of rows \code{nrow(V)} is at least \code{Dim[1]} and at most \code{Dim[1]+Dim[2]}. \code{V} is lower trapezoidal, and its column vectors generate the Householder matrices \eqn{H_j}{Hj} that compose the orthogonal \eqn{Q} factor. Specifically, \eqn{H_j}{Hj} is constructed as \code{diag(Dim[1]) - beta[j] * tcrossprod(V[, j])}.} \item{\code{R}}{an object of class \code{\linkS4class{dgCMatrix}} with \code{nrow(V)} rows and \code{Dim[2]} columns. \code{R} is the upper trapezoidal \eqn{R} factor.} \item{\code{p}, \code{q}}{0-based integer vectors of length \code{nrow(V)} and \code{Dim[2]}, respectively, specifying the permutations applied to the rows and columns of the factorized matrix. \code{q} of length 0 is valid and equivalent to the identity permutation, implying no column pivoting. Using \R{} syntax, the matrix \eqn{P_1 A P_2}{P1 * A * P2} is precisely \code{A[p+1, q+1]} (\code{A[p+1, ]} when \code{q} has length 0).} } } \section{Extends}{ Class \code{\linkS4class{QR}}, directly. Class \code{\linkS4class{MatrixFactorization}}, by class \code{\linkS4class{QR}}, distance 2. } \section{Instantiation}{ Objects can be generated directly by calls of the form \code{new("sparseQR", ...)}, but they are more typically obtained as the value of \code{\link{qr}(x)} for \code{x} inheriting from \code{\linkS4class{sparseMatrix}} (often \code{\linkS4class{dgCMatrix}}). } \section{Methods}{ \describe{ \item{\code{determinant}}{\code{signature(from = "sparseQR", logarithm = "logical")}: computes the determinant of the factorized matrix \eqn{A} or its logarithm.} \item{\code{expand1}}{\code{signature(x = "sparseQR")}: see \code{\link{expand1-methods}}.} \item{\code{expand2}}{\code{signature(x = "sparseQR")}: see \code{\link{expand2-methods}}.} \item{\code{qr.Q}}{\code{signature(qr = "sparseQR")}: returns as a \code{\linkS4class{dgeMatrix}} either \eqn{P_1' Q}{P1' * Q} or \eqn{P_1' Q_1}{P1' * Q1}, depending on optional argument \code{complete}. The default is \code{FALSE}, indicating \eqn{P_1' Q_1}{P1' * Q1}.} \item{\code{qr.R}}{\code{signature(qr = "sparseQR")}: \code{qrR} returns \eqn{R}, \eqn{R_1}{R1}, \eqn{R P2'}{R * P2'}, or \eqn{R_1 P2'}{R1 * P2'}, depending on optional arguments \code{complete} and \code{backPermute}. The default in both cases is \code{FALSE}, indicating \eqn{R_1}{R1}, for compatibility with \pkg{base}. The class of the result in that case is \code{\linkS4class{dtCMatrix}}. In the other three cases, it is \code{\linkS4class{dgCMatrix}}.} \item{\code{qr.X}}{\code{signature(qr = "sparseQR")}: returns \eqn{A} as a \code{\linkS4class{dgeMatrix}}, by default. If \eqn{m > n} and optional argument \code{ncol} is greater than \eqn{n}, then the result is augmented with \eqn{P_1' Q J}{P1 * Q * J}, where \eqn{J} is composed of columns \eqn{(n+1)} through \code{ncol} of the \eqn{m \times m}{m-by-m} identity matrix.} \item{\code{qr.coef}}{\code{signature(qr = "sparseQR", y = .)}: returns as a \code{\linkS4class{dgeMatrix}} or vector the result of multiplying \code{y} on the left by \eqn{P_2 R_1^{-1} Q_1' P_1}{P2 * R1^{-1} * Q1' * P1}.} \item{\code{qr.fitted}}{\code{signature(qr = "sparseQR", y = .)}: returns as a \code{\linkS4class{dgeMatrix}} or vector the result of multiplying \code{y} on the left by \eqn{P_1' Q_1 Q_1' P_1}{P1' * Q1 * Q1' * P1}.} \item{\code{qr.resid}}{\code{signature(qr = "sparseQR", y = .)}: returns as a \code{\linkS4class{dgeMatrix}} or vector the result of multiplying \code{y} on the left by \eqn{P_1' Q_2 Q_2' P_1}{P1' * Q2 * Q2' * P1}.} \item{\code{qr.qty}}{\code{signature(qr = "sparseQR", y = .)}: returns as a \code{\linkS4class{dgeMatrix}} or vector the result of multiplying \code{y} on the left by \eqn{Q' P_1}{Q' * P1}.} \item{\code{qr.qy}}{\code{signature(qr = "sparseQR", y = .)}: returns as a \code{\linkS4class{dgeMatrix}} or vector the result of multiplying \code{y} on the left by \eqn{P_1' Q}{P1' * Q}.} \item{\code{solve}}{\code{signature(a = "sparseQR", b = .)}: see \code{\link{solve-methods}}.} } } \details{ The method for \code{qr.Q} does not return \eqn{Q} but rather the (also orthogonal) product \eqn{P_1' Q}{P1' * Q}. This behaviour is algebraically consistent with the \pkg{base} implementation (see \code{\link[base]{qr}}), which can be seen by noting that \code{qr.default} in \pkg{base} does not pivot rows, constraining \eqn{P_1}{P1} to be an identity matrix. It follows that \code{qr.Q(qr.default(x))} also returns \eqn{P_1' Q}{P1' * Q}. Similarly, the methods for \code{qr.qy} and \code{qr.qty} multiply on the left by \eqn{P_1' Q}{P1' * Q} and \eqn{Q' P_1}{Q' * P1} rather than \eqn{Q} and \eqn{Q'}. It is wrong to expect the values of \code{qr.Q} (or \code{qr.R}, \code{qr.qy}, \code{qr.qty}) computed from \dQuote{equivalent} sparse and dense factorizations (say, \code{qr(x)} and \code{qr(as(x, "matrix"))} for \code{x} of class \code{\linkS4class{dgCMatrix}}) to compare equal. The underlying factorization algorithms are quite different, notably as they employ different pivoting strategies, and in general the factorization is not unique even for fixed \eqn{P_1}{P1} and \eqn{P_2}{P2}. On the other hand, the values of \code{qr.X}, \code{qr.coef}, \code{qr.fitted}, and \code{qr.resid} are well-defined, and in those cases the sparse and dense computations \emph{should} compare equal (within some tolerance). The method for \code{qr.R} is a simple wrapper around \code{qrR}, but not back-permuting by default and never giving row names. It did not support \code{backPermute = TRUE} until \pkg{Matrix} \code{1.6-0}, hence code needing the back-permuted result should call \code{qrR} if \pkg{Matrix} \code{>= 1.6-0} is not known. } \seealso{ Class \code{\linkS4class{dgCMatrix}}. Generic function \code{\link[base]{qr}} from \pkg{base}, whose default method \code{qr.default} \dQuote{defines} the S3 class \code{qr} of dense QR factorizations. \code{\link{qr-methods}} for methods defined in \pkg{Matrix}. Generic functions \code{\link{expand1}} and \code{\link{expand2}}. The many auxiliary functions for QR factorizations: \code{\link{qr.Q}}, \code{\link{qr.R}}, \code{\link{qr.X}}, \code{\link{qr.coef}}, \code{\link{qr.fitted}}, \code{\link{qr.resid}}, \code{\link{qr.qty}}, \code{\link{qr.qy}}, and \code{\link{qr.solve}}. } \references{ Davis, T. A. (2006). \emph{Direct methods for sparse linear systems}. Society for Industrial and Applied Mathematics. \doi{10.1137/1.9780898718881} Golub, G. H., & Van Loan, C. F. (2013). \emph{Matrix computations} (4th ed.). Johns Hopkins University Press. \doi{10.56021/9781421407944} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } showClass("sparseQR") set.seed(2) m <- 300L n <- 60L A <- rsparsematrix(m, n, 0.05) ## With dimnames, to see that they are propagated : dimnames(A) <- dn <- list(paste0("r", seq_len(m)), paste0("c", seq_len(n))) (qr.A <- qr(A)) str(e.qr.A <- expand2(qr.A, complete = FALSE), max.level = 2L) str(E.qr.A <- expand2(qr.A, complete = TRUE), max.level = 2L) t(sapply(e.qr.A, dim)) t(sapply(E.qr.A, dim)) ## Horribly inefficient, but instructive : slowQ <- function(V, beta) { d <- dim(V) Q <- diag(d[1L]) if(d[2L] > 0L) { for(j in d[2L]:1L) { cat(j, "\n", sep = "") Q <- Q - (beta[j] * tcrossprod(V[, j])) \%*\% Q } } Q } ae1 <- function(a, b, ...) all.equal(as(a, "matrix"), as(b, "matrix"), ...) ae2 <- function(a, b, ...) ae1(unname(a), unname(b), ...) ## A ~ P1' Q R P2' ~ P1' Q1 R1 P2' in floating point stopifnot(exprs = { identical(names(e.qr.A), c("P1.", "Q1", "R1", "P2.")) identical(names(E.qr.A), c("P1.", "Q" , "R" , "P2.")) identical(e.qr.A[["P1."]], new("pMatrix", Dim = c(m, m), Dimnames = c(dn[1L], list(NULL)), margin = 1L, perm = invertPerm(qr.A@p, 0L, 1L))) identical(e.qr.A[["P2."]], new("pMatrix", Dim = c(n, n), Dimnames = c(list(NULL), dn[2L]), margin = 2L, perm = invertPerm(qr.A@q, 0L, 1L))) identical(e.qr.A[["R1"]], triu(E.qr.A[["R"]][seq_len(n), ])) identical(e.qr.A[["Q1"]], E.qr.A[["Q"]][, seq_len(n)] ) identical(E.qr.A[["R"]], qr.A@R) ## ae1(E.qr.A[["Q"]], slowQ(qr.A@V, qr.A@beta)) ae1(crossprod(E.qr.A[["Q"]]), diag(m)) ae1(A, with(e.qr.A, P1. \%*\% Q1 \%*\% R1 \%*\% P2.)) ae1(A, with(E.qr.A, P1. \%*\% Q \%*\% R \%*\% P2.)) ae2(A.perm <- A[qr.A@p + 1L, qr.A@q + 1L], with(e.qr.A, Q1 \%*\% R1)) ae2(A.perm , with(E.qr.A, Q \%*\% R )) }) ## More identities b <- rnorm(m) stopifnot(exprs = { ae1(qrX <- qr.X (qr.A ), A) ae2(qrQ <- qr.Q (qr.A ), with(e.qr.A, P1. \%*\% Q1)) ae2( qr.R (qr.A ), with(e.qr.A, R1)) ae2(qrc <- qr.coef (qr.A, b), with(e.qr.A, solve(R1 \%*\% P2., t(qrQ)) \%*\% b)) ae2(qrf <- qr.fitted(qr.A, b), with(e.qr.A, tcrossprod(qrQ) \%*\% b)) ae2(qrr <- qr.resid (qr.A, b), b - qrf) ae2(qrq <- qr.qy (qr.A, b), with(E.qr.A, P1. \%*\% Q \%*\% b)) ae2(qr.qty(qr.A, qrq), b) }) ## Sparse and dense computations should agree here qr.Am <- qr(as(A, "matrix")) # <=> qr.default(A) stopifnot(exprs = { ae2(qrX, qr.X (qr.Am )) ae2(qrc, qr.coef (qr.Am, b)) ae2(qrf, qr.fitted(qr.Am, b)) ae2(qrr, qr.resid (qr.Am, b)) }) } Matrix/man/CAex.Rd0000644000175100001440000000250314446607050013424 0ustar hornikusers\name{CAex} \title{Albers' example Matrix with "Difficult" Eigen Factorization} % \docType{data} \keyword{datasets} % \alias{CAex} % \description{ An example of a sparse matrix for which \code{\link{eigen}()} seemed to be difficult, an unscaled version of this has been posted to the web, accompanying an E-mail to R-help (\url{https://stat.ethz.ch/mailman/listinfo/r-help}), by Casper J Albers, Open University, UK. } \usage{data(CAex)} \format{ This is a \eqn{72 \times 72}{72 * 72} symmetric matrix with 216 non-zero entries in five bands, stored as sparse matrix of class \code{\linkS4class{dgCMatrix}}. } \details{ Historical note (2006-03-30): In earlier versions of \R, \code{\link{eigen}(CAex)} fell into an infinite loop whereas \code{\link{eigen}(CAex, EISPACK=TRUE)} had been okay. } % \source{} \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } data(CAex, package = "Matrix") str(CAex) # of class "dgCMatrix" image(CAex)# -> it's a simple band matrix with 5 bands ## and the eigen values are basically 1 (42 times) and 0 (30 x): zapsmall(ev <- eigen(CAex, only.values=TRUE)$values) ## i.e., the matrix is symmetric, hence sCA <- as(CAex, "symmetricMatrix") ## and stopifnot(class(sCA) == "dsCMatrix", as(sCA, "matrix") == as(CAex, "matrix")) } Matrix/man/index-class.Rd0000644000175100001440000000127414575137654015035 0ustar hornikusers\name{index-class} \title{Virtual Class \dQuote{index} of Index Vectors} % \docType{class} \keyword{classes} % \alias{index-class} % \description{ Class \code{index} is a virtual class designating index vectors, or \dQuote{subscripts}, for (possibly named) vectors and arrays. It is typically used in signatures of methods for the subscript and subassignment operators, namely \code{[} and \code{[<-}. It is implemented as a \emph{union} of the atomic vector classes \code{\linkS4class{numeric}}, \code{\linkS4class{logical}}, and \code{\linkS4class{character}}. } \seealso{ \code{\link{[}}, \code{\link{[-methods}}, and \code{\link{[<--methods}}. } \examples{ showClass("index") } Matrix/man/denseMatrix-class.Rd0000644000175100001440000000343014500445405016165 0ustar hornikusers\name{denseMatrix-class} \title{Virtual Class "denseMatrix" of All Dense Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{denseMatrix-class} % \alias{-,denseMatrix,missing-method} \alias{Math,denseMatrix-method} \alias{Summary,denseMatrix-method} \alias{coerce,ANY,denseMatrix-method} \alias{coerce,matrix,denseMatrix-method} \alias{coerce,vector,denseMatrix-method} \alias{diag,denseMatrix-method} \alias{diag<-,denseMatrix-method} \alias{diff,denseMatrix-method} \alias{dim<-,denseMatrix-method} \alias{log,denseMatrix-method} \alias{mean,denseMatrix-method} \alias{rep,denseMatrix-method} \alias{show,denseMatrix-method} \alias{t,denseMatrix-method} % \description{This is the virtual class of all dense (S4) matrices. It partitions into two subclasses \code{\linkS4class{packedMatrix}} and \code{\linkS4class{unpackedMatrix}}. Alternatively into the (currently) three subclasses \code{\linkS4class{ddenseMatrix}}, \code{\linkS4class{ldenseMatrix}}, and \code{\linkS4class{ndenseMatrix}}. \code{denseMatrix} is (hence) the direct superclass of these (\eqn{2+3 = 5}) classes. } \section{Extends}{ class \code{"Matrix"} directly. } \section{Slots}{ exactly those of its superclass \code{"\linkS4class{Matrix}"}, i.e., \code{"Dim"} and \code{"Dimnames"}. } % \section{Methods}{ Use \code{\link{showMethods}(class = "denseMatrix", where = "package:Matrix")} for an overview of methods. Extraction (\code{"["}) methods, see \code{\link{[-methods}}.%-> ./Xtrct-methods.Rd } \seealso{ \code{\link{colSums}}, \code{\link{kronecker}}, and other such methods with own help pages. Its superclass \code{\linkS4class{Matrix}}, and main subclasses, \code{\linkS4class{ddenseMatrix}} and \code{\linkS4class{sparseMatrix}}. } \examples{ showClass("denseMatrix") } Matrix/man/ltrMatrix-class.Rd0000644000175100001440000000422114467516513015702 0ustar hornikusers\name{ltrMatrix-class} \title{Triangular Dense Logical Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{ltrMatrix-class} \alias{ltpMatrix-class} % \description{ The \code{"ltrMatrix"} class is the class of triangular, dense, logical matrices in nonpacked storage. The \code{"ltpMatrix"} class is the same except in packed storage. } \section{Slots}{ \describe{ \item{\code{x}:}{Object of class \code{"logical"}. The logical values that constitute the matrix, stored in column-major order.} \item{\code{uplo}:}{Object of class \code{"character"}. Must be either "U", for upper triangular, and "L", for lower triangular.} \item{\code{diag}:}{Object of class \code{"character"}. Must be either \code{"U"}, for unit triangular (diagonal is all ones), or \code{"N"}; see \code{\linkS4class{triangularMatrix}}.} \item{\code{Dim},\code{Dimnames}:}{The dimension (a length-2 \code{"integer"}) and corresponding names (or \code{NULL}), see the \code{\linkS4class{Matrix}} class.} \item{\code{factors}:}{Object of class \code{"list"}. A named list of factorizations that have been computed for the matrix.} } } \section{Extends}{ Both extend classes \code{"\linkS4class{ldenseMatrix}"} and \code{"\linkS4class{triangularMatrix}"}, directly; further, class \code{"Matrix"}, \code{"\linkS4class{lMatrix}"} and others, \emph{in}directly. Use \code{\link{showClass}("ltrMatrix")}, e.g., for details. } \section{Methods}{ Currently, mainly \code{\link{t}()} and coercion methods (for \code{\link{as}(.)}; use, e.g., \code{\link{showMethods}(class="ltrMatrix")} for details. } \seealso{ Classes \code{\linkS4class{lgeMatrix}}, \code{\linkS4class{Matrix}}; function \code{\link[base]{t}} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } showClass("ltrMatrix") str(new("ltpMatrix")) (lutr <- as(upper.tri(matrix(, 4, 4)), "ldenseMatrix")) str(lutp <- pack(lutr)) # packed matrix: only 10 = 4*(4+1)/2 entries !lutp # the logical negation (is *not* logical triangular !) ## but this one is: stopifnot(all.equal(lutp, pack(!!lutp))) } Matrix/man/USCounties.Rd0000644000175100001440000000421214447626522014652 0ustar hornikusers\name{USCounties} \title{Contiguity Matrix of U.S. Counties} % \docType{data} \keyword{datasets} % \alias{USCounties} % \description{ This matrix gives the contiguities of 3111 U.S. counties, using the queen criterion of at least one shared vertex or edge. } \usage{data(USCounties)} \format{ A \eqn{3111 \times 3111}{3111-by-3111} sparse, symmetric matrix of class \code{\linkS4class{dsCMatrix}}, with 9101 nonzero entries. } \source{ GAL lattice file \file{usc_q.GAL} (retrieved in 2008 from \file{http://sal.uiuc.edu/weights/zips/usc.zip} with permission from Luc Anselin for use and distribution) was read into \R{} using function \code{read.gal} from package \CRANpkg{spdep}. Neighbour lists were augmented with row-standardized (and then symmetrized) spatial weights, using functions \code{nb2listw} and \code{similar.listw} from packages \CRANpkg{spdep} and \CRANpkg{spatialreg}. The resulting \code{listw} object was coerced to class \code{\linkS4class{dsTMatrix}} using \code{as_dsTMatrix_listw} from \CRANpkg{spatialreg}, and subsequently to class \code{\linkS4class{dsCMatrix}}. } \references{ Ord, J. K. (1975). Estimation methods for models of spatial interaction. \emph{Journal of the American Statistical Association}, \emph{70}(349), 120-126. \doi{10.2307/2285387} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } data(USCounties, package = "Matrix") (n <- ncol(USCounties)) I <- .symDiagonal(n) set.seed(1) r <- 50L rho <- 1 / runif(r, 0, 0.5) system.time(MJ0 <- sapply(rho, function(mult) determinant(USCounties + mult * I, logarithm = TRUE)$modulus)) ## Can be done faster by updating the Cholesky factor: C1 <- Cholesky(USCounties, Imult = 2) system.time(MJ1 <- sapply(rho, function(mult) determinant(update(C1, USCounties, mult), sqrt = FALSE)$modulus)) stopifnot(all.equal(MJ0, MJ1)) C2 <- Cholesky(USCounties, super = TRUE, Imult = 2) system.time(MJ2 <- sapply(rho, function(mult) determinant(update(C2, USCounties, mult), sqrt = FALSE)$modulus)) stopifnot(all.equal(MJ0, MJ2)) } Matrix/man/lgeMatrix-class.Rd0000644000175100001440000000361714467516513015660 0ustar hornikusers\name{lgeMatrix-class} \title{Class "lgeMatrix" of General Dense Logical Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{lgeMatrix-class} % \alias{Arith,lgeMatrix,lgeMatrix-method} \alias{Compare,lgeMatrix,lgeMatrix-method} \alias{Logic,lgeMatrix,lgeMatrix-method} % \description{This is the class of general dense \code{\link{logical}} matrices. } \section{Slots}{ \describe{ \item{\code{x}:}{Object of class \code{"logical"}. The logical values that constitute the matrix, stored in column-major order.} \item{\code{Dim},\code{Dimnames}:}{The dimension (a length-2 \code{"integer"}) and corresponding names (or \code{NULL}), see the \code{\linkS4class{Matrix}} class.} \item{\code{factors}:}{Object of class \code{"list"}. A named list of factorizations that have been computed for the matrix.} } } \section{Extends}{ Class \code{"ldenseMatrix"}, directly. Class \code{"lMatrix"}, by class \code{"ldenseMatrix"}. Class \code{"denseMatrix"}, by class \code{"ldenseMatrix"}. Class \code{"Matrix"}, by class \code{"ldenseMatrix"}. Class \code{"Matrix"}, by class \code{"ldenseMatrix"}. } \section{Methods}{ Currently, mainly \code{\link{t}()} and coercion methods (for \code{\link{as}(.)}); use, e.g., \code{\link{showMethods}(class="lgeMatrix")} for details. } \seealso{ Non-general logical dense matrix classes such as \code{\linkS4class{ltrMatrix}}, or \code{\linkS4class{lsyMatrix}}; \emph{sparse} logical classes such as \code{\linkS4class{lgCMatrix}}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } showClass("lgeMatrix") str(new("lgeMatrix")) set.seed(1) (lM <- Matrix(matrix(rnorm(28), 4,7) > 0))# a simple random lgeMatrix set.seed(11) (lC <- Matrix(matrix(rnorm(28), 4,7) > 0))# a simple random lgCMatrix as(lM, "CsparseMatrix") } Matrix/man/nMatrix-class.Rd0000644000175100001440000000555014500445405015331 0ustar hornikusers\name{nMatrix-class} \title{Class "nMatrix" of Non-zero Pattern Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{nMatrix-class} % \alias{Arith,logical,nMatrix-method} \alias{Arith,nMatrix,logical-method} \alias{Arith,nMatrix,numeric-method} \alias{Arith,numeric,nMatrix-method} \alias{Compare,logical,nMatrix-method} \alias{Compare,nMatrix,logical-method} \alias{Compare,nMatrix,nMatrix-method} \alias{Compare,nMatrix,numeric-method} \alias{Compare,numeric,nMatrix-method} \alias{Logic,logical,nMatrix-method} \alias{Logic,nMatrix,Matrix-method} \alias{Logic,nMatrix,logical-method} \alias{Logic,nMatrix,nMatrix-method} \alias{Logic,nMatrix,numeric-method} \alias{Logic,nMatrix,sparseVector-method} \alias{Logic,numeric,nMatrix-method} \alias{Ops,nMatrix,dMatrix-method} \alias{Ops,nMatrix,lMatrix-method} \alias{Ops,nMatrix,nMatrix-method} \alias{Ops,nMatrix,numeric-method} \alias{Ops,numeric,nMatrix-method} \alias{coerce,matrix,nMatrix-method} \alias{coerce,vector,nMatrix-method} % \description{ The \code{nMatrix} class is the virtual \dQuote{mother} class of all \emph{\bold{n}on-zero pattern} (or simply \emph{patter\bold{n}}) matrices in the \pkg{Matrix} package. } %\section{Objects from the Class}{A virtual Class: No objects may be % created from it. %} \section{Slots}{ Common to \emph{all} matrix object in the package: \describe{ \item{\code{Dim}:}{Object of class \code{"integer"} - the dimensions of the matrix - must be an integer vector with exactly two non-negative values.} \item{\code{Dimnames}:}{list of length two; each component containing NULL or a \code{\link{character}} vector length equal the corresponding \code{Dim} element.} } } \section{Methods}{ \describe{ \item{coerce}{\code{signature(from = "matrix", to = "nMatrix")}: Note that these coercions (must) coerce \code{\link{NA}}s to non-zero, hence conceptually \code{TRUE}. This is particularly important when \code{\linkS4class{sparseMatrix}} objects are coerced to \code{"nMatrix"} and hence to \code{\linkS4class{nsparseMatrix}}. } } --- --- --- Additional methods contain group methods, such as \describe{ \item{Ops}{\code{signature(e1 = "nMatrix", e2 = "....")}, \dots} \item{Arith}{\code{signature(e1 = "nMatrix", e2 = "....")}, \dots} \item{Compare}{\code{signature(e1 = "nMatrix", e2 = "....")}, \dots} \item{Logic}{\code{signature(e1 = "nMatrix", e2 = "....")}, \dots} \item{Summary}{\code{signature(x = "nMatrix", "....")}, \dots} } } \seealso{ The classes \code{\linkS4class{lMatrix}}, \code{\linkS4class{nsparseMatrix}}, and the mother class, \code{\linkS4class{Matrix}}. } \examples{ getClass("nMatrix") L3 <- Matrix(upper.tri(diag(3))) L3 # an "ltCMatrix" as(L3, "nMatrix") # -> ntC* ## similar, not using Matrix() as(upper.tri(diag(3)), "nMatrix")# currently "ngTMatrix" } Matrix/man/nsyMatrix-class.Rd0000644000175100001440000000432214467516513015714 0ustar hornikusers\name{nsyMatrix-class} \title{Symmetric Dense Nonzero-Pattern Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{nsyMatrix-class} \alias{nspMatrix-class} % \description{ The \code{"nsyMatrix"} class is the class of symmetric, dense nonzero-pattern matrices in non-packed storage and \code{"nspMatrix"} is the class of of these in packed storage. Only the upper triangle or the lower triangle is stored. } \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("nsyMatrix", ...)}. } \section{Slots}{ \describe{ \item{\code{uplo}:}{Object of class \code{"character"}. Must be either "U", for upper triangular, and "L", for lower triangular.} \item{\code{x}:}{Object of class \code{"logical"}. The logical values that constitute the matrix, stored in column-major order.} \item{\code{Dim},\code{Dimnames}:}{The dimension (a length-2 \code{"integer"}) and corresponding names (or \code{NULL}), see the \code{\linkS4class{Matrix}} class.} \item{\code{factors}:}{Object of class \code{"list"}. A named list of factorizations that have been computed for the matrix.} } } \section{Extends}{ \code{"nsyMatrix"} extends class \code{"ngeMatrix"}, directly, whereas\cr \code{"nspMatrix"} extends class \code{"ndenseMatrix"}, directly. Both extend class \code{"symmetricMatrix"}, directly, and class \code{"Matrix"} and others, \emph{in}directly, use \code{\link{showClass}("nsyMatrix")}, e.g., for details. } \section{Methods}{ Currently, mainly \code{\link{t}()} and coercion methods (for \code{\link{as}(.)}; use, e.g., \code{\link{showMethods}(class="nsyMatrix")} for details. } %\references{} %\author{} \seealso{ \code{\linkS4class{ngeMatrix}}, \code{\linkS4class{Matrix}}, \code{\link[base]{t}} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } (s0 <- new("nsyMatrix")) (M2 <- Matrix(c(TRUE, NA, FALSE, FALSE), 2, 2)) # logical dense (ltr) (sM <- M2 & t(M2)) # -> "lge" class(sM <- as(sM, "nMatrix")) # -> "nge" (sM <- as(sM, "symmetricMatrix")) # -> "nsy" str(sM <- as(sM, "packedMatrix")) # -> "nsp", i.e., packed symmetric } Matrix/man/ddiMatrix-class.Rd0000644000175100001440000000624114500644730015634 0ustar hornikusers\name{ddiMatrix-class} \title{Class "ddiMatrix" of Diagonal Numeric Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{ddiMatrix-class} % \alias{\%\%,ddiMatrix,Matrix-method} \alias{\%\%,ddiMatrix,ddenseMatrix-method} \alias{\%\%,ddiMatrix,ldenseMatrix-method} \alias{\%\%,ddiMatrix,ndenseMatrix-method} \alias{\%/\%,ddiMatrix,Matrix-method} \alias{\%/\%,ddiMatrix,ddenseMatrix-method} \alias{\%/\%,ddiMatrix,ldenseMatrix-method} \alias{\%/\%,ddiMatrix,ndenseMatrix-method} \alias{&,ddiMatrix,Matrix-method} \alias{&,ddiMatrix,ddenseMatrix-method} \alias{&,ddiMatrix,ldenseMatrix-method} \alias{&,ddiMatrix,ndenseMatrix-method} \alias{*,ddiMatrix,Matrix-method} \alias{*,ddiMatrix,ddenseMatrix-method} \alias{*,ddiMatrix,ldenseMatrix-method} \alias{*,ddiMatrix,ndenseMatrix-method} \alias{/,ddiMatrix,Matrix-method} \alias{/,ddiMatrix,ddenseMatrix-method} \alias{/,ddiMatrix,ldenseMatrix-method} \alias{/,ddiMatrix,ndenseMatrix-method} \alias{Arith,ddiMatrix,logical-method} \alias{Arith,ddiMatrix,numeric-method} \alias{Arith,logical,ddiMatrix-method} \alias{Arith,numeric,ddiMatrix-method} \alias{Ops,ANY,ddiMatrix-method} \alias{Ops,ddiMatrix,ANY-method} \alias{Ops,ddiMatrix,Matrix-method} \alias{Ops,ddiMatrix,dMatrix-method} \alias{Ops,ddiMatrix,ddiMatrix-method} \alias{Ops,ddiMatrix,ldiMatrix-method} \alias{Ops,ddiMatrix,ndiMatrix-method} \alias{Ops,ddiMatrix,logical-method} \alias{Ops,ddiMatrix,numeric-method} \alias{Ops,ddiMatrix,sparseMatrix-method} % \description{The class \code{"ddiMatrix"} of numerical diagonal matrices. %% FIXME add more Note that diagonal matrices now extend \emph{\code{sparseMatrix}}, whereas they did extend dense matrices earlier.% up to early summer 2008. } \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("ddiMatrix", ...)} but typically rather via \code{\link{Diagonal}}. } \section{Slots}{ \describe{ \item{\code{x}:}{numeric vector. For an \eqn{n \times n}{n * n} matrix, the \code{x} slot is of length \eqn{n} or \code{0}, depending on the \code{diag} slot:} \item{\code{diag}:}{\code{"character"} string, either \code{"U"} or \code{"N"} where \code{"U"} denotes unit-diagonal, i.e., identity matrices.} \item{\code{Dim},\code{Dimnames}:}{matrix dimension and \code{\link{dimnames}}, see the \code{\linkS4class{Matrix}} class description.} } } \section{Extends}{ Class \code{"\linkS4class{diagonalMatrix}"}, directly. Class \code{"\linkS4class{dMatrix}"}, directly. Class \code{"\linkS4class{sparseMatrix}"}, indirectly, see \code{\link{showClass}("ddiMatrix")}. } \section{Methods}{ \describe{ \item{\%*\%}{\code{signature(x = "ddiMatrix", y = "ddiMatrix")}: ... } } } \seealso{ Class \code{\linkS4class{diagonalMatrix}} and function \code{\link{Diagonal}}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } (d2 <- Diagonal(x = c(10,1))) str(d2) ## slightly larger in internal size: str(as(d2, "sparseMatrix")) M <- Matrix(cbind(1,2:4)) M \%*\% d2 #> `fast' multiplication chol(d2) # trivial stopifnot(is(cd2 <- chol(d2), "ddiMatrix"), all.equal(cd2@x, c(sqrt(10),1))) } Matrix/man/TsparseMatrix-class.Rd0000644000175100001440000000554214467224234016525 0ustar hornikusers\name{TsparseMatrix-class} \title{Class "TsparseMatrix" of Sparse Matrices in Triplet Form} % \docType{class} \keyword{array} \keyword{classes} % \alias{TsparseMatrix-class} % \alias{coerce,matrix,TsparseMatrix-method} \alias{coerce,vector,TsparseMatrix-method} \alias{diag,TsparseMatrix-method} \alias{diag<-,TsparseMatrix-method} \alias{t,TsparseMatrix-method} % \description{The \code{"TsparseMatrix"} class is the virtual class of all sparse matrices coded in triplet form. Since it is a virtual class, no objects may be created from it. See \code{showClass("TsparseMatrix")} for its subclasses. } \section{Slots}{ \describe{ \item{\code{Dim}, \code{Dimnames}:}{from the \code{"\linkS4class{Matrix}"} class,} \item{\code{i}:}{Object of class \code{"integer"} - the row indices of non-zero entries \emph{in 0-base}, i.e., must be in \code{0:(nrow(.)-1)}.} \item{\code{j}:}{Object of class \code{"integer"} - the column indices of non-zero entries. Must be the same length as slot \code{i} and \emph{0-based} as well, i.e., in \code{0:(ncol(.)-1)}. For numeric Tsparse matrices, \code{(i,j)} pairs can occur more than once, see \code{\linkS4class{dgTMatrix}}. } } } \section{Extends}{ Class \code{"sparseMatrix"}, directly. Class \code{"Matrix"}, by class \code{"sparseMatrix"}. } \section{Methods}{ Extraction (\code{"["}) methods, see \code{\link{[-methods}}.%-> ./Xtrct-methods.Rd } \note{ Most operations with sparse matrices are performed using the compressed, column-oriented or \code{\linkS4class{CsparseMatrix}} representation. The triplet representation is convenient for creating a sparse matrix or for reading and writing such matrices. Once it is created, however, the matrix is generally coerced to a \code{\linkS4class{CsparseMatrix}} for further operations. Note that all \code{new(.)}, \code{\link{spMatrix}} and \code{\link{sparseMatrix}(*, repr="T")} constructors for \code{"TsparseMatrix"} classes implicitly add (i.e., \dQuote{sum up}) \eqn{x_k}'s that belong to identical \eqn{(i_k, j_k)} pairs, see, the example below, or also \code{"\linkS4class{dgTMatrix}"}. For convenience, methods for some operations such as \code{\%*\%} and \code{crossprod} are defined for \code{\linkS4class{TsparseMatrix}} objects. These methods simply coerce the \code{\linkS4class{TsparseMatrix}} object to a \code{\linkS4class{CsparseMatrix}} object then perform the operation. } % \author{Martin Maechler} \seealso{ its superclass, \code{\linkS4class{sparseMatrix}}, and the \code{\linkS4class{dgTMatrix}} class, for the links to other classes. } \examples{ showClass("TsparseMatrix") ## or just the subclasses' names names(getClass("TsparseMatrix")@subclasses) T3 <- spMatrix(3,4, i=c(1,3:1), j=c(2,4:2), x=1:4) T3 # only 3 non-zero entries, 5 = 1+4 ! \dontshow{stopifnot(nnzero(T3) == 3)} } Matrix/man/rcond-methods.Rd0000644000175100001440000001222314575137654015365 0ustar hornikusers\name{rcond-methods} \title{Estimate the Reciprocal Condition Number} % \docType{methods} \keyword{algebra} \keyword{math} \keyword{methods} % \alias{rcond} \alias{rcond-methods} % \alias{rcond,ANY,missing-method} \alias{rcond,denseMatrix,character-method} \alias{rcond,diagonalMatrix,character-method} \alias{rcond,indMatrix,character-method} \alias{rcond,pMatrix,character-method} \alias{rcond,sparseMatrix,character-method} % \usage{ rcond(x, norm, \dots) \S4method{rcond}{sparseMatrix,character}(x, norm, useInv=FALSE, \dots) } \description{ Estimate the reciprocal of the condition number of a matrix. This is a generic function with several methods, as seen by \code{\link{showMethods}(rcond)}. } \arguments{ \item{x}{an \R object that inherits from the \code{Matrix} class.} \item{norm}{character string indicating the type of norm to be used in the estimate. The default is \code{"O"} for the 1-norm (\code{"O"} is equivalent to \code{"1"}). For sparse matrices, when \code{useInv=TRUE}, \code{norm} can be any of the \code{kind}s allowed for \code{\link{norm}}; otherwise, the other possible value is \code{"I"} for the infinity norm, see also \code{\link{norm}}. } \item{useInv}{logical (or \code{"Matrix"} containing \code{\link{solve}(x)}). If not false, compute the reciprocal condition number as \eqn{1/(\|x\| \cdot \|x^{-1}\|)}{1/(||x|| * ||x^(-1)||)}, where \eqn{x^{-1}}{x^(-1)} is the inverse of \eqn{x}, \code{solve(x)}. This may be an efficient alternative (only) in situations where \code{solve(x)} is fast (or known), e.g., for (very) sparse or triangular matrices. Note that the \emph{result} may differ depending on \code{useInv}, as per default, when it is false, an \emph{approximation} is computed. } \item{\dots}{further arguments passed to or from other methods.} } \value{ An estimate of the reciprocal condition number of \code{x}. } \section{BACKGROUND}{ The condition number of a regular (square) matrix is the product of the \code{\link{norm}} of the matrix and the norm of its inverse (or pseudo-inverse). More generally, the condition number is defined (also for non-square matrices \eqn{A}) as \deqn{\kappa(A) = \frac{\max_{\|v\| = 1} \|A v\|}{\min_{\|v\| = 1} \|A v\|}.}{% kappa(A) = (max_(||v|| = 1; || Av ||)) /(min_(||v|| = 1; || Av ||)).} Whenever \code{x} is \emph{not} a square matrix, in our method definitions, this is typically computed via \code{rcond(qr.R(qr(X)), ...)} where \code{X} is \code{x} or \code{t(x)}. The condition number takes on values between 1 and infinity, inclusive, and can be viewed as a factor by which errors in solving linear systems with this matrix as coefficient matrix could be magnified. \code{rcond()} computes the \emph{reciprocal} condition number \eqn{1/\kappa} with values in \eqn{[0,1]} and can be viewed as a scaled measure of how close a matrix is to being rank deficient (aka \dQuote{singular}). Condition numbers are usually estimated, since exact computation is costly in terms of floating-point operations. An (over) estimate of reciprocal condition number is given, since by doing so overflow is avoided. Matrices are well-conditioned if the reciprocal condition number is near 1 and ill-conditioned if it is near zero. } \seealso{ \code{\link{norm}}, \code{\link[base]{kappa}()} from package \pkg{base} computes an \emph{approximate} condition number of a \dQuote{traditional} matrix, even non-square ones, with respect to the \eqn{p=2} (Euclidean) \code{\link{norm}}. \code{\link[base]{solve}}. \code{\link{condest}}, a newer \emph{approximate} estimate of the (1-norm) condition number, particularly efficient for large sparse matrices. } \references{ Golub, G., and Van Loan, C. F. (1989). \emph{Matrix Computations,} 2nd edition, Johns Hopkins, Baltimore. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) } x <- Matrix(rnorm(9), 3, 3) rcond(x) ## typically "the same" (with more computational effort): 1 / (norm(x) * norm(solve(x))) rcond(Hilbert(9)) # should be about 9.1e-13 ## For non-square matrices: rcond(x1 <- cbind(1,1:10))# 0.05278 rcond(x2 <- cbind(x1, 2:11))# practically 0, since x2 does not have full rank ## sparse (S1 <- Matrix(rbind(0:1,0, diag(3:-2)))) rcond(S1) m1 <- as(S1, "denseMatrix") all.equal(rcond(S1), rcond(m1)) ## wide and sparse rcond(Matrix(cbind(0, diag(2:-1)))) ## Large sparse example ---------- m <- Matrix(c(3,0:2), 2,2) M <- bdiag(kronecker(Diagonal(2), m), kronecker(m,m)) 36*(iM <- solve(M)) # still sparse MM <- kronecker(Diagonal(10), kronecker(Diagonal(5),kronecker(m,M))) dim(M3 <- kronecker(bdiag(M,M),MM)) # 12'800 ^ 2 if(interactive()) ## takes about 2 seconds if you have >= 8 GB RAM system.time(r <- rcond(M3)) ## whereas this is *fast* even though it computes solve(M3) system.time(r. <- rcond(M3, useInv=TRUE)) if(interactive()) ## the values are not the same c(r, r.) # 0.05555 0.013888 ## for all 4 norms available for sparseMatrix : cbind(rr <- sapply(c("1","I","F","M"), function(N) rcond(M3, norm=N, useInv=TRUE))) \dontshow{stopifnot(all.equal(r., 1/72, tolerance=1e-12))} } Matrix/man/isSymmetric-methods.Rd0000644000175100001440000000761114467101201016550 0ustar hornikusers\name{isSymmetric-methods} \title{Methods for Function 'isSymmetric' in Package 'Matrix'} % \docType{methods} \keyword{array} \keyword{programming} \keyword{methods} % \alias{isSymmetric} \alias{isSymmetric-methods} % \alias{isSymmetric,CsparseMatrix-method} \alias{isSymmetric,RsparseMatrix-method} \alias{isSymmetric,TsparseMatrix-method} \alias{isSymmetric,denseMatrix-method} \alias{isSymmetric,diagonalMatrix-method} \alias{isSymmetric,indMatrix-method} % tolerating numerical fuzz for [dz]Matrix: \alias{isSymmetric,dgCMatrix-method} \alias{isSymmetric,dgRMatrix-method} \alias{isSymmetric,dgTMatrix-method} \alias{isSymmetric,dgeMatrix-method} \alias{isSymmetric,dtCMatrix-method} \alias{isSymmetric,dtRMatrix-method} \alias{isSymmetric,dtTMatrix-method} \alias{isSymmetric,dtpMatrix-method} \alias{isSymmetric,dtrMatrix-method} % \description{ \code{isSymmetric} tests whether its argument is a symmetric square matrix, by default tolerating some numerical fuzz and requiring symmetric \code{[dD]imnames} in addition to symmetry in the mathematical sense. \code{isSymmetric} is a generic function in \pkg{base}, which has a \link[=isSymmetric]{method} for traditional matrices of implicit \code{\link{class}} \code{"\link{matrix}"}. Methods are defined here for various proper and virtual classes in \pkg{Matrix}, so that \code{isSymmetric} works for all objects inheriting from virtual class \code{"\linkS4class{Matrix}"}. } \usage{ \S4method{isSymmetric}{denseMatrix}(object, checkDN = TRUE, \dots) \S4method{isSymmetric}{CsparseMatrix}(object, checkDN = TRUE, \dots) \S4method{isSymmetric}{RsparseMatrix}(object, checkDN = TRUE, \dots) \S4method{isSymmetric}{TsparseMatrix}(object, checkDN = TRUE, \dots) \S4method{isSymmetric}{diagonalMatrix}(object, checkDN = TRUE, \dots) \S4method{isSymmetric}{indMatrix}(object, checkDN = TRUE, \dots) \S4method{isSymmetric}{dgeMatrix}(object, checkDN = TRUE, tol = 100 * .Machine$double.eps, tol1 = 8 * tol, \dots) \S4method{isSymmetric}{dgCMatrix}(object, checkDN = TRUE, tol = 100 * .Machine$double.eps, \dots) } \arguments{ \item{object}{a \code{"Matrix"}.} \item{checkDN}{a \link{logical} indicating whether symmetry of the \code{Dimnames} \link{slot} of \code{object} should be checked.} \item{tol, tol1}{numerical tolerances allowing \emph{approximate} symmetry of numeric (rather than logical) matrices. See also \code{\link{isSymmetric.matrix}}.} \item{\dots}{further arguments passed to methods (typically methods for \code{\link{all.equal}}).} } \value{ A \link{logical}, either \code{TRUE} or \code{FALSE} (never \code{\link{NA}}). } \details{ The \code{Dimnames} \link{slot} of \code{object}, say \code{dn}, is considered to be symmetric if and only if \itemize{ \item \code{dn[[1]]} and \code{dn[[2]]} are identical \emph{or} one is \code{NULL}; \emph{and} \item \code{ndn <- names(dn)} is \code{NULL} \emph{or} \code{ndn[1]} and \code{ndn[2]} are identical \emph{or} one is the empty string \code{""}. } Hence \code{list(a=nms, a=nms)} is considered to be \emph{symmetric}, and so too are \code{list(a=nms, NULL)} and \code{list(NULL, a=nms)}. Note that this definition is \emph{looser} than that employed by \code{\link{isSymmetric.matrix}}, which requires \code{dn[1]} and \code{dn[2]} to be identical, where \code{dn} is the \code{dimnames} \link[=attr]{attribute} of a traditional matrix. } \seealso{ \code{\link{forceSymmetric}}; \code{\link{symmpart}} and \code{\link{skewpart}}; virtual class \code{"\linkS4class{symmetricMatrix}"} and its subclasses. } \examples{ isSymmetric(Diagonal(4)) # TRUE of course M <- Matrix(c(1,2,2,1), 2,2) isSymmetric(M) # TRUE (*and* of formal class "dsyMatrix") isSymmetric(as(M, "generalMatrix")) # still symmetric, even if not "formally" isSymmetric(triu(M)) # FALSE ## Look at implementations: showMethods("isSymmetric", includeDefs = TRUE) # includes S3 generic from base } Matrix/man/pMatrix-class.Rd0000644000175100001440000001220614545303537015337 0ustar hornikusers\name{pMatrix-class} \title{Permutation matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{pMatrix-class} % \alias{coerce,matrix,pMatrix-method} \alias{coerce,numeric,pMatrix-method} \alias{determinant,pMatrix,logical-method} \alias{t,pMatrix-method} % \description{ The \code{pMatrix} class is the class of \emph{permutation} matrices, stored as 1-based integer permutation vectors. A permutation matrix is a square matrix whose rows \emph{and} columns are all standard unit vectors. It follows that permutation matrices are a special case of \emph{index} matrices (hence \code{pMatrix} is defined as a direct subclass of \code{\linkS4class{indMatrix}}). Multiplying a matrix on the left by a permutation matrix is equivalent to permuting its rows. Analogously, multiplying a matrix on the right by a permutation matrix is equivalent to permuting its columns. Indeed, such products are implemented in \pkg{Matrix} as indexing operations; see \sQuote{Details} below. } \section{Objects from the Class}{ Objects can be created explicitly with calls of the form \code{new("pMatrix", ...)}, but they are more commonly created by coercing 1-based integer index vectors, with calls of the form \code{as(., "pMatrix")}; see \sQuote{Methods} below. } \section{Slots}{ \describe{ \item{\code{margin},\code{perm}}{inherited from superclass \code{\linkS4class{indMatrix}}. Here, \code{perm} is an integer vector of length \code{Dim[1]} and a permutation of \code{1:Dim[1]}.} \item{\code{Dim},\code{Dimnames}}{inherited from virtual superclass \code{\linkS4class{Matrix}}.} } } \section{Extends}{ Class \code{"\linkS4class{indMatrix}"}, directly. } \section{Methods}{ \describe{ \item{\code{\%*\%}}{\code{signature(x = "pMatrix", y = "Matrix")} and others listed by \code{showMethods("\%*\%", classes = "pMatrix")}: matrix products implemented where appropriate as indexing operations.} \item{\code{coerce}}{\code{signature(from = "numeric", to = "pMatrix")}: supporting typical \code{pMatrix} construction from a vector of positive integers, specifically a permutation of \code{1:n}. Row permutation is assumed.} \item{t}{\code{signature(x = "pMatrix")}: the transpose, which is a \code{pMatrix} with identical \code{perm} but opposite \code{margin}. Coincides with the inverse, as permutation matrices are orthogonal.} \item{solve}{\code{signature(a = "pMatrix", b = "missing")}: the inverse permutation matrix, which is a \code{pMatrix} with identical \code{perm} but opposite \code{margin}. Coincides with the transpose, as permutation matrices are orthogonal. See \code{showMethods("solve", classes = "pMatrix")} for more signatures.} \item{determinant}{\code{signature(x = "pMatrix", logarithm = "logical")}: always returning 1 or -1, as permutation matrices are orthogonal. In fact, the result is exactly the \emph{sign} of the permutation.} } } \details{ By definition, a permutation matrix is both a row index matrix and a column index matrix. However, the \code{perm} slot of a \code{pMatrix} cannot be used interchangeably as a row index vector and column index vector. If \code{margin=1}, then \code{perm} is a row index vector, and the corresponding column index vector can be computed as \code{\link{invPerm}(perm)}, i.e., by inverting the permutation. Analogously, if \code{margin=2}, then \code{perm} and \code{invPerm(perm)} are column and row index vectors, respectively. Given an \code{n}-by-\code{n} row permutation matrix \code{P} with \code{perm} slot \code{p} and a matrix \code{M} with conformable dimensions, we have \tabular{lclcl}{ \eqn{P M} \tab = \tab \code{P \%*\% M} \tab = \tab \code{M[p, ]}\cr \eqn{M P} \tab = \tab \code{M \%*\% P} \tab = \tab \code{M[, i(p)]}\cr \eqn{P'M} \tab = \tab \code{crossprod(P, M)} \tab = \tab \code{M[i(p), ]}\cr \eqn{MP'} \tab = \tab \code{tcrossprod(M, P)} \tab = \tab \code{M[, p]}\cr \eqn{P'P} \tab = \tab \code{crossprod(P)} \tab = \tab \code{Diagonal(n)}\cr \eqn{PP'} \tab = \tab \code{tcrossprod(P)} \tab = \tab \code{Diagonal(n)} } where \code{i := invPerm}. } \seealso{ Superclass \code{\linkS4class{indMatrix}} of index matrices, for many inherited methods; \code{\link{invPerm}}, for computing inverse permutation vectors. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) } (pm1 <- as(as.integer(c(2,3,1)), "pMatrix")) t(pm1) # is the same as solve(pm1) pm1 \%*\% t(pm1) # check that the transpose is the inverse stopifnot(all(diag(3) == as(pm1 \%*\% t(pm1), "matrix")), is.logical(as(pm1, "matrix"))) set.seed(11) ## random permutation matrix : (p10 <- as(sample(10),"pMatrix")) ## Permute rows / columns of a numeric matrix : (mm <- round(array(rnorm(3 * 3), c(3, 3)), 2)) mm \%*\% pm1 pm1 \%*\% mm try(as(as.integer(c(3,3,1)), "pMatrix"))# Error: not a permutation as(pm1, "TsparseMatrix") p10[1:7, 1:4] # gives an "ngTMatrix" (most economic!) ## row-indexing of a keeps it as an : p10[1:3, ] } Matrix/man/mat2triplet.Rd0000644000175100001440000000455614473555676015105 0ustar hornikusers\name{mat2triplet} \title{Map Matrix to its Triplet Representation} % \keyword{array} \keyword{utilities} % \alias{mat2triplet} % \description{ From an \R object coercible to \code{"\linkS4class{TsparseMatrix}"}, typically a (sparse) matrix, produce its triplet representation which may collapse to a \dQuote{Duplet} in the case of binary aka pattern, such as \code{"\linkS4class{nMatrix}"} objects. } \usage{ mat2triplet(x, uniqT = FALSE) } \arguments{ \item{x}{any \R object for which \code{as(x, "\linkS4class{TsparseMatrix}")} works; typically a \code{\link{matrix}} of one of the \pkg{Matrix} package matrices.} \item{uniqT}{\code{\link{logical}} indicating if the triplet representation should be \sQuote{unique} in the sense of \code{\link{asUniqueT}(byrow=FALSE)}.} } \value{ A \code{\link{list}}, typically with three components, \item{i}{vector of row indices for all non-zero entries of \code{x}} \item{i}{vector of columns indices for all non-zero entries of \code{x}} \item{x}{vector of all non-zero entries of \code{x}; exists \bold{only} when \code{as(x, "TsparseMatrix")} is \bold{not} a \code{"\linkS4class{nsparseMatrix}"}.} Note that the \code{\link{order}} of the entries is determined by the coercion to \code{"\linkS4class{TsparseMatrix}"} and hence typically with increasing \code{j} (and increasing \code{i} within ties of \code{j}). } \note{ The \code{mat2triplet()} utility was created to be a more efficient and more predictable substitute for \code{\link{summary}()}. UseRs have wrongly expected the latter to return a data frame with columns \code{i} and \code{j} which however is wrong for a \code{"\linkS4class{diagonalMatrix}"}. } \seealso{ The \code{summary()} method for \code{"sparseMatrix"}, \code{\link{summary,sparseMatrix-method}}. \code{mat2triplet()} is conceptually the \emph{inverse} function of \code{\link{spMatrix}} and (one case of) \code{\link{sparseMatrix}}. } \examples{% ../R/sparseMatrix.R \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } mat2triplet # simple definition i <- c(1,3:8); j <- c(2,9,6:10); x <- 7 * (1:7) (Ax <- sparseMatrix(i, j, x = x)) ## 8 x 10 "dgCMatrix" str(trA <- mat2triplet(Ax)) stopifnot(i == sort(trA$i), sort(j) == trA$j, x == sort(trA$x)) D <- Diagonal(x=4:2) summary(D) str(mat2triplet(D)) } Matrix/man/sparseMatrix-class.Rd0000644000175100001440000001350414500445405016367 0ustar hornikusers\name{sparseMatrix-class} \title{Virtual Class "sparseMatrix" --- Mother of Sparse Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{sparseMatrix-class} % \alias{-,sparseMatrix,missing-method} \alias{Math,sparseMatrix-method} \alias{Ops,numeric,sparseMatrix-method} \alias{Ops,sparseMatrix,ddiMatrix-method} \alias{Ops,sparseMatrix,ldiMatrix-method} \alias{Ops,sparseMatrix,nsparseMatrix-method} \alias{Ops,sparseMatrix,numeric-method} \alias{Ops,sparseMatrix,sparseMatrix-method} \alias{Summary,sparseMatrix-method} \alias{coerce,ANY,sparseMatrix-method} \alias{coerce,factor,sparseMatrix-method} \alias{coerce,matrix,sparseMatrix-method} \alias{coerce,vector,sparseMatrix-method} \alias{cov2cor,sparseMatrix-method} \alias{diff,sparseMatrix-method} \alias{dim<-,sparseMatrix-method} \alias{format,sparseMatrix-method} \alias{log,sparseMatrix-method} \alias{mean,sparseMatrix-method} \alias{print,sparseMatrix-method} \alias{rep,sparseMatrix-method} \alias{show,sparseMatrix-method} \alias{summary,sparseMatrix-method} % \alias{print.sparseMatrix} % spoof, only so that users find this topic % \description{Virtual Mother Class of All Sparse Matrices} \section{Slots}{ \describe{ \item{\code{Dim}:}{Object of class \code{"integer"} - the dimensions of the matrix - must be an integer vector with exactly two non-negative values.} \item{\code{Dimnames}:}{a list of length two - inherited from class \code{Matrix}, see \code{\linkS4class{Matrix}}.} } } \section{Extends}{ Class \code{"Matrix"}, directly. } \section{Methods}{ \describe{ \item{show}{\code{(object = "sparseMatrix")}: The \code{\link{show}} method for sparse matrices prints \emph{\dQuote{structural}} zeroes as \code{"."} using \code{\link{printSpMatrix}()} which allows further customization.} \item{print}{\code{signature(x = "sparseMatrix")}, ....\cr The \code{\link{print}} method for sparse matrices by default is the same as \code{show()} but can be called with extra optional arguments, see \code{\link{printSpMatrix}()}.} \item{format}{\code{signature(x = "sparseMatrix")}, ....\cr The \code{\link{format}} method for sparse matrices, see \code{\link{formatSpMatrix}()} for details such as the extra optional arguments.} \item{summary}{\code{(object = "sparseMatrix", uniqT=FALSE)}: Returns an object of S3 class \code{"sparseSummary"} which is basically a \code{\link{data.frame}} with columns \code{(i,j,x)} (or just \code{(i,j)} for \code{\linkS4class{nsparseMatrix}} class objects) with the stored (typically non-zero) entries. The \code{\link{print}} method resembles Matlab's way of printing sparse matrices, and also the MatrixMarket format, see \code{\link{writeMM}}.} \item{cbind2}{\code{(x = *, y = *)}: several methods for binding matrices together, column-wise, see the basic \code{\link{cbind}} and \code{\link{rbind}} functions.\cr Note that the result will typically be sparse, even when one argument is dense and larger than the sparse one. } \item{rbind2}{\code{(x = *, y = *)}: binding matrices together row-wise, see \code{cbind2} above.} \item{determinant}{\code{(x = "sparseMatrix", logarithm=TRUE)}: \code{\link{determinant}()} methods for sparse matrices typically work via \code{\link{Cholesky}} or \code{\link{lu}} decompositions.} \item{diag}{\code{(x = "sparseMatrix")}: extracts the diagonal of a sparse matrix.} \item{dim<-}{\code{signature(x = "sparseMatrix", value = "ANY")}: allows to \emph{reshape} a sparse matrix to a sparse matrix with the same entries but different dimensions. \code{value} must be of length two and fulfill \code{prod(value) == prod(dim(x))}.} \item{coerce}{\code{signature(from = "factor", to = "sparseMatrix")}: Coercion of a factor to \code{"sparseMatrix"} produces the matrix of indicator \bold{rows} stored as an object of class \code{"dgCMatrix"}. To obtain columns representing the interaction of the factor and a numeric covariate, replace the \code{"x"} slot of the result by the numeric covariate then take the transpose. Missing values (\code{\link{NA}}) from the factor are translated to columns of all \code{0}s.} } See also \code{\link{colSums}}, \code{\link{norm}}, ... %% FIXME for methods with separate help pages. } \seealso{ \code{\link{sparseMatrix}}, and its references, such as \code{\link{xtabs}(*, sparse=TRUE)}, or \code{\link{sparse.model.matrix}()}, for constructing sparse matrices. \code{\link{T2graph}} for conversion of \code{"graph"} objects (package \pkg{graph}) to and from sparse matrices. } \note{ In method selection for multiplication operations (i.e. \code{\%*\%} and the two-argument form of \code{\link[base]{crossprod}}) the sparseMatrix class takes precedence in the sense that if one operand is a sparse matrix and the other is any type of dense matrix then the dense matrix is coerced to a \code{dgeMatrix} and the appropriate sparse matrix method is used. } %\author{Martin} \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } showClass("sparseMatrix") ## and look at the help() of its subclasses M <- Matrix(0, 10000, 100) M[1,1] <- M[2,3] <- 3.14 M ## show(.) method suppresses printing of the majority of rows data(CAex, package = "Matrix") dim(CAex) # 72 x 72 matrix determinant(CAex) # works via sparse lu(.) ## factor -> t( ) : (fact <- gl(5, 3, 30, labels = LETTERS[1:5])) (Xt <- as(fact, "sparseMatrix")) # indicator rows ## missing values --> all-0 columns: f.mis <- fact i.mis <- c(3:5, 17) is.na(f.mis) <- i.mis Xt != (X. <- as(f.mis, "sparseMatrix")) # differ only in columns 3:5,17 stopifnot(all(X.[,i.mis] == 0), all(Xt[,-i.mis] == X.[,-i.mis])) } Matrix/man/ndenseMatrix-class.Rd0000644000175100001440000000435314500644730016352 0ustar hornikusers\name{ndenseMatrix-class} \title{Virtual Class "ndenseMatrix" of Dense Logical Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{ndenseMatrix-class} % \alias{!,ndenseMatrix-method} \alias{&,ndenseMatrix,ddiMatrix-method} \alias{&,ndenseMatrix,ldiMatrix-method} \alias{&,ndenseMatrix,ndiMatrix-method} \alias{*,ndenseMatrix,ddiMatrix-method} \alias{*,ndenseMatrix,ldiMatrix-method} \alias{*,ndenseMatrix,ndiMatrix-method} \alias{Ops,ndenseMatrix,ndenseMatrix-method} \alias{^,ndenseMatrix,ddiMatrix-method} \alias{^,ndenseMatrix,ldiMatrix-method} \alias{^,ndenseMatrix,ndiMatrix-method} \alias{coerce,matrix,ndenseMatrix-method} \alias{coerce,vector,ndenseMatrix-method} \alias{which,ndenseMatrix-method} % \description{ \code{ndenseMatrix} is the virtual class of all dense \bold{l}ogical (S4) matrices. It extends both \code{\linkS4class{denseMatrix}} and \code{\linkS4class{lMatrix}} directly. } \section{Slots}{ \describe{ \item{\code{x}:}{logical vector containing the entries of the matrix.} \item{\code{Dim}, \code{Dimnames}:}{see \code{\linkS4class{Matrix}}.} } } \section{Extends}{ Class \code{"nMatrix"}, directly. Class \code{"denseMatrix"}, directly. Class \code{"Matrix"}, by class \code{"nMatrix"}. Class \code{"Matrix"}, by class \code{"denseMatrix"}. } \section{Methods}{ \describe{ \item{\%*\%}{\code{signature(x = "nsparseMatrix", y = "ndenseMatrix")}: ... } \item{\%*\%}{\code{signature(x = "ndenseMatrix", y = "nsparseMatrix")}: ... } \item{crossprod}{\code{signature(x = "nsparseMatrix", y = "ndenseMatrix")}: ... } \item{crossprod}{\code{signature(x = "ndenseMatrix", y = "nsparseMatrix")}: ... } \item{as.vector}{\code{signature(x = "ndenseMatrix", mode = "missing")}: ...} \item{diag}{\code{signature(x = "ndenseMatrix")}: extracts the diagonal as for all matrices, see the generic \code{\link{diag}()}.} \item{which}{\code{signature(x = "ndenseMatrix")}, semantically equivalent to \pkg{base} function \code{\link{which}(x, arr.ind)}; for details, see the \code{\linkS4class{lMatrix}} class documentation.} } } \seealso{ Class \code{\linkS4class{ngeMatrix}} and the other subclasses. } \examples{ showClass("ndenseMatrix") as(diag(3) > 0, "ndenseMatrix")# -> "nge" } Matrix/man/unpackedMatrix-class.Rd0000644000175100001440000000377514574651323016706 0ustar hornikusers\name{unpackedMatrix-class} \title{Virtual Class \code{"unpackedMatrix"} of Unpacked Dense Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{unpackedMatrix-class} % \alias{coerce,matrix,unpackedMatrix-method} \alias{coerce,vector,unpackedMatrix-method} \alias{cov2cor,unpackedMatrix-method} % \description{ Class \code{"unpackedMatrix"} is the \emph{virtual} class of dense matrices in "unpacked" format, storing all \code{m*n} elements of an \code{m}-by-\code{n} matrix. It is used to define common methods for efficient subsetting, transposing, etc. of its \emph{proper} subclasses: currently \code{"[dln]geMatrix"} (unpacked general), \code{"[dln]syMatrix"} (unpacked symmetric), \code{"[dln]trMatrix"} (unpacked triangular), and subclasses of these, such as \code{"\linkS4class{dpoMatrix}"}. } \section{Slots}{ \describe{ \item{\code{Dim}, \code{Dimnames}:}{as all \code{\linkS4class{Matrix}} objects.} } } \section{Extends}{ Class \code{"\linkS4class{denseMatrix}"}, directly. Class \code{"\linkS4class{Matrix}"}, by class \code{"denseMatrix"}, distance 2. } \section{Methods}{ \describe{ \item{pack}{\code{signature(x = "unpackedMatrix")}: ... } \item{unpack}{\code{signature(x = "unpackedMatrix")}: ... } \item{isSymmetric}{\code{signature(object = "unpackedMatrix")}: ... } \item{isTriangular}{\code{signature(object = "unpackedMatrix")}: ... } \item{isDiagonal}{\code{signature(object = "unpackedMatrix")}: ... } \item{t}{\code{signature(x = "unpackedMatrix")}: ... } \item{diag}{\code{signature(x = "unpackedMatrix")}: ... } \item{diag<-}{\code{signature(x = "unpackedMatrix")}: ... } } } %% \references{ %% } \author{Mikael Jagan} %% \note{ %% } \seealso{ \code{\link{pack}} and \code{\link{unpack}}; its virtual "complement" \code{"\linkS4class{packedMatrix}"}; its proper subclasses \code{"\linkS4class{dsyMatrix}"}, \code{"\linkS4class{ltrMatrix}"}, etc. } \examples{ showClass("unpackedMatrix") showMethods(classes = "unpackedMatrix") } Matrix/man/indMatrix-class.Rd0000644000175100001440000001735314545303537015662 0ustar hornikusers\name{indMatrix-class} \title{Index Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{indMatrix-class} % \alias{!,indMatrix-method} \alias{-,indMatrix,missing-method} \alias{Math,indMatrix-method} \alias{Summary,indMatrix-method} \alias{coerce,indMatrix,pMatrix-method} \alias{coerce,list,indMatrix-method} \alias{coerce,matrix,indMatrix-method} \alias{coerce,numeric,indMatrix-method} \alias{determinant,indMatrix,logical-method} \alias{diag,indMatrix-method} \alias{diag<-,indMatrix-method} \alias{log,indMatrix-method} \alias{t,indMatrix-method} \alias{which,indMatrix-method} % \description{ The \code{indMatrix} class is the class of row and column \emph{index} matrices, stored as 1-based integer index vectors. A row (column) index matrix is a matrix whose rows (columns) are standard unit vectors. Such matrices are useful when mapping observations to discrete sets of covariate values. Multiplying a matrix on the left by a row index matrix is equivalent to indexing its rows, i.e., sampling the rows \dQuote{with replacement}. Analogously, multiplying a matrix on the right by a column index matrix is equivalent to indexing its columns. Indeed, such products are implemented in \pkg{Matrix} as indexing operations; see \sQuote{Details} below. A matrix whose rows \emph{and} columns are standard unit vectors is called a \emph{permutation} matrix. This special case is designated by the \code{\linkS4class{pMatrix}} class, a direct subclass of \code{indMatrix}. } \section{Objects from the Class}{ Objects can be created explicitly with calls of the form \code{new("indMatrix", ...)}, but they are more commonly created by coercing 1-based integer index vectors, with calls of the form \code{as(., "indMatrix")}; see \sQuote{Methods} below. } \section{Slots}{ \describe{ \item{\code{margin}}{an integer, either 1 or 2, specifying whether the matrix is a row (1) or column (2) index.} \item{\code{perm}}{a 1-based integer index vector, i.e., a vector of length \code{Dim[margin]} with elements taken from \code{1:Dim[1+margin\%\%2]}.} \item{\code{Dim},\code{Dimnames}}{inherited from virtual superclass \code{\linkS4class{Matrix}}.} } } \section{Extends}{ Classes \code{"\linkS4class{sparseMatrix}"} and \code{"\linkS4class{generalMatrix}"}, directly. } \section{Methods}{ \describe{ \item{\code{\%*\%}}{\code{signature(x = "indMatrix", y = "Matrix")} and others listed by \code{showMethods("\%*\%", classes = "indMatrix")}: matrix products implemented where appropriate as indexing operations.} \item{\code{coerce}}{\code{signature(from = "numeric", to = "indMatrix")}: supporting typical \code{indMatrix} construction from a vector of positive integers. Row indexing is assumed.} \item{\code{coerce}}{\code{signature(from = "list", to = "indMatrix")}: supporting \code{indMatrix} construction for row \emph{and} column indexing, including index vectors of length 0 and index vectors whose maximum is less than the number of rows or columns being indexed.} \item{\code{coerce}}{\code{signature(from = "indMatrix", to = "matrix")}: coercion to a traditional \code{\link{matrix}} of \link{logical} type, with \code{FALSE} and \code{TRUE} in place of 0 and 1.} \item{\code{t}}{\code{signature(x = "indMatrix")}: the transpose, which is an \code{indMatrix} with identical \code{perm} but opposite \code{margin}.} \item{\code{rowSums},\code{rowMeans},\code{colSums},\code{colMeans}}{\code{signature(x = "indMatrix")}: row and column sums and means.} \item{\code{rbind2},\code{cbind2}}{\code{signature(x = "indMatrix", y = "indMatrix")}: row-wise catenation of two row index matrices with equal numbers of columns and column-wise catenation of two column index matrices with equal numbers of rows.} \item{kronecker}{\code{signature(X = "indMatrix", Y = "indMatrix")}: Kronecker product of two row index matrices or two column index matrices, giving the row or column index matrix corresponding to their \dQuote{interaction}.} } } \author{Fabian Scheipl at \file{uni-muenchen.de}, building on the existing class \code{\linkS4class{pMatrix}} after a nice hike's conversation with Martin Maechler. Methods for \code{\link{crossprod}(x, y)} and \code{\link{kronecker}(x, y)} with both arguments inheriting from \code{indMatrix} were made considerably faster thanks to a suggestion by Boris Vaillant. Diverse tweaks by Martin Maechler and Mikael Jagan, notably the latter's implementation of \code{margin}, prior to which the \code{indMatrix} class was designated only for row index matrices. } \details{ The transpose of an index matrix is an index matrix with identical \code{perm} but opposite \code{margin}. Hence the transpose of a row index matrix is a column index matrix, and vice versa. The cross product of a row index matrix \code{R} and itself is a diagonal matrix whose diagonal entries are the the number of entries in each column of \code{R}. Given a row index matrix \code{R} with \code{perm} slot \code{p}, a column index matrix \code{C} with \code{perm} slot \code{q}, and a matrix \code{M} with conformable dimensions, we have \tabular{lclcl}{ \eqn{R M} \tab = \tab \code{R \%*\% M} \tab = \tab \code{M[p, ]}\cr \eqn{M C} \tab = \tab \code{M \%*\% C} \tab = \tab \code{M[, q]}\cr \eqn{C'M} \tab = \tab \code{crossprod(C, M)} \tab = \tab \code{M[q, ]}\cr \eqn{MR'} \tab = \tab \code{tcrossprod(M, R)} \tab = \tab \code{M[, p]}\cr \eqn{R'R} \tab = \tab \code{crossprod(R)} \tab = \tab \code{Diagonal(x=tabulate(p, ncol(R)))}\cr \eqn{CC'} \tab = \tab \code{tcrossprod(C)} \tab = \tab \code{Diagonal(x=tabulate(q, nrow(C)))} } Operations on index matrices that result in index matrices will accordingly return an \code{indMatrix}. These include products of two column index matrices and (equivalently) column-indexing of a column index matrix (when dimensions are not dropped). Most other operations on \code{indMatrix} treat them as sparse nonzero pattern matrices (i.e., inheriting from virtual class \code{\linkS4class{nsparseMatrix}}). Hence vector-valued subsets of \code{indMatrix}, such as those given by \code{\link{diag}}, are always of type \code{"\link{logical}"}. } \seealso{ Subclass \code{\linkS4class{pMatrix}} of permutation matrices, a special case of index matrices; virtual class \code{\linkS4class{nMatrix}} of nonzero pattern matrices, and its subclasses. } \examples{ p1 <- as(c(2,3,1), "pMatrix") (sm1 <- as(rep(c(2,3,1), e=3), "indMatrix")) stopifnot(all(sm1 == p1[rep(1:3, each=3),])) ## row-indexing of a turns it into an : class(p1[rep(1:3, each=3),]) set.seed(12) # so we know '10' is in sample ## random index matrix for 30 observations and 10 unique values: (s10 <- as(sample(10, 30, replace=TRUE),"indMatrix")) ## Sample rows of a numeric matrix : (mm <- matrix(1:10, nrow=10, ncol=3)) s10 \%*\% mm set.seed(27) IM1 <- as(sample(1:20, 100, replace=TRUE), "indMatrix") IM2 <- as(sample(1:18, 100, replace=TRUE), "indMatrix") (c12 <- crossprod(IM1,IM2)) ## same as cross-tabulation of the two index vectors: stopifnot(all(c12 - unclass(table(IM1@perm, IM2@perm)) == 0)) # 3 observations, 4 implied values, first does not occur in sample: as(2:4, "indMatrix") # 3 observations, 5 values, first and last do not occur in sample: as(list(2:4, 5), "indMatrix") as(sm1, "nMatrix") s10[1:7, 1:4] # gives an "ngTMatrix" (most economic!) s10[1:4, ] # preserves "indMatrix"-class I1 <- as(c(5:1,6:4,7:3), "indMatrix") I2 <- as(7:1, "pMatrix") (I12 <- rbind(I1, I2)) stopifnot(is(I12, "indMatrix"), identical(I12, rbind(I1, I2)), colSums(I12) == c(2L,2:4,4:2)) } Matrix/man/dgRMatrix-class.Rd0000644000175100001440000000354714422605232015613 0ustar hornikusers\name{dgRMatrix-class} \title{Sparse Compressed, Row-oriented Numeric Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{dgRMatrix-class} % \alias{determinant,dgRMatrix,logical-method} % \description{The \code{dgRMatrix} class is a class of sparse numeric matrices in the compressed, sparse, row-oriented format. In this implementation the non-zero elements in the rows are sorted into increasing column order. \bold{Note:} The column-oriented sparse classes, e.g., \code{\linkS4class{dgCMatrix}}, are preferred and better supported in the \pkg{Matrix} package. } \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("dgRMatrix", ...)}. } \section{Slots}{ \describe{ \item{\code{j}:}{Object of class \code{"integer"} of length nnzero (number of non-zero elements). These are the column numbers for each non-zero element in the matrix.} \item{\code{p}:}{Object of class \code{"integer"} of pointers, one for each row, to the initial (zero-based) index of elements in the row.} \item{\code{x}:}{Object of class \code{"numeric"} - the non-zero elements of the matrix.} \item{\code{Dim}:}{Object of class \code{"integer"} - the dimensions of the matrix.} } } \section{Methods}{ \describe{ \item{diag}{\code{signature(x = "dgRMatrix")}: returns the diagonal of \code{x}} \item{dim}{\code{signature(x = "dgRMatrix")}: returns the dimensions of \code{x}} \item{image}{\code{signature(x = "dgRMatrix")}: plots an image of \code{x} using the \code{\link[lattice]{levelplot}} function} } } \seealso{ the \code{\linkS4class{RsparseMatrix}} class, the virtual class of all sparse compressed \bold{r}ow-oriented matrices, with its methods. The \code{\linkS4class{dgCMatrix}} class (\bold{c}olumn compressed sparse) is really preferred. } Matrix/man/CHMfactor-class.Rd0000644000175100001440000003335514575234535015535 0ustar hornikusers\name{CHMfactor-class} \title{Sparse Cholesky Factorizations} % \docType{class} \keyword{algebra} \keyword{array} \keyword{classes} \keyword{programming} \keyword{utilities} % \alias{CHMfactor-class} \alias{CHMsimpl-class} \alias{CHMsuper-class} \alias{dCHMsimpl-class} \alias{dCHMsuper-class} \alias{nCHMsimpl-class} \alias{nCHMsuper-class} % \alias{coerce,CHMsimpl,dtCMatrix-method} \alias{coerce,CHMsuper,dgCMatrix-method} \alias{determinant,CHMfactor,logical-method} \alias{diag,CHMfactor-method} \alias{update,CHMfactor-method} % \alias{isLDL} % \description{ \code{CHMfactor} is the virtual class of sparse Cholesky factorizations of \eqn{n \times n}{n-by-n} real, symmetric matrices \eqn{A}, having the general form \deqn{P_1 A P_1' = L_1 D L_1' \overset{D_{jj} \ge 0}{=} L L'}{P1 * A * P1' = L1 * D * L1' [ = L * L' ]} or (equivalently) \deqn{A = P_1' L_1 D L_1' P_1 \overset{D_{jj} \ge 0}{=} P_1' L L' P_1}{A = P1' L1 * D * L1' * P1 [ = P1' * L * L' * P1 ]} where \eqn{P_1}{P1} is a permutation matrix, \eqn{L_1}{L1} is a unit lower triangular matrix, \eqn{D} is a diagonal matrix, and \eqn{L = L_1 \sqrt{D}}{L = L1 * sqrt(D)}. The second equalities hold only for positive semidefinite \eqn{A}, for which the diagonal entries of \eqn{D} are non-negative and \eqn{\sqrt{D}}{sqrt(D)} is well-defined. The implementation of class \code{CHMfactor} is based on CHOLMOD's C-level \code{cholmod_factor_struct}. Virtual subclasses \code{CHMsimpl} and \code{CHMsuper} separate the simplicial and supernodal variants. These have nonvirtual subclasses \code{[dn]CHMsimpl} and \code{[dn]CHMsuper}, where prefix \samp{d} and prefix \samp{n} are reserved for numeric and symbolic factorizations, respectively. } \usage{ isLDL(x) } \arguments{ \item{x}{an object inheriting from virtual class \code{CHMfactor}, almost always the result of a call to generic function \code{\link{Cholesky}}.} } \value{ \code{isLDL(x)} returns \code{TRUE} or \code{FALSE}: \code{TRUE} if \code{x} stores the lower triangular entries of \eqn{L_1-I+D}{L1-I+D}, \code{FALSE} if \code{x} stores the lower triangular entries of \eqn{L}. } \section{Slots}{ Of \code{CHMfactor}: \describe{ \item{\code{Dim}, \code{Dimnames}}{inherited from virtual class \code{\linkS4class{MatrixFactorization}}.} \item{\code{colcount}}{an integer vector of length \code{Dim[1]} giving an \emph{estimate} of the number of nonzero entries in each column of the lower triangular Cholesky factor. If symbolic analysis was performed prior to factorization, then the estimate is exact.} \item{\code{perm}}{a 0-based integer vector of length \code{Dim[1]} specifying the permutation applied to the rows and columns of the factorized matrix. \code{perm} of length 0 is valid and equivalent to the identity permutation, implying no pivoting.} \item{\code{type}}{an integer vector of length 6 specifying details of the factorization. The elements correspond to members \code{ordering}, \code{is_ll}, \code{is_super}, \code{is_monotonic}, \code{maxcsize}, and \code{maxesize} of the original \code{cholmod_factor_struct}. Simplicial and supernodal factorizations are distinguished by \code{is_super}. Simplicial factorizations do not use \code{maxcsize} or \code{maxesize}. Supernodal factorizations do not use \code{is_ll} or \code{is_monotonic}.} } Of \code{CHMsimpl} (all unused by \code{nCHMsimpl}): % FIXME \describe{ \item{\code{nz}}{an integer vector of length \code{Dim[1]} giving the number of nonzero entries in each column of the lower triangular Cholesky factor. There is at least one nonzero entry in each column, because the diagonal elements of the factor are stored explicitly.} \item{\code{p}}{an integer vector of length \code{Dim[1]+1}. Row indices of nonzero entries in column \code{j} of the lower triangular Cholesky factor are obtained as \code{i[p[j]+seq_len(nz[j])]+1}.} \item{\code{i}}{an integer vector of length greater than or equal to \code{sum(nz)} containing the row indices of nonzero entries in the lower triangular Cholesky factor. These are grouped by column and sorted within columns, but the columns themselves need not be ordered monotonically. Columns may be overallocated, i.e., the number of elements of \code{i} reserved for column \code{j} may exceed \code{nz[j]}.} \item{\code{prv}, \code{nxt}}{integer vectors of length \code{Dim[1]+2} indicating the order in which the columns of the lower triangular Cholesky factor are stored in \code{i} and \code{x}. Starting from \code{j <- Dim[1]+2}, the recursion \code{j <- nxt[j+1]+1} traverses the columns in forward order and terminates when \code{nxt[j+1] = -1}. Starting from \code{j <- Dim[1]+1}, the recursion \code{j <- prv[j+1]+1} traverses the columns in backward order and terminates when \code{prv[j+1] = -1}.} } Of \code{dCHMsimpl}: \describe{ \item{\code{x}}{a numeric vector parallel to \code{i} containing the corresponding nonzero entries of the lower triangular Cholesky factor \eqn{L} \emph{or} (if and only if \code{type[2]} is 0) of the lower triangular matrix \eqn{L_1-I+D}{L1-I+D}.} } Of \code{CHMsuper}: \describe{ \item{\code{super}, \code{pi}, \code{px}}{integer vectors of length \code{nsuper+1}, where \code{nsuper} is the number of supernodes. \code{super[j]+1} is the index of the leftmost column of supernode \code{j}. The row indices of supernode \code{j} are obtained as \code{s[pi[j]+seq_len(pi[j+1]-pi[j])]+1}. The numeric entries of supernode \code{j} are obtained as \code{x[px[j]+seq_len(px[j+1]-px[j])]+1} (if slot \code{x} is available).} \item{\code{s}}{an integer vector of length greater than or equal to \code{Dim[1]} containing the row indices of the supernodes. \code{s} may contain duplicates, but not within a supernode, where the row indices must be increasing.} } Of \code{dCHMsuper}: \describe{ \item{\code{x}}{a numeric vector of length less than or equal to \code{prod(Dim)} containing the numeric entries of the supernodes.} } } \section{Extends}{ Class \code{\linkS4class{MatrixFactorization}}, directly. } \section{Instantiation}{ Objects can be generated directly by calls of the form \code{new("dCHMsimpl", ...)}, etc., but \code{dCHMsimpl} and \code{dCHMsuper} are more typically obtained as the value of \code{\link{Cholesky}(x, ...)} for \code{x} inheriting from \code{\linkS4class{sparseMatrix}} (often \code{\linkS4class{dsCMatrix}}). There is currently no API outside of calls to \code{\link{new}} for generating \code{nCHMsimpl} and \code{nCHMsuper}. These classes are vestigial and may be formally deprecated in a future version of \pkg{Matrix}. } \section{Methods}{ \describe{ \item{\code{coerce}}{\code{signature(from = "CHMsimpl", to = "dtCMatrix")}: returns a \code{\linkS4class{dtCMatrix}} representing the lower triangular Cholesky factor \eqn{L} \emph{or} the lower triangular matrix \eqn{L_1-I+D}{L1-I+D}, the latter if and only if \code{from@type[2]} is 0.} \item{\code{coerce}}{\code{signature(from = "CHMsuper", to = "dgCMatrix")}: returns a \code{\linkS4class{dgCMatrix}} representing the lower triangular Cholesky factor \eqn{L}. Note that, for supernodes spanning two or more columns, the supernodal algorithm by design stores non-structural zeros above the main diagonal, hence \code{\linkS4class{dgCMatrix}} is indeed more appropriate than \code{\linkS4class{dtCMatrix}} as a coercion target.} \item{\code{determinant}}{\code{signature(from = "CHMfactor", logarithm = "logical")}: behaves according to an optional argument \code{sqrt}. If \code{sqrt = FALSE}, then this method computes the determinant of the factorized matrix \eqn{A} or its logarithm. If \code{sqrt = TRUE}, then this method computes the determinant of the factor \eqn{L = L_1 sqrt(D)}{L = L1 * sqrt(D)} or its logarithm, giving \code{NaN} for the modulus when \eqn{D} has negative diagonal elements. For backwards compatibility, the default value of \code{sqrt} is \code{TRUE}, but that can be expected change in a future version of \pkg{Matrix}, hence defensive code will always set \code{sqrt} (to \code{TRUE}, if the code must remain backwards compatible with \pkg{Matrix} \code{< 1.6-0}). Calls to this method not setting \code{sqrt} may warn about the pending change. The warnings can be disabled with \code{\link{options}(Matrix.warnSqrtDefault = 0)}.} \item{\code{diag}}{\code{signature(x = "CHMfactor")}: returns a numeric vector of length \eqn{n} containing the diagonal elements of \eqn{D}, which (\emph{if} they are all non-negative) are the squared diagonal elements of \eqn{L}.} \item{\code{expand}}{\code{signature(x = "CHMfactor")}: see \code{\link{expand-methods}}.} \item{\code{expand1}}{\code{signature(x = "CHMsimpl")}: see \code{\link{expand1-methods}}.} \item{\code{expand1}}{\code{signature(x = "CHMsuper")}: see \code{\link{expand1-methods}}.} \item{\code{expand2}}{\code{signature(x = "CHMsimpl")}: see \code{\link{expand2-methods}}.} \item{\code{expand2}}{\code{signature(x = "CHMsuper")}: see \code{\link{expand2-methods}}.} \item{\code{image}}{\code{signature(x = "CHMfactor")}: see \code{\link{image-methods}}.} \item{\code{nnzero}}{\code{signature(x = "CHMfactor")}: see \code{\link{nnzero-methods}}.} \item{\code{solve}}{\code{signature(a = "CHMfactor", b = .)}: see \code{\link{solve-methods}}.} \item{\code{update}}{\code{signature(object = "CHMfactor")}: returns a copy of \code{object} with the same nonzero pattern but with numeric entries updated according to additional arguments \code{parent} and \code{mult}, where \code{parent} is (coercible to) a \code{\linkS4class{dsCMatrix}} or a \code{\linkS4class{dgCMatrix}} and \code{mult} is a numeric vector of positive length. \cr The numeric entries are updated with those of the Cholesky factor of \code{F(parent) + mult[1] * I}, i.e., \code{F(parent)} plus \code{mult[1]} times the identity matrix, where \code{F = \link{identity}} for symmetric \code{parent} and \code{F = \link{tcrossprod}} for other \code{parent}. The nonzero pattern of \code{F(parent)} must match that of \code{S} if \code{object = Cholesky(S, ...)}.} \item{\code{updown}}{\code{signature(update = ., C = ., object = "CHMfactor")}: see \code{\link{updown-methods}}.} } } \seealso{ Class \code{\linkS4class{dsCMatrix}}. Generic functions \code{\link{Cholesky}}, \code{\link{updown}}, \code{\link{expand1}} and \code{\link{expand2}}. } \references{ The CHOLMOD source code; see \url{https://github.com/DrTimothyAldenDavis/SuiteSparse}, notably the header file \file{CHOLMOD/Include/cholmod.h} defining \code{cholmod_factor_struct}. Chen, Y., Davis, T. A., Hager, W. W., & Rajamanickam, S. (2008). Algorithm 887: CHOLMOD, supernodal sparse Cholesky factorization and update/downdate. \emph{ACM Transactions on Mathematical Software}, \emph{35}(3), Article 22, 1-14. \doi{10.1145/1391989.1391995} Amestoy, P. R., Davis, T. A., & Duff, I. S. (2004). Algorithm 837: AMD, an approximate minimum degree ordering algorithm. \emph{ACM Transactions on Mathematical Software}, \emph{17}(4), 886-905. \doi{10.1145/1024074.1024081} Golub, G. H., & Van Loan, C. F. (2013). \emph{Matrix computations} (4th ed.). Johns Hopkins University Press. \doi{10.56021/9781421407944} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } showClass("dCHMsimpl") showClass("dCHMsuper") set.seed(2) m <- 1000L n <- 200L M <- rsparsematrix(m, n, 0.01) A <- crossprod(M) ## With dimnames, to see that they are propagated : dimnames(A) <- dn <- rep.int(list(paste0("x", seq_len(n))), 2L) (ch.A <- Cholesky(A)) # pivoted, by default str(e.ch.A <- expand2(ch.A, LDL = TRUE), max.level = 2L) str(E.ch.A <- expand2(ch.A, LDL = FALSE), max.level = 2L) ae1 <- function(a, b, ...) all.equal(as(a, "matrix"), as(b, "matrix"), ...) ae2 <- function(a, b, ...) ae1(unname(a), unname(b), ...) ## A ~ P1' L1 D L1' P1 ~ P1' L L' P1 in floating point stopifnot(exprs = { identical(names(e.ch.A), c("P1.", "L1", "D", "L1.", "P1")) identical(names(E.ch.A), c("P1.", "L" , "L." , "P1")) identical(e.ch.A[["P1"]], new("pMatrix", Dim = c(n, n), Dimnames = c(list(NULL), dn[2L]), margin = 2L, perm = invertPerm(ch.A@perm, 0L, 1L))) identical(e.ch.A[["P1."]], t(e.ch.A[["P1"]])) identical(e.ch.A[["L1."]], t(e.ch.A[["L1"]])) identical(E.ch.A[["L." ]], t(E.ch.A[["L" ]])) identical(e.ch.A[["D"]], Diagonal(x = diag(ch.A))) all.equal(E.ch.A[["L"]], with(e.ch.A, L1 \%*\% sqrt(D))) ae1(A, with(e.ch.A, P1. \%*\% L1 \%*\% D \%*\% L1. \%*\% P1)) ae1(A, with(E.ch.A, P1. \%*\% L \%*\% L. \%*\% P1)) ae2(A[ch.A@perm + 1L, ch.A@perm + 1L], with(e.ch.A, L1 \%*\% D \%*\% L1.)) ae2(A[ch.A@perm + 1L, ch.A@perm + 1L], with(E.ch.A, L \%*\% L. )) }) ## Factorization handled as factorized matrix ## (in some cases only optionally, depending on arguments) b <- rnorm(n) stopifnot(identical(det(A), det(ch.A, sqrt = FALSE)), identical(solve(A, b), solve(ch.A, b, system = "A"))) u1 <- update(ch.A, A , mult = sqrt(2)) u2 <- update(ch.A, t(M), mult = sqrt(2)) # updating with crossprod(M), not M stopifnot(all.equal(u1, u2, tolerance = 1e-14)) } Matrix/man/sparse.model.matrix.Rd0000644000175100001440000001453314446607050016511 0ustar hornikusers\name{sparse.model.matrix} \title{Construct Sparse Design / Model Matrices} % \keyword{array} \keyword{models} \keyword{utilities} % \alias{sparse.model.matrix} \alias{fac2sparse} \alias{fac2Sparse} % \description{Construct a sparse model or \dQuote{design} matrix, from a formula and data frame (\code{sparse.model.matrix}) or a single factor (\code{fac2sparse}). The \code{fac2[Ss]parse()} functions are utilities, also used internally in the principal user level function \code{sparse.model.matrix()}. } \usage{ sparse.model.matrix(object, data = environment(object), contrasts.arg = NULL, xlev = NULL, transpose = FALSE, drop.unused.levels = FALSE, row.names = TRUE, sep = "", verbose = FALSE, \dots) fac2sparse(from, to = c("d", "l", "n"), drop.unused.levels = TRUE, repr = c("C", "R", "T"), giveCsparse) fac2Sparse(from, to = c("d", "l", "n"), drop.unused.levels = TRUE, repr = c("C", "R", "T"), giveCsparse, factorPatt12, contrasts.arg = NULL) } \arguments{ \item{object}{an object of an appropriate class. For the default method, a model formula or terms object.} \item{data}{a data frame created with \code{\link{model.frame}}. If another sort of object, \code{model.frame} is called first.} \item{contrasts.arg}{\describe{ \item{for \code{sparse.model.matrix()}:}{A list, whose entries are contrasts suitable for input to the \code{\link{contrasts}} replacement function and whose names are the names of columns of \code{data} containing \code{\link{factor}}s.} \item{for \code{fac2Sparse()}:}{character string or \code{NULL} or (coercable to) \code{"\linkS4class{sparseMatrix}"}, specifying the contrasts to be applied to the factor levels.} }} \item{xlev}{to be used as argument of \code{\link{model.frame}} if \code{data} has no \code{"terms"} attribute.} \item{transpose}{logical indicating if the \emph{transpose} should be returned; if the transposed is used anyway, setting \code{transpose = TRUE} is more efficient.} \item{drop.unused.levels}{should factors have unused levels dropped? The default for \code{sparse.model.matrix} has been changed to \code{FALSE}, 2010-07, for compatibility with \R's standard (dense) \code{\link{model.matrix}()}.} \item{row.names}{logical indicating if row names should be used.} \item{sep}{\code{\link{character}} string passed to \code{\link{paste}()} when constructing column names from the variable name and its levels.} \item{verbose}{logical or integer indicating if (and how much) progress output should be printed.} \item{\dots}{further arguments passed to or from other methods.} \item{from}{(for \code{fac2sparse()}:) a \code{\link{factor}}.} \item{to}{a character indicating the \dQuote{kind} of sparse matrix to be returned. The default, \code{"d"} is for \code{\link{double}}.} \item{giveCsparse}{\bold{deprecated}, replaced with \code{repr}; logical indicating if the result must be a \code{\linkS4class{CsparseMatrix}}.} \item{repr}{\code{\link{character}} string, one of \code{"C"}, \code{"T"}, or \code{"R"}, specifying the sparse \emph{repr}esentation to be used for the result, i.e., one from the super classes \code{\linkS4class{CsparseMatrix}}, \code{\linkS4class{TsparseMatrix}}, or \code{\linkS4class{RsparseMatrix}}.} \item{factorPatt12}{logical vector, say \code{fp}, of length two; when \code{fp[1]} is true, return \dQuote{contrasted} \code{t(X)}; when \code{fp[2]} is true, the original (\dQuote{dummy}) \code{t(X)}, i.e, the result of \code{\link{fac2sparse}()}.} } \value{ a sparse matrix, extending \code{\linkS4class{CsparseMatrix}} (for \code{fac2sparse()} if \code{repr = "C"} as per default; a \code{\linkS4class{TsparseMatrix}} or \code{\linkS4class{RsparseMatrix}}, otherwise). For \code{fac2Sparse()}, a \code{\link{list}} of length two, both components with the corresponding transposed model matrix, where the corresponding \code{factorPatt12} is true. \code{fac2sparse()}, the basic workhorse of \code{sparse.model.matrix()}, returns the \emph{transpose} (\code{\link{t}}) of the model matrix. } \note{ \code{model.Matrix(sparse = TRUE)} from package \CRANpkg{MatrixModels} may be nowadays be preferable to \code{sparse.model.matrix}, as \code{model.Matrix} returns an object of class \code{modelMatrix} with additional slots \code{assign} and \code{contrasts} relating to the model variables. } \author{Doug Bates and Martin Maechler, with initial suggestions from Tim Hesterberg. } \seealso{ \code{\link{model.matrix}} in package \pkg{stats}, part of base \R{}. \code{model.Matrix} in package \CRANpkg{MatrixModels}; see \sQuote{Note}. \code{as(f, "sparseMatrix")} (see \code{coerce(from = "factor", ..)} in the class doc \linkS4class{sparseMatrix}) produces the \emph{transposed} sparse model matrix for a single factor \code{f} (and \emph{no} contrasts). } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) } dd <- data.frame(a = gl(3,4), b = gl(4,1,12))# balanced 2-way options("contrasts") # the default: "contr.treatment" sparse.model.matrix(~ a + b, dd) sparse.model.matrix(~ -1+ a + b, dd)# no intercept --> even sparser sparse.model.matrix(~ a + b, dd, contrasts = list(a="contr.sum")) sparse.model.matrix(~ a + b, dd, contrasts = list(b="contr.SAS")) ## Sparse method is equivalent to the traditional one : stopifnot(all(sparse.model.matrix(~ a + b, dd) == Matrix(model.matrix(~ a + b, dd), sparse=TRUE)), all(sparse.model.matrix(~0 + a + b, dd) == Matrix(model.matrix(~0 + a + b, dd), sparse=TRUE))) %% many more and tougher examples ---> ../tests/spModel.matrix.R (ff <- gl(3,4,, c("X","Y", "Z"))) fac2sparse(ff) # 3 x 12 sparse Matrix of class "dgCMatrix" ## ## X 1 1 1 1 . . . . . . . . ## Y . . . . 1 1 1 1 . . . . ## Z . . . . . . . . 1 1 1 1 ## can also be computed via sparse.model.matrix(): f30 <- gl(3,0 ) f12 <- gl(3,0, 12) stopifnot( all.equal(t( fac2sparse(ff) ), sparse.model.matrix(~ 0+ff), tolerance = 0, check.attributes=FALSE), is(M <- fac2sparse(f30, drop= TRUE),"CsparseMatrix"), dim(M) == c(0, 0), is(M <- fac2sparse(f30, drop=FALSE),"CsparseMatrix"), dim(M) == c(3, 0), is(M <- fac2sparse(f12, drop= TRUE),"CsparseMatrix"), dim(M) == c(0,12), is(M <- fac2sparse(f12, drop=FALSE),"CsparseMatrix"), dim(M) == c(3,12) ) } Matrix/man/dgTMatrix-class.Rd0000644000175100001440000000651014473555676015634 0ustar hornikusers\name{dgTMatrix-class} \title{Sparse matrices in triplet form} % \docType{class} \keyword{array} \keyword{classes} % \alias{dgTMatrix-class} % \alias{+,dgTMatrix,dgTMatrix-method} \alias{determinant,dgTMatrix,logical-method} % \description{The \code{"dgTMatrix"} class is the class of sparse matrices stored as (possibly redundant) triplets. The internal representation is not at all unique, contrary to the one for class \code{\linkS4class{dgCMatrix}}. } \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("dgTMatrix", ...)}, but more typically via \code{\link{spMatrix}()} or \code{\link{sparseMatrix}(*, repr = "T")}. } \section{Slots}{ \describe{ \item{\code{i}:}{\code{\link{integer}} row indices of non-zero entries \emph{in 0-base}, i.e., must be in \code{0:(nrow(.)-1)}.} \item{\code{j}:}{\code{\link{integer}} column indices of non-zero entries. Must be the same length as slot \code{i} and \emph{0-based} as well, i.e., in \code{0:(ncol(.)-1)}.} \item{\code{x}:}{\code{\link{numeric}} vector - the (non-zero) entry at position \code{(i,j)}. Must be the same length as slot \code{i}. If an index pair occurs more than once, the corresponding values of slot \code{x} are added to form the element of the matrix.} \item{\code{Dim}:}{Object of class \code{"integer"} of length 2 - the dimensions of the matrix.} } } \section{Methods}{ \describe{ \item{+}{\code{signature(e1 = "dgTMatrix", e2 = "dgTMatrix")}} \item{image}{\code{signature(x = "dgTMatrix")}: plots an image of \code{x} using the \code{\link[lattice]{levelplot}} function} \item{t}{\code{signature(x = "dgTMatrix")}: returns the transpose of \code{x}} } } %\references{} %\author{} \note{Triplet matrices are a convenient form in which to construct sparse matrices after which they can be coerced to \code{\linkS4class{dgCMatrix}} objects. Note that both \code{new(.)} and \code{\link{spMatrix}} constructors for \code{"dgTMatrix"} (and other \code{"\linkS4class{TsparseMatrix}"} classes) implicitly add \eqn{x_k}'s that belong to identical \eqn{(i_k, j_k)} pairs. However this means that a matrix typically can be stored in more than one possible \code{"\linkS4class{TsparseMatrix}"} representations. Use \code{\link{asUniqueT}()} in order to ensure uniqueness of the internal representation of such a matrix. } \seealso{ Class \code{\linkS4class{dgCMatrix}} or the superclasses \code{\linkS4class{dsparseMatrix}} and \code{\linkS4class{TsparseMatrix}}; \code{\link{asUniqueT}}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } m <- Matrix(0+1:28, nrow = 4) m[-3,c(2,4:5,7)] <- m[ 3, 1:4] <- m[1:3, 6] <- 0 (mT <- as(m, "TsparseMatrix")) str(mT) mT[1,] mT[4, drop = FALSE] stopifnot(identical(mT[lower.tri(mT)], m [lower.tri(m) ])) mT[lower.tri(mT,diag=TRUE)] <- 0 mT ## Triplet representation with repeated (i,j) entries ## *adds* the corresponding x's: T2 <- new("dgTMatrix", i = as.integer(c(1,1,0,3,3)), j = as.integer(c(2,2,4,0,0)), x=10*1:5, Dim=4:5) str(T2) # contains (i,j,x) slots exactly as above, but T2 ## has only three non-zero entries, as for repeated (i,j)'s, ## the corresponding x's are "implicitly" added stopifnot(nnzero(T2) == 3) } Matrix/man/diagonalMatrix-class.Rd0000644000175100001440000001104014500445405016641 0ustar hornikusers\name{diagonalMatrix-class} \title{Class "diagonalMatrix" of Diagonal Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{diagonalMatrix-class} % \alias{-,diagonalMatrix,missing-method} \alias{Math,diagonalMatrix-method} \alias{Ops,diagonalMatrix,triangularMatrix-method} \alias{Summary,diagonalMatrix-method} \alias{coerce,diagonalMatrix,symmetricMatrix-method} \alias{coerce,diagonalMatrix,triangularMatrix-method} \alias{coerce,matrix,diagonalMatrix-method} \alias{determinant,diagonalMatrix,logical-method} \alias{diag,diagonalMatrix-method} \alias{diag<-,diagonalMatrix-method} \alias{log,diagonalMatrix-method} \alias{print,diagonalMatrix-method} \alias{show,diagonalMatrix-method} \alias{summary,diagonalMatrix-method} \alias{t,diagonalMatrix-method} % \description{ Class "diagonalMatrix" is the virtual class of all diagonal matrices. } \section{Objects from the Class}{A virtual Class: No objects may be created from it.} \section{Slots}{ \describe{ \item{\code{diag}:}{\code{\link{character}} string, either \code{"U"} or \code{"N"}, where \code{"U"} means \sQuote{unit-diagonal}.} \item{\code{Dim}:}{matrix dimension, and} \item{\code{Dimnames}:}{the \code{\link{dimnames}}, a \code{\link{list}}, see the \code{\linkS4class{Matrix}} class description. Typically \code{list(NULL,NULL)} for diagonal matrices.} } } \section{Extends}{ Class \code{"\linkS4class{sparseMatrix}"}, directly. } \section{Methods}{ These are just a subset of the signature for which defined methods. Currently, there are (too) many explicit methods defined in order to ensure efficient methods for diagonal matrices. \describe{ \item{coerce}{\code{signature(from = "matrix", to = "diagonalMatrix")}: ... } \item{coerce}{\code{signature(from = "Matrix", to = "diagonalMatrix")}: ... } \item{coerce}{\code{signature(from = "diagonalMatrix", to = "generalMatrix")}: ... } \item{coerce}{\code{signature(from = "diagonalMatrix", to = "triangularMatrix")}: ... } \item{coerce}{\code{signature(from = "diagonalMatrix", to = "nMatrix")}: ... } \item{coerce}{\code{signature(from = "diagonalMatrix", to = "matrix")}: ... } \item{coerce}{\code{signature(from = "diagonalMatrix", to = "sparseVector")}: ... } \item{t}{\code{signature(x = "diagonalMatrix")}: ... } \cr and many more methods \item{solve}{\code{signature(a = "diagonalMatrix", b, ...)}: is trivially implemented, of course; see also \code{\link{solve-methods}}.} \item{which}{\code{signature(x = "nMatrix")}, semantically equivalent to \pkg{base} function \code{\link{which}(x, arr.ind)}.} \item{"Math"}{\code{signature(x = "diagonalMatrix")}: all these group methods return a \code{"diagonalMatrix"}, apart from \code{\link{cumsum}()} etc which return a \emph{vector} also for \pkg{base} \code{\link{matrix}}.} \item{*}{\code{signature(e1 = "ddiMatrix", e2="denseMatrix")}: arithmetic and other operators from the \code{\link[=S4groupGeneric]{Ops}} group have a few dozen explicit method definitions, in order to keep the results \emph{diagonal} in many cases, including the following:} \item{/}{\code{signature(e1 = "ddiMatrix", e2="denseMatrix")}: the result is from class \code{\linkS4class{ddiMatrix}} which is typically very desirable. Note that when \code{e2} contains off-diagonal zeros or \code{\link{NA}}s, we implicitly use \eqn{0 / x = 0}, hence differing from traditional \R arithmetic (where \eqn{0 / 0 \mapsto \mbox{NaN}}{0/0 |-> NaN}), in order to preserve sparsity.} \item{summary}{\code{(object = "diagonalMatrix")}: Returns an object of S3 class \code{"diagSummary"} which is the summary of the vector \code{object@x} plus a simple heading, and an appropriate \code{\link{print}} method.} } } \seealso{ \code{\link{Diagonal}()} as constructor of these matrices, and \code{\link{isDiagonal}}. \code{\linkS4class{ddiMatrix}} and \code{\linkS4class{ldiMatrix}} are \dQuote{actual} classes extending \code{"diagonalMatrix"}. } \examples{ I5 <- Diagonal(5) D5 <- Diagonal(x = 10*(1:5)) ## trivial (but explicitly defined) methods: stopifnot(identical(crossprod(I5), I5), identical(tcrossprod(I5), I5), identical(crossprod(I5, D5), D5), identical(tcrossprod(D5, I5), D5), identical(solve(D5), solve(D5, I5)), all.equal(D5, solve(solve(D5)), tolerance = 1e-12) ) solve(D5)# efficient as is diagonal # an unusual way to construct a band matrix: rbind2(cbind2(I5, D5), cbind2(D5, I5)) } Matrix/man/dgeMatrix-class.Rd0000644000175100001440000000666014500445405015636 0ustar hornikusers\name{dgeMatrix-class} \title{Class "dgeMatrix" of Dense Numeric (S4 Class) Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{dgeMatrix-class} % \alias{Arith,dgeMatrix,dgeMatrix-method} \alias{Arith,dgeMatrix,logical-method} \alias{Arith,dgeMatrix,numeric-method} \alias{Arith,dgeMatrix,sparseVector-method} \alias{Arith,logical,dgeMatrix-method} \alias{Arith,numeric,dgeMatrix-method} \alias{determinant,dgeMatrix,logical-method} % \description{A general numeric dense matrix in the S4 Matrix representation. \code{dgeMatrix} is the \emph{\dQuote{standard}} class for dense numeric matrices in the \pkg{Matrix} package. } \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("dgeMatrix", ...)} or, more commonly, by coercion from the \code{Matrix} class (see \linkS4class{Matrix}) or by \code{\link{Matrix}(..)}. } \section{Slots}{ \describe{ \item{\code{x}:}{Object of class \code{"numeric"} - the numeric values contained in the matrix, in column-major order.} \item{\code{Dim}:}{Object of class \code{"integer"} - the dimensions of the matrix - must be an integer vector with exactly two non-negative values.} \item{\code{Dimnames}:}{a list of length two - inherited from class \code{\linkS4class{Matrix}}.} \item{\code{factors}:}{Object of class \code{"list"} - a list of factorizations of the matrix.} } } \section{Methods}{ The are group methods (see, e.g., \code{\link{Arith}}) \describe{ \item{Arith}{\code{signature(e1 = "dgeMatrix", e2 = "dgeMatrix")}: ... } \item{Arith}{\code{signature(e1 = "dgeMatrix", e2 = "numeric")}: ... } \item{Arith}{\code{signature(e1 = "numeric", e2 = "dgeMatrix")}: ... } \item{Math}{\code{signature(x = "dgeMatrix")}: ... } \item{Math2}{\code{signature(x = "dgeMatrix", digits = "numeric")}: ...} } matrix products \code{\link[=crossprod-methods]{\%*\%}}, \code{\link[=crossprod-methods]{crossprod}()} and \code{tcrossprod()}, several \code{\link{solve}} methods, and other matrix methods available: \describe{ \item{Schur}{\code{signature(x = "dgeMatrix", vectors = "logical")}: ... } \item{Schur}{\code{signature(x = "dgeMatrix", vectors = "missing")}: ... } \item{chol}{\code{signature(x = "dgeMatrix")}: see \code{\link{chol}}.} \item{colMeans}{\code{signature(x = "dgeMatrix")}: columnwise means (averages)} \item{colSums}{\code{signature(x = "dgeMatrix")}: columnwise sums} \item{diag}{\code{signature(x = "dgeMatrix")}: ... } \item{dim}{\code{signature(x = "dgeMatrix")}: ... } \item{dimnames}{\code{signature(x = "dgeMatrix")}: ... } \item{eigen}{\code{signature(x = "dgeMatrix", only.values= "logical")}: ...} \item{eigen}{\code{signature(x = "dgeMatrix", only.values= "missing")}: ...} \item{norm}{\code{signature(x = "dgeMatrix", type = "character")}: ... } \item{norm}{\code{signature(x = "dgeMatrix", type = "missing")}: ... } \item{rcond}{\code{signature(x = "dgeMatrix", norm = "character")} or \code{norm = "missing"}: the reciprocal condition number, \code{\link{rcond}()}.} \item{rowMeans}{\code{signature(x = "dgeMatrix")}: rowwise means (averages)} \item{rowSums}{\code{signature(x = "dgeMatrix")}: rowwise sums} \item{t}{\code{signature(x = "dgeMatrix")}: matrix transpose} } } \seealso{ Classes \code{\linkS4class{Matrix}}, \code{\linkS4class{dtrMatrix}}, and \code{\linkS4class{dsyMatrix}}. } %\examples{} Matrix/man/lu-methods.Rd0000644000175100001440000001434314575137654014705 0ustar hornikusers\name{lu-methods} \title{Methods for LU Factorization} % \docType{methods} \keyword{algebra} \keyword{array} \keyword{methods} % \alias{lu} \alias{lu-methods} % \alias{lu,denseMatrix-method} \alias{lu,diagonalMatrix-method} \alias{lu,dgCMatrix-method} \alias{lu,dgRMatrix-method} \alias{lu,dgTMatrix-method} \alias{lu,dgeMatrix-method} \alias{lu,dsCMatrix-method} \alias{lu,dsRMatrix-method} \alias{lu,dsTMatrix-method} \alias{lu,dspMatrix-method} \alias{lu,dsyMatrix-method} \alias{lu,dtCMatrix-method} \alias{lu,dtRMatrix-method} \alias{lu,dtTMatrix-method} \alias{lu,dtpMatrix-method} \alias{lu,dtrMatrix-method} \alias{lu,matrix-method} \alias{lu,sparseMatrix-method} % \description{ Computes the pivoted LU factorization of an \eqn{m \times n}{m-by-n} real matrix \eqn{A}, which has the general form \deqn{P_{1} A P_{2} = L U}{P1 * A * P2 = L * U} or (equivalently) \deqn{A = P_{1}' L U P_{2}'}{A = P1' * L * U * P2'} where \eqn{P_{1}}{P1} is an \eqn{m \times m}{m-by-m} permutation matrix, \eqn{P_{2}}{P2} is an \eqn{n \times n}{n-by-n} permutation matrix, \eqn{L} is an \eqn{m \times \min(m,n)}{m-by-min(m,n)} unit lower trapezoidal matrix, and \eqn{U} is a \eqn{\min(m,n) \times n}{min(m,n)-by-n} upper trapezoidal matrix. Methods for \code{\linkS4class{denseMatrix}} are built on LAPACK routine \code{dgetrf}, which does not permute columns, so that \eqn{P_{2}}{P2} is an identity matrix. Methods for \code{\linkS4class{sparseMatrix}} are built on CXSparse routine \code{cs_lu}, which requires \eqn{m = n}, so that \eqn{L} and \eqn{U} are triangular matrices. } \usage{ lu(x, \dots) \S4method{lu}{dgeMatrix}(x, warnSing = TRUE, \dots) \S4method{lu}{dgCMatrix}(x, errSing = TRUE, order = NA_integer_, tol = 1, \dots) \S4method{lu}{dsyMatrix}(x, cache = TRUE, \dots) \S4method{lu}{dsCMatrix}(x, cache = TRUE, \dots) \S4method{lu}{matrix}(x, \dots) } \arguments{ \item{x}{a \link[=is.finite]{finite} matrix or \code{\linkS4class{Matrix}} to be factorized, which must be square if sparse.} \item{warnSing}{a logical indicating if a \link{warning} should be signaled for singular \code{x}. Used only by methods for dense matrices.} \item{errSing}{a logical indicating if an \link[=stop]{error} should be signaled for singular \code{x}. Used only by methods for sparse matrices.} \item{order}{an integer in \code{0:3} passed to CXSparse routine \code{cs_sqr}, indicating a strategy for choosing the column permutation \eqn{P_{2}}{P2}. 0 means no column permutation. 1, 2, and 3 indicate a fill-reducing ordering of \eqn{A + A'}, \eqn{\tilde{A}' \tilde{A}}{A~' * A~}, and \eqn{A' A}{A' * A}, where \eqn{\tilde{A}}{A~} is \eqn{A} with \dQuote{dense} rows removed. \code{NA} (the default) is equivalent to 2 if \code{tol == 1} and 1 otherwise. Do not set to 0 unless you know that the column order of \eqn{A} is already sensible.} \item{tol}{a number. The original pivot element is used if its absolute value exceeds \code{tol * a}, where \code{a} is the maximum in absolute value of the other possible pivot elements. Set \code{tol < 1} only if you know what you are doing.} \item{cache}{a logical indicating if the result should be cached in \code{x@factors[["LU"]]}. Note that caching is experimental and that only methods for classes extending \code{\linkS4class{generalMatrix}} or \code{\linkS4class{symmetricMatrix}} will have this argument.} \item{\dots}{further arguments passed to or from methods.} } \value{ An object representing the factorization, inheriting from virtual class \code{\linkS4class{LU}}. The specific class is \code{\linkS4class{denseLU}} unless \code{x} inherits from virtual class \code{\linkS4class{sparseMatrix}}, in which case it is \code{\linkS4class{sparseLU}}. } \details{ What happens when \code{x} is determined to be near-singular differs by method. The method for class \code{\linkS4class{dgeMatrix}} completes the factorization, warning if \code{warnSing = TRUE} and in any case returning a valid \code{\linkS4class{denseLU}} object. Users of this method can detect singular \code{x} with a suitable warning handler; see \code{\link{tryCatch}}. In contrast, the method for class \code{\linkS4class{dgCMatrix}} abandons further computation, throwing an error if \code{errSing = TRUE} and otherwise returning \code{NA}. Users of this method can detect singular \code{x} with an error handler or by setting \code{errSing = FALSE} and testing for a formal result with \code{is(., "sparseLU")}. } \seealso{ Classes \code{\linkS4class{denseLU}} and \code{\linkS4class{sparseLU}} and their methods. Classes \code{\linkS4class{dgeMatrix}} and \code{\linkS4class{dgCMatrix}}. Generic functions \code{\link{expand1}} and \code{\link{expand2}}, for constructing matrix factors from the result. Generic functions \code{\link{Cholesky}}, \code{\link{BunchKaufman}}, \code{\link{Schur}}, and \code{\link{qr}}, for computing other factorizations. } \references{ The LAPACK source code, including documentation; see \url{https://netlib.org/lapack/double/dgetrf.f}. Davis, T. A. (2006). \emph{Direct methods for sparse linear systems}. Society for Industrial and Applied Mathematics. \doi{10.1137/1.9780898718881} Golub, G. H., & Van Loan, C. F. (2013). \emph{Matrix computations} (4th ed.). Johns Hopkins University Press. \doi{10.56021/9781421407944} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } showMethods("lu", inherited = FALSE) set.seed(0) ## ---- Dense ---------------------------------------------------------- (A1 <- Matrix(rnorm(9L), 3L, 3L)) (lu.A1 <- lu(A1)) (A2 <- round(10 * A1[, -3L])) (lu.A2 <- lu(A2)) ## A ~ P1' L U in floating point str(e.lu.A2 <- expand2(lu.A2), max.level = 2L) stopifnot(all.equal(A2, Reduce(`\%*\%`, e.lu.A2))) ## ---- Sparse --------------------------------------------------------- A3 <- as(readMM(system.file("external/pores_1.mtx", package = "Matrix")), "CsparseMatrix") (lu.A3 <- lu(A3)) ## A ~ P1' L U P2' in floating point str(e.lu.A3 <- expand2(lu.A3), max.level = 2L) stopifnot(all.equal(A3, Reduce(`\%*\%`, e.lu.A3))) } Matrix/man/coerce-methods-SparseM.Rd0000644000175100001440000000501414575137654017070 0ustar hornikusers\name{coerce-methods-SparseM} \title{Sparse Matrix Coercion from and to those from package \pkg{SparseM}} % \docType{methods} \keyword{methods} % \alias{coerce-methods-SparseM} % \alias{coerce,Matrix,matrix.coo-method} \alias{coerce,Matrix,matrix.csc-method} \alias{coerce,Matrix,matrix.csr-method} \alias{coerce,dgCMatrix,matrix.csc-method} \alias{coerce,dgRMatrix,matrix.csr-method} \alias{coerce,dgTMatrix,matrix.coo-method} % \alias{coerce,matrix.coo,CsparseMatrix-method} \alias{coerce,matrix.coo,Matrix-method} \alias{coerce,matrix.coo,RsparseMatrix-method} \alias{coerce,matrix.coo,TsparseMatrix-method} \alias{coerce,matrix.coo,dgCMatrix-method} \alias{coerce,matrix.coo,dgTMatrix-method} \alias{coerce,matrix.coo,sparseMatrix-method} % \alias{coerce,matrix.csc,CsparseMatrix-method} \alias{coerce,matrix.csc,Matrix-method} \alias{coerce,matrix.csc,RsparseMatrix-method} \alias{coerce,matrix.csc,TsparseMatrix-method} \alias{coerce,matrix.csc,dgCMatrix-method} \alias{coerce,matrix.csc,sparseMatrix-method} % \alias{coerce,matrix.csr,CsparseMatrix-method} \alias{coerce,matrix.csr,Matrix-method} \alias{coerce,matrix.csr,RsparseMatrix-method} \alias{coerce,matrix.csr,TsparseMatrix-method} \alias{coerce,matrix.csr,dgCMatrix-method} \alias{coerce,matrix.csr,dgRMatrix-method} \alias{coerce,matrix.csr,sparseMatrix-method} % \description{ Methods for coercion from and to sparse matrices from package \pkg{SparseM} are provided here, for ease of porting functionality to the \pkg{Matrix} package, and comparing functionality of the two packages. All these work via the usual \code{\link{as}(., "")} coercion, \preformatted{ as(from, Class) }%pre } \section{Methods}{ \describe{ \item{from = "matrix.csr", to = "dgRMatrix"}{ ... } \item{from = "matrix.csc", to = "dgCMatrix"}{ ... } \item{from = "matrix.coo", to = "dgTMatrix"}{ ... } \item{from = "dgRMatrix", to = "matrix.csr"}{ ... } \item{from = "dgCMatrix", to = "matrix.csc"}{ ... } \item{from = "dgTMatrix", to = "matrix.coo"}{ ... } \item{from = "Matrix", to = "matrix.csr"}{ ... } \item{from = "matrix.csr", to = "dgCMatrix"}{ ... } \item{from = "matrix.coo", to = "dgCMatrix"}{ ... } \item{from = "matrix.csr", to = "Matrix"}{ ... } \item{from = "matrix.csc", to = "Matrix"}{ ... } \item{from = "matrix.coo", to = "Matrix"}{ ... } } } \seealso{ The documentation in CRAN package \CRANpkg{SparseM}, such as \code{\link[SparseM]{SparseM.ontology}}, and one important class, \code{\link[SparseM:matrix.csr-class]{matrix.csr}}. } Matrix/man/dpoMatrix-class.Rd0000644000175100001440000001425714565737512015700 0ustar hornikusers\name{dpoMatrix-class} \title{Positive Semi-definite Dense (Packed | Non-packed) Numeric Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{dpoMatrix-class} \alias{dppMatrix-class} \alias{corMatrix-class} \alias{copMatrix-class} % \alias{Arith,dpoMatrix,logical-method} \alias{Arith,dpoMatrix,numeric-method} \alias{Arith,logical,dpoMatrix-method} \alias{Arith,numeric,dpoMatrix-method} \alias{Ops,dpoMatrix,logical-method} \alias{Ops,dpoMatrix,numeric-method} \alias{Ops,logical,dpoMatrix-method} \alias{Ops,numeric,dpoMatrix-method} \alias{coerce,dpoMatrix,corMatrix-method} \alias{coerce,dpoMatrix,dppMatrix-method} \alias{coerce,matrix,dpoMatrix-method} \alias{determinant,dpoMatrix,logical-method} % \alias{Arith,dppMatrix,logical-method} \alias{Arith,dppMatrix,numeric-method} \alias{Arith,logical,dppMatrix-method} \alias{Arith,numeric,dppMatrix-method} \alias{Ops,dppMatrix,logical-method} \alias{Ops,dppMatrix,numeric-method} \alias{Ops,logical,dppMatrix-method} \alias{Ops,numeric,dppMatrix-method} \alias{coerce,dppMatrix,copMatrix-method} \alias{coerce,dppMatrix,dpoMatrix-method} \alias{coerce,matrix,dppMatrix-method} \alias{determinant,dppMatrix,logical-method} % \alias{coerce,corMatrix,copMatrix-method} \alias{coerce,matrix,corMatrix-method} % \alias{coerce,copMatrix,corMatrix-method} \alias{coerce,matrix,copMatrix-method} % \description{ \itemize{ \item The \code{"dpoMatrix"} class is the class of positive-semidefinite symmetric matrices in nonpacked storage. \item The \code{"dppMatrix"} class is the same except in packed storage. Only the upper triangle or the lower triangle is required to be available. \item The \code{"corMatrix"} and \code{"copMatrix"} classes represent correlation matrices. They extend \code{"dpoMatrix"} and \code{"dppMatrix"}, respectively, with an additional slot \code{sd} allowing restoration of the original covariance matrix. } } \section{Objects from the Class}{Objects can be created by calls of the form \code{new("dpoMatrix", ...)} or from \code{crossprod} applied to an \code{"dgeMatrix"} object.} \section{Slots}{ \describe{ \item{\code{uplo}:}{Object of class \code{"character"}. Must be either "U", for upper triangular, and "L", for lower triangular.} \item{\code{x}:}{Object of class \code{"numeric"}. The numeric values that constitute the matrix, stored in column-major order.} \item{\code{Dim}:}{Object of class \code{"integer"}. The dimensions of the matrix which must be a two-element vector of non-negative integers.} \item{\code{Dimnames}:}{inherited from class \code{"Matrix"}} \item{\code{factors}:}{Object of class \code{"list"}. A named list of factorizations that have been computed for the matrix.} \item{\code{sd}:}{(for \code{"corMatrix"} and \code{"copMatrix"}) a \code{\link{numeric}} vector of length \code{n} containing the (original) \eqn{\sqrt{var(.)}}{sqrt(var(.))} entries which allow reconstruction of a covariance matrix from the correlation matrix.} } } \section{Extends}{ Class \code{"dsyMatrix"}, directly.\cr Classes \code{"dgeMatrix"}, \code{"symmetricMatrix"}, and many more by class \code{"dsyMatrix"}. } \section{Methods}{ \describe{ \item{chol}{\code{signature(x = "dpoMatrix")}: Returns (and stores) the Cholesky decomposition of \code{x}, see \code{\link{chol}}.} \item{determinant}{\code{signature(x = "dpoMatrix")}: Returns the \code{\link{determinant}} of \code{x}, via \code{chol(x)}, see above.} \item{rcond}{\code{signature(x = "dpoMatrix", norm = "character")}: Returns (and stores) the reciprocal of the condition number of \code{x}. The \code{norm} can be \code{"O"} for the one-norm (the default) or \code{"I"} for the infinity-norm. For symmetric matrices the result does not depend on the norm.} \item{solve}{\code{signature(a = "dpoMatrix", b = "....")}, and} \item{solve}{\code{signature(a = "dppMatrix", b = "....")} work via the Cholesky composition, see also the Matrix \code{\link{solve-methods}}.} \item{Arith}{\code{signature(e1 = "dpoMatrix", e2 = "numeric")} (and quite a few other signatures): The result of (\dQuote{elementwise} defined) arithmetic operations is typically \emph{not} positive-definite anymore. The only exceptions, currently, are multiplications, divisions or additions with \emph{positive} \code{length(.) == 1} numbers (or \code{\link{logical}}s).} } } %\references{} %\author{} \note{Currently the validity methods for these classes such as \code{\link{getValidity}(getClass("dpoMatrix"))} for efficiency reasons only check the diagonal entries of the matrix -- they may not be negative. This is only necessary but not sufficient for a symmetric matrix to be positive semi-definite. A more reliable (but often more expensive) check for positive semi-definiteness would look at the signs of \code{diag(\link{BunchKaufman}(.))} (with some tolerance for very small negative values), and for (strict) positive definiteness at something like \code{!inherits(tryCatch(chol(.), error=identity), "error")} . Indeed, when \emph{coercing} to these classes, a version of \code{\link{Cholesky}()} or \code{\link{chol}()} is typically used, e.g., see \code{selectMethod("coerce", c(from="dsyMatrix", to="dpoMatrix"))} . } \seealso{ Classes \code{\linkS4class{dsyMatrix}} and \code{\linkS4class{dgeMatrix}}; further, \code{\link{Matrix}}, \code{\link{rcond}}, \code{\link[base]{chol}}, \code{\link[base]{solve}}, \code{\link{crossprod}}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } h6 <- Hilbert(6) rcond(h6) str(h6) h6 * 27720 # is ``integer'' solve(h6) str(hp6 <- pack(h6)) ### Note that as(*, "corMatrix") *scales* the matrix (ch6 <- as(h6, "corMatrix")) stopifnot(all.equal(as(h6 * 27720, "dsyMatrix"), round(27720 * h6), tolerance = 1e-14), all.equal(ch6@sd^(-2), 2*(1:6)-1, tolerance = 1e-12)) chch <- Cholesky(ch6, perm = FALSE) stopifnot(identical(chch, ch6@factors$Cholesky), all(abs(crossprod(as(chch, "dtrMatrix")) - ch6) < 1e-10)) } Matrix/man/abIndex-class.Rd0000644000175100001440000001027214461513642015263 0ustar hornikusers\name{abIndex-class} \title{Class "abIndex" of Abstract Index Vectors} % \docType{class} \keyword{classes} % \alias{abIndex-class} \alias{seqMat-class} % not yet documented {unexported} % \alias{Arith,abIndex,abIndex-method} \alias{Arith,abIndex,numLike-method} \alias{Arith,numLike,abIndex-method} \alias{Ops,ANY,abIndex-method} \alias{Ops,abIndex,ANY-method} \alias{Ops,abIndex,abIndex-method} \alias{Summary,abIndex-method} \alias{as.integer,abIndex-method} \alias{as.numeric,abIndex-method} \alias{as.vector,abIndex-method} \alias{coerce,abIndex,integer-method} \alias{coerce,abIndex,numeric-method} \alias{coerce,abIndex,seqMat-method} \alias{coerce,abIndex,vector-method} \alias{coerce,logical,abIndex-method} \alias{coerce,numeric,abIndex-method} \alias{drop,abIndex-method} \alias{length,abIndex-method} \alias{show,abIndex-method} % \alias{coerce,numeric,seqMat-method} \alias{coerce,seqMat,abIndex-method} \alias{coerce,seqMat,numeric-method} % \description{ The \code{"abIndex"} \code{\link{class}}, short for \dQuote{Abstract Index Vector}, is used for dealing with large index vectors more efficiently, than using integer (or \code{\link{numeric}}) vectors of the kind \code{2:1000000} or \code{c(0:1e5, 1000:1e6)}. Note that the current implementation details are subject to change, and if you consider working with these classes, please contact the package maintainers (\code{packageDescription("Matrix")$Maintainer}). } \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("abIndex", ...)}, but more easily and typically either by \code{as(x, "abIndex")} where \code{x} is an integer (valued) vector, or directly by \code{\link{abIseq}()} and combination \code{\link{c}(...)} of such. } \section{Slots}{ \describe{ \item{\code{kind}:}{a \code{\link{character}} string, one of \code{("int32", "double", "rleDiff")}, denoting the internal structure of the abIndex object.} \item{\code{x}:}{Object of class \code{"numLike"}; is used (i.e., not of length \code{0}) only iff the object is \emph{not} compressed, i.e., currently exactly when \code{kind != "rleDiff"}.} \item{\code{rleD}:}{object of class \code{"\linkS4class{rleDiff}"}, used for compression via \code{\link{rle}}.} } } \section{Methods}{ \describe{ \item{as.numeric, as.integer, as.vector}{\code{signature(x = "abIndex")}: ... } \item{[}{\code{signature(x = "abIndex", i = "index", j = "ANY", drop = "ANY")}: ... } \item{coerce}{\code{signature(from = "numeric", to = "abIndex")}: ... } \item{coerce}{\code{signature(from = "abIndex", to = "numeric")}: ... } \item{coerce}{\code{signature(from = "abIndex", to = "integer")}: ... } \item{length}{\code{signature(x = "abIndex")}: ... } \item{Ops}{\code{signature(e1 = "numeric", e2 = "abIndex")}: These and the following arithmetic and logic operations are \bold{not yet implemented}; see \code{\link[methods]{Ops}} for a list of these (S4) group methods.} \item{Ops}{\code{signature(e1 = "abIndex", e2 = "abIndex")}: ... } \item{Ops}{\code{signature(e1 = "abIndex", e2 = "numeric")}: ... } \item{Summary}{\code{signature(x = "abIndex")}: ... } \item{show}{\code{("abIndex")}: simple \code{\link{show}} method, building on \code{show()}.} \item{is.na}{\code{("abIndex")}: works analogously to regular vectors.} \item{is.finite, is.infinite}{\code{("abIndex")}: ditto.} } } \note{ This is currently experimental and not yet used for our own code. Please contact us (\code{packageDescription("Matrix")$Maintainer}), if you plan to make use of this class. Partly builds on ideas and code from Jens Oehlschlaegel, as implemented (around 2008, in the GPL'ed part of) package \pkg{ff}. } %\author{Martin Maechler} \seealso{ \code{\link{rle}} (\pkg{base}) which is used here; \code{\link{numeric}}% ... FIXME } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } showClass("abIndex") ii <- c(-3:40, 20:70) str(ai <- as(ii, "abIndex"))# note ai # -> show() method %% FIXME: add / exchange with ../tests/abIndex-tsts.R stopifnot(identical(-3:20, as(abIseq1(-3,20), "vector"))) } Matrix/man/nearPD.Rd0000644000175100001440000002064714446607050013766 0ustar hornikusers\name{nearPD} \title{Nearest Positive Definite Matrix} % \keyword{algebra} \keyword{array} \keyword{utilities} % \alias{nearPD} % \description{ Compute the nearest positive definite matrix to an approximate one, typically a correlation or variance-covariance matrix. } \usage{ nearPD(x, corr = FALSE, keepDiag = FALSE, base.matrix = FALSE, do2eigen = TRUE, doSym = FALSE, doDykstra = TRUE, only.values = FALSE, ensureSymmetry = !isSymmetric(x), eig.tol = 1e-06, conv.tol = 1e-07, posd.tol = 1e-08, maxit = 100, conv.norm.type = "I", trace = FALSE) } \arguments{ \item{x}{numeric \eqn{n \times n}{n * n} approximately positive definite matrix, typically an approximation to a correlation or covariance matrix. If \code{x} is not symmetric (and \code{ensureSymmetry} is not false), \code{\link{symmpart}(x)} is used.} \item{corr}{logical indicating if the matrix should be a \emph{correlation} matrix.} \item{keepDiag}{logical, generalizing \code{corr}: if \code{TRUE}, the resulting matrix should have the same diagonal (\code{\link{diag}(x)}) as the input matrix.} \item{base.matrix}{logical indicating if the resulting \code{mat} component should be a \pkg{base} \code{\link{matrix}} or (by default) a \code{\linkS4class{Matrix}} of class \code{\linkS4class{dpoMatrix}}.} \item{do2eigen}{logical indicating if a \code{\link[sfsmisc]{posdefify}()} eigen step should be applied to the result of the Higham algorithm.} \item{doSym}{logical indicating if \code{X <- (X + t(X))/2} should be done, after \code{X <- tcrossprod(Qd, Q)}; some doubt if this is necessary.} \item{doDykstra}{logical indicating if Dykstra's correction should be used; true by default. If false, the algorithm is basically the direct fixpoint iteration \eqn{Y_k = P_U(P_S(Y_{k-1}))}{Y(k) = P_U(P_S(Y(k-1)))}.} \item{only.values}{logical; if \code{TRUE}, the result is just the vector of eigenvalues of the approximating matrix.} \item{ensureSymmetry}{logical; by default, \code{\link{symmpart}(x)} is used whenever \code{\link{isSymmetric}(x)} is not true. The user can explicitly set this to \code{TRUE} or \code{FALSE}, saving the symmetry test. \emph{Beware} however that setting it \code{FALSE} for an \bold{a}symmetric input \code{x}, is typically nonsense!} \item{eig.tol}{defines relative positiveness of eigenvalues compared to largest one, \eqn{\lambda_1}. Eigenvalues \eqn{\lambda_k} are treated as if zero when \eqn{\lambda_k / \lambda_1 \le eig.tol}.} \item{conv.tol}{convergence tolerance for Higham algorithm.} \item{posd.tol}{tolerance for enforcing positive definiteness (in the final \code{posdefify} step when \code{do2eigen} is \code{TRUE}).} \item{maxit}{maximum number of iterations allowed.} \item{conv.norm.type}{convergence norm type (\code{\link{norm}(*, type)}) used for Higham algorithm. The default is \code{"I"} (infinity), for reasons of speed (and back compatibility); using \code{"F"} is more in line with Higham's proposal.} \item{trace}{logical or integer specifying if convergence monitoring should be traced.} } \details{ This implements the algorithm of Higham (2002), and then (if \code{do2eigen} is true) forces positive definiteness using code from \code{\link[sfsmisc]{posdefify}}. The algorithm of Knol and ten Berge (1989) (not implemented here) is more general in that it allows constraints to (1) fix some rows (and columns) of the matrix and (2) force the smallest eigenvalue to have a certain value. Note that setting \code{corr = TRUE} just sets \code{diag(.) <- 1} within the algorithm. Higham (2002) uses Dykstra's correction, but the version by Jens \enc{Oehlschlägel}{Oehlschlaegel} did not use it (accidentally), and still gave reasonable results; this simplification, now only used if \code{doDykstra = FALSE}, was active in \code{nearPD()} up to Matrix version 0.999375-40. } \value{ If \code{only.values = TRUE}, a numeric vector of eigenvalues of the approximating matrix; Otherwise, as by default, an S3 object of \code{\link{class}} \code{"nearPD"}, basically a list with components \item{mat}{a matrix of class \code{\linkS4class{dpoMatrix}}, the computed positive-definite matrix.} \item{eigenvalues}{numeric vector of eigenvalues of \code{mat}.} \item{corr}{logical, just the argument \code{corr}.} \item{normF}{the Frobenius norm (\code{\link{norm}(x-X, "F")}) of the difference between the original and the resulting matrix.} \item{iterations}{number of iterations needed.} \item{converged}{logical indicating if iterations converged.} } \references{%% more in /u/maechler/R/Pkgs/sfsmisc/man/posdefify.Rd Cheng, Sheung Hun and Higham, Nick (1998) A Modified Cholesky Algorithm Based on a Symmetric Indefinite Factorization; \emph{SIAM J. Matrix Anal.\ Appl.}, \bold{19}, 1097--1110. Knol DL, ten Berge JMF (1989) Least-squares approximation of an improper correlation matrix by a proper one. \emph{Psychometrika} \bold{54}, 53--61. Higham, Nick (2002) Computing the nearest correlation matrix - a problem from finance; \emph{IMA Journal of Numerical Analysis} \bold{22}, 329--343. } \author{ Jens \enc{Oehlschlägel}{Oehlschlaegel} donated a first version. Subsequent changes by the Matrix package authors. } \seealso{A first version of this (with non-optional \code{corr=TRUE}) has been available as \code{\link[sfsmisc]{nearcor}()}; and more simple versions with a similar purpose \code{\link[sfsmisc]{posdefify}()}, both from package \pkg{sfsmisc}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library( stats, pos = "package:base", verbose = FALSE) library( graphics, pos = "package:base", verbose = FALSE) library(grDevices, pos = "package:base", verbose = FALSE) library( utils, pos = "package:base", verbose = FALSE) } ## Higham(2002), p.334f - simple example A <- matrix(1, 3,3); A[1,3] <- A[3,1] <- 0 n.A <- nearPD(A, corr=TRUE, do2eigen=FALSE) n.A[c("mat", "normF")] n.A.m <- nearPD(A, corr=TRUE, do2eigen=FALSE, base.matrix=TRUE)$mat stopifnot(exprs = { #=-------------- all.equal(n.A$mat[1,2], 0.760689917) all.equal(n.A$normF, 0.52779033, tolerance=1e-9) all.equal(n.A.m, unname(as.matrix(n.A$mat)), tolerance = 1e-15)# seen rel.d.= 1.46e-16 }) set.seed(27) m <- matrix(round(rnorm(25),2), 5, 5) m <- m + t(m) diag(m) <- pmax(0, diag(m)) + 1 (m <- round(cov2cor(m), 2)) str(near.m <- nearPD(m, trace = TRUE)) round(near.m$mat, 2) norm(m - near.m$mat) # 1.102 / 1.08 if(requireNamespace("sfsmisc")) { m2 <- sfsmisc::posdefify(m) # a simpler approach norm(m - m2) # 1.185, i.e., slightly "less near" } round(nearPD(m, only.values=TRUE), 9) ## A longer example, extended from Jens' original, ## showing the effects of some of the options: pr <- Matrix(c(1, 0.477, 0.644, 0.478, 0.651, 0.826, 0.477, 1, 0.516, 0.233, 0.682, 0.75, 0.644, 0.516, 1, 0.599, 0.581, 0.742, 0.478, 0.233, 0.599, 1, 0.741, 0.8, 0.651, 0.682, 0.581, 0.741, 1, 0.798, 0.826, 0.75, 0.742, 0.8, 0.798, 1), nrow = 6, ncol = 6) nc. <- nearPD(pr, conv.tol = 1e-7) # default nc.$iterations # 2 nc.1 <- nearPD(pr, conv.tol = 1e-7, corr = TRUE) nc.1$iterations # 11 / 12 (!) ncr <- nearPD(pr, conv.tol = 1e-15) str(ncr)# still 2 iterations ncr.1 <- nearPD(pr, conv.tol = 1e-15, corr = TRUE) ncr.1 $ iterations # 27 / 30 ! ncF <- nearPD(pr, conv.tol = 1e-15, conv.norm = "F") stopifnot(all.equal(ncr, ncF))# norm type does not matter at all in this example ## But indeed, the 'corr = TRUE' constraint did ensure a better solution; ## cov2cor() does not just fix it up equivalently : norm(pr - cov2cor(ncr$mat)) # = 0.09994 norm(pr - ncr.1$mat) # = 0.08746 / 0.08805 ### 3) a real data example from a 'systemfit' model (3 eq.): (load(system.file("external", "symW.rda", package="Matrix"))) # "symW" dim(symW) # 24 x 24 class(symW)# "dsCMatrix": sparse symmetric if(dev.interactive()) image(symW) EV <- eigen(symW, only=TRUE)$values summary(EV) ## looking more closely {EV sorted decreasingly}: tail(EV)# all 6 are negative EV2 <- eigen(sWpos <- nearPD(symW)$mat, only=TRUE)$values stopifnot(EV2 > 0) if(requireNamespace("sfsmisc")) { plot(pmax(1e-3,EV), EV2, type="o", log="xy", xaxt="n", yaxt="n") for(side in 1:2) sfsmisc::eaxis(side) } else plot(pmax(1e-3,EV), EV2, type="o", log="xy") abline(0, 1, col="red3", lty=2) } Matrix/man/Cholesky-methods.Rd0000644000175100001440000003654414575234535016051 0ustar hornikusers\name{Cholesky-methods} \title{Methods for Cholesky Factorization} % \docType{methods} \keyword{algebra} \keyword{array} \keyword{methods} \concept{Choleski} % alternate English spelling % \alias{Cholesky} \alias{Cholesky-methods} % \alias{Cholesky,ddiMatrix-method} \alias{Cholesky,diagonalMatrix-method} \alias{Cholesky,dsCMatrix-method} \alias{Cholesky,dsRMatrix-method} \alias{Cholesky,dsTMatrix-method} \alias{Cholesky,dspMatrix-method} \alias{Cholesky,dsyMatrix-method} \alias{Cholesky,generalMatrix-method} \alias{Cholesky,matrix-method} \alias{Cholesky,symmetricMatrix-method} \alias{Cholesky,triangularMatrix-method} % \description{ Computes the pivoted Cholesky factorization of an \eqn{n \times n}{n-by-n} real, symmetric matrix \eqn{A}, which has the general form \deqn{P_1 A P_1' = L_1 D L_1' \overset{D_{jj} \ge 0}{=} L L'}{P1 * A * P1' = L1 * D * L1' [ = L * L' ]} or (equivalently) \deqn{A = P_1' L_1 D L_1' P_1 \overset{D_{jj} \ge 0}{=} P_1' L L' P_1}{A = P1' L1 * D * L1' * P1 [ = P1' * L * L' * P1 ]} where \eqn{P_1}{P1} is a permutation matrix, \eqn{L_1}{L1} is a unit lower triangular matrix, \eqn{D} is a diagonal matrix, and \eqn{L = L_1 \sqrt{D}}{L = L1 * sqrt(D)}. The second equalities hold only for positive semidefinite \eqn{A}, for which the diagonal entries of \eqn{D} are non-negative and \eqn{\sqrt{D}}{sqrt(D)} is well-defined. Methods for \code{\linkS4class{denseMatrix}} are built on LAPACK routines \code{dpstrf}, \code{dpotrf}, and \code{dpptrf}. The latter two do not permute rows or columns, so that \eqn{P_1}{P1} is an identity matrix. Methods for \code{\linkS4class{sparseMatrix}} are built on CHOLMOD routines \code{cholmod_analyze} and \code{cholmod_factorize_p}. } \usage{ Cholesky(A, \dots) \S4method{Cholesky}{dsyMatrix}(A, perm = TRUE, tol = -1, \dots) \S4method{Cholesky}{dspMatrix}(A, \dots) \S4method{Cholesky}{dsCMatrix}(A, perm = TRUE, LDL = !super, super = FALSE, Imult = 0, \dots) \S4method{Cholesky}{ddiMatrix}(A, \dots) \S4method{Cholesky}{generalMatrix}(A, uplo = "U", \dots) \S4method{Cholesky}{triangularMatrix}(A, uplo = "U", \dots) \S4method{Cholesky}{matrix}(A, uplo = "U", \dots) } \arguments{ \item{A}{a \link[=is.finite]{finite}, symmetric matrix or \code{\linkS4class{Matrix}} to be factorized. If \code{A} is square but not symmetric, then it will be \emph{treated} as symmetric; see \code{uplo}. Methods for dense \code{A} require positive definiteness when \code{perm = FALSE} and positive semidefiniteness when \code{perm = TRUE}. Methods for sparse \code{A} require positive definiteness when \code{LDL = TRUE} and nonzero leading principal minors (after pivoting) when \code{LDL = FALSE}. Methods for sparse, \emph{diagonal} \code{A} are an exception, requiring positive semidefiniteness unconditionally.} \item{perm}{a logical indicating if the rows and columns of \eqn{A} should be pivoted. Methods for sparse \code{A} employ the approximate minimum degree (AMD) algorithm in order to reduce fill-in, i.e., without regard for numerical stability. Pivoting for sparsity may introduce nonpositive leading principal minors, causing the factorization to fail, in which case it may be necessary to set \code{perm = FALSE}.} \item{tol}{a \link[=is.finite]{finite} numeric tolerance, used only if \code{perm = TRUE}. The factorization algorithm stops if the pivot is less than or equal to \code{tol}. Negative \code{tol} is equivalent to \code{nrow(A) * .Machine$double.eps * max(diag(A))}.} \item{LDL}{a logical indicating if the simplicial factorization should be computed as \eqn{P_1' L_1 D L_1' P_1}{P1' * L1 * D * L1' * P1}, such that the result stores the lower triangular entries of \eqn{L_1-I+D}{L1-I+D}. The alternative is \eqn{P_1' L L' P_1}{P1' * L * L' * P1}, such that the result stores the lower triangular entries of \eqn{L = L_1 \sqrt{D}}{L = L1 * sqrt(D)}. This argument is ignored if \code{super = TRUE} (or if \code{super = NA} and the supernodal algorithm is chosen), as the supernodal code does not yet support the \code{LDL = TRUE} variant.} \item{super}{a logical indicating if the factorization should use the supernodal algorithm. The alternative is the simplicial algorithm. Setting \code{super = NA} leaves the choice to a CHOLMOD-internal heuristic.} \item{Imult}{a \link[=is.finite]{finite} number. The matrix that is factorized is \code{A + Imult * diag(nrow(A))}, i.e., \code{A} plus \code{Imult} times the identity matrix. This argument is useful for symmetric, indefinite \code{A}, as \code{Imult > max(rowSums(abs(A)) - diag(abs(A)))} ensures that \code{A + Imult * diag(nrow(A))} is diagonally dominant. (Symmetric, diagonally dominant matrices are positive definite.)} \item{uplo}{a string, either \code{"U"} or \code{"L"}, indicating which triangle of \code{A} should be used to compute the factorization. The default is \code{"U"}, even for lower triangular \code{A}, to be consistent with \code{\link[base]{chol}} from \pkg{base}.} \item{\dots}{further arguments passed to or from methods.} } \value{ An object representing the factorization, inheriting from virtual class \code{\linkS4class{CholeskyFactorization}}. For a traditional matrix \code{A}, the specific class is \code{\linkS4class{Cholesky}}. For \code{A} inheriting from \code{\linkS4class{unpackedMatrix}}, \code{\linkS4class{packedMatrix}}, and \code{\linkS4class{sparseMatrix}}, the specific class is \code{\linkS4class{Cholesky}}, \code{\linkS4class{pCholesky}}, and \code{\linkS4class{dCHMsimpl}} or \code{\linkS4class{dCHMsuper}}, respectively. } \details{ Note that the result of a call to \code{Cholesky} inherits from \code{\linkS4class{CholeskyFactorization}} but not \code{\linkS4class{Matrix}}. Users who just want a matrix should consider using \code{\link{chol}}, whose methods are simple wrappers around \code{Cholesky} returning just the upper triangular Cholesky factor \eqn{L'}, typically as a \code{\linkS4class{triangularMatrix}}. However, a more principled approach would be to construct factors as needed from the \code{CholeskyFactorization} object, e.g., with \code{\link{expand1}(x, "L")}, if \code{x} is the object. The behaviour of \code{Cholesky(A, perm = TRUE)} for dense \code{A} is somewhat exceptional, in that it expects \emph{without} checking that \code{A} is positive semidefinite. By construction, if \eqn{A} is positive semidefinite and the exact algorithm encounters a zero pivot, then the unfactorized trailing submatrix is the zero matrix, and there is nothing left to do. Hence when the finite precision algorithm encounters a pivot less than \code{tol}, it signals a warning instead of an error and zeros the trailing submatrix in order to guarantee that \eqn{P' L L' P}{P' * L * L' * P} is positive semidefinite even if \eqn{A} is not. It follows that one way to test for positive semidefiniteness of \eqn{A} in the event of a warning is to analyze the error \deqn{\frac{\lVert A - P' L L' P \rVert}{\lVert A \rVert}\,.}{norm(A - P' * L * L' * P) / norm(A).} See the examples and LAPACK Working Note (\dQuote{LAWN}) 161 for details. } \seealso{ Classes \code{\linkS4class{Cholesky}}, \code{\linkS4class{pCholesky}}, \code{\linkS4class{dCHMsimpl}} and \code{\linkS4class{dCHMsuper}} and their methods. Classes \code{\linkS4class{dpoMatrix}}, \code{\linkS4class{dppMatrix}}, and \code{\linkS4class{dsCMatrix}}. Generic function \code{\link{chol}}, for obtaining the upper triangular Cholesky factor \eqn{L'} as a matrix or \code{\linkS4class{Matrix}}. Generic functions \code{\link{expand1}} and \code{\link{expand2}}, for constructing matrix factors from the result. Generic functions \code{\link{BunchKaufman}}, \code{\link{Schur}}, \code{\link{lu}}, and \code{\link{qr}}, for computing other factorizations. } \references{ The LAPACK source code, including documentation; see \url{https://netlib.org/lapack/double/dpstrf.f}, \url{https://netlib.org/lapack/double/dpotrf.f}, and \url{https://netlib.org/lapack/double/dpptrf.f}. The CHOLMOD source code; see \url{https://github.com/DrTimothyAldenDavis/SuiteSparse}, notably the header file \file{CHOLMOD/Include/cholmod.h} defining \code{cholmod_factor_struct}. Lucas, C. (2004). \emph{LAPACK-style codes for level 2 and 3 pivoted Cholesky factorizations}. LAPACK Working Note, Number 161. \url{https://www.netlib.org/lapack/lawnspdf/lawn161.pdf} Chen, Y., Davis, T. A., Hager, W. W., & Rajamanickam, S. (2008). Algorithm 887: CHOLMOD, supernodal sparse Cholesky factorization and update/downdate. \emph{ACM Transactions on Mathematical Software}, \emph{35}(3), Article 22, 1-14. \doi{10.1145/1391989.1391995} Amestoy, P. R., Davis, T. A., & Duff, I. S. (2004). Algorithm 837: AMD, an approximate minimum degree ordering algorithm. \emph{ACM Transactions on Mathematical Software}, \emph{17}(4), 886-905. \doi{10.1145/1024074.1024081} Golub, G. H., & Van Loan, C. F. (2013). \emph{Matrix computations} (4th ed.). Johns Hopkins University Press. \doi{10.56021/9781421407944} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } showMethods("Cholesky", inherited = FALSE) set.seed(0) ## ---- Dense ---------------------------------------------------------- ## .... Positive definite .............................................. n <- 6L (A1 <- crossprod(Matrix(rnorm(n * n), n, n))) (ch.A1.nopivot <- Cholesky(A1, perm = FALSE)) (ch.A1 <- Cholesky(A1)) stopifnot(exprs = { length(ch.A1@perm) == ncol(A1) isPerm(ch.A1@perm) is.unsorted(ch.A1@perm) # typically not the identity permutation length(ch.A1.nopivot@perm) == 0L }) ## A ~ P1' L D L' P1 ~ P1' L L' P1 in floating point str(e.ch.A1 <- expand2(ch.A1, LDL = TRUE), max.level = 2L) str(E.ch.A1 <- expand2(ch.A1, LDL = FALSE), max.level = 2L) stopifnot(exprs = { all.equal(as(A1, "matrix"), as(Reduce(`\%*\%`, e.ch.A1), "matrix")) all.equal(as(A1, "matrix"), as(Reduce(`\%*\%`, E.ch.A1), "matrix")) }) ## .... Positive semidefinite but not positive definite ................ A2 <- A1 A2[1L, ] <- A2[, 1L] <- 0 A2 try(Cholesky(A2, perm = FALSE)) # fails as not positive definite ch.A2 <- Cholesky(A2) # returns, with a warning and ... A2.hat <- Reduce(`\%*\%`, expand2(ch.A2, LDL = FALSE)) norm(A2 - A2.hat, "2") / norm(A2, "2") # 7.670858e-17 ## .... Not positive semidefinite ...................................... A3 <- A1 A3[1L, ] <- A3[, 1L] <- -1 A3 try(Cholesky(A3, perm = FALSE)) # fails as not positive definite ch.A3 <- Cholesky(A3) # returns, with a warning and ... A3.hat <- Reduce(`\%*\%`, expand2(ch.A3, LDL = FALSE)) norm(A3 - A3.hat, "2") / norm(A3, "2") # 1.781568 ## Indeed, 'A3' is not positive semidefinite, but 'A3.hat' _is_ ch.A3.hat <- Cholesky(A3.hat) A3.hat.hat <- Reduce(`\%*\%`, expand2(ch.A3.hat, LDL = FALSE)) norm(A3.hat - A3.hat.hat, "2") / norm(A3.hat, "2") # 1.777944e-16 ## ---- Sparse --------------------------------------------------------- ## Really just three cases modulo permutation : ## ## type factorization minors of P1 A P1' ## 1 simplicial P1 A P1' = L1 D L1' nonzero ## 2 simplicial P1 A P1' = L L ' positive ## 3 supernodal P1 A P2' = L L ' positive data(KNex, package = "Matrix") A4 <- crossprod(KNex[["mm"]]) ch.A4 <- list(pivoted = list(simpl1 = Cholesky(A4, perm = TRUE, super = FALSE, LDL = TRUE), simpl0 = Cholesky(A4, perm = TRUE, super = FALSE, LDL = FALSE), super0 = Cholesky(A4, perm = TRUE, super = TRUE )), unpivoted = list(simpl1 = Cholesky(A4, perm = FALSE, super = FALSE, LDL = TRUE), simpl0 = Cholesky(A4, perm = FALSE, super = FALSE, LDL = FALSE), super0 = Cholesky(A4, perm = FALSE, super = TRUE ))) ch.A4 s <- simplify2array rapply2 <- function(object, f, ...) rapply(object, f, , , how = "list", ...) s(rapply2(ch.A4, isLDL)) s(m.ch.A4 <- rapply2(ch.A4, expand1, "L")) # giving L = L1 sqrt(D) ## By design, the pivoted and simplicial factorizations ## are more sparse than the unpivoted and supernodal ones ... s(rapply2(m.ch.A4, object.size)) ## Which is nicely visualized by lattice-based methods for 'image' inm <- c("pivoted", "unpivoted") jnm <- c("simpl1", "simpl0", "super0") for(i in 1:2) for(j in 1:3) print(image(m.ch.A4[[c(i, j)]], main = paste(inm[i], jnm[j])), split = c(j, i, 3L, 2L), more = i * j < 6L) simpl1 <- ch.A4[[c("pivoted", "simpl1")]] stopifnot(exprs = { length(simpl1@perm) == ncol(A4) isPerm(simpl1@perm, 0L) is.unsorted(simpl1@perm) # typically not the identity permutation }) ## One can expand with and without D regardless of isLDL(.), ## but "without" requires L = L1 sqrt(D), which is conditional ## on min(diag(D)) >= 0, hence "with" is the default isLDL(simpl1) stopifnot(min(diag(simpl1)) >= 0) str(e.ch.A4 <- expand2(simpl1, LDL = TRUE), max.level = 2L) # default str(E.ch.A4 <- expand2(simpl1, LDL = FALSE), max.level = 2L) stopifnot(exprs = { all.equal(E.ch.A4[["L" ]], e.ch.A4[["L1" ]] \%*\% sqrt(e.ch.A4[["D"]])) all.equal(E.ch.A4[["L."]], sqrt(e.ch.A4[["D"]]) \%*\% e.ch.A4[["L1."]]) all.equal(A4, as(Reduce(`\%*\%`, e.ch.A4), "symmetricMatrix")) all.equal(A4, as(Reduce(`\%*\%`, E.ch.A4), "symmetricMatrix")) }) ## The "same" permutation matrix with "alternate" representation ## [i, perm[i]] {margin=1} <-> [invertPerm(perm)[j], j] {margin=2} alt <- function(P) { P@margin <- 1L + !(P@margin - 1L) # 1 <-> 2 P@perm <- invertPerm(P@perm) P } ## Expansions are elegant but inefficient (transposes are redundant) ## hence programmers should consider methods for 'expand1' and 'diag' stopifnot(exprs = { identical(expand1(simpl1, "P1"), alt(e.ch.A4[["P1"]])) identical(expand1(simpl1, "L"), E.ch.A4[["L"]]) identical(Diagonal(x = diag(simpl1)), e.ch.A4[["D"]]) }) ## chol(A, pivot = value) is a simple wrapper around ## Cholesky(A, perm = value, LDL = FALSE, super = FALSE), ## returning L' = sqrt(D) L1' _but_ giving no information ## about the permutation P1 selectMethod("chol", "dsCMatrix") stopifnot(all.equal(chol(A4, pivot = TRUE), E.ch.A4[["L."]])) ## Now a symmetric matrix with positive _and_ negative eigenvalues, ## hence _not_ positive semidefinite A5 <- new("dsCMatrix", Dim = c(7L, 7L), p = c(0:1, 3L, 6:7, 10:11, 15L), i = c(0L, 0:1, 0:3, 2:5, 3:6), x = c(1, 6, 38, 10, 60, 103, -4, 6, -32, -247, -2, -16, -128, -2, -67)) (ev <- eigen(A5, only.values = TRUE)$values) (t.ev <- table(factor(sign(ev), -1:1))) # the matrix "inertia" ch.A5 <- Cholesky(A5) isLDL(ch.A5) (d.A5 <- diag(ch.A5)) # diag(D) is partly negative ## Sylvester's law of inertia holds here, but not in general ## in finite precision arithmetic stopifnot(identical(table(factor(sign(d.A5), -1:1)), t.ev)) try(expand1(ch.A5, "L")) # unable to compute L = L1 sqrt(D) try(expand2(ch.A5, LDL = FALSE)) # ditto try(chol(A5, pivot = TRUE)) # ditto ## The default expansion is "square root free" and still works here str(e.ch.A5 <- expand2(ch.A5, LDL = TRUE), max.level = 2L) stopifnot(all.equal(A5, as(Reduce(`\%*\%`, e.ch.A5), "symmetricMatrix"))) ## Version of the SuiteSparse library, which includes CHOLMOD Mv <- Matrix.Version() Mv[["suitesparse"]] } Matrix/man/band-methods.Rd0000644000175100001440000001006414575137654015165 0ustar hornikusers\name{band-methods} \title{Extract bands of a matrix} % \docType{methods} \keyword{array} \keyword{methods} % \alias{band} \alias{band-methods} \alias{triu} \alias{triu-methods} \alias{tril} \alias{tril-methods} % \alias{band,CsparseMatrix-method} \alias{band,RsparseMatrix-method} \alias{band,TsparseMatrix-method} \alias{band,denseMatrix-method} \alias{band,diagonalMatrix-method} \alias{band,indMatrix-method} \alias{band,matrix-method} \alias{triu,CsparseMatrix-method} \alias{triu,RsparseMatrix-method} \alias{triu,TsparseMatrix-method} \alias{triu,denseMatrix-method} \alias{triu,diagonalMatrix-method} \alias{triu,indMatrix-method} \alias{triu,matrix-method} \alias{tril,CsparseMatrix-method} \alias{tril,RsparseMatrix-method} \alias{tril,TsparseMatrix-method} \alias{tril,denseMatrix-method} \alias{tril,diagonalMatrix-method} \alias{tril,indMatrix-method} \alias{tril,matrix-method} % \description{ Return the matrix obtained by setting to zero elements below a diagonal (\code{triu}), above a diagonal (\code{tril}), or outside of a general band (\code{band}). } \usage{ band(x, k1, k2, \dots) triu(x, k = 0L, \dots) tril(x, k = 0L, \dots) } \arguments{ \item{x}{a matrix-like object} \item{k,k1,k2}{integers specifying the diagonals that are not set to zero, \code{k1 <= k2}. These are interpreted relative to the main diagonal, which is \code{k = 0}. Positive and negative values of \code{k} indicate diagonals above and below the main diagonal, respectively.} \item{\dots}{optional arguments passed to methods, currently unused by package \pkg{Matrix}.} } \details{ \code{triu(x, k)} is equivalent to \code{band(x, k, dim(x)[2])}. Similarly, \code{tril(x, k)} is equivalent to \code{band(x, -dim(x)[1], k)}. } \value{ An object of a suitable matrix class, inheriting from \code{\linkS4class{triangularMatrix}} where appropriate. It inherits from \code{\linkS4class{sparseMatrix}} if and only if \code{x} does. } \section{Methods}{ \describe{ \item{x = "CsparseMatrix"}{method for compressed, sparse, column-oriented matrices.} \item{x = "RsparseMatrix"}{method for compressed, sparse, row-oriented matrices.} \item{x = "TsparseMatrix"}{method for sparse matrices in triplet format.} \item{x = "diagonalMatrix"}{method for diagonal matrices.} \item{x = "denseMatrix"}{method for dense matrices in packed or unpacked format.} \item{x = "matrix"}{method for traditional matrices of implicit class \code{\link{matrix}}.} } } \seealso{ \code{\link{bandSparse}} for the \emph{construction} of a banded sparse matrix directly from its non-zero diagonals. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) } ## A random sparse matrix : set.seed(7) m <- matrix(0, 5, 5) m[sample(length(m), size = 14)] <- rep(1:9, length=14) (mm <- as(m, "CsparseMatrix")) tril(mm) # lower triangle tril(mm, -1) # strict lower triangle triu(mm, 1) # strict upper triangle band(mm, -1, 2) # general band (m5 <- Matrix(rnorm(25), ncol = 5)) tril(m5) # lower triangle tril(m5, -1) # strict lower triangle triu(m5, 1) # strict upper triangle band(m5, -1, 2) # general band (m65 <- Matrix(rnorm(30), ncol = 5)) # not square triu(m65) # result not "dtrMatrix" unless square (sm5 <- crossprod(m65)) # symmetric band(sm5, -1, 1)# "dsyMatrix": symmetric band preserves symmetry property as(band(sm5, -1, 1), "sparseMatrix")# often preferable (sm <- round(crossprod(triu(mm/2)))) # sparse symmetric ("dsC*") band(sm, -1,1) # remains "dsC", *however* band(sm, -2,1) # -> "dgC" %% Problem is the underlying cholmod_band() which really does symmetric %% banding *only* *if* the matrix is cholmod-symmetric i.e. 'stype != 0' %% \dontshow{ ## this uses special methods (x.x <- crossprod(mm)) tril(x.x) xx <- tril(x.x) + triu(x.x, 1) ## the same as x.x (but stored differently): txx <- t(as(xx, "symmetricMatrix")) stopifnot(identical(triu(x.x), t(tril(x.x))), identical(class(x.x), class(txx)), identical(as(x.x, "generalMatrix"), as(txx, "generalMatrix"))) } } Matrix/man/Schur-methods.Rd0000644000175100001440000000673414575137654015356 0ustar hornikusers\name{Schur-methods} \title{Methods for Schur Factorization} % \docType{methods} \keyword{algebra} \keyword{array} \keyword{methods} % \alias{Schur} \alias{Schur-methods} % \alias{Schur,dgeMatrix-method} \alias{Schur,diagonalMatrix-method} \alias{Schur,dsyMatrix-method} \alias{Schur,generalMatrix-method} \alias{Schur,matrix-method} \alias{Schur,symmetricMatrix-method} \alias{Schur,triangularMatrix-method} % \description{ Computes the Schur factorization of an \eqn{n \times n}{n-by-n} real matrix \eqn{A}, which has the general form \deqn{A = Q T Q'}{A = Q * T * Q'} where \eqn{Q} is an orthogonal matrix and \eqn{T} is a block upper triangular matrix with \eqn{1 \times 1}{1-by-1} and \eqn{2 \times 2}{2-by-2} diagonal blocks specifying the real and complex conjugate eigenvalues of \eqn{A}. The column vectors of \eqn{Q} are the Schur vectors of \eqn{A}, and \eqn{T} is the Schur form of \eqn{A}. Methods are built on LAPACK routine \code{dgees}. } \usage{ Schur(x, vectors = TRUE, \dots) } \arguments{ \item{x}{a \link[=is.finite]{finite} square matrix or \code{\linkS4class{Matrix}} to be factorized.} \item{vectors}{a logical. If \code{TRUE} (the default), then Schur vectors are computed in addition to the Schur form.} \item{\dots}{further arguments passed to or from methods.} } \value{ An object representing the factorization, inheriting from virtual class \code{\linkS4class{SchurFactorization}} if \code{vectors = TRUE}. Currently, the specific class is always \code{\linkS4class{Schur}} in that case. %% FIXME? no other factorization behaves this way: An exception is if \code{x} is a traditional matrix, in which case the result is a named list containing \code{Q}, \code{T}, and \code{EValues} slots of the \code{\linkS4class{Schur}} object. If \code{vectors = FALSE}, then the result is the same named list but without \code{Q}. } \seealso{ Class \code{\linkS4class{Schur}} and its methods. Class \code{\linkS4class{dgeMatrix}}. Generic functions \code{\link{expand1}} and \code{\link{expand2}}, for constructing matrix factors from the result. Generic functions \code{\link{Cholesky}}, \code{\link{BunchKaufman}}, \code{\link{lu}}, and \code{\link{qr}}, for computing other factorizations. } \references{ The LAPACK source code, including documentation; see \url{https://netlib.org/lapack/double/dgees.f}. Golub, G. H., & Van Loan, C. F. (2013). \emph{Matrix computations} (4th ed.). Johns Hopkins University Press. \doi{10.56021/9781421407944} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } showMethods("Schur", inherited = FALSE) set.seed(0) Schur(Hilbert(9L)) # real eigenvalues (A <- Matrix(round(rnorm(25L, sd = 100)), 5L, 5L)) (sch.A <- Schur(A)) # complex eigenvalues ## A ~ Q T Q' in floating point str(e.sch.A <- expand2(sch.A), max.level = 2L) stopifnot(all.equal(A, Reduce(`\%*\%`, e.sch.A))) (e1 <- eigen(sch.A@T, only.values = TRUE)$values) (e2 <- eigen( A , only.values = TRUE)$values) (e3 <- sch.A@EValues) stopifnot(exprs = { all.equal(e1, e2, tolerance = 1e-13) all.equal(e1, e3[order(Mod(e3), decreasing = TRUE)], tolerance = 1e-13) identical(Schur(A, vectors = FALSE), list(T = sch.A@T, EValues = e3)) identical(Schur(as(A, "matrix")), list(Q = as(sch.A@Q, "matrix"), T = as(sch.A@T, "matrix"), EValues = e3)) }) } Matrix/man/dtCMatrix-class.Rd0000644000175100001440000001061114446607050015605 0ustar hornikusers\name{dtCMatrix-class} \title{Triangular, (compressed) sparse column matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{dtCMatrix-class} \alias{dtTMatrix-class} % \alias{Arith,dtCMatrix,dtCMatrix-method} % \description{The \code{"dtCMatrix"} class is a class of triangular, sparse matrices in the compressed, column-oriented format. In this implementation the non-zero elements in the columns are sorted into increasing row order. The \code{"dtTMatrix"} class is a class of triangular, sparse matrices in triplet format. } \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("dtCMatrix", ...)} or calls of the form \code{new("dtTMatrix", ...)}, but more typically automatically via \code{\link{Matrix}()} or coercions such as \code{as(x, "triangularMatrix")}. } \section{Slots}{ \describe{ \item{\code{uplo}:}{Object of class \code{"character"}. Must be either "U", for upper triangular, and "L", for lower triangular.} \item{\code{diag}:}{Object of class \code{"character"}. Must be either \code{"U"}, for unit triangular (diagonal is all ones), or \code{"N"}; see \code{\linkS4class{triangularMatrix}}.} \item{\code{p}:}{(only present in \code{"dtCMatrix"}:) an \code{\link{integer}} vector for providing pointers, one for each column, see the detailed description in \code{\linkS4class{CsparseMatrix}}.} \item{\code{i}:}{Object of class \code{"integer"} of length nnzero (number of non-zero elements). These are the row numbers for each non-zero element in the matrix.} \item{\code{j}:}{Object of class \code{"integer"} of length nnzero (number of non-zero elements). These are the column numbers for each non-zero element in the matrix. (Only present in the \code{dtTMatrix} class.)} \item{\code{x}:}{Object of class \code{"numeric"} - the non-zero elements of the matrix.} \item{\code{Dim},\code{Dimnames}:}{The dimension (a length-2 \code{"integer"}) and corresponding names (or \code{NULL}), inherited from the \code{\linkS4class{Matrix}}, see there.} } } \section{Extends}{ Class \code{"dgCMatrix"}, directly. Class \code{"triangularMatrix"}, directly. Class \code{"dMatrix"}, \code{"sparseMatrix"}, and more by class \code{"dgCMatrix"} etc, see the examples. } \section{Methods}{ \describe{ \item{solve}{\code{signature(a = "dtCMatrix", b = "....")}: sparse triangular solve (aka \dQuote{backsolve} or \dQuote{forwardsolve}), see \code{\link{solve-methods}}.} \item{t}{\code{signature(x = "dtCMatrix")}: returns the transpose of \code{x}} \item{t}{\code{signature(x = "dtTMatrix")}: returns the transpose of \code{x}} } } %\references{} %\author{} %\note{} \seealso{ Classes \code{\linkS4class{dgCMatrix}}, \code{\linkS4class{dgTMatrix}}, \code{\linkS4class{dgeMatrix}}, and \code{\linkS4class{dtrMatrix}}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } showClass("dtCMatrix") showClass("dtTMatrix") t1 <- new("dtTMatrix", x= c(3,7), i= 0:1, j=3:2, Dim= as.integer(c(4,4))) t1 ## from 0-diagonal to unit-diagonal {low-level step}: tu <- t1 ; tu@diag <- "U" tu (cu <- as(tu, "CsparseMatrix")) str(cu)# only two entries in @i and @x stopifnot(cu@i == 1:0, all(2 * symmpart(cu) == Diagonal(4) + forceSymmetric(cu))) t1[1,2:3] <- -1:-2 diag(t1) <- 10*c(1:2,3:2) t1 # still triangular (it1 <- solve(t1)) t1. <- solve(it1) all(abs(t1 - t1.) < 10 * .Machine$double.eps) ## 2nd example U5 <- new("dtCMatrix", i= c(1L, 0:3), p=c(0L,0L,0:2, 5L), Dim = c(5L, 5L), x = rep(1, 5), diag = "U") U5 (iu <- solve(U5)) # contains one '0' validObject(iu2 <- solve(U5, Diagonal(5)))# failed in earlier versions I5 <- iu \%*\% U5 # should equal the identity matrix i5 <- iu2 \%*\% U5 m53 <- matrix(1:15, 5,3, dimnames=list(NULL,letters[1:3])) asDiag <- function(M) as(drop0(M), "diagonalMatrix") stopifnot( all.equal(Diagonal(5), asDiag(I5), tolerance=1e-14) , all.equal(Diagonal(5), asDiag(i5), tolerance=1e-14) , identical(list(NULL, dimnames(m53)[[2]]), dimnames(solve(U5, m53))) ) \dontshow{% i5. <- I5; colnames(i5.) <- LETTERS[11:15] M53 <- as(m53, "denseMatrix") stopifnot( identical((dns <- dimnames(solve(i5., M53))), dimnames(solve(as.matrix(i5.), as.matrix(M53)))) , identical(dns, dimnames(solve(i5., as.matrix(M53)))) ) }%dont } Matrix/man/matmult-methods.Rd0000644000175100001440000003666614575137654015764 0ustar hornikusers\name{matmult-methods} \title{Matrix (Cross) Products (of Transpose)} % \docType{methods} \keyword{algebra} \keyword{arith} \keyword{array} % \alias{\%*\%} \alias{\%*\%-methods} \alias{crossprod} \alias{crossprod-methods} \alias{tcrossprod} \alias{tcrossprod-methods} \alias{matmult-methods} % %*% \alias{\%*\%,ANY,Matrix-method} \alias{\%*\%,ANY,sparseVector-method} \alias{\%*\%,CsparseMatrix,CsparseMatrix-method} \alias{\%*\%,CsparseMatrix,RsparseMatrix-method} \alias{\%*\%,CsparseMatrix,TsparseMatrix-method} \alias{\%*\%,CsparseMatrix,denseMatrix-method} \alias{\%*\%,CsparseMatrix,diagonalMatrix-method} \alias{\%*\%,CsparseMatrix,matrix-method} \alias{\%*\%,CsparseMatrix,vector-method} \alias{\%*\%,Matrix,ANY-method} \alias{\%*\%,Matrix,indMatrix-method} \alias{\%*\%,Matrix,pMatrix-method} \alias{\%*\%,Matrix,sparseVector-method} \alias{\%*\%,RsparseMatrix,CsparseMatrix-method} \alias{\%*\%,RsparseMatrix,RsparseMatrix-method} \alias{\%*\%,RsparseMatrix,TsparseMatrix-method} \alias{\%*\%,RsparseMatrix,denseMatrix-method} \alias{\%*\%,RsparseMatrix,diagonalMatrix-method} \alias{\%*\%,RsparseMatrix,matrix-method} \alias{\%*\%,RsparseMatrix,vector-method} \alias{\%*\%,TsparseMatrix,CsparseMatrix-method} \alias{\%*\%,TsparseMatrix,RsparseMatrix-method} \alias{\%*\%,TsparseMatrix,TsparseMatrix-method} \alias{\%*\%,TsparseMatrix,denseMatrix-method} \alias{\%*\%,TsparseMatrix,diagonalMatrix-method} \alias{\%*\%,TsparseMatrix,matrix-method} \alias{\%*\%,TsparseMatrix,vector-method} \alias{\%*\%,denseMatrix,CsparseMatrix-method} \alias{\%*\%,denseMatrix,RsparseMatrix-method} \alias{\%*\%,denseMatrix,TsparseMatrix-method} \alias{\%*\%,denseMatrix,denseMatrix-method} \alias{\%*\%,denseMatrix,diagonalMatrix-method} \alias{\%*\%,denseMatrix,matrix-method} \alias{\%*\%,denseMatrix,vector-method} \alias{\%*\%,diagonalMatrix,CsparseMatrix-method} \alias{\%*\%,diagonalMatrix,RsparseMatrix-method} \alias{\%*\%,diagonalMatrix,TsparseMatrix-method} \alias{\%*\%,diagonalMatrix,denseMatrix-method} \alias{\%*\%,diagonalMatrix,diagonalMatrix-method} \alias{\%*\%,diagonalMatrix,matrix-method} \alias{\%*\%,diagonalMatrix,vector-method} \alias{\%*\%,indMatrix,Matrix-method} \alias{\%*\%,indMatrix,indMatrix-method} \alias{\%*\%,indMatrix,matrix-method} \alias{\%*\%,indMatrix,pMatrix-method} \alias{\%*\%,indMatrix,vector-method} \alias{\%*\%,matrix,CsparseMatrix-method} \alias{\%*\%,matrix,RsparseMatrix-method} \alias{\%*\%,matrix,TsparseMatrix-method} \alias{\%*\%,matrix,denseMatrix-method} \alias{\%*\%,matrix,diagonalMatrix-method} \alias{\%*\%,matrix,indMatrix-method} \alias{\%*\%,matrix,pMatrix-method} \alias{\%*\%,matrix,sparseVector-method} \alias{\%*\%,pMatrix,Matrix-method} \alias{\%*\%,pMatrix,indMatrix-method} \alias{\%*\%,pMatrix,matrix-method} \alias{\%*\%,pMatrix,pMatrix-method} \alias{\%*\%,pMatrix,vector-method} \alias{\%*\%,sparseVector,ANY-method} \alias{\%*\%,sparseVector,Matrix-method} \alias{\%*\%,sparseVector,matrix-method} \alias{\%*\%,sparseVector,sparseVector-method} \alias{\%*\%,sparseVector,vector-method} \alias{\%*\%,vector,CsparseMatrix-method} \alias{\%*\%,vector,RsparseMatrix-method} \alias{\%*\%,vector,TsparseMatrix-method} \alias{\%*\%,vector,denseMatrix-method} \alias{\%*\%,vector,diagonalMatrix-method} \alias{\%*\%,vector,indMatrix-method} \alias{\%*\%,vector,pMatrix-method} \alias{\%*\%,vector,sparseVector-method} % crossprod \alias{crossprod,ANY,Matrix-method} \alias{crossprod,ANY,sparseVector-method} \alias{crossprod,CsparseMatrix,CsparseMatrix-method} \alias{crossprod,CsparseMatrix,RsparseMatrix-method} \alias{crossprod,CsparseMatrix,TsparseMatrix-method} \alias{crossprod,CsparseMatrix,denseMatrix-method} \alias{crossprod,CsparseMatrix,diagonalMatrix-method} \alias{crossprod,CsparseMatrix,matrix-method} \alias{crossprod,CsparseMatrix,missing-method} \alias{crossprod,CsparseMatrix,vector-method} \alias{crossprod,Matrix,ANY-method} \alias{crossprod,Matrix,indMatrix-method} \alias{crossprod,Matrix,pMatrix-method} \alias{crossprod,Matrix,sparseVector-method} \alias{crossprod,RsparseMatrix,CsparseMatrix-method} \alias{crossprod,RsparseMatrix,RsparseMatrix-method} \alias{crossprod,RsparseMatrix,TsparseMatrix-method} \alias{crossprod,RsparseMatrix,denseMatrix-method} \alias{crossprod,RsparseMatrix,diagonalMatrix-method} \alias{crossprod,RsparseMatrix,matrix-method} \alias{crossprod,RsparseMatrix,missing-method} \alias{crossprod,RsparseMatrix,vector-method} \alias{crossprod,TsparseMatrix,CsparseMatrix-method} \alias{crossprod,TsparseMatrix,RsparseMatrix-method} \alias{crossprod,TsparseMatrix,TsparseMatrix-method} \alias{crossprod,TsparseMatrix,denseMatrix-method} \alias{crossprod,TsparseMatrix,diagonalMatrix-method} \alias{crossprod,TsparseMatrix,matrix-method} \alias{crossprod,TsparseMatrix,missing-method} \alias{crossprod,TsparseMatrix,vector-method} \alias{crossprod,denseMatrix,CsparseMatrix-method} \alias{crossprod,denseMatrix,RsparseMatrix-method} \alias{crossprod,denseMatrix,TsparseMatrix-method} \alias{crossprod,denseMatrix,denseMatrix-method} \alias{crossprod,denseMatrix,diagonalMatrix-method} \alias{crossprod,denseMatrix,matrix-method} \alias{crossprod,denseMatrix,missing-method} \alias{crossprod,denseMatrix,vector-method} \alias{crossprod,diagonalMatrix,CsparseMatrix-method} \alias{crossprod,diagonalMatrix,RsparseMatrix-method} \alias{crossprod,diagonalMatrix,TsparseMatrix-method} \alias{crossprod,diagonalMatrix,denseMatrix-method} \alias{crossprod,diagonalMatrix,diagonalMatrix-method} \alias{crossprod,diagonalMatrix,matrix-method} \alias{crossprod,diagonalMatrix,missing-method} \alias{crossprod,diagonalMatrix,vector-method} \alias{crossprod,indMatrix,Matrix-method} \alias{crossprod,indMatrix,matrix-method} \alias{crossprod,indMatrix,missing-method} \alias{crossprod,indMatrix,vector-method} \alias{crossprod,matrix,CsparseMatrix-method} \alias{crossprod,matrix,RsparseMatrix-method} \alias{crossprod,matrix,TsparseMatrix-method} \alias{crossprod,matrix,denseMatrix-method} \alias{crossprod,matrix,diagonalMatrix-method} \alias{crossprod,matrix,indMatrix-method} \alias{crossprod,matrix,pMatrix-method} \alias{crossprod,matrix,sparseVector-method} \alias{crossprod,pMatrix,missing-method} \alias{crossprod,pMatrix,pMatrix-method} \alias{crossprod,sparseVector,ANY-method} \alias{crossprod,sparseVector,Matrix-method} \alias{crossprod,sparseVector,matrix-method} \alias{crossprod,sparseVector,missing-method} \alias{crossprod,sparseVector,sparseVector-method} \alias{crossprod,sparseVector,vector-method} \alias{crossprod,vector,CsparseMatrix-method} \alias{crossprod,vector,RsparseMatrix-method} \alias{crossprod,vector,TsparseMatrix-method} \alias{crossprod,vector,denseMatrix-method} \alias{crossprod,vector,diagonalMatrix-method} \alias{crossprod,vector,indMatrix-method} \alias{crossprod,vector,pMatrix-method} \alias{crossprod,vector,sparseVector-method} % tcrossprod \alias{tcrossprod,ANY,Matrix-method} \alias{tcrossprod,ANY,sparseVector-method} \alias{tcrossprod,CsparseMatrix,CsparseMatrix-method} \alias{tcrossprod,CsparseMatrix,RsparseMatrix-method} \alias{tcrossprod,CsparseMatrix,TsparseMatrix-method} \alias{tcrossprod,CsparseMatrix,denseMatrix-method} \alias{tcrossprod,CsparseMatrix,diagonalMatrix-method} \alias{tcrossprod,CsparseMatrix,matrix-method} \alias{tcrossprod,CsparseMatrix,missing-method} \alias{tcrossprod,CsparseMatrix,vector-method} \alias{tcrossprod,Matrix,ANY-method} \alias{tcrossprod,Matrix,indMatrix-method} \alias{tcrossprod,Matrix,sparseVector-method} \alias{tcrossprod,RsparseMatrix,CsparseMatrix-method} \alias{tcrossprod,RsparseMatrix,RsparseMatrix-method} \alias{tcrossprod,RsparseMatrix,TsparseMatrix-method} \alias{tcrossprod,RsparseMatrix,denseMatrix-method} \alias{tcrossprod,RsparseMatrix,diagonalMatrix-method} \alias{tcrossprod,RsparseMatrix,matrix-method} \alias{tcrossprod,RsparseMatrix,missing-method} \alias{tcrossprod,RsparseMatrix,vector-method} \alias{tcrossprod,TsparseMatrix,CsparseMatrix-method} \alias{tcrossprod,TsparseMatrix,RsparseMatrix-method} \alias{tcrossprod,TsparseMatrix,TsparseMatrix-method} \alias{tcrossprod,TsparseMatrix,denseMatrix-method} \alias{tcrossprod,TsparseMatrix,diagonalMatrix-method} \alias{tcrossprod,TsparseMatrix,matrix-method} \alias{tcrossprod,TsparseMatrix,missing-method} \alias{tcrossprod,TsparseMatrix,vector-method} \alias{tcrossprod,denseMatrix,CsparseMatrix-method} \alias{tcrossprod,denseMatrix,RsparseMatrix-method} \alias{tcrossprod,denseMatrix,TsparseMatrix-method} \alias{tcrossprod,denseMatrix,denseMatrix-method} \alias{tcrossprod,denseMatrix,diagonalMatrix-method} \alias{tcrossprod,denseMatrix,matrix-method} \alias{tcrossprod,denseMatrix,missing-method} \alias{tcrossprod,denseMatrix,vector-method} \alias{tcrossprod,diagonalMatrix,CsparseMatrix-method} \alias{tcrossprod,diagonalMatrix,RsparseMatrix-method} \alias{tcrossprod,diagonalMatrix,TsparseMatrix-method} \alias{tcrossprod,diagonalMatrix,denseMatrix-method} \alias{tcrossprod,diagonalMatrix,diagonalMatrix-method} \alias{tcrossprod,diagonalMatrix,matrix-method} \alias{tcrossprod,diagonalMatrix,missing-method} \alias{tcrossprod,diagonalMatrix,vector-method} \alias{tcrossprod,indMatrix,Matrix-method} \alias{tcrossprod,indMatrix,matrix-method} \alias{tcrossprod,indMatrix,missing-method} \alias{tcrossprod,indMatrix,vector-method} \alias{tcrossprod,matrix,CsparseMatrix-method} \alias{tcrossprod,matrix,RsparseMatrix-method} \alias{tcrossprod,matrix,TsparseMatrix-method} \alias{tcrossprod,matrix,denseMatrix-method} \alias{tcrossprod,matrix,diagonalMatrix-method} \alias{tcrossprod,matrix,indMatrix-method} \alias{tcrossprod,matrix,sparseVector-method} \alias{tcrossprod,pMatrix,Matrix-method} \alias{tcrossprod,pMatrix,matrix-method} \alias{tcrossprod,pMatrix,missing-method} \alias{tcrossprod,pMatrix,pMatrix-method} \alias{tcrossprod,pMatrix,vector-method} \alias{tcrossprod,sparseVector,ANY-method} \alias{tcrossprod,sparseVector,Matrix-method} \alias{tcrossprod,sparseVector,matrix-method} \alias{tcrossprod,sparseVector,missing-method} \alias{tcrossprod,sparseVector,sparseVector-method} \alias{tcrossprod,sparseVector,vector-method} \alias{tcrossprod,vector,CsparseMatrix-method} \alias{tcrossprod,vector,RsparseMatrix-method} \alias{tcrossprod,vector,TsparseMatrix-method} \alias{tcrossprod,vector,denseMatrix-method} \alias{tcrossprod,vector,diagonalMatrix-method} \alias{tcrossprod,vector,indMatrix-method} \alias{tcrossprod,vector,sparseVector-method} % \description{ The basic matrix product, \code{\%*\%} is implemented for all our \code{\linkS4class{Matrix}} and also for \code{\linkS4class{sparseVector}} classes, fully analogously to \R's base \code{matrix} and vector objects. The functions \code{\link{crossprod}} and \code{\link{tcrossprod}} are matrix products or \dQuote{cross products}, ideally implemented efficiently without computing \code{\link{t}(.)}'s unnecessarily. They also return \code{\linkS4class{symmetricMatrix}} classed matrices when easily detectable, e.g., in \code{crossprod(m)}, the one argument case. \code{tcrossprod()} takes the cross-product of the transpose of a matrix. \code{tcrossprod(x)} is formally equivalent to, but faster than, the call \code{x \%*\% t(x)}, and so is \code{tcrossprod(x, y)} instead of \code{x \%*\% t(y)}. \emph{Boolean} matrix products are computed via either \code{\link{\%&\%}} or \code{boolArith = TRUE}. } \usage{ \S4method{\%*\%}{CsparseMatrix,diagonalMatrix}(x, y) \S4method{crossprod}{CsparseMatrix,diagonalMatrix}(x, y = NULL, boolArith = NA, \dots) ## .... and for many more signatures \S4method{tcrossprod}{TsparseMatrix,missing}(x, y = NULL, boolArith = NA, \dots) ## .... and for many more signatures } \arguments{ \item{x}{a matrix-like object} \item{y}{a matrix-like object, or for \code{[t]crossprod()} \code{NULL} (by default); the latter case is formally equivalent to \code{y = x}.} \item{boolArith}{\code{\link{logical}}, i.e., \code{NA}, \code{TRUE}, or \code{FALSE}. If true the result is (coerced to) a pattern matrix, i.e., \code{"\linkS4class{nMatrix}"}, unless there are \code{NA} entries and the result will be a \code{"\linkS4class{lMatrix}"}. If false the result is (coerced to) numeric. When \code{NA}, currently the default, the result is a pattern matrix when \code{x} and \code{y} are \code{"\linkS4class{nsparseMatrix}"} and numeric otherwise.} \item{\dots}{potentially more arguments passed to and from methods.} } \details{ For some classes in the \code{Matrix} package, such as \code{\linkS4class{dgCMatrix}}, it is much faster to calculate the cross-product of the transpose directly instead of calculating the transpose first and then its cross-product. \code{boolArith = TRUE} for regular (\dQuote{non cross}) matrix products, \code{\%*\%} cannot be specified. Instead, we provide the \code{\link{\%&\%}} operator for \emph{boolean} matrix products. } \note{ \code{boolArith = TRUE}, \code{FALSE} or \code{NA} has been newly introduced for \pkg{Matrix} 1.2.0 (March 2015). Its implementation has still not been tested extensively. Notably the behaviour for sparse matrices with \code{x} slots containing extra zeros had not been documented previously, see the \code{\link{\%&\%}} help page. Currently, \code{boolArith = TRUE} is implemented via \code{\linkS4class{CsparseMatrix}} coercions which may be quite inefficient for dense matrices. Contributions for efficiency improvements are welcome. } \value{ A \code{\linkS4class{Matrix}} object, in the one argument case of an appropriate \emph{symmetric} matrix class, i.e., inheriting from \code{\linkS4class{symmetricMatrix}}. } \section{Methods}{ \describe{ \item{\%*\%}{\code{signature(x = "dgeMatrix", y = "dgeMatrix")}: Matrix multiplication; ditto for several other signature combinations, see \code{showMethods("\%*\%", class = "dgeMatrix")}.} \item{\%*\%}{\code{signature(x = "dtrMatrix", y = "matrix")} and other signatures (use \code{showMethods("\%*\%", class="dtrMatrix")}): matrix multiplication. Multiplication of (matching) triangular matrices now should remain triangular (in the sense of class \linkS4class{triangularMatrix}).} \item{crossprod}{\code{signature(x = "dgeMatrix", y = "dgeMatrix")}: ditto for several other signatures, use \code{showMethods("crossprod", class = "dgeMatrix")}, matrix crossproduct, an efficient version of \code{t(x) \%*\% y}.} \item{crossprod}{\code{signature(x = "CsparseMatrix", y = "missing")} returns \code{t(x) \%*\% x} as an \code{dsCMatrix} object.} \item{crossprod}{\code{signature(x = "TsparseMatrix", y = "missing")} returns \code{t(x) \%*\% x} as an \code{dsCMatrix} object.} \item{crossprod,tcrossprod}{\code{signature(x = "dtrMatrix", y = "matrix")} and other signatures, see \code{"\%*\%"} above.} }%{describe} } \seealso{ \code{\link[base]{tcrossprod}} in \R's base, and \code{\link{crossprod}} and \code{\link{\%*\%}}. \pkg{Matrix} package \code{\link{\%&\%}} for boolean matrix product methods. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } ## A random sparse "incidence" matrix : m <- matrix(0, 400, 500) set.seed(12) m[runif(314, 0, length(m))] <- 1 mm <- as(m, "CsparseMatrix") object.size(m) / object.size(mm) # smaller by a factor of > 200 ## tcrossprod() is very fast: system.time(tCmm <- tcrossprod(mm))# 0 (PIII, 933 MHz) system.time(cm <- crossprod(t(m))) # 0.16 system.time(cm. <- tcrossprod(m)) # 0.02 stopifnot(cm == as(tCmm, "matrix")) ## show sparse sub matrix tCmm[1:16, 1:30] } Matrix/man/nnzero-methods.Rd0000644000175100001440000000652014575137654015576 0ustar hornikusers\name{nnzero-methods} \title{The Number of Non-Zero Values of a Matrix} % \docType{methods} \keyword{array} \keyword{logic} \keyword{methods} % \alias{nnzero} \alias{nnzero-methods} % \alias{nnzero,ANY-method} \alias{nnzero,CHMfactor-method} \alias{nnzero,denseMatrix-method} \alias{nnzero,diagonalMatrix-method} \alias{nnzero,indMatrix-method} \alias{nnzero,sparseMatrix-method} \alias{nnzero,vector-method} % \description{ Returns the number of non-zero values of a numeric-like \R object, and in particular an object \code{x} inheriting from class \code{\linkS4class{Matrix}}. } \usage{ nnzero(x, na.counted = NA) } \arguments{ \item{x}{an \R object, typically inheriting from class \code{\linkS4class{Matrix}} or \code{\link{numeric}}.} \item{na.counted}{a \code{\link{logical}} describing how \code{\link{NA}}s should be counted. There are three possible settings for \code{na.counted}: \describe{ \item{TRUE}{\code{NA}s \emph{are} counted as non-zero (since \dQuote{they are not zero}).} \item{NA}{(default)the result will be \code{NA} if there are \code{NA}'s in \code{x} (since \dQuote{NA's are not known, i.e., \emph{may be} zero}).} \item{FALSE}{\code{NA}s are \emph{omitted} from \code{x} before the non-zero entries are counted.} } For sparse matrices, you may often want to use \code{na.counted = TRUE}. } } % \details{ % } \section{Methods}{ \describe{ \item{\code{signature(x = "ANY")}}{the default method for non-\code{\linkS4class{Matrix}} class objects, simply counts the number \code{0}s in \code{x}, counting \code{NA}'s depending on the \code{na.counted} argument, see above.} \item{\code{signature(x = "denseMatrix")}}{conceptually the same as for traditional \code{\link{matrix}} objects, care has to be taken for \code{"\linkS4class{symmetricMatrix}"} objects.} \item{\code{signature(x = "diagonalMatrix")}, and \code{signature(x = "indMatrix")}}{fast simple methods for these special \code{"sparseMatrix"} classes.} \item{\code{signature(x = "sparseMatrix")}}{typically, the most interesting method, also carefully taking \code{"\linkS4class{symmetricMatrix}"} objects into account.} } } \value{ the number of non zero entries in \code{x} (typically \code{\link{integer}}). Note that for a \emph{symmetric} sparse matrix \code{S} (i.e., inheriting from class \code{\linkS4class{symmetricMatrix}}), \code{nnzero(S)} is typically \emph{twice} the \code{length(S@x)}. } %\author{Martin} \seealso{The \code{\linkS4class{Matrix}} class also has a \code{\link{length}} method; typically, \code{length(M)} is much larger than \code{nnzero(M)} for a sparse matrix M, and the latter is a better indication of the \emph{size} of \code{M}. \code{\link{drop0}}, \code{\link{zapsmall}}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } m <- Matrix(0+1:28, nrow = 4) m[-3,c(2,4:5,7)] <- m[ 3, 1:4] <- m[1:3, 6] <- 0 (mT <- as(m, "TsparseMatrix")) nnzero(mT) (S <- crossprod(mT)) nnzero(S) str(S) # slots are smaller than nnzero() stopifnot(nnzero(S) == sum(as.matrix(S) != 0))# failed earlier data(KNex, package = "Matrix") M <- KNex$mm class(M) dim(M) length(M); stopifnot(length(M) == prod(dim(M))) nnzero(M) # more relevant than length ## the above are also visible from str(M) } Matrix/man/abIseq.Rd0000644000175100001440000000356714422605232014015 0ustar hornikusers\name{abIseq} \title{Sequence Generation of "abIndex", Abstract Index Vectors} % \keyword{manip} \keyword{utilities} % \alias{abIseq} \alias{abIseq1} % \alias{c.abIndex} % \description{ Generation of abstract index vectors, i.e., objects of class \code{"\linkS4class{abIndex}"}. \code{abIseq()} is designed to work entirely like \code{\link{seq}}, but producing \code{"abIndex"} vectors.\cr \code{abIseq1()} is its basic building block, where \code{abIseq1(n,m)} corresponds to \code{n:m}. \code{c(x, ...)} will return an \code{"abIndex"} vector, when \code{x} is one. } \usage{ abIseq1(from = 1, to = 1) abIseq (from = 1, to = 1, by = ((to - from)/(length.out - 1)), length.out = NULL, along.with = NULL) \method{c}{abIndex}(\dots) } \arguments{ \item{from, to}{the starting and (maximal) end value of the sequence.} \item{by}{number: increment of the sequence.} \item{length.out}{desired length of the sequence. A non-negative number, which for \code{seq} and \code{seq.int} will be rounded up if fractional.} \item{along.with}{take the length from the length of this argument.} \item{\dots}{in general an arbitrary number of \R objects; here, when the first is an \code{"\linkS4class{abIndex}"} vector, these arguments will be concatenated to a new \code{"abIndex"} object.} } %\author{Martin Maechler} % \details{ % } \value{ An abstract index vector, i.e., object of class \code{"\linkS4class{abIndex}"}. } % \references{ % %% ~put references to the literature/web site here ~ % } \seealso{ the class \code{\linkS4class{abIndex}} documentation; \code{\link{rep2abI}()} for another constructor; \code{\link{rle}} (\pkg{base}). } \examples{ stopifnot(identical(-3:20, as(abIseq1(-3,20), "vector"))) try( ## (arithmetic) not yet implemented abIseq(1, 50, by = 3) ) %% FIXME: add / exchange with ../tests/abIndex-tsts.R } Matrix/man/image-methods.Rd0000644000175100001440000001603614446607050015335 0ustar hornikusers\name{image-methods} \title{Methods for image() in Package 'Matrix'} % \docType{methods} \keyword{hplot} \keyword{methods} % \alias{image} \alias{image-methods} % \alias{image,ANY-method} \alias{image,CHMfactor-method} \alias{image,Matrix-method} \alias{image,dgTMatrix-method} % \description{ Methods for function \code{\link[graphics]{image}} in package \pkg{Matrix}. An image of a matrix simply color codes all matrix entries and draws the \eqn{n\times m}{n x m} matrix using an \eqn{n\times m}{n x m} grid of (colored) rectangles. The \pkg{Matrix} package \code{image} methods are based on \code{\link[lattice]{levelplot}()} from package \pkg{lattice}; hence these methods return an \dQuote{object} of class \code{"trellis"}, producing a graphic when (auto-) \code{\link{print}()}ed. } \usage{ % want \usage{} since we have many "surprising arguments" \S4method{image}{dgTMatrix}(x, xlim = c(1, di[2]), ylim = c(di[1], 1), aspect = "iso", sub = sprintf("Dimensions: \%d x \%d", di[1], di[2]), xlab = "Column", ylab = "Row", cuts = 15, useRaster = FALSE, useAbs = NULL, colorkey = !useAbs, col.regions = NULL, lwd = NULL, border.col = NULL, \dots) } \arguments{ \item{x}{a Matrix object, i.e., fulfilling \code{\link{is}(x, "Matrix")}.} \item{xlim, ylim}{x- and y-axis limits; may be used to \dQuote{zoom into} matrix. Note that \eqn{x,y} \dQuote{feel reversed}: \code{ylim} is for the rows (= 1st index) and \code{xlim} for the columns (= 2nd index). For convenience, when the limits are integer valued, they are both extended by \code{0.5}; also, \code{ylim} is always used decreasingly.} \item{aspect}{aspect ratio specified as number (y/x) or string; see \code{\link[lattice]{levelplot}}.} \item{sub, xlab, ylab}{axis annotation with sensible defaults; see \code{\link{plot.default}}.} \item{cuts}{number of levels the range of matrix values would be divided into.} \item{useRaster}{logical indicating if raster graphics should be used (instead of the tradition rectangle vector drawing). If true, \code{\link[lattice]{panel.levelplot.raster}} (from \pkg{lattice} package) is used, and the colorkey is also done via rasters, see also \code{\link[lattice]{levelplot}} and possibly \code{\link[grid]{grid.raster}}. Note that using raster graphics may often be faster, but can be slower, depending on the matrix dimensions and the graphics device (dimensions).} \item{useAbs}{logical indicating if \code{\link{abs}(x)} should be shown; if \code{TRUE}, the former (implicit) default, the default \code{col.regions} will be \code{\link{grey}} colors (and no \code{colorkey} drawn). The default is \code{FALSE} unless the matrix has no negative entries.} \item{colorkey}{logical indicating if a color key aka \sQuote{legend} should be produced. Default is to draw one, unless \code{useAbs} is true. You can also specify a \code{\link{list}}, see \code{\link[lattice]{levelplot}}, such as\code{list(raster=TRUE)} in the case of rastering.} \item{col.regions}{vector of gradually varying colors; see \code{\link[lattice]{levelplot}}.} \item{lwd}{(only used when \code{useRaster} is false:) non-negative number or \code{NULL} (default), specifying the line-width of the rectangles of each non-zero matrix entry (drawn by \code{\link[grid]{grid.rect}}). The default depends on the matrix dimension and the device size.} \item{border.col}{color for the border of each rectangle. \code{NA} means no border is drawn. When \code{NULL} as by default, \code{border.col <- if(lwd < .01) NA else NULL} is used. Consider using an opaque color instead of \code{NULL} which corresponds to \code{grid::\link[grid]{get.gpar}("col")}.} \item{\dots}{further arguments passed to methods and \code{\link[lattice]{levelplot}}, notably \code{at} for specifying (possibly non equidistant) cut values for dividing the matrix values (superseding \code{cuts} above).}% FIXME? example *using* at=.. } \section{Methods}{ All methods currently end up calling the method for the \code{\linkS4class{dgTMatrix}} class. Use \code{showMethods(image)} to list them all. } \value{ as all \pkg{lattice} graphics functions, \code{image()} returns a \code{"trellis"} object, effectively the result of \code{\link[lattice]{levelplot}()}. } \seealso{ \code{\link[lattice]{levelplot}}, and \code{\link[lattice]{print.trellis}} from package \pkg{lattice}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(grDevices, pos = "package:base", verbose = FALSE) library( utils, pos = "package:base", verbose = FALSE) } showMethods(image) ## And if you want to see the method definitions: showMethods(image, includeDefs = TRUE, inherited = FALSE) \dontshow{ % warnings should not happen here, notably when print() op <- options(warn = 2) } data(CAex, package = "Matrix") image(CAex, main = "image(CAex)") -> imgC; imgC stopifnot(!is.null(leg <- imgC$legend), is.list(leg$right)) # failed for 2 days .. image(CAex, useAbs=TRUE, main = "image(CAex, useAbs=TRUE)") cCA <- Cholesky(crossprod(CAex), Imult = .01) ## See ?print.trellis --- place two image() plots side by side: print(image(cCA, main="Cholesky(crossprod(CAex), Imult = .01)"), split=c(x=1,y=1,nx=2, ny=1), more=TRUE) print(image(cCA, useAbs=TRUE), split=c(x=2,y=1,nx=2,ny=1)) data(USCounties, package = "Matrix") image(USCounties)# huge image(sign(USCounties))## just the pattern # how the result looks, may depend heavily on # the device, screen resolution, antialiasing etc # e.g. x11(type="Xlib") may show very differently than cairo-based ## Drawing borders around each rectangle; # again, viewing depends very much on the device: image(USCounties[1:400,1:200], lwd=.1) ## Using (xlim,ylim) has advantage : matrix dimension and (col/row) indices: image(USCounties, c(1,200), c(1,400), lwd=.1) image(USCounties, c(1,300), c(1,200), lwd=.5 ) image(USCounties, c(1,300), c(1,200), lwd=.01) ## These 3 are all equivalent : (I1 <- image(USCounties, c(1,100), c(1,100), useAbs=FALSE)) I2 <- image(USCounties, c(1,100), c(1,100), useAbs=FALSE, border.col=NA) I3 <- image(USCounties, c(1,100), c(1,100), useAbs=FALSE, lwd=2, border.col=NA) stopifnot(all.equal(I1, I2, check.environment=FALSE), all.equal(I2, I3, check.environment=FALSE)) ## using an opaque border color image(USCounties, c(1,100), c(1,100), useAbs=FALSE, lwd=3, border.col = adjustcolor("skyblue", 1/2)) \dontshow{options(op)} if(interactive() || nzchar(Sys.getenv("R_MATRIX_CHECK_EXTRA"))) { ## Using raster graphics: For PDF this would give a 77 MB file, ## however, for such a large matrix, this is typically considerably ## *slower* (than vector graphics rectangles) in most cases : if(doPNG <- !dev.interactive()) png("image-USCounties-raster.png", width=3200, height=3200) image(USCounties, useRaster = TRUE) # should not suffer from anti-aliasing if(doPNG) dev.off() ## and now look at the *.png image in a viewer you can easily zoom in and out }#only if(doExtras) } Matrix/man/sparseVector-class.Rd0000644000175100001440000002454014575137654016407 0ustar hornikusers\name{sparseVector-class} \title{Sparse Vector Classes} % \docType{class} \keyword{classes} \keyword{manip} % \alias{sparseVector-class} \alias{nsparseVector-class} \alias{lsparseVector-class} \alias{isparseVector-class} \alias{dsparseVector-class} \alias{zsparseVector-class} % sparse \alias{!,sparseVector-method} \alias{Arith,sparseVector,ddenseMatrix-method} \alias{Arith,sparseVector,dgeMatrix-method} \alias{Arith,sparseVector,sparseVector-method} \alias{Logic,sparseVector,dMatrix-method} \alias{Logic,sparseVector,lMatrix-method} \alias{Logic,sparseVector,nMatrix-method} \alias{Logic,sparseVector,sparseVector-method} \alias{Math,sparseVector-method} \alias{Math2,sparseVector-method} \alias{Ops,ANY,sparseVector-method} \alias{Ops,sparseVector,ANY-method} \alias{Ops,sparseVector,Matrix-method} \alias{Ops,sparseVector,sparseVector-method} \alias{Ops,sparseVector,vector-method} \alias{Ops,vector,sparseVector-method} \alias{Summary,sparseVector-method} \alias{as.array,sparseVector-method} \alias{as.complex,sparseVector-method} \alias{as.integer,sparseVector-method} \alias{as.logical,sparseVector-method} \alias{as.matrix,sparseVector-method} \alias{as.numeric,sparseVector-method} \alias{as.vector,sparseVector-method} \alias{coerce,ANY,sparseVector-method} \alias{coerce,matrix,sparseVector-method} \alias{coerce,sparseVector,CsparseMatrix-method} \alias{coerce,sparseVector,Matrix-method} \alias{coerce,sparseVector,RsparseMatrix-method} \alias{coerce,sparseVector,TsparseMatrix-method} \alias{coerce,sparseVector,denseMatrix-method} \alias{coerce,sparseVector,dsparseVector-method} \alias{coerce,sparseVector,generalMatrix-method} \alias{coerce,sparseVector,isparseVector-method} \alias{coerce,sparseVector,lsparseVector-method} \alias{coerce,sparseVector,nsparseVector-method} \alias{coerce,sparseVector,sparseMatrix-method} \alias{coerce,sparseVector,unpackedMatrix-method} \alias{coerce,sparseVector,zsparseVector-method} \alias{coerce,vector,dsparseVector-method} \alias{coerce,vector,isparseVector-method} \alias{coerce,vector,lsparseVector-method} \alias{coerce,vector,nsparseVector-method} \alias{coerce,vector,sparseVector-method} \alias{coerce,vector,zsparseVector-method} \alias{diff,sparseVector-method} \alias{dim<-,sparseVector-method} \alias{head,sparseVector-method} \alias{initialize,sparseVector-method} \alias{length,sparseVector-method} \alias{log,sparseVector-method} \alias{mean,sparseVector-method} \alias{rep,sparseVector-method} \alias{show,sparseVector-method} \alias{sort,sparseVector-method} \alias{t,sparseVector-method} \alias{tail,sparseVector-method} \alias{toeplitz,sparseVector-method} \alias{zapsmall,sparseVector-method} % nsparse \alias{!,nsparseVector-method} \alias{which,nsparseVector-method} % lsparse \alias{!,lsparseVector-method} \alias{Logic,lsparseVector,lsparseVector-method} \alias{which,lsparseVector-method} % isparse % dsparse \alias{-,dsparseVector,missing-method} \alias{Arith,dsparseVector,dsparseVector-method} % zsparse % \alias{c.sparseVector} % \description{Sparse Vector Classes: The virtual mother class \code{"sparseVector"} has the five actual daughter classes \code{"dsparseVector"}, \code{"isparseVector"}, \code{"lsparseVector"}, \code{"nsparseVector"}, and \code{"zsparseVector"}, where we've mainly implemented methods for the \code{d*}, \code{l*} and \code{n*} ones. } \section{Slots}{ \describe{ \item{\code{length}:}{class \code{"numeric"} - the \code{\link{length}} of the sparse vector. Note that \code{"numeric"} can be considerably larger than the maximal \code{"integer"}, \code{\link{.Machine}$integer.max}, on purpose.} \item{\code{i}:}{class \code{"numeric"} - the (1-based) indices of the non-zero entries. Must \emph{not} be \code{NA} and strictly sorted increasingly. Note that \code{"integer"} is \dQuote{part of} \code{"numeric"}, and can (and often will) be used for non-huge sparseVectors.} \item{\code{x}:}{(for all but \code{"nsparseVector"}): the non-zero entries. This is of class \code{"numeric"} for class \code{"dsparseVector"}, \code{"logical"} for class \code{"lsparseVector"}, etc.} } } \section{Methods}{ \describe{ \item{length}{\code{signature(x = "sparseVector")}: simply extracts the \code{length} slot.} \item{show}{\code{signature(object = "sparseVector")}: The \code{\link{show}} method for sparse vectors prints \emph{\dQuote{structural}} zeroes as \code{"."} using the non-exported \code{prSpVector} function which allows further customization such as replacing \code{"."} by \code{" "} (blank). Note that \code{\link{options}(max.print)} will influence how many entries of large sparse vectors are printed at all.} \item{as.vector}{\code{signature(x = "sparseVector", mode = "character")} coerces sparse vectors to \dQuote{regular}, i.e., atomic vectors. This is the same as \code{as(x, "vector")}.} \item{as}{..: see \code{coerce} below} \item{coerce}{\code{signature(from = "sparseVector", to = "sparseMatrix")}, and} \item{coerce}{\code{signature(from = "sparseMatrix", to = "sparseVector")}, etc: coercions to and from sparse matrices (\code{\linkS4class{sparseMatrix}}) are provided and work analogously as in standard \R, i.e., a vector is coerced to a 1-column matrix.} \item{dim<-}{\code{signature(x = "sparseVector", value = "integer")} coerces a sparse vector to a sparse Matrix, i.e., an object inheriting from \code{\linkS4class{sparseMatrix}}, of the appropriate dimension.} \item{head}{\code{signature(x = "sparseVector")}: as with \R's (package \pkg{util}) \code{\link{head}}, \code{head(x,n)} (for \eqn{n >= 1}) is equivalent to \code{x[1:n]}, but here can be much more efficient, see the example.} \item{tail}{\code{signature(x = "sparseVector")}: analogous to \code{\link{head}}, see above.} \item{toeplitz}{\code{signature(x = "sparseVector")}: as \code{\link[stats]{toeplitz}(x)}, produce the \eqn{n \times n} Toeplitz matrix from \code{x}, where \code{n = length(x)}.} \item{rep}{\code{signature(x = "sparseVector")} repeat \code{x}, with the same argument list \code{(x, times, length.out, each, ...)} as the default method for rep().} \item{which}{\code{signature(x = "nsparseVector")} and} \item{which}{\code{signature(x = "lsparseVector")} return the indices of the non-zero entries (which is trivial for sparse vectors).} \item{Ops}{\code{signature(e1 = "sparseVector", e2 = "*")}: define arithmetic, compare and logic operations, (see \code{\link[=S4groupGeneric]{Ops}}).} \item{Summary}{\code{signature(x = "sparseVector")}: define all the \code{\link[=S4groupGeneric]{Summary}} methods.} \item{is.na, is.finite, is.infinite}{\code{(x = "sparseVector")}, and} \item{is.na, is.finite, is.infinite}{\code{(x = "nsparseVector")}: return \code{\link{logical}} or \code{"nsparseVector"} of the same length as \code{x}, indicating if/where \code{x} is \code{\link{NA}} (or \code{NaN}), finite or infinite, entirely analogously to the corresponding base \R functions.} \item{zapsmall}{\code{signature(x = "sparseVectors")}: typically used for numeric sparse vector: \code{\link{round}()} entries such that (relatively) very small entries become zero exactly.} } \code{c.sparseVector()} is an S3 method for all \code{"sparseVector"}s, but automatic dispatch only happens for the first argument, so it is useful also as regular \R function, see the examples. } \seealso{ \code{\link{sparseVector}()} for friendly construction of sparse vectors (apart from \code{as(*, "sparseVector")}). } %\author{Martin} \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } getClass("sparseVector") getClass("dsparseVector") sx <- c(0,0,3, 3.2, 0,0,0,-3:1,0,0,2,0,0,5,0,0) (ss <- as(sx, "sparseVector")) ix <- as.integer(round(sx)) (is <- as(ix, "sparseVector")) ## an "isparseVector" (!) (ns <- sparseVector(i= c(7, 3, 2), length = 10)) # "nsparseVector" ## rep() works too: (ri <- rep(is, length.out= 25)) ## Using `dim<-` as in base R : r <- ss dim(r) <- c(4,5) # becomes a sparse Matrix: r ## or coercion (as as.matrix() in base R): as(ss, "Matrix") stopifnot(all(ss == print(as(ss, "CsparseMatrix")))) ## currently has "non-structural" FALSE -- printing as ":" (lis <- is & FALSE) (nn <- is[is == 0]) # all "structural" FALSE ## NA-case sN <- sx; sN[4] <- NA (svN <- as(sN, "sparseVector")) v <- as(c(0,0,3, 3.2, rep(0,9),-3,0,-1, rep(0,20),5,0), "sparseVector") v <- rep(rep(v, 50), 5000) set.seed(1); v[sample(v@i, 1e6)] <- 0 str(v) % Formal class 'dsparseVector' [package "Matrix"] with 3 slots % ..@ x : num [1:250000] 3.2 -1 -3 3 5 3.2 -3 3 -1 5 ... % ..@ length: int 9500000 % ..@ i : int [1:250000] 4 16 52 155 189 194 204 231 244 265 ... system.time(for(i in 1:4) hv <- head(v, 1e6)) ## user system elapsed ## 0.033 0.000 0.032 system.time(for(i in 1:4) h2 <- v[1:1e6]) ## user system elapsed ## 1.317 0.000 1.319 stopifnot(identical(hv, h2), identical(is | FALSE, is != 0), validObject(svN), validObject(lis), as.logical(is.na(svN[4])), identical(is^2 > 0, is & TRUE), all(!lis), !any(lis), length(nn@i) == 0, !any(nn), all(!nn), sum(lis) == 0, !prod(lis), range(lis) == c(0,0)) ## create and use the t(.) method: t(x20 <- sparseVector(c(9,3:1), i=c(1:2,4,7), length=20)) (T20 <- toeplitz(x20)) stopifnot(is(T20, "symmetricMatrix"), is(T20, "sparseMatrix"), identical(unname(as.matrix(T20)), toeplitz(as.vector(x20)))) ## c() method for "sparseVector" - also available as regular function (c1 <- c(x20, 0,0,0, -10*x20)) (c2 <- c(ns, is, FALSE)) (c3 <- c(ns, !ns, TRUE, NA, FALSE)) (c4 <- c(ns, rev(ns))) ## here, c() would produce a list {not dispatching to c.sparseVector()} (c5 <- c.sparseVector(0,0, x20)) ## checking (consistency) .v <- as.vector .s <- function(v) as(v, "sparseVector") stopifnot(exprs = { all.equal(c1, .s(c(.v(x20), 0,0,0, -10*.v(x20))), tol = 0) all.equal(c2, .s(c(.v(ns), .v(is), FALSE)), tol = 0) all.equal(c3, .s(c(.v(ns), !.v(ns), TRUE, NA, FALSE)), tol = 0) all.equal(c4, .s(c(.v(ns), rev(.v(ns)))), tol = 0, check.class = FALSE) all.equal(c5, .s(c(0,0, .v(x20))), tol = 0) }) } Matrix/man/dgCMatrix-class.Rd0000644000175100001440000000510514446607050015572 0ustar hornikusers\name{dgCMatrix-class} \title{Compressed, sparse, column-oriented numeric matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{dgCMatrix-class} \alias{Arith,dgCMatrix,dgCMatrix-method} \alias{Arith,dgCMatrix,logical-method} \alias{Arith,dgCMatrix,numeric-method} \alias{Arith,logical,dgCMatrix-method} \alias{Arith,numeric,dgCMatrix-method} \alias{coerce,matrix,dgCMatrix-method} \alias{determinant,dgCMatrix,logical-method} % \description{The \code{dgCMatrix} class is a class of sparse numeric matrices in the compressed, sparse, column-oriented format. In this implementation the non-zero elements in the columns are sorted into increasing row order. \code{dgCMatrix} is the \emph{\dQuote{standard}} class for sparse numeric matrices in the \pkg{Matrix} package. } \section{Objects from the Class}{ Objects can be created by calls of the form \code{new("dgCMatrix", ...)}, more typically via \code{as(*, "CsparseMatrix")} or similar. Often however, more easily via \code{\link{Matrix}(*, sparse = TRUE)}, or most efficiently via \code{\link{sparseMatrix}()}. } \section{Slots}{ \describe{ \item{\code{x}:}{Object of class \code{"numeric"} - the non-zero elements of the matrix.} \item{\dots}{all other slots are inherited from the superclass \code{"\linkS4class{CsparseMatrix}"}. } } } \section{Methods}{ Matrix products (e.g., \link{crossprod-methods}), and (among other) \describe{ \item{coerce}{\code{signature(from = "matrix", to = "dgCMatrix")}} \item{diag}{\code{signature(x = "dgCMatrix")}: returns the diagonal of \code{x}} \item{dim}{\code{signature(x = "dgCMatrix")}: returns the dimensions of \code{x}} \item{image}{\code{signature(x = "dgCMatrix")}: plots an image of \code{x} using the \code{\link[lattice]{levelplot}} function} \item{solve}{\code{signature(a = "dgCMatrix", b = "...")}: see \code{\link{solve-methods}}, notably the extra argument \code{sparse}.} \item{lu}{\code{signature(x = "dgCMatrix")}: computes the LU decomposition of a square \code{dgCMatrix} object} } } %\references{} %\author{} %\note{} \seealso{ Classes \code{\linkS4class{dsCMatrix}}, \code{\linkS4class{dtCMatrix}}, \code{\link{lu}} } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(utils, pos = "package:base", verbose = FALSE) } (m <- Matrix(c(0,0,2:0), 3,5)) str(m) m[,1] \dontshow{## regression test: this must give a validity-check error: stopifnot(inherits(try(new("dgCMatrix", i = 0:1, p = 0:2, x = c(2,3), Dim = 3:4)), "try-error")) } } Matrix/man/dsparseMatrix-class.Rd0000644000175100001440000000252514500445405016534 0ustar hornikusers\name{dsparseMatrix-class} \title{Virtual Class "dsparseMatrix" of Numeric Sparse Matrices} % \docType{class} \keyword{array} \keyword{classes} % \alias{dsparseMatrix-class} % \alias{Arith,dsparseMatrix,logical-method} \alias{Arith,dsparseMatrix,numeric-method} \alias{Arith,logical,dsparseMatrix-method} \alias{Arith,numeric,dsparseMatrix-method} \alias{Ops,dsparseMatrix,nsparseMatrix-method} \alias{coerce,matrix,dsparseMatrix-method} \alias{coerce,vector,dsparseMatrix-method} % \description{The Class \code{"dsparseMatrix"} is the virtual (super) class of all numeric sparse matrices. } \section{Slots}{ \describe{ \item{\code{Dim}:}{the matrix dimension, see class \code{"\linkS4class{Matrix}"}.} \item{\code{Dimnames}:}{see the \code{"Matrix"} class.} \item{\code{x}:}{a \code{\link{numeric}} vector containing the (non-zero) matrix entries.} } } \section{Extends}{ Class \code{"dMatrix"} and \code{"sparseMatrix"}, directly.\cr Class \code{"Matrix"}, by the above classes. } % \section{Methods}{ % No methods defined with class "dsparseMatrix" in the signature. % } %%\author{Martin} \seealso{ the documentation of the (non virtual) sub classes, see \code{showClass("dsparseMatrix")}; in particular, \linkS4class{dgTMatrix}, \linkS4class{dgCMatrix}, and \linkS4class{dgRMatrix}. } \examples{ showClass("dsparseMatrix") } Matrix/man/asUniqueT.Rd0000644000175100001440000000625414575137654014544 0ustar hornikusers\name{asUniqueT} \title{Standardize a Sparse Matrix in Triplet Format} % \keyword{array} \keyword{logic} \keyword{manip} \keyword{utilities} % \alias{anyDuplicatedT} \alias{isUniqueT} \alias{asUniqueT} \alias{aggregateT} % \alias{uniqTsparse} % \description{ Detect or standardize a \code{\linkS4class{TsparseMatrix}} with unsorted or duplicated \eqn{(i,j)} pairs. } \usage{ anyDuplicatedT(x, \dots) isUniqueT(x, byrow = FALSE, isT = is(x, "TsparseMatrix")) asUniqueT(x, byrow = FALSE, isT = is(x, "TsparseMatrix")) aggregateT(x) } \arguments{ \item{x}{an \R{} object. \code{anyDuplicatedT} and \code{aggregateT} require \code{x} inheriting from \code{\linkS4class{TsparseMatrix}}. \code{asUniqueT} requires \code{x} inheriting from \code{\linkS4class{Matrix}} and coerces \code{x} to \code{\linkS4class{TsparseMatrix}} if necessary.} \item{\dots}{optional arguments passed to the default method for generic function \code{\link{anyDuplicated}}.} \item{byrow}{a logical indicating if \code{x} should be sorted by row then by column.} \item{isT}{a logical indicating if \code{x} inherits from virtual class \code{\linkS4class{TsparseMatrix}}.} } \value{ \code{anyDuplicatedT(x)} returns the index of the first duplicated \eqn{(i,j)} pair in \code{x} (0 if there are no duplicated pairs). \code{isUniqueT(x)} returns \code{TRUE} if \code{x} is a \code{\linkS4class{TsparseMatrix}} with sorted, nonduplicated \eqn{(i,j)} pairs and \code{FALSE} otherwise. \code{asUniqueT(x)} returns the unique \code{\linkS4class{TsparseMatrix}} representation of \code{x} with sorted, nonduplicated \eqn{(i,j)} pairs. Values corresponding to identical \eqn{(i,j)} pairs are aggregated by addition, where in the logical case \dQuote{addition} refers to logical OR. \code{aggregateT(x)} aggregates without sorting. } \seealso{Virtual class \code{\linkS4class{TsparseMatrix}}.} \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) library(utils, pos = "package:base", verbose = FALSE) } example("dgTMatrix-class", echo=FALSE) ## -> 'T2' with (i,j,x) slots of length 5 each T2u <- asUniqueT(T2) stopifnot(## They "are" the same (and print the same): all.equal(T2, T2u, tol=0), ## but not internally: anyDuplicatedT(T2) == 2, anyDuplicatedT(T2u) == 0, length(T2 @x) == 5, length(T2u@x) == 3) isUniqueT(T2 ) # FALSE isUniqueT(T2u) # TRUE T3 <- T2u T3[1, c(1,3)] <- 10; T3[2, c(1,5)] <- 20 T3u <- asUniqueT(T3) str(T3u) # sorted in 'j', and within j, sorted in i stopifnot(isUniqueT(T3u)) ## Logical l.TMatrix and n.TMatrix : (L2 <- T2 > 0) validObject(L2u <- asUniqueT(L2)) (N2 <- as(L2, "nMatrix")) validObject(N2u <- asUniqueT(N2)) stopifnot(N2u@i == L2u@i, L2u@i == T2u@i, N2@i == L2@i, L2@i == T2@i, N2u@j == L2u@j, L2u@j == T2u@j, N2@j == L2@j, L2@j == T2@j) # now with a nasty NA [partly failed in Matrix 1.1-5]: L.0N <- L.1N <- L2 L.0N@x[1:2] <- c(FALSE, NA) L.1N@x[1:2] <- c(TRUE, NA) validObject(L.0N) validObject(L.1N) (m.0N <- as.matrix(L.0N)) (m.1N <- as.matrix(L.1N)) stopifnot(identical(10L, which(is.na(m.0N))), !anyNA(m.1N)) symnum(m.0N) symnum(m.1N) } Matrix/man/MatrixClass.Rd0000644000175100001440000000221414422605232015027 0ustar hornikusers\name{MatrixClass} \title{The Matrix (Super-) Class of a Class} % \keyword{utilities} % \alias{MatrixClass} \description{ Return the (maybe super-)\code{\link{class}} of class \code{cl} from package \pkg{Matrix}, returning \code{\link{character}(0)} if there is none. } \usage{ MatrixClass(cl, cld = getClassDef(cl), ...Matrix = TRUE, dropVirtual = TRUE, ...) } \arguments{ \item{cl}{string, class name} \item{cld}{its class definition} \item{...Matrix}{\code{\link{logical}} indicating if the result must be of pattern \code{"[dlniz]..Matrix"} where the first letter "[dlniz]" denotes the content kind.} \item{dropVirtual}{\code{\link{logical}} indicating if virtual classes are included or not.}% ?? (FIXME) -- example \item{\dots}{further arguments are passed to \code{\link{.selectSuperClasses}()}.} } \value{ a \code{\link{character}} string } \author{Martin Maechler, 24 Mar 2009} %% \details{ %% } \seealso{ \code{\linkS4class{Matrix}}, the mother of all \pkg{Matrix} classes. } \examples{ mkA <- setClass("A", contains="dgCMatrix") (A <- mkA()) stopifnot(identical( MatrixClass("A"), "dgCMatrix")) } Matrix/man/Diagonal.Rd0000644000175100001440000001122314446607050014321 0ustar hornikusers\name{Diagonal} \title{Construct a Diagonal Matrix} % \keyword{array} \keyword{utilities} % \alias{Diagonal} \alias{.sparseDiagonal} \alias{.trDiagonal} \alias{.symDiagonal} % \description{ Construct a formally diagonal \code{\linkS4class{Matrix}}, i.e., an object inheriting from virtual class \code{\linkS4class{diagonalMatrix}} (or, if desired, a \emph{mathematically} diagonal \code{\linkS4class{CsparseMatrix}}). } \usage{ Diagonal(n, x = NULL, names = FALSE) .sparseDiagonal(n, x = NULL, uplo = "U", shape = "t", unitri = TRUE, kind, cols) .trDiagonal(n, x = NULL, uplo = "U", unitri = TRUE, kind) .symDiagonal(n, x = NULL, uplo = "U", kind) } \arguments{ \item{n}{integer indicating the dimension of the (square) matrix. If missing, then \code{length(x)} is used.} \item{x}{numeric or logical vector listing values for the diagonal entries, to be recycled as necessary. If \code{NULL} (the default), then the result is a unit diagonal matrix. \code{.sparseDiagonal()} and friends ignore non-\code{NULL} \code{x} when \code{kind = "n"}.} \item{names}{either \code{\link{logical}} \code{TRUE} or \code{FALSE} or then a \code{\link{character}} vector of \code{\link{length}} \code{n}. If true \emph{and} \code{\link{names}(x)} is not \code{NULL}, use that as both row and column names for the resulting matrix. When a character vector, use it for both dimnames.} \item{uplo}{one of \code{c("U","L")}, specifying the \code{uplo} slot of the result if the result is formally triangular of symmetric.} \item{shape}{one of \code{c("t","s","g")}, indicating if the result should be formally triangular, symmetric, or \dQuote{general}. The result will inherit from virtual class \code{\linkS4class{triangularMatrix}}, \code{\linkS4class{symmetricMatrix}}, or \code{\linkS4class{generalMatrix}}, respectively.} \item{unitri}{logical indicating if a formally triangular result with ones on the diagonal should be formally \emph{unit} triangular, i.e., with \code{diag} slot equal to \code{"U"} rather than \code{"N"}.} \item{kind}{one of \code{c("d","l","n")}, indicating the \dQuote{mode} of the result: numeric, logical, or pattern. The result will inherit from virtual class \code{\linkS4class{dsparseMatrix}}, \code{\linkS4class{lsparseMatrix}}, or \code{\linkS4class{nsparseMatrix}}, respectively. Values other than \code{"n"} are ignored when \code{x} is non-\code{NULL}; in that case the mode is determined by \code{\link{typeof}(x)}.} \item{cols}{optional integer vector with values in \code{0:(n-1)}, indexing columns of the specified diagonal matrix. If specified, then the result is (mathematically) \code{D[, cols+1]} rather than \code{D}, where \code{D = Diagonal(n, x)}, and it is always \dQuote{general} (i.e., \code{shape} is ignored).} } \value{ \code{Diagonal()} returns an object inheriting from virtual class \code{\linkS4class{diagonalMatrix}}. \code{.sparseDiagonal()} returns a \code{\linkS4class{CsparseMatrix}} representation of \code{Diagonal(n, x)} or, if \code{cols} is given, of \code{Diagonal(n, x)[, cols+1]}. The precise class of the result depends on \code{shape} and \code{kind}. \code{.trDiagonal()} and \code{.symDiagonal()} are simple wrappers, for \code{.sparseDiagonal(shape = "t")} and \code{.sparseDiagonal(shape = "s")}, respectively. \code{.sparseDiagonal()} exists primarily to leverage efficient C-level methods available for \code{CsparseMatrix}. } \author{Martin Maechler} \seealso{the generic function \code{\link{diag}} for \emph{extraction} of the diagonal from a matrix works for all \dQuote{Matrices}. \code{\link{bandSparse}} constructs a \emph{banded} sparse matrix from its non-zero sub-/super - diagonals. \code{\link{band}(A)} returns a band matrix containing some sub-/super - diagonals of \code{A}. \code{\link{Matrix}} for general matrix construction; further, class \code{\linkS4class{diagonalMatrix}}. } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) } Diagonal(3) Diagonal(x = 10^(3:1)) Diagonal(x = (1:4) >= 2)#-> "ldiMatrix" ## Use Diagonal() + kronecker() for "repeated-block" matrices: M1 <- Matrix(0+0:5, 2,3) (M <- kronecker(Diagonal(3), M1)) (S <- crossprod(Matrix(rbinom(60, size=1, prob=0.1), 10,6))) (SI <- S + 10*.symDiagonal(6)) # sparse symmetric still stopifnot(is(SI, "dsCMatrix")) (I4 <- .sparseDiagonal(4, shape="t"))# now (2012-10) unitriangular stopifnot(I4@diag == "U", all(I4 == diag(4))) \dontshow{% checking some "unit-diagonality": L <- Diagonal(5, TRUE) stopifnot(L@diag == "U", identical(L, Diagonal(5) > 0)) } } Matrix/man/subassign-methods.Rd0000644000175100001440000001325214575137654016261 0ustar hornikusers\name{subassign-methods} \title{Methods for "[<-" - Assigning to Subsets for 'Matrix'} % \docType{methods} \keyword{array} \keyword{methods} % \alias{[<-} \alias{[<--methods} \alias{subassign-methods} % \alias{[<-,CsparseMatrix,Matrix,missing,replValue-method} \alias{[<-,CsparseMatrix,index,index,replValue-method} \alias{[<-,CsparseMatrix,index,index,sparseVector-method} \alias{[<-,CsparseMatrix,index,missing,replValue-method} \alias{[<-,CsparseMatrix,index,missing,sparseVector-method} \alias{[<-,CsparseMatrix,matrix,missing,replValue-method} \alias{[<-,CsparseMatrix,missing,index,replValue-method} \alias{[<-,CsparseMatrix,missing,index,sparseVector-method} \alias{[<-,Matrix,ANY,ANY,ANY-method} \alias{[<-,Matrix,ANY,ANY,Matrix-method} \alias{[<-,Matrix,ANY,ANY,matrix-method} \alias{[<-,Matrix,ANY,missing,Matrix-method} \alias{[<-,Matrix,ANY,missing,matrix-method} \alias{[<-,Matrix,ldenseMatrix,missing,replValue-method} \alias{[<-,Matrix,lsparseMatrix,missing,replValue-method} \alias{[<-,Matrix,matrix,missing,replValue-method} \alias{[<-,Matrix,missing,ANY,Matrix-method} \alias{[<-,Matrix,missing,ANY,matrix-method} \alias{[<-,Matrix,ndenseMatrix,missing,replValue-method} \alias{[<-,Matrix,nsparseMatrix,missing,replValue-method} \alias{[<-,RsparseMatrix,index,index,replValue-method} \alias{[<-,RsparseMatrix,index,index,sparseVector-method} \alias{[<-,RsparseMatrix,index,missing,replValue-method} \alias{[<-,RsparseMatrix,index,missing,sparseVector-method} \alias{[<-,RsparseMatrix,matrix,missing,replValue-method} \alias{[<-,RsparseMatrix,missing,index,replValue-method} \alias{[<-,RsparseMatrix,missing,index,sparseVector-method} \alias{[<-,TsparseMatrix,Matrix,missing,replValue-method} \alias{[<-,TsparseMatrix,index,index,replValue-method} \alias{[<-,TsparseMatrix,index,index,sparseVector-method} \alias{[<-,TsparseMatrix,index,missing,replValue-method} \alias{[<-,TsparseMatrix,index,missing,sparseVector-method} \alias{[<-,TsparseMatrix,matrix,missing,replValue-method} \alias{[<-,TsparseMatrix,missing,index,replValue-method} \alias{[<-,TsparseMatrix,missing,index,sparseVector-method} \alias{[<-,denseMatrix,index,index,replValue-method} \alias{[<-,denseMatrix,index,missing,replValue-method} \alias{[<-,denseMatrix,matrix,missing,replValue-method} \alias{[<-,denseMatrix,missing,index,replValue-method} \alias{[<-,denseMatrix,missing,missing,ANY-method} \alias{[<-,diagonalMatrix,index,index,replValue-method} \alias{[<-,diagonalMatrix,index,index,sparseMatrix-method} \alias{[<-,diagonalMatrix,index,index,sparseVector-method} \alias{[<-,diagonalMatrix,index,missing,replValue-method} \alias{[<-,diagonalMatrix,index,missing,sparseMatrix-method} \alias{[<-,diagonalMatrix,index,missing,sparseVector-method} \alias{[<-,diagonalMatrix,matrix,missing,replValue-method} \alias{[<-,diagonalMatrix,missing,index,replValue-method} \alias{[<-,diagonalMatrix,missing,index,sparseMatrix-method} \alias{[<-,diagonalMatrix,missing,index,sparseVector-method} \alias{[<-,diagonalMatrix,missing,missing,ANY-method} \alias{[<-,indMatrix,index,index,ANY-method} \alias{[<-,indMatrix,index,missing,ANY-method} \alias{[<-,indMatrix,missing,index,ANY-method} \alias{[<-,indMatrix,missing,missing,ANY-method} \alias{[<-,sparseMatrix,ANY,ANY,sparseMatrix-method} \alias{[<-,sparseMatrix,ANY,missing,sparseMatrix-method} \alias{[<-,sparseMatrix,missing,ANY,sparseMatrix-method} \alias{[<-,sparseMatrix,missing,missing,ANY-method} \alias{[<-,sparseVector,index,missing,ANY-method} \alias{[<-,sparseVector,sparseVector,missing,ANY-method} % \description{ Methods for \code{"[<-"}, i.e., extraction or subsetting mostly of matrices, in package \pkg{Matrix}. \bold{Note}: Contrary to standard \code{\link{matrix}} assignment in base \R, in \code{x[..] <- val} it is typically an \bold{error} (see \code{\link{stop}}) when the \link{type} or \code{\link{class}} of \code{val} would require the class of \code{x} to be changed, e.g., when \code{x} is logical, say \code{"lsparseMatrix"}, and \code{val} is numeric. In other cases, e.g., when \code{x} is a \code{"nsparseMatrix"} and \code{val} is not \code{TRUE} or \code{FALSE}, a warning is signalled, and \code{val} is \dQuote{interpreted} as \code{\link{logical}}, and (logical) \code{\link{NA}} is interpreted as \code{TRUE}. } \section{Methods}{ There are \emph{many many} more than these: \describe{ \item{x = "Matrix", i = "missing", j = "missing", value= "ANY"}{ is currently a simple fallback method implementation which ensures \dQuote{readable} error messages.} \item{x = "Matrix", i = "ANY", j = "ANY", value= "ANY"}{ currently gives an error } \item{x = "denseMatrix", i = "index", j = "missing", value= "numeric"}{ ... } \item{x = "denseMatrix", i = "index", j = "index", value= "numeric"}{ ... } \item{x = "denseMatrix", i = "missing", j = "index", value= "numeric"}{ ... } } } \seealso{ %% ./Xtrct-methods.Rd: \code{\link{[-methods}} for subsetting \code{"Matrix"} objects; the \code{\linkS4class{index}} class; \code{\link{Extract}} about the standard subset assignment (and extraction). } \examples{ \dontshow{ % for R_DEFAULT_PACKAGES=NULL library(stats, pos = "package:base", verbose = FALSE) } %% Note that ./Xtrct-methods.Rd has the indexing ones set.seed(101) (a <- m <- Matrix(round(rnorm(7*4),2), nrow = 7)) a[] <- 2.2 # <<- replaces **every** entry a ## as do these: a[,] <- 3 ; a[TRUE,] <- 4 m[2, 3] <- 3.14 # simple number m[3, 3:4]<- 3:4 # simple numeric of length 2 ## sub matrix assignment: m[-(4:7), 3:4] <- cbind(1,2:4) #-> upper right corner of 'm' m[3:5, 2:3] <- 0 m[6:7, 1:2] <- Diagonal(2) m ## rows or columns only: m[1,] <- 10 m[,2] <- 1:7 m[-(1:6), ] <- 3:0 # not the first 6 rows, i.e. only the 7th as(m, "sparseMatrix") } Matrix/man/expm-methods.Rd0000644000175100001440000000506514575137654015237 0ustar hornikusers\name{expm-methods} \title{Matrix Exponential} % \docType{methods} \keyword{array} \keyword{math} \keyword{methods} % \alias{expm} \alias{expm-methods} % \alias{expm,Matrix-method} \alias{expm,dMatrix-method} \alias{expm,ddiMatrix-method} \alias{expm,dgeMatrix-method} \alias{expm,dspMatrix-method} \alias{expm,dsparseMatrix-method} \alias{expm,dsyMatrix-method} \alias{expm,dtpMatrix-method} \alias{expm,dtrMatrix-method} \alias{expm,matrix-method} % \description{ Compute the exponential of a matrix. } \usage{ expm(x) } \arguments{ \item{x}{a matrix, typically inheriting from the \code{\linkS4class{dMatrix}} class.} } \details{ The exponential of a matrix is defined as the infinite Taylor series \code{expm(A) = I + A + A^2/2! + A^3/3! + ...} (although this is definitely not the way to compute it). The method for the \code{dgeMatrix} class uses Ward's diagonal Pade' approximation with three step preconditioning, a recommendation from Moler & Van Loan (1978) \dQuote{Nineteen dubious ways\dots}. } \value{ The matrix exponential of \code{x}. } \references{ \url{https://en.wikipedia.org/wiki/Matrix_exponential} Cleve Moler and Charles Van Loan (2003) Nineteen dubious ways to compute the exponential of a matrix, twenty-five years later. \emph{SIAM Review} \bold{45}, 1, 3--49. \doi{10.1137/S00361445024180} \emph{for historical reference mostly:}\cr Moler, C. and Van Loan, C. (1978) Nineteen dubious ways to compute the exponential of a matrix. \emph{SIAM Review} \bold{20}, 4, 801--836. \doi{10.1137/1020098} %% MM: Till we have something better, this is quite good: Eric W. Weisstein et al. (1999) \emph{Matrix Exponential}. From MathWorld, \url{https://mathworld.wolfram.com/MatrixExponential.html} } \author{This is a translation of the implementation of the corresponding Octave function contributed to the Octave project by A. Scottedward Hodel \email{A.S.Hodel@Eng.Auburn.EDU}. A bug in there has been fixed by Martin Maechler. } %\note{} \seealso{ Package \CRANpkg{expm}, which provides newer (in some cases faster, more accurate) algorithms for computing the matrix exponential via its own (non-generic) function \code{expm()}. \pkg{expm} also implements \code{logm()}, \code{sqrtm()}, etc. Generic function \code{\link{Schur}}. } \examples{ (m1 <- Matrix(c(1,0,1,1), ncol = 2)) (e1 <- expm(m1)) ; e <- exp(1) stopifnot(all.equal(e1@x, c(e,0,e,e), tolerance = 1e-15)) (m2 <- Matrix(c(-49, -64, 24, 31), ncol = 2)) (e2 <- expm(m2)) (m3 <- Matrix(cbind(0,rbind(6*diag(3),0))))# sparse! (e3 <- expm(m3)) # upper triangular } Matrix/DESCRIPTION0000644000175100001440000000633314612713766013264 0ustar hornikusersPackage: Matrix Version: 1.7-0 VersionNote: do also bump src/version.h, inst/include/Matrix/version.h Date: 2024-03-16 Priority: recommended Title: Sparse and Dense Matrix Classes and Methods Description: A rich hierarchy of sparse and dense matrix classes, including general, symmetric, triangular, and diagonal matrices with numeric, logical, or pattern entries. Efficient methods for operating on such matrices, often wrapping the 'BLAS', 'LAPACK', and 'SuiteSparse' libraries. License: GPL (>= 2) | file LICENCE URL: https://Matrix.R-forge.R-project.org BugReports: https://R-forge.R-project.org/tracker/?atid=294&group_id=61 Contact: Matrix-authors@R-project.org Authors@R: c(person("Douglas", "Bates", role = "aut", comment = c(ORCID = "0000-0001-8316-9503")), person("Martin", "Maechler", role = c("aut", "cre"), email = "mmaechler+Matrix@gmail.com", comment = c(ORCID = "0000-0002-8685-9910")), person("Mikael", "Jagan", role = "aut", comment = c(ORCID = "0000-0002-3542-2938")), person("Timothy A.", "Davis", role = "ctb", comment = c(ORCID = "0000-0001-7614-6899", "SuiteSparse libraries", "collaborators listed in dir(system.file(\"doc\", \"SuiteSparse\", package=\"Matrix\"), pattern=\"License\", full.names=TRUE, recursive=TRUE)")), person("George", "Karypis", role = "ctb", comment = c(ORCID = "0000-0003-2753-1437", "METIS library", "Copyright: Regents of the University of Minnesota")), person("Jason", "Riedy", role = "ctb", comment = c(ORCID = "0000-0002-4345-4200", "GNU Octave's condest() and onenormest()", "Copyright: Regents of the University of California")), person("Jens", "Oehlschlägel", role = "ctb", comment = "initial nearPD()"), person("R Core Team", role = "ctb", comment = "base R's matrix implementation")) Depends: R (>= 4.4.0), methods Imports: grDevices, graphics, grid, lattice, stats, utils Suggests: MASS, datasets, sfsmisc, tools Enhances: SparseM, graph LazyData: no LazyDataNote: not possible, since we use data/*.R and our S4 classes BuildResaveData: no Encoding: UTF-8 NeedsCompilation: yes Packaged: 2024-03-19 17:15:14 UTC; maechler Author: Douglas Bates [aut] (), Martin Maechler [aut, cre] (), Mikael Jagan [aut] (), Timothy A. Davis [ctb] (, SuiteSparse libraries, collaborators listed in dir(system.file("doc", "SuiteSparse", package="Matrix"), pattern="License", full.names=TRUE, recursive=TRUE)), George Karypis [ctb] (, METIS library, Copyright: Regents of the University of Minnesota), Jason Riedy [ctb] (, GNU Octave's condest() and onenormest(), Copyright: Regents of the University of California), Jens Oehlschlägel [ctb] (initial nearPD()), R Core Team [ctb] (base R's matrix implementation) Maintainer: Martin Maechler Repository: CRAN Date/Publication: 2024-04-26 12:03:02 UTC Matrix/build/0000755000175100001440000000000014576344040012642 5ustar hornikusersMatrix/build/vignette.rds0000644000175100001440000000063614576344040015206 0ustar hornikusersSAO0!ň %!΃f{`hډ&bczh=i:+\rj1s\+GlpF莮5|'KzA8Ϡ1R ~ã,*f,XcGlns Q0q~& @uٹ⇦?D(RP' ,YlL#TeCL\U?g QqE's-v˼ݰeF nɜve!U3YÇZlP^ ,u",0a $65w7QKQh{g; xv|UWp~ EUv CwBbؼ{"ʠ5'z0- Y*cQ7eiu|f3 cJreFT wiMatrix/build/partial.rdb0000644000175100001440000000007414576343417014777 0ustar hornikusersb```b`a 00 FN ͚Z d@$$7Matrix/tests/0000755000175100001440000000000014576344041012706 5ustar hornikusersMatrix/tests/matr-exp.R0000644000175100001440000000535514507035046014572 0ustar hornikusers## for R_DEFAULT_PACKAGES=NULL : library(stats) library(Matrix) ## Matrix Exponential source(system.file("test-tools.R", package = "Matrix")) ## e ^ 0 = 1 - for matrices: assert.EQ.mat(expm(Matrix(0, 3,3)), diag(3), tol = 0)# exactly ## e ^ diag(.) = diag(e ^ .): assert.EQ.mat(expm(as(diag(-1:4), "generalMatrix")), diag(exp(-1:4))) set.seed(1) rE <- replicate(100, { x <- rlnorm(12) relErr(as(expm(as(diag(x), "generalMatrix")), "matrix"), diag(exp(x))) }) stopifnot(mean(rE) < 1e-15, max(rE) < 1e-14) summary(rE) ## Some small matrices m1 <- Matrix(c(1,0,1,1), ncol = 2) e1 <- expm(m1) assert.EQ.mat(e1, cbind(c(exp(1),0), exp(1))) (p1 <- pack(m1)) stopifnot(exprs = { is(p1, "dtpMatrix") all.equal(pack(e1), expm(p1), tolerance = 2e-15)# failed in Matrix 1.6.1 }) m2 <- Matrix(c(-49, -64, 24, 31), ncol = 2) e2 <- expm(m2) ## The true matrix exponential is 'te2': e_1 <- exp(-1) e_17 <- exp(-17) te2 <- rbind(c(3*e_17 - 2*e_1, -3/2*e_17 + 3/2*e_1), c(4*e_17 - 4*e_1, -2 *e_17 + 3 *e_1)) assert.EQ.mat(e2, te2, tol = 1e-13) ## See the (average relative) difference: all.equal(as(e2,"matrix"), te2, tolerance = 0) # 2.22e-14 {was 1.48e-14} on "lynne" (dsp <- pack(crossprod(matrix(-2:3, 2,3)))) stopifnot(all(abs(expm(dsp) - expm(as.matrix(dsp))) <= 0.5)) # failed badly in Matrix 1.6.1 ## The ``surprising identity'' det(exp(A)) == exp( tr(A) ) ## or log det(exp(A)) == tr(A) : stopifnot(all.equal(c(determinant(e2)$modulus), sum(diag(m2)))) ## a very simple nilpotent one: (m3 <- Matrix(cbind(0,rbind(6*diag(3),0))))# sparse stopifnot(all(m3 %*% m3 %*% m3 %*% m3 == 0))# <-- m3 "^" 4 == 0 e3 <- expm(m3) E3 <- expm(Matrix(m3, sparse=FALSE)) s3 <- symmpart(m3) # dsCMatrix es3 <- expm(s3) e3. <- rbind(c(1,6,18,36), c(0,1, 6,18), c(0,0, 1, 6), c(0,0, 0, 1)) stopifnot(is(e3, "triangularMatrix"), is(es3, "symmetricMatrix"), identical(e3, E3), identical(as.mat(e3), e3.), all.equal(as(es3,"generalMatrix"), expm(as(s3,"generalMatrix"))) ) ## This used to be wrong {bug in octave-origin code}: M6 <- Matrix(c(0, -2, 0, 0, 0, 0, 10, 0, 0, 0,10,-2, 0, 0, 0, 0,-2, 0, 0, 10,-2,-2,-2,10, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0), 6, 6) exp.M6 <- expm(M6) as(exp.M6, "sparseMatrix")# prints a bit more nicely stopifnot(all.equal(t(exp.M6), expm(t(M6)), tolerance = 1e-12), all.equal(exp.M6[,3], c(0,0,1,0,-2,0), tolerance = 1e-12), all.equal(exp.M6[,5], c(0,0,0,0, 1,0), tolerance = 1e-12), all(exp.M6[3:4, c(1:2,5:6)] == 0) ) cat('Time elapsed: ', proc.time(),'\n') # for ``statistical reasons'' Matrix/tests/Class+Meth.R0000644000175100001440000003622214575137654015005 0ustar hornikuserslibrary(Matrix) source(system.file("test-tools.R", package = "Matrix"))# identical3(), # further checkMatrix(), etc if(interactive()) options(error = recover) options(warn=1)# show as they happen cat("doExtras:",doExtras,"\n") setClass("myDGC", contains = "dgCMatrix") (M <- new("myDGC", as(Matrix(c(-2:4, rep(0,9)), 4), "CsparseMatrix"))) stopifnot(exprs = { M[-4L, 2L] == 2:4 MatrixClass( "myDGC") == "dgCMatrix" MatrixClass( "dpoMatrix") == "dsyMatrix" MatrixClass( "dppMatrix") == "dspMatrix" MatrixClass( "corMatrix") == "dsyMatrix" MatrixClass( "copMatrix") == "dspMatrix" identical(MatrixClass("indMatrix"), character(0L)) identical(MatrixClass( "pMatrix"), character(0L)) }) ## [matrix-Bugs][6182] Coercion method doesn't work on child class ## Bugs item #6182, at 2015-09-01 17:49 by Vitalie Spinu setClass("A", contains = "ngCMatrix") ngc <- as(as(as(diag(3), "CsparseMatrix"), "generalMatrix"), "nMatrix") validObject(dd <- as(ngc, "dMatrix")) # fine A. <- as(ngc, "A") stopifnot(identical(as(A., "dMatrix"), dd)) ## as(.) coercion failed in Matrix <= 1.2.3 stopifnot(all( abs(A.)# failed too == diag(3))) d <- Diagonal(3) (dC <- as(d, "CsparseMatrix")) # "dtCMatrix" (unitriangular) (dgC <- as(dC, "generalMatrix")) stopifnot(exprs = { is(dgC, "dgCMatrix") # was wrong in Matrix 1.3.2 ## identical(dgC, as(dC, "dgCMatrix")) # deprecated identical(dC , new("dtCMatrix", p = rep(0L, 4), Dim = c(3L, 3L), diag = "U")) identical(dC , diagN2U(as(dgC, "triangularMatrix"))) }) setClass("posDef", contains = "dspMatrix") N <- as(crossprod(M) + Diagonal(4), "packedMatrix") (N <- new("posDef", N)) stopifnot(is(N[1:2, 1:2], "symmetricMatrix")) #### Automatically display the class inheritance structure #### possibly augmented with methods allCl <- getClasses("package:Matrix") cat("actual and virtual classes:\n") tt <- table( isVirt <- sapply(allCl, isVirtualClass) ) names(tt) <- c('"actual"', "virtual") tt ## The "actual" Matrix classes: aCl <- allCl[!isVirt] (aMcl <- aCl[grep("Matrix$", aCl)]) # length 48 aMc2 <- aCl[sapply(aCl, extends, class2 = "Matrix")] stopifnot(all( aMcl %in% aMc2 )) aMc2[!(aMc2 %in% aMcl)] ## only 4 : p?Cholesky & p?BunchKaufman ## Really nice would be to construct an inheritance graph and display ## it. Following things are computational variations on the theme.. ## We use a version of canCoerce() that works with two *classes* instead of ## canCoerce <- function (object, Class) classCanCoerce <- function (class1, class2) { extends(class1, class2) || !is.null(selectMethod("coerce", optional = TRUE, signature = c(from = class1, to = class2), useInherited = c(from = TRUE, to = FALSE))) } .dq <- function(ch) paste0('"', ch, '"') .subclasses <- function(cnam) { cd <- getClass(cnam) unique(c(cd@className, unlist(lapply(names(cd@subclasses), .subclasses)))) } for(n in allCl) { if(isVirtualClass(n)) cat("Virtual class", .dq(n),"\n") else { cat("\"Actual\" class", .dq(n),":\n") x <- new(n) if(doExtras) for(m in allCl) if(classCanCoerce(n,m)) { ext <- extends(n, m) if(ext) { cat(sprintf(" extends %20s %20s \n", "", .dq(m))) } else { cat(sprintf(" can coerce: %20s -> %20s: ", .dq(n), .dq(m))) tt <- try(as(x, m), silent = TRUE) if(inherits(tt, "try-error")) { cat("\t *ERROR* !!\n") } else { cat("as() ok; validObject: ") vo <- validObject(tt, test = TRUE) cat(if(isTRUE(vo)) "ok" else paste("OOOOOOPS:", vo), "\n") } } } cat("---\n") } } cat('Time elapsed: ', proc.time(),'\n') # for the above "part I" if(doExtras && !interactive()) { # don't want to see on source() cat("All classes in the 'Matrix' package:\n") for(cln in allCl) { cat("\n-----\n\nClass", dQuote(cln),":\n ", paste(rep("~",nchar(cln)),collapse=''),"\n") ## A smarter version would use getClass() instead of showClass(), ## build the "graph" and only then display. ## showClass(cln) } cat("\n \n") ## One could extend the `display' by using (something smarter than) ## are the "coerce" methods showing more than the 'Extends' output above? cat("All (S4) methods in the 'Matrix' package:\n") showMethods(where="package:Matrix") } # end{non-interactive} ## 1-indexing instead of 0-indexing for direct "dgT" should give error: ii <- as.integer(c(1,2,2)) jj <- as.integer(c(1,1,3)) assertError(new("dgTMatrix", i=ii, j=jj, x= 10*(1:3), Dim=2:3)) assertError(new("dgTMatrix", i=ii, j=jj - 1:1, x= 10*(1:3), Dim=2:3)) assertError(new("dgTMatrix", i=ii - 1:1, j=jj, x= 10*(1:3), Dim=2:3)) (mm <- new("dgTMatrix", i=ii - 1:1, j=jj - 1:1, x= 10*(1:3), Dim=2:3)) validObject(mm) ### Sparse Logical: m <- Matrix(c(0,0,2:0), 3,5) mT <- as(mC <- as(m, "CsparseMatrix"), "TsparseMatrix") stopifnot(identical(as(mT,"CsparseMatrix"), mC)) (mC. <- as(mT[1:2, 2:3], "CsparseMatrix")) (mlC <- as(mC. , "lMatrix")) as(mlC, "triangularMatrix") if(!doExtras && !interactive()) q("no") ## (saving testing time) ### Test all classes: validObject(new( * )) should be fulfilled ----------- ## need stoplist for now: Rcl.struc <- c("gR", "sR", "tR") (dR.classes <- paste0(paste0("d", Rcl.struc[Rcl.struc != "gR"]), "Matrix")) (.R.classes <- paste0(sort(outer(c("l", "n"), Rcl.struc, paste0)), "Matrix")) # have only stub implementation Mat.MatFact <- c("Cholesky", "pCholesky", "BunchKaufman", "pBunchKaufman")##, "LDL" ##FIXME maybe move to ../../MatrixModels/tests/ : ## (modmat.classes <- .subclasses("modelMatrix")) no.t.etc <- c(.R.classes, dR.classes, Mat.MatFact)#, modmat.classes) no.t.classes <- c(no.t.etc) # no t() available no.norm.classes <- no.t.classes not.Ops <- NULL # "Ops", e.g. "+" fails not.coerce1 <- no.t.etc # not coercable from "dgeMatrix" not.coerce2 <- no.t.etc # not coercable from "matrix" tstMatrixClass <- function(cl, mM = Matrix(c(2,1,1,2) + 0, 2,2, dimnames=rep( list(c("A","B")), 2)), # dimnames: *symmetric* mm = as(mM, "matrix"), recursive = TRUE, offset = 0) { ## Purpose: Test 'Matrix' class {and do this for all of them} ## ---------------------------------------------------------------------- ## Arguments: cl: class object of a class that extends "Matrix" ## mM: a "Matrix"-matrix which will be coerced to class 'cl' ## mm: a S3-matrix which will be coerced to class 'cl' ## ---------------------------------------------------------------------- ## Author: Martin Maechler ## from pkg sfsmisc : bl.string <- function(no) sprintf("%*s", no, "") ## Compute a few things only once : mM <- as(as(as(mM, "unpackedMatrix"), "generalMatrix"), "dMatrix") # dge trm <- mm; trm[lower.tri(mm)] <- 0 ## not yet used: ## summList <- lapply(getGroupMembers("Summary"), get, ## envir = asNamespace("Matrix")) if(recursive) cList <- character(0) extraValid <- function(m, cl = class(m)) { sN <- slotNames(cl) sN <- sN[sN != "factors"] for(nm in sN) if(!is.null(a <- attributes(slot(m, nm)))) stop(sprintf("slot '%s' with %d attributes, named: ", nm, length(a)), paste(names(a), collapse=", ")) invisible(TRUE) } ## This is the recursive function dotestMat <- function(cl, offset) { cat. <- function(...) cat(bl.string(offset), ...) clNam <- cl@subClass deprecated <- grepl("^[dln](ge|tr|sy|tp|sp|[gts][CRT])Matrix$", clNam) cat("\n==>") cat.(clNam) ##--------- clD <- getClassDef(clNam) if(isVirtualClass(clD)) { cat(" - is virtual\n") if(recursive) { cat.("----- begin{class :", clNam, "}----new subclasses----\n") for(ccl in clD@subclasses) { cclN <- ccl@subClass if(cclN %in% cList) cat.(cclN,": see above\n") else { cList <<- c(cList, cclN) dotestMat(ccl, offset = offset + 3) } } cat.("----- end{class :", clNam, "}---------------------\n") } } else { ## --- actual class --- genC <- extends(clD, "generalMatrix") symC <- extends(clD, "symmetricMatrix") triC <- extends(clD, "triangularMatrix") diaC <- extends(clD, "diagonalMatrix") indC <- extends(clD, "indMatrix") if(!(genC || symC || triC || diaC || indC)) stop("does not extend one of 'general', 'symmetric', 'triangular', 'diagonal', 'ind'") sparseC <- extends(clD, "sparseMatrix") denseC <- extends(clD, "denseMatrix") if(!(sparseC || denseC)) stop("does not extend either 'sparse' or 'dense'") cat("; new(*): ") m <- new(clNam) ; cat("ok; ") m0 <- matrix(,0,0) if(canCoerce(m0, clNam)) { cat("; canCoerce(matrix(,0,0), *) => as(m0, <.>): ") m0. <- if(deprecated) eval(Matrix:::.as.via.virtual( "matrix", clNam, quote(m0))) else as(m0, clNam) if(.hasSlot(m, "diag") && .hasSlot(m0., "diag") && identical(m@diag, "N") && identical(m0.@diag, "U")) ## tolerate as(0-by-0, .) formally having unit diagonal m0.@diag <- "N" stopifnot(Qidentical(m, m0.)); cat("ok; ") } is_p <- extends(clD, "indMatrix") is_cor <- extends(clD, "corMatrix") || extends(clD, "copMatrix") ## ^^^ has diagonal divided out if(canCoerce(mm, clNam)) { ## replace 'm' by `non-empty' version cat("canCoerce(mm, *) ") m0 <- { if(triC) trm else if(is_p) mm == 1 # logical *and* "true" permutation else mm } if(extends(clD, "lMatrix") || extends(clD, "nMatrix")) storage.mode(m0) <- "logical" else if(extends(clD, "zMatrix")) storage.mode(m0) <- "complex" validObject(m) ## validity of trivial 'm' before replacing m <- if(deprecated) eval(Matrix:::.as.via.virtual( "matrix", clNam, quote(m0))) else as(m0, clNam) if(is_cor) m0 <- cov2cor(m0) } else { m0 <- vector(Matrix:::.type.kind[Matrix:::.M.kind(m)]) dim(m0) <- c(0L,0L) } ## m0 is the 'matrix' version of our 'Matrix' m m. <- m0 ##m. <- if(is_p) as.integer(m0) else m0 EQ <- if(is_cor) all.equal else identical stopifnot(EQ(m0[FALSE], m[FALSE]) , EQ(m.[TRUE], m[TRUE]) , if(length(m) >= 2) EQ(m.[2:1], m[2:1]) else TRUE) if(all(dim(m) > 0)) { ## matrix(0,0,0)[FALSE,] is invalid too m00 <- m[FALSE,FALSE] m.. <- m[TRUE , TRUE] stopifnot(dim(m00) == c(0L,0L), dim(m..) == dim(m)) ## not yet , class(m00) == clNam , identical(m.. , m) } cat("valid: ", validObject(m), extraValid(m, clNam),"\n") ## This can only work as long as 'm' has no NAs : ## not yet -- have version in not.Ops below ## once we have is.na(): ## stopifnot(all(m == m | is.na(m))) ## check all() and "==" [Compare] ## if(any(m != m && !is.na(m))) show(m) ## coerce to 'matrix' m.m <- as(m, "matrix") ##=========## checkMatrix(m, m.m, ##=========## do.t= !(clNam %in% no.t.classes), doNorm= !(clNam %in% no.norm.classes), doOps = all(clNam != not.Ops), doCoerce = all(clNam != not.coerce1), catFUN = cat.) ### FIXME: organize differently : ### 1) produce 'mM' and 'mm' for the other cases, ### 2) use identical code for all cases if(is(m, "dMatrix") && (is(m, "generalMatrix") || is(m, "symmetricMatrix"))) { if(any(clNam == not.coerce1)) cat.("not coercable_1\n") else if(canCoerce(mM, clNam)) { m2 <- if(deprecated) eval(Matrix:::.as.via.virtual( class(mM), clNam, quote(mM))) else as(mM, clNam) cat("valid:", validObject(m2), "\n") if(!is_cor) ## as.vector() stopifnot(as.vector(m2) == as.vector(mM)) cat.("[cr]bind2():"); mm2 <- cbind2(m2,m2) stopifnot(dim(rbind2(m2,m2)) == 2:1 * dim(mM)); cat(" ok") if(genC && class(mm2) == clNam) ## non-square matrix when "allowed" m2 <- mm2 dd <- diag(m2) cat("; `diag<-` ") diag(m2) <- 10*dd stopifnot(is_cor || identical(dd, diag(mM)), identical(10*dd, diag(m2))); cat("ok ") } ## if(all(clNam != not.coerce2)) { if(canCoerce("matrix", clNam)) { cat.("as(matrix, ): ") m3 <- if(deprecated) eval(Matrix:::.as.via.virtual( "matrix", clNam, quote(mm))) else as(mm, clNam) cat("valid:", validObject(m3), "\n") } else cat.(" not coerceable from \"matrix\"\n") ## } } ## else { ... no happens in tstMatrix() above .. } ## if(is(m, "denseMatrix")) { ## ## ......... ## cat.("as dsparse* ") ## msp <- as(m, "dsparseMatrix") ## cat.("; valid coercion: ", validObject(msp), "\n") ## } else if(is(m, "sparseMatrix")) { ## } else cat.("-- not dense nor sparse -- should not happen(!?)\n") if(is(m, "dsparseMatrix")) { if(any(clNam == not.coerce1)) cat.("not coercable_1\n") else { ## make sure we can coerce to dgT* -- needed, e.g. for "image" cat.("as dgT* ") mgT <- eval(Matrix:::.as.via.virtual( class(m), "dgTMatrix", quote(m))) cat(sprintf("; valid dgT* coercion: %s\n", validObject(mgT))) } } } } # end{dotestMat} for(scl in getClass(cl)@subclasses) dotestMat(scl, offset + 1) } ## in case we want to make progress: ## codetools::checkUsage(tstMatrixClass, all=TRUE) tstMatrixClass("Matrix") if(FALSE)## or just a sub class tstMatrixClass("triangularMatrix") cat('Time elapsed: ', proc.time(),'\n') # for ``statistical reasons'' if(!interactive()) warnings() Matrix/tests/dtpMatrix.R0000644000175100001440000000427314444520706015011 0ustar hornikusers### triangular packed ## for R_DEFAULT_PACKAGES=NULL : library(stats) library(utils) library(Matrix) source(system.file("test-tools.R", package = "Matrix"))# identical3() etc cp6 <- as(Cholesky(H6 <- Hilbert(6), perm = FALSE), "dtrMatrix") (tp6 <- as(cp6, "packedMatrix")) round(tp6, 3)## round() is "Math2" group method 1/tp6 ## "Arith" group : gives 'dgeMatrix' str(tp6) ## arithmetic with a mix of dimnames / no dimnames tp <- tp6; dimnames(tp) <- list(LETTERS[1:6], letters[11:16]) ## as.matrix() --> "logical" matrix stopifnot(as.matrix(tp - tp6 == tp6 - tp), as.matrix(0 == tp - tp6), identical(as(tp6,"CsparseMatrix"), as(cp6,"CsparseMatrix"))) stopifnot(validObject(tp6), all.equal(tp6 %*% diag(6), as(tp6, "generalMatrix")), validObject(tp6. <- diag(6) %*% tp6), identical(t(tt6 <- t(tp6)), tp6), tp6@uplo == "U" && tt6@uplo == "L") all.equal(as(tp6.,"matrix"), as(tp6, "matrix"), tolerance= 1e-15) dH6 <- determinant(H6) D. <- determinant(tp6) rc <- rcond(tp6) stopifnot(all.equal(dH6$modulus, determinant(as.matrix(H6))$modulus), is.all.equal3(c(D.$modulus), c(dH6$modulus) / 2, -19.883103353), all.equal(rc, 1.791511257e-4), all.equal(norm(tp6, "I") , 2.45), all.equal(norm(tp6, "1") , 1), all.equal(norm(tp6, "F") , 1.37047826623) ) object.size(tp6) object.size(as(tp6, "unpackedMatrix")) object.size(as(tp6, "matrix")) D6 <- as(diag(6), "generalMatrix") ge6 <- as(tp6, "generalMatrix") stopifnot(all.equal(D6 %*% tp6, ge6), all.equal(tp6 %*% D6, ge6)) ## larger case RNGversion("3.6.0")# future proof set.seed(123) rl <- new("dtpMatrix", uplo="L", diag="N", Dim = c(1000L, 1000L), x = rnorm(500*1001)) validObject(rl) str(rl) sapply(c("I", "1", "F"), function(type) norm(rl, type=type)) rcond(rl)# 0 ! stopifnot(all.equal(as(rl %*% diag(1000),"matrix"), as(rl, "matrix"))) object.size(rl) ## 4 MB object.size(as(rl, "unpackedMatrix"))# 8 MB object.size(as(rl, "matrix"))# ditto print(drl <- determinant(rl), digits = 12) stopifnot(all.equal(c(drl$modulus), -638.257312422)) cat('Time elapsed: ', proc.time(),'\n') # for ``statistical reasons'' Matrix/tests/dpo-test.R0000644000175100001440000001440714467053122014572 0ustar hornikusers### Testing positive definite matrices ## for R_DEFAULT_PACKAGES=NULL : library(stats) library(utils) library(Matrix) source(system.file("test-tools.R", package = "Matrix"))# identical3() etc cat("doExtras:",doExtras,"\n") h9 <- Hilbert(9) stopifnot(c(0,0) == dim(Hilbert(0)), c(9,9) == dim(h9), identical(h9@factors, list())) str(h9)# no 'factors' 32b: -96.73694669 2.08e-8 assert.EQ.(c(determinant(h9)$modulus), -96.7369487, tol = 8e-8) ## 64b: -96.73695078 2.15e-8 then 6.469e-8 ## determinant() now working via chol(): ==> h9 now has factorization stopifnot(names(h9@factors) == "Cholesky", identical(ch9 <- Cholesky(h9, perm = FALSE), h9@factors$Cholesky)) str(f9 <- as(ch9, "dtrMatrix")) round(f9, 3) ## round() preserves 'triangular' ! stopifnot(all.equal(rcond(h9), 9.0938e-13), all.equal(rcond(f9), 9.1272e-7, tolerance = 1e-6))# more precision fails options(digits=4) (cf9 <- crossprod(f9))# looks the same as h9 : assert.EQ.mat(h9, as(cf9,"matrix"), tol=1e-15) h9. <- round(h9, 2) # dpo->dsy h9p <- pack(h9) ch9p <- Cholesky(h9p, perm = FALSE) stopifnot(identical(ch9p, h9p@factors$pCholesky), identical(names(h9p@factors), c("Cholesky", "pCholesky"))) h4 <- h9.[1:4, 1:4] # this and the next h9.[1,1] <- 10 # had failed in 0.995-14 h9p[1,1] <- 10 stopifnotValid(h9., "symmetricMatrix") stopifnotValid(h9p, "symmetricMatrix") stopifnotValid(h4, "symmetricMatrix") h9p[1,2] <- 99 stopifnot(class(h9p) == "dgeMatrix", h9p[1,1:2] == c(10,99)) str(h9p <- as(h9, "dppMatrix"))# {again} h6 <- h9[1:6,1:6] stopifnot(all(h6 == Hilbert(6)), length(h6@factors) == 0) stopifnotValid(th9p <- t(h9p), "dppMatrix") stopifnotValid(h9p@factors$Cholesky,"Cholesky") H6 <- as(h6, "packedMatrix") pp6 <- as(H6, "dppMatrix") po6 <- as(pp6, "dpoMatrix") hs <- as(h9p, "dspMatrix") stopifnot(names(H6@factors) == "pCholesky", names(pp6@factors) == "pCholesky", names(hs@factors) == "Cholesky") # for now chol(hs) # and that is cached in 'hs' too : stopifnot(names(hs@factors) %in% c("Cholesky","pCholesky"), all.equal(h9, crossprod(as(hs@factors$pCholesky, "dtpMatrix")), tolerance = 1e-13), all.equal(h9, crossprod(as(hs@factors$ Cholesky, "dtrMatrix")), tolerance = 1e-13)) hs@x <- 1/h9p@x # is not pos.def. anymore validObject(hs) # "but" this does not check stopifnot(diag(hs) == seq(1, by = 2, length.out = 9)) s9 <- solve(h9p, seq(nrow(h9p))) signif(t(s9)/10000, 4)# only rounded numbers are platform-independent (I9 <- h9p %*% s9) m9 <- as.matrix(1:9) stopifnot(all.equal(m9, as(I9, "matrix"), tolerance = 2e-9)) ### Testing nearPD() --- this is partly in ../man/nearPD.Rd : pr <- Matrix(c(1, 0.477, 0.644, 0.478, 0.651, 0.826, 0.477, 1, 0.516, 0.233, 0.682, 0.75, 0.644, 0.516, 1, 0.599, 0.581, 0.742, 0.478, 0.233, 0.599, 1, 0.741, 0.8, 0.651, 0.682, 0.581, 0.741, 1, 0.798, 0.826, 0.75, 0.742, 0.8, 0.798, 1), nrow = 6, ncol = 6) nL <- list(r = nearPD(pr, conv.tol = 1e-7), # default r.1 = nearPD(pr, conv.tol = 1e-7, corr = TRUE), rs = nearPD(pr, conv.tol = 1e-7, doDykstra=FALSE), rs1 = nearPD(pr, conv.tol = 1e-7, doDykstra=FALSE, corr = TRUE), rH = nearPD(pr, conv.tol = 1e-15), rH.1= nearPD(pr, conv.tol = 1e-15, corr = TRUE)) sapply(nL, `[`, c("iterations", "normF")) allnorms <- function(d) vapply(c("1","I","F","M","2"), norm, x = d, double(1)) ## "F" and "M" distances are larger for the (corr=TRUE) constrained: 100 * sapply(nL, function(rr) allnorms((pr - rr $ mat))) ## But indeed, the 'corr = TRUE' constraint yield a better solution, ## if you need the constraint : cov2cor() does not just fix it up : 100 * (nn <- sapply(nL, function(rr) allnorms((pr - cov2cor(rr $ mat))))) stopifnot( all.equal(nn["1",], c(r =0.0999444286984696, r.1= 0.0880468666522317, rs=0.0999444286984702, rs1= 0.0874614179943388, rH=0.0999444286984696, rH.1=0.0880468927726625), tolerance=1e-9)) nr <- nL $rH.1 $mat stopifnot( all.equal(nr[lower.tri(nr)], c(0.4877861230299, 0.6429309061748, 0.4904554299278, 0.6447150779852, 0.8082100656035, 0.514511537243, 0.2503412693503, 0.673249718642, 0.7252316891977, 0.5972811755863, 0.5818673040157, 0.7444549621769, 0.7308954865819, 0.7713984381710, 0.8124321235679), tolerance = 1e-9)) showProc.time() suppressWarnings(RNGversion("3.5.0")); set.seed(27) m9 <- h9 + rnorm(9^2)/1000 ; m9 <- (m9 + t(m9))/2 nm9 <- nearPD(m9) showProc.time() nRep <- if(doExtras) 50 else 4 CPU <- 0 for(M in c(5, 12)) for(i in 1:nRep) { m <- matrix(round(rnorm(M^2),2), M, M) m <- m + t(m) diag(m) <- pmax(0, diag(m)) + 1 m <- cov2cor(m) CPU <- CPU + system.time(n.m <- nearPD(m, base.matrix=TRUE))[1] X <- n.m$mat stopifnot(all.equal(X, (X + t(X))/2, tolerance = 8*.Machine$double.eps), all.equal(eigen(n.m$mat, only.values=TRUE)$values, n.m$eigenvalues, tolerance = 4e-8)) } cat('Time elapsed for ',nRep, 'nearPD(): ', CPU,'\n') showProc.time() ## cov2cor() m <- diag(6:1) %*% as(pr,"matrix") %*% diag(6:1) # so we can "vector-index" m[upper.tri(m)] <- 0 ltm <- which(lower.tri(m)) ne <- length(ltm) set.seed(17) m[ltm[sample(ne, 3/4*ne)]] <- 0 m <- (m + t(m))/2 # now is a covariance matrix with many 0 entries (spr <- Matrix(m)) cspr <- cov2cor(spr) ev <- eigen(cspr, only.values = TRUE)$values stopifnot(is(spr, "dsCMatrix"), is(cspr,"dsCMatrix"), all.equal(ev, c(1.5901626099, 1.1902658504, 1, 1, 0.80973414959, 0.40983739006), tolerance=1e-10)) x <- c(2,1,1,2) mM <- Matrix(x, 2,2, dimnames=rep( list(c("A","B")), 2))# dsy mM stopifnot(length(mM@factors)== 0) (po <- as(mM, "dpoMatrix")) # still has dimnames mm <- as(mM, "matrix") msy <- as(mm, "symmetricMatrix") stopifnot(Qidentical(mM, msy), length(mM @factors)== 1, length(msy@factors)== 0) c1 <- as(mm, "corMatrix") c2 <- as(mM, "corMatrix") c3 <- as(po, "corMatrix") (co.x <- matrix(x/2, 2,2)) checkMatrix(c1) assert.EQ.mat(c1, co.x) assert.EQ.mat(c2, co.x) # failed in Matrix 0.999375-9, because of ## the wrong automatic "dsyMatrix" -> "corMatrix" coerce method stopifnot(identical(dimnames(c1), dimnames(mM)), all.equal(c1, c3, tolerance =1e-15)) showProc.time() Matrix/tests/Simple.R0000644000175100001440000017164614535165176014306 0ustar hornikusers#### Currently a collection of simple tests ## (since 'Matrix' takes long to load, rather have fewer source files!) ## for R_DEFAULT_PACKAGES=NULL : library(methods) library(stats) library(utils) ##-------- *BEFORE* attaching Matrix: -------------------------------- str(Matrix::Matrix)# -> load the namespace T <- new("ngTMatrix", i=0L, j=2L, Dim = c(2L,6L)) T as(T, "CsparseMatrix") ## gave Error in asMethod(object) : could not find function ".M.classEnv" ## from 0.999375-23 to *-25 ## another even shorter version of this: n <- new("dgCMatrix") n ## this: m <- Matrix::Matrix(cbind(1,0,diag(x=2:4))) m mt <- m + table(gl(3,5), gl(5,3))# failed in Matrix <= 1.2.9 mt stopifnot(is(mt, "sparseMatrix")) ##-------------------------------------------------------------------- library(Matrix) source(system.file("test-tools.R", package = "Matrix"))# identical3() etc if(interactive()) { options(error = recover, Matrix.verbose = TRUE, warn = 1) } else options( Matrix.verbose = TRUE, warn = 1) # ^^^^^^ to show Matrix.msg()s (Mv <- Matrix.Version()) stopifnot(identical(packageVersion("Matrix"), Mv[["package"]])) ### Matrix() ''smartness'' (d40 <- Matrix( diag(4))) (z4 <- Matrix(0*diag(4))) (o4 <- Matrix(1+diag(4))) (tr <- Matrix(cbind(1,0:1))) (M4 <- Matrix(m4 <- cbind(0,rbind(6*diag(3),0)))) dM4 <- Matrix(M4, sparse = FALSE) d4. <- diag(4); dimnames(d4.) <- dns <- rep(list(LETTERS[1:4]), 2) d4a <- diag(4); dimnames(d4a) <- dna <- list(LETTERS[1:4], letters[1:4])# "a"symmetric m1a <- matrix(0, dimnames=list("A","b"))# "a"symmetric d4di<- as(d4., "diagonalMatrix") d4da<- as(d4a, "diagonalMatrix") d4d <- as(d4., "denseMatrix") d4aS <- Matrix(d4a, sparse=TRUE, doDiag=FALSE) d1aS <- Matrix(m1a, sparse=TRUE, doDiag=FALSE) stopifnot(exprs = { identical(d4di@x, numeric()) # was "named" unnecessarily identical(dimnames(d4 <- Matrix(d4.)), dns) identical4(d40, Matrix(diag(4)), unname(d4), unname(d4da)) identical3(d4, as(d4., "Matrix"), as(d4., "diagonalMatrix")) is(d4aS, "dtCMatrix") # not "dsC*", as asymmetric dimnames is(d4d, "denseMatrix") identical(dimnames(d4T <- as(d4., "TsparseMatrix")), dns) # failed till 2019-09-xx ## identical(d4T, as(d4., "dsTMatrix")) # deprecated }) showProc.time() class(mN <- Matrix(NA, 3,4)) # NA *is* logical validObject(Matrix(NA)) bd4 <- bdiag(M4,dM4,M4) stopifnotValid(o4, "dsyMatrix") stopifnotValid(M4, "dtCMatrix") stopifnot(validObject(dM4), validObject(mN), identical(bdiag(M4), bdiag(dM4)), identical(bd4@p, c(0L,0:3,3:6,6:9)), identical(bd4@i, c(0:2, 4:6, 8:10)), bd4@x == 6 ) assert.EQ.mat(dM4, m4) assert.EQ.mat(M4^M4, m4^m4) assert.EQ.mat(mN, matrix(NA, 3,4)) assert.EQ.mat(bdiag(diag(4)), diag(4)) sL <- Matrix(, 3,4, sparse=TRUE)# -> "lgC" trS <- Matrix(tr, sparse=TRUE)# failed in 0.9975-11 stopifnotValid(d4, "diagonalMatrix"); stopifnotValid(z4, "diagonalMatrix") stopifnotValid(tr, "triangularMatrix"); stopifnotValid(trS, "triangularMatrix") stopifnot(all(is.na(sL@x)), ## not yet: all(is.na(sL)), !any(sL, na.rm=TRUE), all(!sL, na.rm=TRUE), validObject(Matrix(c(NA,0), 4, 3, byrow = TRUE)), validObject(Matrix(c(NA,0), 4, 4))) stopifnotValid(Matrix(c(NA,0,0,0), 4, 4), "sparseMatrix") I <- i1 <- I1 <- Diagonal(1) ## TODO? stopifnot(identical(I, Matrix(1, sparse=TRUE))) # doDiag=TRUE default I1[1,1] <- i1[1, ] <- I [ ,1] <- NA stopifnot(identical3(I,i1,I1)) image(d4) # gave infinite recursion ## Steve Walker, Mar 12, 2014: n <- 7 (M <- triu(Matrix(seq_len(n^2), n, sparse=TRUE))) im <- image(M) # was not an n-by-n image plot stopifnot(n == diff(sort(im$y.limits))) ## ylimits were too small (by 1 on each side) ## Image of *empty* sparseMatrix (has failed in spite of claim in r3282 | 2018-08-20) (Z <- Matrix(0, 11, 22)) # empty "dgCMatrix" Z0 <- Z; Z0[1,1] <- 1; Z0@x <- 0 ## is also all 0, but not "empty" stopifnot(all(Z == Z0)) image(Z) ## gave Error in seq.default(zrng[1], zrng[2], length.out = cuts + 2) : 'from' must be a finite number image(Z, useAbs=FALSE) # gave *different* Error in seq.int... : 'length.out' must be ... image(Z0,useAbs=FALSE) # (ditto) image(Z0) # had worked previously already showProc.time() assertError( Matrix(factor(letters)) ) n.lsec <- length(.leap.seconds)# 27 (2017-07) mlp <- matrix(.leap.seconds)## 27 x 1 numeric matrix Mlp <- Matrix(.leap.seconds) stopifnot(identical(dim(Mlp), c(n.lsec, 1L))) assert.EQ.mat(Mlp, mlp) lt.leap.seconds <- .LS <- as.POSIXlt(.leap.seconds, tz = "GMT") # GMT => sparse HMS .LS <- unclass(.LS); .LS <- .LS[setdiff(names(.LS), "zone")] # "zone" is character (not there for GMT/UTC in R <= 4.2.x) (matLS <- data.matrix(data.frame(.LS))) stopifnot(inherits(MLp <- as(matLS, "Matrix"), "sparseMatrix"), is.EQ.mat(MLp, matLS)) printSpMatrix(MLp, col.names = TRUE) # nice sparse dgC* w/ col.names (mLp <- matrix(lt.leap.seconds))## prints fine as 27 x 1 matrix of dates (internally is list+dim) ## E <- rep(c(TRUE,NA,TRUE), length.out=8) F <- new("nsparseVector", length = 8L, i = c(2L, 5L, 8L)) e <- as(E, "sparseVector"); f <- as(F,"lsparseVector") Fv <- as.vector(F, "any") # failed in Matrix <= 1.2.0, and base::as.vector(.) failed too: stopifnot(E | as.vector(F), identical(E | F, F | E), all(e | f), all(E | F), # <- failed Ops.spv.spv identical(Fv, base::as.vector(F)), is.logical(Fv), which(Fv) == c(2,5,8)) F[-8:-1] # was partly "illegal" (length = 0 is ok; nnz '3' is not) F.ineg <- lapply(1:8, function(k) F[-8:-k]) F.pos <- lapply(1:8, function(k) F[seq_len(k-1)]) F.vec <- lapply(1:8, function(k) Fv[seq_len(k-1)]) str(F.vec, vec.len=8) (nT <- vapply(F.vec, sum, 1L)) # == 0 0 1 1 1 2 2 2 str(whichT <- lapply(F.vec, which)) i.lengths <- function(L) vapply(L, function(.) length(.@i), 1L) stopifnot(exprs = { identical(lengths(F.vec), 0:7) identical(lengths(F.ineg), 0:7) identical(lengths(F.pos), 0:7) identical(i.lengths(F.pos), nT) identical(i.lengths(F.ineg), nT) # failed before 2018-03-19 identical(lapply(F.pos, slot, "i"), whichT) identical(lapply(F.ineg, slot, "i"), whichT) # failed before 2018-03-19 }) ## Here, sparseVector '[' is really wrong: SV <- new("nsparseVector", length = 30L, i = c(1L, 8L, 9L, 12L, 13L, 18L, 21L, 22L)) NI <- -c(1:5, 7:10, 12:16, 18:27, 29,30) sv <- SV[1:14]; ni <- -(1:14)[-c(6,11)] # smaller example selectMethod("[", c("nsparseVector","index","missing","missing"))# the culprit if(FALSE) trace("[", browser, signature=c("nsparseVector","index","missing","missing")) stopifnot( SV[NI] == as.vector(SV)[NI] ## badly failed before 2018-03-19 , sv[ni] == as.vector(sv)[ni] ## ditto ) if(FALSE) untrace("[", signature=c("nsparseVector","index","missing","missing")) dT <- new("dgTMatrix", i = c(1:2,1:2), j=rep(1:2, each=2), Dim = c(4L, 4L), x = c(1, 1, NA, 2)) dt <- new("dtTMatrix", i = 0:3, j = 0:3, Dim = c(4L, 4L), x = c(1,0,0,0), uplo = "U", diag = "N") c1 <- as(dT, "CsparseMatrix") c2 <- as(dt, "CsparseMatrix") isValid(lc <- c1 > c2,"lgCMatrix") isValid(lt <- dT > dt,"lgCMatrix") stopifnot(identical(lc,lt)) ## Versions of Diagonal() dD <- Diagonal(x = 5:1) sD <- .symDiagonal(5, 5:1) tD <- .trDiagonal (5, 5:1) # x= had failed for both stopifnot(all(sD == dD) , all(tD == dD) , identical(sD, .symDiagonal(x = 5:1)) , identical(tD, .sparseDiagonal(x=5:1)) , identical(tD, .trDiagonal (x = 5:1)))# 'n' now has default M <- Diagonal(4); M[1,2] <- 2 ; M cM <- crossprod(M) # >> as_cholmod_l_triplet(): could not reallocate for internal diagU2N() stopifnot(identical(cM, tcrossprod(t(M)))) S.na <- spMatrix(3, 4, c(1,2,3), c(2,3,3), c(NA,1,0)) (S.na <- S.na - 2 * S.na) (L <- S.na != 0) (Ln0 <- S.na != rep(0, prod(dim(L)))) .Lm0 <- S.na != Matrix(0, 3, 4) stopifnot(Q.eq(L, Ln0), identical(Ln0, .Lm0)); rm(Ln0, .Lm0) showProc.time() ### Unit-diagonal and unitriangular {methods need diagU2N() or similar} I <- Diagonal(3) (T <- as(I,"TsparseMatrix")) # unitriangular (C <- as(I,"CsparseMatrix")) # (ditto) lT <- as(T,"lMatrix") lC <- as(C,"lMatrix") stopifnot( identical((n0 <- I != 0), Diagonal(3, TRUE)), I@diag == "U", identical(n0, I & TRUE), identical(n0, I | FALSE), identical(n0, TRUE & I), identical(n0, FALSE | I), all(n0 == !(I == 0)), all(I == n0), identical(n0 == I, I == n0) , identical4(lT, as(Diagonal(3, x=TRUE),"TsparseMatrix"), T & TRUE, TRUE & T), identical4(lC, as(Diagonal(3, x=TRUE),"CsparseMatrix"), C & TRUE, TRUE & C), identical3(lT, T | FALSE, FALSE | T), identical3(lC, C | FALSE, FALSE | C), TRUE) I[,1] <- NA; I[2,2] <- NA ; I[3,] <- NaN stopifnotValid(I, "sparseMatrix") I # gave error in printSpMatrix() - because of R bug in format.info() L <- spMatrix(9, 30, i = rep(1:9, 3), 1:27, (1:27) %% 4 != 1) M <- drop0(crossprod(L)) diag(M) <- diag(M) + 5 # to make it pos.def. M. <- M[1:12,1:12] # small ex N3 <- as(Matrix(upper.tri(diag(3))), "nMatrix") stopifnotValid(bdN <- bdiag(N3, N3),"nsparseMatrix") stopifnot(identical(L, L == TRUE), ## used to give infinite recursion all(drop0((0 - L) != 0) == drop0(L))) L[sample(length(L), 10)] <- NA ll <- as(L,"logical") stopifnot(all.equal(mean(L, na.rm=TRUE), mean(ll, na.rm=TRUE), tolerance=1e-14), all.equal(mean(L, na.rm=TRUE, trim=1/4),# <- with a warning mean(ll, na.rm=TRUE, trim=1/4), tolerance=1e-14)) ## Examples where is.na(.) was wrong: validObject(sc <- new("dsCMatrix", i=as.integer(c(0,0:1,1:2,0:1,3)), Dim=c(4L,4L), p = c(0L,1L,3L,5L,8L), x = c(0,NA,NA,0:1,0,NA,1))) validObject(gc <- as(sc, "generalMatrix")) stopifnot(isSymmetric(M), isSymmetric(M.), is(bdiag(M., M.),"symmetricMatrix"), is(bdN, "triangularMatrix"), all(sc == gc | (is.na(sc) & is.na(gc))), all.equal(N3,N3), identical(all.equal(N3, t(N3)), all.equal.raw(1:6, 2:7)), # == "6 element mismatches" all((bdN != t(bdN)) == (bdN + t(bdN))), # != failed to work... !any((0+bdN) > bdN), # o !any(bdN != (0+bdN)), # o length(grep("Length", all.equal(M., (vM <- as.vector(M.))))) > 0, identical(M., (M2 <- Matrix(vM, 12,12))), all.equal(M., M2, tolerance =0) ) Filter(function(.) inherits(get(.), "symmetricMatrix"), ls()) ## [1] "M" "M." "M2" "cM" "d4T" "d4d" "o4" "sD" "sc" cc <- kronecker(cM, Diagonal(x = c(10,1))) dimnames(cc) <- list(NULL, cn <- letters[1:ncol(cc)]) stopifnotValid(cc, "dsCMatrix") (tt <- as(cc, "TsparseMatrix")) # shows *symmetric* dimnames stopifnot(identical3( cc @Dimnames, tt @Dimnames, list(NULL, cn)), ## t() does not reverse 'Dimnames' slot for symmetricMatrix identical3(t(cc)@Dimnames, t(tt)@Dimnames, list(NULL, cn)), identical3(dimnames(cc), dimnames(tt), list(cn, cn))) # now symmetric! stopifnot(identical3(dimnames(cc), dimnames(as(cc, "generalMatrix")), ## should fixup dimnames to *symmetric* dimnames(as(tt, "generalMatrix")))) ## --> .Call(Csparse_symmetric_to_general, from) mat <- as(cc, "matrix") ## --> should fixup dimnames to *symmetric* mat # should print *symmetric* dimnames stopifnot(identical3(dimnames(cc), dimnames(mat), dimnames(as(tt, "matrix")))) selectMethod(coerce, c("dsCMatrix", "denseMatrix")) dmat <- as(cc, "denseMatrix") ## --> gave Error (!!) in Matrix 1.1-5 stopifnot(identical3(tt@Dimnames, dmat@Dimnames, list(NULL, cn))) dmat # should print *symmetric* dimnames (not modifying dmat as it did intermittently) stopifnot(identical(dmat@Dimnames, list(NULL, cn))) ttdm <- as(tt, "denseMatrix") stopifnot(identical(dmat, ttdm), identical(dimnames(cc), dimnames(dmat)), ## coercing back should give original : identical(cc, as(dmat, "sparseMatrix")), identical(asUniqueT(tt), as(ttdm, "TsparseMatrix"))) ## MM: now *if* cc is "truly symmetric", these dimnames should be, too: d5 <- cn[1:5]; dnm5 <- list(d5,d5) stopifnot(identical(dimnames( cc [1:5, 1:5]), dnm5), identical(dimnames(t(cc)[1:5, 1:5]), dnm5)) ## large sparse ones: these now directly "go sparse": str(m0 <- Matrix(0, nrow=100, ncol = 1000)) str(l0 <- Matrix(FALSE, nrow=100, ncol = 200)) stopifnot(all(!l0), identical(FALSE, any(l0))) if(!interactive()) warnings() ## really large {length() is beyond R's limits}: op <- options(warn = 2) # warnings (e.g. integer overflow!) become errors: n <- 50000L stopifnot(n^2 > .Machine$integer.max) ## had integer overflow in index constructions: x <- 1:n D <- Diagonal(n, x=x[n:1]) summary(D)# special method summary(D != 0) stopifnot(identical(x*D, (Dx <- D*x)), identical(D != 0, as(D, "lMatrix")), identical(Dx, local({d <- D; d@x <- d@x * x; d}))) Lrg <- new("dgTMatrix", Dim = c(n,n)) l0 <- as(as(Lrg, "lMatrix"), "CsparseMatrix") # lgC d0 <- as(l0, "dMatrix") showProc.time() if(FALSE) { #_____________________ FIXME: Should use cholmod_l_*() everywhere (?)____ ## problem in Csparse_to_dense : dl0 <- as(l0, "denseMatrix") dd0 <- as(d0, "denseMatrix") ## currently, both give --- Error in asMethod(object) : ## Cholmod error 'problem too large' at file ../Core/cholmod_dense.c, line 105 ##--> And there it is 'Int_max' ==> ../src/CHOLMOD/Include/cholmod_internal.h ## defines 'Int_max' and does that depending of "mode", and ## MM thinks we should use the "DLONG" mode now -- for 64-bit integers! ## ==> Then Int_max := SuiteSparse_long_max := LONG_MAX ## (the latter from ../src/SuiteSparse_config/SuiteSparse_config.h ) ## ==> use cholmod_l_ instead of cholmod_ in *many places* ## ## check they are ok stopifnot(identical(dim(dl0), c(n,n)), identical(dim(dd0), c(n,n)), !any(dl0), all(dd0 == 0)) rm(dl0, dd0)# too large to keep in memory and pass to checkMatrix() } diag(Lrg[2:9,1:8]) <- 1:8 ## ==: Lrg[2:9,1:8] <- `diag<-`(Lrg[2:9,1:8], 1:8) options(warn = 1) # Matrix 1.5-0 (Sep 2022): we now warn when lots of memory is used (memGB <- Sys.memGB("MemFree")) # from test-tools-1.R, only works with /proc/* system.time( # ~10 sec. __vv__ e1 <- if(doExtras && is.finite(memGB) && memGB > 30) { # need around 18 GB try(Lrg == Lrg) ## had Cholmod error 'problem too large' at file ../Core/cholmod_dense.c, line 105 ## (error message almost ok) }) # now works, taking 42.7 sec on ada-20 w/ 504 GB; if(is(e1, "Matrix")) object.size(e1) # 10000001176 bytes system.time( # ~10 sec. __vv__ e2 <- if(doExtras && is.finite(memGB) && memGB > 30) { # need around 18 GB try(!Lrg) # now *works* on 64-bit machines with enough RAM ## and immediately errors if LONG_VECTORs are not available }) ## when it works, see ## Warning in .sparse2dense(x) : sparse->dense coercion: allocating vector of size 9.3 GiB ## user system elapsed ## 6.812 10.744 17.612 str(e2) # error, NULL or "worked" (=> 50000 x 50000 lgeMatrix) ina <- is.na(Lrg)# "all FALSE" stopifnot(if(inherits(e1, "try-error")) grepl("too large", e1) else is.null(e1) || (is(e1, "denseMatrix") && is(e1, "lMatrix")), if(inherits(e2, "try-error")) grep("too large", e2) == 1 else is.null(e2) || length(e2@x) == n^2, !any(ina))# <- gave warning previously stopifnot(suppressWarnings(any(Lrg)))# (double -> logical warning) rm(e1, e2)# too large... ## Matrix bug #6610, did segfault system.time({ # ... sec __vv__ ## FIXME: reproducible example (not using 'MatrixModels' which triggers) "Out of memory" etc }) showProc.time() RNGversion("3.6.0")# future proof if(doExtras && is.finite(memGB) && memGB > 49) withAutoprint({ cat("computing SM .. \n") showSys.time(m <- matrix(0, 3e6, 1024)) ## user system elapsed ## 2.475 10.688 13.196 (faster in past ??) set.seed(1); inot0 <- unique(sort(c(1, length(m), sample(length(m), 20)))) ai0 <- arrayInd(inot0, .dim=dim(m), useNames=FALSE) showSys.time(m[inot0] <- 1:22) ## user system elapsed ## 5.931 11.184 17.162 showSys.time(SM <- as(m, "sparseMatrix")) # ~ 8 sec ## gave 'Error in asMethod(object) : negative length vectors are not allowed' ## now works - via C matrix_to_Csparse() showSys.time(n0.m <- c(m) != 0) # logical (full, base R) matrix, 12 GB ## user system elapsed ## 14.901 10.789 25.776 try( ## _FIXME_ in R: Error ... long vectors not supported yet in0.m <- which(n0.m) ) ## DONE: now very fast! [previously did coerce the whole matrix to dense first !] subS <- SM[inot0] selectMethod("[", c("dgCMatrix","numeric","missing","missing"))# -> .M.vectorSub(x,i) ## Directly via arrayInd(), is *FAST*: subSij <- SM[ai0] stopifnot(subS == 1:22, identical(subS, subSij)) cat(" [Ok]\n") rm(m) str(SM) ## checking SM: TM <- as(SM, "TsparseMatrix") stopifnot(as.matrix(summary(TM)) == cbind(ai0, 1:22)) ## cleanup: rm(SM, TM) }) showProc.time() ## Constructing *packed* dense symmetric (dsp*) | triangular (dtp*) Matrices: if(doExtras && is.finite(memGB) && memGB > 35) withAutoprint({ m <- as.integer(2^16) ## = 65536 showSys.time(x <- rep(as.numeric(1:100), length.out=m*(m+1)/2)) ## user system elapsed ## 6.028 8.964 15.074 gc() object.size(x) # 17'180'131'368 bytes: ~ 17 GB mat <- new("dspMatrix", x = x, Dim = c(m, m)) # failed with ## long vectors not supported yet: ../../src/include/Rinlinedfuns.h:... validObject(mat) mat <- new("dtpMatrix", x = x, Dim = c(m, m)) # failed ....... validObject(mat) ## cleanup rm(mat) }) showProc.time() options(warn = 2)# warnings => errors ## with dimnames: v <- c(a=1, b=2:3) m <- as.matrix(v) (M <- as(v, "denseMatrix") ) stopifnot(identical(dimnames(m), list(c("a", "b1", "b2"), NULL)), inherits(M, "dgeMatrix"), identical(dimnames(M), dimnames(m))) ## dimnames(.) of symmpart() / skewpart() : ns <- c("symmpart", "skewpart", "forceSymmetric") symFUNs <- setNames(lapply(ns, get), ns); rm(ns) chkSS <- function(m) { r <- lapply(symFUNs, function(fn) fn(m)) m0 <- as(m, "matrix") r0 <- lapply(symFUNs, function(fn) fn(m0)) stopifnotValid(fS <- r [["forceSymmetric"]], "symmetricMatrix") stopifnotValid(fS0 <- r0[["forceSymmetric"]], "symmetricMatrix") dnms <- dimnames(m) d.sy <- dimnames(r[["symmpart"]]) id <- if(is.null(dnms[[2]]) && !is.null(dnms[[1]])) 1 else 2 stopifnot(identical(d.sy, dnms[c(id,id)]), identical(d.sy, dimnames(r [["skewpart"]])), if(identical(dnms, list(NULL, NULL))) is.null(dimnames(r0[["skewpart"]])) else identical(d.sy, dimnames(r0[["skewpart"]])), all(m == with(r, symmpart + skewpart)), all(m0 == with(r0, symmpart + skewpart)), identical(dS <- dimnames(fS), dimnames(fS0)), identical(dS[1], dS[2])) } cat(sprintf("chkSS() {valid %s} for a list of matrices:\n", paste(paste0(names(symFUNs), "()"), collapse=", "))) L <- list(M1 = Matrix(1:4, 2,2), M2 = Matrix(c(0, rep(1:0, 3),0:1), 3,3)) L$M3 <- pack(as(forceSymmetric(L$M2), "denseMatrix")) stopifnotValid(L$M3, "dspMatrix") for(m in L) { cat("\n---\nm:\n"); show(m) chkSS(m) dn <- list(row = paste0("r", 1:nrow(m)), col = paste0("var.", 1:ncol(m))) dimnames(m) <- dn ; chkSS(m) colnames(m) <- NULL ; chkSS(m) dimnames(m) <- unname(dn) ; chkSS(m) } m. <- matrix(c(0, 0, 2:0), 3, 5) dimnames(m.) <- list(LETTERS[1:3], letters[1:5]) (m0 <- m <- Matrix(m.)) m@Dimnames[[2]] <- m@Dimnames[[1]] ## not valid anymore: (val <- validObject(m, test=TRUE)); stopifnot(is.character(val)) dm <- as(m0, "denseMatrix"); rm(m) stopifnot(all.equal(rcond(dm), rcond(m.), tolerance = 1e-14), ##^^^^^^^ dm and m. are both dense, interestingly small differences ## show in at least one case of optimized BLAS all.equal(rcond(dm), 0.4899474520656), ## show() had revealed a bug in C: identical(capture.output(show(as(m0, "RsparseMatrix")))[-(1:2)], gsub("0", ".", capture.output(show(m.))[-1]))) m.1 <- m.; dimnames(m.1) <- list(row=NULL, col=NULL) M.1 <- Matrix(m.1, sparse=TRUE) show(M.1)# had bug in .formatSparseSimple() showProc.time() ###-- Sparse Triangular : g5 <- new("dgCMatrix", Dim = c(5L, 5L), x = c(10, 1, 3, 10, 1, 10, 1, 10, 10), i = c(0L,2L,4L, 1L, 3L,2L,4L, 3L, 4L), p = c(0L, 3L, 5L, 7:9)) t5 <- as(g5, "triangularMatrix") # fine stopifnot(class(t5) == "dtCMatrix", identical(t5, tril(g5))) ## This is really a regression test for 'methods::selectMethod()' ## Maybe move to R once 'Matrix' is recommended sm <- selectMethod(coerce, c("dgCMatrix", "triangularMatrix"), verbose=TRUE) stopifnot(identical(sm(g5), t5)) dimnames(t5) <- list(row=paste0("r",1:5), col=paste0("C.",1:5)) s5 <- symmpart(t5) # gave an error showProc.time() (t1 <- new("dtTMatrix", x= c(3,7), i= 0:1, j=3:2, Dim= as.integer(c(4,4)))) ## Diagonal o Sparse I4 <- Diagonal(4) D4 <- Diagonal(4, x=1:4) validObject(t1) validObject(t2 <- t1 + I4) validObject(tt2 <- t(t1) + I4) validObject(t1c <- as(t1, "CsparseMatrix")) validObject(t2c <- as(t2, "CsparseMatrix")) stopifnotValid(2 * I4, "diagonalMatrix") stopifnotValid(D4 * 3, "diagonalMatrix") stopifnotValid(I4 / 5, "diagonalMatrix") stopifnotValid(D4 / 2, "diagonalMatrix") stopifnotValid(t1c + I4,"triangularMatrix") stopifnotValid(t2c + I4,"triangularMatrix") stopifnot(identical(t1, t(t(t1))), identical(t1c, t(t(t1c))), c(class(t2), class(t1c), class(t2c), class(tt2)) == "dtCMatrix", identical(t(tt2), t2)) assert.EQ.mat(t1, as(t1c, "matrix")) D4. <- D4 * (A4 <- Matrix(1:4, 4,4)) D4p <- A4 + D4 Lg1 <- D4 > 0 & D4 > 1 nLg <- !Lg1 nnLg <- !nLg D4m <- D4 * 4:1 assert.EQ.mat(D4., diag(x= (1:4)^2)) assert.EQ.mat(D4p, diag(x= (1:4)) + (1:4)) assert.EQ.mat(D4m, diag(x=c(4,6,6,4))) assert.EQ.mat(Lg1, diag(x= c(FALSE, rep(TRUE,3)))) stopifnot(is(Lg1, "diagonalMatrix"), is(D4m, "diagonalMatrix"), is(D4., "diagonalMatrix"), is(nLg, "generalMatrix"), is(nnLg, "generalMatrix"), identical3(Lg1, Matrix(nnLg, forceCheck = TRUE), as(nnLg, "diagonalMatrix")), all(Lg1 != (!Lg1))) ## tri[lu]() td3 <- triu(diag(3)); stopifnot(is(td3, "triangularMatrix"), td3@uplo == "U") Ld3 <- tril(diag(3)); stopifnot(is(Ld3, "triangularMatrix"), Ld3@uplo == "L") ## the latter did fail till 2014-12-20 D3 <- Diagonal(3) stopifnot(identical3(D3, tril(D3), triu(D3))) ## methods were missing showProc.time() ## as(, ) : str(cls <- names(getClass("Matrix")@subclasses))# all Matrix classes ## Matrix >= 1.4.2 : (basically) only coerce to virtual classes: table(isVirt <- vapply(cls, isVirtualClass, NA)) for(cl in cls[isVirt]) if(canCoerce(I4, cl)) { cat(cl,":") M <- as(I4, cl) M. <- as(D4, cl) stopifnot(diag(4) == as(M,"matrix"), if(is(cl,"dMatrix")) diag(x=1:4) == as(M.,"matrix") else TRUE) cat(" [Ok]\n") } s4 <- as(D4,"sparseMatrix") v <- c(11,2,2,12); s4[2:3,2:3] <- v; validObject(s4) s4. <- D4; s4.[2:3,2:3] <- v; validObject(s4.) stopifnot(all(s4 == s4.)) ## now assign symmetrically to symmetricMatrix s4 <- as(as(D4,"sparseMatrix"),"symmetricMatrix") s4[2:3,2:3] <- v validObject(s4) stopifnot(is(s4,"symmetricMatrix")) assert.EQ.mat(s4, as(s4.,"matrix"),tol=0) ## lower-triangular unit-diagonal L <- new("dtCMatrix", i = 1L, p = c(0:1, 1L), Dim = c(2L, 2L), x = 0.5, uplo = "L", diag = "U") stopifnot(range(L) == 0:1, all.equal(mean(L), 5/8)) ## from 0-diagonal to unit-diagonal triangular {low-level step}: tu <- t1 ; tu@diag <- "U" tu validObject(cu <- as(tu, "CsparseMatrix")) # still unitriangular validObject(cnu <- diagU2N(cu))# <- testing diagU2N validObject(tt <- as(cu, "TsparseMatrix")) tu. <- tt ## validObject(tu. <- as(cu, "dtTMatrix")) stopifnot(exprs = { ## NOT: identical(tu, tu.), # since T* is not unique! identical(cu, as(tt, "CsparseMatrix")) length(cnu@i) == length(cu@i) + nrow(cu) identical(cu, diagN2U(cnu)) # <- testing diagN2U all(cu >= 0, na.rm = TRUE) all(cu >= 0) any(cu >= 7) }) validObject(tcu <- t(cu)) validObject(ttu <- t(tu)) validObject(ltu <- as(ttu, "lMatrix")) validObject(ldtu <- as(ltu, "denseMatrix")) validObject(Cltu <- as(ltu, "CsparseMatrix")) stopifnot(identical(asCsp(ttu > 0), asCsp(ltu)), all(ltu == as(ttu > 0,"denseMatrix"))) ltu - (ttu > 0) # failed assert.EQ.mat(cu, as(tu,"matrix"), tol=0) assert.EQ.mat(cnu, as(tu,"matrix"), tol=0) showProc.time() C <- suppressWarnings(Matrix(c(0,1,0,0), 5,5)) + Diagonal(5) (tU <- diagN2U(tril(C))) # dtC Unitriangular ntU <- as(tU, "nMatrix") nT <- as(ntU, "TsparseMatrix") R <- as(tU, "RsparseMatrix") Tt <- diagU2N(R) # used to accidentally drop the diag. stopifnot(R@x == c(1,1,1), diag(Tt) == 1) lcu <- new("ltCMatrix", Dim = c(4L, 4L), i = c(0:1, 0L), p = c(0L, 0:3), x = c(TRUE, FALSE, FALSE), uplo = "U", diag = "U") (lTu <- as(lcu,"TsparseMatrix"))# prints wrongly (in Matrix 0.999375-31) stopifnot(identical3(rowSums(lcu), rowSums(lTu), rowSums(drop0(lcu)))) (ncu <- as(lcu, "nMatrix"))# -- gives the "pattern" of lcu, i.e. FALSE are *there* ncn <- diagU2N(ncu) (cncn <- crossprod(ncn))# works -> "nsCMatrix" stopifnot(identical(ncu, as(lcu,"nsparseMatrix")), identical(rowSums(ncu), c(3:1, 1L)), Q.eq(ncn, ncu), Q.eq(crossprod(drop0(lcu)), crossprod(lcu)),# crossprod works -> "dsCMatrix" identical(crossprod(ncu), cncn), Q.eq(cncn, t(ncu) %&% ncu)) #used to seg.fault U <- new("dtCMatrix", Dim = c(6L, 6L), i = c(0:1, 0L, 2:3, 1L, 4L), p = c(0L,0L,0L, 2:3, 5L, 7L), x = rep.int(-0.5, 7), diag = "U") validObject(U) U. <- solve(iU <- solve(U))#-> gave segmentation fault stopifnot(validObject(U), ## had a case where solve(U) modified U ! validObject(iU), validObject(U.), ## no rounding error, since have iU@x * 8 is integer : identical(U, diagN2U(drop0(U.)))) showProc.time() ## o (of length > 1): stopifnotValid(tm <- tu * 1:8, "sparseMatrix") stopifnot(identical4(tm, cu * 1:8, 1:8 * cu, 1:8 * tu)) cu[1,2] <- tu[1,2] <- NA mu <- as(tu,"matrix") stopifnotValid(cu, "CsparseMatrix"); stopifnotValid(cu, "triangularMatrix") stopifnotValid(tu, "TsparseMatrix"); stopifnotValid(tu, "triangularMatrix") stopifnot(identical(cu * 1:8, tu * 1:8), # but are no longer triangular identical(cu > .1, as(tu > .1, "CsparseMatrix")), all(cu >= 0, na.rm=TRUE), !all(cu >= 1), is.na(all(tu >= 0)), ## Csparse_drop: preserves triangularity incl diag="U" ## ^^^^^^^^^^^^ now using more general R_sparse_drop0 identical(cu, .Call(Matrix:::R_sparse_drop0, cu, 0.)) ) assert.EQ.mat(cu * 1:8, mu * 1:8) ina <- is.na(as(cu,"matrix")) ## These 3 were each different (2008-03) !! stopifnot(all(ina == is.na(cu)), all(ina == is.na(as(cu,"generalMatrix"))), all(ina == as(is.na(as(cu,"matrix")),"nMatrix"))) set.seed(7) xx <- rpois(10, 50) Samp <- function(n,size) sample(n, size, replace=TRUE) Tn <- sparseMatrix(i=Samp(8, 50), j=Samp(9,50), x=xx, repr = "T") Tn stopifnot(xx == Tn@x, max(xx) < max(Tn), 0 == min(Tn), (sT <- sum(Tn)) == sum(colSums(Tn)), sT == sum(Tn@x), range(Tn) == range(as(Tn, "CsparseMatrix"))) ## tu. is diag "U", but tu2 not: tu2 <- as(as(tu., "generalMatrix"), "triangularMatrix") assert.EQ.mat(cu, mu, tol=0) stopifnot(identical3(cu[cu > 1], tu [tu > 1], mu [mu > 1]), identical3(cu <= 1, tu <= 1, as(mu <= 1, "lMatrix")),# all lgeMatrix identical3(cu[cu <= 1], tu[tu <= 1], mu[mu <= 1]), identical3(cu , triu(cu ), t(t(cu))), identical3(tu , triu(tu ), t(t(tu))), identical3(tu., triu(tu.), t(t(tu.))), identical(tu2, triu(tu2)), identical(tcu , tril(tcu)), identical(ttu , tril(ttu)), identical(t(tu), tril(t(tu))) ) assert.EQ.mat(triu(cu), as(triu(as(cu, "matrix")), "matrix")) for(k in -1:1) assert.EQ.mat(tril(cu,k), as(tril(as(cu, "matrix"), k), "matrix")) (dtr <- Matrix(local({m <- diag(2); m[1,2] <- 3;m}))) identical(dtr, triu(dtr)) assert.EQ.mat(tril(dtr), diag(2)) (t4 <- new("dgTMatrix", i = 3:0, j = 0:3, x = rep(1,4), Dim = as.integer(c(4,4)))) c4 <- as(t4, "CsparseMatrix") ## the same but "dsT" (symmetric) suppressWarnings(M <- Matrix(c(0, rep(c(0,0:1),4)), 4,4))# warning:.. length [13] is not ..multiple tt <- as(M, "TsparseMatrix") stopifnot(all.equal(triu(t4) + tril(t4), c4), all.equal(triu(tt) + tril(tt), c4)) showProc.time() ###-- Numeric Dense: Crossprod & Solve set.seed(123) mm. <- mm <- Matrix(rnorm(500 * 150), ncol = 150) stopifnot(validObject(mm)) xpx <- crossprod(mm) stopifnot(identical(mm, mm.))# once upon a time, mm was altered by crossprod() stopifnotValid(xpx, "dpoMatrix") str(mm) # 'dge*" str(xpx)# 'dpo*" xpy <- crossprod(mm, rnorm(500)) res <- solve(xpx, xpy) str(xpx)# now with Cholesky factor stopifnot(validObject(xpx), validObject(xpy), validObject(res)) stopifnot(all.equal(xpx %*% res, xpy, tolerance = 1e-12)) lp <- xpx >= 1 slp <- as(lp, "sparseMatrix") ltlp <- lp[ lower.tri(lp) ] sltlp <- slp[ lower.tri(slp) ] dim(ij <- which(lower.tri(lp), arr.ind = TRUE)) ss <- slp[ij] # now fast (!) stopifnot(identical4(lp[ij], ltlp, sltlp, as(lp, "matrix")[ij]), identical(ss, sltlp), isValid(lp, "lsyMatrix"), lp@uplo == "U") showProc.time() ###-- more solve() methods {was ./solve.R } ## first for "dgeMatrix" and all kinds of RHS : (m6 <- 1 + as(diag(0:5), "generalMatrix")) rcond(m6) I6 <- as(diag(6), "generalMatrix") stopifnot(all.equal(I6, m6 %*% solve(m6)), all.equal(I6, solve(m6) %*% m6) ) (i6 <- solve(m6, Matrix(1:6))) stopifnot(identical(i6, as(cbind(c(-4, rep(1,5))), "generalMatrix")), identical(drop(i6), solve(m6, 1:6)), identical(i6, solve(m6, matrix(1:6))), identical(i6, solve(m6, matrix(c(1,2,3,4,5,6)))) ) ## solve() (m <- t1+ t(t1) + Diagonal(4)) i.m <- solve(as.mat(m)) I1 <- m %*% i.m o4 <- diag(I1) im <- solve(m)# is now sparse {not yet} (I2 <- m %*% im) (ms <- as(m, "symmetricMatrix")) ## solve(, ): s.mm <- solve(m,m) s.mms <- solve(m, ms) ## these now work "fully-sparse" s.ms2 <- solve(ms, ms) s.msm <- solve(ms, m) I4c <- as(Matrix(diag(4),sparse=TRUE), "generalMatrix") stopifnot(isValid(im, "Matrix"), isValid(I2, "Matrix"), class(I4c) == "dgCMatrix", all.equal(I1, as(I2,"denseMatrix"), tolerance = 1e-14), all.equal(diag(4), as.mat(I2), tolerance = 1e-12), all.equal(s.mm, I2, tolerance = 1e-14), all.equal(s.mms, I2, tolerance = 1e-14), all.equal(s.ms2, s.msm, tolerance = 4e-15), all.equal(s.ms2, I4c , tolerance = 4e-15), abs(o4 - 1) < 1e-14) image(T125 <- kronecker(kronecker(t5,t5),t5), main = paste("T125:",class(T125))) dim(T3k <- kronecker(t5,kronecker(T125, t5))) system.time(IT3 <- solve(T3k))# incredibly fast I. <- drop0(zapsmall(IT3 %*% T3k)) I.. <- diagN2U(I.) I <- Diagonal(5^5) stopifnotValid(IT3, "dtCMatrix") stopifnot(## something like the equivalent of all(I. == Diagonal(3125)) : identical(as(I., "diagonalMatrix"), I), identical(as(I..,"diagonalMatrix"), I) ) showProc.time() ## printSpMatrix() ; "suppressing (columns | rows) .." {and do it correctly!} IT3 op0 <- options(width = 70, max.print = 1000) T125[-(1:50),] ## suppression ... is it correctly done? ## Still buggy -- FIXME: see ../TODO --- even if we'd require max.print >= 5 or so for(mm in 1:21) { options(max.print=mm) cat("----------\n\nmax.print=",mm,":\n", sep="") cat("\n>> U: ") ; show(U) cat("\n>> slp: ") ; show(slp) } options(op0)# revert to max.print = 1000 ###-- row- and column operations {was ./rowcolOps.R } set.seed(321) (m1 <- round(Matrix(rnorm(25), 5), 2)) m1k <- Matrix(round(rnorm(1000), 2), 50, 20) m.m <- as(m1k, "matrix") stopifnot(all.equal(colMeans(m1k), colMeans(m.m)), all.equal(colSums (m1k), colSums (m.m)), all.equal(rowMeans(m1k), rowMeans(m.m)), all.equal(rowSums (m1k), rowSums (m.m)), all.equal(colMeans(m1k, na.rm=TRUE), colMeans(m.m, na.rm=TRUE)), all.equal(colSums (m1k, na.rm=TRUE), colSums (m.m, na.rm=TRUE)), all.equal(rowMeans(m1k, na.rm=TRUE), rowMeans(m.m, na.rm=TRUE)), all.equal(rowSums (m1k, na.rm=TRUE), rowSums (m.m, na.rm=TRUE)) ) ###-- kronecker for nonsparse uses Matrix(.): stopifnotValid(kr <- kronecker(m1, m6), "Matrix") assert.EQ.mat(kr, kronecker(as(m1, "matrix"), as(m6, "matrix")), tol = 0) ## sparse: (kt1 <- kronecker(t1, tu)) kt2 <- kronecker(t1c, cu) stopifnot(identical(as(kt1, "CsparseMatrix"), kt2)) ktf <- kronecker(as(t1, "matrix"), as(tu, "matrix")) if(FALSE) # FIXME? our kronecker treats "0 * NA" as "0" for structural-0 assert.EQ.mat(kt2, ktf, tol= 0) (cs1 <- colSums(kt1)) NA.or.True <- function(x) is.na(x) | x eq <- (cs1 == colSums(as(kt1, "matrix"))) stopifnot(NA.or.True(eq), identical(is.na(eq), is.na(cs1))) nt1 <- as(kt1, "nMatrix") # no NA's anymore (ng1 <- as(as(nt1, "generalMatrix"),"CsparseMatrix")) # ngC dg1 <- as(ng1, "dMatrix")# dgC lt1 <- kt1 > 5 nt1 <- as(lt1, "nMatrix") (colSums(nt1, sparseResult = TRUE)) (colSums(kt1, sparseResult = TRUE)) # dsparse, with NA (colSums(lt1, sparseResult = TRUE)) # isparse, with NA (colSums(lt1, sparseResult = TRUE, na.rm = TRUE)) (colSums(nt1, sparseResult = TRUE)) # isparse, no NA ## check correct sparseness of both: for(M in list(kt1, nt1, ng1, dg1, lt1, nt1)) { m <- as(M, "matrix") for(na.rm in c(FALSE,TRUE)) { cs <- colSums(M, na.rm = na.rm) cs. <- colSums(M, na.rm = na.rm, sparseResult = TRUE) rs <- rowSums(M, na.rm = na.rm) rs. <- rowSums(M, na.rm = na.rm, sparseResult = TRUE) stopifnotValid(cs., "sparseVector") stopifnotValid(rs., "sparseVector") stopifnot(identical(cs, as(cs., "vector")), identical(rs, as(rs., "vector")), {eq <- cs == colSums(m, na.rm = na.rm) ; ineq <- is.na(eq) all(ineq | eq) && identical(ineq, is.na(cs)) }, {eq <- rs == rowSums(m, na.rm = na.rm) ; ineq <- is.na(eq) all(ineq | eq) && identical(ineq, is.na(rs)) } ) } } i1 <- cs. == 1 cs2 <- cs. cs2[i1] <- 0 # failed in *-31 !! ## now *index* with a NA-sparseVector : i2 <- i1 ; i2[3] <- NA ; li2 <- as.logical(i2) cs3 <- cs. ; cs3 [i2] <- 0 v3 <- as(cs.,"vector"); v3[li2] <- 0 cs4 <- cs. ; cs4[li2] <- 0 stopifnot(length(i1@x) == 2, identical(li2, as(i2,"vector")), identical(cs3, cs4), cs3 == v3, all(as(v3, "sparseVector") == cs3) ## indexing simple "numeric" with sparseVector: ## see 'R_FIXME' in ../R/sparseVector.R ## , identical(v3[i2], v3[li2]) ## TODO: ## sub-assigning into simple "numeric" with sparseVector index: ) showProc.time() M <- Matrix(c(2:0,1),2); M. <- as(M, "sparseMatrix") (N <- as(crossprod(kronecker(diag(2), M)) > 0, "nMatrix")) (L. <- as(N,"lMatrix")) stopifnot(identical(N, as(L.,"nMatrix")), identical(kronecker( c(1,0), M), kronecker(cbind(1:0), M))) assert.EQ.mat(kronecker(M, c(1,0,0)), kronecker(as(M, "matrix"), c(1,0,0))) ## coercion from "dpo" or "dsy" xx <- as(xpx, "dsyMatrix") stopifnot(isSymmetric(xxS <- as(xx, "sparseMatrix")), isSymmetric(xpxS <- as(xpx, "sparseMatrix"))) tm <- matrix(0, 8,8) tm[cbind(c(1,1,2,7,8), c(3,6,4,8,8))] <- c(2,-30,15,20,80) (tM <- Matrix(tm)) ## dtC (mM <- Matrix(m <- (tm + t(tm)))) ## dsC mT <- as(mM, "TsparseMatrix") gC <- as(as(mT, "generalMatrix"), "CsparseMatrix") lT <- as(Matrix(TRUE, 2, 2), "TsparseMatrix") ## Check that mT, lT, and gC print properly : pr.mT <- capture.output(mT) pr.lT <- capture.output(lT)[-(1:2)] nn <- unlist(strsplit(gsub(" +\\.", "", sub("^....", "", pr.mT[-(1:2)])), " ")) stopifnot(as.numeric(nn[nn != ""]) == m[m != 0], identical(1:2, grep("|", pr.lT, fixed=TRUE)), identical(pr.lT, capture.output(as(lT, "nMatrix"))[-(1:2)]), capture.output(gC)[-1] == pr.mT[-1]) assert.EQ.mat(tM, tm, tol=0) assert.EQ.mat(gC, m, tol=0) assert.EQ.mat(mT, m, tol=0) stopifnotValid(mM, "dsCMatrix") stopifnotValid(tM, "dtCMatrix") stopifnot(identical(mT, as(mM, "TsparseMatrix")) , identical(gC, as(mM, "generalMatrix")) ## coercions general <-> symmetric , identical(as(mM. <- as(mM, "generalMatrix"), "symmetricMatrix"), mM) , identical(as(as(mM., "TsparseMatrix"), "symmetricMatrix"), mT) , identical(as(as(tM, "generalMatrix"),"triangularMatrix"), tM) , identical(tM + Diagonal(8), tMD <- Diagonal(8) + tM) ) stopifnotValid(tMD, "dtCMatrix") eM <- eigen(mM) # works thanks to base::as.matrix hack in ../R/zzz.R stopifnot(all.equal(eM$values, { v <- c(162.462112512353, 30.0665927567458) c(v, 15, 0, 0, 160-v[1], -15, -v[2])}, tolerance=1e-14)) ##--- symmetric -> pos.def. needs valid test: m5 <- Matrix(diag(5) - 1) assertError(as(m5, "dpoMatrix"))# not pos.definite! pm5 <- as(m5, "packedMatrix") # packed assertError(as(pm5, "dppMatrix"))# not pos.definite! sm <- as(Matrix(diag(5) + 1), "packedMatrix") pm <- as(sm,"dpoMatrix")## gave infinite recursion (for a day or so) pp <- as(pm,"dppMatrix") x <- round(100 * crossprod(Matrix(runif(25),5))) D <- Diagonal(5, round(1000*runif(5))) px <- pack(x) stopifnot(is(x, "dsyMatrix"), is(px, "dspMatrix"), is(D, "ddiMatrix")) class(x+D)#--> now "dsyMatrix" stopifnot(is(x+D, "symmetricMatrix"), is(D+px, "dspMatrix"), identical(x+D, D+x), identical(px+D, D+px), identical(pack(x-D), px-D)) tx <- tril(x) ptx <- pack(tx) stopifnot(is(tx, "dtrMatrix"), is(ptx, "dtpMatrix"), is(t(tx), "dtrMatrix"), is(t(ptx), "dtpMatrix"), is(D + tx, "dtrMatrix"), is(tx + D, "dtrMatrix"), is(ptx + D, "dtpMatrix"), is(D + ptx, "dtpMatrix")) showProc.time() ###-- dense nonzero pattern: class(m <- Matrix(TRUE,2,2)) # lsy isValid(n <- as(m, "nMatrix"), "nsyMatrix") ## 1) as(n,"CsparseMatrix") # used to give CHOLMOD error: invalid xtype... ls2 <- as(m, "CsparseMatrix") # works fine ## and really 'm' and 'n' are interally slot identical (!!!) as(n,"sparseMatrix") as(m,"sparseMatrix") ### -- now when starting with nsparse : nT <- new("ngTMatrix", i = as.integer(c(0, 1, 0)), j = as.integer(c(0, 0, 1)), Dim = as.integer(c(2,2))) (nC <- as(nT, "CsparseMatrix")) str(nC)# of course, no 'x' slot tt <- as(nT,"denseMatrix") # nge (was lge "wrongly") stopifnot(is(tt,"ngeMatrix"), identical(as(tt, "lMatrix"), as(as(nT, "lMatrix"), "denseMatrix"))) tt as(nC,"denseMatrix") showProc.time() ###-- sparse nonzero pattern : ---------- (nkt <- as(as(as(kt1, "CsparseMatrix"), "generalMatrix"), "nMatrix"))# ok dkt <- as(nkt, "denseMatrix") (clt <- crossprod(nkt)) stopifnotValid(nkt, "ngCMatrix") stopifnotValid(clt, "nsCMatrix") suppressWarnings(crossprod(clt)) ## warning "crossprod() of symmetric ..." ## a Csparse with *repeated* entry is not valid! assertError(new("ngCMatrix", p = c(0L,2L), i = c(0L,0L), Dim = 2:1)) ### "d" <-> "l" for (symmetric) sparse : -------------------------------------- data(KNex, package = "Matrix") mm <- KNex$mm xpx <- crossprod(mm) ## extract nonzero pattern nxpx <- as(xpx, "nMatrix") show(nxpx) ## now ok, since subsetting works r <- nxpx[1:2,] lmm <- as(mm, "lMatrix") nmm <- as(lmm, "nMatrix") xlx <- crossprod(lmm) x.x <- crossprod(nmm) ## now A = lxpx and B = xlx should be close, but not quite the same ## since = 0 is well possible when x!=0 and y!=0 . ## However, A[i,j] != 0 ==> B[i,j] != 0: A <- as(as(nxpx, "lMatrix"), "TsparseMatrix") B <- as(as(xlx, "lMatrix"), "TsparseMatrix") ij <- function(a) a@i + ncol(a) * a@j stopifnot(all(ij(A) %in% ij(B))) l3 <- upper.tri(matrix(,3,3)) validObject(c3 <- as(l3, "CsparseMatrix")) stopifnotValid(c3, "lMatrix")# lgC (M <- Matrix(l3)) stopifnotValid(M, "ltCMatrix") stopifnotValid(M2 <- M %x% M, "triangularMatrix") # is "dtT" (why not "dtC" ?) stopifnot(dim(M2) == c(9,9), identical(M2, kronecker(M,M))) M3 <- M %x% M2 #ok (cM3 <- colSums(M3, sparseResult=TRUE)) identical(as.vector(cM3), as(rev(rowSums(M3, sparseResult=TRUE)), "vector")) M. <- M2 %x% M # gave infinite recursion ## diagonal, sparse & interactions stopifnotValid(as(Diagonal(3), "TsparseMatrix"), "TsparseMatrix") stopifnotValid(X <- Diagonal(7) + 1.5 * tM[1:7,1:7], "sparseMatrix") stopifnotValid(X, "triangularMatrix") stopifnotValid(XX <- X - chol(crossprod(X)), "triangularMatrix") X XX XX <- as(drop0(XX), "symmetricMatrix") stopifnot(identical(XX, Matrix(0, nrow(X), ncol(X), doDiag=FALSE))) M <- Matrix(m., sparse = FALSE) (sM <- Matrix(m.)) class(dlM <- M >= 1) stopifnot(identical(dlM, !(M < 1))) stopifnotValid(sM, "sparseMatrix") stopifnotValid(dlM, "denseMatrix") (lM <- as(dlM, "sparseMatrix")) lM2 <- as(dlM, "CsparseMatrix") #-> now ok lM0 <- .dense2sparse(dlM, "C") stopifnot(identical3(lM, lM2, lM0)) selectMethod("coerce", c("lgeMatrix", "CsparseMatrix"), useInherited = c(from = TRUE, to = FALSE)) ms0 <- Matrix(c(0,1,1,0), 2,2) ms <- as(ms0, "TsparseMatrix") cs <- as(ms, "CsparseMatrix") ll <- as(ms, "lMatrix") lt <- as(ll, "generalMatrix") nn <- as(cs, "nsparseMatrix") l2 <- as(cs, "lsparseMatrix") nt <- triu(nn) n3 <- as(nt, "lsparseMatrix") da <- nt + t(nt) dm <- nt * t(nt) + da ## mnt <- as(nt, "matrix") m <- rbind(v <- 2:3) assert.EQ.mat(nt %*% v, mnt %*% v) assert.EQ.mat(v %*% nt, v %*% mnt) assert.EQ.mat( crossprod(nt, v), crossprod(mnt,v)) assert.EQ.mat( crossprod(v, nt), crossprod(v,mnt)) assert.EQ.mat(tcrossprod(v, nt), tcrossprod(v,mnt)) assert.EQ.mat(tcrossprod(nt, m), tcrossprod(mnt, m)) ## stopifnotValid(ms, "dsTMatrix") stopifnot(as(ms0,"matrix") == as(ll, "matrix"), # coercing num |-> log as(lt, "matrix") == as(ll, "matrix"), identical(ms, as(ll, "dMatrix")), identical4(as(ll, "CsparseMatrix"), as(cs, "lMatrix"),# lsC* as(nn, "lsparseMatrix"), l2), identical3(da, dm, as(cs, "generalMatrix")), # dgC* identical(as(da, "lMatrix"), as(lt, "CsparseMatrix")) # lgC* ) ## Dense *packed* ones: s4 <- as(D4, "symmetricMatrix") sp <- as(s4, "packedMatrix") tp <- triu(sp) tpL <- tril(sp) (spL <- t(sp)) stopifnot(sp @uplo=="U", tp @uplo=="U", spL@uplo=="L", tpL@uplo=="L") ## band(): n <- 4 ; m <- 6 r1 <- Matrix(1:24, n,m) validObject(M1 <- band(r1, 0,0)) (M1 <- as(M1, "sparseMatrix")) r2 <- Matrix(1:18, 3, 6) stopifnot(identical(M1, bandSparse(n,m, k=0, diagonals = list(diag(r1)))), identical(band(r2, 0,4), band(r2, 0,3) + band(r2, 4,4))) s1 <- as(r1, "sparseMatrix") # such that band(s1) is sparse, too for(k1 in (-n):m) for(k2 in k1:m) { stopifnotValid(br1 <- band(r1, k1,k2), "ddenseMatrix") stopifnotValid(bs1 <- band(s1, k1,k2), "CsparseMatrix") stopifnot(all(r1 == s1)) } showProc.time() ## large dimensions -- gave integer overflow ## R-forge bug 6743 by Ariel Paulson ## https://r-forge.r-project.org/tracker/?func=detail&atid=294&aid=6743&group_id=61 n <- 47000 stopifnotValid(Mn <- sparseMatrix(i = rep(1:6, 2), dims = c(n,n), j = c(1L,4L, 6:8, 10:12, 16:19)), "nsparseMatrix") stopifnotValid(M <- as(Mn, "dMatrix"), "dgCMatrix") dim(M) # 47000 47000 i <- 46341 stopifnotValid(bM <- band(M, i, i ), "dtCMatrix") ## gave Error in if (sqr && k1 * k2 >= 0) .... ## In addition: Warning message: ## In k1 * k2 : NAs produced by integer overflow x <- 1:999 bM2 <- bandSparse(n, k=i+(0:3), diagonals = list(x,10*x,32*x,5*x), symmetric=TRUE) stopifnotValid(bM2, "dsCMatrix") stopifnotValid(bb2 <- band(bM2, k1=i-2, k2=i+5), "dtCMatrix") stopifnotValid(b0 <- band(bM2, -1000, 1000), "dsCMatrix") stopifnotValid(b0a <- band(bM2, -1000, 1001), "dgCMatrix") (id <- nrow(M)-i)# 659 colN <- colSums(bM2 != 0) stopifnot(exprs = { identical(bb2, triu(bM2)) identical(b0 @x, numeric(0)) identical(b0a@x, numeric(0)) identical(bM2, band(bM2, -(i+3), i+3)) assert.EQ(as(bM2, "generalMatrix"), band(bM2, -(i+3), i+11), showOnly = TRUE) colN == { cN <- c(1:3, rep(4L, id-3)); c(rev(cN), rep(0L, i-id), cN)} }) showProc.time() ## some of these failed before Matrix 1.4.0 (Oct.7, 2021) D. <- Diagonal(x= c(-2,3:4)); D.[lower.tri(D.)] <- 1:3 ; D. D0 <- Diagonal(x= 0:3); D0[upper.tri(D0)] <- 1:6 ; D0 stopifnot(all.equal(list(modulus = structure(24, logarithm = FALSE), sign = -1L), unclass(determinant(D.,FALSE)), tolerance=1e-15), det(Matrix(0,1)) == 0, all.equal(list(modulus = structure(0, logarithm = FALSE), sign = 1L), unclass(determinant(D0,FALSE)), tolerance=0) ) ### More sparseVector checks: ------------------------------- validObject(new("isparseVector")) R <- sv <- as(D4, "sparseVector") ## dim() <- (n1,n2) --> sparse Matrix : dim(R) <- dim(D4) stopifnotValid(sv,"sparseVector") stopifnotValid(R, "sparseMatrix") stopifnot(identical(D4, as(R, "diagonalMatrix"))) iv <- c(rep(0, 5), 3, 0,0,7,0,0,0) sv <- as(iv, "sparseVector") sv. <- as(as.integer(iv), "sparseVector") ## Note: Method with signature "numeric#sparseVector" chosen ... (sv2 <- as(sv, "isparseVector")) ## gave error as(sv, "zsparseVector") stopifnot(identical(sv., sv2), identical( Matrix(sv, 3,4, byrow=TRUE), t(Matrix(sv, 4,3)))) options(warn = 0)# no longer error ## "Large" sparse: n <- 100000 m <- 50000 ; nnz <- 47 M <- spMatrix(n, m, i = sample(n, nnz, replace = TRUE), j = sample(m, nnz, replace = TRUE), x = round(rnorm(nnz),1)) validObject(Mv <- as(M, "sparseVector")) validObject(Dv <- as(Diagonal(60000), "sparseVector")) validObject(LD <- Diagonal(60000, TRUE)) validObject(Lv <- as(LD, "sparseVector")) Dm <- Dv; dim(Dm) <- c(180000L, 20000L) stopifnot(!doExtras || isValid(Md <- M * rowSums(M, sparseResult=TRUE), "sparseMatrix"), LD@diag == "U", isValid(Dm, "sparseMatrix"), identical(Dv, as(Dm, "sparseVector"))) p. <- new("dtCMatrix", i = c(2:3, 2L), p = c(0L, 2:3, 3L, 3L), Dim = c(4L, 4L), x = rep(-0.5, 3), uplo = "L", diag = "U") assert.EQ.mat(solve(solve(p.)), as(p., "matrix")) dimnames(p.)[[1]] <- paste(1:4) ii <- is.na(p.) stopifnot(all(!ii), !any(as(ii, "denseMatrix")))# used to fail lst <- ls() table(istri <- sapply(lst, function(.) is(get(.),"triangularMatrix"))) table(triC <- sapply(lst[istri], function(.) class(get(.)))) table(uniC <- sapply(lst[istri], function(.) get(.)@diag == "U")) lsUtr <- lst[istri][uniC] (di <- sapply(lsUtr, function(.) dim(get(.)))) ## TODO: use %*%, crossprod(), .. on all those 4 x 4 -- and check "triangular rules" assertError(new("ltrMatrix", Dim = c(2L,2L), x=TRUE))# gave "illegal" object w/o error assertError(new("ntrMatrix", Dim = c(2L,2L)))# dito showProc.time()# == "stats" cat("doExtras:",doExtras,"\n") if(doExtras) { cat("checkMatrix() of all: \n---------\n") Sys.setlocale("LC_COLLATE", "C") # to keep ls() reproducible for(nm in setdiff(ls(), "d4da")) { # FIXME: checkMatrix(d4da) if(is(.m <- get(nm), "Matrix")) { cat("\n", rep("-",nchar(nm)),"\n",nm, ":\n", sep='') checkMatrix(.m) } } showProc.time() } ## in any case, test d4d.2 <- .dense2sparse(!!d4da, "C") ## <<- did wrongly make dimnames symmetric l4da <- as(d4da, "lMatrix") assert.EQ.Mat(l4da, as(l4da,"CsparseMatrix")) dtr <- tr4 <- triu(Matrix(1:16, 4,4)) dtr@x[Matrix:::indTri(4, upper=FALSE, diag=FALSE)] <- 100*(-3:2) stopifnot(all.equal(dtr, tr4), # because are same *as* simple matrices dtr@x[1:4] == c(1, -(3:1)*100), range(tr4) == c(0,16), range(dtr) == c(0,16)) # <- failed ## new("nsyMatrix") + new("lgeMatrix") # failed cln <- sort(outer(c("l","n"), paste0(c("ge","sy"), "Matrix"), paste0)) dim(c.c <- as.matrix(expand.grid(cln, cln, KEEP.OUT.ATTRS=FALSE))) # 16 x 2 ## clTry <- function(expr) class(tryCatch(expr, error=identity))[[1]] ## '+' [Arith] failed -- now fixed cbind(c.c, Res = apply(c.c, 1, function(x) class(new(x[1]) + new(x[2])))) ## '<' [Compare] works fine cbind(c.c, Res = apply(c.c, 1, function(x) class(new(x[1]) < new(x[2])))) if(!interactive()) warnings() ## R-forge matrix-Bugs [#6708] (2021-02-25, by David Cortes): sVec <- sparseVector(c(1,exp(1),pi), c(1,3,7), length=9) vec <- c(1, 0, exp(1), 0, 0, 0, pi, 0, 0) stopifnot(identical(as.matrix(sVec), as.matrix(vec)), identical(as.array (sVec), as.array (vec))) ## R-forge matrix-Bugs [#6656] (2020-02-05, by Chun Fung (Jackson) Kwok (kcf.jackson) ## (*is* a bug, but not in kronecker etc, but rather in Arith / Ops) dC <- sparseMatrix(i=1:4, j=1:4, x=5:2, triangular = TRUE) (dT <- as(dC, "TsparseMatrix")) stopifnot(identical(--dC, dC), identical(--dT, dT) ) ## both - gave : Error .... 'factors' is not a slot in class "dtTMatrix" ## R PR#18250 - by Mikael Jagan nm2 <- c("a","b") x <- new("dspMatrix", x = c(3,2,1), Dim = c(2L,2L), Dimnames = list(nm2, NULL)) dn <- list(nm2,nm2) stopifnotValid(x. <- unpack(x), "dsyMatrix") validObject( y <- as(x , "generalMatrix") ) validObject( y. <- as(x., "generalMatrix") ) stopifnotValid( l <- x > 0, "lspMatrix") stopifnotValid( l. <- unpack(l), "lsyMatrix") stopifnotValid( lg <- as(l, "generalMatrix"), "lgeMatrix") stopifnotValid( lg2<- as(l.,"generalMatrix"), "lgeMatrix") stopifnot(exprs = { identical(dimnames(x ), dn) identical(dimnames(x.), dn) identical(dimnames(y ), dn) # was wrong identical(dimnames(y.), dn) # was wrong identical(dimnames(l ), dn) identical(dimnames(l.), dn) identical(dimnames(lg), dn) # was wrong identical(lg, lg2) ## even more cases (?) }) showProc.time() dn4 <- list(letters[1:4], LETTERS[1:4]) (D4n <- `dimnames<-`(D4, dn4)) m4 <- as(D4n, "matrix") stopifnot(identical(dimnames(m4), dn4), Q.eq(D4n, m4, superclasses=NULL)) ## as(, "matrix") had lost dimnames before s24 <- new("dgCMatrix", Dim = c(2L, 4L), p = integer(5L)) triu(s24, k = 4L) # was an error tril(s24, k = 4L) # was an error ## band(, -k, k) used isSymmetric(tol > 0) to test ## for symmetry of the result, and forcing symmetry lost information s44 <- new("dgCMatrix", Dim = c(4L, 4L), p = c(0L, 0L, 1L, 1L, 1L), i = 0L, x = .Machine$double.xmin) (bs44 <- band(s44, -1L, 1L)) stopifnot(identical(s44, bs44)) l0.u <- new("ltrMatrix", diag = "U") !l0.u # was an error n11 <- new("ngeMatrix", Dim = c(1L, 1L), x = NA) nn11 <- !n11 # did not respect NA<=>TRUE stopifnot(is(nn11, "ngeMatrix"), identical(nn11@x, FALSE)) ## coercions preserving mathematical equality ought to preserve 'factors' slot; ## though currently only for sparse->sparse and dense->dense mC <- as(as(Diagonal(x = rlnorm(5)), "CsparseMatrix"), "symmetricMatrix") stopifnot(identical(mC@factors, list())) chol(mC) mR <- as(mC, "RsparseMatrix") mT <- as(mR, "TsparseMatrix") stopifnot(!identical(mTf <- mT@factors, list()), identical(mTf, mR@factors), identical(mTf, mC@factors)) ## overallocated l.T should follow usual logic ... NA || TRUE -> TRUE, etc. lT. <- lT0 <- lT1 <- new("lgTMatrix", Dim = c(1L, 1L), i = c(0L, 0L), j = c(0L, 0L), x = c(NA, NA)) lT0@x[1L] <- FALSE lT1@x[1L] <- TRUE stopifnot(identical(as.vector(lT.), NA), identical(as.vector(lT0), NA), identical(as.vector(lT1), TRUE), identical(as(lT1, "CsparseMatrix")@x, TRUE), identical(as(lT1, "dMatrix")@x, 1)) ## various is.na(), anyNA(), which() bugs in Matrix <= 1.4-1 .nge <- new("ngeMatrix", Dim = c(2L, 2L), x = rep.int(NA, 4L)) .dtr <- new("dtrMatrix", Dim = c(2L, 2L), x = c(NA, 1, 2, Inf), diag = "U") .dsy <- new("dsyMatrix", Dim = c(2L, 2L), x = c(1, NA, 2, 3)) stopifnot(!any(is.na(.nge)), !any(is.na(.dtr)), !any(is.infinite(.dtr)), !any(is.na(.dsy)), !anyNA(.nge), !anyNA(.dtr), !anyNA(.dsy), identical(which(.nge), 1:4)) ## various `dim<-`() bugs in Matrix <= 1.4-1 .dgR <- new("dgRMatrix", Dim = c(2L, 2L), p = integer(3L)) assertError(`dim<-`(.dgR, -x@Dim)) # had yielded an invalid object stopifnot(is(`dim<-`(.dgR, c(4L, 1L)), "RsparseMatrix")) # was TsparseMatrix ## symmpart() was not a dMatrix or a symmetricMatrix; ## symmpart() did not get symmetrized 'Dimnames' .ldi.sp <- symmpart(new("ldiMatrix", Dim = c(1L, 1L), Dimnames = list("a", "b"), x = TRUE)) stopifnot(is(.ldi.sp, "dMatrix"), is(.ldi.sp, "diagonalMatrix"), Matrix:::isSymmetricDN(.ldi.sp@Dimnames)) ## as.vector(), etc. must do NA->TRUE stopifnot(identical(as.vector(.nge), rep.int(TRUE, 4L)), identical(as.logical(.nge), rep.int(TRUE, 4L)), identical(as.double(.nge), rep.int(1, 4L)), identical(as(.nge, "vector"), rep.int(TRUE, 4L)), identical(as(.nge, "matrix"), array(TRUE, .nge@Dim)), identical(as(.nge, "dMatrix")@x, rep.int(1, 4L)), identical(nnzero(.nge), 4L)) ## symmpart() and skewpart() have been documented ## as returning matrix, _not_ Matrix z0 <- matrix((-2)^(0:3), 2L, 2L) z1 <- symmpart(z0) z2 <- skewpart(z0) stopifnot(!isS4(z1), is.matrix(z1), !isS4(z2), is.matrix(z2)) ## various Matrix() bugs in Matrix <= 1.4-1 .d0 <- new("ddiMatrix", Dim = c(1L, 1L), Dimnames = list("A", "B"), diag = "U") .d1 <- Matrix(`dimnames<-`(diag(1), list("A", "B")), doDiag = TRUE) .s0 <- new("dsyMatrix", Dim = c(1L, 1L), Dimnames = list("B", "B"), x = 1) .s1 <- Matrix(.d0, doDiag = FALSE) stopifnot(identical(.d1, .d0), identical(.s1, .s0), identical(Matrix(sparseVector(1, 1L, 3L)), new("dgTMatrix", Dim = c(3L, 1L), i = 0L, j = 0L, x = 1)), identical(Matrix(new("dgeMatrix"), sparse= TRUE, forceCheck=FALSE), new("dgCMatrix")), identical(Matrix(new("dgCMatrix"), sparse=FALSE, forceCheck=FALSE), new("dgeMatrix")), identical(Matrix(table(1)), Matrix(1)), identical(Matrix(table(1, 1, 1)), Matrix(1)), grepl("too long", vapply(alist(Matrix(0, 0.5, ), Matrix(0, , 0.5), Matrix(0, 0.0, ), Matrix(0, , 0.0)), function(e) conditionMessage(assertError(eval(e))[[1L]]), ""))) ## From: Mikael Jagan , 16 Aug 2022 validObject(x <- new("dtrMatrix", Dim = c(2L, 2L), diag = "U", x = double(4L))) x == 0 -> L x > 2 -> L. # ditto ## gave Error in validObject(.Object) : ## invalid class "ltrMatrix" object: length of x slot != prod(Dim) stopifnot(all(L == ((1:4) != 2)), all(L. == diag(2))) ## 'Same' with "Logic" instead of "Compare": x & FALSE -> L. ## gave Error in validObject(.Object) : invalid class "ltrMatrix" object stopifnot(all(L. == diag(2))) validObject(y <- new("dgCMatrix", Dim = c(0L, 6L), p = integer(7L))) y == c(0, 0) -> L2 y == rep(0,6)-> L6 ## gave Error in validObject(*): invalid class "lgCMatrix" object: slot p ... stopifnot(identical(L2, L6), is(L2, "lgCMatrix"), identical(dim(L2), c(0L, 6L))) ## .. "Logic" instead of "Compare": y & c(FALSE, FALSE) -> L2 ## gave Error in validObject(*): invalid class "lgCMatrix" object: slot p ... stopifnot(identical(L2, L6), is(L2, "lgCMatrix"), identical(dim(L2), c(0L, 6L))) ## Briefly wrong between 1.4-1 and 1.5-0 x.inf <- new("dgCMatrix", Dim = c(2L, 3L), p = c(0:2, 2L), i = 0:1, x = c(-Inf, Inf)) stopifnot(identical(is.infinite(x.inf), as(abs(x.inf) == Inf, "nMatrix"))) showProc.time() ## C-level bugs in 1.5-0, detected by full CRAN (incl. ASAN) check as(new("dgTMatrix"), "CsparseMatrix") # out-of-bounds access as(seq_len(10000), "pMatrix") # segfault ## %*% gave b %*% a prior to Matrix 1.5-2 set.seed(163006) for(i in 1:6) { x <- as(sample.int(10L), "pMatrix") y <- as(sample.int(10L), "pMatrix") stopifnot(as(x %*% y, "matrix") == as(x, "matrix") %*% as(y, "matrix")) } ## %*% forgot to set 'Dim' briefly prior to 1.5-2 x <- new("indMatrix", Dim = c(5L, 3L), perm = sample.int(3L, size = 5L, replace = TRUE)) y <- new("indMatrix", Dim = c(3L, 9L), perm = sample.int(9L, size = 3L, replace = TRUE)) validObject(x %*% y) stopifnot(all(tril(y, -1) == 0)) # was wrong in Matrix 1.5-x ## dimScale(x) (i.e., with 'd1' missing) did not work in 1.5-2; ## same with dimScale() ... set.seed(3054) V <- matrix(rlnorm(16L), 4L, 4L) stopifnot(all.equal(as(dimScale(V), "matrix"), cov2cor(V))) ## Diagonal(n, x, names=TRUE) must recycle 'x' _and_ its names p <- 6L a0 <- c(a = 0) stopifnot(identical(unname(nD <- Diagonal(n = p, x = a0, names = TRUE)), Diagonal(n = p, x = a0, names = FALSE)), identical(nD, Diagonal(n = p, x = rep(a0, p), names = TRUE))) ## Diagonal(n, names=) should also get 'Dimnames' stopifnot(identical(Diagonal(1L, names = "a")@Dimnames, list("a", "a"))) ## Diagonal(x=, names = TRUE) should get list(NULL, NULL) stopifnot(identical(Diagonal(x = a0[0L], names = TRUE)@Dimnames, list(NULL, NULL))) ## names were forgotten prior to 1.5-3 d1 <- Diagonal(1L, names = "b") stopifnot(identical(colSums(d1), c(b = 1)), identical(rowMeans(as(d1, "indMatrix")), c(b = 1))) ## na.rm was ignored prior to 1.5-3 d1 <- Diagonal(x = NaN) stopifnot(identical(colSums(d1), NaN), identical(colSums(d1, na.rm = TRUE), 0), identical(rowMeans(d1), NaN), identical(rowMeans(d1, na.rm = TRUE), NaN)) ## Matrix bug #6810 library(Matrix) x <- as(matrix(c(FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE), 4L, 2L), "RsparseMatrix") stopifnot(identical(which(x), seq_along(x)[as.vector(!is.na(x) & x)]), identical(which(x, arr.ind = TRUE, useNames = FALSE), arrayInd(which(x), dim(x), dimnames(x), useNames = FALSE))) ## drop0(give.Csparse = FALSE) R <- new("dtRMatrix", Dim = c(6L, 6L), p = 0:6, j = 0:5, x = 0+0:5) T <- as(as(R, "TsparseMatrix"), "symmetricMatrix") for(tol in 0+0:5) { i.tol <- R@x > tol stopifnot(exprs = { identical(drop0(R, tol = tol, give.Csparse = FALSE), new("dtRMatrix", Dim = c(6L, 6L), p = c(0L, cumsum(i.tol)), j = R@j[i.tol], x = R@x[i.tol])) identical(drop0(T, tol = tol, give.Csparse = FALSE), new("dsTMatrix", Dim = c(6L, 6L), i = R@j[i.tol], j = R@j[i.tol], x = R@x[i.tol])) }) } ## No-op for pattern-like sparse matrices: i1 <- new("indMatrix", Dim = c(6L, 8L), margin = 1L, perm = sample.int(8L, size = 6L, replace = TRUE)) i1.s <- as(i1, "nsparseMatrix") i1.d <- as(i1, "ndenseMatrix") stopifnot(exprs = { identical(drop0(i1 , give.Csparse = FALSE), i1) identical(drop0(i1.s, give.Csparse = FALSE), i1.s) identical(drop0(i1.d, give.Csparse = FALSE), as(i1.d, "CsparseMatrix")) }) ## Setting diagonal elements of non-square RsparseMatrix produced ## an invalid object x <- new("dgRMatrix", Dim = c(1L, 2L), p = c(0L, 0L)) diag(x) <- 1 validObject(x) ## Subassigning double to logical briefly did not change class x <- new("lgeMatrix", Dim = c(2L, 3L), x = logical(6L)) y <- new("dgeMatrix", Dim = c(2L, 3L), x = replace(double(6L), 1L, 1)) x[1L, 1L] <- 1 stopifnot(identical(x, y)) ## as(, "Matrix") was briefly a error (invalid type "list") stopifnot(identical(as(data.frame(a = 1:2, b = 3:4), "Matrix"), new("dgeMatrix", x = as.double(1:4), Dim = c(2L, 2L), Dimnames = list(NULL, c("a", "b"))))) ## tri[ul](<.t[rp]Matrix>) was often wrong at least in 1.6-1 u <- new("dtrMatrix", Dim = c(8L, 8L), x = as.double(seq_len(64L))) stopifnot(identical(triu(u, 1L), triu(as(u, "generalMatrix"), 1L))) ## more tril()/triu() woes {introduced after 2021; present till 1.6-4} for(n in 0:7) { cat("n = ", n,"\n----\n") ##TODO: for(m in pmax(0, n-3):(n+3)) { for(m in pmax(0, n-3):(n+3)) { #-- n x m matrix cat(" m = ", m,": using k's in ", (-n),":", m, "\n", sep="") symm <- (m == n) mn2 <- (mn <- m*n) %/% 2 ma <- array(seq_len(mn) - mn2 - 1/2, dim = c(n, m)) if(symm) ma <- crossprod(ma) # crossprod() to be symmetric dM <- as(as(ma, "denseMatrix"), "generalMatrix") sM <- as(as(ma, "CsparseMatrix"), "generalMatrix") for(k in (-n):m) { trum <- triuChk(ma,k); trlm <- trilChk(ma, k) trud <- triuChk(dM,k); trld <- trilChk(dM, k) trus <- triuChk(sM,k); trls <- trilChk(sM, k) if(symm) { assert.EQ( trum, t(tril(ma,-k))) assert.EQ.mat(trud, as.mat(t(tril(dM,-k)))) assert.EQ.mat(trus, as.mat(t(tril(sM,-k)))) } stopifnot(exprs = { ## matrix identical(trlm, band(ma, -n, k)) identical(trum, band(ma, k, m)) inherits(trum, "denseMatrix") # "dge" / "dtr" ... ## denseMatrix identical(trld, band(dM, -n, k)) identical(trud, band(dM, k, m)) inherits(trud, "denseMatrix") assert.EQ.Mat(trud, trum, giveRE=TRUE) ## sparseMatrix identical(trls, band(sM, -n, k)) identical(trus, band(sM, k, m)) inherits(trus, "sparseMatrix") assert.EQ.Mat(trus, trum, giveRE=TRUE) }) } } } ## Platform - and other such info -- so we find it in old saved outputs .libPaths() SysI <- Sys.info() structure(Sys.info()[c(4,5,1:3)], class="simple.list") sessionInfo() c(Matrix = packageDescription("Matrix")$Built) if(SysI[["sysname"]] == "Linux" && requireNamespace("sfsmisc")) local({ nn <- names(.Sc <- sfsmisc::Sys.cpuinfo()) nn <- names(.Sc <- .Sc[!grepl("^flags", nn)]) print(.Sc[ grep("\\.[0-9]+$", nn, invert=TRUE) ]) }) showProc.time() Matrix/tests/symmDN.R0000644000175100001440000001442614503206514014237 0ustar hornikusers## These are tests related to the centralization (since r~3454) of various ## methods for symmetrizing the (possibly asymmetric) 'Dimnames' of symmetric ## matrices. library(Matrix) if (interactive()) { options(Matrix.verbose = TRUE, warn = 1, error = recover) } else { options(Matrix.verbose = TRUE, warn = 1) } ## For getting and setting '[dD]imnames' on '[mM]atrix' DN <- function(x) { if (is(x, "Matrix")) { x@Dimnames } else { dimnames(x) } } `DN<-` <- function(x, value) { if (is(x, "Matrix")) { x@Dimnames <- value } else { dimnames(x) <- value } x } ## SDN1(dn) is documented to behave as SDN2(dn, NULL) SDN1 <- Matrix:::symDN SDN2 <- function(dn, uplo = NULL) { J <- if (is.null(uplo)) { if (!is.null(dn[[1L]]) && is.null(dn[[2L]])) 1L else 2L } else { if (uplo == "U") 2L else 1L } rep(dn[J], 2L) } ## isSDN1(dn) is documented to behave as isSDN2(dn) isSDN1 <- Matrix:::isSymmetricDN isSDN2 <- function(dn) { (is.null(ndn <- names(dn)) || !all(nzchar(ndn)) || ndn[1L] == ndn[2L]) && (is.null(rn <- dn[[1L]]) || is.null(cn <- dn[[2L]]) || isTRUE(all(rn == cn | (is.na(rn) & is.na(cn))))) } ## Various possible (a)symmetries of 'Dimnames' n <- 4L rn <- letters[seq_len(n)] cn <- LETTERS[seq_len(n)] ldn <- list(list(rn, rn), list(rn, cn), list(rn, NULL), list(NULL, cn), list(NULL, NULL), list(x = rn, rn), list(x = rn, cn), list(x = rn, NULL), list(x = NULL, cn), list(x = NULL, NULL), list(rn, y = rn), list(rn, y = cn), list(rn, y = NULL), list(NULL, y = cn), list(NULL, y = NULL), list(x = rn, y = rn), list(x = rn, y = cn), list(x = rn, y = NULL), list(x = NULL, y = cn), list(x = NULL, y = NULL)) ## 'matrix' and _most_ 'd..Matrix' ... ## zero matrices are fine for the purpose of testing handling of 'Dimnames' lM <- c(list(matrix(0, n, n), new("ddiMatrix", x = double(n), Dim = c(n, n)), new("dgeMatrix", x = double(n * n), Dim = c(n, n))), .mapply(new, expand.grid(Class = c("dsyMatrix", "dtrMatrix"), uplo = c("U", "L"), stringsAsFactors = FALSE), list(x = double(n * n), Dim = c(n, n))), .mapply(new, expand.grid(Class = c("dspMatrix", "dtpMatrix"), uplo = c("U", "L"), stringsAsFactors = FALSE), list(x = double((n * (n + 1L)) %/% 2L), Dim = c(n, n))), list(new("dgCMatrix", x = double(0L), Dim = c(n, n), i = integer(0L), p = rep.int(0L, n + 1L))), .mapply(new, expand.grid(Class = c("dsCMatrix", "dtCMatrix"), uplo = c("U", "L"), stringsAsFactors = FALSE), list(x = double(0L), Dim = c(n, n), i = integer(0L), p = rep.int(0L, n + 1L)))) ## A few dense symmetric matrices, which are _not_ symmetricMatrix ## and whose symmetry (in the sense of 'isSymmetric') should depend ## only on their 'Dimnames' slot .d <- diag(n) .lM <- list(new("dgeMatrix", x = as.vector(.d), Dim = c(n, n)), new("ltrMatrix", x = as.vector(.d != 0), Dim = c(n, n), uplo = "U"), new("ntpMatrix", x = .d[upper.tri(.d, TRUE)] != 0, Dim = c(n, n), uplo = "U")) .iS <- function(M, dn) { M@Dimnames <- dn isSymmetric(M, tol = 0, checkDN = TRUE) } for (dn in ldn) { stopifnot(identical(sdn <- SDN1(dn), SDN2(dn)), (isdn <- isSDN1(dn)) == isSDN2(dn), vapply(.lM, .iS, NA, dn = dn) == isdn) for (M in lM) { DN(M) <- dn if (is.s <- is(M, "symmetricMatrix")) { ## 'dimnames' should symmetrize stopifnot(identical(dimnames(M), sdn)) } if (is.s && !identical(dn[1L], dn[2L])) { ## Methods for 'symmetricMatrix' assume symmetric 'Dimnames' ## for efficiency ... should they? next } stopifnot(identical(DN(forceSymmetric(M)), sdn), identical(DN(symmpart(M)), sdn), identical(DN(skewpart(M)), sdn)) ## others? } } ## r3459: allowing initialization with typeof(Dimnames[[i]]) != "character" ## ... nothing to do with symmetry, but here for now ... stopifnot(identical(new("dgeMatrix", x = as.double(1:4), Dim = c(2L, 2L), Dimnames = list(1:2, as.factor(3:4))), new("dgeMatrix", x = as.double(1:4), Dim = c(2L, 2L), Dimnames = list(c("1", "2"), c("3", "4"))))) stopifnot(vapply(ldn, isSDN1, NA) == vapply(ldn, isSDN2, NA)) ## cov2cor(), dimScale() etc -- matrix-Bugs [#6783] 2022-10-23 by Ben Bolker "https://r-forge.r-project.org/tracker/?func=detail&atid=294&aid=6783&group_id=61" ## base R vs Matrix cov2cor() m <- diag(1:3) dimnames(m) <- adn <- list(LETTERS[1:3], letters[1:3]) # MM: *a*symmetric dimnames .. Md <- as(m, "denseMatrix") Ms <- as(m, "sparseMatrix") stopifnot(exprs = { identical(adn, dimnames(cov2cor(m))) identical((dn2 <- rep(adn[2], 2)), dimnames(ms <- forceSymmetric(m))) # a b c for *both* rows & cols identical( dn2, dimnames(cMd <- cov2cor(Md))) identical( dn2, dimnames(cMs <- cov2cor(Ms))) # gave error in Matrix <= 1.5-1 all.equal(as(cMd, "sparseMatrix"), cMs, tolerance=1e-15) # see even tol=0 }) dns <- rep(list(letters[1:3]), 2) m <- matrix(1:9, 3, dimnames = dns); m <- (m+t(m))/2 + 2*diag(3) # to be pos.def. m (cm <- cov2cor(m)) (cM <- cov2cor(M <- as(m, "denseMatrix"))) stopifnot(exprs = { identical(dns, dimnames(cm)) inherits(cM, "dpoMatrix") identical(dns, dimnames(cM)) inherits((cS <- cov2cor(S <- as(m, "sparseMatrix"))), "dsCMatrix") identical(dns, dimnames(cS)) all.equal(cS, dimScale(S)) all.equal(as(cM, "sparseMatrix"), cS, tolerance=2e-15) # see even tol=0 all.equal(as(cM, "dpoMatrix"), as(dimScale(M), "dpoMatrix"), tolerance=2e-15) # seen 1.665e-16 }) cat("Time elapsed:", proc.time(), "\n") # "stats" Matrix/tests/indexing.R0000644000175100001440000014004314563762457014653 0ustar hornikusers#### For both 'Extract' ("[") and 'Replace' ("[<-") Method testing #### aka subsetting and subassignment #### ~~~~~~~~~~ ~~~~~~~~~~~~~ ## for R_DEFAULT_PACKAGES=NULL : library(stats) library(utils) if(interactive()) { options(error = recover, warn = 1) } else if(FALSE) { ## MM / developer testing *manually* : options(error = recover, Matrix.verbose = 2, warn = 1) } else { options( Matrix.verbose = 2, warn = 1) } ## Matrix.verbose = .. (*before* loading 'Matrix' pkg) ## ==> will also show method dispath ambiguity messages: getOption("ambiguousMethodSelection") #### suppressPackageStartupMessages(...) as we have an *.Rout.save to Rdiff against suppressPackageStartupMessages(library(Matrix)) source(system.file("test-tools.R", package = "Matrix"), keep.source = FALSE) ##-> identical3() etc cat("doExtras:",doExtras,"\n") if(exists("Sys.setLanguage", mode="function")) Sys.setLanguage("en") englishMsgs <- (lang <- Sys.getenv("LANGUAGE")) %in% c("en", "C") cat(sprintf("LANGUAGE env.: '%s'; englishMsgs: %s\n", lang, englishMsgs)) ### Dense Matrices m <- Matrix(1:28 +0, nrow = 7) validObject(m) stopifnot(identical(m, m[]), identical(m[2, 3], 16), # simple number identical(m[2, 3:4], c(16,23)), # simple numeric of length 2 identical(m[NA,NA], as(Matrix(NA, 7,4), "dMatrix"))) m[2, 3:4, drop=FALSE] # sub matrix of class 'dgeMatrix' m[-(4:7), 3:4] # ditto; the upper right corner of 'm' ## rows or columns only: m[1,] # first row, as simple numeric vector m[,2] # 2nd column m[,1:2] # sub matrix of first two columns m[-(1:6),, drop=FALSE] # not the first 6 rows, i.e. only the 7th m[integer(0),] #-> 0 x 4 Matrix m[2:4, numeric(0)] #-> 3 x 0 Matrix ## logical indexing stopifnot(identical(m[2,3], m[(1:nrow(m)) == 2, (1:ncol(m)) == 3]), identical(m[2,], m[(1:nrow(m)) == 2, ]), identical(m[,3:4], m[, (1:4) >= 3])) ## dimnames indexing: mn <- m dimnames(mn) <- list(paste("r",letters[1:nrow(mn)],sep=""), LETTERS[1:ncol(mn)]) checkMatrix(mn) mn["rd", "D"] msr <- ms <- as(mn,"sparseMatrix") mnr <- mn v <- rev(as(ms, "vector")) mnr[] <- v msr[] <- v # [<- "sparse" -- not very sensical; did fail w/o a message z <- msr; z[] <- 0 zz <- as(array(0, dim(z)), "sparseMatrix") a.m <- as(mnr,"matrix") stopifnot(identical(mn["rc", "D"], mn[3,4]), mn[3,4] == 24, identical(mn[, "A"], mn[,1]), mn[,1] == 1:7, identical(mn[c("re", "rb"), "B"], mn[c(5,2), 2]), identical(ms["rc", "D"], ms[3,4]), ms[3,4] == 24, identical(ms[, "A"], ms[,1]), ms[,1] == 1:7, identical(ms[ci <- c("re", "rb"), "B"], ms[c(5,2), 2]), identical(rownames(mn[ci, ]), ci), identical(rownames(ms[ci, ]), ci), identical(colnames(mn[,cj <- c("B","D")]), cj), identical(colnames(ms[,cj]), cj), identical(a.m, as(msr,"matrix")), identical(unname(z), zz), identical(a.m, array(v, dim=dim(mn), dimnames=dimnames(mn))) ) showProc.time() ## Bug found thanks to Timothy Mak, Feb 3, 2017: ## sparseMatrix logical indexing with (partial) NA: a.m <- as(mn,"matrix") assert.EQ(as(ms,"matrix"), a.m) # incl. dimnames iN4 <- c(NA, TRUE, FALSE, TRUE) assert.EQ(as(mn[,iN4],"matrix"), a.m[,iN4]) # (incl. dimnames) ##assert.EQ(as.matrix(ms[,iN4]), a.m[,iN4]) # ms[, ] fails still : _FIXME_ try(ms[,iN4]) try(ms[,iN4] <- 100) ## <- segfaulted in Matrix <= 1.2-8 (!) ## R-forge Matrix bug #2556: Subsetting a sparse matrix did remove names(dimnames(.)) : m44 <- matrix(1:16, 4, 4, dimnames=list(row=c('a','b','c','d'), col=c('x','y','z','w'))) ## Dense matrix: ------------------------------------------ a <- Matrix(m44) identical( dimnames(m44[,FALSE, drop=FALSE]), dimnames( a[,FALSE, drop=FALSE])) chk.ndn <- function(a, a0=m44) stopifnot(identical(names(dimnames(a)), names(dimnames(a0)))) i <- 1:2 chk.ndn(a[i,]); chk.ndn(a[i, i]) ## Sparse matrix: ----------------------------------------- s <- as(a %% 3 == 1, "sparseMatrix") ts <- as(s,"TsparseMatrix") b <- sparseMatrix(i=1:3, j=rep(2,3), dims=c(4,4), dimnames=dimnames(s)) tb <- as(b,"TsparseMatrix") stopifnot(identical5( dimnames(a), dimnames(s), dimnames(ts), dimnames(b), dimnames(tb))) chk.ndn(b [i, i]); chk.ndn(b [i, ]) chk.ndn(s [i, i]); chk.ndn(s [i, ]) chk.ndn(tb[i, i]); chk.ndn(tb[i, ]) chk.ndn(ts[i, i]); chk.ndn(ts[i, ]) chk.ndn( b[ , 1, drop=FALSE]); chk.ndn( s[i, 2, drop=FALSE]) chk.ndn(tb[ , 1, drop=FALSE]); chk.ndn(ts[i, 2, drop=FALSE]) L0 <- logical(0) stopifnot(exprs = { identical(dim(b[,L0]), c(4L, 0L)) identical(dim(b[L0,]), c(0L, 4L)) # failed till 2019-09-x }) ## Printing sparse colnames: ms[sample(28, 20)] <- 0 ms <- t(rbind2(ms, 3*ms)) cnam1 <- capture.output(show(ms))[2] ; op <- options("sparse.colnames" = "abb3") cnam2 <- capture.output(show(ms))[2] ; options(op) # revert stopifnot(## sparse printing grep("^ +$", cnam1) == 1, # cnam1 is empty identical(cnam2, paste(" ", paste(rep(rownames(mn), 2), collapse=" ")))) mo <- m m[2,3] <- 100 m[1:2, 4] <- 200 m[, 1] <- -1 m[1:3,] m. <- as(m, "matrix") ## m[ cbind(i,j) ] indexing: iN <- ij <- cbind(1:6, 2:3) iN[2:3,] <- iN[5,2] <- NA stopifnot(identical(m[ij], m.[ij]), identical(m[iN], m.[iN])) ## testing operations on logical Matrices rather more than indexing: g10 <- m [ m > 10 ] stopifnot(18 == length(g10)) stopifnot(10 == length(m[ m <= 10 ])) sel <- (20 < m) & (m < 150) sel.<- (20 < m.)& (m.< 150) nsel <-(20 >= m) | (m >= 150) (ssel <- as(sel, "sparseMatrix")) stopifnot(is(sel, "lMatrix"), is(ssel, "lsparseMatrix"), identical3(as.mat(sel.), as.mat(sel), as.mat(ssel)), identical3(!sel, !ssel, nsel), # ! is typically dense identical3(m[ sel], m[ ssel], as(m, "matrix")[as( ssel, "matrix")]), identical3(m[!sel], m[!ssel], as(m, "matrix")[as(!ssel, "matrix")]) ) showProc.time() ## more sparse Matrices -------------------------------------- ##' @title Check sparseMatrix sub-assignment m[i,j] <- v ##' @param ms sparse Matrix ##' @param mm its [traditional matrix]-equivalent ##' @param k (approximate) length of index vectors (i,j) ##' @param n.uniq (approximate) number of unique values in i,j ##' @param vRNG function(n) for random 'v' generation ##' @param show logical; if TRUE, it will not stop on error ##' @return ##' @author Martin Maechler chkAssign <- function(ms, mm = as(ms, "matrix"), k = min(20,dim(mm)), n.uniq = k %/% 3, vRNG = { if(is.numeric(mm) || is.complex(mm)) function(n) rpois(n,lambda= 0.75)# <- about 47% zeros else ## logical function(n) runif(n) > 0.8 }, ## 80% zeros showOnly=FALSE) { stopifnot(is(ms,"sparseMatrix")) d <- dim(ms) s1 <- function(n) sample(n, pmin(n, pmax(1, rpois(1, n.uniq)))) i <- sample(s1(d[1]), k/2+ rpois(1, k/2), replace = TRUE) j <- sample(s1(d[2]), k/2+ rpois(1, k/2), replace = TRUE) assert.EQ.mat(ms[i,j], mm[i,j]) ms2 <- ms. <- ms; mm. <- mm # save ## now sub*assign* to these repeated indices, and then compare ----- v <- vRNG(length(i) * length(j)) mm[i,j] <- v ms[i,j] <- v ## useful to see (ii,ij), but confusing R/ESS when additionally debugging: ## if(!showOnly && interactive()) { op <- options(error = recover); on.exit(options(op)) } assert.EQ.mat(ms, mm, showOnly=showOnly) ## vector indexing m[cbind(i,j)] == m[i + N(j-1)] , N = nrow(.) ii <- seq_len(min(length(i), length(j))) i <- i[ii] j <- j[ii] ij <- cbind(i, j) ii <- i + nrow(ms)*(j - 1) ord.i <- order(ii) iio <- ii[ord.i] ui <- unique(iio) # compare these with : neg.ii <- - setdiff(seq_len(prod(d)), ii) stopifnot(identical(mm[ii], mm[ij]), identical(ms.[ui], ms.[neg.ii]), ms.[ij] == mm.[ii], ## M[ cbind(i,j) ] was partly broken; now checking ms.[ii] == mm.[ii]) v <- v[seq_len(length(i))] if(is(ms,"nMatrix")) v <- as.logical(v) # ! mm.[ij] <- v ms.[ii] <- v nodup <- (length(ui) == length(ii)) ## <==> ! anyDuplicated(iio) if(nodup) { cat("[-]") # rare, unfortunately ms2[neg.ii] <- v[ord.i] stopifnot(identical(ms2, ms.)) } assert.EQ.mat(ms., mm., showOnly=showOnly) } ##{chkAssign} ## Get duplicated index {because these are "hard" (and rare) getDuplIndex <- function(n, k) { repeat { i <- sample(n, k, replace=TRUE) # 3 4 6 9 2 9 : 9 is twice if(anyDuplicated(i)) break } i } suppressWarnings(RNGversion("3.5.0")); set.seed(101) m <- 1:800 m[sample(800, 600)] <- 0 m0 <- Matrix(m, nrow = 40) m1 <- add.simpleDimnames(m0) for(kind in c("n", "l", "d")) { for(m in list(m0,m1)) { ## -- with and without dimnames ------------------------- kClass <-paste0(kind, "Matrix" ) Ckind <- paste0(kind, "gCMatrix") Tkind <- paste0(kind, "gTMatrix") str(mC <- as(as(as(m, kClass), "CsparseMatrix"), "generalMatrix")) # was as(m, Ckind) deprecated #was mT <- as(as(as(m, kClass), "TsparseMatrix"), Tkind)) str(mT <- as(as(as(m, kClass), "generalMatrix"), "TsparseMatrix")) mm <- as(mC, "matrix") # also logical or double IDENT <- if(kind == "n") function(x,y) Q.eq2(x,y, tol=0) else identical stopifnot(exprs = { identical(mT, as(mC, "TsparseMatrix")) identical(mC, as(mT, "CsparseMatrix")) # was Ckind; now deprecated Qidentical(mC[0,0], new(Ckind)) # M..3 Csp..4 Qidentical(mT[0,0], new(Tkind)) # " identical(unname(mT[0,]), new(Tkind, Dim = c(0L,ncol(m))))# M.3 T.4 C.4 identical(unname(mT[,0]), new(Tkind, Dim = c(nrow(m),0L)))# M.3 C.4 is.null(cat("IDENT():\n")) IDENT(mC[0,], as(mT[FALSE,], "CsparseMatrix")) # M.3 C.4 M.3 + Tsp..4 Csp..4 | as(., Ckind) deprecated IDENT(mC[,0], as(mT[,FALSE], "CsparseMatrix")) # M.3 C.4 M.3 C.4 | as(., Ckind) deprecated is.null(cat("sapply(..):\n")) sapply(pmin(min(dim(mC)), c(0:2, 5:10)), function(k) {i <- seq_len(k); all(mC[i,i] == mT[i,i])}) }) cat("ok\n") show(mC[,1]) show(mC[1:2,]) show(mC[7, drop = FALSE]) assert.EQ.mat(mC[1:2,], mm[1:2,]) assert.EQ.mat(mC[0,], mm[0,]) assert.EQ.mat(mC[,FALSE], mm[,FALSE]) ## ## *repeated* (aka 'duplicated') indices - did not work at all ... i <- pmin(nrow(mC), rep(8:10,2)) j <- c(2:4, 4:3) assert.EQ.mat(mC[i,], mm[i,]) assert.EQ.mat(mC[,j], mm[,j]) ## FIXME? assert.EQ.mat(mC[,NA], mm[,NA]) -- mC[,NA] is all 0 "instead" of all NA ## MM currently thinks we should NOT allow [ ] assert.EQ.mat(mC[i, 2:1], mm[i, 2:1]) assert.EQ.mat(mC[c(4,1,2:1), j], mm[c(4,1,2:1), j]) assert.EQ.mat(mC[i,j], mm[i,j]) ## ## set.seed(7) op <- options(Matrix.verbose = FALSE) cat(" for(): ") for(n in 1:(if(doExtras) 50 else 5)) { # (as chkAssign() is random) chkAssign(mC, mm) chkAssign(mC[-3,-2], mm[-3,-2]) cat(".") } options(op) cat(sprintf("\n[Ok]%s\n\n", strrep("-", 64))) } cat(sprintf("\nok( %s )\n== ###%s\n\n", kind, strrep("=", 70))) }## end{for}--------------------------------------------------------------- showProc.time() if(doExtras) {### {was ./AAA_index.R, MM-only} ## an nsparse-example A <- Matrix(c(rep(c(1,0,0),2), rep(c(2,0),7), c(0,0,2), rep(0,4)), 3,9) i <- c(3,1:2) j <- c(3, 5, 9, 5, 9) vv <- logical(length(i)*length(j)); vv[6:9] <- TRUE print(An <- as(A,"nMatrix")); an <- as(An, "matrix") assert.EQ.mat(An, an) An[i, j] <- vv an[i, j] <- vv assert.EQ.mat(An, an)## error if(!all(An == an)) show(drop0(An - an)) ## all are +1 options("Matrix.subassign.verbose" = TRUE)# output from C An <- as(A,"nMatrix"); An[i, j] <- vv ## and compare with this: Al <- as(A,"lMatrix"); Al[i, j] <- vv options("Matrix.subassign.verbose" = FALSE) ##--- An interesting not small not large example for M[i,j] <- v ------------ ## M <- Matrix(c(1, rep(0,7), 1:4), 3,4) N0 <- kronecker(M,M) mkN1 <- function(M) { stopifnot(length(d <- dim(M)) == 2) isC <- is(M,"CsparseMatrix") M[,d[2]] <- c(0,2,0) N <- kronecker(diag(x=1:2), M)## remains sparse if 'M' is if(isC) N <- as(N, "CsparseMatrix") diag(N[-1,]) <- -2 N[9,] <- 1:4 # is recycled N[,12] <- -7:-9 # ditto N } show(N1 <- t(N <- mkN1(N0))) # transpose {for display reasons} C1 <- t(C <- mkN1(as(N0,"CsparseMatrix"))) stopifnot(all(C == N)) assert.EQ.mat(C, mkN1(as(N0, "matrix"))) C. <- C1 show(N <- N1) ; n <- as(N, "matrix"); str(N) sort(i <- c(6,8,19,11,21,20,10,7,12,9,5,18,17,22,13))## == c(5:13, 17:22)) sort(j <- c(3,8,6,15,10,4,14,13,16,2,11,17,7,5))## == c(2:8, 10:11, 13:17) val <- v.l <- 5*c(0,6,0,7,0,0,8:9, 0,0) show(spv <- as(val, "sparseVector")); str(spv) n [i,j] <- v.l N [i,j] <- val# is recycled, too C.[i,j] <- val assert.EQ.mat(N,n) ; stopifnot(all(C. == N)) ## and the same *again*: n [i,j] <- v.l N [i,j] <- val C.[i,j] <- val assert.EQ.mat(N,n) stopifnot(all(C. == N)) print(load(system.file("external", "symA.rda", package="Matrix"))) # "As" stopifnotValid(As, "dsCMatrix"); stopifnot(identical(As@factors, list())) R. <- drop0(chol(As)) stopifnot(exprs = { 1:32 == sort(diag(R.)) ## ! R.@x > 0 R.@x == as.integer(R.@x)## so it is an integer-valued chol-decomp ! ## shows that (1) As is *not* singular (2) the matrix is not random all.equal(crossprod(R.), As, tolerance=1e-15) }) print(summary(evA <- eigen(As, only.values=TRUE)$values)) print(tail(evA)) ## largest three ~= 10^7, smallest two *negative* print(rcond(As)) # 1.722 e-21 == very bad ! ##-> this *is* a border line case, i.e. very close to singular ! ## and also determinant(.) is rather random here! cc0 <- Cholesky(As)# no problem try({ cc <- Cholesky(As, super=TRUE) ## gives --on 32-bit only-- ## Cholmod error 'matrix not positive definite' at file:../Supernodal/t_cholmod_super_numeric.c, line 613 ecc <- expand(cc) L.P <- with(ecc, crossprod(L,P)) ## == L'P ## crossprod(L.P) == (L'P)' L'P == P'LL'P stopifnot( all.equal(crossprod(L.P), As) ) }) ##---- end{ eigen( As ) ----------- } ## only if(doExtras) ##---- Symmetric indexing of symmetric Matrix ---------- m. <- mC m.[, c(2, 7:12)] <- 0 stopifnotValid(S <- crossprod(add.simpleDimnames(m.) %% 100), "dsCMatrix") ss <- as(S, "matrix") ds <- as(S, "denseMatrix") ## NA-indexing of *dense* Matrices: should work as traditionally assert.EQ.mat(ds[NA,NA], ss[NA,NA]) assert.EQ.mat(ds[NA, ], ss[NA,]) assert.EQ.mat(ds[ ,NA], ss[,NA]) T <- as(S, "TsparseMatrix") stopifnot(identical(ds[2 ,NA], ss[2,NA]), identical(ds[NA, 1], ss[NA, 1]), identical(S, as(T, "CsparseMatrix")) ) ## non-repeated indices: i <- c(7:5, 2:4);assert.EQ.mat(T[i,i], ss[i,i]) ## NA in indices -- check that we get a helpful error message: i[2] <- NA er <- tryCatch(T[i,i], error = function(e)e) if(englishMsgs) stopifnot(as.logical(grep("indices.*sparse Matrices", er$message))) N <- nrow(T) set.seed(11) for(n in 1:(if(doExtras) 50 else 3)) { i <- sample(N, max(2, sample(N,1)), replace = FALSE) validObject(Tii <- T[i,i]) ; tTi <- t(T)[i,i] stopifnot(is(Tii, "dsTMatrix"), # remained symmetric Tsparse is(tTi, "dsTMatrix"), # may not be identical when *sorted* differently identical(as(t(Tii),"CsparseMatrix"), as(tTi,"CsparseMatrix"))) assert.EQ.mat(Tii, ss[i,i]) } b <- diag(1:2)[,c(1,1,2,2)] cb <- crossprod(b) cB <- crossprod(Matrix(b, sparse=TRUE)) a <- matrix(0, 6, 6) a[1:4, 1:4] <- cb A1 <- A2 <- Matrix(0, 6, 6)#-> ddiMatrix A1[1:4, 1:4] <- cb A2[1:4, 1:4] <- cB assert.EQ.mat(A1, a)# indeed ## "must": symmetric and sparse, i.e., ds*Matrix: stopifnot(identical(A1, A2), is(A1, "dsCMatrix")) ## repeated ones ``the challenge'' (to do smartly): j <- c(4, 4, 9, 12, 9, 4, 17, 3, 18, 4, 12, 18, 4, 9) assert.EQ.mat(T[j,j], ss[j,j]) ## and another two sets (a, A) & (a., A.) : a <- matrix(0, 6,6) a[upper.tri(a)] <- (utr <- c(2, 0,-1, 0,0,5, 7,0,0,0, 0,0,-2,0,8)) ta <- t(a); ta[upper.tri(a)] <- utr; a <- t(ta) diag(a) <- c(0,3,0,4,6,0) A <- as(Matrix(a), "TsparseMatrix") A. <- A diag(A.) <- 10 * (1:6) a. <- as(A., "matrix") ## More testing {this was not working for a long time..} set.seed(1) for(n in 1:(if(doExtras) 100 else 6)) { i <- sample(1:nrow(A), 3+2*rpois(1, lambda=3), replace=TRUE) Aii <- A[i,i] A.ii <- A.[i,i] stopifnot(class(Aii) == class(A), class(A.ii) == class(A.)) assert.EQ.mat(Aii , a [i,i]) assert.EQ.mat(A.ii, a.[i,i]) assert.EQ.mat(T[i,i], ss[i,i]) } showProc.time() stopifnot(all.equal(mC[,3], mm[,3]), identical(mC[ij], mC[ij + 0.4]), identical(mC[ij], mm[ij]), identical(mC[iN], mm[iN])) ## out of bound indexing must be detected: assertError(mC[cbind(ij[,1] - 5, ij[,2])]) assertError(mC[cbind(ij[,1], ij[,2] + ncol(mC))]) assert.EQ.mat(mC[7, , drop=FALSE], mm[7, , drop=FALSE]) identical (mC[7, drop=FALSE], mm[7, drop=FALSE]) # *vector* indexing stopifnot(dim(mC[numeric(0), ]) == c(0,20), # used to give warnings dim(mC[, integer(0)]) == c(40,0), identical(mC[, integer(0)], mC[, FALSE])) validObject(print(mT[,c(2,4)])) stopifnot(all.equal(mT[2,], mm[2,]), ## row or column indexing in combination with t() : Q.C.identical(mT[2,], t(mT)[,2]), Q.C.identical(mT[-2,], t(t(mT)[,-2])), Q.C.identical(mT[c(2,5),], t(t(mT)[,c(2,5)])) ) assert.EQ.mat(mT[4,, drop = FALSE], mm[4,, drop = FALSE]) stopifnot(identical3(mm[,1], mC[,1], mT[,1]), identical3(mm[3,], mC[3,], mT[3,]), identical3(mT[2,3], mC[2,3], 0), identical(mT[], mT), identical4( mm[c(3,7), 2:4], as.mat( m[c(3,7), 2:4]), as.mat(mT[c(3,7), 2:4]), as.mat(mC[c(3,7), 2:4])) ) x.x <- crossprod(mC) stopifnot(class(x.x) == "dsCMatrix", class(x.x. <- round(x.x / 10000)) == "dsCMatrix", identical(x.x[cbind(2:6, 2:6)], diag(x.x[2:6, 2:6], names=FALSE))) head(x.x.) # Note the *non*-structural 0's printed as "0" tail(x.x., -3) # all but the first three lines lx.x <- as(as(x.x, "lMatrix"), "symmetricMatrix") # FALSE only for "structural" 0 (l10 <- lx.x[1:10, 1:10])# "lsC" (l3 <- lx.x[1:3, ]) m.x <- as.mat(x.x) # as.mat() *drops* (NULL,NULL) dimnames stopifnot(class(l10) == "lsCMatrix", # symmetric indexing -> symmetric ! identical(as.mat(lx.x), m.x != 0), identical(as.logical(lx.x), as.logical(m.x)), identical(as.mat(l10), m.x[1:10, 1:10] != 0), identical(as.mat(l3 ), m.x[1:3, ] != 0) ) ##-- Sub*assignment* with repeated / duplicated index: A <- Matrix(0,4,3) ; A[c(1,2,1), 2] <- 1 ; A B <- A; B[c(1,2,1), 2] <- 1:3; B; B. <- B B.[3,] <- rbind(4:2) ## change the diagonal and the upper and lower subdiagonal : diag(B.) <- 10 * diag(B.) diag(B.[,-1]) <- 5* diag(B.[,-1]) diag(B.[-1,]) <- 4* diag(B.[-1,]) ; B. C <- B.; C[,2] <- C[,2]; C[1,] <- C[1,]; C[2:3,2:1] <- C[2:3,2:1] stopifnot(identical(unname(as(A, "matrix")), local({a <- matrix(0,4,3); a[c(1,2,1), 2] <- 1 ; a})), identical(unname(as(B, "matrix")), local({a <- matrix(0,4,3); a[c(1,2,1), 2] <- 1:3; a})), identical(C, drop0(B.))) ## [] <- v failed in the past T <- as(C,"TsparseMatrix"); C. <- C T[T>0] <- 21 C[C>0] <- 21 a. <- local({a <- as(C., "matrix"); a[a>0] <- 21; a}) assert.EQ.mat(C, a.) stopifnot(identical(C, as(T, "CsparseMatrix"))) ## used to fail n <- 5 ## or much larger sm <- new("dsTMatrix", i=1L, j=1L, Dim=as.integer(c(n,n)), x = 1) (cm <- as(sm, "CsparseMatrix")) sm[2,] stopifnot(sm[2,] == c(0:1, rep.int(0,ncol(sm)-2)), sm[2,] == cm[2,], sm[,3] == sm[3,], all(sm[,-(1:3)] == t(sm[-(1:3),])), # all() all(sm[,-(1:3)] == 0) ) showProc.time() ##--- "nsparse*" sub-assignment :---------- M <- Matrix(c(1, rep(0,7), 1:4), 3,4) N0 <- kronecker(M,M) Nn <- as(N0, "nMatrix"); nn <- as(Nn,"matrix") (Nn00 <- Nn0 <- Nn); nn00 <- nn0 <- nn set.seed(1) Nn0 <- Nn00; nn0 <- nn00 for(i in 1:(if(doExtras) 200 else 25)) { Nn <- Nn0 nn <- nn0 i. <- getDuplIndex(nrow(N0), 6) j. <- getDuplIndex(ncol(N0), 4) vv <- sample(c(FALSE,TRUE), length(i.)*length(j.), replace=TRUE) cat(",") Nn[i., j.] <- vv nn[i., j.] <- vv assert.EQ.mat(Nn, nn) if(!all(Nn == nn)) { cat("i=",i,":\n i. <- "); dput(i.) cat("j. <- "); dput(j.) cat("which(vv): "); dput(which(vv)) cat("Difference matrix:\n") show(drop0(Nn - nn)) } cat("k") ## sub-assign double precision to logical sparseMatrices: now *with* warning: ## {earlier: gave *no* warning}: assertWarning(Nn[1:2,] <- -pi) assertWarning(Nn[, 5] <- -pi) assertWarning(Nn[2:4, 5:8] <- -pi) stopifnotValid(Nn,"nsparseMatrix") ## cat(".") if(i %% 10 == 0) cat("\n") if(i == 100) { Nn0 <- as(Nn0, "CsparseMatrix") cat("Now: class", class(Nn0)," :\n~~~~~~~~~~~~~~~~~\n") } } showProc.time() Nn <- Nn0 ## Check that NA is interpreted as TRUE (with a warning), for "nsparseMatrix": assertWarning(Nn[ii <- 3 ] <- NA); stopifnot(isValid(Nn,"nsparseMatrix"), Nn[ii]) assertWarning(Nn[ii <- 22:24] <- NA); stopifnot(isValid(Nn,"nsparseMatrix"), Nn[ii]) assertWarning(Nn[ii <- -(1:99)] <- NA); stopifnot(isValid(Nn,"nsparseMatrix"), Nn[ii]) assertWarning(Nn[ii <- 3:4 ] <- c(0,NA)) stopifnot(isValid(Nn,"nsparseMatrix"), Nn[ii] == 0:1) assertWarning(Nn[ii <- 25:27] <- c(0,1,NA)) stopifnot(isValid(Nn,"nsparseMatrix"), Nn[ii] == c(FALSE,TRUE,TRUE)) m0 <- Diagonal(5) stopifnot(identical(m0[2,], m0[,2]), identical(m0[,1], c(1,0,0,0,0))) ### Diagonal -- Sparse: (m1 <- as(m0, "TsparseMatrix")) # dtTMatrix unitriangular (m2 <- as(m0, "CsparseMatrix")) # dtCMatrix unitriangular m1g <- as(m1, "generalMatrix") tr1 <- as(m1, "denseMatrix") # dtrMatrix unitriangular stopifnotValid(m1g, "dgTMatrix") diag(tr1) <- 100 stopifnot(diag(tr1) == 100)# failed when 'diag<-' did not recycle assert.EQ.mat(m2[1:3,], diag(5)[1:3,]) assert.EQ.mat(m2[,c(4,1)], diag(5)[,c(4,1)]) stopifnot(identical(m2[1:3,], as(m1[1:3,], "CsparseMatrix")), identical(asUniqueT(m1[, c(4,2)]), asUniqueT(m2[, c(4,2)])) )## failed in 0.9975-11 ## 0-dimensional diagonal - subsetting ---------------------------- ## before that diagU2N() etc for 0-dim. dtC*: m0. <- m00 <- matrix(numeric(),0,0) tC0.<- new("dtCMatrix") tC0 <- new("dtCMatrix", diag="U") (gC0 <- new("dgCMatrix")) # 0 x 0 D0 <- Diagonal(0) stopifnot(exprs = { identical(m0., as(tC0, "matrix")) # failed: Cholmod error 'invalid xtype' .. identical(numeric(), as(tC0, "numeric"))# " identical(numeric(), tC0[ 0 ])# --> .M.vectorSub(x, i) failed in as(., "matrix") identical(m00[TRUE ], tC0[TRUE ])# (worked already) identical(m00[FALSE], tC0[FALSE])# ditto ## identical(D0, D0[0,0]) # used to fail --> subCsp_ij (..) identical(gC0, D0[, 0]) # (ditto) --> subCsp_cols(..) identical(gC0, D0[0, ]) # " --> subCsp_rows(..) identical(D0, D0[,]) # (worked already) identical(m00[ 0 ], D0[ 0 ] )# ditto identical(m00[TRUE ], D0[TRUE ])# " identical(m00[FALSE], D0[FALSE])# " ## identical(tC0, tC0[0,0]) # failed --> subCsp_ij (..) identical(gC0, tC0[ ,0]) # " --> subCsp_cols(..) identical(gC0, tC0[0, ]) # " --> subCsp_rows(..) identical(tC0, tC0[,]) # (worked already) ## vector indexing }) expr <- quote({ ## FIXME -- both 'TRUE' and 'FALSE' should fail "out of bound",etc D0[TRUE, TRUE ] D0[ , TRUE ] D0[TRUE, ] # worked but should *NOT* tC0[TRUE, TRUE ] tC0[ , TRUE ] tC0[TRUE, ] # worked but should *NOT* ## D0[FALSE,FALSE] # fails --> subCsp_ij(..) -> intI() D0[ ,FALSE] # ditto ............ D0[FALSE, ] # ditto tC0[FALSE,FALSE] # " tC0[FALSE, ] # " tC0[ ,FALSE] # " }) EE <- lapply(expr[-1], function(e) list(expr = e, r = tryCatch(eval(e), error = identity))) exR <- lapply(EE, `[[`, "r") stopifnot(exprs = { vapply(exR, inherits, logical(1), what = "error") !englishMsgs || unique( vapply(exR, `[[`, "", "message") ) == "logical subscript too long" }) (uTr <- new("dtTMatrix", Dim = c(3L,3L), diag="U")) uTr[1,] <- 0 assert.EQ.mat(uTr, cbind(0, rbind(0,diag(2)))) M <- m0; M[1,] <- 0 Z <- m0; Z[] <- 0; z <- array(0, dim(M)) stopifnot(identical(M, Diagonal(x=c(0, rep(1,4)))), all(Z == 0), Qidentical(as(Z, "matrix"), z)) M <- m0; M[,3] <- 3 ; M ; stopifnot(is(M, "sparseMatrix"), M[,3] == 3) checkMatrix(M) M <- m0; M[1:3, 3] <- 0 ;M T <- m0; T[1:3, 3] <- 10 stopifnot(identical(M, Diagonal(x=c(1,1, 0, 1,1))), isValid(T, "triangularMatrix"), identical(T[,3], c(10,10,10,0,0))) M <- m1; M[1,] <- 0 ; M ; assert.EQ.mat(M, diag(c(0,rep(1,4))), tol=0) M <- m1; M[,3] <- 3 ; stopifnot(is(M,"sparseMatrix"), M[,3] == 3) Z <- m1; Z[] <- 0 checkMatrix(M) M <- m1; M[1:3, 3] <- 0 ;M assert.EQ.mat(M, diag(c(1,1, 0, 1,1)), tol=0) T <- m1; T[1:3, 3] <- 10; checkMatrix(T) stopifnot(is(T, "triangularMatrix"), identical(T[,3], c(10,10,10,0,0)), Qidentical(as(Z, "matrix"), z)) M <- m2; M[1,] <- 0 ; M ; assert.EQ.mat(M, diag(c(0,rep(1,4))), tol=0) M <- m2; M[,3] <- 3 ; stopifnot(is(M,"sparseMatrix"), M[,3] == 3) checkMatrix(M) Z <- m2; Z[] <- 0 M <- m2; M[1:3, 3] <- 0 ;M assert.EQ.mat(M, diag(c(1,1, 0, 1,1)), tol=0) T <- m2; T[1:3, 3] <- 10; checkMatrix(T) stopifnot(is(T, "dtCMatrix"), identical(T[,3], c(10,10,10,0,0)), Qidentical(as(Z, "matrix"), z)) showProc.time() ## "Vector indices" ------------------- asLogical <- function(x) { stopifnot(is.atomic(x)) storage.mode(x) <- "logical" x } .iniDiag.example <- expression({ D <- Diagonal(6) M <- as(D,"generalMatrix") # was "dge", now "dgC" d <- as(D,"unpackedMatrix") # "dtr" (unitri) m <- as(D,"matrix") s <- as(D,"TsparseMatrix"); N <- as(s,"nMatrix") S <- as(s,"CsparseMatrix"); C <- as(S,"nMatrix") }) eval(.iniDiag.example) i <- c(3,1,6); v <- c(10,15,20) ## (logical,value) which both are recycled: L <- c(TRUE, rep(FALSE,8)) ; z <- c(50,99) ## vector subassignment, both with integer & logical ## these now work correctly {though not very efficiently; hence warnings} m[i] <- v # the role model: only first column is affected M[i] <- v; assert.EQ.mat(M,m) # dgC D[i] <- v; assert.EQ.mat(D,m) # ddi -> dtC (new! 2019-07; was dgT) s[i] <- v; assert.EQ.mat(s,m) # dtT -> dgT S[i] <- v; assert.EQ.mat(S,m); S # dtC -> dtT -> dgT -> dgC m.L <- asLogical(m) ; assertWarning( C[i] <- v, verbose=TRUE) # warning: C is nMatrix, v not T/F assert.EQ.mat(C,m.L); validObject(C); assertWarning( N[i] <- v, verbose=TRUE) assert.EQ.mat(N,m.L); validObject(N) stopifnot(identical(D, as(as(s, "triangularMatrix"), "CsparseMatrix"))) ## logical *vector* indexing eval(.iniDiag.example) m[L] <- z; m.L <- asLogical(m) M[L] <- z; assert.EQ.mat(M,m) D[L] <- z; assert.EQ.mat(D,m) s[L] <- z; assert.EQ.mat(s,m) S[L] <- z; assert.EQ.mat(S,m) ; S ; assertWarning( C[L] <- z, verbose=TRUE); assert.EQ.mat(C,m.L) ; assertWarning( N[L] <- z, verbose=TRUE); assert.EQ.mat(N,m.L) ## indexing [i] vs [i,] --- now ok eval(.iniDiag.example) stopifnot(identical5(m[i], M[i], D[i], s[i], S[i]), identical3(as.logical(m[i]), C[i], N[i]), identical5(m[L], M[L], D[L], s[L], S[L]), identical3(as.logical(m[L]), C[L], N[L])) ## bordercase ' drop = .' *vector* indexing {failed till 2009-04-..) stopifnot(identical5(m[i,drop=FALSE], M[i,drop=FALSE], D[i,drop=FALSE], s[i,drop=FALSE], S[i,drop=FALSE]), identical3(as.logical(m[i,drop=FALSE]), C[i,drop=FALSE], N[i,drop=FALSE])) stopifnot(identical5(m[L,drop=FALSE], M[L,drop=FALSE], D[L,drop=FALSE], s[L,drop=FALSE], S[L,drop=FALSE]), identical3(as.logical(m[L,drop=FALSE]), C[L,drop=FALSE], N[L,drop=FALSE])) ## using L for row-indexing should give an error assertError(m[L,]); assertError(m[L,, drop=FALSE]) ## these did not signal an error, upto (including) 0.999375-30: assertError(s[L,]); assertError(s[L,, drop=FALSE]) assertError(S[L,]); assertError(S[L,, drop=FALSE]) assertError(N[L,]); assertError(N[L,, drop=FALSE]) ## row indexing: assert.EQ.mat(D[i,], m[i,]) assert.EQ.mat(M[i,], m[i,]) assert.EQ.mat(s[i,], m[i,]) assert.EQ.mat(S[i,], m[i,]) assert.EQ.mat(C[i,], asLogical(m[i,])) assert.EQ.mat(N[i,], asLogical(m[i,])) ## column indexing: assert.EQ.mat(D[,i], m[,i]) assert.EQ.mat(M[,i], m[,i]) assert.EQ.mat(s[,i], m[,i]) assert.EQ.mat(S[,i], m[,i]) assert.EQ.mat(C[,i], asLogical(m[,i])) assert.EQ.mat(N[,i], asLogical(m[,i])) ### --- negative indices ---------- ## 1) negative *vector* indexing eval(.iniDiag.example) i <- -(2:30) stopifnot(identical5(m[i], M[i], D[i], s[i], S[i]), identical3(as.logical(m[i]), C[i], N[i])) ## negative vector subassignment : v <- seq_along(m[i]) m[i] <- v; m.L <- asLogical(m) M[i] <- v; assert.EQ.mat(M,m) # dge D[i] <- v; assert.EQ.mat(D,m) # ddi -> dtT -> dgT s[i] <- v; assert.EQ.mat(s,m) # dtT -> dgT S[i] <- v; assert.EQ.mat(S,m); S ; assertWarning( # dtC -> dtT -> dgT -> dgC N[i] <- v, verbose=TRUE) assert.EQ.mat(N,m.L); N ; assertWarning( C[i] <- v, verbose=TRUE) assert.EQ.mat(C,m.L); C # options(warn = 2) #----------------------# NO WARNINGS from here ----------------- ## ===================== ## 2) negative [i,j] indices mc <- mC[1:5, 1:7] mt <- mT[1:5, 1:7] ## sub matrix assert.EQ.mat(mC[1:2, 0:3], mm[1:2, 0:3]) # test 0-index stopifnot(identical(mc[-(3:5), 0:2], mC[1:2, 0:2]), identical(mt[-(3:5), 0:2], mT[1:2, 0:2]), identical(mC[2:3, 4], mm[2:3, 4])) assert.EQ.mat(mC[1:2,], mm[1:2,]) ## sub vector stopifnot(identical4(mc[-(1:4), ], mC[5, 1:7], mt[-(1:4), ], mT[5, 1:7])) stopifnot(identical4(mc[-(1:4), -(2:4)], mC[5, c(1,5:7)], mt[-(1:4), -(2:4)], mT[5, c(1,5:7)])) ## mixing of negative and positive must give error assertError(mT[-1:1,]) showProc.time() ## Sub *Assignment* ---- now works (partially): mt0 <- mt nt <- as(mt, "nMatrix") mt[1, 4] <- -99 mt[2:3, 1:6] <- 0 mt m2 <- mt+mt m2[1,4] <- -200 m2[c(1,3), c(5:6,2)] <- 1:6 stopifnot(m2[1,4] == -200, as.vector(m2[c(1,3), c(5:6,2)]) == 1:6) mt[,3] <- 30 mt[2:3,] <- 250 mt[1:5 %% 2 == 1, 3] <- 0 mt[3:1, 1:7 > 5] <- 0 mt tt <- as(mt,"matrix") ii <- c(0,2,5) jj <- c(2:3,5) tt[ii, jj] <- 1:6 # 0 is just "dropped" mt[ii, jj] <- 1:6 assert.EQ.mat(mt, tt) mt[1:5, 2:6] as((mt0 - mt)[1:5,], "dsparseMatrix")# [1,5] and lines 2:3 mt[c(2,4), ] <- 0; stopifnot(as(mt[c(2,4), ],"matrix") == 0) mt[2:3, 4:7] <- 33 checkMatrix(mt) mt mc[1,4] <- -99 ; stopifnot(mc[1,4] == -99) mc[1,4] <- 00 ; stopifnot(mc[1,4] == 00) mc[1,4] <- -99 ; stopifnot(mc[1,4] == -99) mc[1:2,4:3] <- 4:1; stopifnot(as(mc[1:2,4:3], "matrix") == 4:1) mc[-1, 3] <- -2:1 # 0 should not be entered; 'value' recycled mt[-1, 3] <- -2:1 stopifnot(mc@x != 0, mt@x != 0, mc[-1,3] == -2:1, mt[-1,3] == -2:1) ## failed earlier mc0 <- mc mt0 <- as(mc0, "TsparseMatrix") m0 <- as(mc0, "matrix") set.seed(1); options(Matrix.verbose = FALSE) for(i in 1:(if(doExtras) 50 else 4)) { mc <- mc0; mt <- mt0 ; m <- m0 ev <- 1:5 %% 2 == round(runif(1))# 0 or 1 j <- sample(ncol(mc), 1 + round(runif(1))) nv <- rpois(sum(ev) * length(j), lambda = 1) mc[ev, j] <- nv m[ev, j] <- nv mt[ev, j] <- nv if(i %% 10 == 1) print(mc[ev,j, drop = FALSE]) stopifnot(as.vector(mc[ev, j]) == nv, ## failed earlier... as.vector(mt[ev, j]) == nv) validObject(mc) ; assert.EQ.mat(mc, m) validObject(mt) ; assert.EQ.mat(mt, m) } showProc.time() options(Matrix.verbose = TRUE) mc # no longer has non-structural zeros mc[ii, jj] <- 1:6 mc[c(2,5), c(3,5)] <- 3.2 checkMatrix(mc) m. <- mc mc[4,] <- 0 mc S <- as(Diagonal(5),"TsparseMatrix") H <- Hilbert(9) Hc <- as(round(H, 3), "CsparseMatrix")# a sparse matrix with no 0 ... (trH <- tril(Hc[1:5, 1:5])) stopifnot(is(trH, "triangularMatrix"), trH@uplo == "L", is(S, "triangularMatrix")) ## triangular assignment ## the slick (but inefficient in case of sparse!) way to assign sub-diagonals: ## equivalent to tmp <- `diag<-`(S[,-1], -2:1); S[,-1] <- tmp ## which dispatches to (x="TsparseMatrix", i="missing",j="index", value="replValue") diag(S[,-1]) <- -2:1 # used to give a wrong warning S <- as(S,"triangularMatrix") assert.EQ.mat(S, local({s <- diag(5); diag(s[,-1]) <- -2:1; s})) trH[c(1:2,4), c(2:3,5)] <- 0 # gave an *error* upto Jan.2008 trH[ lower.tri(trH) ] <- 0 # ditto, because of callNextMethod() m <- Matrix(0+1:28, nrow = 4) m[-3,c(2,4:5,7)] <- m[ 3, 1:4] <- m[1:3, 6] <- 0 mT <- as(m, "TsparseMatrix") stopifnot(identical(mT[lower.tri(mT)], m [lower.tri(m) ])) lM <- upper.tri(mT, diag=TRUE) mT[lM] <- 0 m[lM] <- 0 assert.EQ.mat(mT, as(m,"matrix")) mT[lM] <- -1:0 m[lM] <- -1:0 assert.EQ.mat(mT, as(m,"matrix")) (mT <- drop0(mT)) i <- c(1:2, 4, 6:7); j <- c(2:4,6) H[i,j] <- 0 (H. <- round(as(H, "sparseMatrix"), 3)[ , 2:7]) Hc. <- Hc Hc.[i,j] <- 0 ## now "works", but setting "non-structural" 0s stopifnot(as(Hc.[i,j], "matrix") == 0) Hc.[, 1:6] ## an example that failed for a long time sy3 <- new("dsyMatrix", Dim = as.integer(c(2, 2)), x = c(14, -1, 2, -7)) checkMatrix(dm <- kronecker(Diagonal(2), sy3))# now sparse with new kronecker dm <- Matrix(as(dm, "matrix"))# -> "dsyMatrix" (s2 <- as(dm, "sparseMatrix")) checkMatrix(st <- as(s2, "TsparseMatrix")) stopifnot(is(s2, "symmetricMatrix"), is(st, "symmetricMatrix")) checkMatrix(s.32 <- st[1:3,1:2]) ## 3 x 2 - and *not* dsTMatrix checkMatrix(s2.32 <- s2[1:3,1:2]) I <- c(1,4:3) stopifnot(is(s2.32, "generalMatrix"), is(s.32, "generalMatrix"), identical(as.mat(s.32), as.mat(s2.32)), identical3(dm[1:3,-1], asD(s2[1:3,-1]), asD(st[1:3,-1])), identical4(2, dm[4,3], s2[4,3], st[4,3]), identical3(diag(dm), diag(s2), diag(st)), is((cI <- s2[I,I]), "dsCMatrix"), is((tI <- st[I,I]), "dsTMatrix"), identical4(as.mat(dm)[I,I], as.mat(dm[I,I]), as.mat(tI), as.mat(cI)) ) ## now sub-assign and check for consistency ## symmetric subassign should keep symmetry st[I,I] <- 0; checkMatrix(st); stopifnot(is(st,"symmetricMatrix")) s2[I,I] <- 0; checkMatrix(s2); stopifnot(is(s2,"symmetricMatrix")) ## m <- as.mat(st) m[2:1,2:1] <- 4:1 st[2:1,2:1] <- 4:1 s2[2:1,2:1] <- 4:1 stopifnot(identical(m, as.mat(st)), 1:4 == as.vector(s2[1:2,1:2]), identical(m, as.mat(s2))) ## now a slightly different situation for 's2' (had bug) s2 <- as(dm, "sparseMatrix") s2[I,I] <- 0; diag(s2)[2:3] <- -(1:2) stopifnot(is(s2,"symmetricMatrix"), diag(s2) == c(0:-2,0)) t2 <- as(s2, "TsparseMatrix") m <- as.mat(s2) s2[2:1,2:1] <- 4:1 t2[2:1,2:1] <- 4:1 m[2:1,2:1] <- 4:1 assert.EQ.mat(t2, m) assert.EQ.mat(s2, m) ## and the same (for a different s2 !) s2[2:1,2:1] <- 4:1 t2[2:1,2:1] <- 4:1 assert.EQ.mat(t2, m)# ok assert.EQ.mat(s2, m)# failed in 0.9975-8 showProc.time() ## sub-assign RsparseMatrix -- Matrix bug [#6709] by David Cortes ## https://r-forge.r-project.org/tracker/?func=detail&atid=294&aid=6709&group_id=61 ## simplified by MM X <- new("dgCMatrix", i = c(0L,3L), p = c(0L,2L,2L,2L), x = c(100, -20), Dim = c(12L,3L)) R <- as(X, "RsparseMatrix") T <- as(R, "TsparseMatrix") T[, 2] <- 22 # works fine R[, 2] <- 22 # failed, as it called replTmat() giving narg() == 3 ## now R is Tsparse (as documented on ../man/RsparseMatrix-class.Rd), identical(R, T) ## but as this may change, rather R & T should have the same *content* assert.EQ.Mat(R, T) ## m[cbind(i,j)] <- value: (2-column matrix subassignment): ------------------------- m.[ cbind(3:5, 1:3) ] <- 1:3 stopifnot(m.[3,1] == 1, m.[4,2] == 2) nt. <- nt ; nt[rbind(2:3, 3:4, c(3,3))] <- FALSE s. <- m. ; m.[cbind(3,4:6)] <- 0 ## assigning 0 where there *is* 0 .. stopifnot(identical(nt.,nt), ## should not have changed identical(s., m.)) x.x[ cbind(2:6, 2:6)] <- 12:16 stopifnot(isValid(x.x, "dsCMatrix"), 12:16 == as.mat(x.x)[cbind(2:6, 2:6)]) (ne1 <- (mc - m.) != 0) stopifnot(identical(ne1, 0 != abs(mc - m.))) (ge <- m. >= mc) # contains "=" -> result is dense ne. <- mc != m. # was wrong (+ warning) stopifnot(identical(!(m. < mc), m. >= mc), identical(m. < mc, as(!ge, "sparseMatrix")), identical(ne., drop0(ne1))) d6 <- Diagonal(6) ii <- c(1:2, 4:5) d6[cbind(ii,ii)] <- 7*ii stopifnot(is(d6, "ddiMatrix"), identical(d6, Diagonal(x=c(7*1:2,1,7*4:5,1)))) sclass <- function(obj) as.vector(class(obj)) # as.v*(): drop attr(*,"package") show2cls <- function(C,D, chr = "") cat(sprintf("%s & %s%s: %s %s\n", deparse(substitute(C)), deparse(substitute(D)), chr, sclass(C), sclass(D))) for(j in 2:6) { ## even and odd j used to behave differently cat("j = ", j, ":\n-------\n") M <- Matrix(0, j,j); m <- matrix(0, j,j) T <- as(M, "TsparseMatrix") TG <- as(T, "generalMatrix") G <- as(M, "generalMatrix"); show2cls(TG, G) stopifnot(is(TG, "TsparseMatrix"), is(G, "CsparseMatrix")) id <- cbind(1:j,1:j) i2 <- cbind(1:j,j:1) m[id] <- 1:j M[id] <- 1:j T[id] <- 1:j ; show2cls(M, T,' ("diag")') stopifnot(is(M, "diagonalMatrix"), # since 2019-07 // FIXME (?!) for j=1 is(T,"triangularMatrix"), isDiagonal(T)) # was "symmetricMatrix" G[id] <- 1:j TG[id]<- 1:j m[i2] <- 10 M[i2] <- 10 T[i2] <- 10 ; show2cls(M, T,' ("symm")') G[i2] <- 10 TG[i2]<- 10 ## assert.EQ.mat(M, m) assert.EQ.mat(T, m) assert.EQ.mat(G, m) assert.EQ.mat(TG,m) } ## drop, triangular, ... (M3 <- Matrix(upper.tri(matrix(, 3, 3)))) # ltC; indexing used to fail T3 <- as(M3, "TsparseMatrix") stopifnot(identical(drop(M3), M3), identical4(drop(M3[,2, drop = FALSE]), M3[,2, drop = TRUE], drop(T3[,2, drop = FALSE]), T3[,2, drop = TRUE]), is(T3, "triangularMatrix"), !is(T3[,2, drop=FALSE], "triangularMatrix") ) (T6 <- as(as(as(kronecker(Matrix(c(0,0,1,0),2,2), t(T3)), "lMatrix"), "triangularMatrix"), "TsparseMatrix")) T6[1:4, -(1:3)] # failed (trying to coerce back to ltTMatrix) stopifnot(identical(T6[1:4, -(1:3)][2:3, -3], spMatrix(2,2, i=c(1,2,2), j=c(1,1,2), x=rep(TRUE,3)))) M <- Diagonal(4); M[1,2] <- 2 M. <- as(M, "CsparseMatrix") (R <- as(M., "RsparseMatrix")) (Ms <- symmpart(M.)) Rs <- as(Ms, "RsparseMatrix") stopifnot(isValid(M, "triangularMatrix"), isValid(M.,"triangularMatrix"), isValid(Ms, "dsCMatrix"), isValid(R, "dtRMatrix"), isValid(Rs, "dsRMatrix") ) stopifnot(dim(M[2:3, FALSE]) == c(2,0), dim(R[2:3, FALSE]) == c(2,0), identical(M [2:3,TRUE], M [2:3,]), identical(M.[2:3,TRUE], M.[2:3,]), identical(R [2:3,TRUE], R [2:3,]), dim(R[FALSE, FALSE]) == c(0,0)) n <- 50000L Lrg <- new("dgTMatrix", Dim = c(n,n)) diag(Lrg) <- 1:n dLrg <- as(Lrg, "diagonalMatrix") stopifnot(identical(Diagonal(x = 1:n), dLrg)) diag(dLrg) <- 1 + diag(dLrg) Clrg <- as(Lrg,"CsparseMatrix") Ctrg <- as(Clrg, "triangularMatrix") diag(Ctrg) <- 1 + diag(Ctrg) stopifnot(identical(Diagonal(x = 1+ 1:n), dLrg), identical(Ctrg, as(dLrg,"CsparseMatrix"))) cc <- capture.output(show(dLrg))# show() used to error for large n showProc.time() ## FIXME: "dspMatrix" (symmetric *packed*) not going via "matrix" ## Large Matrix indexing / subassignment ## ------------------------------------- (from ex. by Imran Rashid) n <- 7000000 m <- 100000 nnz <- 20000 op <- options(Matrix.verbose = 2, warn = 1) set.seed(12) f <- sparseMatrix(i = sample(n, size=nnz, replace=TRUE), j = sample(m, size=nnz, replace=TRUE)) str(f) dim(f) # 6999863 x 99992 prod(dim(f)) # 699930301096 == 699'930'301'096 (~ 700'000 millions) str(thisCol <- f[,5000])# logi [~ 7 mio....] sv <- as(thisCol, "sparseVector") str(sv) ## "empty" ! validObject(spCol <- f[,5000, drop=FALSE]) # "empty" [n x 1] ngCmatrix ## ## *not* identical(): as(spCol, "sparseVector")@length is "double"prec: stopifnot(all.equal(as(spCol, "sparseVector"), as(sv, "nsparseVector"), tolerance=0)) if(interactive()) selectMethod("[<-", c("ngCMatrix", "missing","numeric", "logical")) # -> replCmat() in ../R/Csparse.R f[,5762] <- thisCol # now "fine" and fast thanks to replCmat() --> replCmat4() fx <- sparseMatrix(i = sample(n, size=nnz, replace=TRUE), j = sample(m, size=nnz, replace=TRUE), x = round(10*rnorm(nnz))) class(fx)## dgCMatrix fx[,6000] <- (tC <- rep(thisCol, length.out=nrow(fx)))# fine thCol <- fx[,2000] fx[,5762] <- thCol# fine stopifnot(is(f, "ngCMatrix"), is(fx, "dgCMatrix"), identical(thisCol, f[,5762]),# perfect identical(as.logical(fx[,6000]), tC), identical(thCol, fx[,5762])) showProc.time() options(op)# revert ## if(doExtras) {#----------------------------------------------------------------- cat("checkMatrix() of all: \n---------\n") Sys.setlocale("LC_COLLATE", "C")# to keep ls() reproducible for(nm in ls()) if(is(.m <- get(nm), "Matrix")) { cat(nm, "\n") checkMatrix(.m, verbose = FALSE , doDet = nm != "As" ## <- "As" almost singular <=> det() "ill posed" ) } showProc.time() }#--------------end if(doExtras) ----------------------------------------------- ## Bugs found by Peter Ralph n <- 17 x <- Matrix(0, n,n) # "ddiMatrix" now ## x must have at least three nonzero entries x[1,1] <- x[2,1:2] <- 1.; class(x) # "dtC" x0 <- x <- as(x,"generalMatrix") # if x is dgCMatrix, no error ## z <- matrix(x) # <== not the "Matrix way": a (n, 1) matrix z[1] <- 0 x[1:n, 1:n] <- as(z, "sparseVector") ## gave Error: ... invalid subscript type 'S4' x2 <- x dim(zC <- as(z, "CsparseMatrix")) x <- x0 x[] <- zC # did fail, then gave warning. x1 <- x ## x <- x0 x[] <- as(zC, "sparseVector") # did fail, too x2 <- x stopifnot(identical(x1,x2)) x <- as(x0, "matrix") x[] <- z assert.EQ.mat(x1, x) i <- 4:7 x1 <- x0; x1[cbind(i, i+10)] <- i^2 x2 <- x0; x2[cbind(i, i+10)] <- as(i^2, "matrix") ## failed: nargs() = 4 ... please report class(x1) # was "dgT", now "dgC" stopifnot(isValid(x1, class(x1)), identical(x1, x2)) showProc.time() ## check valid indexing (using *random* indices, often duplicated): chk_dsp_ind <- function(sv, n=512, negI = FALSE, verbose=FALSE) { stopifnot(inherits(sv, "dsparseVector"), n >= 1) d <- length(sv) ## lambda=2 ==> aiming for short 'i' {easier to work with} P <- rpois(n, lambda = if(negI) 5 else 2) for(i in seq_len(n)) { I <- if(negI) { # negative indices: 2 are, 4 neither ... always "valid" !! k <- max(4L, d - max(1L, P[i])) if(verbose) cat(sprintf("size=k = %2d: ", k)) - sort(sample.int(d, size=k))# replace=FALSE } else sample.int(d, size=1L+P[i], replace=TRUE) ## validObject(ss <- sv[I]) # Error if not true } invisible() } s <- as(c(3,5,6), "sparseVector") set.seed(11); chk_dsp_ind(s) set.seed(3) (s2 <- as(rsparsematrix(ncol=1, nrow=37, density=1/4),"sparseVector")) (s3 <- as(rsparsematrix(ncol=1, nrow=64, density=1/4),"sparseVector")) set.seed(1) chk_dsp_ind(s2) chk_dsp_ind(s3) ## set.seed(47) ## system.time(e.N2 <- chk_dsp_ind(s2, negI=TRUE, verbose=TRUE)) chk_dsp_ind(s2, negI=TRUE) chk_dsp_ind(s3, negI=TRUE) iv <- c(rep(0,100), 3, 0,0,7,0,0,0) sv0 <- sv <- as(iv, "sparseVector") sv.0 <- sv. <- as(as.integer(iv), "sparseVector") stopifnot(canCoerce("integer", "sparseVector")) sv2 <- as(sv, "isparseVector") stopifnot(validObject(sv), validObject(sv2), identical(sv., sv2), sv == sv.) n0 <- sv. != 0 # -> is "lsparseV.." sv [n0] <- sv [n0] sv.[n0] <- sv.[n0] # gave error stopifnot(identical(sv , sv0), identical(sv., sv.0)) sv [3:7] <- 0 sv.[3:7] <- 0L stopifnot(identical(sv , sv0), identical(sv., sv.0)) sv [2:4] <- 2:4 sv.[2:4] <- 2:4 stopifnot(which(sv != 0) == (which(sv. != 0) -> in0), in0 == c(2:4, 101L, 104L)) sv [2:6] <- 0L sv.[2:6] <- 0L stopifnot(identical(sv , sv0), identical(sv., sv.0)) ## the next six *all* gave an error -- but should be no-op's: for(vv in list(sv, sv.0)) for(ind in list(0, FALSE, logical(length(vv)))) vv[ind] <- NA stopifnot(identical(sv , sv0), identical(sv., sv.0)) ## [i] <- val -- failed to resort @i sometimes: (R-forge Matrix bug #6659) y1 <- sparseVector(1:3, 13:15, 16) y2 <- sparseVector(1:6, c(5, 6, 7, 9, 14, 15), 16) i <- 1:16*12 # 12 24 36 ... 192 x <- sparseVector(numeric(1), 1, length=200) x[i] <- y1 ; validObject(x[i]) # TRUE N <- x[i] + y2 ; validObject( N ) # TRUE x[i] <- N ## <== bug was here .. validObject(x) ## gave 'Error' invalid .."dsparseVector".. 'i' must be sorted strictly increasingly stopifnot(all.equal(x[i] , y1+y2, tolerance=0), x[i] == y1+y2) showProc.time() if(!interactive()) warnings() ## [matrix-Bugs][#6720] Subsetting with empty indices does not drop -- 17 Apr 2021, by David Cortes ## https://r-forge.r-project.org/tracker/?func=detail&atid=294&aid=6720&group_id=61 ## extended by MM to all versions of "empty" : x <- c(1,8) (m1 <- rbind(x)) m1[] # remains matrix m1[,,drop=FALSE] # ditto m1[,] # [1] 1 2 -- drops (as default drop=TRUE !) ## Sparse Matrix and actually *any* Matrix-extending class did not work (M1 <- as(m1, "denseMatrix")) # "dgeMatrix" S1 <- as(m1, "CsparseMatrix") R1 <- as(m1, "RsparseMatrix") stopifnot(exprs = { identical(M1[], M1) # remains identical(S1[], S1) # remains identical(R1[], R1) # remains identical(M1[,,drop=FALSE], M1) # ditto identical(S1[,,drop=FALSE], S1) # " identical(R1[,,drop=FALSE], R1) # " ## but drop=TRUE which is the *default* much be obeyed (also for *empty* (i,j): identical(m1[,], x) identical(M1[,], x) # should drop, but did not identical(S1[,], x) # " identical(R1[,], x) # " identical(m1[,,drop=TRUE], x) identical(M1[,,drop=TRUE], x) # should drop, but did not identical(S1[,,drop=TRUE], x) # " identical(R1[,,drop=TRUE], x) # " }) ## [matrix-Bugs][#6721] Assignment to 'dgRMatrix' with missing index takes only first element ## MM: This has been fixed already! X <- rbind(0, 1:3, 0, c(0,1,0)) Rx <- as(X, "RsparseMatrix") Cx <- as(X, "CsparseMatrix") X [2,] <- 0 Cx[2,] <- 0 Rx[2,] <- 0 stopifnot(all(Cx == X), all(Rx == X)) ## [matrix-Bugs][#6745] show() ## NB: is from a bug in head(*); *only* applies to *empty* sparseV: length(x@i) == 0 op <- options(max.print=999) ( s0 <- sparseVector(i=integer(), length=2^33)) # show -> head() failed in Matrix <= 1.3-* (xs0 <- sparseVector(i=integer(), length=2^33, x = numeric()))# ditto options(op); tail(s0) ; tail(xs0) # (always worked) ## *related* bug in `[` --> needed to fix intIv() for such large sparseVectors stopifnot(exprs = { identical(s0[length(s0) - 3:0], # gave Error in if (any(i < 0L)) { : missing value .... new("nsparseVector", i=integer(), length=4L)) identical(xs0[length(s0) - 3:0], # gave Error .. new("dsparseVector", i=integer(), length=4L)) }) ## Yielded an invalid object in Matrix <= 1.4-1, instead of throwing error llc04 <- new("dgCMatrix", Dim = c(4L, 0L)) c40 <- new("dgCMatrix", Dim = c(0L, 4L), p = integer(5L)) assertError(c04[1L, ] <- 1) assertError(c40[, 1L] <- 1) ## Indexing with nMatrix rather than lMatrix set.seed(3601) gC <- rsparsematrix(6, 6, 0.6) gC@x[sample.int(length(gC@x), 6L)] <- NA ni <- is.na(gC) li <- as(ni, "lMatrix") stopifnot(identical(gC[ ni], gC[ li]), identical(gC[!ni], gC[!li])) ## Dispatch thinko in Matrix <= 1.5-4 R0 <- R. <- new("dgRMatrix", Dim = c(12L, 12L), p = c(0L, 0L, 4L, 5L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 16L), j = c(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 7L, 8L, 4L, 7L, 9L, 9L, 10L, 11L), x = as.double(1:16)) R.[1:2, ] <- R.[1:2, ] # was an error stopifnot(identical(R0, as(R., "RsparseMatrix"))) ## Didn't drop dimensions ... stopifnot(identical(t(as(1:6,"CsparseMatrix"))[TRUE, ], as.double(1:6))) ## Was briefly wrong prior to Matrix 1.6-0 set.seed(0) S <- new("dsyMatrix", Dim = c(4L, 4L), x = rnorm(16L)) Sii <- S[4:1, 4:1] stopifnot(exprs = { is(Sii, "dsyMatrix") Sii@uplo == "L" identical(as(Sii, "matrix"), as(S, "matrix")[4:1, 4:1]) }) ## Bug #6839: regression in <.s[CT]Matrix>[] in Matrix 1.6-z x <- new("dsCMatrix", Dim = c(4L, 4L), p = cumsum(0:4), i = sequence(1:4) - 1L, x = as.double(1:10)) i <- c(TRUE, FALSE) xi <- as(x, "matrix")[i] for(cl in paste0(c("C", "R", "T"), "sparseMatrix")) stopifnot(identical(as(x, cl)[i], xi)) Matrix/tests/other-pkgs.R0000644000175100001440000001146414473555676015140 0ustar hornikusers####--------- Test interfaces to other non-standard Packages --------------- ## for R_DEFAULT_PACKAGES=NULL : library(grDevices) library(stats) library(utils) library(Matrix) source(system.file("test-tools.R", package = "Matrix"))# identical3() etc MatrixRversion <- pkgRversion("Matrix") ###-- 1) 'graph' (from Bioconductor) --------------------------- ###-- == ======= --------------------------- if(requireNamespace("graph")) { if(packageVersion("graph") <= "1.10.2") { ## graph 1.10.x for x <= 2 had too many problems as(, "matrix") cat("Version of 'graph' is too old --- no tests done here!\n") } else if(pkgRversion("graph") != MatrixRversion) { cat(sprintf("The R version (%s) of 'graph' installation differs from the Matrix one (%s)\n", pkgRversion("graph"), MatrixRversion)) } else { ## do things if(doPdf <- !dev.interactive(orNone = TRUE)) pdf("other-pkgs-graph.pdf") ## 0) Simplest non-trivial graph: has no weights: g0 <- graph::graphNEL(paste(1:2), edgeL=list("1"="2"), "directed") m0 <- as(g0, "Matrix") stopifnot(is(m0,"ngCMatrix"), dim(m0) == c(2,2), which(m0) == 3) g. <- as(m0, "graph") ## failed in Matrix <= 1.1-0 m. <- as(g., "Matrix") stopifnot( identical(m., m0) ) ## but (g0, g.) differ: the latter has '1' weights ## 1) undirected V <- LETTERS[1:4] edL <- vector("list", length=4) names(edL) <- V ## 1a) unweighted for(i in 1:4) edL[[i]] <- list(edges = 5-i) gR <- new("graphNEL", nodes=V, edgeL=edL) str(graph::edges(gR)) sm.g <- as(gR, "sparseMatrix") str(sm.g) ## dgC: TODO: want 'ds.' (symmetric) validObject(sm.g) show( sm.g )## (incl colnames !) ## 1b) weighted set.seed(123) for(i in 1:4) edL[[i]] <- list(edges = 5-i, weights=runif(1)) gRw <- new("graphNEL", nodes=V, edgeL=edL) str(graph::edgeWeights(gRw)) sm.gw <- as(gRw, "sparseMatrix") str(sm.gw) ## *numeric* dgCMatrix validObject(sm.gw) show( sm.gw )## U[0,1] numbers in anti-diagonal ## 2) directed gU <- gR; graph::edgemode(gU) <- "directed" sgU <- as(gU, "sparseMatrix") str(sgU) ## 'dgC' validObject(sgU) show( sgU ) ## Reverse : sparseMatrix -> graph sm.g[1,2] <- TRUE gmg <- as(sm.g, "graph") validObject(gmg2 <- as(sm.g, "graphNEL")) gmgw <- as(sm.gw, "graph") validObject(gmgw2 <- as(sm.gw, "graphNEL")) gmgU <- as(sgU, "graph") validObject(gmgU2 <- as(sgU, "graphNEL")) stopifnot(identical(gmg, gmg2), identical(gmgw, gmgw2), identical(gmgU, gmgU2)) data(CAex, package = "Matrix") cc <- crossprod(CAex) ## work around bug in 'graph': diagonal must be empty: diag(cc) <- 0; cc <- drop0(cc) image(cc) gg <- as(cc, "graph") ## Don't run on CRAN and don't trigger 'R CMD check' : if(doExtras && match.fun("requireNamespace")("Rgraphviz")) get("plot", asNamespace("Rgraphviz"), mode = "function")(gg, "circo") stopifnot(all.equal(graph::edgeMatrix(gg), rbind(from = c(rep(1:24, each=2), 25:48), to = c(rbind(25:48,49:72), 49:72)))) if(doPdf) dev.off() } # {else} } # end{graph} ###-- 2) 'SparseM' --------------------------------------------- ###-- == ========= --------------------------------------------- if(requireNamespace("SparseM")) { if(pkgRversion("SparseM") != MatrixRversion) { cat(sprintf("The R version (%s) of 'SparseM' installation differs from the Matrix one (%s)\n", pkgRversion("SparseM"), MatrixRversion)) } else { ## do things set.seed(1) a <- round(rnorm(5*4), 2) a[abs(a) < 0.7] <- 0 A <- matrix(a,5,4) print(M <- Matrix(A)) stopifnot( validObject(A.csr <- SparseM::as.matrix.csr(A)), validObject(At.csr <- SparseM::as.matrix.csr(t(A))), validObject(A.csc <- SparseM::as.matrix.csc(A)), identical(At.csr, t(A.csr)), identical(A, as.matrix(A.csr)), identical(A.csr, as(M, "matrix.csr")), identical(A.csc, as(M, "matrix.csc")), identical3(M, as(A.csr, "CsparseMatrix"), as(A.csr, "dgCMatrix")), identical(t(M), as(At.csr, "CsparseMatrix")) ) ## More tests, notably for triplets A.coo <- SparseM::as.matrix.coo(A) str(T <- as(M, "TsparseMatrix")) # has 'j' sorted str(T. <- as(A.coo, "TsparseMatrix")) # has 'i' sorted T3 <- as(as(T, "matrix.coo"), "Matrix") # dgT M3 <- as(A.csr, "Matrix") # dgC M4 <- as(A.csc, "Matrix") # dgC M5 <- as(as(M, "matrix.coo"), "Matrix") # dgT stopifnot(identical4(asUniqueT(T ), asUniqueT(T.), asUniqueT(T3), asUniqueT(M5)), identical3(M, M3, M4)) } # {else} } # end{SparseM} Matrix/tests/dg_Matrix.R0000644000175100001440000000701614473555676014771 0ustar hornikusers## for R_DEFAULT_PACKAGES=NULL : library(stats) library(utils) library(Matrix) source(system.file("test-tools.R", package = "Matrix")) data(KNex, package = "Matrix") mm <- KNex$mm stopifnot(##is(mm) == c("dgCMatrix", "dMatrix", "Matrix"), dim(mm) == (dm <- c(1850, 712)), identical(dimnames(mm), list(NULL,NULL))) str(mm) tmm <- t(mm) str(tmm) str(mTm <- crossprod(mm)) mmT <- crossprod(tmm) mmT. <- tcrossprod(mm) stopifnot(all.equal(mmT, mmT.)) ## Previously these were not the same ## Should be the same but not quite: even length( * @ x ) differs! ##str(mmT, max=2)# much larger than mTm (i.e less sparse) ##str(mmT., max=2)# x slot is currently slightly larger --> improve tcrossprod()? ##system.time(ae <- all.equal(as(mmT.,"matrix"), as(mmT,"matrix"), tolerance = 1e-14)) ## 4-5 seconds on a 850 MHz, P III ##stopifnot(ae) stopifnot(validObject(tmm), dim(tmm) == dm[2:1], validObject(mTm), dim(mTm) == dm[c(2,2)], validObject(mmT), dim(mmT) == dm[c(1,1)], identical(as(tmm, "matrix"), t(as(mm, "matrix")))) ## from a bug report by Guissepe Ragusa RNGversion("3.6.0")# future proof set.seed(101) for(i in 1:10) { A <- matrix(rnorm(400), nrow = 100, ncol = 4) A[A < +1] <- 0 ; Am <- A Acsc <- as(Am, "CsparseMatrix") A <- as(Am, "unpackedMatrix") b <- matrix(rnorm(400), nrow = 4, ncol = 100) B <- as(b, "unpackedMatrix") assert.EQ.mat(A %*% B, Am %*% b) assert.EQ.mat(B %*% A, b %*% Am) stopifnot(identical(A, as(Acsc, "unpackedMatrix")), identical(Acsc, as(A, "CsparseMatrix")), is.all.equal4(A %*% B, Acsc %*% B, A %*% b, Acsc %*% b), is.all.equal4(b %*% A, b %*% Acsc, B %*% A, B %*% Acsc)) } ###--- dgTMatrix {was ./dgTMatrix.R } ------- ### Use ``non-unique'' versions of dgTMatrix objects N <- 200 set.seed(1) i <- as.integer(round(runif (N, 0, 100))) j <- as.integer(3* rpois (N, lambda=15)) x <- round(rnorm(N), 2) which(duplicated(cbind(i,j))) # 8 index pairs are duplicated m1 <- new("dgTMatrix", Dim = c(max(i)+1:1, max(j)+1:1), i = i, j = j, x = x) mc <- as(m1, "CsparseMatrix") m2 <- as(mc, "TsparseMatrix")## the same as 'm1' but without duplicates stopifnot(!isTRUE(all.equal.default(m1, m2)), all.equal(as(m1,"matrix"), as(m2,"matrix"), tolerance =1e-15), all.equal(crossprod(m1), crossprod(m2), tolerance =1e-15), identical(mc, as(m2, "CsparseMatrix"))) ### -> uniq* functions now in ../R/Auxiliaries.R (t2 <- system.time(um2 <- asUniqueT(m1))) stopifnot(identical(m2,um2)) ### -> error/warning condition for solve() of a singular matrix (Barry Rowlingson) (M <- Matrix(0+ 1:16, ncol = 4)) assertError(solve(M), verbose=TRUE)## ".. computationally singular" + warning + caches LU assertError(solve(t(M))) options(warn=2) # no more warnings allowed from here lum <- lu(M, warnSing=FALSE) stopifnot(is(fLU <- M@factors[["denseLU"]], "MatrixFactorization"), identical(lum, fLU)) (e.lu <- expand(fLU)) M2 <- with(e.lu, P %*% L %*% U) assert.EQ.mat(M2, as(M, "matrix")) ## now the sparse LU : M. <- as(M,"sparseMatrix") tt <- try(solve(M.)) # less nice: factor is *not* cached ## use a non-singular one: M1 <- M. + 0.5*Diagonal(nrow(M.)) luM1 <- lu(M1) d1 <- determinant(as(M1,"denseMatrix")) stopifnot(identical(luM1, M1@factors[["sparseLU~"]]), diag(luM1@L) == 1,# L is *unit*-triangular all.equal(log(-prod(diag(luM1@U))), c(d1$modulus))) cat('Time elapsed: ', proc.time(),'\n') # for ``statistical reasons'' Matrix/tests/indexing.Rout.save0000644000175100001440000027702714563762457016355 0ustar hornikusers R version 4.3.2 Patched (2024-02-13 r85897) -- "Eye Holes" Copyright (C) 2024 The R Foundation for Statistical Computing Platform: aarch64-apple-darwin22.6.0 (64-bit) R is free software and comes with ABSOLUTELY NO WARRANTY. You are welcome to redistribute it under certain conditions. Type 'license()' or 'licence()' for distribution details. R is a collaborative project with many contributors. Type 'contributors()' for more information and 'citation()' on how to cite R or R packages in publications. Type 'demo()' for some demos, 'help()' for on-line help, or 'help.start()' for an HTML browser interface to help. Type 'q()' to quit R. > #### For both 'Extract' ("[") and 'Replace' ("[<-") Method testing > #### aka subsetting and subassignment > #### ~~~~~~~~~~ ~~~~~~~~~~~~~ > > ## for R_DEFAULT_PACKAGES=NULL : > library(stats) > library(utils) > > if(interactive()) { + options(error = recover, warn = 1) + } else if(FALSE) { ## MM / developer testing *manually* : + options(error = recover, Matrix.verbose = 2, warn = 1) + } else { + options( Matrix.verbose = 2, warn = 1) + } > ## Matrix.verbose = .. (*before* loading 'Matrix' pkg) > ## ==> will also show method dispath ambiguity messages: getOption("ambiguousMethodSelection") > > #### suppressPackageStartupMessages(...) as we have an *.Rout.save to Rdiff against > suppressPackageStartupMessages(library(Matrix)) > > source(system.file("test-tools.R", package = "Matrix"), keep.source = FALSE) Loading required package: tools > ##-> identical3() etc > cat("doExtras:",doExtras,"\n") doExtras: FALSE > if(exists("Sys.setLanguage", mode="function")) + Sys.setLanguage("en") > englishMsgs <- (lang <- Sys.getenv("LANGUAGE")) %in% c("en", "C") > cat(sprintf("LANGUAGE env.: '%s'; englishMsgs: %s\n", + lang, englishMsgs)) LANGUAGE env.: 'en'; englishMsgs: TRUE > > ### Dense Matrices > > m <- Matrix(1:28 +0, nrow = 7) > validObject(m) [1] TRUE > stopifnot(identical(m, m[]), + identical(m[2, 3], 16), # simple number + identical(m[2, 3:4], c(16,23)), # simple numeric of length 2 + identical(m[NA,NA], as(Matrix(NA, 7,4), "dMatrix"))) > > m[2, 3:4, drop=FALSE] # sub matrix of class 'dgeMatrix' 1 x 2 Matrix of class "dgeMatrix" [,1] [,2] [1,] 16 23 > m[-(4:7), 3:4] # ditto; the upper right corner of 'm' 3 x 2 Matrix of class "dgeMatrix" [,1] [,2] [1,] 15 22 [2,] 16 23 [3,] 17 24 > > ## rows or columns only: > m[1,] # first row, as simple numeric vector [1] 1 8 15 22 > m[,2] # 2nd column [1] 8 9 10 11 12 13 14 > m[,1:2] # sub matrix of first two columns 7 x 2 Matrix of class "dgeMatrix" [,1] [,2] [1,] 1 8 [2,] 2 9 [3,] 3 10 [4,] 4 11 [5,] 5 12 [6,] 6 13 [7,] 7 14 > m[-(1:6),, drop=FALSE] # not the first 6 rows, i.e. only the 7th 1 x 4 Matrix of class "dgeMatrix" [,1] [,2] [,3] [,4] [1,] 7 14 21 28 > m[integer(0),] #-> 0 x 4 Matrix 0 x 4 Matrix of class "dgeMatrix" [,1] [,2] [,3] [,4] > m[2:4, numeric(0)] #-> 3 x 0 Matrix 3 x 0 Matrix of class "dgeMatrix" [1,] [2,] [3,] > > ## logical indexing > stopifnot(identical(m[2,3], m[(1:nrow(m)) == 2, (1:ncol(m)) == 3]), + identical(m[2,], m[(1:nrow(m)) == 2, ]), + identical(m[,3:4], m[, (1:4) >= 3])) > > ## dimnames indexing: > mn <- m > dimnames(mn) <- list(paste("r",letters[1:nrow(mn)],sep=""), + LETTERS[1:ncol(mn)]) > checkMatrix(mn) norm(m [7 x 4]) : 1 I F M ok Summary: ok 2*m =?= m+m: identical m >= m for all: ok m < m for none: ok > mn["rd", "D"] [1] 25 > msr <- ms <- as(mn,"sparseMatrix") > mnr <- mn > v <- rev(as(ms, "vector")) > mnr[] <- v > msr[] <- v # [<- "sparse" -- not very sensical; did fail w/o a message replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > z <- msr; z[] <- 0 > zz <- as(array(0, dim(z)), "sparseMatrix") > a.m <- as(mnr,"matrix") > stopifnot(identical(mn["rc", "D"], mn[3,4]), mn[3,4] == 24, + identical(mn[, "A"], mn[,1]), mn[,1] == 1:7, + identical(mn[c("re", "rb"), "B"], mn[c(5,2), 2]), + identical(ms["rc", "D"], ms[3,4]), ms[3,4] == 24, + identical(ms[, "A"], ms[,1]), ms[,1] == 1:7, + identical(ms[ci <- c("re", "rb"), "B"], ms[c(5,2), 2]), + identical(rownames(mn[ci, ]), ci), + identical(rownames(ms[ci, ]), ci), + identical(colnames(mn[,cj <- c("B","D")]), cj), + identical(colnames(ms[,cj]), cj), + identical(a.m, as(msr,"matrix")), + identical(unname(z), zz), + identical(a.m, array(v, dim=dim(mn), dimnames=dimnames(mn))) + ) > showProc.time() Time (user system elapsed): 0.164 0.007 0.171 > > ## Bug found thanks to Timothy Mak, Feb 3, 2017: > ## sparseMatrix logical indexing with (partial) NA: > a.m <- as(mn,"matrix") > assert.EQ(as(ms,"matrix"), a.m) # incl. dimnames > iN4 <- c(NA, TRUE, FALSE, TRUE) > assert.EQ(as(mn[,iN4],"matrix"), a.m[,iN4]) # (incl. dimnames) > ##assert.EQ(as.matrix(ms[,iN4]), a.m[,iN4]) # ms[, ] fails still : _FIXME_ > try(ms[,iN4]) Error in ..subscript.2ary(x, l[[1L]], l[[2L]], drop = drop[1L]) : NA subscripts in x[i,j] not supported for 'x' inheriting from sparseMatrix > try(ms[,iN4] <- 100) ## <- segfaulted in Matrix <= 1.2-8 (!) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) Error in intI(i, n = di[margin], dn = dn[[margin]], give.dn = FALSE) : 'NA' indices are not (yet?) supported for sparse Matrices > > ## R-forge Matrix bug #2556: Subsetting a sparse matrix did remove names(dimnames(.)) : > m44 <- matrix(1:16, 4, 4, dimnames=list(row=c('a','b','c','d'), col=c('x','y','z','w'))) > ## Dense matrix: ------------------------------------------ > a <- Matrix(m44) > identical( + dimnames(m44[,FALSE, drop=FALSE]), + dimnames( a[,FALSE, drop=FALSE])) [1] TRUE > chk.ndn <- function(a, a0=m44) + stopifnot(identical(names(dimnames(a)), names(dimnames(a0)))) > i <- 1:2 > chk.ndn(a[i,]); chk.ndn(a[i, i]) > ## Sparse matrix: ----------------------------------------- > s <- as(a %% 3 == 1, "sparseMatrix") > ts <- as(s,"TsparseMatrix") > b <- sparseMatrix(i=1:3, j=rep(2,3), dims=c(4,4), dimnames=dimnames(s)) > tb <- as(b,"TsparseMatrix") > stopifnot(identical5( + dimnames(a), dimnames(s), dimnames(ts), + dimnames(b), dimnames(tb))) > > chk.ndn(b [i, i]); chk.ndn(b [i, ]) > chk.ndn(s [i, i]); chk.ndn(s [i, ]) > chk.ndn(tb[i, i]); chk.ndn(tb[i, ]) > chk.ndn(ts[i, i]); chk.ndn(ts[i, ]) > chk.ndn( b[ , 1, drop=FALSE]); chk.ndn( s[i, 2, drop=FALSE]) > chk.ndn(tb[ , 1, drop=FALSE]); chk.ndn(ts[i, 2, drop=FALSE]) > > L0 <- logical(0) > stopifnot(exprs = { + identical(dim(b[,L0]), c(4L, 0L)) + identical(dim(b[L0,]), c(0L, 4L)) # failed till 2019-09-x + }) > > ## Printing sparse colnames: > ms[sample(28, 20)] <- 0 replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > ms <- t(rbind2(ms, 3*ms)) > cnam1 <- capture.output(show(ms))[2] ; op <- options("sparse.colnames" = "abb3") [[ suppressing 14 column names 'ra', 'rb', 'rc' ... ]] > cnam2 <- capture.output(show(ms))[2] ; options(op) # revert > stopifnot(## sparse printing + grep("^ +$", cnam1) == 1, # cnam1 is empty + identical(cnam2, + paste(" ", paste(rep(rownames(mn), 2), collapse=" ")))) > > mo <- m > m[2,3] <- 100 > m[1:2, 4] <- 200 > m[, 1] <- -1 > m[1:3,] 3 x 4 Matrix of class "dgeMatrix" [,1] [,2] [,3] [,4] [1,] -1 8 15 200 [2,] -1 9 100 200 [3,] -1 10 17 24 > > m. <- as(m, "matrix") > > ## m[ cbind(i,j) ] indexing: > iN <- ij <- cbind(1:6, 2:3) > iN[2:3,] <- iN[5,2] <- NA > stopifnot(identical(m[ij], m.[ij]), + identical(m[iN], m.[iN])) > > ## testing operations on logical Matrices rather more than indexing: > g10 <- m [ m > 10 ] > stopifnot(18 == length(g10)) > stopifnot(10 == length(m[ m <= 10 ])) > sel <- (20 < m) & (m < 150) > sel.<- (20 < m.)& (m.< 150) > nsel <-(20 >= m) | (m >= 150) > (ssel <- as(sel, "sparseMatrix")) 7 x 4 sparse Matrix of class "lgCMatrix" [1,] . . . . [2,] . . | . [3,] . . . | [4,] . . . | [5,] . . . | [6,] . . . | [7,] . . | | > stopifnot(is(sel, "lMatrix"), is(ssel, "lsparseMatrix"), + identical3(as.mat(sel.), as.mat(sel), as.mat(ssel)), + identical3(!sel, !ssel, nsel), # ! is typically dense + identical3(m[ sel], m[ ssel], as(m, "matrix")[as( ssel, "matrix")]), + identical3(m[!sel], m[!ssel], as(m, "matrix")[as(!ssel, "matrix")]) + ) > showProc.time() Time (user system elapsed): 0.044 0.001 0.045 > > ## more sparse Matrices -------------------------------------- > > ##' @title Check sparseMatrix sub-assignment m[i,j] <- v > ##' @param ms sparse Matrix > ##' @param mm its [traditional matrix]-equivalent > ##' @param k (approximate) length of index vectors (i,j) > ##' @param n.uniq (approximate) number of unique values in i,j > ##' @param vRNG function(n) for random 'v' generation > ##' @param show logical; if TRUE, it will not stop on error > ##' @return > ##' @author Martin Maechler > chkAssign <- function(ms, mm = as(ms, "matrix"), + k = min(20,dim(mm)), n.uniq = k %/% 3, + vRNG = { if(is.numeric(mm) || is.complex(mm)) + function(n) rpois(n,lambda= 0.75)# <- about 47% zeros + else ## logical + function(n) runif(n) > 0.8 }, ## 80% zeros + showOnly=FALSE) + { + stopifnot(is(ms,"sparseMatrix")) + d <- dim(ms) + s1 <- function(n) sample(n, pmin(n, pmax(1, rpois(1, n.uniq)))) + i <- sample(s1(d[1]), k/2+ rpois(1, k/2), replace = TRUE) + j <- sample(s1(d[2]), k/2+ rpois(1, k/2), replace = TRUE) + assert.EQ.mat(ms[i,j], mm[i,j]) + ms2 <- ms. <- ms; mm. <- mm # save + ## now sub*assign* to these repeated indices, and then compare ----- + v <- vRNG(length(i) * length(j)) + mm[i,j] <- v + ms[i,j] <- v + ## useful to see (ii,ij), but confusing R/ESS when additionally debugging: + ## if(!showOnly && interactive()) { op <- options(error = recover); on.exit(options(op)) } + assert.EQ.mat(ms, mm, showOnly=showOnly) + ## vector indexing m[cbind(i,j)] == m[i + N(j-1)] , N = nrow(.) + ii <- seq_len(min(length(i), length(j))) + i <- i[ii] + j <- j[ii] + ij <- cbind(i, j) + ii <- i + nrow(ms)*(j - 1) + ord.i <- order(ii) + iio <- ii[ord.i] + ui <- unique(iio) # compare these with : + neg.ii <- - setdiff(seq_len(prod(d)), ii) + stopifnot(identical(mm[ii], mm[ij]), + identical(ms.[ui], ms.[neg.ii]), + ms.[ij] == mm.[ii], ## M[ cbind(i,j) ] was partly broken; now checking + ms.[ii] == mm.[ii]) + v <- v[seq_len(length(i))] + if(is(ms,"nMatrix")) v <- as.logical(v) # ! + mm.[ij] <- v + ms.[ii] <- v + nodup <- (length(ui) == length(ii)) ## <==> ! anyDuplicated(iio) + if(nodup) { cat("[-]") # rare, unfortunately + ms2[neg.ii] <- v[ord.i] + stopifnot(identical(ms2, ms.)) + } + assert.EQ.mat(ms., mm., showOnly=showOnly) + } ##{chkAssign} > > ## Get duplicated index {because these are "hard" (and rare) > getDuplIndex <- function(n, k) { + repeat { + i <- sample(n, k, replace=TRUE) # 3 4 6 9 2 9 : 9 is twice + if(anyDuplicated(i)) break + } + i + } > > suppressWarnings(RNGversion("3.5.0")); set.seed(101) > m <- 1:800 > m[sample(800, 600)] <- 0 > m0 <- Matrix(m, nrow = 40) > m1 <- add.simpleDimnames(m0) > for(kind in c("n", "l", "d")) { + for(m in list(m0,m1)) { ## -- with and without dimnames ------------------------- + kClass <-paste0(kind, "Matrix" ) + Ckind <- paste0(kind, "gCMatrix") + Tkind <- paste0(kind, "gTMatrix") + str(mC <- as(as(as(m, kClass), "CsparseMatrix"), "generalMatrix")) # was as(m, Ckind) deprecated + #was mT <- as(as(as(m, kClass), "TsparseMatrix"), Tkind)) + str(mT <- as(as(as(m, kClass), "generalMatrix"), "TsparseMatrix")) + mm <- as(mC, "matrix") # also logical or double + IDENT <- if(kind == "n") function(x,y) Q.eq2(x,y, tol=0) else identical + stopifnot(exprs = { + identical(mT, as(mC, "TsparseMatrix")) + identical(mC, as(mT, "CsparseMatrix")) # was Ckind; now deprecated + Qidentical(mC[0,0], new(Ckind)) # M..3 Csp..4 + Qidentical(mT[0,0], new(Tkind)) # " + identical(unname(mT[0,]), new(Tkind, Dim = c(0L,ncol(m))))# M.3 T.4 C.4 + identical(unname(mT[,0]), new(Tkind, Dim = c(nrow(m),0L)))# M.3 C.4 + is.null(cat("IDENT():\n")) + IDENT(mC[0,], as(mT[FALSE,], "CsparseMatrix")) # M.3 C.4 M.3 + Tsp..4 Csp..4 | as(., Ckind) deprecated + IDENT(mC[,0], as(mT[,FALSE], "CsparseMatrix")) # M.3 C.4 M.3 C.4 | as(., Ckind) deprecated + is.null(cat("sapply(..):\n")) + sapply(pmin(min(dim(mC)), c(0:2, 5:10)), + function(k) {i <- seq_len(k); all(mC[i,i] == mT[i,i])}) + }) + cat("ok\n") + show(mC[,1]) + show(mC[1:2,]) + show(mC[7, drop = FALSE]) + assert.EQ.mat(mC[1:2,], mm[1:2,]) + assert.EQ.mat(mC[0,], mm[0,]) + assert.EQ.mat(mC[,FALSE], mm[,FALSE]) + ## + ## *repeated* (aka 'duplicated') indices - did not work at all ... + i <- pmin(nrow(mC), rep(8:10,2)) + j <- c(2:4, 4:3) + assert.EQ.mat(mC[i,], mm[i,]) + assert.EQ.mat(mC[,j], mm[,j]) + ## FIXME? assert.EQ.mat(mC[,NA], mm[,NA]) -- mC[,NA] is all 0 "instead" of all NA + ## MM currently thinks we should NOT allow [ ] + assert.EQ.mat(mC[i, 2:1], mm[i, 2:1]) + assert.EQ.mat(mC[c(4,1,2:1), j], mm[c(4,1,2:1), j]) + assert.EQ.mat(mC[i,j], mm[i,j]) + ## + ## set.seed(7) + op <- options(Matrix.verbose = FALSE) + cat(" for(): ") + for(n in 1:(if(doExtras) 50 else 5)) { # (as chkAssign() is random) + chkAssign(mC, mm) + chkAssign(mC[-3,-2], mm[-3,-2]) + cat(".") + } + options(op) + cat(sprintf("\n[Ok]%s\n\n", strrep("-", 64))) + } + cat(sprintf("\nok( %s )\n== ###%s\n\n", kind, strrep("=", 70))) + }## end{for}--------------------------------------------------------------- Formal class 'ngCMatrix' [package "Matrix"] with 5 slots ..@ i : int [1:200] 2 6 11 21 24 29 37 38 1 4 ... ..@ p : int [1:21] 0 8 22 28 37 41 50 63 71 81 ... ..@ Dim : int [1:2] 40 20 ..@ Dimnames:List of 2 .. ..$ : NULL .. ..$ : NULL ..@ factors : list() Formal class 'ngTMatrix' [package "Matrix"] with 5 slots ..@ i : int [1:200] 2 6 11 21 24 29 37 38 1 4 ... ..@ j : int [1:200] 0 0 0 0 0 0 0 0 1 1 ... ..@ Dim : int [1:2] 40 20 ..@ Dimnames:List of 2 .. ..$ : NULL .. ..$ : NULL ..@ factors : list() IDENT(): sapply(..): ok [1] FALSE FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE TRUE [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE [25] TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE [37] FALSE TRUE TRUE FALSE 2 x 20 sparse Matrix of class "ngCMatrix" [1,] . . . | . . | . . . . | . . | . | . . . [2,] . | . . . | . . . . . . | | . . . . | . [1] TRUE for(): ..... [Ok]---------------------------------------------------------------- Formal class 'ngCMatrix' [package "Matrix"] with 5 slots ..@ i : int [1:200] 2 6 11 21 24 29 37 38 1 4 ... ..@ p : int [1:21] 0 8 22 28 37 41 50 63 71 81 ... ..@ Dim : int [1:2] 40 20 ..@ Dimnames:List of 2 .. ..$ : chr [1:40] "r1" "r2" "r3" "r4" ... .. ..$ : chr [1:20] "c1" "c2" "c3" "c4" ... ..@ factors : list() Formal class 'ngTMatrix' [package "Matrix"] with 5 slots ..@ i : int [1:200] 2 6 11 21 24 29 37 38 1 4 ... ..@ j : int [1:200] 0 0 0 0 0 0 0 0 1 1 ... ..@ Dim : int [1:2] 40 20 ..@ Dimnames:List of 2 .. ..$ : chr [1:40] "r1" "r2" "r3" "r4" ... .. ..$ : chr [1:20] "c1" "c2" "c3" "c4" ... ..@ factors : list() IDENT(): sapply(..): ok r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 FALSE FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE r14 r15 r16 r17 r18 r19 r20 r21 r22 r23 r24 r25 r26 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE r27 r28 r29 r30 r31 r32 r33 r34 r35 r36 r37 r38 r39 FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE r40 FALSE 2 x 20 sparse Matrix of class "ngCMatrix" [[ suppressing 20 column names 'c1', 'c2', 'c3' ... ]] r1 . . . | . . | . . . . | . . | . | . . . r2 . | . . . | . . . . . . | | . . . . | . [1] TRUE for(): ..... [Ok]---------------------------------------------------------------- ok( n ) == ###====================================================================== Formal class 'lgCMatrix' [package "Matrix"] with 6 slots ..@ i : int [1:200] 2 6 11 21 24 29 37 38 1 4 ... ..@ p : int [1:21] 0 8 22 28 37 41 50 63 71 81 ... ..@ Dim : int [1:2] 40 20 ..@ Dimnames:List of 2 .. ..$ : NULL .. ..$ : NULL ..@ x : logi [1:200] TRUE TRUE TRUE TRUE TRUE TRUE ... ..@ factors : list() Formal class 'lgTMatrix' [package "Matrix"] with 6 slots ..@ i : int [1:200] 2 6 11 21 24 29 37 38 1 4 ... ..@ j : int [1:200] 0 0 0 0 0 0 0 0 1 1 ... ..@ Dim : int [1:2] 40 20 ..@ Dimnames:List of 2 .. ..$ : NULL .. ..$ : NULL ..@ x : logi [1:200] TRUE TRUE TRUE TRUE TRUE TRUE ... ..@ factors : list() IDENT(): sapply(..): ok [1] FALSE FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE TRUE [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE [25] TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE [37] FALSE TRUE TRUE FALSE 2 x 20 sparse Matrix of class "lgCMatrix" [1,] . . . | . . | . . . . | . . | . | . . . [2,] . | . . . | . . . . . . | | . . . . | . [1] TRUE for(): ..... [Ok]---------------------------------------------------------------- Formal class 'lgCMatrix' [package "Matrix"] with 6 slots ..@ i : int [1:200] 2 6 11 21 24 29 37 38 1 4 ... ..@ p : int [1:21] 0 8 22 28 37 41 50 63 71 81 ... ..@ Dim : int [1:2] 40 20 ..@ Dimnames:List of 2 .. ..$ : chr [1:40] "r1" "r2" "r3" "r4" ... .. ..$ : chr [1:20] "c1" "c2" "c3" "c4" ... ..@ x : logi [1:200] TRUE TRUE TRUE TRUE TRUE TRUE ... ..@ factors : list() Formal class 'lgTMatrix' [package "Matrix"] with 6 slots ..@ i : int [1:200] 2 6 11 21 24 29 37 38 1 4 ... ..@ j : int [1:200] 0 0 0 0 0 0 0 0 1 1 ... ..@ Dim : int [1:2] 40 20 ..@ Dimnames:List of 2 .. ..$ : chr [1:40] "r1" "r2" "r3" "r4" ... .. ..$ : chr [1:20] "c1" "c2" "c3" "c4" ... ..@ x : logi [1:200] TRUE TRUE TRUE TRUE TRUE TRUE ... ..@ factors : list() IDENT(): sapply(..): ok r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 FALSE FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE r14 r15 r16 r17 r18 r19 r20 r21 r22 r23 r24 r25 r26 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE r27 r28 r29 r30 r31 r32 r33 r34 r35 r36 r37 r38 r39 FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE r40 FALSE 2 x 20 sparse Matrix of class "lgCMatrix" [[ suppressing 20 column names 'c1', 'c2', 'c3' ... ]] r1 . . . | . . | . . . . | . . | . | . . . r2 . | . . . | . . . . . . | | . . . . | . [1] TRUE for(): ..... [Ok]---------------------------------------------------------------- ok( l ) == ###====================================================================== Formal class 'dgCMatrix' [package "Matrix"] with 6 slots ..@ i : int [1:200] 2 6 11 21 24 29 37 38 1 4 ... ..@ p : int [1:21] 0 8 22 28 37 41 50 63 71 81 ... ..@ Dim : int [1:2] 40 20 ..@ Dimnames:List of 2 .. ..$ : NULL .. ..$ : NULL ..@ x : num [1:200] 3 7 12 22 25 30 38 39 42 45 ... ..@ factors : list() Formal class 'dgTMatrix' [package "Matrix"] with 6 slots ..@ i : int [1:200] 2 6 11 21 24 29 37 38 1 4 ... ..@ j : int [1:200] 0 0 0 0 0 0 0 0 1 1 ... ..@ Dim : int [1:2] 40 20 ..@ Dimnames:List of 2 .. ..$ : NULL .. ..$ : NULL ..@ x : num [1:200] 3 7 12 22 25 30 38 39 42 45 ... ..@ factors : list() IDENT(): sapply(..): ok [1] 0 0 3 0 0 0 7 0 0 0 0 12 0 0 0 0 0 0 0 0 0 22 0 0 25 [26] 0 0 0 0 30 0 0 0 0 0 0 0 38 39 0 2 x 20 sparse Matrix of class "dgCMatrix" [1,] . . . 121 . . 241 . . . . 441 . . 561 . 641 . . . [2,] . 42 . . . 202 . . . . . . 482 522 . . . . 722 . [1] 7 for(): ..... [Ok]---------------------------------------------------------------- Formal class 'dgCMatrix' [package "Matrix"] with 6 slots ..@ i : int [1:200] 2 6 11 21 24 29 37 38 1 4 ... ..@ p : int [1:21] 0 8 22 28 37 41 50 63 71 81 ... ..@ Dim : int [1:2] 40 20 ..@ Dimnames:List of 2 .. ..$ : chr [1:40] "r1" "r2" "r3" "r4" ... .. ..$ : chr [1:20] "c1" "c2" "c3" "c4" ... ..@ x : num [1:200] 3 7 12 22 25 30 38 39 42 45 ... ..@ factors : list() Formal class 'dgTMatrix' [package "Matrix"] with 6 slots ..@ i : int [1:200] 2 6 11 21 24 29 37 38 1 4 ... ..@ j : int [1:200] 0 0 0 0 0 0 0 0 1 1 ... ..@ Dim : int [1:2] 40 20 ..@ Dimnames:List of 2 .. ..$ : chr [1:40] "r1" "r2" "r3" "r4" ... .. ..$ : chr [1:20] "c1" "c2" "c3" "c4" ... ..@ x : num [1:200] 3 7 12 22 25 30 38 39 42 45 ... ..@ factors : list() IDENT(): sapply(..): ok r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 r20 0 0 3 0 0 0 7 0 0 0 0 12 0 0 0 0 0 0 0 0 r21 r22 r23 r24 r25 r26 r27 r28 r29 r30 r31 r32 r33 r34 r35 r36 r37 r38 r39 r40 0 22 0 0 25 0 0 0 0 30 0 0 0 0 0 0 0 38 39 0 2 x 20 sparse Matrix of class "dgCMatrix" [[ suppressing 20 column names 'c1', 'c2', 'c3' ... ]] r1 . . . 121 . . 241 . . . . 441 . . 561 . 641 . . . r2 . 42 . . . 202 . . . . . . 482 522 . . . . 722 . [1] 7 for(): ..... [Ok]---------------------------------------------------------------- ok( d ) == ###====================================================================== > showProc.time() Time (user system elapsed): 0.21 0.008 0.218 > > if(doExtras) {### {was ./AAA_index.R, MM-only} + ## an nsparse-example + A <- Matrix(c(rep(c(1,0,0),2), rep(c(2,0),7), c(0,0,2), rep(0,4)), 3,9) + i <- c(3,1:2) + j <- c(3, 5, 9, 5, 9) + vv <- logical(length(i)*length(j)); vv[6:9] <- TRUE + + print(An <- as(A,"nMatrix")); an <- as(An, "matrix") + assert.EQ.mat(An, an) + An[i, j] <- vv + an[i, j] <- vv + assert.EQ.mat(An, an)## error + if(!all(An == an)) show(drop0(An - an)) + ## all are +1 + + options("Matrix.subassign.verbose" = TRUE)# output from C + An <- as(A,"nMatrix"); An[i, j] <- vv + ## and compare with this: + Al <- as(A,"lMatrix"); Al[i, j] <- vv + options("Matrix.subassign.verbose" = FALSE) + + ##--- An interesting not small not large example for M[i,j] <- v ------------ + ## + M <- Matrix(c(1, rep(0,7), 1:4), 3,4) + N0 <- kronecker(M,M) + mkN1 <- function(M) { + stopifnot(length(d <- dim(M)) == 2) + isC <- is(M,"CsparseMatrix") + M[,d[2]] <- c(0,2,0) + N <- kronecker(diag(x=1:2), M)## remains sparse if 'M' is + if(isC) N <- as(N, "CsparseMatrix") + diag(N[-1,]) <- -2 + N[9,] <- 1:4 # is recycled + N[,12] <- -7:-9 # ditto + N + } + + show(N1 <- t(N <- mkN1(N0))) # transpose {for display reasons} + C1 <- t(C <- mkN1(as(N0,"CsparseMatrix"))) + stopifnot(all(C == N)) + assert.EQ.mat(C, mkN1(as(N0, "matrix"))) + + C. <- C1 + show(N <- N1) ; n <- as(N, "matrix"); str(N) + sort(i <- c(6,8,19,11,21,20,10,7,12,9,5,18,17,22,13))## == c(5:13, 17:22)) + sort(j <- c(3,8,6,15,10,4,14,13,16,2,11,17,7,5))## == c(2:8, 10:11, 13:17) + val <- v.l <- 5*c(0,6,0,7,0,0,8:9, 0,0) + show(spv <- as(val, "sparseVector")); str(spv) + + n [i,j] <- v.l + N [i,j] <- val# is recycled, too + C.[i,j] <- val + assert.EQ.mat(N,n) ; stopifnot(all(C. == N)) + ## and the same *again*: + n [i,j] <- v.l + N [i,j] <- val + C.[i,j] <- val + assert.EQ.mat(N,n) + stopifnot(all(C. == N)) + + print(load(system.file("external", "symA.rda", package="Matrix"))) # "As" + stopifnotValid(As, "dsCMatrix"); stopifnot(identical(As@factors, list())) + R. <- drop0(chol(As)) + stopifnot(exprs = { + 1:32 == sort(diag(R.)) ## ! + R.@x > 0 + R.@x == as.integer(R.@x)## so it is an integer-valued chol-decomp ! + ## shows that (1) As is *not* singular (2) the matrix is not random + all.equal(crossprod(R.), As, tolerance=1e-15) + }) + print(summary(evA <- eigen(As, only.values=TRUE)$values)) + print(tail(evA)) ## largest three ~= 10^7, smallest two *negative* + print(rcond(As)) # 1.722 e-21 == very bad ! + ##-> this *is* a border line case, i.e. very close to singular ! + ## and also determinant(.) is rather random here! + cc0 <- Cholesky(As)# no problem + try({ + cc <- Cholesky(As, super=TRUE) + ## gives --on 32-bit only-- + ## Cholmod error 'matrix not positive definite' at file:../Supernodal/t_cholmod_super_numeric.c, line 613 + ecc <- expand(cc) + L.P <- with(ecc, crossprod(L,P)) ## == L'P + ## crossprod(L.P) == (L'P)' L'P == P'LL'P + stopifnot( all.equal(crossprod(L.P), As) ) + }) + ##---- end{ eigen( As ) ----------- + + } ## only if(doExtras) > > > ##---- Symmetric indexing of symmetric Matrix ---------- > m. <- mC > m.[, c(2, 7:12)] <- 0 replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) > stopifnotValid(S <- crossprod(add.simpleDimnames(m.) %% 100), "dsCMatrix") > ss <- as(S, "matrix") > ds <- as(S, "denseMatrix") > ## NA-indexing of *dense* Matrices: should work as traditionally > assert.EQ.mat(ds[NA,NA], ss[NA,NA]) > assert.EQ.mat(ds[NA, ], ss[NA,]) > assert.EQ.mat(ds[ ,NA], ss[,NA]) > T <- as(S, "TsparseMatrix") > stopifnot(identical(ds[2 ,NA], ss[2,NA]), + identical(ds[NA, 1], ss[NA, 1]), + identical(S, as(T, "CsparseMatrix")) ) > > ## non-repeated indices: > i <- c(7:5, 2:4);assert.EQ.mat(T[i,i], ss[i,i]) > ## NA in indices -- check that we get a helpful error message: > i[2] <- NA > er <- tryCatch(T[i,i], error = function(e)e) > if(englishMsgs) + stopifnot(as.logical(grep("indices.*sparse Matrices", er$message))) > > N <- nrow(T) > set.seed(11) > for(n in 1:(if(doExtras) 50 else 3)) { + i <- sample(N, max(2, sample(N,1)), replace = FALSE) + validObject(Tii <- T[i,i]) ; tTi <- t(T)[i,i] + stopifnot(is(Tii, "dsTMatrix"), # remained symmetric Tsparse + is(tTi, "dsTMatrix"), # may not be identical when *sorted* differently + identical(as(t(Tii),"CsparseMatrix"), as(tTi,"CsparseMatrix"))) + assert.EQ.mat(Tii, ss[i,i]) + } > > b <- diag(1:2)[,c(1,1,2,2)] > cb <- crossprod(b) > cB <- crossprod(Matrix(b, sparse=TRUE)) > a <- matrix(0, 6, 6) > a[1:4, 1:4] <- cb > A1 <- A2 <- Matrix(0, 6, 6)#-> ddiMatrix > A1[1:4, 1:4] <- cb replCmat[x,i,j,..,val] : nargs()=4; > A2[1:4, 1:4] <- cB replCmat[x,i,j,..,val] : nargs()=4; > assert.EQ.mat(A1, a)# indeed > ## "must": symmetric and sparse, i.e., ds*Matrix: > stopifnot(identical(A1, A2), is(A1, "dsCMatrix")) > > ## repeated ones ``the challenge'' (to do smartly): > j <- c(4, 4, 9, 12, 9, 4, 17, 3, 18, 4, 12, 18, 4, 9) > assert.EQ.mat(T[j,j], ss[j,j]) > ## and another two sets (a, A) & (a., A.) : > a <- matrix(0, 6,6) > a[upper.tri(a)] <- (utr <- c(2, 0,-1, 0,0,5, 7,0,0,0, 0,0,-2,0,8)) > ta <- t(a); ta[upper.tri(a)] <- utr; a <- t(ta) > diag(a) <- c(0,3,0,4,6,0) > A <- as(Matrix(a), "TsparseMatrix") > A. <- A > diag(A.) <- 10 * (1:6) > a. <- as(A., "matrix") > ## More testing {this was not working for a long time..} > set.seed(1) > for(n in 1:(if(doExtras) 100 else 6)) { + i <- sample(1:nrow(A), 3+2*rpois(1, lambda=3), replace=TRUE) + Aii <- A[i,i] + A.ii <- A.[i,i] + stopifnot(class(Aii) == class(A), + class(A.ii) == class(A.)) + assert.EQ.mat(Aii , a [i,i]) + assert.EQ.mat(A.ii, a.[i,i]) + assert.EQ.mat(T[i,i], ss[i,i]) + } > showProc.time() Time (user system elapsed): 0.055 0.002 0.056 > > stopifnot(all.equal(mC[,3], mm[,3]), + identical(mC[ij], mC[ij + 0.4]), + identical(mC[ij], mm[ij]), + identical(mC[iN], mm[iN])) > ## out of bound indexing must be detected: > assertError(mC[cbind(ij[,1] - 5, ij[,2])]) > assertError(mC[cbind(ij[,1], ij[,2] + ncol(mC))]) > > assert.EQ.mat(mC[7, , drop=FALSE], mm[7, , drop=FALSE]) > identical (mC[7, drop=FALSE], mm[7, drop=FALSE]) # *vector* indexing [1] TRUE > > stopifnot(dim(mC[numeric(0), ]) == c(0,20), # used to give warnings + dim(mC[, integer(0)]) == c(40,0), + identical(mC[, integer(0)], mC[, FALSE])) > validObject(print(mT[,c(2,4)])) 40 x 2 sparse Matrix of class "dgTMatrix" c2 c4 r1 . 121 r2 42 . r3 . . r4 . . r5 45 . r6 . . r7 . . r8 . 128 r9 . 129 r10 50 . r11 . . r12 52 132 r13 . 133 r14 . . r15 55 . r16 . . r17 . . r18 . 138 r19 . . r20 . . r21 . 141 r22 . 142 r23 63 . r24 . . r25 65 . r26 . . r27 67 . r28 68 . r29 . . r30 . . r31 71 . r32 72 . r33 . . r34 74 . r35 . . r36 76 . r37 . . r38 . . r39 . 159 r40 80 . [1] TRUE > stopifnot(all.equal(mT[2,], mm[2,]), + ## row or column indexing in combination with t() : + Q.C.identical(mT[2,], t(mT)[,2]), + Q.C.identical(mT[-2,], t(t(mT)[,-2])), + Q.C.identical(mT[c(2,5),], t(t(mT)[,c(2,5)])) ) > assert.EQ.mat(mT[4,, drop = FALSE], mm[4,, drop = FALSE]) > stopifnot(identical3(mm[,1], mC[,1], mT[,1]), + identical3(mm[3,], mC[3,], mT[3,]), + identical3(mT[2,3], mC[2,3], 0), + identical(mT[], mT), + identical4( mm[c(3,7), 2:4], as.mat( m[c(3,7), 2:4]), + as.mat(mT[c(3,7), 2:4]), as.mat(mC[c(3,7), 2:4])) + ) > > x.x <- crossprod(mC) > stopifnot(class(x.x) == "dsCMatrix", + class(x.x. <- round(x.x / 10000)) == "dsCMatrix", + identical(x.x[cbind(2:6, 2:6)], + diag(x.x[2:6, 2:6], names=FALSE))) > head(x.x.) # Note the *non*-structural 0's printed as "0" 6 x 20 sparse Matrix of class "dgCMatrix" [[ suppressing 20 column names 'c1', 'c2', 'c3' ... ]] c1 1 0 . 1 . 1 1 3 . 3 2 1 6 1 . 2 4 6 5 1 c2 0 6 2 1 3 5 7 5 12 14 14 9 11 16 12 13 17 19 19 10 c3 . 2 6 . 4 2 5 3 8 12 5 16 9 11 23 . . 6 7 7 c4 1 1 . 17 . 8 10 13 8 6 18 18 29 35 14 8 25 10 19 21 c5 . 3 4 . 14 4 10 . . 29 8 9 19 11 11 . . 26 26 16 c6 1 5 2 8 4 42 5 19 14 9 8 10 42 56 50 27 29 32 64 16 > tail(x.x., -3) # all but the first three lines 17 x 20 sparse Matrix of class "dgCMatrix" [[ suppressing 20 column names 'c1', 'c2', 'c3' ... ]] c4 1 1 . 17 . 8 10 13 8 6 18 18 29 35 14 8 25 10 19 21 c5 . 3 4 . 14 4 10 . . 29 8 9 19 11 11 . . 26 26 16 c6 1 5 2 8 4 42 5 19 14 9 8 10 42 56 50 27 29 32 64 16 c7 1 7 5 10 10 5 87 14 9 31 77 47 79 43 28 17 67 110 36 121 c8 3 5 3 13 . 19 14 70 10 24 37 13 59 62 34 19 58 21 64 44 c9 . 12 8 8 . 14 9 10 116 41 58 33 33 72 78 43 69 72 75 25 c10 3 14 12 6 29 9 31 24 41 167 69 56 99 44 70 24 105 82 85 32 c11 2 14 5 18 8 8 77 37 58 69 267 80 86 139 49 105 194 119 122 129 c12 1 9 16 18 9 10 47 13 33 56 80 194 70 77 81 . 90 32 . 106 c13 6 11 9 29 19 42 79 59 33 99 86 70 324 157 55 . 69 142 144 155 c14 1 16 11 35 11 56 43 62 72 44 139 77 157 375 123 102 145 39 196 81 c15 . 12 23 14 11 50 28 34 78 70 49 81 55 123 368 71 112 41 41 86 c16 2 13 . 8 . 27 17 19 43 24 105 . . 102 71 233 124 44 139 . c17 4 17 . 25 . 29 67 58 69 105 194 90 69 145 112 124 523 141 245 100 c18 6 19 6 10 26 32 110 21 72 82 119 32 142 39 41 44 141 497 104 111 c19 5 19 7 19 26 64 36 64 75 85 122 . 144 196 41 139 245 104 542 55 c20 1 10 7 21 16 16 121 44 25 32 129 106 155 81 86 . 100 111 55 541 > > lx.x <- as(as(x.x, "lMatrix"), "symmetricMatrix") # FALSE only for "structural" 0 > (l10 <- lx.x[1:10, 1:10])# "lsC" 10 x 10 sparse Matrix of class "lsCMatrix" [[ suppressing 10 column names 'c1', 'c2', 'c3' ... ]] c1 | | . | . | | | . | c2 | | | | | | | | | | c3 . | | . | | | | | | c4 | | . | . | | | | | c5 . | | . | | | . . | c6 | | | | | | | | | | c7 | | | | | | | | | | c8 | | | | . | | | | | c9 . | | | . | | | | | c10 | | | | | | | | | | > (l3 <- lx.x[1:3, ]) 3 x 20 sparse Matrix of class "lgCMatrix" [[ suppressing 20 column names 'c1', 'c2', 'c3' ... ]] c1 | | . | . | | | . | | | | | . | | | | | c2 | | | | | | | | | | | | | | | | | | | | c3 . | | . | | | | | | | | | | | . . | | | > m.x <- as.mat(x.x) # as.mat() *drops* (NULL,NULL) dimnames > stopifnot(class(l10) == "lsCMatrix", # symmetric indexing -> symmetric ! + identical(as.mat(lx.x), m.x != 0), + identical(as.logical(lx.x), as.logical(m.x)), + identical(as.mat(l10), m.x[1:10, 1:10] != 0), + identical(as.mat(l3 ), m.x[1:3, ] != 0) + ) > > ##-- Sub*assignment* with repeated / duplicated index: > A <- Matrix(0,4,3) ; A[c(1,2,1), 2] <- 1 ; A replCmat[x,i,j,..,val] : nargs()=4; 4 x 3 sparse Matrix of class "dgCMatrix" [1,] . 1 . [2,] . 1 . [3,] . . . [4,] . . . > B <- A; B[c(1,2,1), 2] <- 1:3; B; B. <- B replCmat[x,i,j,..,val] : nargs()=4; 4 x 3 sparse Matrix of class "dgCMatrix" [1,] . 3 . [2,] . 2 . [3,] . . . [4,] . . . > B.[3,] <- rbind(4:2) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) > ## change the diagonal and the upper and lower subdiagonal : > diag(B.) <- 10 * diag(B.) > diag(B.[,-1]) <- 5* diag(B.[,-1]) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) > diag(B.[-1,]) <- 4* diag(B.[-1,]) ; B. replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) 4 x 3 sparse Matrix of class "dgCMatrix" [1,] . 15 . [2,] . 20 . [3,] 4 12 20 [4,] . . . > C <- B.; C[,2] <- C[,2]; C[1,] <- C[1,]; C[2:3,2:1] <- C[2:3,2:1] replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; > stopifnot(identical(unname(as(A, "matrix")), + local({a <- matrix(0,4,3); a[c(1,2,1), 2] <- 1 ; a})), + identical(unname(as(B, "matrix")), + local({a <- matrix(0,4,3); a[c(1,2,1), 2] <- 1:3; a})), + identical(C, drop0(B.))) > ## [] <- v failed in the past > T <- as(C,"TsparseMatrix"); C. <- C > T[T>0] <- 21 .TM.repl.i.mat(): "lMatrix" case ... diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > C[C>0] <- 21 .TM.repl.i.mat(): "lMatrix" case ... diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > a. <- local({a <- as(C., "matrix"); a[a>0] <- 21; a}) > assert.EQ.mat(C, a.) > stopifnot(identical(C, as(T, "CsparseMatrix"))) > > ## used to fail > n <- 5 ## or much larger > sm <- new("dsTMatrix", i=1L, j=1L, Dim=as.integer(c(n,n)), x = 1) > (cm <- as(sm, "CsparseMatrix")) 5 x 5 sparse Matrix of class "dsCMatrix" [1,] . . . . . [2,] . 1 . . . [3,] . . . . . [4,] . . . . . [5,] . . . . . > sm[2,] [1] 0 1 0 0 0 > stopifnot(sm[2,] == c(0:1, rep.int(0,ncol(sm)-2)), + sm[2,] == cm[2,], + sm[,3] == sm[3,], + all(sm[,-(1:3)] == t(sm[-(1:3),])), # all() + all(sm[,-(1:3)] == 0) + ) > showProc.time() Time (user system elapsed): 0.049 0.003 0.053 > > ##--- "nsparse*" sub-assignment :---------- > M <- Matrix(c(1, rep(0,7), 1:4), 3,4) > N0 <- kronecker(M,M) > Nn <- as(N0, "nMatrix"); nn <- as(Nn,"matrix") > (Nn00 <- Nn0 <- Nn); nn00 <- nn0 <- nn 9 x 16 sparse Matrix of class "ngCMatrix" [1,] | . . | . . . . . . . . | . . | [2,] . . . | . . . . . . . . . . . | [3,] . . | | . . . . . . . . . . | | [4,] . . . . . . . . . . . . | . . | [5,] . . . . . . . . . . . . . . . | [6,] . . . . . . . . . . . . . . | | [7,] . . . . . . . . | . . | | . . | [8,] . . . . . . . . . . . | . . . | [9,] . . . . . . . . . . | | . . | | > > set.seed(1) > Nn0 <- Nn00; nn0 <- nn00 > for(i in 1:(if(doExtras) 200 else 25)) { + Nn <- Nn0 + nn <- nn0 + i. <- getDuplIndex(nrow(N0), 6) + j. <- getDuplIndex(ncol(N0), 4) + vv <- sample(c(FALSE,TRUE), + length(i.)*length(j.), replace=TRUE) + cat(",") + Nn[i., j.] <- vv + nn[i., j.] <- vv + assert.EQ.mat(Nn, nn) + if(!all(Nn == nn)) { + cat("i=",i,":\n i. <- "); dput(i.) + cat("j. <- "); dput(j.) + cat("which(vv): "); dput(which(vv)) + cat("Difference matrix:\n") + show(drop0(Nn - nn)) + } + cat("k") + ## sub-assign double precision to logical sparseMatrices: now *with* warning: + ## {earlier: gave *no* warning}: + assertWarning(Nn[1:2,] <- -pi) + assertWarning(Nn[, 5] <- -pi) + assertWarning(Nn[2:4, 5:8] <- -pi) + stopifnotValid(Nn,"nsparseMatrix") + ## + cat(".") + if(i %% 10 == 0) cat("\n") + if(i == 100) { + Nn0 <- as(Nn0, "CsparseMatrix") + cat("Now: class", class(Nn0)," :\n~~~~~~~~~~~~~~~~~\n") + } + } ,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; . ,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; . ,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .,replCmat[x,i,j,..,val] : nargs()=4; kreplCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) replCmat[x,i,j,..,val] : nargs()=4; .> showProc.time() Time (user system elapsed): 0.056 0.001 0.058 > Nn <- Nn0 > ## Check that NA is interpreted as TRUE (with a warning), for "nsparseMatrix": > assertWarning(Nn[ii <- 3 ] <- NA); stopifnot(isValid(Nn,"nsparseMatrix"), Nn[ii]) replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > assertWarning(Nn[ii <- 22:24] <- NA); stopifnot(isValid(Nn,"nsparseMatrix"), Nn[ii]) replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > assertWarning(Nn[ii <- -(1:99)] <- NA); stopifnot(isValid(Nn,"nsparseMatrix"), Nn[ii]) replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > assertWarning(Nn[ii <- 3:4 ] <- c(0,NA)) replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > stopifnot(isValid(Nn,"nsparseMatrix"), Nn[ii] == 0:1) > assertWarning(Nn[ii <- 25:27] <- c(0,1,NA)) replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > stopifnot(isValid(Nn,"nsparseMatrix"), Nn[ii] == c(FALSE,TRUE,TRUE)) > > m0 <- Diagonal(5) > stopifnot(identical(m0[2,], m0[,2]), + identical(m0[,1], c(1,0,0,0,0))) > ### Diagonal -- Sparse: > (m1 <- as(m0, "TsparseMatrix")) # dtTMatrix unitriangular 5 x 5 sparse Matrix of class "dtTMatrix" (unitriangular) [1,] I . . . . [2,] . I . . . [3,] . . I . . [4,] . . . I . [5,] . . . . I > (m2 <- as(m0, "CsparseMatrix")) # dtCMatrix unitriangular 5 x 5 sparse Matrix of class "dtCMatrix" (unitriangular) [1,] I . . . . [2,] . I . . . [3,] . . I . . [4,] . . . I . [5,] . . . . I > m1g <- as(m1, "generalMatrix") > tr1 <- as(m1, "denseMatrix") # dtrMatrix unitriangular > stopifnotValid(m1g, "dgTMatrix") > diag(tr1) <- 100 > stopifnot(diag(tr1) == 100)# failed when 'diag<-' did not recycle > assert.EQ.mat(m2[1:3,], diag(5)[1:3,]) > assert.EQ.mat(m2[,c(4,1)], diag(5)[,c(4,1)]) > stopifnot(identical(m2[1:3,], as(m1[1:3,], "CsparseMatrix")), + identical(asUniqueT(m1[, c(4,2)]), + asUniqueT(m2[, c(4,2)])) + )## failed in 0.9975-11 > > ## 0-dimensional diagonal - subsetting ---------------------------- > ## before that diagU2N() etc for 0-dim. dtC*: > m0. <- m00 <- matrix(numeric(),0,0) > tC0.<- new("dtCMatrix") > tC0 <- new("dtCMatrix", diag="U") > (gC0 <- new("dgCMatrix")) # 0 x 0 0 x 0 sparse Matrix of class "dgCMatrix" <0 x 0 matrix> > D0 <- Diagonal(0) > stopifnot(exprs = { + identical(m0., as(tC0, "matrix")) # failed: Cholmod error 'invalid xtype' .. + identical(numeric(), as(tC0, "numeric"))# " + identical(numeric(), tC0[ 0 ])# --> .M.vectorSub(x, i) failed in as(., "matrix") + identical(m00[TRUE ], tC0[TRUE ])# (worked already) + identical(m00[FALSE], tC0[FALSE])# ditto + ## + identical(D0, D0[0,0]) # used to fail --> subCsp_ij (..) + identical(gC0, D0[, 0]) # (ditto) --> subCsp_cols(..) + identical(gC0, D0[0, ]) # " --> subCsp_rows(..) + identical(D0, D0[,]) # (worked already) + identical(m00[ 0 ], D0[ 0 ] )# ditto + identical(m00[TRUE ], D0[TRUE ])# " + identical(m00[FALSE], D0[FALSE])# " + ## + identical(tC0, tC0[0,0]) # failed --> subCsp_ij (..) + identical(gC0, tC0[ ,0]) # " --> subCsp_cols(..) + identical(gC0, tC0[0, ]) # " --> subCsp_rows(..) + identical(tC0, tC0[,]) # (worked already) + ## vector indexing + }) > > expr <- quote({ ## FIXME -- both 'TRUE' and 'FALSE' should fail "out of bound",etc + D0[TRUE, TRUE ] + D0[ , TRUE ] + D0[TRUE, ] # worked but should *NOT* + tC0[TRUE, TRUE ] + tC0[ , TRUE ] + tC0[TRUE, ] # worked but should *NOT* + ## + D0[FALSE,FALSE] # fails --> subCsp_ij(..) -> intI() + D0[ ,FALSE] # ditto ............ + D0[FALSE, ] # ditto + tC0[FALSE,FALSE] # " + tC0[FALSE, ] # " + tC0[ ,FALSE] # " + }) > EE <- lapply(expr[-1], function(e) + list(expr = e, + r = tryCatch(eval(e), error = identity))) > exR <- lapply(EE, `[[`, "r") > stopifnot(exprs = { + vapply(exR, inherits, logical(1), what = "error") + !englishMsgs || + unique( vapply(exR, `[[`, "", "message") + ) == "logical subscript too long" + }) > > > (uTr <- new("dtTMatrix", Dim = c(3L,3L), diag="U")) 3 x 3 sparse Matrix of class "dtTMatrix" (unitriangular) [1,] I . . [2,] . I . [3,] . . I > uTr[1,] <- 0 .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dtTMatrix; len.(value)=1; missing (i,j) = (0,1) > assert.EQ.mat(uTr, cbind(0, rbind(0,diag(2)))) > > M <- m0; M[1,] <- 0 replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) > Z <- m0; Z[] <- 0; z <- array(0, dim(M)) > stopifnot(identical(M, Diagonal(x=c(0, rep(1,4)))), + all(Z == 0), Qidentical(as(Z, "matrix"), z)) > M <- m0; M[,3] <- 3 ; M ; stopifnot(is(M, "sparseMatrix"), M[,3] == 3) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) 5 x 5 sparse Matrix of class "dgCMatrix" [1,] 1 . 3 . . [2,] . 1 3 . . [3,] . . 3 . . [4,] . . 3 1 . [5,] . . 3 . 1 > checkMatrix(M) Compare -- "dgCMatrix" != "dgCMatrix" : norm(m [5 x 5]) : 1 I F M ok Summary: ok as(., "nMatrix") giving full nonzero-pattern: ok 2*m =?= m+m: identical m >= m for all: ok m < m for none: Compare -- "dgCMatrix" < "dgCMatrix" : ok symmpart(m) + skewpart(m) == m: ok; determinant(): ok > M <- m0; M[1:3, 3] <- 0 ;M replCmat[x,i,j,..,val] : nargs()=4; 5 x 5 diagonal matrix of class "ddiMatrix" [,1] [,2] [,3] [,4] [,5] [1,] 1 . . . . [2,] . 1 . . . [3,] . . 0 . . [4,] . . . 1 . [5,] . . . . 1 > T <- m0; T[1:3, 3] <- 10 replCmat[x,i,j,..,val] : nargs()=4; > stopifnot(identical(M, Diagonal(x=c(1,1, 0, 1,1))), + isValid(T, "triangularMatrix"), identical(T[,3], c(10,10,10,0,0))) > > M <- m1; M[1,] <- 0 ; M ; assert.EQ.mat(M, diag(c(0,rep(1,4))), tol=0) .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dtTMatrix; len.(value)=1; missing (i,j) = (0,1) 5 x 5 sparse Matrix of class "dtTMatrix" [1,] . . . . . [2,] . 1 . . . [3,] . . 1 . . [4,] . . . 1 . [5,] . . . . 1 > M <- m1; M[,3] <- 3 ; stopifnot(is(M,"sparseMatrix"), M[,3] == 3) .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dtTMatrix; len.(value)=1; missing (i,j) = (1,0) M[i,j] <- v : coercing symmetric M[] into non-symmetric > Z <- m1; Z[] <- 0 > checkMatrix(M) Compare -- "dgCMatrix" != "dgCMatrix" : norm(m [5 x 5]) : 1 I F M ok Summary: ok as(., "nMatrix") giving full nonzero-pattern: ok 2*m =?= m+m: ok m >= m for all: ok m < m for none: Compare -- "dgCMatrix" < "dgCMatrix" : ok symmpart(m) + skewpart(m) == m: ok; determinant(): ok > M <- m1; M[1:3, 3] <- 0 ;M .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dtTMatrix; len.(value)=1; 5 x 5 sparse Matrix of class "dtTMatrix" [1,] 1 . . . . [2,] . 1 . . . [3,] . . . . . [4,] . . . 1 . [5,] . . . . 1 > assert.EQ.mat(M, diag(c(1,1, 0, 1,1)), tol=0) > T <- m1; T[1:3, 3] <- 10; checkMatrix(T) .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dtTMatrix; len.(value)=1; Compare -- "dtCMatrix" != "dtCMatrix" : norm(m [5 x 5]) : 1 I F M ok Summary: ok as(., "nMatrix") giving full nonzero-pattern: ok 2*m =?= m+m: identical m >= m for all: ok m < m for none: Compare -- "dtCMatrix" < "dtCMatrix" : ok symmpart(m) + skewpart(m) == m: ok; determinant(): ok .TM.repl.i.mat(): drop 'matrix' case ... diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) 'sub-optimal sparse 'x[i] <- v' assignment: Coercing class dtTMatrix to dgTMatrix as(mm., "triangularMatrix"): valid: TRUE > stopifnot(is(T, "triangularMatrix"), identical(T[,3], c(10,10,10,0,0)), + Qidentical(as(Z, "matrix"), z)) > > M <- m2; M[1,] <- 0 ; M ; assert.EQ.mat(M, diag(c(0,rep(1,4))), tol=0) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (0,1) 5 x 5 sparse Matrix of class "dtCMatrix" [1,] . . . . . [2,] . 1 . . . [3,] . . 1 . . [4,] . . . 1 . [5,] . . . . 1 > M <- m2; M[,3] <- 3 ; stopifnot(is(M,"sparseMatrix"), M[,3] == 3) replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) > checkMatrix(M) Compare -- "dgCMatrix" != "dgCMatrix" : norm(m [5 x 5]) : 1 I F M ok Summary: ok as(., "nMatrix") giving full nonzero-pattern: ok 2*m =?= m+m: identical m >= m for all: ok m < m for none: Compare -- "dgCMatrix" < "dgCMatrix" : ok symmpart(m) + skewpart(m) == m: ok; determinant(): ok > Z <- m2; Z[] <- 0 > M <- m2; M[1:3, 3] <- 0 ;M replCmat[x,i,j,..,val] : nargs()=4; 5 x 5 sparse Matrix of class "dtCMatrix" [1,] 1 . . . . [2,] . 1 . . . [3,] . . . . . [4,] . . . 1 . [5,] . . . . 1 > assert.EQ.mat(M, diag(c(1,1, 0, 1,1)), tol=0) > T <- m2; T[1:3, 3] <- 10; checkMatrix(T) replCmat[x,i,j,..,val] : nargs()=4; Compare -- "dtCMatrix" != "dtCMatrix" : norm(m [5 x 5]) : 1 I F M ok Summary: ok as(., "nMatrix") giving full nonzero-pattern: ok 2*m =?= m+m: identical m >= m for all: ok m < m for none: Compare -- "dtCMatrix" < "dtCMatrix" : ok symmpart(m) + skewpart(m) == m: ok; determinant(): ok .TM.repl.i.mat(): drop 'matrix' case ... diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) 'sub-optimal sparse 'x[i] <- v' assignment: Coercing class dtTMatrix to dgTMatrix as(mm., "triangularMatrix"): valid: TRUE > stopifnot(is(T, "dtCMatrix"), identical(T[,3], c(10,10,10,0,0)), + Qidentical(as(Z, "matrix"), z)) > showProc.time() Time (user system elapsed): 0.178 0.003 0.18 > > > ## "Vector indices" ------------------- > asLogical <- function(x) { + stopifnot(is.atomic(x)) + storage.mode(x) <- "logical" + x + } > .iniDiag.example <- expression({ + D <- Diagonal(6) + M <- as(D,"generalMatrix") # was "dge", now "dgC" + d <- as(D,"unpackedMatrix") # "dtr" (unitri) + m <- as(D,"matrix") + s <- as(D,"TsparseMatrix"); N <- as(s,"nMatrix") + S <- as(s,"CsparseMatrix"); C <- as(S,"nMatrix") + }) > eval(.iniDiag.example) > i <- c(3,1,6); v <- c(10,15,20) > ## (logical,value) which both are recycled: > L <- c(TRUE, rep(FALSE,8)) ; z <- c(50,99) > > ## vector subassignment, both with integer & logical > ## these now work correctly {though not very efficiently; hence warnings} > m[i] <- v # the role model: only first column is affected > M[i] <- v; assert.EQ.mat(M,m) # dgC replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > D[i] <- v; assert.EQ.mat(D,m) # ddi -> dtC (new! 2019-07; was dgT) replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > s[i] <- v; assert.EQ.mat(s,m) # dtT -> dgT diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) 'sub-optimal sparse 'x[i] <- v' assignment: Coercing class dtTMatrix to dgTMatrix > S[i] <- v; assert.EQ.mat(S,m); S # dtC -> dtT -> dgT -> dgC replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) 'sub-optimal sparse 'x[i] <- v' assignment: Coercing class dtTMatrix to dgTMatrix 6 x 6 sparse Matrix of class "dgCMatrix" [1,] 15 . . . . . [2,] . 1 . . . . [3,] 10 . 1 . . . [4,] . . . 1 . . [5,] . . . . 1 . [6,] 20 . . . . 1 > m.L <- asLogical(m) ; assertWarning( + C[i] <- v, verbose=TRUE) # warning: C is nMatrix, v not T/F replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) 'sub-optimal sparse 'x[i] <- v' assignment: Coercing class ntTMatrix to ngTMatrix Asserted warning: x[.] <- val: x is "ngTMatrix", val not in {TRUE, FALSE} is coerced. > assert.EQ.mat(C,m.L); validObject(C); assertWarning( [1] TRUE + N[i] <- v, verbose=TRUE) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) 'sub-optimal sparse 'x[i] <- v' assignment: Coercing class ntTMatrix to ngTMatrix Asserted warning: x[.] <- val: x is "ngTMatrix", val not in {TRUE, FALSE} is coerced. > assert.EQ.mat(N,m.L); validObject(N) [1] TRUE > stopifnot(identical(D, as(as(s, "triangularMatrix"), "CsparseMatrix"))) > ## logical *vector* indexing > eval(.iniDiag.example) > m[L] <- z; m.L <- asLogical(m) > M[L] <- z; assert.EQ.mat(M,m) replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > D[L] <- z; assert.EQ.mat(D,m) replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > s[L] <- z; assert.EQ.mat(s,m) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) 'sub-optimal sparse 'x[i] <- v' assignment: Coercing class dtTMatrix to dgTMatrix > S[L] <- z; assert.EQ.mat(S,m) ; S ; assertWarning( replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) 'sub-optimal sparse 'x[i] <- v' assignment: Coercing class dtTMatrix to dgTMatrix 6 x 6 sparse Matrix of class "dgCMatrix" [1,] 50 . . 50 . . [2,] . 1 . . . . [3,] . . 1 . . . [4,] . 99 . 1 99 . [5,] . . . . 1 . [6,] . . . . . 1 + C[L] <- z, verbose=TRUE); assert.EQ.mat(C,m.L) ; assertWarning( replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) 'sub-optimal sparse 'x[i] <- v' assignment: Coercing class ntTMatrix to ngTMatrix Asserted warning: x[.] <- val: x is "ngTMatrix", val not in {TRUE, FALSE} is coerced. + N[L] <- z, verbose=TRUE); assert.EQ.mat(N,m.L) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) 'sub-optimal sparse 'x[i] <- v' assignment: Coercing class ntTMatrix to ngTMatrix Asserted warning: x[.] <- val: x is "ngTMatrix", val not in {TRUE, FALSE} is coerced. > > > ## indexing [i] vs [i,] --- now ok > eval(.iniDiag.example) > stopifnot(identical5(m[i], M[i], D[i], s[i], S[i]), identical3(as.logical(m[i]), C[i], N[i]), + identical5(m[L], M[L], D[L], s[L], S[L]), identical3(as.logical(m[L]), C[L], N[L])) > ## bordercase ' drop = .' *vector* indexing {failed till 2009-04-..) > stopifnot(identical5(m[i,drop=FALSE], M[i,drop=FALSE], D[i,drop=FALSE], + s[i,drop=FALSE], S[i,drop=FALSE]), + identical3(as.logical(m[i,drop=FALSE]), + C[i,drop=FALSE], N[i,drop=FALSE])) > stopifnot(identical5(m[L,drop=FALSE], M[L,drop=FALSE], D[L,drop=FALSE], + s[L,drop=FALSE], S[L,drop=FALSE]), + identical3(as.logical(m[L,drop=FALSE]), + C[L,drop=FALSE], N[L,drop=FALSE])) > ## using L for row-indexing should give an error > assertError(m[L,]); assertError(m[L,, drop=FALSE]) > ## these did not signal an error, upto (including) 0.999375-30: > assertError(s[L,]); assertError(s[L,, drop=FALSE]) > assertError(S[L,]); assertError(S[L,, drop=FALSE]) > assertError(N[L,]); assertError(N[L,, drop=FALSE]) > > ## row indexing: > assert.EQ.mat(D[i,], m[i,]) > assert.EQ.mat(M[i,], m[i,]) > assert.EQ.mat(s[i,], m[i,]) > assert.EQ.mat(S[i,], m[i,]) > assert.EQ.mat(C[i,], asLogical(m[i,])) > assert.EQ.mat(N[i,], asLogical(m[i,])) > ## column indexing: > assert.EQ.mat(D[,i], m[,i]) > assert.EQ.mat(M[,i], m[,i]) > assert.EQ.mat(s[,i], m[,i]) > assert.EQ.mat(S[,i], m[,i]) > assert.EQ.mat(C[,i], asLogical(m[,i])) > assert.EQ.mat(N[,i], asLogical(m[,i])) > > > ### --- negative indices ---------- > > ## 1) negative *vector* indexing > eval(.iniDiag.example) > i <- -(2:30) > stopifnot(identical5(m[i], M[i], D[i], s[i], S[i]), + identical3(as.logical(m[i]), C[i], N[i])) > ## negative vector subassignment : > v <- seq_along(m[i]) > m[i] <- v; m.L <- asLogical(m) > M[i] <- v; assert.EQ.mat(M,m) # dge replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > D[i] <- v; assert.EQ.mat(D,m) # ddi -> dtT -> dgT replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > s[i] <- v; assert.EQ.mat(s,m) # dtT -> dgT diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) 'sub-optimal sparse 'x[i] <- v' assignment: Coercing class dtTMatrix to dgTMatrix > S[i] <- v; assert.EQ.mat(S,m); S ; assertWarning( # dtC -> dtT -> dgT -> dgC replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) 'sub-optimal sparse 'x[i] <- v' assignment: Coercing class dtTMatrix to dgTMatrix 6 x 6 sparse Matrix of class "dgCMatrix" [1,] 1 . . . . 2 [2,] . 1 . . . 3 [3,] . . 1 . . 4 [4,] . . . 1 . 5 [5,] . . . . 1 6 [6,] . . . . . 7 + N[i] <- v, verbose=TRUE) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) 'sub-optimal sparse 'x[i] <- v' assignment: Coercing class ntTMatrix to ngTMatrix Asserted warning: x[.] <- val: x is "ngTMatrix", val not in {TRUE, FALSE} is coerced. > assert.EQ.mat(N,m.L); N ; assertWarning( 6 x 6 sparse Matrix of class "ngTMatrix" [1,] | . . . . | [2,] . | . . . | [3,] . . | . . | [4,] . . . | . | [5,] . . . . | | [6,] . . . . . | + C[i] <- v, verbose=TRUE) replCmat[x,i,j,..,val] : nargs()=3; missing (i,j) = (0,1) diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) 'sub-optimal sparse 'x[i] <- v' assignment: Coercing class ntTMatrix to ngTMatrix Asserted warning: x[.] <- val: x is "ngTMatrix", val not in {TRUE, FALSE} is coerced. > assert.EQ.mat(C,m.L); C # 6 x 6 sparse Matrix of class "ngCMatrix" [1,] | . . . . | [2,] . | . . . | [3,] . . | . . | [4,] . . . | . | [5,] . . . . | | [6,] . . . . . | > > options(warn = 2) #----------------------# NO WARNINGS from here ----------------- > ## ===================== > > ## 2) negative [i,j] indices > mc <- mC[1:5, 1:7] > mt <- mT[1:5, 1:7] > ## sub matrix > assert.EQ.mat(mC[1:2, 0:3], mm[1:2, 0:3]) # test 0-index > stopifnot(identical(mc[-(3:5), 0:2], mC[1:2, 0:2]), + identical(mt[-(3:5), 0:2], mT[1:2, 0:2]), + identical(mC[2:3, 4], mm[2:3, 4])) > assert.EQ.mat(mC[1:2,], mm[1:2,]) > ## sub vector > stopifnot(identical4(mc[-(1:4), ], mC[5, 1:7], + mt[-(1:4), ], mT[5, 1:7])) > stopifnot(identical4(mc[-(1:4), -(2:4)], mC[5, c(1,5:7)], + mt[-(1:4), -(2:4)], mT[5, c(1,5:7)])) > > ## mixing of negative and positive must give error > assertError(mT[-1:1,]) > showProc.time() Time (user system elapsed): 0.039 0.001 0.041 > > ## Sub *Assignment* ---- now works (partially): > mt0 <- mt > nt <- as(mt, "nMatrix") > mt[1, 4] <- -99 .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dgTMatrix; len.(value)=1; > mt[2:3, 1:6] <- 0 .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dgTMatrix; len.(value)=1; > mt 5 x 7 sparse Matrix of class "dgTMatrix" c1 c2 c3 c4 c5 c6 c7 r1 . . . -99 . . 241 r2 . . . . . . . r3 . . . . . . 243 r4 . . . . . . . r5 . 45 . . . . . > m2 <- mt+mt > m2[1,4] <- -200 .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dgTMatrix; len.(value)=1; > m2[c(1,3), c(5:6,2)] <- 1:6 .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dgTMatrix; len.(value)=6; > stopifnot(m2[1,4] == -200, + as.vector(m2[c(1,3), c(5:6,2)]) == 1:6) > mt[,3] <- 30 .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dgTMatrix; len.(value)=1; missing (i,j) = (1,0) > mt[2:3,] <- 250 .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dgTMatrix; len.(value)=1; missing (i,j) = (0,1) > mt[1:5 %% 2 == 1, 3] <- 0 .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dgTMatrix; len.(value)=1; > mt[3:1, 1:7 > 5] <- 0 .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dgTMatrix; len.(value)=1; > mt 5 x 7 sparse Matrix of class "dgTMatrix" c1 c2 c3 c4 c5 c6 c7 r1 . . . -99 . . . r2 250 250 250 250 250 . . r3 250 250 . 250 250 . . r4 . . 30 . . . . r5 . 45 . . . . . > > tt <- as(mt,"matrix") > ii <- c(0,2,5) > jj <- c(2:3,5) > tt[ii, jj] <- 1:6 # 0 is just "dropped" > mt[ii, jj] <- 1:6 .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dgTMatrix; len.(value)=6; > assert.EQ.mat(mt, tt) > > mt[1:5, 2:6] 5 x 5 sparse Matrix of class "dgTMatrix" c2 c3 c4 c5 c6 r1 . . -99 . . r2 1 3 250 5 . r3 250 . 250 250 . r4 . 30 . . . r5 2 4 . 6 . > as((mt0 - mt)[1:5,], "dsparseMatrix")# [1,5] and lines 2:3 5 x 7 sparse Matrix of class "dgCMatrix" c1 c2 c3 c4 c5 c6 c7 r1 . . . 220 . . 241 r2 -250 41 -3 -250 -5 202 . r3 -247 -250 . -250 -250 . 243 r4 . . -30 . . . . r5 . 43 -4 . -6 . . > > mt[c(2,4), ] <- 0; stopifnot(as(mt[c(2,4), ],"matrix") == 0) .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dgTMatrix; len.(value)=1; missing (i,j) = (0,1) > mt[2:3, 4:7] <- 33 .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dgTMatrix; len.(value)=1; > checkMatrix(mt) Compare -- "dgCMatrix" != "dgCMatrix" : norm(m [5 x 7]) : 1 I F M ok Summary: ok as(., "nMatrix") giving full nonzero-pattern: ok 2*m =?= m+m: ok m >= m for all: ok m < m for none: Compare -- "dgCMatrix" < "dgCMatrix" : ok > mt 5 x 7 sparse Matrix of class "dgTMatrix" c1 c2 c3 c4 c5 c6 c7 r1 . . . -99 . . . r2 . . . 33 33 33 33 r3 250 250 . 33 33 33 33 r4 . . . . . . . r5 . 2 4 . 6 . . > > mc[1,4] <- -99 ; stopifnot(mc[1,4] == -99) replCmat[x,i,j,..,val] : nargs()=4; > mc[1,4] <- 00 ; stopifnot(mc[1,4] == 00) replCmat[x,i,j,..,val] : nargs()=4; > mc[1,4] <- -99 ; stopifnot(mc[1,4] == -99) replCmat[x,i,j,..,val] : nargs()=4; > mc[1:2,4:3] <- 4:1; stopifnot(as(mc[1:2,4:3], "matrix") == 4:1) replCmat[x,i,j,..,val] : nargs()=4; > > mc[-1, 3] <- -2:1 # 0 should not be entered; 'value' recycled replCmat[x,i,j,..,val] : nargs()=4; > mt[-1, 3] <- -2:1 .. replTmat(x,i,j,v): nargs()= 4; cl.(x)=dgTMatrix; len.(value)=4; > stopifnot(mc@x != 0, mt@x != 0, + mc[-1,3] == -2:1, mt[-1,3] == -2:1) ## failed earlier > > mc0 <- mc > mt0 <- as(mc0, "TsparseMatrix") > m0 <- as(mc0, "matrix") > set.seed(1); options(Matrix.verbose = FALSE) > for(i in 1:(if(doExtras) 50 else 4)) { + mc <- mc0; mt <- mt0 ; m <- m0 + ev <- 1:5 %% 2 == round(runif(1))# 0 or 1 + j <- sample(ncol(mc), 1 + round(runif(1))) + nv <- rpois(sum(ev) * length(j), lambda = 1) + mc[ev, j] <- nv + m[ev, j] <- nv + mt[ev, j] <- nv + if(i %% 10 == 1) print(mc[ev,j, drop = FALSE]) + stopifnot(as.vector(mc[ev, j]) == nv, ## failed earlier... + as.vector(mt[ev, j]) == nv) + validObject(mc) ; assert.EQ.mat(mc, m) + validObject(mt) ; assert.EQ.mat(mt, m) + } 2 x 1 sparse Matrix of class "dgCMatrix" c5 r2 2 r4 . > showProc.time() Time (user system elapsed): 0.07 0.003 0.073 > options(Matrix.verbose = TRUE) > > mc # no longer has non-structural zeros 5 x 7 sparse Matrix of class "dgCMatrix" c1 c2 c3 c4 c5 c6 c7 r1 . . 2 4 . . 241 r2 . 42 . 3 . 202 . r3 3 . -1 . . . 243 r4 . . 1 . . . . r5 . 45 1 . . . . > mc[ii, jj] <- 1:6 > mc[c(2,5), c(3,5)] <- 3.2 > checkMatrix(mc) norm(m [5 x 7]) : 1 I F M ok Summary: ok as(., "nMatrix") giving full nonzero-pattern: ok 2*m =?= m+m: identical m >= m for all: ok m < m for none: ok > m. <- mc > mc[4,] <- 0 > mc 5 x 7 sparse Matrix of class "dgCMatrix" c1 c2 c3 c4 c5 c6 c7 r1 . . 2.0 4 . . 241 r2 . 1 3.2 3 3.2 202 . r3 3 . -1.0 . . . 243 r4 . . . . . . . r5 . 2 3.2 . 3.2 . . > > S <- as(Diagonal(5),"TsparseMatrix") > H <- Hilbert(9) > Hc <- as(round(H, 3), "CsparseMatrix")# a sparse matrix with no 0 ... > (trH <- tril(Hc[1:5, 1:5])) 5 x 5 sparse Matrix of class "dtCMatrix" [1,] 1.000 . . . . [2,] 0.500 0.333 . . . [3,] 0.333 0.250 0.200 . . [4,] 0.250 0.200 0.167 0.143 . [5,] 0.200 0.167 0.143 0.125 0.111 > stopifnot(is(trH, "triangularMatrix"), trH@uplo == "L", + is(S, "triangularMatrix")) > > ## triangular assignment > ## the slick (but inefficient in case of sparse!) way to assign sub-diagonals: > ## equivalent to tmp <- `diag<-`(S[,-1], -2:1); S[,-1] <- tmp > ## which dispatches to (x="TsparseMatrix", i="missing",j="index", value="replValue") > diag(S[,-1]) <- -2:1 # used to give a wrong warning M[i,j] <- v : coercing symmetric M[] into non-symmetric > S <- as(S,"triangularMatrix") > assert.EQ.mat(S, local({s <- diag(5); diag(s[,-1]) <- -2:1; s})) > > trH[c(1:2,4), c(2:3,5)] <- 0 # gave an *error* upto Jan.2008 > trH[ lower.tri(trH) ] <- 0 # ditto, because of callNextMethod() diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) 'sub-optimal sparse 'x[i] <- v' assignment: Coercing class dtTMatrix to dgTMatrix > > m <- Matrix(0+1:28, nrow = 4) > m[-3,c(2,4:5,7)] <- m[ 3, 1:4] <- m[1:3, 6] <- 0 > mT <- as(m, "TsparseMatrix") > stopifnot(identical(mT[lower.tri(mT)], + m [lower.tri(m) ])) > lM <- upper.tri(mT, diag=TRUE) > mT[lM] <- 0 diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > m[lM] <- 0 > assert.EQ.mat(mT, as(m,"matrix")) > mT[lM] <- -1:0 diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > m[lM] <- -1:0 > assert.EQ.mat(mT, as(m,"matrix")) > (mT <- drop0(mT)) 4 x 7 sparse Matrix of class "dgCMatrix" [1,] -1 . . -1 -1 -1 -1 [2,] 2 -1 -1 . . . . [3,] . . . -1 -1 -1 -1 [4,] 4 . 12 . . . . > > i <- c(1:2, 4, 6:7); j <- c(2:4,6) > H[i,j] <- 0 > (H. <- round(as(H, "sparseMatrix"), 3)[ , 2:7]) 9 x 6 sparse Matrix of class "dgCMatrix" [1,] . . . 0.200 . 0.143 [2,] . . . 0.167 . 0.125 [3,] 0.250 0.200 0.167 0.143 0.125 0.111 [4,] . . . 0.125 . 0.100 [5,] 0.167 0.143 0.125 0.111 0.100 0.091 [6,] . . . 0.100 . 0.083 [7,] . . . 0.091 . 0.077 [8,] 0.111 0.100 0.091 0.083 0.077 0.071 [9,] 0.100 0.091 0.083 0.077 0.071 0.067 > Hc. <- Hc > Hc.[i,j] <- 0 ## now "works", but setting "non-structural" 0s > stopifnot(as(Hc.[i,j], "matrix") == 0) > Hc.[, 1:6] 9 x 6 sparse Matrix of class "dgCMatrix" [1,] 1.000 . . . 0.200 . [2,] 0.500 . . . 0.167 . [3,] 0.333 0.250 0.200 0.167 0.143 0.125 [4,] 0.250 . . . 0.125 . [5,] 0.200 0.167 0.143 0.125 0.111 0.100 [6,] 0.167 . . . 0.100 . [7,] 0.143 . . . 0.091 . [8,] 0.125 0.111 0.100 0.091 0.083 0.077 [9,] 0.111 0.100 0.091 0.083 0.077 0.071 > > ## an example that failed for a long time > sy3 <- new("dsyMatrix", Dim = as.integer(c(2, 2)), x = c(14, -1, 2, -7)) > checkMatrix(dm <- kronecker(Diagonal(2), sy3))# now sparse with new kronecker norm(m [4 x 4]) : 1 I F suboptimal 'Arith' implementation of 'dsC* o dsC*' M ok Summary: ok as(., "nMatrix") giving full nonzero-pattern: ok 2*m =?= m+m: suboptimal 'Arith' implementation of 'dsC* o dsC*' identical m >= m for all: ok m < m for none: ok symmpart(m) + skewpart(m) == m: suboptimal 'Arith' implementation of 'dsC* o dsC*' ok; determinant(): ok > dm <- Matrix(as(dm, "matrix"))# -> "dsyMatrix" > (s2 <- as(dm, "sparseMatrix")) 4 x 4 sparse Matrix of class "dsCMatrix" [1,] 14 2 . . [2,] 2 -7 . . [3,] . . 14 2 [4,] . . 2 -7 > checkMatrix(st <- as(s2, "TsparseMatrix")) norm(m [4 x 4]) : 1 I F suboptimal 'Arith' implementation of 'dsC* o dsC*' M ok Summary: ok as(., "nMatrix") giving full nonzero-pattern: ok 2*m =?= m+m: suboptimal 'Arith' implementation of 'dsC* o dsC*' identical m >= m for all: ok m < m for none: ok symmpart(m) + skewpart(m) == m: suboptimal 'Arith' implementation of 'dsC* o dsC*' ok; determinant(): ok > stopifnot(is(s2, "symmetricMatrix"), + is(st, "symmetricMatrix")) > checkMatrix(s.32 <- st[1:3,1:2]) ## 3 x 2 - and *not* dsTMatrix norm(m [3 x 2]) : 1 I F M ok Summary: ok as(., "nMatrix") giving full nonzero-pattern: ok 2*m =?= m+m: ok m >= m for all: ok m < m for none: ok > checkMatrix(s2.32 <- s2[1:3,1:2]) norm(m [3 x 2]) : 1 I F M ok Summary: ok as(., "nMatrix") giving full nonzero-pattern: ok 2*m =?= m+m: identical m >= m for all: ok m < m for none: ok > I <- c(1,4:3) > stopifnot(is(s2.32, "generalMatrix"), + is(s.32, "generalMatrix"), + identical(as.mat(s.32), as.mat(s2.32)), + identical3(dm[1:3,-1], asD(s2[1:3,-1]), asD(st[1:3,-1])), + identical4(2, dm[4,3], s2[4,3], st[4,3]), + identical3(diag(dm), diag(s2), diag(st)), + is((cI <- s2[I,I]), "dsCMatrix"), + is((tI <- st[I,I]), "dsTMatrix"), + identical4(as.mat(dm)[I,I], as.mat(dm[I,I]), as.mat(tI), as.mat(cI)) + ) > > ## now sub-assign and check for consistency > ## symmetric subassign should keep symmetry > st[I,I] <- 0; checkMatrix(st); stopifnot(is(st,"symmetricMatrix")) norm(m [4 x 4]) : 1 I F suboptimal 'Arith' implementation of 'dsC* o dsC*' M ok Summary: ok as(., "nMatrix") giving full nonzero-pattern: ok 2*m =?= m+m: suboptimal 'Arith' implementation of 'dsC* o dsC*' identical m >= m for all: ok m < m for none: ok symmpart(m) + skewpart(m) == m: suboptimal 'Arith' implementation of 'dsC* o dsC*' ok; determinant(): ok > s2[I,I] <- 0; checkMatrix(s2); stopifnot(is(s2,"symmetricMatrix")) norm(m [4 x 4]) : 1 I F suboptimal 'Arith' implementation of 'dsC* o dsC*' M ok Summary: ok as(., "nMatrix") giving full nonzero-pattern: ok 2*m =?= m+m: suboptimal 'Arith' implementation of 'dsC* o dsC*' identical m >= m for all: ok m < m for none: ok symmpart(m) + skewpart(m) == m: suboptimal 'Arith' implementation of 'dsC* o dsC*' ok; determinant(): ok > ## > m <- as.mat(st) > m[2:1,2:1] <- 4:1 > st[2:1,2:1] <- 4:1 M[i,j] <- v : coercing symmetric M[] into non-symmetric > s2[2:1,2:1] <- 4:1 > stopifnot(identical(m, as.mat(st)), + 1:4 == as.vector(s2[1:2,1:2]), + identical(m, as.mat(s2))) > > ## now a slightly different situation for 's2' (had bug) > s2 <- as(dm, "sparseMatrix") > s2[I,I] <- 0; diag(s2)[2:3] <- -(1:2) > stopifnot(is(s2,"symmetricMatrix"), diag(s2) == c(0:-2,0)) > t2 <- as(s2, "TsparseMatrix") > m <- as.mat(s2) > s2[2:1,2:1] <- 4:1 > t2[2:1,2:1] <- 4:1 M[i,j] <- v : coercing symmetric M[] into non-symmetric > m[2:1,2:1] <- 4:1 > assert.EQ.mat(t2, m) > assert.EQ.mat(s2, m) > ## and the same (for a different s2 !) > s2[2:1,2:1] <- 4:1 > t2[2:1,2:1] <- 4:1 > assert.EQ.mat(t2, m)# ok > assert.EQ.mat(s2, m)# failed in 0.9975-8 > showProc.time() Time (user system elapsed): 0.161 0.003 0.163 > > ## sub-assign RsparseMatrix -- Matrix bug [#6709] by David Cortes > ## https://r-forge.r-project.org/tracker/?func=detail&atid=294&aid=6709&group_id=61 > ## simplified by MM > X <- new("dgCMatrix", i = c(0L,3L), p = c(0L,2L,2L,2L), x = c(100, -20), Dim = c(12L,3L)) > R <- as(X, "RsparseMatrix") > T <- as(R, "TsparseMatrix") > T[, 2] <- 22 # works fine > R[, 2] <- 22 # failed, as it called replTmat() giving narg() == 3 > ## now R is Tsparse (as documented on ../man/RsparseMatrix-class.Rd), > identical(R, T) ## but as this may change, rather R & T should have the same *content* [1] TRUE > assert.EQ.Mat(R, T) > > > ## m[cbind(i,j)] <- value: (2-column matrix subassignment): ------------------------- > m.[ cbind(3:5, 1:3) ] <- 1:3 > stopifnot(m.[3,1] == 1, m.[4,2] == 2) > nt. <- nt ; nt[rbind(2:3, 3:4, c(3,3))] <- FALSE > s. <- m. ; m.[cbind(3,4:6)] <- 0 ## assigning 0 where there *is* 0 .. > stopifnot(identical(nt.,nt), ## should not have changed + identical(s., m.)) > x.x[ cbind(2:6, 2:6)] <- 12:16 > stopifnot(isValid(x.x, "dsCMatrix"), + 12:16 == as.mat(x.x)[cbind(2:6, 2:6)]) > (ne1 <- (mc - m.) != 0) 5 x 7 sparse Matrix of class "lgCMatrix" c1 c2 c3 c4 c5 c6 c7 r1 . . : : . . : r2 . : : : : : . r3 | . : . . . : r4 . | | . . . . r5 . : | . : . . > stopifnot(identical(ne1, 0 != abs(mc - m.))) > (ge <- m. >= mc) # contains "=" -> result is dense 5 x 7 Matrix of class "lgeMatrix" c1 c2 c3 c4 c5 c6 c7 r1 TRUE TRUE TRUE TRUE TRUE TRUE TRUE r2 TRUE TRUE TRUE TRUE TRUE TRUE TRUE r3 FALSE TRUE TRUE TRUE TRUE TRUE TRUE r4 TRUE TRUE TRUE TRUE TRUE TRUE TRUE r5 TRUE TRUE FALSE TRUE TRUE TRUE TRUE > ne. <- mc != m. # was wrong (+ warning) > stopifnot(identical(!(m. < mc), m. >= mc), + identical(m. < mc, as(!ge, "sparseMatrix")), + identical(ne., drop0(ne1))) > > d6 <- Diagonal(6) > ii <- c(1:2, 4:5) > d6[cbind(ii,ii)] <- 7*ii > stopifnot(is(d6, "ddiMatrix"), identical(d6, Diagonal(x=c(7*1:2,1,7*4:5,1)))) > > sclass <- function(obj) as.vector(class(obj)) # as.v*(): drop attr(*,"package") > show2cls <- function(C,D, chr = "") + cat(sprintf("%s & %s%s: %s %s\n", + deparse(substitute(C)), deparse(substitute(D)), chr, + sclass(C), sclass(D))) > for(j in 2:6) { ## even and odd j used to behave differently + cat("j = ", j, ":\n-------\n") + M <- Matrix(0, j,j); m <- matrix(0, j,j) + T <- as(M, "TsparseMatrix") + TG <- as(T, "generalMatrix") + G <- as(M, "generalMatrix"); show2cls(TG, G) + stopifnot(is(TG, "TsparseMatrix"), + is(G, "CsparseMatrix")) + id <- cbind(1:j,1:j) + i2 <- cbind(1:j,j:1) + m[id] <- 1:j + M[id] <- 1:j + T[id] <- 1:j ; show2cls(M, T,' ("diag")') + stopifnot(is(M, "diagonalMatrix"), # since 2019-07 // FIXME (?!) for j=1 + is(T,"triangularMatrix"), isDiagonal(T)) # was "symmetricMatrix" + G[id] <- 1:j + TG[id]<- 1:j + m[i2] <- 10 + M[i2] <- 10 + T[i2] <- 10 ; show2cls(M, T,' ("symm")') + G[i2] <- 10 + TG[i2]<- 10 + ## + assert.EQ.mat(M, m) + assert.EQ.mat(T, m) + assert.EQ.mat(G, m) + assert.EQ.mat(TG,m) + } j = 2 : ------- TG & G: dgTMatrix dgCMatrix M & T ("diag"): ddiMatrix dtTMatrix M[ij] <- v : coercing symmetric M[] into non-symmetric M[ij] <- v : coercing symmetric M[] into non-symmetric M & T ("symm"): dgCMatrix dgTMatrix j = 3 : ------- TG & G: dgTMatrix dgCMatrix M & T ("diag"): ddiMatrix dtTMatrix M[ij] <- v : coercing symmetric M[] into non-symmetric M[ij] <- v : coercing symmetric M[] into non-symmetric M & T ("symm"): dgCMatrix dgTMatrix j = 4 : ------- TG & G: dgTMatrix dgCMatrix M & T ("diag"): ddiMatrix dtTMatrix M[ij] <- v : coercing symmetric M[] into non-symmetric M[ij] <- v : coercing symmetric M[] into non-symmetric M & T ("symm"): dgCMatrix dgTMatrix j = 5 : ------- TG & G: dgTMatrix dgCMatrix M & T ("diag"): ddiMatrix dtTMatrix M[ij] <- v : coercing symmetric M[] into non-symmetric M[ij] <- v : coercing symmetric M[] into non-symmetric M & T ("symm"): dgCMatrix dgTMatrix j = 6 : ------- TG & G: dgTMatrix dgCMatrix M & T ("diag"): ddiMatrix dtTMatrix M[ij] <- v : coercing symmetric M[] into non-symmetric M[ij] <- v : coercing symmetric M[] into non-symmetric M & T ("symm"): dgCMatrix dgTMatrix > > > ## drop, triangular, ... > (M3 <- Matrix(upper.tri(matrix(, 3, 3)))) # ltC; indexing used to fail 3 x 3 sparse Matrix of class "ltCMatrix" [1,] . | | [2,] . . | [3,] . . . > T3 <- as(M3, "TsparseMatrix") > stopifnot(identical(drop(M3), M3), + identical4(drop(M3[,2, drop = FALSE]), M3[,2, drop = TRUE], + drop(T3[,2, drop = FALSE]), T3[,2, drop = TRUE]), + is(T3, "triangularMatrix"), + !is(T3[,2, drop=FALSE], "triangularMatrix") + ) > > (T6 <- as(as(as(kronecker(Matrix(c(0,0,1,0),2,2), t(T3)), + "lMatrix"), "triangularMatrix"), "TsparseMatrix")) 6 x 6 sparse Matrix of class "ltTMatrix" [1,] . . . . . . [2,] . . . | . . [3,] . . . | | . [4,] . . . . . . [5,] . . . . . . [6,] . . . . . . > T6[1:4, -(1:3)] # failed (trying to coerce back to ltTMatrix) 4 x 3 sparse Matrix of class "lgTMatrix" [1,] . . . [2,] | . . [3,] | | . [4,] . . . > stopifnot(identical(T6[1:4, -(1:3)][2:3, -3], + spMatrix(2,2, i=c(1,2,2), j=c(1,1,2), x=rep(TRUE,3)))) > > M <- Diagonal(4); M[1,2] <- 2 > M. <- as(M, "CsparseMatrix") > (R <- as(M., "RsparseMatrix")) 4 x 4 sparse Matrix of class "dtRMatrix" [1,] 1 2 . . [2,] . 1 . . [3,] . . 1 . [4,] . . . 1 > (Ms <- symmpart(M.)) 4 x 4 sparse Matrix of class "dsCMatrix" [1,] 1 1 . . [2,] 1 1 . . [3,] . . 1 . [4,] . . . 1 > Rs <- as(Ms, "RsparseMatrix") > stopifnot(isValid(M, "triangularMatrix"), + isValid(M.,"triangularMatrix"), + isValid(Ms, "dsCMatrix"), + isValid(R, "dtRMatrix"), + isValid(Rs, "dsRMatrix") ) > stopifnot(dim(M[2:3, FALSE]) == c(2,0), + dim(R[2:3, FALSE]) == c(2,0), + identical(M [2:3,TRUE], M [2:3,]), + identical(M.[2:3,TRUE], M.[2:3,]), + identical(R [2:3,TRUE], R [2:3,]), + dim(R[FALSE, FALSE]) == c(0,0)) > > n <- 50000L > Lrg <- new("dgTMatrix", Dim = c(n,n)) > diag(Lrg) <- 1:n > dLrg <- as(Lrg, "diagonalMatrix") > stopifnot(identical(Diagonal(x = 1:n), dLrg)) > diag(dLrg) <- 1 + diag(dLrg) > Clrg <- as(Lrg,"CsparseMatrix") > Ctrg <- as(Clrg, "triangularMatrix") > diag(Ctrg) <- 1 + diag(Ctrg) > stopifnot(identical(Diagonal(x = 1+ 1:n), dLrg), + identical(Ctrg, as(dLrg,"CsparseMatrix"))) > > cc <- capture.output(show(dLrg))# show() used to error for large n > showProc.time() Time (user system elapsed): 0.125 0.007 0.133 > > ## FIXME: "dspMatrix" (symmetric *packed*) not going via "matrix" > > > ## Large Matrix indexing / subassignment > ## ------------------------------------- (from ex. by Imran Rashid) > n <- 7000000 > m <- 100000 > nnz <- 20000 > op <- options(Matrix.verbose = 2, warn = 1) > > set.seed(12) > f <- sparseMatrix(i = sample(n, size=nnz, replace=TRUE), + j = sample(m, size=nnz, replace=TRUE)) > str(f) Formal class 'ngCMatrix' [package "Matrix"] with 5 slots ..@ i : int [1:20000] 6692226 4657233 4490801 3688935 344371 6380246 2797160 3584813 6553304 2327896 ... ..@ p : int [1:99993] 0 1 1 1 1 1 1 1 1 1 ... ..@ Dim : int [1:2] 6999863 99992 ..@ Dimnames:List of 2 .. ..$ : NULL .. ..$ : NULL ..@ factors : list() > dim(f) # 6999863 x 99992 [1] 6999863 99992 > prod(dim(f)) # 699930301096 == 699'930'301'096 (~ 700'000 millions) [1] 699930301096 > str(thisCol <- f[,5000])# logi [~ 7 mio....] logi [1:6999863] FALSE FALSE FALSE FALSE FALSE FALSE ... > sv <- as(thisCol, "sparseVector") > str(sv) ## "empty" ! Formal class 'lsparseVector' [package "Matrix"] with 3 slots ..@ x : logi(0) ..@ length: int 6999863 ..@ i : int(0) > validObject(spCol <- f[,5000, drop=FALSE]) # "empty" [n x 1] ngCmatrix [1] TRUE > ## > ## *not* identical(): as(spCol, "sparseVector")@length is "double"prec: > stopifnot(all.equal(as(spCol, "sparseVector"), + as(sv, "nsparseVector"), tolerance=0)) > if(interactive()) + selectMethod("[<-", c("ngCMatrix", "missing","numeric", "logical")) > # -> replCmat() in ../R/Csparse.R > f[,5762] <- thisCol # now "fine" and fast thanks to replCmat() --> replCmat4() replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) > > fx <- sparseMatrix(i = sample(n, size=nnz, replace=TRUE), + j = sample(m, size=nnz, replace=TRUE), + x = round(10*rnorm(nnz))) > class(fx)## dgCMatrix [1] "dgCMatrix" attr(,"package") [1] "Matrix" > fx[,6000] <- (tC <- rep(thisCol, length.out=nrow(fx)))# fine replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) > thCol <- fx[,2000] > fx[,5762] <- thCol# fine replCmat[x,i,j,..,val] : nargs()=4; missing (i,j) = (1,0) > stopifnot(is(f, "ngCMatrix"), is(fx, "dgCMatrix"), + identical(thisCol, f[,5762]),# perfect + identical(as.logical(fx[,6000]), tC), + identical(thCol, fx[,5762])) > > showProc.time() Time (user system elapsed): 0.416 0.05 0.465 > options(op)# revert > ## > if(doExtras) {#----------------------------------------------------------------- + cat("checkMatrix() of all: \n---------\n") + Sys.setlocale("LC_COLLATE", "C")# to keep ls() reproducible + for(nm in ls()) if(is(.m <- get(nm), "Matrix")) { + cat(nm, "\n") + checkMatrix(.m, verbose = FALSE + , doDet = nm != "As" ## <- "As" almost singular <=> det() "ill posed" + ) + } + showProc.time() + }#--------------end if(doExtras) ----------------------------------------------- > > ## Bugs found by Peter Ralph > n <- 17 > x <- Matrix(0, n,n) # "ddiMatrix" now > ## x must have at least three nonzero entries > x[1,1] <- x[2,1:2] <- 1.; class(x) # "dtC" [1] "dtCMatrix" attr(,"package") [1] "Matrix" > x0 <- x <- as(x,"generalMatrix") # if x is dgCMatrix, no error > ## > z <- matrix(x) # <== not the "Matrix way": a (n, 1) matrix > z[1] <- 0 > > x[1:n, 1:n] <- as(z, "sparseVector") > ## gave Error: ... invalid subscript type 'S4' > x2 <- x > > dim(zC <- as(z, "CsparseMatrix")) [1] 289 1 > x <- x0 > x[] <- zC # did fail, then gave warning. diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > x1 <- x > ## > x <- x0 > x[] <- as(zC, "sparseVector") # did fail, too diagnosing replTmat(x,i,j,v): nargs()= 3; missing (i,j) = (0,1) > x2 <- x > stopifnot(identical(x1,x2)) > x <- as(x0, "matrix") > x[] <- z > assert.EQ.mat(x1, x) > > i <- 4:7 > x1 <- x0; x1[cbind(i, i+10)] <- i^2 > x2 <- x0; x2[cbind(i, i+10)] <- as(i^2, "matrix") > ## failed: nargs() = 4 ... please report > > class(x1) # was "dgT", now "dgC" [1] "dgCMatrix" attr(,"package") [1] "Matrix" > stopifnot(isValid(x1, class(x1)), identical(x1, x2)) > showProc.time() Time (user system elapsed): 0.011 0 0.012 > > > ## check valid indexing (using *random* indices, often duplicated): > chk_dsp_ind <- function(sv, n=512, negI = FALSE, verbose=FALSE) { + stopifnot(inherits(sv, "dsparseVector"), n >= 1) + d <- length(sv) + ## lambda=2 ==> aiming for short 'i' {easier to work with} + P <- rpois(n, lambda = if(negI) 5 else 2) + for(i in seq_len(n)) { + I <- + if(negI) { # negative indices: 2 are, 4 neither ... always "valid" !! + k <- max(4L, d - max(1L, P[i])) + if(verbose) cat(sprintf("size=k = %2d: ", k)) + - sort(sample.int(d, size=k))# replace=FALSE + } + else + sample.int(d, size=1L+P[i], replace=TRUE) + ## + validObject(ss <- sv[I]) # Error if not true + } + invisible() + } > s <- as(c(3,5,6), "sparseVector") > set.seed(11); chk_dsp_ind(s) > set.seed(3) > (s2 <- as(rsparsematrix(ncol=1, nrow=37, density=1/4),"sparseVector")) sparse vector (nnz/length = 9/37) of class "dsparseVector" [1] . . . -2.200 . . 0.330 . -1.300 . [11] . 0.950 . 0.140 . . 0.810 . . 0.540 [21] . . . . . . . . . 0.013 [31] . . -0.580 . . . . > (s3 <- as(rsparsematrix(ncol=1, nrow=64, density=1/4),"sparseVector")) sparse vector (nnz/length = 16/64) of class "dsparseVector" [1] . . . . . . . . 1.80 . 2.50 . [13] . . -0.76 . . . -0.58 . . . -0.80 0.84 [25] . . 1.30 . . . -0.51 . . . . -0.62 [37] . . . 0.71 . . . . . . -1.30 . [49] -1.60 . . . . 0.10 . . -1.30 . 0.18 . [61] . . . -1.30 > set.seed(1) > chk_dsp_ind(s2) > chk_dsp_ind(s3) > ## > set.seed(47) > ## system.time(e.N2 <- chk_dsp_ind(s2, negI=TRUE, verbose=TRUE)) > chk_dsp_ind(s2, negI=TRUE) > chk_dsp_ind(s3, negI=TRUE) > > iv <- c(rep(0,100), 3, 0,0,7,0,0,0) > sv0 <- sv <- as(iv, "sparseVector") > sv.0 <- sv. <- as(as.integer(iv), "sparseVector") > stopifnot(canCoerce("integer", "sparseVector")) > sv2 <- as(sv, "isparseVector") > stopifnot(validObject(sv), validObject(sv2), identical(sv., sv2), + sv == sv.) > n0 <- sv. != 0 # -> is "lsparseV.." > > sv [n0] <- sv [n0] > sv.[n0] <- sv.[n0] # gave error > stopifnot(identical(sv , sv0), + identical(sv., sv.0)) > sv [3:7] <- 0 > sv.[3:7] <- 0L > stopifnot(identical(sv , sv0), identical(sv., sv.0)) > sv [2:4] <- 2:4 > sv.[2:4] <- 2:4 > stopifnot(which(sv != 0) == (which(sv. != 0) -> in0), + in0 == c(2:4, 101L, 104L)) > sv [2:6] <- 0L > sv.[2:6] <- 0L > stopifnot(identical(sv , sv0), identical(sv., sv.0)) > > ## the next six *all* gave an error -- but should be no-op's: > for(vv in list(sv, sv.0)) + for(ind in list(0, FALSE, logical(length(vv)))) + vv[ind] <- NA > stopifnot(identical(sv , sv0), identical(sv., sv.0)) > > ## [i] <- val -- failed to resort @i sometimes: (R-forge Matrix bug #6659) > y1 <- sparseVector(1:3, 13:15, 16) > y2 <- sparseVector(1:6, c(5, 6, 7, 9, 14, 15), 16) > i <- 1:16*12 # 12 24 36 ... 192 > x <- sparseVector(numeric(1), 1, length=200) > x[i] <- y1 ; validObject(x[i]) # TRUE [1] TRUE > N <- x[i] + y2 ; validObject( N ) # TRUE [1] TRUE > x[i] <- N ## <== bug was here .. > validObject(x) [1] TRUE > ## gave 'Error' invalid .."dsparseVector".. 'i' must be sorted strictly increasingly > stopifnot(all.equal(x[i] , y1+y2, tolerance=0), + x[i] == y1+y2) > showProc.time() Time (user system elapsed): 0.24 0.003 0.243 > > if(!interactive()) warnings() > > ## [matrix-Bugs][#6720] Subsetting with empty indices does not drop -- 17 Apr 2021, by David Cortes > ## https://r-forge.r-project.org/tracker/?func=detail&atid=294&aid=6720&group_id=61 > > ## extended by MM to all versions of "empty" : > x <- c(1,8) > (m1 <- rbind(x)) [,1] [,2] x 1 8 > m1[] # remains matrix [,1] [,2] x 1 8 > m1[,,drop=FALSE] # ditto [,1] [,2] x 1 8 > m1[,] # [1] 1 2 -- drops (as default drop=TRUE !) [1] 1 8 > > ## Sparse Matrix and actually *any* Matrix-extending class did not work > (M1 <- as(m1, "denseMatrix")) # "dgeMatrix" 1 x 2 Matrix of class "dgeMatrix" [,1] [,2] x 1 8 > S1 <- as(m1, "CsparseMatrix") > R1 <- as(m1, "RsparseMatrix") > stopifnot(exprs = { + identical(M1[], M1) # remains + identical(S1[], S1) # remains + identical(R1[], R1) # remains + identical(M1[,,drop=FALSE], M1) # ditto + identical(S1[,,drop=FALSE], S1) # " + identical(R1[,,drop=FALSE], R1) # " + ## but drop=TRUE which is the *default* much be obeyed (also for *empty* (i,j): + identical(m1[,], x) + identical(M1[,], x) # should drop, but did not + identical(S1[,], x) # " + identical(R1[,], x) # " + identical(m1[,,drop=TRUE], x) + identical(M1[,,drop=TRUE], x) # should drop, but did not + identical(S1[,,drop=TRUE], x) # " + identical(R1[,,drop=TRUE], x) # " + }) > > > ## [matrix-Bugs][#6721] Assignment to 'dgRMatrix' with missing index takes only first element > ## MM: This has been fixed already! > X <- rbind(0, 1:3, 0, c(0,1,0)) > Rx <- as(X, "RsparseMatrix") > Cx <- as(X, "CsparseMatrix") > X [2,] <- 0 > Cx[2,] <- 0 > Rx[2,] <- 0 > stopifnot(all(Cx == X), + all(Rx == X)) > > ## [matrix-Bugs][#6745] show() > ## NB: is from a bug in head(*); *only* applies to *empty* sparseV: length(x@i) == 0 > op <- options(max.print=999) > ( s0 <- sparseVector(i=integer(), length=2^33)) # show -> head() failed in Matrix <= 1.3-* sparse vector (nnz/length = 0/8589934592) of class "nsparseVector" [1] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [38] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [75] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [112] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [149] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [186] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [223] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [260] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [297] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [334] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [371] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [408] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [445] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [482] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [519] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [556] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [593] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [630] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [667] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [704] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [741] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [778] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [815] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [852] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [889] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [926] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [963] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ............................ ........suppressing 8589933593 entries in show(); maybe adjust options(max.print=) ............................ > (xs0 <- sparseVector(i=integer(), length=2^33, x = numeric()))# ditto sparse vector (nnz/length = 0/8589934592) of class "dsparseVector" [1] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [38] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [75] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [112] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [149] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [186] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [223] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [260] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [297] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [334] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [371] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [408] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [445] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [482] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [519] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [556] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [593] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [630] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [667] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [704] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [741] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [778] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [815] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [852] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [889] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [926] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [963] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ............................ ........suppressing 8589933593 entries in show(); maybe adjust options(max.print=) ............................ > options(op); tail(s0) ; tail(xs0) # (always worked) sparse vector (nnz/length = 0/6) of class "nsparseVector" [1] . . . . . . sparse vector (nnz/length = 0/6) of class "dsparseVector" [1] . . . . . . > ## *related* bug in `[` --> needed to fix intIv() for such large sparseVectors > stopifnot(exprs = { + identical(s0[length(s0) - 3:0], # gave Error in if (any(i < 0L)) { : missing value .... + new("nsparseVector", i=integer(), length=4L)) + identical(xs0[length(s0) - 3:0], # gave Error .. + new("dsparseVector", i=integer(), length=4L)) + }) > > ## Yielded an invalid object in Matrix <= 1.4-1, instead of throwing error > llc04 <- new("dgCMatrix", Dim = c(4L, 0L)) > c40 <- new("dgCMatrix", Dim = c(0L, 4L), p = integer(5L)) > assertError(c04[1L, ] <- 1) > assertError(c40[, 1L] <- 1) > > ## Indexing with nMatrix rather than lMatrix > set.seed(3601) > gC <- rsparsematrix(6, 6, 0.6) > gC@x[sample.int(length(gC@x), 6L)] <- NA > ni <- is.na(gC) > li <- as(ni, "lMatrix") > stopifnot(identical(gC[ ni], gC[ li]), + identical(gC[!ni], gC[!li])) > > ## Dispatch thinko in Matrix <= 1.5-4 > R0 <- R. <- + new("dgRMatrix", + Dim = c(12L, 12L), + p = c(0L, 0L, 4L, 5L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 16L), + j = c(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 7L, 8L, 4L, 7L, 9L, 9L, 10L, 11L), + x = as.double(1:16)) > R.[1:2, ] <- R.[1:2, ] # was an error > stopifnot(identical(R0, as(R., "RsparseMatrix"))) > > ## Didn't drop dimensions ... > stopifnot(identical(t(as(1:6,"CsparseMatrix"))[TRUE, ], as.double(1:6))) > > ## Was briefly wrong prior to Matrix 1.6-0 > set.seed(0) > S <- new("dsyMatrix", Dim = c(4L, 4L), x = rnorm(16L)) > Sii <- S[4:1, 4:1] > stopifnot(exprs = { + is(Sii, "dsyMatrix") + Sii@uplo == "L" + identical(as(Sii, "matrix"), as(S, "matrix")[4:1, 4:1]) + }) > > ## Bug #6839: regression in <.s[CT]Matrix>[] in Matrix 1.6-z > x <- new("dsCMatrix", Dim = c(4L, 4L), + p = cumsum(0:4), i = sequence(1:4) - 1L, x = as.double(1:10)) > i <- c(TRUE, FALSE) > xi <- as(x, "matrix")[i] > for(cl in paste0(c("C", "R", "T"), "sparseMatrix")) + stopifnot(identical(as(x, cl)[i], xi)) > > proc.time() user system elapsed 2.300 0.127 2.425 Matrix/tests/validObj.R0000644000175100001440000001610014575137654014572 0ustar hornikuserslibrary(Matrix) ### Do all kinds of object creation and coercion source(system.file("test-tools.R", package = "Matrix")) .drop.factors <- function(x, check = FALSE) `slot<-`(x, "factors", check = check, value = list()) ## the empty ones: checkMatrix(new("dgeMatrix")) checkMatrix(Matrix(,0,0)) ## "dge" assertError( new("dgeMatrix", Dim = c(2,2), x= 1:4) )# double 'Dim' assertError( new("dgeMatrix", Dim = as.integer(c(2,2)), x= 1:4) )# int 'x' assertError( new("dgeMatrix", Dim = 2:2, x=as.double(1:4)) )# length(Dim) !=2 assertError( new("dgeMatrix", Dim = as.integer(c(2,2)), x= as.double(1:5))) checkMatrix(m1 <- Matrix(1:6, ncol=2)) checkMatrix(m2 <- Matrix(1:7 +0, ncol=3)) # a (desired) warning c("dgeMatrix", "ddenseMatrix", "generalMatrix", "dMatrix", "denseMatrix", "Matrix") -> m1.cl stopifnot(!anyNA(match(m1.cl, is(m1))), dim(t(m1)) == 2:3, identical(m1, t(t(m1)))) c.nam <- paste("C",1:2, sep='') dimnames(m1) <- list(NULL, c.nam) checkMatrix(m1) # failed in 0.999375-10 checkMatrix(tm1 <- t(m1)) stopifnot(colnames(m1) == c.nam, identical(dimnames(tm1), list(c.nam, NULL)), identical(m1, t(tm1))) ## an example of *named* dimnames (t34N <- as(unclass(table(x = gl(3,4), y=gl(4,3))), "unpackedMatrix")) stopifnot(identical(dimnames(t34N), dimnames(as(t34N, "matrix"))), identical(t34N, t(t(t34N)))) ## "dpo" checkMatrix(cm <- crossprod(m1)) checkMatrix(cp <- as(cm, "packedMatrix"))# 'dpp' + factors checkMatrix(cs <- as(cm, "dsyMatrix"))# 'dsy' + factors checkMatrix(dcm <- as(cm, "generalMatrix"))#'dge' checkMatrix(mcm <- as(cm, "dMatrix")) # 'dsy' + factors -- buglet? rather == cm? checkMatrix(mc. <- as(cm, "Matrix")) # dpo --> dsy -- (as above) FIXME? ?? stopifnot(identical(mc., mcm), identical(.drop.factors(cm), (2*cm)/2),# remains dpo identical(cm + cp, cp + cs),# dge identical(mc., mcm), all(2*cm == mcm * 2)) checkMatrix(eq <- cm == cs) stopifnot(all(eq@x), identical3(pack(eq), cs == cp, cm == cp), as.logical(!(cs < cp)), identical4(!(cs < cp), !(cp > cs), cp <= cs, cs >= cp)) ## Coercion to 'dpo' should give an error if result would be invalid M <- Matrix(diag(4) - 1) assertError(as(M, "dpoMatrix")) M. <- as(M, "generalMatrix") M.[1,2] <- 10 # -> not even symmetric anymore assertError(as(M., "dpoMatrix")) ## Cholesky checkMatrix(ch <- chol(cm)) checkMatrix(ch2 <- chol(as(cm, "dsyMatrix"))) checkMatrix(ch3 <- chol(as(cm, "generalMatrix"))) stopifnot(is.all.equal3(as(ch, "matrix"), as(ch2, "matrix"), as(ch3, "matrix"))) ### Very basic triangular matrix stuff assertError( new("dtrMatrix", Dim = c(2,2), x= 1:4) )# double 'Dim' assertError( new("dtrMatrix", Dim = as.integer(c(2,2)), x= 1:4) )# int 'x' ## This caused a segfault (before revision r1172 in ../src/dtrMatrix.c): assertError( new("dtrMatrix", Dim = 2:2, x=as.double(1:4)) )# length(Dim) !=2 assertError( new("dtrMatrix", Dim = as.integer(c(2,2)), x= as.double(1:5))) tr22 <- new("dtrMatrix", Dim = as.integer(c(2,2)), x=as.double(1:4)) tt22 <- t(tr22) (tPt <- tr22 + tt22) stopifnot(identical(10 * tPt, tPt * 10), as.vector(t.22 <- (tr22 / .5)* .5) == c(1,0,3,4), TRUE) ## not yet: class(t.22) == "dtrMatrix") ## non-square triagonal Matrices --- are forbidden --- assertError(new("dtrMatrix", Dim = 2:3, x=as.double(1:6), uplo="L", diag="U")) n <- 3:3 assertError(new("dtCMatrix", Dim = c(n,n), diag = "U")) validObject(T <- new("dtTMatrix", Dim = c(n,n), diag = "U")) validObject(M <- new("dtCMatrix", Dim = c(n,n), diag = "U", p = rep.int(0:0, n+1))) stopifnot(identical(as.mat(T), diag(n))) suppressWarnings(RNGversion("3.5.0")); set.seed(3) (p9 <- p9. <- as(sample(9), "pMatrix")) (np9 <- np9. <- as(p9, "TsparseMatrix")) p9.[1,1] <- np9.[1,1] <- TRUE stopifnot(is.logical(p9[1,]), is(p9[2,, drop=FALSE], "indMatrix"), is(p9[9:1,], "indMatrix"), isTRUE(p9[-c(1:6, 8:9), 1]), identical(t(p9), solve(p9)), identical(p9[TRUE, ], p9), identical(p9[, TRUE], p9), identical(p9., np9.), identical(as(diag(9), "pMatrix"), as(1:9, "pMatrix")) ) assert.EQ.mat(p9[TRUE,], as.matrix(np9)) ## validObject --> Cparse_validate(.) mm <- new("dgCMatrix", Dim = c(3L, 5L), i = c(2L, 0L, 1L, 2L, 0L, 1L), x = c( 2, 1, 1, 2, 1, 2), p = c(0:2, 4L, 4L, 6L)) ## Previously unsorted columns were sorted - now are flagged as invalid m. <- mm ip <- c(1:2, 4:3, 6:5) # permute the 'i' and 'x' slot just "inside column": m.@i <- m.i <- mm@i[ip] m.@x <- m.x <- mm@x[ip] stopifnot(identical(1L, grep("not increasing within columns", validObject(m., test = TRUE)))) .validateCsparse(m., TRUE) # don't use this at home, boys! m. # now is fixed ## Make sure that validObject() objects... ## 1) to wrong 'p' m. <- mm; m.@p[1] <- 1L stopifnot(identical(1L, grep("first element of 'p' slot", validObject(m., test = TRUE)))) m.@p <- mm@p[c(1,3:2,4:6)] stopifnot(identical(1L, grep("not nondecreasing", validObject(m., test = TRUE)))) ## 2) to non-strictly increasing i's: m. <- mm ; ix <- c(1:3,3,5:6) m.@i <- mm@i[ix] m.@x <- mm@x[ix] stopifnot(identical(1L, grep("not increasing within columns", validObject(m., test = TRUE)))) ## ix <- c(1:3, 3:6) # now the the (i,x) slots are too large (and decreasing at end) ## m.@i <- mm@i[ix] ## m.@x <- mm@x[ix] ## stopifnot(identical(grep("^slot i is not.* increasing .*sort", ## (msg <- validObject(m., test=TRUE))),# seg.fault in the past ## 1L)) ## over-allocation of the i- and x- slot should be allowed: ## (though it does not really help in M[.,.] <- * yet) m. <- mm m.@i <- c(mm@i, NA, NA, NA) m.@x <- c(mm@x, 10:12) validObject(m.) m. # show() now works stopifnot(all(m. == mm), # in spite of length(m.@i) > length(mm@i), identical(t(t(m.)), mm), identical3(m. * m., m. * mm, mm * mm)) m.[1,4] <- 99 ## FIXME: warning and cuts (!) the over-allocated slots ## Low-level construction of invalid object: ## Ensure that it does *NOT* segfault foo <- new("ngCMatrix", i = as.integer(c(12204, 16799, 16799, 33517, 1128, 11930, 1128, 11930, 32183)), p = rep(0:9, c(2,4,1,11,10,0,1,0,9,12)), Dim = c(36952L, 49L)) validObject(foo)# TRUE foo@i[5] <- foo@i[5] + 50000L msg <- validObject(foo, test=TRUE)# is -- correctly -- *not* valid anymore stopifnot(is.character(msg)) ## Error in validObject(foo) : ## invalid class "ngCMatrix" object: all row indices must be between 0 and nrow-1 getLastMsg <- function(tryRes) { ## Extract "final" message from erronous try result sub("\n$", "", sub("^.*: ", "", as.character(tryRes))) } t1 <- try(show(foo)) # error t2 <- try(head(foo)) # error, but previously a segfault stopifnot(identical(msg, getLastMsg(t1)), identical(msg, getLastMsg(t2))) ## test that all prototypes of nonvirtual classes are valid for (cl in c(names(getClassDef("Matrix")@subclasses), names(getClassDef("MatrixFactorization")@subclasses))) if(!isVirtualClass(def <- getClassDef(cl))) validObject(new(def)) cat('Time elapsed: ', proc.time(),'\n') # "stats" if(!interactive()) warnings() Matrix/tests/factorizing.R0000644000175100001440000006757114545303537015371 0ustar hornikusers#### Matrix Factorizations --- of all kinds ## for R_DEFAULT_PACKAGES=NULL : library(stats) library(utils) library(Matrix) source(system.file("test-tools.R", package = "Matrix"))# identical3() etc options(warn = 0) is64bit <- .Machine$sizeof.pointer == 8 cat("doExtras:", doExtras,"; is64bit:", is64bit, "\n") ### "sparseQR" : Check consistency of methods ## -------- data(KNex, package = "Matrix") mm <- KNex$mm y <- KNex$y stopifnot(is((Y <- Matrix(y)), "dgeMatrix")) md <- as(mm, "matrix") # dense (cS <- system.time(Sq <- qr(mm))) # 0.009 (cD <- system.time(Dq <- qr(md))) # 0.499 (lynne, 2014 f); 1.04 lynne 2019 ????? cD[1] / cS[1] # dense is much ( ~ 100--170 times) slower ## chkQR() in ../inst/test-tools-1.R ; if(doExtras) { ## ~ 20 sec {"large" example} + 2x qr.R() warnings cat("chkQR( ) .. takes time .. ") system.time(chkQR(mm, y=y, a.qr = Sq, verbose=TRUE)) system.time(chkQR(md, y=y, a.qr = Dq, verbose=TRUE)) cat(" done: [Ok]\n") } ## consistency of results dense and sparse ## chk.qr.D.S() and checkQR.DS.both() >>> ../inst/test-tools-Matrix.R chk.qr.D.S(Dq, Sq, y, Y) ## Another small example with pivoting (and column name "mess"): suppressWarnings(RNGversion("3.5.0")); set.seed(1) X <- rsparsematrix(9,5, 1/4, dimnames=list(paste0("r", 1:9), LETTERS[1:5])) qX <- qr(X); qd <- qr(as(X, "matrix")) ## are the same (now, *including* names): assert.EQ(print(qr.coef(qX, 1:9)), qr.coef(qd, 1:9), tol=1e-14) chk.qr.D.S(d. = qd, s. = qX, y = 1:9) ## rank deficient QR cases: --------------- ## From Simon (15 Jul 2009) + dimnames (11 May 2015) set.seed(10) a <- matrix(round(10 * runif(90)), 10,9, dimnames = list(LETTERS[1:10], paste0("c", 1:9))) a[a < 7.5] <- 0 (A <- Matrix(a))# first column = all zeros qD <- chkQR(a, giveRE=TRUE) ## using base qr qS <- chkQR(A, giveRE=TRUE) ## using Matrix "sparse qr" -- "structurally rank deficient! validObject(qS)# with the validity now (2012-11-18) -- ok, also for "bad" case ## Here, have illegal access Up[-1] in ../src/cs.c try( ## After patch (2016-10-04 - *NOT* committed), this fails ## definitely "fails" (with good singularity message) after c3194 (cs.c): chk.qr.D.S(qD, qS, y = 10 + 1:nrow(A), force=TRUE)# 6 warnings: "structurally rank deficient" ) try( ## NOTE: *Both* checks currently fail here: chkQR(A, Qinv.chk=TRUE, QtQ.chk=TRUE) ) ## Larger Scale random testing oo <- options(Matrix.quiet.qr.R = TRUE, Matrix.verbose = TRUE, nwarnings = 1e4) set.seed(101) quiet <- doExtras for(N in 1:(if(doExtras) 1008 else 24)) { A <- rsparsematrix(8,5, nnz = rpois(1, lambda=16)) cat(sprintf(if(quiet) "%d " else "%4d -", N)); if(quiet && N %% 50 == 0) cat("\n") checkQR.DS.both(A, Qinv.chk= NA, QtQ.chk=NA, quiet=quiet, ## --- => FALSE if struct. rank deficient giveRE = FALSE, tol = 1e-12) ## with doExtras = TRUE, 64bit (F34, R 4.3.0-dev. 2022-05): seen 8.188e-13 } summary(warnings()) ## Look at single "hard" cases: -------------------------------------- ## This is *REALLY* nice and small : A0 <- new("dgCMatrix", Dim = 4:3, i = c(0:3, 3L), p = c(0L, 3:5), x = rep(1,5)) A0 checkQR.DS.both(A0, Qinv.chk = FALSE, QtQ.chk=FALSE) ## ----- *both* still needed : try( checkQR.DS.both(A0, TRUE, FALSE) ) try( checkQR.DS.both(A0, FALSE, TRUE) ) ## and the same when dropping the first row { --> 3 x 3 }: A1 <- A0[-1 ,] checkQR.DS.both(A1, Qinv.chk = FALSE, QtQ.chk=FALSE) ## ----- *both* still needed : try( checkQR.DS.both(A1, TRUE, FALSE) ) try( checkQR.DS.both(A1, FALSE, TRUE) ) qa <- qr(as(A0,"matrix")) qA <- qr(A0) # -> message: ".. Matrix structurally rank deficient" drop0(crossprod( Qd <- qr.Q(qa) ), 1e-15) # perfect = diag( 3 ) drop0(crossprod( Qs <- qr.Q(qA) ), 1e-15) # R[3,3] == 0 -- OOPS! ## OTOH, qr.R() is fine, as checked in the checkQR.DS.both(A0, *) above ## zero-row *and* zero-column : (A2 <- new("dgCMatrix", i = c(0L, 1L, 4L, 7L, 5L, 2L, 4L) , p = c(0L, 3L, 4L, 4L, 5L, 7L) , Dim = c(8L, 5L) , x = c(0.92, 1.06, -1.74, 0.74, 0.19, -0.63, 0.68))) checkQR.DS.both(A2, Qinv.chk = FALSE, QtQ.chk=FALSE) ## ----- *both* still needed : try( checkQR.DS.both(A2, TRUE, FALSE) ) try( checkQR.DS.both(A2, FALSE, TRUE) ) ## Case of *NO* zero-row or zero-column: (A3 <- new("dgCMatrix", Dim = 6:5 , i = c(0L, 2L, 4L, 0L, 1L, 5L, 1L, 3L, 0L) , p = c(0L, 1L, 3L, 6L, 8L, 9L) , x = c(40, -54, -157, -28, 75, 166, 134, 3, -152))) checkQR.DS.both(A3, Qinv.chk = FALSE, QtQ.chk=FALSE) ## ----- *both* still needed : try( checkQR.DS.both(A3, TRUE, FALSE) ) try( checkQR.DS.both(A3, FALSE, TRUE) ) (A4 <- new("dgCMatrix", Dim = c(7L, 5L) , i = c(1:2, 4L, 6L, 1L, 5L, 0:3, 0L, 2:4) , p = c(0L, 4L, 6L, 10L, 10L, 14L) , x = c(9, -8, 1, -9, 1, 10, -1, -2, 6, 14, 10, 2, 12, -9))) checkQR.DS.both(A4, Qinv.chk = FALSE, QtQ.chk=FALSE) ## ----- *both* still needed : try( checkQR.DS.both(A4, TRUE, FALSE) ) try( checkQR.DS.both(A4, FALSE, TRUE) ) (A5 <- new("dgCMatrix", Dim = c(4L, 4L) , i = c(2L, 2L, 0:1, 0L, 2:3), p = c(0:2, 4L, 7L) , x = c(48, 242, 88, 18, -167, -179, 18))) checkQR.DS.both(A5, Qinv.chk = FALSE, QtQ.chk=FALSE) ## ----- *both* still needed : try( checkQR.DS.both(A5, TRUE, FALSE) ) try( checkQR.DS.both(A5, FALSE, TRUE) ) quiet <- doExtras for(N in 1:(if(doExtras) 2^12 else 128)) { A <- round(100*rsparsematrix(5,3, nnz = min(15,rpois(1, lambda=10)))) if(any(apply(A, 2, function(x) all(x == 0)))) ## "column of all 0" next cat(sprintf(if(quiet) "%d " else "%4d -", N)); if(quiet && N %% 50 == 0) cat("\n") checkQR.DS.both(A, Qinv.chk=NA, giveRE=FALSE, tol = 1e-12, quiet = quiet) ## --- => FALSE if struct. rank deficient } summary(warnings()) options(oo) ### "denseLU" ## Testing expansions of factorizations {was ./expand.R, then in simple.R } ## new: [m x n] where m and n may differ x. <- c(2^(0:5),9:1,-3:8, round(sqrt(0:16))) set.seed(1) for(nnn in 1:100) { y <- sample(x., replace=TRUE) m <- sample(2:6, 1) n <- sample(2:7, 1) x <- matrix(seq_len(m*n), m,n) lux <- lu(x)# occasionally a warning about exact singularity xx <- with(expand(lux), (P %*% L %*% U)) print(dim(xx)) assert.EQ.mat(xx, x, tol = 16*.Machine$double.eps) } ### "sparseLU" por1 <- readMM(system.file("external/pores_1.mtx", package = "Matrix")) lu1 <- lu(por1) pm <- as(por1, "CsparseMatrix") (pmLU <- lu(pm)) # -> show() xp <- expand(pmLU) ## permute rows and columns of original matrix ppm <- pm[pmLU@p + 1:1, pmLU@q + 1:1] Ppm <- pmLU@L %*% pmLU@U ## identical only as long as we don't keep the original class info: stopifnot(identical3(lu1, pmLU, pm@factors$sparseLU),# TODO === por1@factors$LU identical(ppm, with(xp, P %*% pm %*% t(Q))), sapply(xp, is, class2="Matrix")) Ipm <- solve(pm, sparse=FALSE) Spm <- solve(pm, sparse=TRUE) # is not sparse at all, here assert.EQ.Mat(Ipm, Spm, giveRE=TRUE, tol = 1e-13)# seen 7.36e-15 only on 32-bit stopifnot(abs(as.vector(solve(Diagonal(30, x=10) %*% pm) / Ipm) - 1/10) < 1e-7, abs(as.vector(solve(rep.int(4, 30) * pm) / Ipm) - 1/ 4) < 1e-7) ## these two should be the same, and `are' in some ways: assert.EQ.mat(ppm, as(Ppm, "matrix"), tol = 1e-14, giveRE=TRUE) ## *however* length(ppm@x)# 180 length(Ppm@x)# 317 ! table(Ppm@x == 0)# (194, 123) - has 123 "zero" and 14 ``almost zero" entries ##-- determinant() and det() --- working via LU --- m <- matrix(c(0, NA, 0, NA, NA, 0, 0, 0, 1), 3,3) m0 <- rbind(0,cbind(0,m)) M <- as(m,"Matrix"); M ## "dsCMatrix" ... M0 <- rbind(0, cbind(0, M)) dM <- as(M, "denseMatrix") dM0 <- as(M0,"denseMatrix") try( lum <- lu(M) )# Err: "near-singular A" (lum <- lu(M, errSing=FALSE))# NA --- *BUT* it is not stored in @factors (lum0 <- lu(M0, errSing=FALSE))# NA --- and it is stored in M0@factors[["LU"]] ## "FIXME" - TODO: Consider replNA <- function(x, value) { x[is.na(x)] <- value ; x } (EL.1 <- expand(lu.1 <- lu(M.1 <- replNA(M, -10)))) ## so it's quite clear how lu() of the *singular* matrix M should work ## but it's not supported by the C code in ../src/cs.c which errors out stopifnot(all.equal(M.1, with(EL.1, t(P) %*% L %*% U %*% Q)), is.na(det(M)), is.na(det(dM)), is.na(det(M0)), is.na(det(dM0)) ) ###________ Cholesky() ________ ##-------- LDL' ---- small exact examples set.seed(1) for(n in c(5:12)) { cat("\nn = ",n,"\n-------\n") rr <- mkLDL(n) ## -------- from 'test-tools.R' stopifnot(all(with(rr, A == as(L %*% D %*% t(L), "symmetricMatrix"))), all(with(rr, A == tcrossprod(L %*% sqrt(D))))) d <- rr$d.half A <- rr$A .A <- as(A, "TsparseMatrix") # 'factors' slot is retained => do chol() _after_ coercion R <- chol(A) assert.EQ.Mat(R, chol(.A)) # gave infinite recursion print(d. <- diag(R)) D. <- Diagonal(x= d.^2) L. <- t(R) %*% Diagonal(x = 1/d.) stopifnot(all.equal(as.matrix(D.), as.matrix(rr$ D)), all.equal(as.matrix(L.), as.matrix(rr$ L))) ## CAp <- Cholesky(A)# perm=TRUE --> Permutation: validObject(CAp) p <- CAp@perm + 1L P <- as(p, "pMatrix") ## the inverse permutation: invP <- solve(P)@perm lDet <- sum(2* log(d))# the "true" value ldetp <- .diag.dsC(Chx = CAp, res.kind = "sumLog") ldetp. <- sum(log(.diag.dsC(Chx = CAp, res.kind = "diag") )) ## CA <- Cholesky(A,perm=FALSE) validObject(CA) ldet <- .diag.dsC(Chx = CA, res.kind = "sumLog") ## not printing CAp : ends up non-integer for n >= 11 mCAp <- as(CAp, "CsparseMatrix") print(mCA <- drop0(as(CA, "CsparseMatrix"))) stopifnot(identical(A[p,p], as(P %*% A %*% t(P), "symmetricMatrix")), relErr(d.^2, .diag.dsC(Chx= CA, res.kind="diag")) < 1e-14, relErr(A[p,p], tcrossprod(mCAp)) < 1e-14) if(FALSE) rbind(lDet,ldet, ldetp, ldetp.) ## ==> Empirically, I see lDet = ldet != ldetp == ldetp. ## if(rr$rcond.A < ...) warning("condition number of A ..." ## <- TODO cat(1,""); assert.EQ.(lDet, ldet, tol = 1e-14) cat(2,""); assert.EQ.(ldetp, ldetp., tol = 1e-14) cat(3,""); assert.EQ.(lDet, ldetp, tol = n^2* 1e-7)# extreme: have seen 0.0011045 !! }## for() mkCholhash <- function(r.all) { ## r.all %*% (2^(2:0)), but only those that do not have NA / "?" : stopifnot(is.character(rn <- rownames(r.all)), is.matrix(r.all), is.logical(r.all)) c.rn <- vapply(rn, function(ch) strsplit(ch, " ")[[1]], character(3)) ## Now h1 <- function(i) { ok <- rep.int(TRUE, 3L) if(c.rn[3L, i] == "?") ok[2:3] <- FALSE # no supernodal LDL' factorization !! r.all[i, ok] %*% 2^((2:0)[ok]) } vapply(seq_len(nrow(r.all)), h1, numeric(1)) } set.seed(17) (rr <- mkLDL(4)) (CA <- Cholesky(rr$A)) validObject(CA) stopifnot(all.equal(determinant(rr$A) -> detA, determinant(as(rr$A, "matrix"))), is.all.equal3(c(detA$modulus), log(det(rr$D)), sum(log(rr$D@x)))) A12 <- mkLDL(12, 1/10) (r12 <- allCholesky(A12$A))[-1] aCh.hash <- mkCholhash(r12$r.all) if(requireNamespace("sfsmisc")) split(rownames(r12$r.all), sfsmisc::Duplicated(aCh.hash)) ## TODO: find cases for both choices when we leave it to CHOLMOD to choose for(n in 1:50) { ## used to seg.fault at n = 10 ! mkA <- mkLDL(1+rpois(1, 30), 1/10, rcond = FALSE, condest = FALSE) cat(sprintf("n = %3d, LDL-dim = %d x %d ", n, nrow(mkA$A), ncol(mkA$A))) r <- allCholesky(mkA$A, silentTry=TRUE) ## Compare .. apart from the NAs that happen from (perm=FALSE, super=TRUE) iNA <- apply(is.na(r$r.all), 1, any) cat(sprintf(" -> %3s NAs\n", if(any(iNA)) format(sum(iNA)) else "no")) stopifnot(aCh.hash[!iNA] == mkCholhash(r$r.all[!iNA,])) ## cat("--------\n") } ## This is a relatively small "critical example" : A. <- new("dsCMatrix", Dim = c(25L, 25L), uplo = "U" , i = as.integer( c(0, 1, 2, 3, 4, 2, 5, 6, 0, 8, 8, 9, 3, 4, 10, 11, 6, 12, 13, 4, 10, 14, 15, 1, 2, 5, 16, 17, 0, 7, 8, 18, 9, 19, 10, 11, 16, 20, 0, 6, 7, 16, 17, 18, 20, 21, 6, 9, 12, 14, 19, 21, 22, 9, 11, 19, 20, 22, 23, 1, 16, 24)) ## , p = c(0:6, 8:10, 12L, 15:16, 18:19, 22:23, 27:28, 32L, 34L, 38L, 46L, 53L, 59L, 62L) ## , x = c(1, 1, 1, 1, 2, 100, 2, 40, 1, 2, 100, 6700, 100, 100, 13200, 1, 50, 4100, 1, 5, 400, 20, 1, 40, 100, 5600, 9100, 5000, 5, 100, 100, 5900, 100, 6200, 30, 20, 9, 2800, 1, 100, 8, 10, 8000, 100, 600, 23900, 30, 100, 2800, 50, 5000, 3100, 15100, 100, 10, 5600, 800, 4500, 5500, 7, 600, 18200)) validObject(A.) ## A1: the same pattern as A. just simply filled with '1's : A1 <- A.; A1@x[] <- 1; A1@factors <- list() A1.8 <- A1; diag(A1.8) <- 8 ## nT. <- as(AT <- as(A., "TsparseMatrix"),"nMatrix") stopifnot(all(nT.@i <= nT.@j), identical(qr(A1.8), qr(as(A1.8, "generalMatrix")))) CA <- Cholesky(A. + Diagonal(x = rowSums(abs(A.)) + 1)) validObject(CA) stopifnotValid(CAinv <- solve(CA), "dsCMatrix") MA <- as(CA, "CsparseMatrix") # with a confusing warning -- FIXME! stopifnotValid(MAinv <- solve(MA), "dtCMatrix") ## comparing MAinv with some solve(CA, system="...") .. *not* trivial? - TODO ## CAinv2 <- solve(CA, Diagonal(nrow(A.))) CAinv2 <- as(CAinv2, "symmetricMatrix") stopifnot(identical(CAinv, CAinv2)) ## FINALLY fix "TODO": (not implemented *symbolic* factorization of nMatrix) try( tc <- Cholesky(nT.) ) for(p in c(FALSE,TRUE)) for(L in c(FALSE,TRUE)) for(s in c(FALSE,TRUE, NA)) { cat(sprintf("p,L,S = (%2d,%2d,%2d): ", p,L,s)) r <- tryCatch(Cholesky(A., perm=p, LDL=L, super=s), error = function(e)e) cat(if(inherits(r, "error")) " *** E ***" else sprintf("%3d", r@type),"\n", sep="") } str(A., max.level=3) ## look at the 'factors' facs <- A.@factors names(facs) <- sub("Cholesky$", "", names(facs)) facs <- facs[order(names(facs))] sapply(facs, class) str(lapply(facs, slot, "type")) ## super = TRUE currently always entails LDL=FALSE : ## hence isLDL is TRUE for ("D" and not "S"): sapply(facs, isLDL) chkCholesky <- function(chmf, A) { stopifnot(is(chmf, "CHMfactor"), validObject(chmf), is(A, "Matrix"), isSymmetric(A)) if(!is(A, "dsCMatrix")) A <- as(as(as(A, "CsparseMatrix"), "symmetricMatrix", "dMatrix")) L <- drop0(zapsmall(L. <- as(chmf, "CsparseMatrix"))) cat("no. nonzeros in L {before / after drop0(zapsmall(.))}: ", c(nnzero(L.), nnzero(L)), "\n") ## 112, 95 ecc <- expand(chmf) A... <- with(ecc, crossprod(crossprod(L,P))) stopifnot(all.equal(L., ecc$L, tolerance = 1e-14), all.equal(A, A..., tolerance = 1e-14)) invisible(ecc) } c1.8 <- try(Cholesky(A1.8, super = TRUE))# works "always", interestingly ... chkCholesky(c1.8, A1.8) ## --- now a "large" (712 x 712) real data example --------------------------- data(KNex, package = "Matrix") mtm <- with(KNex, crossprod(mm)) ld.3 <- determinant(Cholesky(mtm, perm = TRUE), sqrt = FALSE) stopifnot(identical(names(mtm@factors), "sPDCholesky")) ld.4 <- determinant(Cholesky(mtm, perm = FALSE), sqrt = FALSE) stopifnot(identical(names(mtm@factors), c("sPDCholesky", "spDCholesky"))) c2 <- Cholesky(mtm, super = TRUE) validObject(c2) stopifnot(identical(names(mtm@factors), c("sPDCholesky", "spDCholesky", "SPdCholesky"))) r <- allCholesky(mtm) r[-1] ## is now taken from cache c1 <- Cholesky(mtm) bv <- 1:nrow(mtm) # even integer b <- matrix(bv) ## solve(c2, b) by default solves Ax = b, where A = c2'c2 ! x <- solve(c2,b) stopifnot(identical3(drop(x), solve(c2, bv), drop(solve(c2, b, system = "A"))), all.equal(x, solve(mtm, b))) for(sys in c("A", "LDLt", "LD", "DLt", "L", "Lt", "D", "P", "Pt")) { x <- solve(c2, b, system = sys) cat(sys,":\n"); print(head(x)) stopifnot(dim(x) == c(712, 1), identical(drop(x), solve(c2, bv, system = sys))) } ## log(|LL'|) - check if super = TRUE and simplicial give same determinant (ld.1 <- determinant(mtm)) if(FALSE) { ## MJ: CHMfactor_ldetL2 is unused outside of these tests, so we no longer ## have it in the namespace { old definition is in ../src/CHMfactor.c } ld1 <- .Call("CHMfactor_ldetL2", c1) ld2 <- .Call("CHMfactor_ldetL2", c2) stopifnot(all.equal(ld1, ld2), all.equal(ld1, as.vector(ld.1$modulus), tolerance = 1e-14), all.equal(ld1, as.vector(ld.3$modulus), tolerance = 1e-14), all.equal(ld1, as.vector(ld.4$modulus), tolerance = 1e-14)) } else { stopifnot(all.equal(as.vector(ld.1$modulus), as.vector(ld.3$modulus), tolerance = 1e-14), all.equal(as.vector(ld.1$modulus), as.vector(ld.4$modulus), tolerance = 1e-14)) } ## MJ: ldet[123].dsC() are unused outside of these tests, so we no longer ## have them in the namespace { old definitions are in ../R/determinant.R } if(FALSE) { ## Some timing measurements mtm <- with(KNex, crossprod(mm)) I <- .symDiagonal(n=nrow(mtm)) set.seed(101); r <- runif(100) system.time(D1 <- sapply(r, function(rho) Matrix:::ldet1.dsC(mtm + (1/rho) * I))) ## 0.842 on fast cmath-5 system.time(D2 <- sapply(r, function(rho) Matrix:::ldet2.dsC(mtm + (1/rho) * I))) ## 0.819 system.time(D3 <- sapply(r, function(rho) Matrix:::ldet3.dsC(mtm + (1/rho) * I))) ## 0.810 stopifnot(is.all.equal3(D1,D2,D3, tol = 1e-13)) } ## Updating LL' should remain LL' and not become LDL' : cholCheck <- function(Ut, tol = 1e-12, super = FALSE, LDL = !super) { L <- Cholesky(UtU <- tcrossprod(Ut), super=super, LDL=LDL, Imult = 1) L1 <- update(L, UtU, mult = 1) L2 <- update(L, Ut, mult = 1) stopifnot(is.all.equal3(L, L1, L2, tol = tol), all.equal(update(L, UtU, mult = pi), update(L, Ut, mult = pi), tolerance = tol) ) } ## Inspired by ## data(Dyestuff, package = "lme4") ## Zt <- as(Dyestuff$Batch, "sparseMatrix") Zt <- new("dgCMatrix", Dim = c(6L, 30L), x = 2*1:30, i = rep(0:5, each=5), p = 0:30, Dimnames = list(LETTERS[1:6], NULL)) cholCheck(0.78 * Zt, tol=1e-14) oo <- options(Matrix.quiet.qr.R = TRUE, warn = 2)# no warnings allowed qrZ <- qr(t(Zt)) Rz <- qr.R(qrZ) stopifnot(exprs = { inherits(qrZ, "sparseQR") inherits(Rz, "sparseMatrix") isTriangular(Rz) isDiagonal(Rz) # even though formally a "dtCMatrix" qr2rankMatrix(qrZ, do.warn=FALSE) == 6 }) options(oo) ## problematic rank deficient rankMatrix() case -- only seen in large cases ?? ## MJ: NA in diag(@R) not seen with Apple Clang 14.0.3 Z. <- readRDS(system.file("external", "Z_NA_rnk.rds", package="Matrix")) (rnkZ. <- rankMatrix(Z., method = "qr")) # gave errors; now warns typically, but not on aarm64 (M1) qrZ. <- qr(Z.) options(warn=1) rnk2 <- qr2rankMatrix(qrZ.) # warning ".. only 684 out of 822 finite diag(R) entries" oo <- options(warn=2)# no warnings allowed from here di.NA <- anyNA(diag(qrZ.@R)) stopifnot(is(qrZ, "sparseQR"), identical(is.na(rnkZ.), di.NA), identical(is.na(rnk2), di.NA)) ## The above bug fix was partly wrongly extended to dense matrices for "qr.R": x <- cbind(1, rep(0:9, 18)) qr.R(qr(x)) # one negative diagonal qr.R(qr(x, LAPACK=TRUE)) # two negative diagonals chkRnk <- function(x, rnk) { stopifnot(exprs = { rankMatrix(x) == rnk rankMatrix(x, method="maybeGrad") == rnk ## but "useGrad" is not ! rankMatrix(x, method="qrLINPACK") == rnk rankMatrix(x, method="qr.R" ) == rnk })# the last gave '0' and a warning in Matrix 1.3-0 } chkRnk( x, 2) chkRnk(diag(1), 1) # had "empty stopifnot" (-> Error in MM's experimental setup) + warning 'min()' (m3 <- cbind(2, rbind(diag(pi, 2), 8))) chkRnk(m3, 3) chkRnk(matrix(0, 4,3), 0) chkRnk(matrix(1, 5,5), 1) # had failed for "maybeGrad" chkRnk(matrix(1, 5,2), 1) showSys.time( for(i in 1:120) { set.seed(i) M <- rspMat(n=rpois(1,50), m=rpois(1,20), density = 1/(4*rpois(1, 4))) cat(sprintf("%3d: dim(M) = %2dx%2d, rank=%2d, k=%9.4g; ", i, nrow(M), ncol(M), rankMatrix(M), kappa(M))) for(super in c(FALSE,TRUE)) { cat("super=",super,"M: ") ## 2018-01-04, Avi Adler: needed 1.2e-12 in Windows 64 (for i=55, l.1): cholCheck( M , tol=2e-12, super=super); cat(" M': ") cholCheck(t(M), tol=2e-12, super=super) } cat(" [Ok]\n") }) .updateCHMfactor ## TODO: (--> ../TODO "Cholesky"): ## ---- ## allow Cholesky(A,..) when A is not symmetric *AND* ## we really want to factorize AA' ( + beta * I) ## Schur() ---------------------- checkSchur <- function(A, SchurA = Schur(A), tol = 1e-14) { stopifnot(is(SchurA, "Schur"), isOrthogonal(Q <- SchurA@Q), all.equal(as.mat(A), as.mat(Q %*% SchurA@T %*% t(Q)), tolerance = tol)) } SH <- Schur(H5 <- Hilbert(5)) checkSchur(H5, SH) checkSchur(Diagonal(x = 9:3)) p <- 4L uTp <- new("dtpMatrix", x=c(2, 3, -1, 4:6, -2:1), Dim = c(p,p)) (uT <- as(uTp, "unpackedMatrix")) ## Schur ( ) <--> Schur( ) Su <- Schur(uT) ; checkSchur(uT, Su) gT <- as(uT,"generalMatrix") Sg <- Schur(gT) ; checkSchur(gT, Sg) Stg <- Schur(t(gT));checkSchur(t(gT), Stg) Stu <- Schur(t(uT));checkSchur(t(uT), Stu) stopifnot(exprs = { identical3(Sg@T, uT, Su@T) identical(Sg@Q, as(diag(p), "generalMatrix")) ## LaPck 3.12.0: these must be more careful (Q is *different* permutation): is.integer(print(ip <- invPerm(pp <- as(Stg@Q, "pMatrix")@perm))) identical(Stg@T, as(t(gT[,ip])[,ip], "triangularMatrix")) identical(Stg@Q, as( diag(p)[,ip], "generalMatrix")) ## Stu still has p:1 permutation, but should not rely on it is.integer(print(i2 <- invPerm(as(Stu@Q, "pMatrix")@perm))) identical(Stu@T, as(t(uT[,i2])[,i2], "triangularMatrix")) identical(Stu@Q, as( diag(p)[,i2], "pMatrix")) # Schur() ==> 'Q' is pMatrix }) ## the pedigreemm example where solve(.) failed: p <- new("dtCMatrix", i = c(2L, 3L, 2L, 5L, 4L, 4:5), p = c(0L, 2L, 4:7, 7L), Dim = c(6L, 6L), Dimnames = list(as.character(1:6), NULL), x = rep.int(-0.5, 7), uplo = "L", diag = "U") Sp <- Schur(p) Sp. <- Schur(as(p,"generalMatrix")) Sp.p <- Schur(crossprod(p)) ## the last two failed ip <- solve(p) assert.EQ.mat(solve(ip), as(p,"matrix")) ## chol2inv() for a traditional matrix assert.EQ.mat( crossprod(chol2inv(chol(Diagonal(x = 5:1)))), C <- crossprod(chol2inv(chol( diag(x = 5:1))))) stopifnot(all.equal(C, diag((5:1)^-2))) ## failed in some versions because of a "wrong" implicit generic U <- cbind(1:0, 2*(1:2)) (sU <- as(U, "CsparseMatrix")) validObject(sS <- crossprod(sU)) C. <- chol(sS) stopifnot(all.equal(C., sU, tolerance=1e-15)) ## chol() tC7 <- .trDiagonal(7, 7:1) stopifnotValid(tC7, "dtCMatrix") ch7 <- chol(tC7) ## this (and the next 2) failed: 'no slot .. "factors" ..."dtCMatrix"' chT7 <- chol(tT7 <- as(tC7, "TsparseMatrix")) chR7 <- chol(tR7 <- as(tC7, "RsparseMatrix")) stopifnot(expr = { isDiagonal(ch7) identical(chT7, ch7) # "ddiMatrix" all of them identical(chR7, ch7) # "ddiMatrix" all of them all.equal(sqrt(7:1), diag(ch7 )) }) ## From [Bug 14834] New: chol2inv *** caught segfault *** n <- 1e6 # was 595362 A <- chol( D <- Diagonal(n) ) stopifnot(identical(A,D)) # A remains (unit)diagonal is(tA <- as(A,"triangularMatrix"))# currently a dtTMatrix stopifnotValid(tA, "dsparseMatrix") CA <- as(tA, "CsparseMatrix") selectMethod(solve, c("dtCMatrix","missing")) ##--> .Call(dtCMatrix_sparse_solve, a, .trDiagonal(n)) in ../src/dtCMatrix.c sA <- solve(CA)## -- R_CheckStack() segfault in Matrix <= 1.0-4 nca <- diagU2N(CA) stopifnot(identical(sA, nca)) ## same check with non-unit-diagonal D : A <- chol(D <- Diagonal(n, x = 0.5)) ia <- chol2inv(A) stopifnot(is(ia, "diagonalMatrix"), all.equal(ia@x, rep(2,n), tolerance = 1e-15)) ##------- Factor caches must be cleaned - even after scalar-Ops such as "2 *" set.seed(7) d <- 5 S <- 10*Diagonal(d) + rsparsematrix(d,d, 1/4) class(M <- as(S, "denseMatrix")) # dgeMatrix m <- as.matrix(M) (dS <- determinant(S)) stopifnot(exprs = { all.equal(determinant(m), dS, tolerance=1e-15) all.equal(dS, determinant(M), tolerance=1e-15) ## These had failed, as the "LU" factor cache was kept unchanged in 2*M : all.equal(determinant(2*S), determinant(2*M) -> d2M) all.equal(determinant(S^2), determinant(M^2) -> dM2) all.equal(determinant(m^2), dM2) all.equal(d*log(2), c(d2M$modulus - dS$modulus)) }) ## misc. bugs found in Matrix 1.4-1 L. <- new("dtCMatrix", Dim = c(1L, 1L), uplo = "L", p = c(0L, 1L), i = 0L, x = 1) S. <- forceSymmetric(L.) lu(S.) stopifnot(validObject(lu(L.)), # was invalid identical(names(S.@factors), "sparseLU")) # was "lu" ## chol() should give matrix with 'Dimnames', ## even if 'Dimnames' are not cached D. <- as(diag(3), "CsparseMatrix") D.@Dimnames <- dn <- list(zzz = letters[1:3], ZZZ = LETTERS[1:3]) cd1 <- chol(D.) # "fresh" stopifnot(identical(cd1@Dimnames, rep(dn[2L], 2L))) cd2 <- chol(D.) # from cache stopifnot(identical(cd1, cd2)) ## lu(), lu(<0-by-n>), BunchKaufman(<0-by-0>), chol(<0-by-0>) stopifnot(identical(lu(new("dgeMatrix", Dim = c(2L, 0L))), new("denseLU", Dim = c(2L, 0L))), identical(lu(new("dgeMatrix", Dim = c(0L, 2L))), new("denseLU", Dim = c(0L, 2L))), identical(BunchKaufman(new("dsyMatrix", uplo = "U")), new("BunchKaufman", uplo = "U")), identical(BunchKaufman(new("dspMatrix", uplo = "L")), new("pBunchKaufman", uplo = "L")), identical(Cholesky(new("dpoMatrix", uplo = "U")), new("Cholesky", uplo = "U")), identical(Cholesky(new("dppMatrix", uplo = "L")), new("pCholesky", uplo = "L"))) ## determinant() going via Bunch-Kaufman set.seed(15742) n <- 10L syU <- syL <- new("dsyMatrix", Dim = c(n, n), x = rnorm(n * n)) spU <- spL <- new("dspMatrix", Dim = c(n, n), x = rnorm((n * (n + 1L)) %/% 2L)) syL@uplo <- spL@uplo <- "L" for(m in list(syU, syL, spU, spL)) for(givelog in c(FALSE, TRUE)) stopifnot(all.equal(determinant( m, givelog), determinant(as(m, "matrix"), givelog))) ## was an error at least in Matrix 1.5-4 ... BunchKaufman(as.matrix(1)) ## 'expand2': product of listed factors should reproduce factorized matrix ## FIXME: many of our %*% methods still mangle dimnames or names(dimnames) ... ## hence for now we coerce the factors to matrix before multiplying chkMF <- function(X, Y, FUN, ...) { ## t(x)@factors may preserve factorizations with x@uplo X@factors <- list() mf <- FUN(X, ...) e2.mf <- expand2(mf) e1.mf <- sapply(names(e2.mf), expand1, x = mf, simplify = FALSE) m.e2.mf <- lapply(e2.mf, as, "matrix") m.e1.mf <- lapply(e1.mf, as, "matrix") identical(m.e1.mf, lapply(m.e2.mf, unname)) && isTRUE(all.equal(Reduce(`%*%`, m.e2.mf), Y)) } set.seed(24831) n <- 16L mS <- tcrossprod(matrix(rnorm(n * n), n, n, dimnames = list(A = paste0("s", seq_len(n)), NULL))) sS <- as(pS <- as(S <- as(mS, "dpoMatrix"), "packedMatrix"), "CsparseMatrix") stopifnot(exprs = { chkMF( S , mS, Schur) chkMF( pS , mS, Schur) chkMF( S , mS, lu) chkMF( pS , mS, lu) chkMF( sS , mS, lu) chkMF( sS , mS, qr) chkMF( S , mS, BunchKaufman) chkMF( pS , mS, BunchKaufman) chkMF(t( S), mS, BunchKaufman) chkMF(t(pS), mS, BunchKaufman) chkMF( S , mS, Cholesky) chkMF( pS , mS, Cholesky) chkMF(t( S), mS, Cholesky) chkMF(t(pS), mS, Cholesky) chkMF( sS , mS, Cholesky, super = FALSE, LDL = TRUE) chkMF( sS , mS, Cholesky, super = FALSE, LDL = FALSE) chkMF( sS , mS, Cholesky, super = TRUE, LDL = FALSE) }) cat('Time elapsed: ', proc.time(),'\n') # for ``statistical reasons'' Matrix/tests/abIndex-tsts.R0000644000175100001440000001063314444520706015377 0ustar hornikusers#### Testing consistency of "abIndex" == "abstract-indexing vectors" class : ## for R_DEFAULT_PACKAGES=NULL : library(stats) library(utils) library(Matrix) source(system.file("test-tools.R", package = "Matrix"))# identical3() etc validObject(ab <- new("abIndex")) str(ab) set.seed(1) ex. <- list(2:1000, 0:10, sample(100), c(-3:40, 20:70), c(1:100,77L, 50:40, 10L), c(17L, 3L*(12:3))) ## we know which kinds will come out: "compressed" for all but random: rD <- "rleDiff"; kinds <- c(rD,rD,"int32", rD, rD, rD) isCmpr <- kinds == rD ab. <- lapply(ex., as, Class = "abIndex") nu. <- lapply(ab., as, Class = "numeric") in. <- lapply(ab., as, Class = "integer") rles <- lapply(ab.[isCmpr], function(u) u@rleD@rle) r.x <- lapply(ex.[isCmpr], function(.) rle(diff(.))) stopifnot(sapply(ab., validObject), identical(ex., nu.), identical(ex., in.), ## Check that the relevant cases really *are* "compressed": sapply(ab., slot, "kind") == kinds, ## Using rle(diff(.)) is equivalent to using our C code: identical(rles, r.x), ## Checking Group Methods - "Summary" : sapply(ab., range) == sapply(ex., range), sapply(ab., any) == sapply(ex., any), TRUE) ## testing c() method, i.e. currently c.abIndex(): tst.c.abI <- function(lii) { stopifnot(is.list(lii), all(unlist(lapply(lii, mode)) == "numeric")) aii <- lapply(lii, as, "abIndex") v.i <- do.call(c, lii) a.i <- do.call(c, aii) avi <- as(v.i, "abIndex") ## identical() is too hard, as values & lengths can be double/integer stopifnot(all.equal(a.i, avi, tolerance = 0)) } tst.c.abI(list(2:6, 70:50, 5:-2)) ## now an example where *all* are uncompressed: tst.c.abI(list(c(5, 3, 2, 4, 7, 1, 6), 3:4, 1:-1)) ## and one with parts that are already non-trivial: exc <- ex.[isCmpr] tst.c.abI(exc) set.seed(101) N <- length(exc) # 5 for(i in 1:10) { tst.c.abI(exc[sample(N, replace=TRUE)]) tst.c.abI(exc[sample(N, N-1)]) tst.c.abI(exc[sample(N, N-2)]) } for(n in 1:120) { cat(".") k <- 1 + 4*rpois(1, 5) # >= 1 ## "random" rle -- NB: consecutive values *must* differ (for uniqueness) v <- as.integer(1+ 10*rnorm(k)) while(any(dv <- duplicated(v))) v[dv] <- v[dv] + 1L rl <- structure(list(lengths = as.integer(1 + rpois(k, 10)), values = v), class = "rle") ai <- new("abIndex", kind = "rleDiff", rleD = new("rleDiff", first = rpois(1, 20), rle = rl)) validObject(ai) ii <- as(ai, "numeric") iN <- ii; iN[180] <- NA; aiN <- as(iN,"abIndex") iN <- as(aiN, "numeric") ## NA from 180 on stopifnot(is.numeric(ii), ii == round(ii), identical(ai, as(ii, "abIndex")), identical(is.na(ai), is.na(ii)), identical(is.na(aiN), is.na(iN)), identical(is.finite (aiN), is.finite(iN)), identical(is.infinite(aiN), is.infinite(iN)) ) if(n %% 40 == 0) cat(n,"\n") } ## we have : identical(lapply(ex., as, "abIndex"), ab.) mkStr <- function(ch, n) paste(rep.int(ch, n), collapse="") ##O for(grMeth in getGroupMembers("Ops")) { ##O cat(sprintf("\n%s :\n%s\n", grMeth, mkStr("=", nchar(grMeth)))) grMeth <- "Arith" for(ng in getGroupMembers(grMeth)) { cat(ng, ": ") G <- get(ng) t.tol <- if(ng == "/") 1e-12 else 0 ## "/" with no long double (e.g. on Sparc Solaris): 1.125e-14 AEq <- function(a,b, ...) assert.EQ(a, b, tol=t.tol, giveRE=TRUE) for(v in ex.) { va <- as(v, "abIndex") for(s in list(-1, 17L, TRUE, FALSE)) # numeric *and* logical if(!((identical(s, FALSE) && ng == "/"))) { ## division by 0 may "fail" AEq(as(G(v, s), "abIndex"), G(va, s)) AEq(as(G(s, v), "abIndex"), G(s, va)) } cat(".") } cat(" [Ok]\n") } ##O } ## check the abIndex versions of indDiag() and indTri() : for(n in 1:7) { stopifnotValid(ii <- Matrix:::abIindDiag(n), "abIndex") stopifnot(ii@kind == "rleDiff", Matrix:::indDiag(n) == as(ii, "numeric")) } for(n in 0:7) for(diag in c(TRUE,FALSE)) for(upper in c(TRUE,FALSE)) { stopifnotValid(ii <- Matrix:::abIindTri(n, diag=diag,upper=upper), "abIndex") if(n) stopifnot(Matrix:::indTri(n, diag=diag,upper=upper) == as(ii, "numeric"), allow.logical0=TRUE) # works also in R versions w/o it as formal argument } cat('Time elapsed: ', (.pt <- proc.time()),'\n') # "stats" Matrix/tests/matprod.R0000644000175100001440000011562314500446564014507 0ustar hornikusers## for R_DEFAULT_PACKAGES=NULL : library(stats) library(utils) library(Matrix) ### Matrix Products including cross products source(system.file("test-tools.R", package = "Matrix")) # is.EQ.mat(), dnIdentical() ..etc doExtras options(warn=1, # show as they happen Matrix.verbose = doExtras) ##' Check matrix multiplications with (unit) Diagonal matrices chkDiagProd <- function(M) { if(is.matrix(M)) { noRN <- function(x) { if(!is.null(dn <- dimnames(x))) dimnames(x) <- c(list(NULL), dn[2L]) x } noCN <- function(x) { if(!is.null(dn <- dimnames(x))) dimnames(x) <- c(dn[1L], list(NULL)) x } } else if(is(M, "Matrix")) { noRN <- function(x) { x@Dimnames <- c(list(NULL), x@Dimnames[2L]) x } noCN <- function(x) { x@Dimnames <- c(x@Dimnames[1L], list(NULL)) x } } else stop("'M' must be a [mM]atrix") I.l <- Diagonal(nrow(M)) # I_n -- "unit" Diagonal I.r <- Diagonal(ncol(M)) # I_d D2.l <- Diagonal(nrow(M), x = 2) # D_n D2.r <- Diagonal(ncol(M), x = 2) # I_d stopifnot(is.EQ.mat(noCN(M), M %*% I.r), is.EQ.mat(noRN(M), I.l %*% M), is.EQ.mat(noCN(2*M), M %*% D2.r), is.EQ.mat(noRN(M*2), D2.l %*% M), ## crossprod is.EQ.mat(noCN(t(M)), crossprod(M, I.l)), is.EQ.mat(noRN(M), crossprod(I.l, M)), is.EQ.mat(noCN(t(2*M)), crossprod(M, D2.l)), is.EQ.mat(noRN(M*2) , crossprod(D2.l, M)), ## tcrossprod is.EQ.mat(noCN(M), tcrossprod(M, I.r)), is.EQ.mat(noRN(t(M)), tcrossprod(I.r, M)), is.EQ.mat(noCN(2*M), tcrossprod(M, D2.r)), is.EQ.mat(noRN(t(M*2)), tcrossprod(D2.r, M))) } ### dimnames -- notably for matrix products ---------------- # ##' Checks that matrix products are the same, including dimnames ##' ##' @param m matrix = traditional-R-matrix version of M ##' @param M optional Matrix = "Matrix class version of m" ##' @param browse chkDnProd <- function(m = as(M, "matrix"), M = Matrix(m), browse=FALSE, warn.ok=FALSE) { ## TODO: ## if(browse) stopifnot <- f.unction(...) such that it enters browser() when it is not fulfilled if(!warn.ok) { # NO warnings allowd op <- options(warn = 2) on.exit(options(op)) } stopifnot(is.matrix(m), is(M, "Matrix"), identical(dim(m), dim(M)), dnIdentical(m,M)) ## m is n x d (say) is.square <- nrow(m) == ncol(m) p1 <- (tm <- t(m)) %*% m ## d x d p1. <- crossprod(m) stopifnot(is.EQ.mat3(p1, p1., crossprod(m,m))) t1 <- m %*% tm ## n x n t1. <- tcrossprod(m) stopifnot(is.EQ.mat3(t1, t1., tcrossprod(m,m))) if(is.square) { mm <- m %*% m stopifnot(is.EQ.mat3(mm, crossprod(tm,m), tcrossprod(m,tm))) } chkDiagProd(m)## was not ok in Matrix 1.2.0 ## Now the "Matrix" ones -- should match the "matrix" above M0 <- M cat("sparse: ") for(sparse in c(TRUE, FALSE)) { cat(sparse, "; ") M <- as(M0, if(sparse) "sparseMatrix" else "denseMatrix") P1 <- (tM <- t(M)) %*% M P1. <- crossprod(M) stopifnot(is.EQ.mat3(P1, P1., p1), is.EQ.mat3(P1., crossprod(M,M), crossprod(M,m)), is.EQ.mat (P1., crossprod(m,M))) ## P1. is "symmetricMatrix" -- semantically "must have" symm.dimnames PP1 <- P1. %*% P1. ## still d x d R <- triu(PP1); r <- as(R, "matrix") # upper - triangular L <- tril(PP1); l <- as(L, "matrix") # lower - triangular stopifnot(isSymmetric(P1.), isSymmetric(PP1), isDiagonal(L) || is(L,"triangularMatrix"), isDiagonal(R) || is(R,"triangularMatrix"), isTriangular(L, upper=FALSE), isTriangular(R, upper=TRUE), is.EQ.mat(PP1, (pp1 <- p1 %*% p1)), dnIdentical(PP1, R), dnIdentical(L, R)) T1 <- M %*% tM T1. <- tcrossprod(M) stopifnot(is.EQ.mat3(T1, T1., t1), is.EQ.mat3(T1., tcrossprod(M,M), tcrossprod(M,m)), is.EQ.mat (T1., tcrossprod(m,M)), is.EQ.mat(tcrossprod(T1., tM), tcrossprod(t1., tm)), is.EQ.mat(crossprod(T1., M), crossprod(t1., m))) ## Now, *mixing* Matrix x matrix: stopifnot(is.EQ.mat3(tM %*% m, tm %*% M, tm %*% m)) if(is.square) stopifnot(is.EQ.mat (mm, M %*% M), is.EQ.mat3(mm, crossprod(tM,M), tcrossprod(M,tM)), ## "mixing": is.EQ.mat3(mm, crossprod(tm,M), tcrossprod(m,tM)), is.EQ.mat3(mm, crossprod(tM,m), tcrossprod(M,tm))) ## Symmetric and Triangular stopifnot(is.EQ.mat(PP1 %*% tM, pp1 %*% tm), is.EQ.mat(R %*% tM, r %*% tm), is.EQ.mat(L %*% tM, L %*% tm)) ## Diagonal : chkDiagProd(M) } cat("\n") invisible(TRUE) } # chkDnProd() ## All these are ok {now, (2012-06-11) also for dense (m <- matrix(c(0, 0, 2:0), 3, 5)) m00 <- m # *no* dimnames dimnames(m) <- list(LETTERS[1:3], letters[1:5]) (m.. <- m) # has *both* dimnames m0. <- m.0 <- m.. dimnames(m0.)[1] <- list(NULL); m0. dimnames(m.0)[2] <- list(NULL); m.0 d <- diag(3); dimnames(d) <- list(c("u","v","w"), c("X","Y","Z")); d dU <- diagN2U(Matrix(d, doDiag = FALSE)) # unitriangular sparse tU <- dU; tU[1,2:3] <- 3:4; tU[2,3] <- 7; tU # ditto "unitri" sparse (T <- new("dtrMatrix", diag = "U", x= c(0,0,5,0), Dim= c(2L,2L), Dimnames= list(paste0("r",1:2),paste0("C",1:2)))) # unitriangular dense pT <- pack(T)# ^^^^^^^^^^^^ mt <- m[,2:3] %*% pT # deprecation warning in pre-1.5-4 stopifnot(is(pT, "dtpMatrix"), validObject(pT), validObject(mt), is(mt, "dgeMatrix"), identical(as.matrix(mt), array(c(1,0,0, 5,2,1), dim = 3:2, dimnames = list(c("A","B","C"), c("C1","C2")))) ) A <- matrix(c(0.4, 0.1, 0, 0), 2) B <- matrix(c(1.1, 0, 0, 0), 2); ABt <- tcrossprod(A, B) ## Matrix version # both Matrix version: class(AM <- as(A, "triangularMatrix")) # dtr class(BM <- as(B, "Matrix")) # ddi class(Bs <- as(as(B, "CsparseMatrix"), "symmetricMatrix")) # "dsC" (ABst <- tcrossprod(A, Bs)) # was wrong since at least Matrix 1.3-3 (R-4.0.5) assert.EQ.mat(ABst, ABt) assert.EQ.mat(tcrossprod(AM, BM), ABt) assert.EQ.mat(tcrossprod(AM, Bs), ABt) assert.EQ.mat(tcrossprod(A , Bs), ABt) ## currently many warnings about sub-optimal matrix products : chkDnProd(m..) chkDnProd(m0.) chkDnProd(m.0) chkDnProd(m00) chkDnProd(M = T) chkDnProd(M = t(T)) if(FALSE) { ## FIXME: ## Matrix() bug fix has revealed that diagonalMatrix product methods are not ## handling (have never handled?) 'Dimnames' correctly, causing these to fail chkDnProd(M = dU) chkDnProd(M = t(dU)) } ## all the above failed in 1.2-0 and 1.1-5, 1.1-4 some even earlier chkDnProd(M = tU) chkDnProd(M = t(tU)) ## the two above failed in Matrix <= 1.4-1 chkDnProd(M = Diagonal(4)) chkDnProd(diag(x=3:1)) if(FALSE) { ## FIXME: as for dU, t(dU) above chkDnProd(d) chkDnProd(M = as(d, "denseMatrix"))# M: dtrMatrix (diag = "N") } m5 <- 1 + as(diag(-1:4)[-5,], "generalMatrix") ## named dimnames: dimnames(m5) <- list(Rows= LETTERS[1:5], paste("C", 1:6, sep="")) tr5 <- tril(m5[,-6]) m. <- as(m5, "matrix") m5.2 <- local({t5 <- as.matrix(tr5); t5 %*% t5}) stopifnotValid(tr5, "dtrMatrix") stopifnot(dim(m5) == 5:6, class(cm5 <- crossprod(m5)) == "dpoMatrix") assert.EQ.mat(t(m5) %*% m5, as(cm5, "matrix")) assert.EQ.mat(tr5.2 <- tr5 %*% tr5, m5.2) stopifnotValid(tr5.2, "dtrMatrix") stopifnot(as.vector(rep(1,6) %*% cm5) == colSums(cm5), as.vector(cm5 %*% rep(1,6)) == rowSums(cm5)) ## uni-diagonal dtrMatrix with "wrong" entries in diagonal ## {the diagonal can be anything: because of diag = "U" it should never be used}: tru <- Diagonal(3, x=3); tru[i.lt <- lower.tri(tru, diag=FALSE)] <- c(2,-3,4) tru@diag <- "U" ; stopifnot(diag(trm <- as.matrix(tru)) == 1) ## TODO: Also add *upper-triangular* *packed* case !! stopifnot((tru %*% tru)[i.lt] == (trm %*% trm)[i.lt]) ## crossprod() with numeric vector RHS and LHS i5 <- rep.int(1, 5) isValid(S5 <- tcrossprod(tr5), "dpoMatrix")# and inherits from "dsy" G5 <- as(S5, "generalMatrix")# "dge" assert.EQ.mat( crossprod(i5, m5), rbind( colSums(m5))) assert.EQ.mat( crossprod(i5, m.), rbind( colSums(m5))) assert.EQ.mat( crossprod(m5, i5), cbind( colSums(m5))) assert.EQ.mat( crossprod(m., i5), cbind( colSums(m5))) assert.EQ.mat( crossprod(i5, S5), rbind( colSums(S5))) # failed in Matrix 1.1.4 ## tcrossprod() with numeric vector RHS and LHS : stopifnot(identical(tcrossprod(i5, S5), # <- lost dimnames tcrossprod(i5, G5) -> m51), identical(dimnames(m51), list(NULL, Rows = LETTERS[1:5])) ) m51 <- m5[, 1, drop=FALSE] # [6 x 1] m.1 <- m.[, 1, drop=FALSE] ; assert.EQ.mat(m51, m.1) ## The only (M . v) case assert.EQ.mat(tcrossprod(m51, 5:1), tcrossprod(m.1, 5:1)) ## The two (v . M) cases: assert.EQ.mat(tcrossprod(rep(1,6), m.), rbind( rowSums(m5)))# |v| = ncol(m) assert.EQ.mat(tcrossprod(rep(1,3), m51), tcrossprod(rep(1,3), m.1))# ncol(m) = 1 ## classes differ tc.m5 <- m5 %*% t(m5) # "dge*", no dimnames (FIXME) (tcm5 <- tcrossprod(m5)) # "dpo*" w/ dimnames assert.EQ.mat(tc.m5, mm5 <- as(tcm5, "matrix")) ## tcrossprod(x,y) : assert.EQ.mat(tcrossprod(m5, m5), mm5) assert.EQ.mat(tcrossprod(m5, m.), mm5) assert.EQ.mat(tcrossprod(m., m5), mm5) M50 <- m5[,FALSE, drop=FALSE] M05 <- t(M50) s05 <- as(M05, "sparseMatrix") s50 <- t(s05) assert.EQ.mat(M05, matrix(1, 0,5)) assert.EQ.mat(M50, matrix(1, 5,0)) assert.EQ.mat(tcrossprod(M50), tcrossprod(as(M50, "matrix"))) assert.EQ.mat(tcrossprod(s50), tcrossprod(as(s50, "matrix"))) assert.EQ.mat( crossprod(s50), crossprod(as(s50, "matrix"))) stopifnot(identical( crossprod(s50), tcrossprod(s05)), identical( crossprod(s05), tcrossprod(s50))) (M00 <- crossprod(M50))## used to fail -> .Call(dgeMatrix_crossprod, x, FALSE) stopifnot(identical(M00, tcrossprod(M05)), all(M00 == t(M50) %*% M50), dim(M00) == 0) ## simple cases with 'scalars' treated as 1x1 matrices: d <- Matrix(1:5) d %*% 2 10 %*% t(d) assertError(3 %*% d) # must give an error , similar to assertError(5 %*% as.matrix(d)) # -> error ## right and left "numeric" and "matrix" multiplication: (p1 <- m5 %*% c(10, 2:6)) (p2 <- c(10, 2:5) %*% m5) (pd1 <- m5 %*% diag(1:6)) (pd. <- m5 %*% Diagonal(x = 1:6)) (pd2 <- diag (10:6) %*% m5) (pd..<- Diagonal(x = 10:6) %*% m5) stopifnot(exprs = { dim(crossprod(t(m5))) == c(5,5) c(class(p1),class(p2),class(pd1),class(pd2), class(pd.),class(pd..)) == "dgeMatrix" identical(dimnames(pd.), c(dimnames(m5)[1L], list(NULL))) identical(dimnames(pd..), c(list(NULL), dimnames(m5)[2L])) }) assert.EQ.mat(p1, cbind(c(20,30,33,38,54))) assert.EQ.mat(pd1, m. %*% diag(1:6)) assert.EQ.mat(pd2, diag(10:6) %*% m.) assert.EQ.mat(pd., as(pd1,"matrix")) assert.EQ.mat(pd..,as(pd2,"matrix")) ## check that 'solve' and '%*%' are inverses suppressWarnings(RNGversion("3.5.0")); set.seed(1) A <- Matrix(rnorm(25), ncol = 5) y <- rnorm(5) all.equal((A %*% solve(A, y))@x, y) Atr <- new("dtrMatrix", Dim = A@Dim, x = A@x, uplo = "U") all.equal((Atr %*% solve(Atr, y))@x, y) ## R-forge bug 5933 by Sebastian Herbert, ## https://r-forge.r-project.org/tracker/index.php?func=detail&aid=5933&group_id=61&atid=294 mLeft <- matrix(data = double(0), nrow = 3, ncol = 0) mRight <- matrix(data = double(0), nrow = 0, ncol = 4) MLeft <- Matrix(data = double(0), nrow = 3, ncol = 0) MRight <- Matrix(data = double(0), nrow = 0, ncol = 4) stopifnot(exprs = { class(mLeft) == class(mRight) class(MLeft) == class(MRight) class(MLeft) == "dgeMatrix" }) Qidentical3 <- function(a,b,c) Q.eq(a,b) && Q.eq(b,c) Qidentical4 <- function(a,b,c,d) Q.eq(a,b) && Q.eq(b,c) && Q.eq(c,d) chkP <- function(mLeft, mRight, MLeft, MRight, cl = class(MLeft)) { ident4 <- if(extends(cl, "generalMatrix")) { function(a,b,c,d) { r <- eval(Matrix:::.as.via.virtual( class(a)[1L], cl[1], quote(a))) identical4(r,b,c,d) } } else { function(a,b,c,d) { assert.EQ.mat(M=b, m=a, tol=0) Qidentical3(b,c,d) } } mm <- mLeft %*% mRight # ok m.m <- crossprod(mRight) mm. <- tcrossprod(mLeft, mLeft) stopifnot(mm == 0, ident4(mm, mLeft %*% MRight, MLeft %*% mRight, MLeft %*% MRight),# now ok m.m == 0, identical(m.m, crossprod(mRight, mRight)), mm. == 0, identical(mm., tcrossprod(mLeft, mLeft)), allow.logical0 = TRUE) stopifnot(ident4(m.m, crossprod(MRight, MRight), crossprod(MRight, mRight), crossprod(mRight, MRight))) stopifnot(ident4(mm., tcrossprod(mLeft, MLeft), tcrossprod(MLeft, MLeft), tcrossprod(MLeft, mLeft))) } chkP(mLeft, mRight, MLeft, MRight, "dgeMatrix") m0 <- mLeft[FALSE,] # 0 x 0 for(cls in c("triangularMatrix", "symmetricMatrix")) { cat(cls,": "); stopifnotValid(ML0 <- as(MLeft[FALSE,], cls), cls) chkP(m0, mRight, ML0, MRight, class(ML0)) chkP(mLeft, m0 , MLeft, ML0 , class(ML0)) chkP(m0, m0 , ML0, ML0 , class(ML0)); cat("\n") } ## New in R 3.2.0 -- for traditional matrix m and vector v for(spV in c(FALSE,TRUE)) { cat("sparseV:", spV, "\n") v <- if(spV) as(1:3, "sparseVector") else 1:3 stopifnot(identical(class(v2 <- v[1:2]), class(v))) assertError(crossprod(v, v2)) ; assertError(v %*% v2) assertError(crossprod(v, 1:2)); assertError(v %*% 1:2) assertError(crossprod(v, 2)) ; assertError(v %*% 2) assertError(crossprod(1:2, v)); assertError(1:2 %*% v) cat("doing vec x vec ..\n") stopifnot(identical(crossprod(2, v), t(2) %*% v), identical(5 %*% v, 5 %*% t(v))) for(sp in c(FALSE, TRUE)) { m <- Matrix(1:2, 1,2, sparse=sp) cat(sprintf("class(m): '%s'\n", class(m))) stopifnot(identical( crossprod(m, v), t(m) %*% v), # m'v gave *outer* prod wrongly! identical(tcrossprod(m, v2), m %*% v2)) assert.EQ.Mat(m %*% v2, m %*% 1:2, tol=0) } ## gave error "non-conformable arguments" } ## crossprod(m, v) t(1 x 2) * 3 ==> (2 x 1) * (1 x 3) ==> 2 x 3 ## tcrossprod(m,v2) 1 x 2 * 2 ==> (1 x 2) * t(1 x 2) ==> 1 x 1 ### ------ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Sparse Matrix products ### ------ ## solve() for dtC* mc <- round(chol(crossprod(A)), 2) B <- A[1:3,] # non-square on purpose stopifnot(all.equal(sum(rowSums(B %*% mc)), 5.82424475145)) assert.EQ.mat(tcrossprod(B, mc), as.matrix(t(tcrossprod(mc, B)))) m <- kronecker(Diagonal(2), mc) stopifnot(is(mc, "dtrMatrix"), is(m, "sparseMatrix")) im <- solve(m) round(im, 3) itm <- solve(t(m)) iim <- solve(im) # should be ~= 'm' of course iitm <- solve(itm) I <- Diagonal(nrow(m)) (del <- c(mean(abs(as.numeric(im %*% m - I))), mean(abs(as.numeric(m %*% im - I))), mean(abs(as.numeric(im - t(itm)))), mean(abs(as.numeric( m - iim))), mean(abs(as.numeric(t(m)- iitm))))) stopifnot(is(m, "triangularMatrix"), is(m, "sparseMatrix"), is(im, "dtCMatrix"), is(itm, "dtCMatrix"), is(iitm, "dtCMatrix"), del < 1e-15) ## crossprod(.,.) & tcrossprod(), mixing dense & sparse v <- c(0,0,2:0) mv <- as.matrix(v) ## == cbind(v) (V <- Matrix(v, 5,1, sparse=TRUE)) sv <- as(v, "sparseVector") a <- as.matrix(A) cav <- crossprod(a,v) tva <- tcrossprod(v,a) assert.EQ.mat(crossprod(A, V), cav) # gave infinite recursion assert.EQ.mat(crossprod(A,sv), cav) assert.EQ.mat(tcrossprod( sv, A), tva) assert.EQ.mat(tcrossprod(t(V),A), tva) ## [t]crossprod() for . incl. one arg.: stopifnotValid(s.s <- crossprod(sv,sv), "Matrix") stopifnotValid(ss. <- tcrossprod(sv,sv), "sparseMatrix") stopifnot(identical(as(s.s, "symmetricMatrix"), crossprod(sv)), identical(as(ss., "symmetricMatrix"), tcrossprod(sv))) assert.EQ.mat(s.s, crossprod(v,v)) assert.EQ.mat(ss., tcrossprod(v,v)) dm <- Matrix(v, sparse=FALSE) sm <- Matrix(v, sparse=TRUE) vvt <- tcrossprod(v, v) validObject(d.vvt <- as(as(vvt, "unpackedMatrix"), "generalMatrix")) validObject(s.vvt <- as(as(vvt, "CsparseMatrix"), "generalMatrix")) stopifnot( identical4(tcrossprod(v, v), tcrossprod(mv, v), tcrossprod(v,mv), tcrossprod(mv,mv))## (base R) , identical4(d.vvt, tcrossprod(dm, v), tcrossprod(v,dm), tcrossprod(dm,dm)) ## (v, dm) failed , identical(s.vvt, tcrossprod(sm,sm)) , identical3(d.vvt, tcrossprod(sm, v), tcrossprod(v,sm)) ## both (sm,v) and (v,sm) failed ) assert.EQ.mat(d.vvt, vvt) assert.EQ.mat(s.vvt, vvt) M <- Matrix(0:5, 2,3) ; sM <- as(M, "sparseMatrix"); m <- as(M, "matrix") v <- 1:3; v2 <- 2:1 sv <- as( v, "sparseVector") sv2 <- as(v2, "sparseVector") tvm <- tcrossprod(v, m) assert.EQ.mat(tcrossprod( v, M), tvm) assert.EQ.mat(tcrossprod( v,sM), tvm) assert.EQ.mat(tcrossprod(sv,sM), tvm) assert.EQ.mat(tcrossprod(sv, M), tvm) assert.EQ.mat(crossprod(M, sv2), crossprod(m, v2)) stopifnot(identical(tcrossprod(v, M), v %*% t(M)), identical(tcrossprod(v,sM), v %*% t(sM)), identical(tcrossprod(v, M), crossprod(v, t(M))), identical(tcrossprod(sv,sM), sv %*% t(sM)), identical(crossprod(sM, sv2), t(sM) %*% sv2), identical(crossprod(M, v2), t(M) %*% v2)) ## *unit* triangular : t1 <- new("dtTMatrix", x= c(3,7), i= 0:1, j=3:2, Dim= as.integer(c(4,4))) ## from 0-diagonal to unit-diagonal {low-level step}: tu <- t1 ; tu@diag <- "U" cu <- as(tu, "CsparseMatrix") cl <- t(cu) # unit lower-triangular cl10 <- cl %*% Diagonal(4, x=10) assert.EQ.mat(cl10, as(cl, "matrix") %*% diag(4, x=10)) stopifnot(is(cl,"dtCMatrix"), cl@diag == "U") (cu2 <- cu %*% cu) cl2 <- cl %*% cl validObject(cl2) cu3 <- tu[-1,-1] assert.EQ.mat(crossprod(tru, cu3),## <- "FIXME" should return triangular ... crossprod(trm, as.matrix(cu3))) cl2 mcu <- as.matrix(cu) cu2. <- Diagonal(4) + Matrix(c(rep(0,9),14,0,0,6,0,0,0), 4,4) D4 <- Diagonal(4, x=10:7); d4 <- as(D4, "matrix") D.D4 <- crossprod(D4); assert.EQ.mat(D.D4, crossprod(d4)) stopifnotValid(D.D4, "ddiMatrix") stopifnotValid(su <- crossprod(cu), "dsCMatrix") asGe <- function(x) as(as(x, "unpackedMatrix"), "generalMatrix") stopifnot(exprs = { all(cu2 == cu2.) ## was wrong for ver. <= 0.999375-4 identical(D.D4, tcrossprod(D4)) identical4(crossprod(d4, D4), crossprod(D4, d4), tcrossprod(d4, D4), asGe(D.D4)) is(cu2, "dtCMatrix") # triangularity preserved is(cl2, "dtCMatrix") cu2@diag == "U" # unit triangularity preserved cl2@diag == "U" all.equal(D4 %*% mcu, asGe(D4 %*% cu)) all.equal(mcu %*% D4, asGe(cu %*% D4)) all(D4 %*% su == D4 %*% as.mat(su)) all(su %*% D4 == as.mat(su) %*% D4) identical(t(cl2), cu2) ## !! identical(crossprod(mcu, D4), asGe(crossprod(cu, D4))) identical4(asGe(tcrossprod(cu, D4)), tcrossprod(mcu, D4), asGe(cu %*% D4), mcu %*% D4) identical4(asGe(tcrossprod(D4, cu)), tcrossprod(D4,mcu), asGe(D4 %*% t(cu)), D4 %*% t(mcu)) identical( crossprod(cu), Matrix( crossprod(mcu),sparse=TRUE)) identical(tcrossprod(cu), Matrix(tcrossprod(mcu),sparse=TRUE)) }) assert.EQ.mat( crossprod(cu, D4), crossprod(mcu, d4)) assert.EQ.mat(tcrossprod(cu, D4), tcrossprod(mcu, d4)) tr8 <- kronecker(Matrix(rbind(c(2,0),c(1,4))), cl2) T8 <- tr8 %*% (tr8/2) # triangularity preserved? T8.2 <- (T8 %*% T8) / 4 stopifnot(is(T8, "triangularMatrix"), T8@uplo == "L", is(T8.2, "dtCMatrix")) mr8 <- as(tr8,"matrix") m8. <- (mr8 %*% mr8 %*% mr8 %*% mr8)/16 assert.EQ.mat(T8.2, m8.) data(KNex, package = "Matrix") mm <- KNex$mm M <- mm[1:500, 1:200] MT <- as(M, "TsparseMatrix") cpr <- t(mm) %*% mm cpr. <- crossprod(mm) cpr.. <- crossprod(mm, mm) stopifnot(is(cpr., "symmetricMatrix"), identical3(cpr, as(cpr., "generalMatrix"), cpr..)) ## with dimnames: m <- Matrix(c(0, 0, 2:0), 3, 5) dimnames(m) <- list(LETTERS[1:3], letters[1:5]) m p1 <- t(m) %*% m (p1. <- crossprod(m)) t1 <- m %*% t(m) (t1. <- tcrossprod(m)) stopifnot(isSymmetric(p1.), isSymmetric(t1.), identical(p1, as(p1., "generalMatrix")), identical(t1, as(t1., "generalMatrix")), identical(dimnames(p1), dimnames(p1.)), identical(dimnames(p1), list(colnames(m), colnames(m))), identical(dimnames(t1), dimnames(t1.)) ) showMethods("%*%", classes=class(M)) v1 <- rep(1, ncol(M)) str(r <- M %*% Matrix(v1)) str(rT <- MT %*% Matrix(v1)) stopifnot(identical(r, rT)) str(r. <- M %*% as.matrix(v1)) stopifnot(identical4(r, r., rT, M %*% as(v1, "matrix"))) v2 <- rep(1,nrow(M)) r2 <- t(Matrix(v2)) %*% M r2T <- v2 %*% MT str(r2. <- v2 %*% M) stopifnot(identical3(r2, r2., t(as(v2, "matrix")) %*% M)) ###------------------------------------------------------------------ ### Close to singular matrix W ### (from micEconAids/tests/aids.R ... priceIndex = "S" ) (load(system.file("external", "symW.rda", package="Matrix"))) # "symW" stopifnot(is(symW, "symmetricMatrix")) n <- nrow(symW) I <- .sparseDiagonal(n, shape="g") S <- as(symW, "matrix") sis <- solve(S, S) ## solve(, ) when Cholmod fails was buggy for *long*: o. <- options(Matrix.verbose = 2) # <-- showing Cholmod error & warning now SIS <- solve(symW, symW) iw <- solve(symW) ## << TODO: LU *not* saved in @factors iss <- iw %*% symW ## nb-mm3 openBLAS (Avi A.) assert.EQ.(I, drop0(sis), tol = 1e-8)# 2.6e-10; 7.96e-9 assert.EQ.(I, SIS, tol = 1e-7)# 8.2e-9 assert.EQ.(I, iss, tol = 4e-4)# 3.3e-5 ## solve(, ) : I <- diag(nrow=n) SIS <- solve(symW, as(symW,"denseMatrix")) iw <- solve(symW, I) iss <- iw %*% symW assert.EQ.mat(SIS, I, tol = 1e-7, giveRE=TRUE) assert.EQ.mat(iss, I, tol = 4e-4, giveRE=TRUE) rm(SIS,iss) WW <- as(symW, "generalMatrix") # the one that gave problems IW <- solve(WW) class(I1 <- IW %*% WW)# "dge" or "dgC" (!) class(I2 <- WW %*% IW) ## these two were wrong for for M.._1.0-13: assert.EQ.(as(I1,"matrix"), I, tol = 1e-4) assert.EQ.(as(I2,"matrix"), I, tol = 7e-7) ## now slightly perturb WW (and hence break exact symmetry set.seed(131); ii <- sample(length(WW), size= 100) WW[ii] <- WW[ii] * (1 + 1e-7*runif(100)) SW. <- symmpart(WW) SW2 <- forceSymmetric(WW) stopifnot(all.equal(as(SW.,"matrix"), as(SW2,"matrix"), tolerance = 1e-7)) (ch <- all.equal(WW, as(SW., "generalMatrix"), tolerance = 0)) stopifnot(is.character(ch), length(ch) == 1)## had length(.) 2 previously IW <- solve(WW) # ( => stores in WW@factors !) class(I1 <- IW %*% WW)# "dge" or "dgC" (!) class(I2 <- WW %*% IW) I <- diag(nrow=nrow(WW)) stopifnot(all.equal(as(I1,"matrix"), I, check.attributes=FALSE, tolerance = 1e-4), ## "Mean relative difference: 3.296549e-05" (or "1.999949" for Matrix_1.0-13 !!!) all.equal(as(I2,"matrix"), I, check.attributes=FALSE)) #default tol gives "1" for M.._1.0-13 options(o.) # revert to less Matrix.verbose if(doExtras) { print(kappa(WW)) ## [1] 5.129463e+12 print(rcond(WW)) ## [1] 6.216103e-14 ## Warning message: rcond(.) via sparse -> dense coercion } class(Iw. <- solve(SW.))# FIXME? should be "symmetric" but is not class(Iw2 <- solve(SW2))# FIXME? should be "symmetric" but is not class(IW. <- as(Iw., "denseMatrix")) class(IW2 <- as(Iw2, "denseMatrix")) ### The next two were wrong for very long, too assert.EQ.(I, as.matrix(IW. %*% SW.), tol= 4e-4) assert.EQ.(I, as.matrix(IW2 %*% SW2), tol= 4e-4) dIW <- as(IW, "denseMatrix") assert.EQ.(dIW, IW., tol= 4e-4) assert.EQ.(dIW, IW2, tol= 8e-4) ##------------------------------------------------------------------ ## Sparse Cov.matrices from Harri Kiiveri @ CSIRO a <- matrix(0,5,5) a[1,2] <- a[2,3] <- a[3,4] <- a[4,5] <- 1 a <- a + t(a) + 2*diag(5) b <- as(a, "CsparseMatrix") ## ok, but we recommend to use Matrix() ``almost always'' : (b. <- Matrix(a, sparse = TRUE)) stopifnot(identical(b, b.)) ## calculate conditional variance matrix ( vars 3 4 5 given 1 2 ) (B2 <- b[1:2, 1:2]) bb <- b[1:2, 3:5] stopifnot(is(B2, "dsCMatrix"), # symmetric indexing keeps symmetry identical(as.mat(bb), rbind(0, c(1,0,0))), ## TODO: use fully-sparse cholmod_spsolve() based solution : is(z.s <- solve(B2, bb), "sparseMatrix")) assert.EQ.mat(B2 %*% z.s, as(bb, "matrix")) ## -> dense RHS and dense result z. <- solve(as(B2, "generalMatrix"), bb)# now *sparse* z <- solve( B2, as(bb, "denseMatrix")) stopifnot(is(z., "sparseMatrix"), all.equal(z, as(z.,"denseMatrix"))) ## finish calculating conditional variance matrix v <- b[3:5,3:5] - crossprod(bb,z) stopifnot(all.equal(as.mat(v), matrix(c(4/3, 1:0, 1,2,1, 0:2), 3), tolerance = 1e-14)) ###--- "logical" Matrices : --------------------- ##__ FIXME __ now works for lsparse* and nsparse* but not yet for lge* and nge* ! ## Robert's Example, a bit more readable fromTo <- rbind(c(2,10), c(3, 9)) N <- 10 nrFT <- nrow(fromTo) rowi <- rep.int(1:nrFT, fromTo[,2]-fromTo[,1] + 1) - 1:1 coli <- unlist(lapply(1:nrFT, function(x) fromTo[x,1]:fromTo[x,2])) - 1:1 # ## "n" --- nonzero pattern Matrices chk.ngMatrix <- function(M, verbose = TRUE) { if(!(is(M, "nsparseMatrix") && length(d <- dim(M)) == 2 && d[1] == d[2])) stop("'M' must be a square sparse [patter]n Matrix") if(verbose) show(M) m <- as(M, "matrix") ## Part I : matrix products of pattern Matrices ## ------ For now [by default]: *pattern* <==> boolean arithmetic ## ==> FIXME ??: warning that this will change? MM <- M %*% M # numeric (dgC) if(verbose) { cat("M %*% M:\n"); show(MM) } assert.EQ.mat(MM, m %*% m) assert.EQ.mat(t(M) %&% M, (t(m) %*% m) > 0, tol=0) cM <- crossprod(M) # pattern {FIXME ?? warning ...} tM <- tcrossprod(M) # pattern {FIXME ?? warning ...} if(verbose) {cat( "crossprod(M):\n"); show(cM) } if(verbose) {cat("tcrossprod(M):\n"); show(tM) } stopifnot(is(cM,"symmetricMatrix"), is(tM,"symmetricMatrix"), identical(as(as(cM, "CsparseMatrix"), "generalMatrix"), t(M) %&% M), identical(as(as(tM, "CsparseMatrix"), "generalMatrix"), M %&% t(M))) assert.EQ.mat(cM, crossprod(m) > 0) assert.EQ.mat(tM, as(tcrossprod(m), "matrix") > 0) ## Part II : matrix products pattern Matrices with numeric: ## ## "n" x "d" (and "d" x "n") --> "d", i.e. numeric in any case dM <- as(M, "dMatrix") stopifnot(exprs = { ## dense ones: identical(M %*% m, m %*% M -> Mm) ## sparse ones : identical3(M %*% dM, dM %*% M -> sMM, eval(Matrix:::.as.via.virtual( "matrix", class(sMM), quote(m %*% m)))) }) if(verbose) {cat( "M %*% m:\n"); show(Mm) } stopifnotValid(Mm, "dMatrix") # not "n.." stopifnotValid(sMM, "dMatrix") # not "n.." stopifnotValid(cdM <- crossprod(dM, M), "CsparseMatrix") stopifnotValid(tdM <- tcrossprod(dM, M), "CsparseMatrix") assert.EQ.mat (cdM, crossprod(m)) assert.EQ.mat (tdM, tcrossprod(m)) stopifnot(identical( crossprod(dM), as(cdM, "symmetricMatrix"))) stopifnot(identical(tcrossprod(dM), as(tdM, "symmetricMatrix"))) invisible(TRUE) } sM <- new("ngTMatrix", i = rowi, j=coli, Dim=as.integer(c(N,N))) chk.ngMatrix(sM) # "ngTMatrix" chk.ngMatrix(tsM <- as(sM, "triangularMatrix")) # ntT chk.ngMatrix(as( sM, "CsparseMatrix")) # ngC chk.ngMatrix(as(tsM, "CsparseMatrix")) # ntC ## "l" --- logical Matrices -- use usual 0/1 arithmetic nsM <- sM sM <- as(sM, "lMatrix") sm <- as(sM, "matrix") stopifnot(identical(sm, as.matrix(nsM))) stopifnotValid(sMM <- sM %*% sM, "dsparseMatrix") assert.EQ.mat (sMM, sm %*% sm) assert.EQ.mat(t(sM) %*% sM, t(sm) %*% sm, tol=0) stopifnotValid(cM <- crossprod(sM), "dsCMatrix") stopifnotValid(tM <- tcrossprod(sM), "dsCMatrix") stopifnot(identical(cM, as(t(sM) %*% sM, "symmetricMatrix")), identical(tM, forceSymmetric(sM %*% t(sM)))) assert.EQ.mat( cM, crossprod(sm)) assert.EQ.mat( tM, as(tcrossprod(sm),"matrix")) dm <- as(sM, "denseMatrix") ## the following 6 products (dm o sM) all failed up to 2013-09-03 stopifnotValid(dm %*% sM, "denseMatrix")## failed {missing coercion} stopifnotValid(crossprod (dm , sM),"denseMatrix") stopifnotValid(tcrossprod(dm , sM),"denseMatrix") dm[2,1] <- TRUE # no longer triangular stopifnotValid( dm %*% sM, "denseMatrix") stopifnotValid(crossprod (dm , sM),"denseMatrix") stopifnotValid(tcrossprod(dm , sM),"denseMatrix") ## A sparse example - with *integer* matrix: M <- Matrix(cbind(c(1,0,-2,0,0,0,0,0,2.2,0), c(2,0,0,1,0), 0, 0, c(0,0,8,0,0),0)) t(M) (-4:5) %*% M stopifnot(as.vector(print(t(M %*% 1:6))) == c(as(M,"matrix") %*% 1:6)) (M.M <- crossprod(M)) MM. <- tcrossprod(M) stopifnot(class(MM.) == "dsCMatrix", class(M.M) == "dsCMatrix") M3 <- Matrix(c(rep(c(2,0),4),3), 3,3, sparse=TRUE) I3 <- as(Diagonal(3), "CsparseMatrix") m3 <- as.matrix(M3) iM3 <- solve(m3) stopifnot(all.equal(unname(iM3), matrix(c(3/2,0,-1,0,1/2,0,-1,0,1), 3))) assert.EQ.mat(solve(as(M3, "sparseMatrix")), iM3) assert.EQ.mat(solve(I3,I3), diag(3)) assert.EQ.mat(solve(M3, I3), iM3)# was wrong because I3 is unit-diagonal assert.EQ.mat(solve(m3, I3), iM3)# gave infinite recursion in (<=) 0.999375-10 stopifnot(identical(ttI3 <- crossprod(tru, I3), t(tru) %*% I3), identical(tI3t <- crossprod(I3, tru), t(I3) %*% tru), identical(I3tt <- tcrossprod(I3, tru), I3 %*% t(tru))) I3@uplo # U pper triangular tru@uplo# L ower triangular ## "FIXME": These are all FALSE now; the first one *is* ok (L o U); the others *not* isValid(tru %*% I3, "triangularMatrix") isValid(ttI3, "triangularMatrix") isValid(tI3t, "triangularMatrix") isValid(I3tt, "triangularMatrix") ## even simpler m <- matrix(0, 4,7); m[c(1, 3, 6, 9, 11, 22, 27)] <- 1 (mm <- Matrix(m)) (cm <- Matrix(crossprod(m))) stopifnot(identical(crossprod(mm), cm)) (tm1 <- Matrix(tcrossprod(m))) #-> had bug in 'Matrix()' ! (tm2 <- tcrossprod(mm)) Im2 <- solve(tm2[-4,-4]) P <- as(as.integer(c(4,1,3,2)),"pMatrix") p <- as(P, "matrix") P %*% mm assertError(mm %*% P) # dimension mismatch assertError(m %*% P) # ditto assertError(crossprod(t(mm), P)) # ditto stopifnotValid(tm1, "dsCMatrix") stopifnot(exprs = { all.equal(tm1, tm2, tolerance = 1e-15) all.equal(Im2 %*% tm2[1:3,], Matrix(cbind(diag(3), 0))) identical(p, as.matrix(P)) all(P %*% m == as.matrix(P) %*% m) all(P %*% mm == P %*% m) all(P %*% mm - P %*% m == 0) all(t(mm) %*% P == t(m) %*% P) all(crossprod(m, P) == crossprod(mm, P)) }) d <- function(m) as(m,"dsparseMatrix") IM1 <- as(c(3,1,2), "indMatrix") IM2 <- as(c(1,2,1), "indMatrix") assert.EQ.Mat(crossprod( IM1, IM2), crossprod(d(IM1),d(IM2)), tol=0)# failed at first iM <- as(cbind2(IM2, 0), "indMatrix") assert.EQ.Mat(crossprod(iM), Diagonal(x = 2:0)) assert.EQ.Mat(crossprod(iM, iM), Diagonal(x = 2:0)) N3 <- Diagonal(x=1:3) U3 <- Diagonal(3) # unit diagonal (@diag = "U") C3 <- as(N3, "CsparseMatrix") lM <- as(IM2, "lMatrix") nM <- as(IM2, "nMatrix") nCM <- as(nM, "CsparseMatrix") NM <- N3 %*% IM2 NM. <- C3 %*% IM2 stopifnot(Q.C.identical(NM, ## <- failed d(N3) %*% d(IM2), checkClass=FALSE), identical(NM, N3 %*% lM), identical(NM, N3 %*% nM) , ## all these "work" (but partly wrongly gave non-numeric Matrix: Q.C.identical(NM, NM., checkClass=FALSE) , mQidentical(as.matrix(NM.), array(c(1, 0, 3, 0, 2, 0), dim=3:2)) , identical(NM., C3 %*% lM) , identical(NM., C3 %*% nM) # wrongly gave n*Matrix , isValid(U3 %*% IM2, "dsparseMatrix")# was l* , isValid(U3 %*% lM, "dsparseMatrix")# was l* , isValid(U3 %*% nM, "dsparseMatrix")# was n* , identical(C3 %*% nM -> C3n, # wrongly gave ngCMatrix C3 %*% nCM) , isValid(C3n, "dgCMatrix") , identical3(U3 %*% IM2, # wrongly gave lgTMatrix U3 %*% lM -> U3l, # ditto U3 %*% nM) # wrongly gave ngTMatrix , isValid(U3l, "dgRMatrix") ) selectMethod("%*%", c("dtCMatrix", "ngTMatrix")) # x %*% .T.2.C(y) --> selectMethod("%*%", c("dtCMatrix", "ngCMatrix")) # .Call(Csparse_Csparse_prod, x, y) selectMethod("%*%", c("ddiMatrix", "indMatrix")) # x %*% as(y, "lMatrix") -> selectMethod("%*%", c("ddiMatrix", "lgTMatrix")) # diagCspprod(as(x, "Csp.."), y) selectMethod("%*%", c("ddiMatrix", "ngTMatrix")) # (ditto) stopifnot( isValid(show(crossprod(C3, nM)), "dgCMatrix"), # wrongly gave ngCMatrix identical3(## the next 4 should give the same (since C3 and U3 are symmetric): show(crossprod(U3, IM2)),# wrongly gave ngCMatrix crossprod(U3, nM), # ditto crossprod(U3, lM))) # wrongly gave lgCMatrix set.seed(123) for(n in 1:250) { n1 <- 2 + rpois(1, 10) n2 <- 2 + rpois(1, 10) N <- rpois(1, 25) ii <- seq_len(N + min(n1,n2)) IM1 <- as(c(sample(n1), sample(n1, N, replace=TRUE))[ii], "indMatrix") IM2 <- as(c(sample(n2), sample(n2, N, replace=TRUE))[ii], "indMatrix") ## stopifnot(identical(crossprod( IM1, IM2), ## crossprod(d(IM1), d(IM2)))) if(!identical(C1 <- crossprod( IM1, IM2 ), CC <- crossprod(d(IM1), d(IM2))) && !all(C1 == CC)) { cat("The two crossprod()s differ: C1 - CC =\n") print(C1 - CC) stop("The two crossprod()s differ!") } else if(n %% 25 == 0) cat(n, " ") }; cat("\n") ## two with an empty column --- these failed till 2014-06-14 X <- as(c(1,3,4,5,3), "indMatrix") Y <- as(c(2,3,4,2,2), "indMatrix") ## kronecker: stopifnot(identical(X %x% Y, as(as.matrix(X) %x% as.matrix(Y), "indMatrix"))) ## crossprod: (XtY <- crossprod(X, Y))# gave warning in Matrix 1.1-3 XtY_ok <- as(crossprod(as.matrix(X), as.matrix(Y)), "TsparseMatrix") assert.EQ.Mat(XtY, XtY_ok) # not true, previously ###------- %&% -------- Boolean Arithmetic Matrix products x5 <- c(2,0,0,1,4) D5 <- Diagonal(x=x5) N5 <- as(D5 != 0, "nMatrix") ## an "ndiMatrix" D. <- Diagonal(x=c(TRUE,FALSE,TRUE,TRUE,TRUE)) stopifnot(identical(D5 %&% D., N5)) stopifnot(identical(D5 %&% as(D.,"CsparseMatrix"), as(N5,"CsparseMatrix"))) set.seed(7) L <- Matrix(rnorm(20) > 1, 4,5) (N <- as(L, "nMatrix")) D <- Matrix(round(rnorm(30)), 5,6) # "dge", values in -1:1 (for this seed) L %&% D stopifnot(identical(L %&% D, N %&% D), all(L %&% D == as((L %*% abs(D)) > 0, "sparseMatrix"))) stopifnotValid(show(crossprod(N )) , "nsCMatrix") # (TRUE/FALSE : boolean arithmetic) stopifnotValid(show(crossprod(N +0)) -> cN0, "dsCMatrix") # -> numeric Matrix (with same "pattern") stopifnot(all(crossprod(N) == t(N) %&% N), identical(crossprod(N, boolArith=TRUE) -> cN., as(cN0 != 0, "nMatrix")), identical (cN., crossprod(L, boolArith=TRUE)), identical3(cN0, crossprod(L), crossprod(L, boolArith=FALSE)) ) stopifnotValid(cD <- crossprod(D, boolArith = TRUE), "nsCMatrix") # sparse: "for now" ## another slightly differing test "series" L.L <- crossprod(L) (NN <- as(L.L > 0,"nMatrix")) nsy <- as(NN,"denseMatrix") stopifnot(identical(NN, crossprod(NN)))# here stopifnotValid(csy <- crossprod(nsy), "nsCMatrix") stopifnotValid(csy. <- crossprod(nsy, boolArith=TRUE),"nsCMatrix") stopifnot(all((csy > 0) == csy.), all(csy. == (nsy %&% nsy))) ## for "many" more seeds: set.seed(7); for(nn in 1:256) { L <- Matrix(rnorm(20) > 1, 4,5) D <- Matrix(round(rnorm(30)), 5,6) stopifnot(all(L %&% D == as((L %*% abs(D)) > 0, "sparseMatrix"))) } ## [Diagonal] o [0-rows/colums] : m20 <- matrix(nrow = 2, ncol = 0); m02 <- t(m20) M20 <- Matrix(nrow = 2, ncol = 0); M02 <- t(M20) stopifnot(identical(dim(Diagonal(x=c(1,2)) %*% m20), c(2L, 0L)), identical(dim(Diagonal(2) %*% M20), c(2L, 0L)), identical(dim(Diagonal(x=2:1) %*% M20), c(2L, 0L))) stopifnot(identical(dim(m02 %*% Diagonal(x=c(1,2))), c(0L, 2L)), identical(dim(M02 %*% Diagonal(2) ), c(0L, 2L)), identical(dim(M02 %*% Diagonal(x=2:1) ), c(0L, 2L))) ## RsparseMatrix --- Arko Bose (Jan.2022): "Method for %*% " (m <- Matrix(c(0,0,2:0), 3,5)) stopifnotValid(R <- as(m, "RsparseMatrix"), "RsparseMatrix") stopifnotValid(T <- as(m, "TsparseMatrix"), "TsparseMatrix") stopifnot(exprs = { all.equal(as(t(R) %*% R, "symmetricMatrix"), crossprod(R) -> cR) all.equal(as(R %*% t(R), "symmetricMatrix"), tcrossprod(R) -> tR) all.equal(as(R %*% t(m), "symmetricMatrix"), as(tcrossprod(m), "RsparseMatrix")) all.equal(as(m %*% t(R), "symmetricMatrix"), as(tcrossprod(m), "CsparseMatrix")) ## failed in Matrix <= 1.4.1 (since 1.2.0, when 'boolArith' was introduced): all.equal(as(cR, "RsparseMatrix"), as( crossprod(R, T), "symmetricMatrix")) all.equal(as(cR, "CsparseMatrix"), as( crossprod(T, R), "symmetricMatrix")) all.equal(as(tR, "RsparseMatrix"), as(tcrossprod(R, T), "symmetricMatrix")) all.equal(as(tR, "CsparseMatrix"), as(tcrossprod(T, R), "symmetricMatrix")) }) ## More for kronecker() ------------------------------------------------ checkKronecker <- function(X, Y, ...) { k1 <- as(k0 <- kronecker(X, Y, ...), "matrix") k2 <- kronecker(as(X, "matrix"), as(Y, "matrix"), ...) cldX <- getClassDef(class(X)) cldY <- getClassDef(class(Y)) if(extends(cldX, "indMatrix") && extends(cldY, "indMatrix")) { stopifnot(is(k0, "indMatrix")) storage.mode(k2) <- "logical" } if(extends(cldX, "triangularMatrix") && extends(cldY, "triangularMatrix") && X@uplo == Y@uplo) stopifnot(is(k0, "triangularMatrix"), k0@uplo == X@uplo, k0@diag == (if(X@diag == "N" || Y@diag == "N") "N" else "U")) else if(extends(cldX, "symmetricMatrix") && extends(cldY, "symmetricMatrix")) stopifnot(is(k0, "symmetricMatrix"), k0@uplo == X@uplo) ## could test for more special cases if(!isTRUE(ae <- all.equal(k1, k2))) stop(sprintf("checkKronecker(<%s>, <%s>):\n %s", class(X), class(Y), paste0(ae, collapse = "\n "))) } set.seed(145133) lXY <- lapply(rpois(2L, 10), function(n) { x <- rsparsematrix(n, n, 0.6) dn <- replicate(2L, if(sample(c(FALSE, TRUE), 1L)) sample(letters, n, TRUE), simplify = FALSE) x@Dimnames <- dn x4 <- list(as(as(x, "dMatrix"), "denseMatrix"), as(as(x, "dMatrix"), "CsparseMatrix"), as(as(x, "lMatrix"), "RsparseMatrix"), as(as(x, "nMatrix"), "TsparseMatrix")) mkList <- function(y) list(x, triu(x), tril(x), { z <- triu(x, 1L); z@diag <- "U"; z }, { z <- tril(x, -1L); z@diag <- "U"; z }, forceSymmetric(x, "U"), forceSymmetric(x, "L"), { z <- Diagonal(x = diag(x)); z@Dimnames <- dn; z }, as(sample.int(n, replace = TRUE), "indMatrix"), as(x, "matrix")) unlist(lapply(x4, mkList), FALSE, FALSE) }) lX <- lXY[[1L]] lY <- lXY[[2L]] for(i in seq_along(lX)) for(j in seq_along(lY)) checkKronecker(lX[[i]], lY[[j]], make.dimnames = TRUE) cat('Time elapsed: ', proc.time(),'\n') # for ``statistical reasons'' Matrix/tests/bind.R0000644000175100001440000002007614470702707013752 0ustar hornikusers#### Testing cbind() & rbind() -- based on cbind2() & rbind2() ## (where using 'cBind()' and 'rBind()' in Matrix) ## for R_DEFAULT_PACKAGES=NULL : library(utils) library(Matrix) source(system.file("test-tools.R", package = "Matrix"))# identical3() etc ### --- Dense Matrices --- m1 <- m2 <- m <- matrix(1:12, 3,4) dimnames(m2) <- list(LETTERS[1:3], letters[1:4]) dimnames(m1) <- list(NULL,letters[1:4]) M <- Matrix(m) M1 <- Matrix(m1) M2 <- Matrix(m2) stopifnot( identical3(cbind ( M, 10*M), show(cbind2( M, 10*M)), Matrix(cbind ( m, 10*m))) , identical3(cbind (M1, 100+M1), show(cbind2(M1, 100+M1)), Matrix(cbind (m1, 100+m1))) , identical3(cbind (M1, 10*M2), show(cbind2(M1, 10*M2)), Matrix(cbind (m1, 10*m2))) , identical3(cbind (M2, M1+M2), show(cbind2(M2, M1+M2)), Matrix(cbind (m2, m1+m2))) , identical(colnames(show(cbind(M1, MM = -1))), c(colnames(M1), "MM")) , identical3(rbind ( M, 10*M), show(rbind2( M, 10*M)), Matrix(rbind ( m, 10*m))) , identical3(rbind (M2, M1+M2), show(rbind2(M2, M1+M2)), Matrix(rbind (m2, m1+m2))) , Qidentical(show (rbind(R1 = 10:11, M1)), Matrix(rbind(R1 = 10:11, m1)), strictClass=FALSE) , TRUE) identical.or.eq <- function(x,y, tol=0, ...) { if(identical(x,y, ...)) TRUE else if(isTRUE(aeq <- all.equal(x,y, tolerance = tol))) structure(TRUE, comment = "not identical") else aeq } identicalShow <- function(x,y, ...) if(!isTRUE(id <- identical.or.eq(x, y, ...))) cat(id,"\n") ## Checking deparse.level { <==> example at end of ?cbind }: checkRN <- function(dd, B = rbind) { FN <- function(deparse.level) rownames(B(1:4, c=2,"a+"=10, dd, deparse.level=deparse.level)) rn <- c("1:4", "c", "a+", "dd", "") isMatr <- (length(dim(dd)) == 2) id <- if(isMatr) 5 else 4 identicalShow(rn[c(5,2:3, 5)], FN(deparse.level= 0)) # middle two names identicalShow(rn[c(5,2:3,id)], FN(deparse.level= 1)) # last shown if vector identicalShow(rn[c(1,2:3,id)], FN(deparse.level= 2)) # first shown; (last if vec.) } checkRN(10) # <==> ?cbind's ex checkRN(1:4) checkRN( rbind(c(0:1,0,0))) checkRN(Matrix(rbind(c(0:1,0,0)))) ## in R <= 3.4.1, from methods:::rbind bug : ## Modes: character, NULL Lengths: 4, 0 target is character, current is NULL checkRN(10 , rbind) checkRN(1:4, rbind) checkRN( rbind(c(0:1,0,0)), rbind) checkRN(Matrix(rbind(c(0:1,0,0))), rbind) cbind(0, Matrix(0+0:1, 1,2), 3:2)# FIXME? should warn - as with matrix() as(rbind(0, Matrix(0+0:1, 1,2), 3:2), "sparseMatrix") cbind(M2, 10*M2[nrow(M2):1 ,])# keeps the rownames from the first (im <- cbind(I = 100, M)) str(im) (mi <- cbind(M2, I = 1000)) str(mi) (m1m <- cbind(M,I=100,M2)) showProc.time() ## lgeMatrix -- rbind2() had bug (in C code): is.lge <- function(M) isValid(M, "lgeMatrix") stopifnot(exprs = { is.lge(rbind(M2 > 0, M2 < 0)) # had Error in rbind2(): ## REAL() can only be applied to a 'numeric', not a 'logical' is.lge(rbind(M2 < 0, M2 > 0)) # ditto is.lge(rbind(Matrix(1:6 %% 3 != 0, 2,3), FALSE)) is.lge(L <- rbind(Matrix(TRUE, 2,3), TRUE)) all(L) is.lge(rbind(Matrix(TRUE, 2,3), FALSE)) }) ### --- Diagonal / Sparse - had bugs D4 <- Diagonal(4) (D4T <- as(D4, "TsparseMatrix")) D4C <- as(D4T, "CsparseMatrix") c1 <- Matrix(0+0:3, 4, sparse=TRUE) ; r1 <- t(c1); r1 d4 <- rbind(Diagonal(4), 0:3) m4 <- cbind(Diagonal(x=-1:2), 0:3) c4. <- cbind(Diagonal(4), c1) c.4 <- cbind(c1, Diagonal(4)) r4. <- rbind(Diagonal(4), r1) r.4 <- rbind(r1, Diagonal(4)) assert.EQ.mat(d4, rbind(diag(4), 0:3)) assert.EQ.mat(m4, cbind(diag(-1:2), 0:3)) stopifnot(identical(Matrix(cbind(diag(3),0)), cbind2(Diagonal(3),0)), is(d4, "sparseMatrix"), is(m4, "sparseMatrix"), identical(.tCRT(d4), cbind(Diagonal(4), 0:3)), identical(.tCRT(m4), rbind(Diagonal(x=-1:2), 0:3))) showProc.time() ### --- Sparse Matrices --- identical4(cbind(diag(4), diag(4)), cbind(D4C, D4C), cbind(D4T, D4C), cbind(D4C, D4T)) nr <- 4 nc <- 6 m. <- matrix(rep_len(c(0, 2:-1), nr * nc), nr, nc) M <- Matrix(m.) (mC <- as(M, "CsparseMatrix")) (mT <- as(M, "TsparseMatrix")) stopifnot(identical(mT, as(mC, "TsparseMatrix")), identical(mC, as(mT, "CsparseMatrix"))) for(v in list(0, 2, 1:0)) for(fnam in c("cbind", "rbind")) { cat(fnam,"(m, v=", deparse(v),"), class(m) :") FUN <- get(fnam) for(m in list(M, mC, mT)) { cat("", class(m),"") assert.EQ.mat(FUN(v, m), FUN(v, m.)) ; cat(",") assert.EQ.mat(FUN(m, v), FUN(m., v)) ; cat(".") } cat("\n") } showProc.time() cbind(0, mC); cbind(mC, 0) cbind(0, mT); cbind(mT, 2) cbind(diag(nr), mT) stopifnot(identical(t(cbind(diag(nr), mT)), rbind(diag(nr), t(mT)))) (cc <- cbind(mC, 0,7,0, diag(nr), 0)) stopifnot(identical3(cc, as(cbind(mT, 0, 7, 0, diag(nr), 0), "CsparseMatrix"), as(cbind( M, 0, 7, 0, diag(nr), 0), "CsparseMatrix"))) cbind(mC, 1, 100*mC, 0, 0:2) cbind(mT, 1, 0, mT+10*mT, 0, 0:2) one <- 1 zero <- 0 dimnames(mC) <- dimnames(mT) <- list(LETTERS[1:4], letters[1:6]) op <- options(sparse.colnames = TRUE)# show colnames in print : cbind(mC, one, 100*mC, zero, 0:2) cbind(mC, one, 100*mC, zero, 0:2, deparse.level=0)# no "zero", "one" cbind(mC, one, 100*mC, zero, 0:2, deparse.level=2)# even "0:2" cbind(mT, one, zero, mT+10*mT, zero, 0:2) ## logical (sparse) - should remain logical : L5 <- Diagonal(n = 5, x = TRUE) v5 <- rep(x = c(FALSE,TRUE), length.out = ncol(L5)) stopifnot(is(show(rbind(L5,v5)), "lsparseMatrix"), is(show(cbind(v5,L5)), "lsparseMatrix"), is(rbind(L5, 2* v5), "dsparseMatrix"), is(cbind(2* v5, L5), "dsparseMatrix")) ## print() / show() of non-structural zeros: (m <- Matrix(c(0, 0, 2:0), 3, 5)) (m2 <- cbind(m,m)) (m4 <- rbind(m2,m2)) diag(m4) for(i in 1:6) { m4[i, i ] <- i m4[i,i+1] <- 0 } m4 ## now show some non-structural zeros: ## Mixture of dense and sparse/diagonal -- used to fail, even in 1.0-0 D5 <- Diagonal(x = 10*(1:5)) (D5.1 <- cbind2(D5, 1)) ## "FIXME" in newer versions of R, do not need Matrix() here: s42 <- Matrix(z42 <- cbind2(rep(0:1,4), rep(1:0,4)), sparse=TRUE) (C86 <- rbind(1, 0, D5.1, 0)) stopifnotValid(D5.1, "dgCMatrix") stopifnotValid(print(rbind2(Matrix(1:10, 2,5), D5)), "dgRMatrix") stopifnotValid(print(cbind2(Matrix(10:1, 5,2), D5.1)), "dgCMatrix") stopifnotValid(zz <- cbind2(z42, C86), "dgCMatrix") stopifnot(identical(zz, cbind2(s42, C86))) ## Using "nMatrix" (m1 <- sparseMatrix(1:3, 1:3)) # ngCMatrix m2 <- sparseMatrix(1:3, 1:3, x = 1:3) stopifnotValid(c12 <- cbind(m1,m2), "dgCMatrix") # was "ngC.." because of cholmod_horzcat ! stopifnotValid(c21 <- cbind(m2,m1), "dgCMatrix") # ditto stopifnotValid(r12 <- rbind(m1,m2), "dgCMatrix") # was "ngC.." because of cholmod_vertcat ! stopifnotValid(r21 <- rbind(m2,m1), "dgCMatrix") # ditto d1 <- as(m1, "denseMatrix") d2 <- as(m2, "denseMatrix") stopifnotValid(cbind2(d2,d1), "dgeMatrix") stopifnotValid(cbind2(d1,d2), "dgeMatrix")## gave an error in Matrix 1.1-5 stopifnotValid(rbind2(d2,d1), "dgeMatrix") stopifnotValid(rbind2(d1,d2), "dgeMatrix")## gave an error in Matrix 1.1-5 ## rbind2() / cbind2() mixing sparse/dense: used to "fail", ## ------------------- then (in 'devel', ~ 2015-03): completely wrong S <- .sparseDiagonal(2) s <- diag(2) S9 <- rbind(S,0,0,S,0,NaN,0,0,0,2)## r/cbind2() failed to determine 'sparse' in Matrix <= 1.2-2 s9 <- rbind(s,0,0,s,0,NaN,0,0,0,2) assert.EQ.mat(S9, s9) D <- Matrix(1:6, 3,2); d <- as(D, "matrix") T9 <- t(S9); t9 <- t(s9); T <- t(D); t <- t(d) stopifnot(identical(rbind (s9,d), rbind2(s9,d)), identical(rbind2(D,S9), t(cbind2(T,T9))), identical(rbind2(S9,D), t(cbind2(T9,T)))) assert.EQ.mat(rbind2(S9,D), rbind2(s9,d)) assert.EQ.mat(rbind2(D,S9), rbind2(d,s9)) ## now with cbind2() -- no problem! stopifnot(identical(cbind (t9,t), cbind2(t9,t))) assert.EQ.mat(cbind2(T9,T), cbind2(t9,t)) assert.EQ.mat(cbind2(T,T9), cbind2(t,t9)) options(op) showProc.time() Matrix/tests/packed-unpacked.R0000644000175100001440000003137314565737512016066 0ustar hornikusers## These are tests related to the replacement of many methods for the ## proper subclasses of 'denseMatrix' with methods for the (new, more ## general) virtual subclasses '(un)?packedMatrix'. ## for R_DEFAULT_PACKAGES=NULL : library(stats) library(Matrix) set.seed(145206) if (interactive()) { options(Matrix.verbose = TRUE, warn = 1, error = recover) } else { options(Matrix.verbose = TRUE, warn = 1) } U <- function(x, diag = FALSE) x[upper.tri(x, diag)] L <- function(x, diag = FALSE) x[lower.tri(x, diag)] `U<-` <- function(x, diag = FALSE, value) { x[upper.tri(x, diag)] <- value; x } `L<-` <- function(x, diag = FALSE, value) { x[lower.tri(x, diag)] <- value; x } mkDN <- function(Dim) list(A = paste0("a", seq_len(Dim[1L])), B = paste0("b", seq_len(Dim[2L]))) denseMatrix <- getClassDef("denseMatrix") packedMatrix <- getClassDef("packedMatrix") unpackedMatrix <- getClassDef("unpackedMatrix") generalMatrix <- getClassDef("generalMatrix") symmetricMatrix <- getClassDef("symmetricMatrix") triangularMatrix <- getClassDef("triangularMatrix") dMatrix <- getClassDef("dMatrix") lMatrix <- getClassDef("lMatrix") nMatrix <- getClassDef("nMatrix") ## FIXME: Implement in C?? unpackedClass <- function(packedClass) { getClassDef(c(dspMatrix = "dsyMatrix", lspMatrix = "lsyMatrix", nspMatrix = "nsyMatrix", dtpMatrix = "dtrMatrix", ltpMatrix = "ltrMatrix", ntpMatrix = "ntrMatrix", dppMatrix = "dpoMatrix", copMatrix = "corMatrix")[[packedClass@className]]) } packedClass <- function(unpackedClass) { getClassDef(c(dgeMatrix = NA, lgeMatrix = NA, ngeMatrix = NA, dsyMatrix = "dspMatrix", lsyMatrix = "lspMatrix", nsyMatrix = "nspMatrix", dtrMatrix = "dtpMatrix", ltrMatrix = "ltpMatrix", ntrMatrix = "ntpMatrix", dpoMatrix = "dppMatrix", corMatrix = "copMatrix")[[unpackedClass@className]]) } ...Class <- function(denseClass) { cl <- "...Matrix" substr(cl, 1L, 1L) <- if (d <- extends(denseClass, dMatrix)) "d" else if (extends(denseClass, lMatrix)) "l" else "n" substr(cl, 2L, 3L) <- if (g <- extends(denseClass, generalMatrix)) "ge" else if (extends(denseClass, symmetricMatrix)) "sy" else "tr" if (!g && extends(denseClass, packedMatrix)) { substr(cl, 3L, 3L) <- "p" } getClassDef(cl) } ## Tests methods for packed (unpacked) class 'Class' ## using randomly generated matrices of size 'n' testDenseClass <- function(Class, n) { if (!is(Class, "classRepresentation")) { Class <- getClassDef(Class) } stopifnot(extends(Class, denseMatrix), !isVirtualClass(Class)) is.p <- extends(Class, packedMatrix) is.ge <- extends(Class, generalMatrix) is.sy <- !is.ge && extends(Class, symmetricMatrix) is.tr <- !is.ge && !is.sy is.d <- extends(Class, dMatrix) is.l <- !is.d && extends(Class, lMatrix) is.n <- !is.d && !is.l ## For randomly generating matrix data .mkX <- if (is.d) function(n) rlnorm(n) # not rnorm(n), for validObject() else function(n) sample(c(NA, FALSE, TRUE), n, TRUE) mkX <- if (is.p) function(Dim) .mkX((Dim[1L] * (Dim[1L] + 1L)) %/% 2L) else function(Dim) .mkX(prod(Dim)) ## "Full factorial" design with varying 'Dim', 'uplo', 'diag' slots .Dim <- c(list(c(n, n)), if (is.ge) list(c(n+1L, n), c(n, n+1L))) .a <- c(list(Dim = seq_along(.Dim)), if (!is.ge) list(uplo = c("U", "L")), if ( is.tr) list(diag = c("N", "U")), list(stringsAsFactors = FALSE)) newargs <- do.call(expand.grid, .a) newargs[["Dim"]] <- .Dim[.i <- newargs[["Dim"]]] newargs[["Dimnames"]] <- lapply(.Dim, mkDN)[.i] newargs[["x"]] <- lapply(.Dim, mkX)[.i] if (is.sy) { iD <- Matrix:::indDiag if (extends(Class, "corMatrix")) newargs[["x"]] <- lapply(newargs[["x"]], replace, iD(n), 1) else if (extends(Class, "copMatrix")) newargs[["x"]] <- Map(function(x, upper) replace(x, iD(n, upper, TRUE), 1), newargs[["x"]], newargs[["uplo"]] == "U") } ## Test the matrices generated by each set of arguments to 'new' all(unlist(.mapply(testDenseMatrix, newargs, list(Class = Class)))) } testDenseMatrix <- function(Class, ...) { is.p <- extends(Class, packedMatrix) is.ge <- extends(Class, generalMatrix) is.sy <- !is.ge && extends(Class, symmetricMatrix) is.tr <- !is.ge && !is.sy is.d <- extends(Class, dMatrix) is.l <- !is.d && extends(Class, lMatrix) is.n <- !is.d && !is.l ## This class needs special care because it has an additional 'sd' slot is.cr <- is.sy && (extends(Class, "corMatrix") || extends(Class, "copMatrix")) newargs <- list(Class = Class, ...) if (is.cr) newargs[["sd"]] <- rep.int(1, newargs[["Dim"]][2L]) .M <- M <- do.call(new, newargs) m <- M@Dim[1L] n <- M@Dim[2L] r <- min(m, n) p0 <- (n * (n - 1L)) %/% 2L p1 <- (n * (n + 1L)) %/% 2L .ZERO <- as.vector(0, typeof(M@x)) .ONE <- as.vector(1, typeof(M@x)) .NA <- as.vector(NA, typeof(M@x)) loup <- if (is.ge) NA_character_ else if (M@uplo == "U") "L" else "U" ## For conveniently getting and setting (non)trivial triangles ## of _traditional_ symmetric or triangular matrices if (!is.ge) { if (M@uplo == "U") { tri1 <- U; `tri1<-` <- `U<-` tri0 <- L; `tri0<-` <- `L<-` } else { tri1 <- L; `tri1<-` <- `L<-` tri0 <- U; `tri0<-` <- `U<-` } } .m <- m1 <- m2 <- if (is.p) `tri1<-`(array(.ZERO, dim = M@Dim, dimnames = M@Dimnames), diag = TRUE, M@x) else array(M@x, dim = M@Dim, dimnames = M@Dimnames) diag(.M) <- diag(.m) <- if (is.d) rlnorm(r) else sample(c(.NA, .ZERO, .ONE), r, TRUE) if (is.sy) { tri0(m2, diag = TRUE) <- tri0(t(m2), diag = TRUE) dimnames(m2) <- Matrix:::symDN(M@Dimnames) } if (is.tr && M@diag == "U") { diag(m2) <- .ONE } pM <- if (is.p) M else if (!is.ge) do.call(new, replace(newargs, c("Class", "x"), list(packedClass(Class), tri1(m1, diag = TRUE)))) upM <- if (!is.p) M else do.call(new, replace(newargs, c("Class", "x"), list(unpackedClass(Class), as.vector(m1)))) tM <- do.call(new, replace(newargs, c("Dim", "Dimnames", "x", if (!is.ge) "uplo"), c(list(M@Dim[2:1], M@Dimnames[if (is.sy) 1:2 else 2:1], if (is.p) tri0(t(m1), diag = TRUE) else as.vector(t(m1))), if (!is.ge) list(loup)))) dM <- do.call(new, replace(newargs[names(newargs) != "sd"], c("Class", "x", if (is.tr) "diag"), c(list(...Class(Class), if (is.p) tri1(.m, diag = TRUE) else as.vector(.m)), if (is.tr) list("N")))) stopifnot(is.ge || identical(pack(M), pM), identical(unpack(M), upM), identical(t(M), tM), identical(diag(M, names = FALSE), diag(m2, names = FALSE)), identical(diag(M, names = TRUE), diag(m2, names = TRUE)), identical(.M, dM)) if (is.ge) { if (m == n) { ## Not symmetric and not triangular U(m2) <- if (is.d) rlnorm(p0) else rep_len(c(.NA, .ZERO, .ONE), p0) L(m2) <- if (is.d) -rlnorm(p0) else rep_len(c(.ZERO, .ONE, .NA), p0) M@x <- as.vector(m2) stopifnot(isSymmetric(M, tol = 0, checkDN = FALSE) == (n <= 1L), isTriangular(M, upper = NA) == (n <= 1L), isDiagonal(M) == (n <= 1L)) ## Symmetric but not triangular L(m2) <- L(t(m2)) M@x <- as.vector(m2) stopifnot(isSymmetric(M, tol = 0, checkDN = FALSE), isTriangular(M, upper = NA) == (n <= 1L), isDiagonal(M) == (n <= 1L)) ## Not symmetric but triangular L(m2) <- .ZERO M@x <- as.vector(m2) stopifnot(isSymmetric(M, tol = 0, checkDN = FALSE) == (n <= 1L), identical(isTriangular(M, upper = TRUE), TRUE), identical(isTriangular(M, upper = FALSE), FALSE), identical(isTriangular(M, upper = NA), `attr<-`(TRUE, "kind", "U")), isDiagonal(M) == (n <= 1L)) ## Symmetric and triangular U(m2) <- .ZERO M@x <- as.vector(m2) stopifnot(isSymmetric(M, tol = 0, checkDN = FALSE), identical(isTriangular(M, upper = TRUE), TRUE), identical(isTriangular(M, upper = FALSE), TRUE), identical(isTriangular(M, upper = NA), `attr<-`(TRUE, "kind", "U")), isDiagonal(M)) } else { ## Non-square ... _never_ symmetric, triangular, or diagonal stopifnot(!isSymmetric(M, tol = 0, checkDN = FALSE), !isTriangular(M, upper = NA), !isDiagonal(M)) } } else if (is.sy) { ## Not triangular tri1(m2) <- if (is.d) rlnorm(p0) else rep_len(c(.NA, .ZERO, .ONE), p0) M@x <- if (is.p) tri1(m2, diag = TRUE) else as.vector(m2) stopifnot(isSymmetric(M, tol = 0, checkDN = FALSE), isTriangular(M, upper = NA) == (n <= 1L), isDiagonal(M) == (n <= 1L)) ## Triangular tri1(m2) <- .ZERO M@x <- if (is.p) tri1(m2, diag = TRUE) else as.vector(m2) stopifnot(isSymmetric(M, tol = 0, checkDN = FALSE), identical(isTriangular(M, upper = TRUE), TRUE), identical(isTriangular(M, upper = FALSE), TRUE), identical(isTriangular(M, upper = NA), `attr<-`(TRUE, "kind", M@uplo)), isDiagonal(M)) } else { ## Not symmetric tri1(m2) <- if (is.d) rlnorm(p0) else rep_len(c(.NA, .ZERO, .ONE), p0) M@x <- if (is.p) tri1(m2, diag = TRUE) else as.vector(m2) stopifnot(isSymmetric(M, tol = 0, checkDN = FALSE) == (n <= 1L), identical(isTriangular(M, upper = M@uplo == "U"), TRUE), identical(isTriangular(M, upper = M@uplo != "U"), n <= 1L), identical(isTriangular(M, upper = NA), `attr<-`(TRUE, "kind", M@uplo)), isDiagonal(M) == (n <= 1L)) ## Symmetric tri1(m2) <- .ZERO M@x <- if (is.p) tri1(m2, diag = TRUE) else as.vector(m2) stopifnot(isSymmetric(M, tol = 0, checkDN = FALSE), identical(isTriangular(M, upper = M@uplo == "U"), TRUE), identical(isTriangular(M, upper = M@uplo != "U"), TRUE), identical(isTriangular(M, upper = NA), `attr<-`(TRUE, "kind", M@uplo)), isDiagonal(M)) } TRUE } .dense.subclasses <- c(names(getClassDef("packedMatrix")@subclasses), names(getClassDef("unpackedMatrix")@subclasses)) stopifnot(all(vapply(.dense.subclasses, testDenseClass, NA, n = 4L))) ## diag(, names = TRUE) preserves names ## if head of longer character vector matches shorter character vector n <- 4L m <- array(rnorm(n * (n + 1L)), dim = c(n, n + 1L)) M <- new("dgeMatrix", x = as.vector(m), Dim = dim(m)) rn <- letters[seq_len(n)] cn <- letters[seq_len(n + 1L)] ldn <- list(list(rn, cn), list(rn, replace(cn, 1L, ""))) for (dn in ldn) { stopifnot(identical(diag(`slot<-`(M, "Dimnames", TRUE, dn), names = TRUE), diag(`dimnames<-`(m, dn), names = TRUE))) } cat("Time elapsed:", proc.time(), "\n") # "stats" Matrix/tests/spModel.matrix.R0000644000175100001440000002241114467060443015737 0ustar hornikusers## for R_DEFAULT_PACKAGES=NULL : library(stats) library(utils) library(Matrix) ## This is example(sp....) -- much extended mEQ <- function(x, y, check.attributes = NA, ...) { ## first drop columns from y which are all 0 : if(any(i0 <- colSums(abs(x)) == 0)) { message(gettextf("x had %d zero-columns", sum(i0))) x <- x[, !i0, drop = FALSE] } if(any(i0 <- colSums(abs(y)) == 0)) { message(gettextf("y had %d zero-columns", sum(i0))) y <- y[, !i0, drop = FALSE] } isTRUE(all.equal(x, y, tolerance = 0, check.attributes = check.attributes, ...)) } ##' Is sparse.model.matrix() giving the "same" as dense model.matrix() ? ##' ##' @return logical ##' @param frml formula ##' @param dat data frame ##' @param showFactors ##' @param ... further arguments passed to {sparse.}model.matrix() isEQsparseDense <- function(frml, dat, showFactors = isTRUE(getOption("verboseSparse")), ...) { ## Author: Martin Maechler, Date: 21 Jul 2009 stopifnot(inherits(frml, "formula"), is.data.frame(dat)) if(showFactors) print(attr(terms(frml, data=dat), "factors")) smm <- sparse.model.matrix(frml, dat, ...) mm <- model.matrix(frml, dat, ...) sc <- smm@contrasts mEQ(as(smm, "generalMatrix"), Matrix(mm, sparse=TRUE)) & identical(smm@assign, attr(mm, "assign")) & (if(is.null(mc <- attr(mm, "contrasts"))) length(sc) == 0 else identical(sc, mc)) } ### ------------ all the "datasets" we construct for use ------------- dd <- data.frame(a = gl(3,4), b = gl(4,1,12))# balanced 2-way (dd3 <- cbind(dd, c = gl(2,6), d = gl(3,8))) dd. <- dd3[- c(1, 13:15, 17), ] set.seed(17) dd4 <- cbind(dd, c = gl(2,6), d = gl(8,3)) dd4 <- cbind(dd4, x = round(rnorm(nrow(dd4)), 1)) dd4 <- dd4[- c(1, 13:15, 17), ] ##-> 'd' has unused levels dM <- dd4 dM$X <- outer(10*rpois(nrow(dM), 2), 1:3) dM$Y <- cbind(pmax(0, dM$x - .3), floor(4*rnorm(nrow(dM)))) str(dM)# contains *matrices* options("contrasts") # the default: "contr.treatment" op <- options(sparse.colnames = TRUE) # for convenience stopifnot(identical(## non-sensical, but "should work" (with a warning each): sparse.model.matrix(a~ 1, dd), sparse.model.matrix( ~ 1, dd))) sparse.model.matrix(~ a + b, dd, contrasts.arg = list(a="contr.sum")) sparse.model.matrix(~ a + b, dd, contrasts.arg = list(b="contr.SAS")) xm <- sparse.model.matrix(~ x, dM) # {no warning anymore ...} dxm <- Matrix(model.matrix(~ x, dM), sparse=TRUE) stopifnot(is(xm, "sparseMatrix"), mEQ(as(xm,"generalMatrix"), dxm)) ## Sparse method is equivalent to the traditional one : stopifnot(isEQsparseDense(~ a + b, dd), suppressWarnings(isEQsparseDense(~ x, dM)), isEQsparseDense(~ 0 + a + b, dd), identical(sparse.model.matrix(~ 0 + a + b, dd), sparse.model.matrix(~ -1 + a + b, dd)), isEQsparseDense(~ a + b, dd, contrasts.arg = list(a="contr.sum")), isEQsparseDense(~ a + b, dd, contrasts.arg = list(a="contr.SAS")), ## contrasts as *functions* or contrast *matrices* : isEQsparseDense(~ a + b, dd, contrasts.arg = list( a=contr.sum, b=contr.treatment(4))), isEQsparseDense(~ a + b, dd, contrasts.arg = list( a=contr.SAS(3), b = function(n, contr=TRUE, sparse=FALSE) contr.sum(n=n, contrasts=contr, sparse=sparse)))) sm <- sparse.model.matrix(~a * b, dd, contrasts.arg = list(a=contr.SAS(3, sparse=TRUE))) sm ## FIXME: Move part of this to ../../MatrixModels/tests/ ##stopifnot(all(sm == model.Matrix( ~a * b, dd, contrasts= list(a= contr.SAS(3))))) ## stopifnot(isEQsparseDense(~ a + b + c + d, dd.)) stopifnot(isEQsparseDense(~ a + b:c + c + d, dd.)) ## no intercept -- works too stopifnot(isEQsparseDense(~ -1+ a + b + c + d, dd.)) stopifnot(isEQsparseDense(~ 0 + a + b:c + c + d, dd.)) Sparse.model.matrix <- function(...) { s <- sparse.model.matrix(...) as(s, "generalMatrix")# dropping 'assign',.. slots } ## dim(mm <- Matrix(model.matrix(~ a + b + c + d, dd4), sparse=TRUE)) dim(sm <- Sparse.model.matrix(~ a + b + c + d, dd4)) ## was (19 13), when 'drop.unused.levels' was implicitly TRUE dim(sm. <- Sparse.model.matrix(~ a + b + c + d, dd4, drop.unused.levels=TRUE)) stopifnot(mEQ(sm , mm), ## (both have a zero column) mEQ(sm., mm)) ## << that's ok, since mm has all-0 column ! ## look at this : all(mm[,"d5"] == 0) ## !!!! --- correct: a column of all 0 <--> dropped level! stopifnot(all.equal(sm., mm[, - which("d5" == colnames(mm))], ## indeed ! check.attributes = NA)) ## i.e., sm has just dropped an all zero column --- which it should! stopifnot(isEQsparseDense(~ 1 + sin(x) + b*c + a:x, dd4, showFactors=TRUE)) stopifnot(isEQsparseDense(~ I(a) + b*c + a:x, dd4, showFactors=TRUE)) ## no intercept -- works too stopifnot(isEQsparseDense(~ 0+ I(a) + b*c + a:x, dd4, showFactors=TRUE)) f <- ~ 1 + a + b*c + a*x attr(terms(f, data=dd4), "factors") dim(mm <- Matrix(model.matrix(f, data=dd4), sparse=TRUE)) dim(sm <- Sparse.model.matrix(f, data=dd4)) # == stopifnot(mEQ(sm, mm)) f <- ~ a*X + X*Y + a*c attr(terms(f, data=dM), "factors") dim(mm <- Matrix(model.matrix(f, data=dM), sparse=TRUE)) dim(sm <- Sparse.model.matrix(f, data=dM, verbose=TRUE)) stopifnot(mEQ(sm, mm)) ## high order f <- ~ a:b:X:c:Y mm <- Matrix(model.matrix(f, data=dM), sparse=TRUE) sm <- Sparse.model.matrix(f, data=dM, verbose=2) stopifnot(mEQ(sm, mm)) f <- ~ 1 + a + b*c + a*x + b*d*x + b:c:d attr(terms(f, data=dd4), "factors") dim(mm <- Matrix(model.matrix(f, data=dd4), sparse=TRUE)) ## 19 100 dim(sm <- Sparse.model.matrix(f, data=dd4)) ## (ditto) dim(sm. <- Sparse.model.matrix(f, data=dd4, drop.unused.levels=TRUE)) # 19 88 stopifnot(mEQ(sm, mm), mEQ(sm., mm))# {32, 32; 20 and 32 zero-columns ..} ## now get a bit courageous: ## ## stopifnot(isEQsparseDense(~ 1 + c + a:b:d, dat=dd4)) dim(mm <- Matrix(model.matrix(~ 1 + a + b*c + a:b:c:d, data=dd4), sparse=TRUE)) ## 19 202 dim(sm <- Sparse.model.matrix(~ 1 + a + b*c + a:b:c:d, data=dd4)) dim(sm. <- Sparse.model.matrix(~ 1 + a + b*c + a:b:c:d, data=dd4, drop.unused.levels=TRUE)) stopifnot(mEQ(sm, mm), mEQ(sm., mm))# {173, 173, 149 and 173 zero-columns !} ## stopifnot(isEQsparseDense(~ 1 + a + b*c + a:b:c:d, dat=dd4)) dim(mm <- Matrix(model.matrix(~ 1 + a + b:c + a:b:d, data=dd4), sparse=TRUE)) ## 19 107 dim(sm <- Sparse.model.matrix(~ 1 + a + b:c + a:b:d, data=dd4)) dim(sm. <- Sparse.model.matrix(~ 1 + a + b:c + a:b:d, data=dd4, drop.unused.levels=TRUE)) stopifnot(mEQ(sm, mm), mEQ(sm., mm)) dim(mm <- Matrix(model.matrix(~ a*b*c +c*d, dd4), sparse=TRUE)) ## 19 38 dim(sm <- Sparse.model.matrix(~ a*b*c +c*d, dd4))# (ditto) dim(sm. <- Sparse.model.matrix(~ a*b*c +c*d, dd4, drop.unused.levels=TRUE)) stopifnot(mEQ(sm, mm), mEQ(sm., mm)) f1 <- ~ (a+b+c+d)^2 + (a+b):c:d + a:b:c:d f2 <- ~ (a+b+c+d)^4 - a:b:c - a:b:d mm1 <- Matrix(model.matrix(f1, dd4), sparse=TRUE) dim(mm2 <- Matrix(model.matrix(f2, dd4), sparse=TRUE)) sm1 <- sparse.model.matrix(f1, dd4) dim(sm2 <- sparse.model.matrix(f2, dd4)) s.1 <- sparse.model.matrix(f1, dd4, drop.unused.levels=TRUE) dim(s.2 <- sparse.model.matrix(f2, dd4, drop.unused.levels=TRUE)) stopifnot(identical(mm1,mm2), identical(sm1,sm2), identical(s.1,s.2), mEQ(sm1,mm1), mEQ(s.1,mm1)) str(dd <- data.frame(d = gl(10,6), a = ordered(gl(3,20)))) X. <- sparse.model.matrix(~ a + d, data = dd) ## failed because of contr.poly default in Matrix 0.999375-33 stopifnot(dim(X.) == c(60, 12), nnzero(X.) == 234, isEQsparseDense(~ 0 + d + I(as.numeric(d)^2), dd)) ## I(.) failed (upto 2010-05-07) ## When the *contrasts* are sparse : spC <- as(contrasts(dd$d), "sparseMatrix") ddS <- dd contrasts(ddS$d) <- spC Xs <- sparse.model.matrix(~ a + d, data=ddS) stopifnot(exprs = { inherits(spC, "sparseMatrix") identical(spC, contrasts(ddS[,"d"])) mEQ(X., Xs) }) ## Fixing matrix-Bugs [#6673] by Davor Josipovic df <- data.frame('a' = factor(1:3), 'b' = factor(4:6)) Cid <- lapply(df, contrasts, contrasts=FALSE) CidS <- lapply(df, contrasts, contrasts=FALSE, sparse=TRUE) X2 <- sparse.model.matrix(~ . -1, data = df, contrasts.arg = Cid) X2S <- sparse.model.matrix(~ . -1, data = df, contrasts.arg = CidS) X2 stopifnot(all.equal(X2, X2S, tolerance = 0, check.attributes = NA)) ## X2S was missing the last column ('b6') in Matrix <= 1.x-y ## Fixing (my repr.ex.) of Matrix bug [#6657] by Nick Hanewinckel mkD <- function(n, p2 = 2^ceiling(log2(n)), sd = 10, rf = 4) { stopifnot(p2 >= n, n >= 0, p2 %% 2 == 0) G <- gl(2, p2/2, labels=c("M","F"))[sample.int(p2, n)] data.frame(sex = G, age = round(rf*rnorm(n, mean=32 + 2*as.numeric(G), sd=sd)) / rf) } set.seed(101) D1 <- mkD(47) Xs <- sparse.model.matrix(~ sex* poly(age, 2), data = D1) ## Error in model.spmatrix(..): no slot of name "i" for .. class "dgeMatrix" validObject(Xs) stopifnot(exprs = { identical(c(47L, 6L), dim(Xs)) identical(colnames(Xs)[3:6], c(1:2, outer("sexF", 1:2, paste, sep=":"))) all(Xs == model.matrix(~ sex* poly(age, 2), data = D1)) }) cat('Time elapsed: ', proc.time(),'\n') # for ``statistical reasons'' if(!interactive()) warnings() Matrix/tests/write-read.R0000644000175100001440000000347114444662477015113 0ustar hornikusers## for R_DEFAULT_PACKAGES=NULL : library(utils) library(Matrix) #### Read / Write (sparse) Matrix objects ---------------------- ### Rebuild the 'mm' example matrix, now in KNex data ### This is no longer really important, as we now use ### ../data/KNex.R which creates the S4 object *every time* data(KNex, package = "Matrix") ## recreate 'mm' from list : sNms <- c("Dim", "i","p","x") L <- lapply(sNms, function(SN) slot(KNex$mm, SN)); names(L) <- sNms mm2 <- new(class(KNex$mm)) for (n in sNms) slot(mm2, n) <- L[[n]] stopifnot(validObject(mm2), identical(mm2, KNex$mm)) L$y <- KNex$y ## save(L, file = "/u/maechler/R/Pkgs/Matrix/inst/external/KNex_slots.rda") ## recreate 'mm' from ASCI file : mmT <- as(KNex$mm, "TsparseMatrix") str(mmT) mm3 <- cbind(i = mmT@i, j = mmT@j, x = mmT@x) write.table(mm3, file = "mm-Matrix.tab", row.names=FALSE)# -> ASCII version str(mmr <- read.table("mm-Matrix.tab", header = TRUE)) mmr$i <- as.integer(mmr$i) mmr$j <- as.integer(mmr$j) mmN <- with(mmr, new("dgTMatrix", Dim = c(max(i)+1:1,max(j)+1:1), i = i, j = j, x = x)) stopifnot(identical(mmT, mmN)) # !! ## weaker (and hence TRUE too): stopifnot(all.equal(as(mmN, "matrix"), as(mmT, "matrix"), tolerance=0)) mm <- as(mmN, "CsparseMatrix") stopifnot(all.equal(mm, KNex$mm)) ## save(mm, file = "....../Matrix/data/mm.rda", compress = TRUE) A <- Matrix(c(1,0,3,0,0,5), 10, 10, sparse = TRUE) # warning about [6] vs [10] (fname <- file.path(tempdir(), "kk.mm")) writeMM(A, fname) (B <- readMM(fname)) validObject(B) Bc <- as(B, "CsparseMatrix") stopifnot(identical(A, Bc)) fname <- system.file("external", "wrong.mtx", package = "Matrix") r <- try(readMM(fname)) stopifnot(inherits(r, "try-error"), length(grep("readMM.*row.*1:nr", r)) == 1) ## gave a much less intelligible error message Matrix/tests/group-methods.R0000644000175100001440000005361714523122502015626 0ustar hornikusers### Testing the group methods --- some also happens in ./Class+Meth.R ## for R_DEFAULT_PACKAGES=NULL : library(stats) library(utils) library(Matrix) source(system.file("test-tools.R", package = "Matrix"))# identical3() etc assertErrV <- function(e) tools::assertError(e, verbose=TRUE) cat("doExtras:",doExtras,"\n") options(nwarnings = 1e4) set.seed(2001) mm <- Matrix(rnorm(50 * 7), ncol = 7) xpx <- crossprod(mm)# -> "factors" in mm ! round(xpx, 3) # works via "Math2" y <- rnorm(nrow(mm)) xpy <- crossprod(mm, y) res <- solve(xpx, xpy) signif(res, 4) # 7 x 1 Matrix stopifnot(all(signif(res) == signif(res, 6)), all(round (xpx) == round (xpx, 0))) ## exp(): component wise signif(dd <- (expm(xpx) - exp(xpx)) / 1e34, 3)# 7 x 7 validObject(xpx) validObject(xpy) validObject(dd) ## "Math" also, for log() and [l]gamma() which need special treatment stopifnot(exprs = { identical(exp(res)@x, exp(res@x)) identical(log(abs(res))@x, log(abs((res@x)))) identical(lgamma(res)@x, lgamma(res@x)) }) ## "Arith" / "Ops" M <- Matrix(1:12, 4,3) m <- cbind(4:1) stopifnot(exprs = { identical(M*m, M*c(m)) # M*m failed in Matrix_1.3-3 pre-release: identical(m*M, c(m)*M) ## M*m: Error in eval(....) : object 'x1' not found isValid(M1 <- M[, 1, drop=FALSE], "dgeMatrix") identical(M*M1, M*M1[,1]) # M*M1 failed .. identical(M-M1, M-M1[,1]) identical(M/M1, M/M1[,1]) identical(M1*M, M1[,1]*M) identical(M1-M, M1[,1]-M) identical(M1/M, M1[,1]/M) }) ###--- sparse matrices --------- mC <- Matrix(c(0, 0, 2:0), 3, 5) sm <- sin(mC) stopifnot(class(sm) == class(mC), class(mC) == class(mC^2), dim(sm) == dim(mC), class(0 + 100*mC) == class(mC), all.equal(0.1 * ((0 + 100*mC)/10), mC), all.equal(sqrt(mC ^ 2), mC), identical(mC^2, mC * mC), identical(mC*2, mC + mC) ) x <- Matrix(rbind(0,cbind(0, 0:3,0,0,-1:2,0),0)) x # sparse (x2 <- x + 10*t(x)) stopifnot(is(x2, "sparseMatrix"), identical(x2, t(x*10 + t(x))), identical(x, as((x + 10) - 10, "CsparseMatrix"))) (px <- Matrix(x^x - 1))#-> sparse again stopifnot(px@i == c(3,4,1,4), px@x == c(3,26,-2,3)) ## From: "Florent D." .. Thu, 23 Feb 2012 -- bug report ##---> MM: Make a regression test: tst <- function(n, i = 1) { stopifnot(i >= 1, n >= i) D <- .sparseDiagonal(n) ee <- numeric(n) ; ee[i] <- 1 stopifnot(all(D - ee == diag(n) - ee), all(D * ee == diag(n) * ee), all(ee - D == ee - diag(n)), {C <- (ee / D == ee / diag(n)); all(is.na(C) | C)}, TRUE) } nn <- if(doExtras) 27 else 7 tmp <- sapply(1:nn, tst) # failed in Matrix 1.0-4 i <- sapply(1:nn, function(i) sample(i,1)) tmp <- mapply(tst, n= 1:nn, i= i)# failed too (lsy <- new("lsyMatrix", Dim = c(2L,2L), x=c(TRUE,FALSE,TRUE,TRUE))) nsy <- as(lsy, "nMatrix") (t1 <- new("ltrMatrix", Dim = c(1L,1L), x = TRUE)) (t2 <- new("ltrMatrix", Dim = c(2L,2L), x = rep(TRUE,4))) stopifnot(all(lsy), # failed in Matrix 1.0-4 all(nsy), # dito all(t1), # " ## ok previously (all following): !all(t2), all(sqrt(lsy) == 1)) dsy <- lsy+1 D3 <- Diagonal(x=4:2); L7 <- Diagonal(7) > 0 validObject(xpp <- pack(round(xpx,2))) lsp <- xpp > 0 (dsyU <- .diag2dense(D3, ".", "s")) lsyU <- .diag2dense(Diagonal(5) > 0, ".", "s") str(lsyU) stopifnot({ isValid(dsyU, "dsyMatrix") && dsyU@uplo == "U" isValid(dsyL <- t(dsyU), "dsyMatrix") && dsyL@uplo == "L" isValid(dspU <- pack(dsyU), "dspMatrix") && dspU@uplo == "U" isValid(dspL <- pack(dsyL), "dspMatrix") && dspL@uplo == "L" identical(dspU, t(dspL)) isValid(lsyU, "lsyMatrix") && lsyU@uplo == "U" isValid(lsyL <- t(lsyU), "lsyMatrix") && lsyL@uplo == "L" isValid(lspU <- pack(lsyU), "lspMatrix") && lspU@uplo == "U" isValid(lspL <- pack(lsyL), "lspMatrix") && lspL@uplo == "L" identical(lspL, t(lspU)) ## ## log(x, ) -- was mostly *wrong* upto 2019-10 [Matrix <= 1.2-17] all.equal(log(abs(dsy), 2), log2(abs(dsy))) all.equal(log(abs(dsyL),2), log2(abs(dsyL))) all.equal(log(abs(dspU),2), log2(abs(dspU))) all.equal(log(abs(dspL),2), log2(abs(dspL))) ## These always worked, as {0,1} -> {-Inf,0} independent of 'base': all.equal(log(abs(lsy), 2), log2(abs(lsy))) all.equal(log(abs(lsyL),2), log2(abs(lsyL))) all.equal(log(abs(lspU),2), log2(abs(lspU))) all.equal(log(abs(lspL),2), log2(abs(lspL))) ## all.equal(log(abs(res), 2), log2(abs(res))) all.equal(log(abs(xpy), 2), log2(abs(xpy))) all.equal(log(abs(xpp), 2), log2(abs(xpp))) all.equal(log(abs( D3), 2), log2(abs( D3))) all.equal(log(abs( L7), 2), log2(abs( L7))) }) showProc.time() ## is.finite() -- notably for symmetric packed / uplo="L" with NA : spU <- new("dspMatrix", Dim = c(3L, 3L), x = c(0, NA, 0, NA, NA, 0), uplo = "U") sU <- new("dsyMatrix", Dim = c(3L, 3L), x = c(1, NA, NA, NA, 1, NA, 8, 2, 1), uplo = "U") sL <- t(sU) spL <- t(spU) trU <- triu(spU) trL <- tril(spL) stopifnot(exprs = { spL@uplo == "L" trU@uplo == "U" trL@uplo == "L" identical(trU, triu(spL)) identical(trL, tril(spU)) }) isU <- is.finite(sU) isL <- is.finite(sL) stopifnot(exprs = { identical(isU, t(isL)) all(isU == isL) which(!isU, arr.ind = TRUE) == c(2:1, 1:2) }) isFu <- is.finite(spU) isFl <- is.finite(spL) isFtu <- is.finite(trU) isFtl <- is.finite(trL) stopifnot(exprs = { all(isFu == diag(TRUE, 3)) all(isFu == isFl) # has failed till 2022-06-11 isTriangular(isFtu) isTriangular(isFtl) identical(rep(TRUE, 6), pack(tril(isFtu))@x) identical(rep(TRUE, 6), pack(triu(isFtl))@x) }) showProc.time() set.seed(111) local({ for(i in 1:(if(doExtras) 20 else 5)) { M <- rspMat(n=1000, 200, density = 1/20) v <- rnorm(ncol(M)) m <- as(M,"matrix") stopifnot(all(t(M)/v == t(m)/v)) cat(".") }});cat("\n") ## Now just once, with a large such matrix: local({ n <- 100000; m <- 30000 AA <- rspMat(n, m, density = 1/20000) v <- rnorm(m) st <- system.time({ BB <- t(AA)/v # should happen *fast* stopifnot(dim(BB) == c(m,n), is(BB, "sparseMatrix")) }) str(BB) print(st) if(Sys.info()[["sysname"]] == "Linux") { mips <- try(as.numeric(sub(".*: *", '', grep("bogomips", readLines("/proc/cpuinfo"), ignore.case=TRUE, # e.g. ARM : "BogoMIPS" value=TRUE)[[1]]))) print(mips) if(is.numeric(mips) && all(mips) > 0 && doExtras) # doExtras: valgrind (2023-07-26) gave large 'st[1]' stopifnot(st[1] < 1000/mips)# ensure there was no gross inefficiency } }) ###----- Compare methods ---> logical Matrices ------------ l3 <- upper.tri(matrix(, 3, 3)) (ll3 <- Matrix(l3)) dt3 <- (99* Diagonal(3) + (10 * ll3 + Diagonal(3)))/10 (dsc <- crossprod(ll3)) stopifnot(identical(ll3, t(t(ll3))), identical(dsc, t(t(dsc)))) stopifnotValid(ll3, "ltCMatrix") stopifnotValid(dsc, "dsCMatrix") stopifnotValid(dsc + 3 * Diagonal(nrow(dsc)), "dsCMatrix") stopifnotValid(dt3, "triangularMatrix") # remained triangular stopifnotValid(dt3 > 0, "triangularMatrix")# ditto (lm1 <- dsc >= 1) # now ok (lm2 <- dsc == 1) # now ok nm1 <- as(lm1, "nMatrix") (nm2 <- as(lm2, "nMatrix")) stopifnot(validObject(lm1), validObject(lm2), validObject(nm1), validObject(nm2), identical(dsc, dsc * as(lm1, "dMatrix"))) crossprod(lm1) # lm1: "lsC*" cnm1 <- crossprod(nm1, boolArith = FALSE) stopifnot(is(cnm1, "symmetricMatrix"), ## whereas the %*% is not: Q.eq(cnm1, nm1 %*% nm1)) dn1 <- as(nm1, "denseMatrix") stopifnot(all(dn1 == nm1)) dsc[2,3] <- NA ## now has an NA (and no longer is symmetric) ## ----- and "everything" is different ## also add "non-structural 0": dsc@x[1] <- 0 dsc dsc/ 5 dsc + dsc dsc - dsc dsc + 1 # -> no longer sparse Tsc <- as(dsc, "TsparseMatrix") dsc. <- drop0(dsc) stopifnot(Q.eq(dsc., Matrix((dsc + 1) - 1)), identical(as(-Tsc,"CsparseMatrix"), (-1) * Tsc), identical(-dsc., (-1) * dsc.), identical3(-Diagonal(3), Diagonal(3, -1), (-1) * Diagonal(3)), Q.eq(dsc., Matrix((Tsc + 1) -1)), # ok (exact arithmetic) Q.eq(0 != dsc, dsc != Matrix(0, 3, 3)), Q.eq(0 != dsc, dsc != c(0,0)) # with a warning ("not multiple ..") ) str(lm1 <- dsc >= 1) # now ok (NA in proper place, however: lm1 ## NA used to print as ' ' , now 'N' (lm2 <- dsc == 1)# ditto stopifnot(identical(crossprod(lm1),# "lgC": here works! crossprod(as(lm1, "dMatrix"))), identical(lm2, lm1 & lm2), identical(lm1, lm1 | lm2)) ddsc <- kronecker(Diagonal(7), dsc) isValid(ddv <- rowSums(ddsc, sparseResult=TRUE), "sparseVector") sv <- colSums(kC <- kronecker(mC,kronecker(mC,mC)), sparseResult=TRUE) EQ <- ddv == rowSums(ddsc) na.ddv <- is.na(ddv) sM <- Matrix(pmax(0, round(rnorm(50*15, -1.5), 2)), 50,15) stopifnot(sv == colSums(kC), is.na(as.vector(ddv)) == na.ddv, isValid(sM/(-7:7), "CsparseMatrix"), all(EQ | na.ddv)) ## Subclasses (!) setClass("m.spV", contains = "dsparseVector") (m.ddv <- as(ddv, "m.spV")) stopifnot(all.equal(m.ddv, ddv, check.class = FALSE))# failed setClass("m.dgC", contains = "dgCMatrix") (m.mC <- as(mC, "m.dgC")) stopifnot(all(m.mC == mC)) ## 2-level inheritance (R-forge Matrix bug #6185) ## https://r-forge.r-project.org/tracker/index.php?func=detail&aid=6185&group_id=61&atid=294 setClass("Z", representation(zz = "list")) setClass("C", contains = c("Z", "dgCMatrix")) setClass("C2", contains = "C") setClass("C3", contains = "C2") (cc <- as(mC, "C")) c2 <- as(mC, "C2") c3 <- as(mC, "C3") # as(*, "matrix") of these __fail__ in R < 3.5.0 # before R_check_class_and_super() became better : print(c2) print(c3) ## ==> Error in asMethod(object) : invalid class of object to as_cholmod_sparse stopifnot(identical(cc > 0, mC > 0 -> m.gt.0), ## cc > 0 - gave error in Matrix <= 1.2-11 identical(c2 > 0, m.gt.0), identical(c3 > 0, m.gt.0)) ## Just for print "show": z <- round(rnorm(77), 2) z[sample(77,10)] <- NA (D <- Matrix(z, 7)) # dense z[sample(77,15)] <- 0 (D <- Matrix(z, 7)) # sparse abs(D) >= 0.5 # logical sparse ## For the checks below, remove some and add a few more objects: rm(list= ls(pattern="^.[mMC]?$")) T3 <- Diagonal(3) > 0; stopifnot(T3@diag == "U") # "uni-diagonal" validObject(dtp <- pack(as(dt3, "denseMatrix"))) stopifnot(exprs = { isValid(lsC <- as(lsp, "CsparseMatrix"), "lsCMatrix") ## 0-extent matrices {fixes in Feb.2019}: isValid(L00 <- L7[FALSE,FALSE], "ldiMatrix") isValid(x60 <- x2[,FALSE], "dgCMatrix") identical(t(x60), x06 <- x2[FALSE,]) isValid(x00 <- x06[,FALSE], "dgCMatrix") isValid(sv0 <- as(x06, "sparseVector"), "dsparseVector") }) showProc.time() ### Consider "all" Matrix classes cl <- sapply(ls(), function(.) class(get(.))) Mcl <- cl[vapply(cl, extends, "Matrix", FUN.VALUE=NA) | vapply(cl, extends, "sparseVector", FUN.VALUE=NA)] table(Mcl) ## choose *one* of each class: ## M.objs <- names(Mcl[!duplicated(Mcl)]) ## choose all M.objs <- names(Mcl) # == the ls() from above Mat.objs <- M.objs[vapply(M.objs, function(nm) is(get(nm), "Matrix"), NA)] MatDims <- t(vapply(Mat.objs, function(nm) dim(get(nm)), 0:1)) ## Nice summary info : noquote(cbind(Mcl[Mat.objs], format(MatDims))) ## dtCMatrix, uplo="L" : (CtL <- t(as(Diagonal(x=4:2), "CsparseMatrix"))) m2 <- cbind(c(0, NA, NA), c(0, 0, NA), 0) op <- options(Matrix.verbose = 2) r <- CtL > m2 # failed in Matrix <= 1.4-1, with ## Compare -- "dtCMatrix" > "dtCMatrix" : stopifnot(identical(is.na(m2), unname(as.matrix(is.na(r)))), diag(r), isDiagonal(triu(r))) M <- new("dtCMatrix", i = c(0L, 0:1, 0:2), p = c(0:1, 3L, 6L), x = c(10,1, 10,1, 1,10), Dim = c(3L, 3L), uplo = "U") m2 <- matrix(c(0, NA, NA, 0, 0, NA, 0, 0, 0), 3) r <- M & m2 # failed in Matrix <= 1.4-1 assert.EQ.mat(M | m2 -> ro, as.mat(M)| m2, tol=0) D4 <- Diagonal(x=0+ 4:2) rd <- D4 | m2 # gave invalid class "ltTMatrix" object: uplo='U' must not have sparse entries below the diagonal M2 <- Matrix(m2); T2 <- Matrix:::.diag2T.smart(D4, M2, kind="l") stopifnot(exprs = { all(!r) ## fix in .do.Logic.lsparse() {needed uplo="L"} identical(rd, T2 | M2) identical(rd, as(T2, "CsparseMatrix") | as(M2, "lMatrix")) }) options(op) if(doExtras || interactive()) { # save testing time ### Systematically look at all "Ops" group generics for "all" Matrix classes ### -------------- Main issue: Detect infinite recursion problems mDims <- MatDims %*% (d.sig <- c(1, 1000)) # "dim-signature" to match against m2num <- function(m) { if(is.integer(m)) storage.mode(m) <- "double" ; m } M.knd <- Matrix:::.M.kind cat("Checking all Ops group generics for a set of arguments:\n", "-------------------------------------------------------\n", sep='') op <- options(warn = 2)#, error=recover) for(gr in getGroupMembers("Ops")) { cat(gr,"\n",paste(rep.int("=",nchar(gr)),collapse=""),"\n", sep='') v0 <- if(gr == "Arith") numeric() else logical() for(f in getGroupMembers(gr)) { line <- strrep("-", nchar(f) + 2) cat(sprintf("%s\n%s :\n%s\n", line, dQuote(f), line)) for(nm in M.objs) { if(doExtras) cat(" '",nm,"' ", sep="") M <- get(nm, inherits=FALSE) n.m <- NROW(M) cat("o") for(x in list(TRUE, -3.2, 0L, seq_len(n.m))) { cat(".") validObject(r1 <- do.call(f, list(M,x))) validObject(r2 <- do.call(f, list(x,M))) stopifnot(dim(r1) == dim(M), dim(r2) == dim(M), allow.logical0 = TRUE) } ## M o 0-length === M : validObject(M0. <- do.call(f, list(M, numeric()))) validObject(.M0 <- do.call(f, list(numeric(), M))) if(length(M)) # o <0-length v> == 0-length v stopifnot(identical(M0., v0), identical(.M0, v0)) else if(is(M, "Matrix")) stopifnot(identical(M0., as(M, if(gr == "Arith") "dMatrix" else "lMatrix")), identical(M0., .M0)) else # if(is(M, "sparseVector")) of length 0 stopifnot(identical(M0., v0), identical(.M0, v0)) ## M o x <- numeric(n.m) if(length(x)) x[c(1,length(x))] <- 1:2 sv <- as(x, "sparseVector") cat("s.") validObject(r3 <- do.call(f, list(M, sv))) stopifnot(identical(dim(r3), dim(M))) if(doExtras && is(M, "Matrix")) { ## M o d <- dim(M) ds <- sum(d * d.sig) # signature .. match with all other sigs match. <- ds == mDims # (matches at least itself) cat("\nM o M:") for(oM in Mat.objs[match.]) { M2 <- get(oM) ## R4 := M f M2 validObject(R4 <- do.call(f, list(M, M2))) cat(".") for(M. in list(as.mat(M), M)) { ## two cases .. r4 <- m2num(as.mat(do.call(f, list(M., as.mat(M2))))) cat(",") if(!identical(r4, as.mat(R4))) { cat(sprintf("\n %s %s %s gave not identical r4 & R4:\n", nm, f, oM)); print(r4); print(R4) C1 <- (eq <- R4 == r4) | (N4 <- as.logical((nr4 <- is.na(eq)) & !is.finite(R4))) if(isTRUE(all(C1)) || isTRUE(all.equal(as.mat(R4), r4, tolerance = 1e-14))) cat(sprintf( " --> %s %s %s (ok): only difference is %s (matrix) and %s (Matrix)\n", M.knd(M), f, M.knd(M2) , paste(vapply(unique(r4[N4]), format, ""), collapse="/") , paste(vapply(unique(R4[N4]), format, ""), collapse="/") )) else if(isTRUE(all(eq | (nr4 & Matrix:::is0(R4))))) cat(" --> 'ok': only difference is 'NA' (matrix) and 0 (Matrix)\n") else stop("R4 & r4 differ \"too much\"") } } cat("i") } } } cat("\n") } } if(length(warnings())) print(summary(warnings())) showProc.time() options(op) # reset 'warn' } # doExtras ###---- Now checking 0-length / 0-dim cases <==> to R >= 3.4.0 ! ## arithmetic, logic, and comparison (relop) for 0-extent arrays (m <- Matrix(cbind(a=1[0], b=2[0]))) Lm <- as(m, "lMatrix") ## Im <- as(m, "iMatrix") stopifnot( identical(m, m + 1), identical(m, m + 1[0]), identical(m, m + NULL),## now (2016-09-27) ok identical(m, Lm+ 1L) , identical(m, m+2:3), ## gave error "length does not match dimension" identical(Lm, m & 1), identical(Lm, m | 2:3),## had Warning "In .... : data length exceeds size of matrix" identical(Lm, m & TRUE[0]), identical(Lm, m | FALSE[0]), identical(Lm, m > NULL), identical(Lm, m > 1), identical(Lm, m > .1[0]),## was losing dimnames identical(Lm, m > NULL), ## was not-yet-implemented identical(Lm, m <= 2:3) ## had "wrong" warning ) mm <- m[,c(1:2,2:1,2)] assertErrV(m + mm) # ... non-conformable arrays assertErrV(m | mm) # ... non-conformable arrays ## Matrix: ok ; R : ok, in R >= 3.4.0 assertErrV(m == mm) ## in R <= 3.3.x, relop returned logical(0) and m + 2:3 returned numeric(0) ## ## arithmetic, logic, and comparison (relop) -- inconsistency for 1x1 array o = 2>: ## FIXME: desired errors are _not_ thrown for ddiMatrix (when doDiag=TRUE) (m1 <- Matrix(1, 1L, 1L, dimnames = list("Ro", "col"), doDiag = FALSE)) ## col ## Ro 1 ## Before Sep.2016, here, Matrix was the *CONTRARY* to R: assertErrV(m1 + 1:2)## M.: "correct" ERROR // R 3.4.0: "deprecated" warning (--> will be error) assertErrV(m1 & 1:2)## gave 1 x 1 [TRUE] -- now Error, as R assertErrV(m1 <= 1:2)## gave 1 x 1 [TRUE] -- now Error, as R assertErrV(m1 & 1:2)## gave 1 x 1 [TRUE] -- now Error, as R assertErrV(m1 <= 1:2)## gave 1 x 1 [TRUE] -- now Error, as R ## ## arrays combined with NULL works now stopifnot(identical(Matrix(3,1,1) + NULL, 3[0])) stopifnot(identical(Matrix(3,1,1) > NULL, T[0])) stopifnot(identical(Matrix(3,1,1) & NULL, T[0])) ## in R >= 3.4.0: logical(0) # with *no* warning and that's correct! if(doExtras || interactive()) { # save testing time mStop <- function(...) stop(..., call. = FALSE) ## cat("Checking the Math (+ Math2) group generics for a set of arguments:\n", "------------ ==== ------------------------------------------------\n", sep='') doStop <- function() mStop("**Math: ", f,"(<",class(M),">) of 'wrong' class ", dQuote(class(R))) mM <- getGroupMembers("Math") mM2 <- getGroupMembers("Math2") (mVec <- grep("^cum", mM, value=TRUE)) ## <<- are special: return *vector* for matrix input for(f in c(mM, mM2)) { cat(sprintf("%-9s :\n %-7s\n", paste0('"',f,'"'), paste(rep("-", nchar(f)), collapse=""))) givesVec <- f %in% mVec fn <- get(f) if(f %in% mM2) { fn0 <- fn ; fn <- function(x) fn0(x, digits=3) } for(nm in M.objs) { M <- get(nm, inherits=FALSE) is.m <- length(dim(M)) == 2 cat(" '",nm,"':", if(is.m) "m" else "v", sep="") R <- fn(M) r <- fn(m <- if(is.m) as.mat(M) else as.vector(M)) stopifnot(identical(dim(R), dim(r))) if(givesVec || !is.m) { assert.EQ(R, r, check.class = FALSE) } else { ## (almost always:) matrix result assert.EQ.mat(R, r, check.class = FALSE) ## check preservation of properties, notably super class if(prod(dim(M)) > 1 && is(M, "diagonalMatrix" ) && isDiagonal(R) && !is(R, "diagonalMatrix" )) doStop() if(prod(dim(M)) > 1 && is(M, "triangularMatrix") && (iT <- isTriangular(R)) && attr(iT, "kind") == M@uplo && !is(R, "triangularMatrix")) doStop() } } cat("\n") } showProc.time() ## cat("Checking the Summary group generics for a set of arguments:\n", "------------ ======= ------------------------------------------------\n", sep='') for(f in getGroupMembers("Summary")) { cat(sprintf("%-9s :\n %-7s\n", paste0('"',f,'"'), paste(rep("-", nchar(f)), collapse=""))) givesVec <- f %in% mVec fn <- get(f) if(f %in% mM2) { fn0 <- fn ; fn <- function(x) fn0(x, digits=3) } for(nm in M.objs) { M <- get(nm, inherits=FALSE) is.m <- length(dim(M)) == 2 cat(" '",nm,"':", if(is.m) "m" else "v", sep="") R <- fn(M) r <- fn(m <- if(is.m) as.mat(M) else as.vector(M)) stopifnot(identical(dim(R), dim(r))) assert.EQ(R, r) } cat("\n") if(length(warnings())) print(summary(warnings())) } } # doExtras ## (x) behaved incorrectly in Matrix <= 1.4-1 ## for unit diagonal 'x' when f(0) == 0 and f(1) != 1 Dn <- list(c("a", "b"), c("A", "B")) udi <- new("ddiMatrix", Dim = c(2L, 2L), Dimnames = Dn, diag = "U") utC <- new("dtCMatrix", Dim = c(2L, 2L), Dimnames = Dn, diag = "U", p = integer(3L)) utr <- new("dtrMatrix", Dim = c(2L, 2L), Dimnames = Dn, diag = "U", x = double(4L)) sinu <- `dimnames<-`(sin(diag(2L)), Dn) for(u in list(udi, utC, utr)) stopifnot(identical(as(sin(u), "matrix"), sinu)) ## Originally in ../man/all-methods.Rd : M <- Matrix(1:12 +0, 3,4) all(M >= 1) # TRUE any(M < 0 ) # FALSE MN <- M; MN[2,3] <- NA; MN all(MN >= 0) # NA any(MN < 0) # NA any(MN < 0, na.rm = TRUE) # -> FALSE sM <- as(MN, "sparseMatrix") stopifnot(all(M >= 1), !any(M < 0), all.equal((sM >= 1), as(MN >= 1, "sparseMatrix")), ## MN: any(MN < 2), !all(MN < 5), is.na(all(MN >= 0)), is.na(any(MN < 0)), all(MN >= 0, na.rm=TRUE), !any(MN < 0, na.rm=TRUE), ## same for sM : any(sM < 2), !all(sM < 5), is.na(all(sM >= 0)), is.na(any(sM < 0)), all(sM >= 0, na.rm=TRUE), !any(sM < 0, na.rm=TRUE) ) ## prod() does not perform multiplies in row/column order : x4 <- new("dspMatrix", Dim = c(4L, 4L), x = c(171, 53, 79, 205, 100, 285, 98, 15, 99, 84)) p4 <- prod( x4) p4. <- prod(as(x4, "generalMatrix")) p4.. <- prod(as(x4, "matrix")) stopifnot(all.equal(p4, p4. , tolerance = 1e-15), all.equal(p4., p4.., tolerance = 1e-15)) all.equal(p4, p4. , tolerance = 0) all.equal(p4., p4.., tolerance = 0) .Machine[["sizeof.longdouble"]] cat('Time elapsed: ', proc.time(),'\n') # for ``statistical reasons'' �����������������������������������������������������������������������������������������������������������������Matrix/tests/bind.Rout.save�������������������������������������������������������������������������0000644�0001751�0000144�00000045017�14470702707�015441� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ R version 4.3.1 Patched (2023-08-08 r84910) -- "Beagle Scouts" Copyright (C) 2023 The R Foundation for Statistical Computing Platform: aarch64-apple-darwin22.5.0 (64-bit) R is free software and comes with ABSOLUTELY NO WARRANTY. You are welcome to redistribute it under certain conditions. Type 'license()' or 'licence()' for distribution details. R is a collaborative project with many contributors. Type 'contributors()' for more information and 'citation()' on how to cite R or R packages in publications. Type 'demo()' for some demos, 'help()' for on-line help, or 'help.start()' for an HTML browser interface to help. Type 'q()' to quit R. > #### Testing cbind() & rbind() -- based on cbind2() & rbind2() > ## (where using 'cBind()' and 'rBind()' in Matrix) > > ## for R_DEFAULT_PACKAGES=NULL : > library(utils) > > library(Matrix) > > source(system.file("test-tools.R", package = "Matrix"))# identical3() etc Loading required package: tools > > ### --- Dense Matrices --- > > m1 <- m2 <- m <- matrix(1:12, 3,4) > dimnames(m2) <- list(LETTERS[1:3], + letters[1:4]) > dimnames(m1) <- list(NULL,letters[1:4]) > M <- Matrix(m) > M1 <- Matrix(m1) > M2 <- Matrix(m2) > > stopifnot( + identical3(cbind ( M, 10*M), + show(cbind2( M, 10*M)), + Matrix(cbind ( m, 10*m))) + , + identical3(cbind (M1, 100+M1), + show(cbind2(M1, 100+M1)), + Matrix(cbind (m1, 100+m1))) + , + identical3(cbind (M1, 10*M2), + show(cbind2(M1, 10*M2)), + Matrix(cbind (m1, 10*m2))) + , + identical3(cbind (M2, M1+M2), + show(cbind2(M2, M1+M2)), + Matrix(cbind (m2, m1+m2))) + , + identical(colnames(show(cbind(M1, MM = -1))), + c(colnames(M1), "MM")) + , + identical3(rbind ( M, 10*M), + show(rbind2( M, 10*M)), + Matrix(rbind ( m, 10*m))) + , + identical3(rbind (M2, M1+M2), + show(rbind2(M2, M1+M2)), + Matrix(rbind (m2, m1+m2))) + , + Qidentical(show (rbind(R1 = 10:11, M1)), + Matrix(rbind(R1 = 10:11, m1)), strictClass=FALSE) + , TRUE) 3 x 8 Matrix of class "dgeMatrix" [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [1,] 1 4 7 10 10 40 70 100 [2,] 2 5 8 11 20 50 80 110 [3,] 3 6 9 12 30 60 90 120 3 x 8 Matrix of class "dgeMatrix" a b c d a b c d [1,] 1 4 7 10 101 104 107 110 [2,] 2 5 8 11 102 105 108 111 [3,] 3 6 9 12 103 106 109 112 3 x 8 Matrix of class "dgeMatrix" a b c d a b c d A 1 4 7 10 10 40 70 100 B 2 5 8 11 20 50 80 110 C 3 6 9 12 30 60 90 120 3 x 8 Matrix of class "dgeMatrix" a b c d a b c d A 1 4 7 10 2 8 14 20 B 2 5 8 11 4 10 16 22 C 3 6 9 12 6 12 18 24 3 x 5 Matrix of class "dgeMatrix" a b c d MM [1,] 1 4 7 10 -1 [2,] 2 5 8 11 -1 [3,] 3 6 9 12 -1 6 x 4 Matrix of class "dgeMatrix" [,1] [,2] [,3] [,4] [1,] 1 4 7 10 [2,] 2 5 8 11 [3,] 3 6 9 12 [4,] 10 40 70 100 [5,] 20 50 80 110 [6,] 30 60 90 120 6 x 4 Matrix of class "dgeMatrix" a b c d A 1 4 7 10 B 2 5 8 11 C 3 6 9 12 2 8 14 20 4 10 16 22 6 12 18 24 4 x 4 Matrix of class "dgeMatrix" a b c d R1 10 11 10 11 1 4 7 10 2 5 8 11 3 6 9 12 > > identical.or.eq <- function(x,y, tol=0, ...) { + if(identical(x,y, ...)) + TRUE + else if(isTRUE(aeq <- all.equal(x,y, tolerance = tol))) + structure(TRUE, comment = "not identical") + else aeq + } > identicalShow <- function(x,y, ...) + if(!isTRUE(id <- identical.or.eq(x, y, ...))) cat(id,"\n") > > ## Checking deparse.level { <==> example at end of ?cbind }: > checkRN <- function(dd, B = rbind) { + FN <- function(deparse.level) + rownames(B(1:4, c=2,"a+"=10, dd, deparse.level=deparse.level)) + rn <- c("1:4", "c", "a+", "dd", "") + isMatr <- (length(dim(dd)) == 2) + id <- if(isMatr) 5 else 4 + identicalShow(rn[c(5,2:3, 5)], FN(deparse.level= 0)) # middle two names + identicalShow(rn[c(5,2:3,id)], FN(deparse.level= 1)) # last shown if vector + identicalShow(rn[c(1,2:3,id)], FN(deparse.level= 2)) # first shown; (last if vec.) + } > checkRN(10) # <==> ?cbind's ex > checkRN(1:4) > checkRN( rbind(c(0:1,0,0))) > checkRN(Matrix(rbind(c(0:1,0,0)))) ## in R <= 3.4.1, from methods:::rbind bug : > ## Modes: character, NULL Lengths: 4, 0 target is character, current is NULL > checkRN(10 , rbind) > checkRN(1:4, rbind) > checkRN( rbind(c(0:1,0,0)), rbind) > checkRN(Matrix(rbind(c(0:1,0,0))), rbind) > > cbind(0, Matrix(0+0:1, 1,2), 3:2)# FIXME? should warn - as with matrix() 1 x 4 Matrix of class "dgeMatrix" [,1] [,2] [,3] [,4] [1,] 0 0 1 3 Warning message: In cbind.Matrix(x, y, deparse.level = 0L) : number of rows of result is not a multiple of vector length > as(rbind(0, Matrix(0+0:1, 1,2), 3:2), + "sparseMatrix") 3 x 2 sparse Matrix of class "dgCMatrix" [1,] . . [2,] . 1 [3,] 3 2 > cbind(M2, 10*M2[nrow(M2):1 ,])# keeps the rownames from the first 3 x 8 Matrix of class "dgeMatrix" a b c d a b c d A 1 4 7 10 30 60 90 120 B 2 5 8 11 20 50 80 110 C 3 6 9 12 10 40 70 100 > > (im <- cbind(I = 100, M)) 3 x 5 Matrix of class "dgeMatrix" I [1,] 100 1 4 7 10 [2,] 100 2 5 8 11 [3,] 100 3 6 9 12 > str(im) Formal class 'dgeMatrix' [package "Matrix"] with 4 slots ..@ Dim : int [1:2] 3 5 ..@ Dimnames:List of 2 .. ..$ : NULL .. ..$ : chr [1:5] "I" "" "" "" ... ..@ x : num [1:15] 100 100 100 1 2 3 4 5 6 7 ... ..@ factors : list() > (mi <- cbind(M2, I = 1000)) 3 x 5 Matrix of class "dgeMatrix" a b c d I A 1 4 7 10 1000 B 2 5 8 11 1000 C 3 6 9 12 1000 > str(mi) Formal class 'dgeMatrix' [package "Matrix"] with 4 slots ..@ Dim : int [1:2] 3 5 ..@ Dimnames:List of 2 .. ..$ : chr [1:3] "A" "B" "C" .. ..$ : chr [1:5] "a" "b" "c" "d" ... ..@ x : num [1:15] 1 2 3 4 5 6 7 8 9 10 ... ..@ factors : list() > (m1m <- cbind(M,I=100,M2)) 3 x 9 Matrix of class "dgeMatrix" I a b c d A 1 4 7 10 100 1 4 7 10 B 2 5 8 11 100 2 5 8 11 C 3 6 9 12 100 3 6 9 12 > showProc.time() Time (user system elapsed): 0.051 0.006 0.056 > > ## lgeMatrix -- rbind2() had bug (in C code): > is.lge <- function(M) isValid(M, "lgeMatrix") > stopifnot(exprs = { + is.lge(rbind(M2 > 0, M2 < 0)) # had Error in rbind2(): + ## REAL() can only be applied to a 'numeric', not a 'logical' + is.lge(rbind(M2 < 0, M2 > 0)) # ditto + is.lge(rbind(Matrix(1:6 %% 3 != 0, 2,3), FALSE)) + is.lge(L <- rbind(Matrix(TRUE, 2,3), TRUE)) + all(L) + is.lge(rbind(Matrix(TRUE, 2,3), FALSE)) + }) > > ### --- Diagonal / Sparse - had bugs > > D4 <- Diagonal(4) > (D4T <- as(D4, "TsparseMatrix")) 4 x 4 sparse Matrix of class "dtTMatrix" (unitriangular) [1,] I . . . [2,] . I . . [3,] . . I . [4,] . . . I > D4C <- as(D4T, "CsparseMatrix") > c1 <- Matrix(0+0:3, 4, sparse=TRUE) ; r1 <- t(c1); r1 1 x 4 sparse Matrix of class "dgCMatrix" [1,] . 1 2 3 > > d4 <- rbind(Diagonal(4), 0:3) > m4 <- cbind(Diagonal(x=-1:2), 0:3) > c4. <- cbind(Diagonal(4), c1) > c.4 <- cbind(c1, Diagonal(4)) > r4. <- rbind(Diagonal(4), r1) > r.4 <- rbind(r1, Diagonal(4)) > assert.EQ.mat(d4, rbind(diag(4), 0:3)) > assert.EQ.mat(m4, cbind(diag(-1:2), 0:3)) > stopifnot(identical(Matrix(cbind(diag(3),0)), cbind2(Diagonal(3),0)), + is(d4, "sparseMatrix"), is(m4, "sparseMatrix"), + identical(.tCRT(d4), cbind(Diagonal(4), 0:3)), + identical(.tCRT(m4), rbind(Diagonal(x=-1:2), 0:3))) > showProc.time() Time (user system elapsed): 0.019 0 0.02 > > ### --- Sparse Matrices --- > > identical4(cbind(diag(4), diag(4)), + cbind(D4C, D4C), + cbind(D4T, D4C), + cbind(D4C, D4T)) [1] FALSE > nr <- 4 > nc <- 6 > m. <- matrix(rep_len(c(0, 2:-1), nr * nc), nr, nc) > M <- Matrix(m.) > (mC <- as(M, "CsparseMatrix")) 4 x 6 sparse Matrix of class "dgCMatrix" [1,] . -1 . 1 2 . [2,] 2 . -1 . 1 2 [3,] 1 2 . -1 . 1 [4,] . 1 2 . -1 . > (mT <- as(M, "TsparseMatrix")) 4 x 6 sparse Matrix of class "dgTMatrix" [1,] . -1 . 1 2 . [2,] 2 . -1 . 1 2 [3,] 1 2 . -1 . 1 [4,] . 1 2 . -1 . > stopifnot(identical(mT, as(mC, "TsparseMatrix")), + identical(mC, as(mT, "CsparseMatrix"))) > > for(v in list(0, 2, 1:0)) + for(fnam in c("cbind", "rbind")) { + cat(fnam,"(m, v=", deparse(v),"), class(m) :") + FUN <- get(fnam) + for(m in list(M, mC, mT)) { + cat("", class(m),"") + assert.EQ.mat(FUN(v, m), FUN(v, m.)) ; cat(",") + assert.EQ.mat(FUN(m, v), FUN(m., v)) ; cat(".") + } + cat("\n") + } cbind (m, v= 0 ), class(m) : dgeMatrix ,. dgCMatrix ,. dgTMatrix ,. rbind (m, v= 0 ), class(m) : dgeMatrix ,. dgCMatrix ,. dgTMatrix ,. cbind (m, v= 2 ), class(m) : dgeMatrix ,. dgCMatrix ,. dgTMatrix ,. rbind (m, v= 2 ), class(m) : dgeMatrix ,. dgCMatrix ,. dgTMatrix ,. cbind (m, v= 1:0 ), class(m) : dgeMatrix ,. dgCMatrix ,. dgTMatrix ,. rbind (m, v= 1:0 ), class(m) : dgeMatrix ,. dgCMatrix ,. dgTMatrix ,. > showProc.time() Time (user system elapsed): 0.018 0.001 0.019 > > cbind(0, mC); cbind(mC, 0) 4 x 7 sparse Matrix of class "dgCMatrix" [1,] . . -1 . 1 2 . [2,] . 2 . -1 . 1 2 [3,] . 1 2 . -1 . 1 [4,] . . 1 2 . -1 . 4 x 7 sparse Matrix of class "dgCMatrix" [1,] . -1 . 1 2 . . [2,] 2 . -1 . 1 2 . [3,] 1 2 . -1 . 1 . [4,] . 1 2 . -1 . . > cbind(0, mT); cbind(mT, 2) 4 x 7 sparse Matrix of class "dgTMatrix" [1,] . . -1 . 1 2 . [2,] . 2 . -1 . 1 2 [3,] . 1 2 . -1 . 1 [4,] . . 1 2 . -1 . 4 x 7 sparse Matrix of class "dgTMatrix" [1,] . -1 . 1 2 . 2 [2,] 2 . -1 . 1 2 2 [3,] 1 2 . -1 . 1 2 [4,] . 1 2 . -1 . 2 > cbind(diag(nr), mT) 4 x 10 sparse Matrix of class "dgTMatrix" [1,] 1 . . . . -1 . 1 2 . [2,] . 1 . . 2 . -1 . 1 2 [3,] . . 1 . 1 2 . -1 . 1 [4,] . . . 1 . 1 2 . -1 . > stopifnot(identical(t(cbind(diag(nr), mT)), + rbind(diag(nr), t(mT)))) > (cc <- cbind(mC, 0,7,0, diag(nr), 0)) 4 x 14 sparse Matrix of class "dgCMatrix" [1,] . -1 . 1 2 . . 7 . 1 . . . . [2,] 2 . -1 . 1 2 . 7 . . 1 . . . [3,] 1 2 . -1 . 1 . 7 . . . 1 . . [4,] . 1 2 . -1 . . 7 . . . . 1 . > stopifnot(identical3(cc, + as(cbind(mT, 0, 7, 0, diag(nr), 0), "CsparseMatrix"), + as(cbind( M, 0, 7, 0, diag(nr), 0), "CsparseMatrix"))) > > cbind(mC, 1, 100*mC, 0, 0:2) 4 x 15 sparse Matrix of class "dgCMatrix" [1,] . -1 . 1 2 . 1 . -100 . 100 200 . . . [2,] 2 . -1 . 1 2 1 200 . -100 . 100 200 . 1 [3,] 1 2 . -1 . 1 1 100 200 . -100 . 100 . 2 [4,] . 1 2 . -1 . 1 . 100 200 . -100 . . . > cbind(mT, 1, 0, mT+10*mT, 0, 0:2) 4 x 16 sparse Matrix of class "dgCMatrix" [1,] . -1 . 1 2 . 1 . . -11 . 11 22 . . . [2,] 2 . -1 . 1 2 1 . 22 . -11 . 11 22 . 1 [3,] 1 2 . -1 . 1 1 . 11 22 . -11 . 11 . 2 [4,] . 1 2 . -1 . 1 . . 11 22 . -11 . . . > one <- 1 > zero <- 0 > dimnames(mC) <- dimnames(mT) <- list(LETTERS[1:4], letters[1:6]) > op <- options(sparse.colnames = TRUE)# show colnames in print : > cbind(mC, one, 100*mC, zero, 0:2) 4 x 15 sparse Matrix of class "dgCMatrix" a b c d e f one a b c d e f zero A . -1 . 1 2 . 1 . -100 . 100 200 . . . B 2 . -1 . 1 2 1 200 . -100 . 100 200 . 1 C 1 2 . -1 . 1 1 100 200 . -100 . 100 . 2 D . 1 2 . -1 . 1 . 100 200 . -100 . . . > cbind(mC, one, 100*mC, zero, 0:2, deparse.level=0)# no "zero", "one" 4 x 15 sparse Matrix of class "dgCMatrix" a b c d e f a b c d e f A . -1 . 1 2 . 1 . -100 . 100 200 . . . B 2 . -1 . 1 2 1 200 . -100 . 100 200 . 1 C 1 2 . -1 . 1 1 100 200 . -100 . 100 . 2 D . 1 2 . -1 . 1 . 100 200 . -100 . . . > cbind(mC, one, 100*mC, zero, 0:2, deparse.level=2)# even "0:2" 4 x 15 sparse Matrix of class "dgCMatrix" a b c d e f one a b c d e f zero 0:2 A . -1 . 1 2 . 1 . -100 . 100 200 . . . B 2 . -1 . 1 2 1 200 . -100 . 100 200 . 1 C 1 2 . -1 . 1 1 100 200 . -100 . 100 . 2 D . 1 2 . -1 . 1 . 100 200 . -100 . . . > cbind(mT, one, zero, mT+10*mT, zero, 0:2) 4 x 16 sparse Matrix of class "dgCMatrix" a b c d e f one zero a b c d e f zero A . -1 . 1 2 . 1 . . -11 . 11 22 . . . B 2 . -1 . 1 2 1 . 22 . -11 . 11 22 . 1 C 1 2 . -1 . 1 1 . 11 22 . -11 . 11 . 2 D . 1 2 . -1 . 1 . . 11 22 . -11 . . . > > > ## logical (sparse) - should remain logical : > L5 <- Diagonal(n = 5, x = TRUE) > v5 <- rep(x = c(FALSE,TRUE), length.out = ncol(L5)) > stopifnot(is(show(rbind(L5,v5)), "lsparseMatrix"), + is(show(cbind(v5,L5)), "lsparseMatrix"), + is(rbind(L5, 2* v5), "dsparseMatrix"), + is(cbind(2* v5, L5), "dsparseMatrix")) 6 x 5 sparse Matrix of class "lgRMatrix" [,1] [,2] [,3] [,4] [,5] | . . . . . | . . . . . | . . . . . | . . . . . | v5 . | . | . 5 x 6 sparse Matrix of class "lgCMatrix" v5 [1,] . | . . . . [2,] | . | . . . [3,] . . . | . . [4,] | . . . | . [5,] . . . . . | > > ## print() / show() of non-structural zeros: > (m <- Matrix(c(0, 0, 2:0), 3, 5)) 3 x 5 sparse Matrix of class "dgCMatrix" [,1] [,2] [,3] [,4] [,5] [1,] . 1 . . 2 [2,] . . 2 . 1 [3,] 2 . 1 . . > (m2 <- cbind(m,m)) 3 x 10 sparse Matrix of class "dgCMatrix" [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [1,] . 1 . . 2 . 1 . . 2 [2,] . . 2 . 1 . . 2 . 1 [3,] 2 . 1 . . 2 . 1 . . > (m4 <- rbind(m2,m2)) 6 x 10 sparse Matrix of class "dgCMatrix" [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [1,] . 1 . . 2 . 1 . . 2 [2,] . . 2 . 1 . . 2 . 1 [3,] 2 . 1 . . 2 . 1 . . [4,] . 1 . . 2 . 1 . . 2 [5,] . . 2 . 1 . . 2 . 1 [6,] 2 . 1 . . 2 . 1 . . > diag(m4) [1] 0 0 1 0 1 2 > for(i in 1:6) { + m4[i, i ] <- i + m4[i,i+1] <- 0 + } > m4 ## now show some non-structural zeros: 6 x 10 sparse Matrix of class "dgCMatrix" [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [1,] 1 . . . 2 . 1 . . 2 [2,] . 2 . . 1 . . 2 . 1 [3,] 2 . 3 . . 2 . 1 . . [4,] . 1 . 4 . . 1 . . 2 [5,] . . 2 . 5 . . 2 . 1 [6,] 2 . 1 . . 6 . 1 . . > > ## Mixture of dense and sparse/diagonal -- used to fail, even in 1.0-0 > D5 <- Diagonal(x = 10*(1:5)) > (D5.1 <- cbind2(D5, 1)) 5 x 6 sparse Matrix of class "dgCMatrix" [,1] [,2] [,3] [,4] [,5] [,6] [1,] 10 . . . . 1 [2,] . 20 . . . 1 [3,] . . 30 . . 1 [4,] . . . 40 . 1 [5,] . . . . 50 1 > ## "FIXME" in newer versions of R, do not need Matrix() here: > s42 <- Matrix(z42 <- cbind2(rep(0:1,4), rep(1:0,4)), + sparse=TRUE) > (C86 <- rbind(1, 0, D5.1, 0)) 8 x 6 sparse Matrix of class "dgCMatrix" [,1] [,2] [,3] [,4] [,5] [,6] [1,] 1 1 1 1 1 1 [2,] . . . . . . [3,] 10 . . . . 1 [4,] . 20 . . . 1 [5,] . . 30 . . 1 [6,] . . . 40 . 1 [7,] . . . . 50 1 [8,] . . . . . . > stopifnotValid(D5.1, "dgCMatrix") > stopifnotValid(print(rbind2(Matrix(1:10, 2,5), D5)), "dgRMatrix") 7 x 5 sparse Matrix of class "dgRMatrix" [,1] [,2] [,3] [,4] [,5] [1,] 1 3 5 7 9 [2,] 2 4 6 8 10 [3,] 10 . . . . [4,] . 20 . . . [5,] . . 30 . . [6,] . . . 40 . [7,] . . . . 50 > stopifnotValid(print(cbind2(Matrix(10:1, 5,2), D5.1)), "dgCMatrix") 5 x 8 sparse Matrix of class "dgCMatrix" [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [1,] 10 5 10 . . . . 1 [2,] 9 4 . 20 . . . 1 [3,] 8 3 . . 30 . . 1 [4,] 7 2 . . . 40 . 1 [5,] 6 1 . . . . 50 1 > stopifnotValid(zz <- cbind2(z42, C86), "dgCMatrix") > stopifnot(identical(zz, cbind2(s42, C86))) > > ## Using "nMatrix" > (m1 <- sparseMatrix(1:3, 1:3)) # ngCMatrix 3 x 3 sparse Matrix of class "ngCMatrix" [,1] [,2] [,3] [1,] | . . [2,] . | . [3,] . . | > m2 <- sparseMatrix(1:3, 1:3, x = 1:3) > stopifnotValid(c12 <- cbind(m1,m2), "dgCMatrix") # was "ngC.." because of cholmod_horzcat ! > stopifnotValid(c21 <- cbind(m2,m1), "dgCMatrix") # ditto > stopifnotValid(r12 <- rbind(m1,m2), "dgCMatrix") # was "ngC.." because of cholmod_vertcat ! > stopifnotValid(r21 <- rbind(m2,m1), "dgCMatrix") # ditto > d1 <- as(m1, "denseMatrix") > d2 <- as(m2, "denseMatrix") > stopifnotValid(cbind2(d2,d1), "dgeMatrix") > stopifnotValid(cbind2(d1,d2), "dgeMatrix")## gave an error in Matrix 1.1-5 > stopifnotValid(rbind2(d2,d1), "dgeMatrix") > stopifnotValid(rbind2(d1,d2), "dgeMatrix")## gave an error in Matrix 1.1-5 > > ## rbind2() / cbind2() mixing sparse/dense: used to "fail", > ## ------------------- then (in 'devel', ~ 2015-03): completely wrong > S <- .sparseDiagonal(2) > s <- diag(2) > S9 <- rbind(S,0,0,S,0,NaN,0,0,0,2)## r/cbind2() failed to determine 'sparse' in Matrix <= 1.2-2 > s9 <- rbind(s,0,0,s,0,NaN,0,0,0,2) > assert.EQ.mat(S9, s9) > D <- Matrix(1:6, 3,2); d <- as(D, "matrix") > T9 <- t(S9); t9 <- t(s9); T <- t(D); t <- t(d) > stopifnot(identical(rbind (s9,d), rbind2(s9,d)), + identical(rbind2(D,S9), t(cbind2(T,T9))), + identical(rbind2(S9,D), t(cbind2(T9,T)))) > assert.EQ.mat(rbind2(S9,D), rbind2(s9,d)) > assert.EQ.mat(rbind2(D,S9), rbind2(d,s9)) > ## now with cbind2() -- no problem! > stopifnot(identical(cbind (t9,t), cbind2(t9,t))) > assert.EQ.mat(cbind2(T9,T), cbind2(t9,t)) > assert.EQ.mat(cbind2(T,T9), cbind2(t,t9)) > > > > options(op) > showProc.time() Time (user system elapsed): 0.06 0.003 0.063 > > proc.time() user system elapsed 0.609 0.039 0.646 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/tests/base-matrix-fun.R����������������������������������������������������������������������0000644�0001751�0000144�00000003223�14444662477�016045� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#### Thanks to the manipulation in base namespace, see ../R/zzz.R , #### all the functions (in 'base' or namespaces that import it) #### starting with something like #### " x <- as.matrix(x) " or " X <- as.array(X) " #### will work for 'Matrix'-matrices ## for R_DEFAULT_PACKAGES=NULL : library(stats) library(utils) library(Matrix) data(KNex, package = "Matrix") mm <- KNex$mm str(m1 <- mm[1:500, 1:200]) m11 <- m1[1:100, 1:20] ## These now work thanks to using our as.matrix(): str(D1 <- dist(m11)) str(rs <- apply(m1, 1, sum)) stopifnot(identical(kappa(Matrix(2:5, 2)), kappa(matrix(2:5, 2)))) ## used to seg.fault, PR#7984, ## because qr() was calling the wrong as.matrix() ## also matplot() or pairs(). ## a regression test for as.matrix.dist(.) still working data(USJudgeRatings, package = "datasets") stopifnot(c(43, 43) == dim(as.matrix(d <- dist(USJudgeRatings)))) m <- Matrix(0:5, 3, 2) (m2 <- Matrix(diag(c(3,1)))) (m3 <- crossprod(t(m))) # <- that's an S4 method; nothing "base" str( svd(m) ) str( lapply(eigen(m3), zapsmall)) ### outer() used to work thanks to as.array() -- up to R 2.2.1 ## no longer, because the definition of outer has changed -- FIXME? ## Whould work by providing an as.vector(.) method ## *and* is.array(.) \-> TRUE which may be too strong ##--> For %o%: "need" to make outer(.,.) an S3 generic ## *and* provide Matrix S3 methods ## stopifnot(identical(outer(m, m2), ## outer(as(m,"matrix"), as(m2,"matrix"))), ## identical(outer(m3, m2), ## outer(as(m3,"matrix"), as(m2,"matrix")))) cat('Time elapsed: ', proc.time(),'\n') # for ``statistical reasons'' �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/�����������������������������������������������������������������������������������������0000755�0001751�0000144�00000000000�14576344041�012333� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/cholmod-common.h�������������������������������������������������������������������������0000644�0001751�0000144�00000002520�14575137654�015427� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_CHOLMOD_COMMON_H #define MATRIX_CHOLMOD_COMMON_H #include "cholmod-etc.h" cholmod_factor * sexp_as_cholmod_factor (cholmod_factor *, SEXP); cholmod_sparse * sexp_as_cholmod_sparse (cholmod_sparse *, SEXP, Rboolean, Rboolean); cholmod_triplet * sexp_as_cholmod_triplet(cholmod_triplet *, SEXP, Rboolean); cholmod_dense * sexp_as_cholmod_dense (cholmod_dense *, SEXP); cholmod_dense *numeric_as_cholmod_dense (cholmod_dense *, double *, int, int); SEXP cholmod_factor_as_sexp (cholmod_factor *, int); SEXP cholmod_sparse_as_sexp (cholmod_sparse *, int, int, int, const char *, SEXP); SEXP cholmod_triplet_as_sexp(cholmod_triplet *, int, int, int, const char *, SEXP); SEXP cholmod_dense_as_sexp (cholmod_dense *, int); double cholmod_factor_ldetA (cholmod_factor *); cholmod_factor *cholmod_factor_update(cholmod_factor *, cholmod_sparse *, double); int R_cholmod_start (cholmod_common *); int R_cholmod_finish(cholmod_common *); SEXP R_cholmod_common_envini(SEXP); void R_cholmod_common_envset(void); void R_cholmod_common_envget(void); #endif /* MATRIX_CHOLMOD_COMMON_H */ ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/expm.h�����������������������������������������������������������������������������������0000644�0001751�0000144�00000000175�14574651213�013460� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_EXPM_H #define MATRIX_EXPM_H #include SEXP dgeMatrix_expm(SEXP); #endif /* MATRIX_EXPM_H */ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/Matrix-win.def���������������������������������������������������������������������������0000644�0001751�0000144�00000000052�14510016544�015037� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������LIBRARY Matrix.dll EXPORTS R_init_Matrix ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/attrib.c���������������������������������������������������������������������������������0000644�0001751�0000144�00000012624�14512321002�013747� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Mdefines.h" #include "attrib.h" /* .... Dimnames .................................................... */ int DimNames_is_trivial(SEXP dn) { return isNull(VECTOR_ELT(dn, 0)) && isNull(VECTOR_ELT(dn, 1)) && isNull(getAttrib(dn, R_NamesSymbol)); } int DimNames_is_symmetric(SEXP dn) { SEXP rn, cn, ndn; const char *nrn, *ncn; int n; return !((!isNull(rn = VECTOR_ELT(dn, 0)) && !isNull(cn = VECTOR_ELT(dn, 1)) && rn != cn && ((n = LENGTH(rn)) != LENGTH(cn) || !equal_character_vectors(rn, cn, n))) || ((!isNull(ndn = getAttrib(dn, R_NamesSymbol)) && *(nrn = CHAR(STRING_ELT(ndn, 0))) != '\0' && *(ncn = CHAR(STRING_ELT(ndn, 1))) != '\0' && strcmp(nrn, ncn) != 0))); } SEXP R_DimNames_is_symmetric(SEXP dn) { return ScalarLogical(DimNames_is_symmetric(dn)); } void symDN(SEXP dest, SEXP src, int J /* -1|0|1 */) { SEXP s; if (J < 0) { if (!isNull(s = VECTOR_ELT(src, J = 1)) || !isNull(s = VECTOR_ELT(src, J = 0))) { SET_VECTOR_ELT(dest, 0, s); SET_VECTOR_ELT(dest, 1, s); } else { J = 1; } } else { if (!isNull(s = VECTOR_ELT(src, J))) { SET_VECTOR_ELT(dest, 0, s); SET_VECTOR_ELT(dest, 1, s); } } PROTECT(s = getAttrib(src, R_NamesSymbol)); if (!isNull(s)) { SEXP destnms = PROTECT(allocVector(STRSXP, 2)); if (*CHAR(s = STRING_ELT(s, J)) != '\0') { SET_STRING_ELT(destnms, 0, s); SET_STRING_ELT(destnms, 1, s); } setAttrib(dest, R_NamesSymbol, destnms); UNPROTECT(1); } UNPROTECT(1); return; } void revDN(SEXP dest, SEXP src) { SEXP s; if (!isNull(s = VECTOR_ELT(src, 0))) SET_VECTOR_ELT(dest, 1, s); if (!isNull(s = VECTOR_ELT(src, 1))) SET_VECTOR_ELT(dest, 0, s); PROTECT(s = getAttrib(src, R_NamesSymbol)); if (!isNull(s)) { SEXP srcnms = s, destnms = PROTECT(allocVector(STRSXP, 2)); if (*CHAR(s = STRING_ELT(srcnms, 0)) != '\0') SET_STRING_ELT(destnms, 1, s); if (*CHAR(s = STRING_ELT(srcnms, 1)) != '\0') SET_STRING_ELT(destnms, 0, s); setAttrib(dest, R_NamesSymbol, destnms); UNPROTECT(1); } UNPROTECT(1); return; } SEXP R_symDN(SEXP dn) { if (DimNames_is_trivial(dn)) return dn; SEXP newdn = PROTECT(allocVector(VECSXP, 2)); symDN(newdn, dn, -1); UNPROTECT(1); return newdn; } SEXP R_revDN(SEXP dn) { if (DimNames_is_trivial(dn)) return dn; SEXP newdn = PROTECT(allocVector(VECSXP, 2)); revDN(newdn, dn); UNPROTECT(1); return newdn; } SEXP get_symmetrized_DimNames(SEXP obj, int J) { SEXP dn = PROTECT(GET_SLOT(obj, Matrix_DimNamesSym)); if (DimNames_is_trivial(dn)) { UNPROTECT(1); return dn; } SEXP newdn = PROTECT(allocVector(VECSXP, 2)); symDN(newdn, dn, J); UNPROTECT(2); return newdn; } SEXP get_reversed_DimNames(SEXP obj) { SEXP dn = PROTECT(GET_SLOT(obj, Matrix_DimNamesSym)); if (DimNames_is_trivial(dn)) { UNPROTECT(1); return dn; } SEXP newdn = PROTECT(allocVector(VECSXP, 2)); revDN(newdn, dn); UNPROTECT(2); return newdn; } void set_symmetrized_DimNames(SEXP obj, SEXP dn, int J) { if (!DimNames_is_trivial(dn)) { SEXP newdn = PROTECT(allocVector(VECSXP, 2)); symDN(newdn, dn, J); SET_SLOT(obj, Matrix_DimNamesSym, newdn); UNPROTECT(1); } return; } void set_reversed_DimNames(SEXP obj, SEXP dn) { if (!DimNames_is_trivial(dn)) { SEXP newdn = PROTECT(allocVector(VECSXP, 2)); revDN(newdn, dn); SET_SLOT(obj, Matrix_DimNamesSym, newdn); UNPROTECT(1); } return; } /* .... factors ..................................................... */ static int strmatch(const char *x, SEXP valid) { int i, n = LENGTH(valid); for (i = 0; i < n; ++i) if (strcmp(x, CHAR(STRING_ELT(valid, i))) == 0) return i; return -1; } static SEXP append_to_named_list(SEXP x, const char *nm, SEXP val) { PROTECT(val); R_xlen_t n = XLENGTH(x); SEXP y = PROTECT(allocVector(VECSXP, n + 1)), ny = PROTECT(allocVector(STRSXP, n + 1)), nval = PROTECT(mkChar(nm)); if (n > 0) { SEXP nx = PROTECT(getAttrib(x, R_NamesSymbol)); R_xlen_t i; for (i = 0; i < n; ++i) { SET_VECTOR_ELT( y, i, VECTOR_ELT( x, i)); SET_STRING_ELT(ny, i, STRING_ELT(nx, i)); } UNPROTECT(1); } SET_VECTOR_ELT( y, n, val); SET_STRING_ELT(ny, n, nval); setAttrib(y, R_NamesSymbol, ny); UNPROTECT(4); return y; } SEXP get_factor(SEXP obj, const char *nm) { SEXP factors = PROTECT(GET_SLOT(obj, Matrix_factorsSym)), val = R_NilValue; if (LENGTH(factors) > 0) { SEXP valid = PROTECT(getAttrib(factors, R_NamesSymbol)); int i = strmatch(nm, valid); if (i >= 0) val = VECTOR_ELT(factors, i); UNPROTECT(1); } UNPROTECT(1); return val; } void set_factor(SEXP obj, const char *nm, SEXP val) { PROTECT(val); SEXP factors; PROTECT_INDEX pid; PROTECT_WITH_INDEX(factors = GET_SLOT(obj, Matrix_factorsSym), &pid); if (LENGTH(factors) > 0) { SEXP valid = PROTECT(getAttrib(factors, R_NamesSymbol)); int i = strmatch(nm, valid); UNPROTECT(1); if (i >= 0) { SET_VECTOR_ELT(factors, i, val); UNPROTECT(2); return; } } REPROTECT(factors = append_to_named_list(factors, nm, val), pid); SET_SLOT(obj, Matrix_factorsSym, factors); UNPROTECT(2); return; } SEXP R_set_factor(SEXP obj, SEXP nm, SEXP val, SEXP warn) { if (TYPEOF(nm) != STRSXP || LENGTH(nm) < 1 || (nm = STRING_ELT(nm, 0)) == NA_STRING) error(_("invalid factor name")); else if (TYPEOF(getAttrib(obj, Matrix_factorsSym)) == VECSXP) set_factor(obj, CHAR(nm), val); else if (asLogical(warn) != 0) warning(_("attempt to set factor on %s without '%s' slot"), "Matrix", "factors"); return val; } ������������������������������������������������������������������������������������������������������������Matrix/src/subscript.c������������������������������������������������������������������������������0000644�0001751�0000144�00000145213�14574054152�014522� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Mdefines.h" #include "subscript.h" #define F_X( _X_) (_X_) #define F_ND(_X_) ((_X_) ? 1 : 0) #define F_NS(_X_) 1 #define AR21_UP(i, j, m) i + j + ( j * ( j - 1)) / 2 #define AR21_LO(i, j, m) i + (j * m + j * (m - j - 1)) / 2 static SEXP unpackedMatrix_subscript_1ary(SEXP x, SEXP w, const char *cl) { #define SUB1_START(_SEXPTYPE_) \ SEXPTYPE typ = _SEXPTYPE_; \ R_xlen_t l = 0, len = XLENGTH(w); \ SEXP res = allocVector(typ, len); \ if (len == 0) \ return res; \ PROTECT(res); \ \ SEXP dim = PROTECT(GET_SLOT(x, Matrix_DimSym)); \ int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; \ Matrix_int_fast64_t mn64 = (Matrix_int_fast64_t) m * n; \ UNPROTECT(1); #define SUB1_START_EXTRA(_SEXPTYPE_) \ SUB1_START(_SEXPTYPE_); \ \ int ge = cl[1] == 'g', tr = cl[1] == 't', upper = 1, nonunit = 1; \ if (!ge) { \ SEXP uplo = PROTECT(GET_SLOT(x, Matrix_uploSym)); \ upper = *CHAR(STRING_ELT(uplo, 0)) == 'U'; \ UNPROTECT(1); \ if (tr) { \ SEXP diag = PROTECT(GET_SLOT(x, Matrix_diagSym)); \ nonunit = *CHAR(STRING_ELT(diag, 0)) == 'N'; \ UNPROTECT(1); \ } \ } SUB1_START_EXTRA(kindToType(cl[0])); #define SUB1_CASES(_SUB1_N_, _SUB1_X_, _F_N_, _F_X_) \ do { \ switch (cl[0]) { \ case 'n': \ _SUB1_N_(int, LOGICAL, NA_LOGICAL, 0, 1, _F_N_); \ break; \ case 'l': \ _SUB1_X_(int, LOGICAL, NA_LOGICAL, 0, 1, _F_X_); \ break; \ case 'i': \ _SUB1_X_(int, INTEGER, NA_INTEGER, 0, 1, _F_X_); \ break; \ case 'd': \ _SUB1_X_(double, REAL, NA_REAL, 0.0, 1.0, _F_X_); \ break; \ case 'z': \ _SUB1_X_(Rcomplex, COMPLEX, \ Matrix_zna, Matrix_zzero, Matrix_zone, _F_X_); \ break; \ default: \ break; \ } \ } while (0) #define SUB1_N(_CTYPE_, _PTR_, _NA_, _ZERO_, _ONE_, _F_) \ do { \ _CTYPE_ *pres = _PTR_(res); \ if (TYPEOF(w) == INTSXP) { \ int *pw = INTEGER(w); \ if (mn64 >= INT_MAX) { \ /* index is never out of bounds */ \ SUB1_LOOP((pw[l] == NA_INTEGER), \ _NA_, _ZERO_, _ONE_, _F_, Matrix_int_fast64_t); \ } else { \ int mn = m * n; \ SUB1_LOOP((pw[l] == NA_INTEGER || pw[l] > mn), \ _NA_, _ZERO_, _ONE_, _F_, int); \ } \ } else { \ double *pw = REAL(w); \ if (mn64 >= 0x1.0p+53) \ /* m*n may not be exactly representable as double */ \ /* but it does not exceed INT_MAX * INT_MAX */ \ SUB1_LOOP((ISNAN(pw[l]) || pw[l] >= 0x1.0p+62 || \ (Matrix_int_fast64_t) pw[l] > mn64), \ _NA_, _ZERO_, _ONE_, _F_, Matrix_int_fast64_t); \ else { \ double mn1a = (double) m * n + 1.0; \ SUB1_LOOP((ISNAN(pw[l]) || pw[l] >= mn1a), \ _NA_, _ZERO_, _ONE_, _F_, Matrix_int_fast64_t); \ } \ } \ } while (0) #define SUB1_X(_CTYPE_, _PTR_, _NA_, _ZERO_, _ONE_, _F_) \ do { \ PROTECT(x = GET_SLOT(x, Matrix_xSym)); \ _CTYPE_ *px = _PTR_(x); \ SUB1_N(_CTYPE_, _PTR_, _NA_, _ZERO_, _ONE_, _F_); \ UNPROTECT(1); \ } while (0) #define SUB1_LOOP(_NA_SUBSCRIPT_, _NA_, _ZERO_, _ONE_, _F_, _INT_) \ do { \ _INT_ index, i_, j_; \ for (l = 0; l < len; ++l) { \ if (_NA_SUBSCRIPT_) \ pres[l] = _NA_; \ else { \ index = (_INT_) pw[l] - 1; \ if (ge) \ pres[l] = _F_(px[index]); \ else { \ i_ = index % m; \ j_ = index / m; \ if (tr) { \ if ((upper) ? i_ > j_ : i_ < j_) \ pres[l] = _ZERO_; \ else if (!nonunit && i_ == j_) \ pres[l] = _ONE_; \ else \ pres[l] = _F_(px[index]); \ } else { \ if ((upper) ? i_ > j_ : i_ < j_) \ pres[l] = _F_(px[i_ * m + j_]); \ else \ pres[l] = _F_(px[index]); \ } \ } \ } \ } \ } while (0) SUB1_CASES(SUB1_X, SUB1_X, F_ND, F_X); #undef SUB1_LOOP UNPROTECT(1); return res; } static SEXP packedMatrix_subscript_1ary(SEXP x, SEXP w, const char *cl) { SUB1_START_EXTRA(kindToType(cl[0])); #define SUB1_LOOP(_NA_SUBSCRIPT_, _NA_, _ZERO_, _ONE_, _F_, _INT_) \ do { \ _INT_ index, i_, j_; \ for (l = 0; l < len; ++l) { \ if (_NA_SUBSCRIPT_) \ pres[l] = _NA_; \ else { \ index = (_INT_) pw[l] - 1; \ i_ = index % m; \ j_ = index / m; \ if (tr) { \ if (upper) { \ if (i_ > j_) \ pres[l] = _ZERO_; \ else if (!nonunit && i_ == j_) \ pres[l] = _ONE_; \ else \ pres[l] = _F_(px[AR21_UP(i_, j_, m)]); \ } else { \ if (i_ < j_) \ pres[l] = _ZERO_; \ else if (!nonunit && i_ == j_) \ pres[l] = _ONE_; \ else \ pres[l] = _F_(px[AR21_LO(i_, j_, m)]); \ } \ } else { \ if (upper) { \ if (i_ > j_) \ pres[l] = _F_(px[AR21_UP(j_, i_, m)]); \ else \ pres[l] = _F_(px[AR21_UP(i_, j_, m)]); \ } else { \ if (i_ < j_) \ pres[l] = _F_(px[AR21_LO(j_, i_, m)]); \ else \ pres[l] = _F_(px[AR21_LO(i_, j_, m)]); \ } \ } \ } \ } \ } while (0) SUB1_CASES(SUB1_X, SUB1_X, F_ND, F_X); #undef SUB1_LOOP UNPROTECT(1); return res; } static SEXP CsparseMatrix_subscript_1ary(SEXP x, SEXP w, const char *cl) { SUB1_START(kindToType(cl[0])); SEXP p = PROTECT(GET_SLOT(x, Matrix_pSym)), i = PROTECT(GET_SLOT(x, Matrix_iSym)); int *pp = INTEGER(p), *pi = INTEGER(i), i_, j_, j, k = 0, kend; #define SUB1_LOOP(_NA_SUBSCRIPT_, _NA_, _ZERO_, _ONE_, _F_, _INT_) \ do { \ _INT_ index; \ if (_NA_SUBSCRIPT_) \ j = -1; \ else { \ index = (_INT_) pw[l] - 1; \ i_ = (int) (index % m); \ j_ = j = (int) (index / m); \ } \ while (j >= 0) { \ k = pp[j]; \ kend = pp[j + 1]; \ while (k < kend && j_ == j) { \ if (pi[k] < i_) \ ++k; \ else { \ if (pi[k] > i_) \ pres[l] = _ZERO_; \ else \ pres[l] = _F_(px[k]); \ ++l; \ if (l == len || _NA_SUBSCRIPT_) \ j_ = -1; \ else { \ index = (_INT_) pw[l] - 1; \ i_ = (int) (index % m); \ j_ = (int) (index / m); \ } \ } \ } \ while (j_ == j) { \ pres[l] = _ZERO_; \ ++l; \ if (l == len || _NA_SUBSCRIPT_) \ j_ = -1; \ else { \ index = (_INT_) pw[l] - 1; \ i_ = (int) (index % m); \ j_ = (int) (index / m); \ } \ } \ j = j_; \ } \ while (l < len) { \ pres[l] = _NA_; \ ++l; \ } \ } while (0) SUB1_CASES(SUB1_N, SUB1_X, F_NS, F_X); #undef SUB1_LOOP UNPROTECT(3); return res; } static SEXP RsparseMatrix_subscript_1ary(SEXP x, SEXP w, const char *cl) { SUB1_START(kindToType(cl[0])); SEXP p = PROTECT(GET_SLOT(x, Matrix_pSym)), j = PROTECT(GET_SLOT(x, Matrix_jSym)); int *pp = INTEGER(p), *pj = INTEGER(j), i, i_, j_, k = 0, kend; #define SUB1_LOOP(_NA_SUBSCRIPT_, _NA_, _ZERO_, _ONE_, _F_, _INT_) \ do { \ _INT_ index; \ if (_NA_SUBSCRIPT_) \ i = -1; \ else { \ index = (_INT_) pw[l] - 1; \ i_ = i = (int) (index % m); \ j_ = (int) (index / m); \ } \ while (i >= 0) { \ k = pp[i]; \ kend = pp[i + 1]; \ while (k < kend && i_ == i) { \ if (pj[k] < j_) \ ++k; \ else { \ if (pj[k] > j_) \ pres[l] = _ZERO_; \ else \ pres[l] = _F_(px[k]); \ ++l; \ if (l == len || _NA_SUBSCRIPT_) \ i_ = -1; \ else { \ index = (_INT_) pw[l] - 1; \ i_ = (int) (index % m); \ j_ = (int) (index / m); \ } \ } \ } \ while (i_ == i) { \ pres[l] = _ZERO_; \ ++l; \ if (l == len || _NA_SUBSCRIPT_) \ i_ = -1; \ else { \ index = (_INT_) pw[l] - 1; \ i_ = (int) (index % m); \ j_ = (int) (index / m); \ } \ } \ i = i_; \ } \ while (l < len) { \ pres[l] = _NA_; \ ++l; \ } \ } while (0) SUB1_CASES(SUB1_N, SUB1_X, F_NS, F_X); #undef SUB1_LOOP UNPROTECT(3); return res; } static SEXP diagonalMatrix_subscript_1ary(SEXP x, SEXP w, const char *cl) { SUB1_START(kindToType(cl[0])); SEXP diag = PROTECT(GET_SLOT(x, Matrix_diagSym)); int nonunit = *CHAR(STRING_ELT(diag, 0)) == 'N'; UNPROTECT(1); Matrix_int_fast64_t index, n1a = (Matrix_int_fast64_t) n + 1; #define SUB1_LOOP(_NA_SUBSCRIPT_, _NA_, _ZERO_, _ONE_, _F_, _INT_) \ do { \ for (l = 0; l < len; ++l) { \ if (_NA_SUBSCRIPT_) \ pres[l] = _NA_; \ else if ((index = (Matrix_int_fast64_t) pw[l] - 1) % n1a != 0) \ pres[l] = _ZERO_; \ else if (!nonunit) \ pres[l] = _ONE_; \ else \ pres[l] = _F_(px[index / n1a]); \ } \ } while (0) SUB1_CASES(SUB1_X, SUB1_X, F_ND, F_X); #undef SUB1_LOOP UNPROTECT(1); return res; } static SEXP indMatrix_subscript_1ary(SEXP x, SEXP w) { SUB1_START(LGLSXP); SEXP perm = PROTECT(GET_SLOT(x, Matrix_permSym)); int *pperm = INTEGER(perm), i_, j_; SEXP margin = PROTECT(GET_SLOT(x, Matrix_marginSym)); int mg = INTEGER(margin)[0] - 1; UNPROTECT(1); #define SUB1_LOOP(_NA_SUBSCRIPT_, _NA_, _ZERO_, _ONE_, _F_, _INT_) \ do { \ _INT_ index; \ for (l = 0; l < len; ++l) { \ if (_NA_SUBSCRIPT_) \ pres[l] = _NA_; \ else { \ index = (_INT_) pw[l] - 1; \ i_ = (int) (index % m); \ j_ = (int) (index / m); \ if (!mg) \ pres[l] = j_ == pperm[i_] - 1; \ else \ pres[l] = i_ == pperm[j_] - 1; \ } \ } \ } while (0) SUB1_N(int, LOGICAL, NA_LOGICAL, 0, 1, ); #undef SUB1_LOOP #undef SUB1_N #undef SUB1_START #undef SUB1_START_EXTRA UNPROTECT(2); return res; } /* x[i] with 'i' of type "integer" or "double" {i >= 1 or NA} */ SEXP R_subscript_1ary(SEXP x, SEXP i) { static const char *valid[] = { VALID_NONVIRTUAL_MATRIX, "" }; int ivalid = R_check_class_etc(x, valid); if (ivalid < 0) ERROR_INVALID_CLASS(x, __func__); ivalid += VALID_NONVIRTUAL_SHIFT(ivalid, 1); const char *cl = valid[ivalid]; validObject(x, cl); switch (cl[2]) { case 'e': case 'y': case 'r': return unpackedMatrix_subscript_1ary(x, i, cl); case 'p': return packedMatrix_subscript_1ary(x, i, cl); /* NB: for [CRT], the caller must preprocess 'x' and 'i'; symmetric and unit triangular 'x' are not handled specially, and it is assumed for speed that 'i' is sorted by row [R] or column [CT] with NA last */ case 'C': return CsparseMatrix_subscript_1ary(x, i, cl); case 'R': return RsparseMatrix_subscript_1ary(x, i, cl); case 'T': { char cl_[] = "..CMatrix"; cl_[0] = cl[0]; cl_[1] = cl[1]; /* defined in ./coerce.c : */ SEXP sparse_as_Csparse(SEXP, const char *); x = sparse_as_Csparse(x, cl); PROTECT(x); x = CsparseMatrix_subscript_1ary(x, i, cl_); UNPROTECT(1); return x; } case 'i': return diagonalMatrix_subscript_1ary(x, i, cl); default: return indMatrix_subscript_1ary(x, i); } } static SEXP unpackedMatrix_subscript_1ary_mat(SEXP x, SEXP w, const char *cl) { #define SUB1_START(_SEXPTYPE_) \ SEXPTYPE typ = _SEXPTYPE_; \ int l = 0, len = (int) (XLENGTH(w) / 2); \ SEXP res = allocVector(typ, len); \ if (len == 0) \ return res; \ PROTECT(res); \ int *pw0 = INTEGER(w), *pw1 = pw0 + len; #define SUB1_START_EXTRA(_SEXPTYPE_) \ SUB1_START(_SEXPTYPE_); \ \ SEXP dim = PROTECT(GET_SLOT(x, Matrix_DimSym)); \ int m = INTEGER(dim)[0]; \ UNPROTECT(1); \ \ int ge = cl[1] == 'g', tr = cl[1] == 't', upper = 1, nonunit = 1; \ if (!ge) { \ SEXP uplo = PROTECT(GET_SLOT(x, Matrix_uploSym)); \ upper = *CHAR(STRING_ELT(uplo, 0)) == 'U'; \ UNPROTECT(1); \ if (tr) { \ SEXP diag = PROTECT(GET_SLOT(x, Matrix_diagSym)); \ nonunit = *CHAR(STRING_ELT(diag, 0)) == 'N'; \ UNPROTECT(1); \ } \ } SUB1_START_EXTRA(kindToType(cl[0])); Matrix_int_fast64_t i_, j_; #define SUB1_N(_CTYPE_, _PTR_, _NA_, _ZERO_, _ONE_, _F_) \ do { \ _CTYPE_ *pres = _PTR_(res); \ SUB1_LOOP((pw0[l] == NA_INTEGER || pw1[l] == NA_INTEGER), \ _NA_, _ZERO_, _ONE_, _F_); \ } while (0) #define SUB1_LOOP(_NA_SUBSCRIPT_, _NA_, _ZERO_, _ONE_, _F_) \ do { \ for (l = 0; l < len; ++l) { \ if (_NA_SUBSCRIPT_) \ pres[l] = _NA_; \ else { \ i_ = pw0[l] - 1; \ j_ = pw1[l] - 1; \ if (ge) \ pres[l] = _F_(px[j_ * m + i_]); \ else if (tr) { \ if ((upper) ? i_ > j_ : i_ < j_) \ pres[l] = _ZERO_; \ else if (!nonunit && i_ == j_) \ pres[l] = _ONE_; \ else \ pres[l] = _F_(px[j_ * m + i_]); \ } else { \ if ((upper) ? i_ > j_ : i_ < j_) \ pres[l] = _F_(px[i_ * m + j_]); \ else \ pres[l] = _F_(px[j_ * m + i_]); \ } \ } \ } \ } while (0) SUB1_CASES(SUB1_X, SUB1_X, F_ND, F_X); #undef SUB1_LOOP UNPROTECT(1); return res; } static SEXP packedMatrix_subscript_1ary_mat(SEXP x, SEXP w, const char *cl) { SUB1_START_EXTRA(kindToType(cl[0])); Matrix_int_fast64_t i_, j_; #define SUB1_LOOP(_NA_SUBSCRIPT_, _NA_, _ZERO_, _ONE_, _F_) \ do { \ for (l = 0; l < len; ++l) { \ if (_NA_SUBSCRIPT_) \ pres[l] = _NA_; \ else { \ i_ = pw0[l] - 1; \ j_ = pw1[l] - 1; \ if (tr) { \ if (upper) { \ if (i_ > j_) \ pres[l] = _ZERO_; \ else if (!nonunit && i_ == j_) \ pres[l] = _ONE_; \ else \ pres[l] = _F_(px[AR21_UP(i_, j_, m)]); \ } else { \ if (i_ < j_) \ pres[l] = _ZERO_; \ else if (!nonunit && i_ == j_) \ pres[l] = _ONE_; \ else \ pres[l] = _F_(px[AR21_LO(i_, j_, m)]); \ } \ } else { \ if (upper) { \ if (i_ > j_) \ pres[l] = _F_(px[AR21_UP(j_, i_, m)]); \ else \ pres[l] = _F_(px[AR21_UP(i_, j_, m)]); \ } else { \ if (i_ < j_) \ pres[l] = _F_(px[AR21_LO(j_, i_, m)]); \ else \ pres[l] = _F_(px[AR21_LO(i_, j_, m)]); \ } \ } \ } \ } \ } while (0) SUB1_CASES(SUB1_X, SUB1_X, F_ND, F_X); #undef SUB1_LOOP UNPROTECT(1); return res; } static SEXP CsparseMatrix_subscript_1ary_mat(SEXP x, SEXP w, const char *cl) { SUB1_START(kindToType(cl[0])); SEXP p = PROTECT(GET_SLOT(x, Matrix_pSym)), i = PROTECT(GET_SLOT(x, Matrix_iSym)); int *pp = INTEGER(p), *pi = INTEGER(i), i_, j_, j, k = 0, kend; #define SUB1_LOOP(_NA_SUBSCRIPT_, _NA_, _ZERO_, _ONE_, _F_) \ do { \ if (_NA_SUBSCRIPT_) \ j = -1; \ else { \ i_ = pw0[l] - 1; \ j_ = j = pw1[l] - 1; \ } \ while (j >= 0) { \ k = pp[j]; \ kend = pp[j + 1]; \ while (k < kend && j_ == j) { \ if (pi[k] < i_) \ ++k; \ else { \ if (pi[k] > i_) \ pres[l] = _ZERO_; \ else \ pres[l] = _F_(px[k]); \ ++l; \ if (l == len || _NA_SUBSCRIPT_) \ j_ = -1; \ else { \ i_ = pw0[l] - 1; \ j_ = pw1[l] - 1; \ } \ } \ } \ while (j_ == j) { \ pres[l] = _ZERO_; \ ++l; \ if (l == len || _NA_SUBSCRIPT_) \ j_ = -1; \ else { \ i_ = pw0[l] - 1; \ j_ = pw1[l] - 1; \ } \ } \ j = j_; \ } \ while (l < len) { \ pres[l] = _NA_; \ ++l; \ } \ } while (0) SUB1_CASES(SUB1_N, SUB1_X, F_NS, F_X); #undef SUB1_LOOP UNPROTECT(3); return res; } static SEXP RsparseMatrix_subscript_1ary_mat(SEXP x, SEXP w, const char *cl) { SUB1_START(kindToType(cl[0])); SEXP p = PROTECT(GET_SLOT(x, Matrix_pSym)), j = PROTECT(GET_SLOT(x, Matrix_jSym)); int *pp = INTEGER(p), *pj = INTEGER(j), i, i_, j_, k = 0, kend; #define SUB1_LOOP(_NA_SUBSCRIPT_, _NA_, _ZERO_, _ONE_, _F_) \ do { \ if (_NA_SUBSCRIPT_) \ i = -1; \ else { \ i_ = i = pw0[l] - 1; \ j_ = pw1[l] - 1; \ } \ while (i >= 0) { \ k = pp[i]; \ kend = pp[i + 1]; \ while (k < kend && i_ == i) { \ if (pj[k] < j_) \ ++k; \ else { \ if (pj[k] > j_) \ pres[l] = _ZERO_; \ else \ pres[l] = _F_(px[k]); \ ++l; \ if (l == len || _NA_SUBSCRIPT_) \ i_ = -1; \ else { \ i_ = pw0[l] - 1; \ j_ = pw1[l] - 1; \ } \ } \ } \ while (i_ == i) { \ pres[l] = _ZERO_; \ ++l; \ if (l == len || _NA_SUBSCRIPT_) \ i_ = -1; \ else { \ i_ = pw0[l] - 1; \ j_ = pw1[l] - 1; \ } \ } \ i = i_; \ } \ while (l < len) { \ pres[l] = _NA_; \ ++l; \ } \ } while (0) SUB1_CASES(SUB1_N, SUB1_X, F_NS, F_X); #undef SUB1_LOOP UNPROTECT(3); return res; } static SEXP diagonalMatrix_subscript_1ary_mat(SEXP x, SEXP w, const char *cl) { SUB1_START(kindToType(cl[0])); SEXP diag = PROTECT(GET_SLOT(x, Matrix_diagSym)); int nonunit = *CHAR(STRING_ELT(diag, 0)) == 'N'; UNPROTECT(1); #define SUB1_LOOP(_NA_SUBSCRIPT_, _NA_, _ZERO_, _ONE_, _F_) \ do { \ for (l = 0; l < len; ++l) { \ if (_NA_SUBSCRIPT_) \ pres[l] = _NA_; \ else if (pw0[l] != pw1[l]) \ pres[l] = _ZERO_; \ else if (!nonunit) \ pres[l] = _ONE_; \ else \ pres[l] = _F_(px[pw0[l] - 1]); \ } \ } while (0) SUB1_CASES(SUB1_X, SUB1_X, F_ND, F_X); #undef SUB1_LOOP UNPROTECT(1); return res; } static SEXP indMatrix_subscript_1ary_mat(SEXP x, SEXP w) { SUB1_START(LGLSXP); SEXP perm = PROTECT(GET_SLOT(x, Matrix_permSym)); int *pperm = INTEGER(perm); SEXP margin = PROTECT(GET_SLOT(x, Matrix_marginSym)); int mg = INTEGER(margin)[0] - 1; UNPROTECT(1); #define SUB1_LOOP(_NA_SUBSCRIPT_, _NA_, _ZERO_, _ONE_, _F_) \ do { \ for (l = 0; l < len; ++l) { \ if (_NA_SUBSCRIPT_) \ pres[l] = _NA_; \ else if (!mg) \ pres[l] = pw1[l] == pperm[pw0[l] - 1]; \ else \ pres[l] = pw0[l] == pperm[pw1[l] - 1]; \ } \ } while (0) SUB1_N(int, LOGICAL, NA_LOGICAL, 0, 1, ); #undef SUB1_LOOP #undef SUB1_N #undef SUB1_X #undef SUB1_CASES #undef SUB1_START #undef SUB1_START_EXTRA UNPROTECT(2); return res; } /* x[i] with 'i' of type "integer" and dimensions c(.,2) {i[,1] in 1:m or NA, i[,2] in 1:n or NA} */ SEXP R_subscript_1ary_mat(SEXP x, SEXP i) { static const char *valid[] = { VALID_NONVIRTUAL_MATRIX, "" }; int ivalid = R_check_class_etc(x, valid); if (ivalid < 0) ERROR_INVALID_CLASS(x, __func__); ivalid += VALID_NONVIRTUAL_SHIFT(ivalid, 1); const char *cl = valid[ivalid]; validObject(x, cl); switch (cl[2]) { case 'e': case 'y': case 'r': return unpackedMatrix_subscript_1ary_mat(x, i, cl); case 'p': return packedMatrix_subscript_1ary_mat(x, i, cl); /* NB: for [CRT], the caller must preprocess 'x' and 'i'; symmetric and unit triangular 'x' are not handled specially, and it is assumed for speed that 'i' is sorted by row [R] or column [CT] with NA (incl. out-of-bounds indices) last */ case 'C': return CsparseMatrix_subscript_1ary_mat(x, i, cl); case 'R': return RsparseMatrix_subscript_1ary_mat(x, i, cl); case 'T': { char cl_[] = "..CMatrix"; cl_[0] = cl[0]; cl_[1] = cl[1]; /* defined in ./coerce.c : */ SEXP sparse_as_Csparse(SEXP, const char *); x = sparse_as_Csparse(x, cl); PROTECT(x); x = CsparseMatrix_subscript_1ary_mat(x, i, cl_); UNPROTECT(1); return x; } case 'i': return diagonalMatrix_subscript_1ary_mat(x, i, cl); default: return indMatrix_subscript_1ary_mat(x, i); } } static int keep_tr(int *pi, int *pj, int n, int upper, int nonunit, int checkNA) { int k, ident = memcmp(pi, pj, n * sizeof(int)) == 0; if (checkNA) { if (ident) { for (k = 0; k < n; ++k) if (pi[k] == NA_INTEGER) return 0; } else { for (k = 0; k < n; ++k) if (pi[k] == NA_INTEGER || pj[k] == NA_INTEGER) return 0; } } int r = (upper) ? 1 : -1; if (ident) { /* triangular iff monotone; unit diagonal is preserved */ if (n >= 2) { if (pi[0] == pi[1]) return 0; else if (pi[0] < pi[1]) { for (k = 2; k < n; ++k) if (pi[k - 1] >= pi[k]) return 0; /* up->up, lo->lo */ } else { for (k = 2; k < n; ++k) if (pi[k - 1] <= pi[k]) return 0; /* up->lo, lo->up */ r = -r; } } if (!nonunit) r *= 2; return r; } else { /* brute force ... */ int ki, kj, j_; if (upper) { for (kj = 0; kj < n; ++kj) for (ki = kj + 1, j_ = pj[kj]; ki < n; ++ki) if (pi[ki] <= j_) goto LO; /* up->up */ return r; LO: for (kj = 0; kj < n; ++kj) for (ki = 0, j_ = pj[kj]; ki < kj; ++ki) if (pi[ki] <= j_) return 0; /* up->lo */ return -r; } else { for (kj = 0; kj < n; ++kj) for (ki = 0, j_ = pj[kj]; ki < kj; ++ki) if (pi[ki] >= j_) goto UP; /* lo->lo */ return r; UP: for (kj = 0; kj < n; ++kj) for (ki = kj + 1, j_ = pj[kj]; ki < n; ++ki) if (pi[ki] >= j_) return 0; /* lo->up */ return -r; } } } static int keep_sy(int *pi, int *pj, int n, int upper, int checkNA) { if (memcmp(pi, pj, n * sizeof(int)) != 0) return 0; int k, r = (upper) ? 1 : -1; if (checkNA) { for (k = 0; k < n; ++k) if (pi[k] == NA_INTEGER) return r; } if (n >= 2) { /* triangular iff monotone */ if (pi[0] == pi[1]) return r; else if (pi[0] < pi[1]) { for (k = 2; k < n; ++k) if (pi[k - 1] >= pi[k]) return r; /* up->up, lo->lo */ } else { for (k = 2; k < n; ++k) if (pi[k - 1] <= pi[k]) return r; /* up->lo, lo->up */ r = -r; } } return 2 * r; } static int keep_di(int *pi, int *pj, int n, int nonunit, int checkNA, int lwork) { int k, ident = memcmp(pi, pj, n * sizeof(int)) == 0; if (checkNA) { if (ident) { for (k = 0; k < n; ++k) if (pi[k] == NA_INTEGER) return 0; } else { for (k = 0; k < n; ++k) if (pi[k] == NA_INTEGER || pj[k] == NA_INTEGER) return 0; } } if (ident) { /* diagonal iff no duplicates; unit diagonal is preserved */ char *work; Matrix_Calloc(work, lwork, char); --work; for (k = 0; k < n; ++k) { if (work[pi[k]]) return 0; work[pi[k]] = 1; } ++work; Matrix_Free(work, lwork); return (nonunit) ? 1 : 2; } else { /* brute force ... */ int ki, kj, j_; for (kj = 0; kj < n; ++kj) { j_ = pj[kj]; for (ki = 0; ki < kj; ++ki) if (pi[ki] == j_) return 0; for (ki = kj + 1; ki < n; ++ki) if (pi[ki] == j_) return 0; } return 1; } } static void sort_cr(SEXP obj, const char *cl) { SEXP dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[(cl[2] == 'C') ? 0 : 1], n = pdim[(cl[2] == 'C') ? 1 : 0], r = (m < n) ? n : m; UNPROTECT(1); /* dim */ SEXP iSym = (cl[2] == 'C') ? Matrix_iSym : Matrix_jSym, p = PROTECT(GET_SLOT(obj, Matrix_pSym)), i = PROTECT(GET_SLOT(obj, iSym)); int *pp = INTEGER(p), *pi = INTEGER(i); int i_, j_, k, kend, nnz = pp[n], *workA, *workB, *workC; size_t lwork = (size_t) m + 1 + r + nnz; Matrix_Calloc(workA, lwork, int); workB = workA + m + 1; workC = workB + r; #define SORT_LOOP(_MASK_) \ do { \ ++workA; \ for (k = 0; k < nnz; ++k) \ ++workA[pi[k]]; \ --workA; \ \ for (i_ = 1; i_ < m; ++i_) \ workA[i_] = workB[i_] = workB[i_ - 1] + workA[i_]; \ workA[m] = nnz; \ \ ++pp; \ k = 0; \ for (j_ = 0; j_ < n; ++j_) { \ kend = pp[j_]; \ while (k < kend) { \ i_ = pi[k]; \ workC[workB[i_]] = j_; \ _MASK_(workD[workB[i_]] = px[k]); \ ++workB[i_]; \ ++k; \ } \ } \ --pp; \ \ for (j_ = 0; j_ < n; ++j_) \ workB[j_] = pp[j_]; \ \ ++workA; \ k = 0; \ for (i_ = 0; i_ < m; ++i_) { \ kend = workA[i_]; \ while (k < kend) { \ j_ = workC[k]; \ pi[workB[j_]] = i_; \ _MASK_(px[workB[j_]] = workD[k]); \ ++workB[j_]; \ ++k; \ } \ } \ --workA; \ } while (0) #define SORT(_CTYPE_, _PTR_) \ do { \ _CTYPE_ *px = _PTR_(x), *workD; \ Matrix_Calloc(workD, nnz, _CTYPE_); \ SORT_LOOP(SHOW); \ Matrix_Free(workD, nnz); \ } while (0) if (cl[0] == 'n') SORT_LOOP(HIDE); else { SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)); switch (cl[0]) { case 'l': SORT(int, LOGICAL); break; case 'i': SORT(int, INTEGER); break; case 'd': SORT(double, REAL); break; case 'z': SORT(Rcomplex, COMPLEX); break; default: break; } UNPROTECT(1); /* x */ } #undef SORT_LOOP #undef SORT Matrix_Free(workA, lwork); UNPROTECT(2); /* i, p */ return; } #define XIJ_GE( _X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ *(_X_ + _J_ * _M_ + _I_) #define XIJ_TR_U_N(_X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ ((_I_ <= _J_) \ ? XIJ_GE(_X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ : _ZERO_) #define XIJ_TR_U_U(_X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ ((_I_ < _J_) \ ? XIJ_GE(_X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ : ((_I_ == _J_) ? _ONE_ : _ZERO_)) #define XIJ_TR_L_N(_X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ ((_I_ >= _J_) \ ? XIJ_GE(_X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ : _ZERO_) #define XIJ_TR_L_U(_X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ ((_I_ > _J_) \ ? XIJ_GE(_X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ : ((_I_ == _J_) ? _ONE_ : _ZERO_)) #define XIJ_TP_U_N(_X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ ((_I_ <= _J_) \ ? *(_X_ + AR21_UP(_I_, _J_, _M_)) \ : _ZERO_) #define XIJ_TP_U_U(_X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ ((_I_ < _J_) \ ? *(_X_ + AR21_UP(_I_, _J_, _M_)) \ : ((_I_ == _J_) ? _ONE_ : _ZERO_)) #define XIJ_TP_L_N(_X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ ((_I_ >= _J_) \ ? *(_X_ + AR21_LO(_I_, _J_, _M_)) \ : _ZERO_) #define XIJ_TP_L_U(_X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ ((_I_ > _J_) \ ? *(_X_ + AR21_LO(_I_, _J_, _M_)) \ : ((_I_ == _J_) ? _ONE_ : _ZERO_)) #define XIJ_SY_U( _X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ ((_I_ <= _J_) \ ? XIJ_GE(_X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ : XIJ_GE(_X_, _J_, _I_, _M_, _ZERO_, _ONE_)) #define XIJ_SY_L( _X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ ((_I_ >= _J_) \ ? XIJ_GE(_X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ : XIJ_GE(_X_, _J_, _I_, _M_, _ZERO_, _ONE_)) #define XIJ_SP_U( _X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ ((_I_ <= _J_) \ ? *(_X_ + AR21_UP(_I_, _J_, _M_)) \ : *(_X_ + AR21_UP(_J_, _I_, _M_))) #define XIJ_SP_L( _X_, _I_, _J_, _M_, _ZERO_, _ONE_) \ ((_I_ >= _J_) \ ? *(_X_ + AR21_LO(_I_, _J_, _M_)) \ : *(_X_ + AR21_LO(_J_, _I_, _M_))) static SEXP unpackedMatrix_subscript_2ary(SEXP x, SEXP i, SEXP j, const char *cl) { #define SUB2_START \ SEXP dim = PROTECT(GET_SLOT(x, Matrix_DimSym)); \ int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; \ UNPROTECT(1); /* dim */ \ \ int ki, kj, \ mi = i == R_NilValue, \ mj = j == R_NilValue, \ ni = (mi) ? m : LENGTH(i), \ nj = (mj) ? n : LENGTH(j), \ *pi = (mi) ? NULL : INTEGER(i), \ *pj = (mj) ? NULL : INTEGER(j); #define SUB2_START_EXTRA(_E_, _R_, _Y_, _DENSE_) \ SUB2_START; \ \ int upper = 1, nonunit = 1, keep = 0; \ SEXP uplo, diag; \ if (cl[1] != 'g') { \ PROTECT(uplo = GET_SLOT(x, Matrix_uploSym)); \ upper = *CHAR(STRING_ELT(uplo, 0)) == 'U'; \ UNPROTECT(1); /* uplo */ \ if (cl[1] == 't') { \ PROTECT(diag = GET_SLOT(x, Matrix_diagSym)); \ nonunit = *CHAR(STRING_ELT(diag, 0)) == 'N'; \ UNPROTECT(1); /* diag */ \ } \ } \ \ char cl_[] = "...Matrix"; \ cl_[0] = cl[0]; \ cl_[1] = 'g'; \ cl_[2] = _E_; \ if (cl[1] != 'g' && !(mi || mj) && ni == nj) { \ if (cl[1] == 't') { \ keep = keep_tr(pi, pj, ni, upper, nonunit, _DENSE_); \ if (keep != 0) { \ cl_[1] = 't'; \ cl_[2] = _R_; \ } \ } else { \ keep = keep_sy(pi, pj, ni, upper, 0); \ if ((_DENSE_) ? keep != 0 : keep < -1 || keep > 1) { \ cl_[1] = 's'; \ cl_[2] = _Y_; \ } \ } \ } \ SEXP res = PROTECT(newObject(cl_)); \ \ PROTECT(dim = GET_SLOT(res, Matrix_DimSym)); \ pdim = INTEGER(dim); \ pdim[0] = ni; \ pdim[1] = nj; \ UNPROTECT(1); /* dim */ \ \ if ((cl[1] != 's') ? keep < 0 : keep < -1) { \ PROTECT(uplo = GET_SLOT(res, Matrix_uploSym)); \ SEXP uplo_ = PROTECT(mkChar("L")); \ SET_STRING_ELT(uplo, 0, uplo_); \ UNPROTECT(2); /* uplo_, uplo */ \ } \ if (cl[1] == 't' && (keep < -1 || keep > 1)) { \ PROTECT(diag = GET_SLOT(res, Matrix_diagSym)); \ SEXP diag_ = PROTECT(mkChar("U")); \ SET_STRING_ELT(diag, 0, diag_); \ UNPROTECT(2); /* diag_, diag */ \ } SUB2_START_EXTRA('e', 'r', 'y', 1); double ninj = (double) ni * nj; if (ninj > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); SEXP x0 = PROTECT(GET_SLOT(x, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), (R_xlen_t) ninj)); int i_, j_; Matrix_int_fast64_t m_ = m; #define SUB2_CASES(_SUB2_) \ do { \ switch (cl[0]) { \ case 'n': \ case 'l': \ _SUB2_(int, LOGICAL, NA_LOGICAL, 0, 1); \ break; \ case 'i': \ _SUB2_(int, INTEGER, NA_INTEGER, 0, 1); \ break; \ case 'd': \ _SUB2_(double, REAL, NA_REAL, 0.0, 1.0); \ break; \ case 'z': \ _SUB2_(Rcomplex, COMPLEX, \ Matrix_zna, Matrix_zzero, Matrix_zone); \ break; \ default: \ break; \ } \ } while (0) #define SUB2(_CTYPE_, _PTR_, _NA_, _ZERO_, _ONE_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ if (cl_[1] == 'g') { \ if (cl[1] == 'g') \ SUB2_LOOP(for (ki = 0; ki < ni; ++ki), \ XIJ_GE, , , _NA_, _ZERO_, _ONE_); \ else if (cl[1] == 't') { \ if (upper) { \ if (nonunit) \ SUB2_LOOP(for (ki = 0; ki < ni; ++ki), \ XIJ_TR_U_N, , , _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = 0; ki < ni; ++ki), \ XIJ_TR_U_U, , , _NA_, _ZERO_, _ONE_); \ } else { \ if (nonunit) \ SUB2_LOOP(for (ki = 0; ki < ni; ++ki), \ XIJ_TR_L_N, , , _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = 0; ki < ni; ++ki), \ XIJ_TR_L_U, , , _NA_, _ZERO_, _ONE_); \ } \ } else { \ if (upper) \ SUB2_LOOP(for (ki = 0; ki < ni; ++ki), \ XIJ_SY_U, , , _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = 0; ki < ni; ++ki), \ XIJ_SY_L, , , _NA_, _ZERO_, _ONE_); \ } \ } else if (cl_[1] == 't') { \ Matrix_memset(px1, 0, XLENGTH(x1), sizeof(_CTYPE_)); \ if (upper) { \ if (nonunit) { \ if (keep > 0) \ SUB2_LOOP(for (ki = 0; ki <= kj; ++ki), \ XIJ_TR_U_N, , px1 += ni - kj - 1, \ _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = kj; ki < ni; ++ki), \ XIJ_TR_U_N, px1 += kj, , \ _NA_, _ZERO_, _ONE_); \ } else { \ if (keep > 0) \ SUB2_LOOP(for (ki = 0; ki <= kj; ++ki), \ XIJ_TR_U_U, , px1 += ni - kj - 1, \ _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = kj; ki < ni; ++ki), \ XIJ_TR_U_U, px1 += kj, , \ _NA_, _ZERO_, _ONE_); \ } \ } else { \ if (nonunit) { \ if (keep > 0) \ SUB2_LOOP(for (ki = 0; ki <= kj; ++ki), \ XIJ_TR_L_N, , px1 += ni - kj - 1, \ _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = kj; ki < ni; ++ki), \ XIJ_TR_L_N, px1 += kj, , \ _NA_, _ZERO_, _ONE_); \ } else { \ if (keep > 0) \ SUB2_LOOP(for (ki = 0; ki <= kj; ++ki), \ XIJ_TR_L_U, , px1 += ni - kj - 1, \ _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = kj; ki < ni; ++ki), \ XIJ_TR_L_U, px1 += kj, , \ _NA_, _ZERO_, _ONE_); \ } \ } \ } else { \ Matrix_memset(px1, 0, XLENGTH(x1), sizeof(_CTYPE_)); \ if (upper) { \ if (keep > 0) \ SUB2_LOOP(for (ki = 0; ki <= kj; ++ki), \ XIJ_SY_U, , px1 += ni - kj - 1, \ _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = kj; ki < ni; ++ki), \ XIJ_SY_U, px1 += kj, , \ _NA_, _ZERO_, _ONE_); \ } else { \ if (keep > 0) \ SUB2_LOOP(for (ki = 0; ki <= kj; ++ki), \ XIJ_SY_L, , px1 += ni - kj - 1, \ _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = kj; ki < ni; ++ki), \ XIJ_SY_L, px1 += kj, , \ _NA_, _ZERO_, _ONE_); \ } \ } \ } while (0) #define SUB2_LOOP(_FOR_, _XIJ_, _JUMP1_, _JUMP2_, \ _NA_, _ZERO_, _ONE_) \ do { \ for (kj = 0; kj < nj; ++kj) { \ if (mj) \ j_ = kj; \ else { \ j_ = pj[kj]; \ if (j_ != NA_INTEGER) \ j_ -= 1; \ else { \ _JUMP1_; \ _FOR_ { \ *(px1++) = _NA_; \ } \ _JUMP2_; \ continue; \ } \ } \ _JUMP1_; \ _FOR_ { \ if (mi) \ i_ = ki; \ else { \ i_ = pi[ki]; \ if (i_ != NA_INTEGER) \ i_ -= 1; \ else { \ *(px1++) = _NA_; \ continue; \ } \ } \ *(px1++) = _XIJ_(px0, i_, j_, m_, _ZERO_, _ONE_); \ } \ _JUMP2_; \ } \ } while (0) SUB2_CASES(SUB2); #undef SUB2 SET_SLOT(res, Matrix_xSym, x1); UNPROTECT(3); /* x1, x0, res */ return res; } static SEXP packedMatrix_subscript_2ary(SEXP x, SEXP i, SEXP j, const char *cl) { SUB2_START_EXTRA('e', 'p', 'p', 1); double ninj = (double) ni * nj, ninj_ = (keep) ? 0.5 * (ninj + ni) : ninj; if (ninj_ > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); SEXP x0 = PROTECT(GET_SLOT(x, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), (R_xlen_t) ninj_)); int i_, j_; Matrix_int_fast64_t m_ = m; #define SUB2(_CTYPE_, _PTR_, _NA_, _ZERO_, _ONE_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ if (cl_[1] == 'g') { \ if (cl[1] == 't') { \ if (upper) { \ if (nonunit) \ SUB2_LOOP(for (ki = 0; ki < ni; ++ki), \ XIJ_TP_U_N, , , _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = 0; ki < ni; ++ki), \ XIJ_TP_U_U, , , _NA_, _ZERO_, _ONE_); \ } else { \ if (nonunit) \ SUB2_LOOP(for (ki = 0; ki < ni; ++ki), \ XIJ_TP_L_N, , , _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = 0; ki < ni; ++ki), \ XIJ_TP_L_U, , , _NA_, _ZERO_, _ONE_); \ } \ } else { \ if (upper) \ SUB2_LOOP(for (ki = 0; ki < ni; ++ki), \ XIJ_SP_U, , , _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = 0; ki < ni; ++ki), \ XIJ_SP_L, , , _NA_, _ZERO_, _ONE_); \ } \ } else if (cl_[1] == 't') { \ if (upper) { \ if (nonunit) { \ if (keep > 0) \ SUB2_LOOP(for (ki = 0; ki <= kj; ++ki), \ XIJ_TP_U_N, , , _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = kj; ki < ni; ++ki), \ XIJ_TP_U_N, , , _NA_, _ZERO_, _ONE_); \ } else { \ if (keep > 0) \ SUB2_LOOP(for (ki = 0; ki <= kj; ++ki), \ XIJ_TP_U_U, , , _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = kj; ki < ni; ++ki), \ XIJ_TP_U_U, , , _NA_, _ZERO_, _ONE_); \ } \ } else { \ if (nonunit) { \ if (keep > 0) \ SUB2_LOOP(for (ki = 0; ki <= kj; ++ki), \ XIJ_TP_L_N, , , _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = kj; ki < ni; ++ki), \ XIJ_TP_L_N, , , _NA_, _ZERO_, _ONE_); \ } else { \ if (keep > 0) \ SUB2_LOOP(for (ki = 0; ki <= kj; ++ki), \ XIJ_TP_L_U, , , _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = kj; ki < ni; ++ki), \ XIJ_TP_L_U, , , _NA_, _ZERO_, _ONE_); \ } \ } \ } else { \ if (upper) { \ if (keep > 0) \ SUB2_LOOP(for (ki = 0; ki <= kj; ++ki), \ XIJ_SP_U, , , _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = kj; ki < ni; ++ki), \ XIJ_SP_U, , , _NA_, _ZERO_, _ONE_); \ } else { \ if (keep > 0) \ SUB2_LOOP(for (ki = 0; ki <= kj; ++ki), \ XIJ_SP_L, , , _NA_, _ZERO_, _ONE_); \ else \ SUB2_LOOP(for (ki = kj; ki < ni; ++ki), \ XIJ_SP_L, , , _NA_, _ZERO_, _ONE_); \ } \ } \ } while (0) SUB2_CASES(SUB2); #undef SUB2_LOOP #undef SUB2 SET_SLOT(res, Matrix_xSym, x1); UNPROTECT(3); /* x1, x0, res */ return res; } static SEXP CsparseMatrix_subscript_2ary(SEXP x, SEXP i, SEXP j, const char *cl) { SUB2_START_EXTRA('C', 'C', 'C', 0); if (cl[1] != 'g' && cl_[1] == 'g') { /* defined in ./coerce.c : */ SEXP sparse_as_general(SEXP, const char *); x = sparse_as_general(x, cl); } PROTECT(x); SEXP p0 = PROTECT(GET_SLOT(x, Matrix_pSym)), i0 = PROTECT(GET_SLOT(x, Matrix_iSym)), p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) nj + 1)), i1 = NULL; int *pp0 = INTEGER(p0), *pi0 = INTEGER(i0), *pp1 = INTEGER(p1), *pi1 = NULL, d, k, kend, doSort = 0; Matrix_int_fast64_t nnz = 0; *(pp1++) = 0; #define SUB2_FINISH \ if (nnz > INT_MAX) \ error(_("%s too dense for %s; would have more than %s nonzero entries"), \ "x[i,j]", "[CR]sparseMatrix", "2^31-1"); \ \ PROTECT(i1 = allocVector(INTSXP, (R_xlen_t) nnz)); \ pi1 = INTEGER(i1); \ \ if (cl[0] == 'n') \ SUB2_LOOP(HIDE); \ else { \ SEXP x0 = PROTECT(GET_SLOT(x, Matrix_xSym)), \ x1 = PROTECT(allocVector(TYPEOF(x0), (R_xlen_t) nnz)); \ SUB2_CASES(SUB2); \ SET_SLOT(res, Matrix_xSym, x1); \ UNPROTECT(2); /* x1, x0 */ \ } #define SUB2(_CTYPE_, _PTR_, _NA_, _ZERO_, _ONE_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ SUB2_LOOP(SHOW); \ } while (0) if (mi) { for (kj = 0; kj < nj; ++kj) { nnz += pp0[pj[kj]] - pp0[pj[kj] - 1]; pp1[kj] = (int) nnz; } #define SUB2_LOOP(_MASK_) \ do { \ for (kj = 0; kj < nj; ++kj) { \ k = pp0[pj[kj] - 1]; \ kend = pp0[pj[kj]]; \ d = kend - k; \ if (d) { \ Matrix_memcpy(pi1, pi0 + k, d, sizeof(int)); \ pi1 += d; \ _MASK_(Matrix_memcpy(px1, px0 + k, d, sizeof(*px1))); \ _MASK_(px1 += d); \ } \ } \ } while (0) SUB2_FINISH; #undef SUB2_LOOP } else { int *workA, *workB, *workC; size_t lwork = (size_t) m + m + ni; Matrix_Calloc(workA, lwork, int); workB = workA + m; workC = workB + m; /* workA[ i] : size of the set { ki : pi[ki] - 1 == i } workB[ i] : smallest ki such that pi[ki] - 1 == i workC[ki] : smallest ki' > ki such that pi[ki'] == pi[ki] */ int i_, j_, i_prev = m; for (ki = ni - 1; ki >= 0; --ki) { i_ = pi[ki] - 1; ++workA[i_]; workC[ki] = workB[i_]; workB[i_] = ki; if (i_ > i_prev) doSort = 1; i_prev = i_; } for (kj = 0; kj < nj; ++kj) { j_ = (mj) ? kj : pj[kj] - 1; k = pp0[j_]; kend = pp0[j_ + 1]; while (k < kend) { nnz += workA[pi0[k]]; ++k; } pp1[kj] = (int) nnz; } #define SUB2_LOOP(_MASK_) \ do { \ for (kj = 0; kj < nj; ++kj) { \ j_ = (mj) ? kj : pj[kj] - 1; \ k = pp0[j_]; \ kend = pp0[j_ + 1]; \ while (k < kend) { \ i_ = pi0[k]; \ d = workA[i_]; \ ki = workB[i_]; \ while (d--) { \ *(pi1++) = ki; \ _MASK_(*(px1++) = px0[k]); \ ki = workC[ki]; \ } \ ++k; \ } \ } \ } while (0) SUB2_FINISH; #undef SUB2_LOOP Matrix_Free(workA, lwork); } #undef SUB2_FINISH SET_SLOT(res, Matrix_pSym, p1); SET_SLOT(res, Matrix_iSym, i1); UNPROTECT(4); /* i1, p1, i0, p0 */ if (doSort) sort_cr(res, cl); if (cl[1] == 's' && (keep == -1 || keep == 1)) { /* defined in ./sparse.c : */ SEXP sparse_force_symmetric(SEXP, const char *, char); res = sparse_force_symmetric(res, cl_, (keep == 1) ? 'U' : 'L'); } UNPROTECT(2); /* x, res */ return res; } static SEXP RsparseMatrix_subscript_2ary(SEXP x, SEXP i, SEXP j, const char *cl) { SUB2_START_EXTRA('R', 'R', 'R', 0); if (cl[1] != 'g' && cl_[1] == 'g') { /* defined in ./coerce.c : */ SEXP sparse_as_general(SEXP, const char *); x = sparse_as_general(x, cl); } PROTECT(x); SEXP p0 = PROTECT(GET_SLOT(x, Matrix_pSym)), j0 = PROTECT(GET_SLOT(x, Matrix_jSym)), p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) ni + 1)), j1 = NULL; int *pp0 = INTEGER(p0), *pj0 = INTEGER(j0), *pp1 = INTEGER(p1), *pj1 = NULL, d, k, kend, doSort = 0; Matrix_int_fast64_t nnz = 0; *(pp1++) = 0; #define SUB2_FINISH \ if (nnz > INT_MAX) \ error(_("%s too dense for %s; would have more than %s nonzero entries"), \ "x[i,j]", "[CR]sparseMatrix", "2^31-1"); \ \ PROTECT(j1 = allocVector(INTSXP, (R_xlen_t) nnz)); \ pj1 = INTEGER(j1); \ \ if (cl[0] == 'n') \ SUB2_LOOP(HIDE); \ else { \ SEXP x0 = PROTECT(GET_SLOT(x, Matrix_xSym)), \ x1 = PROTECT(allocVector(TYPEOF(x0), (R_xlen_t) nnz)); \ SUB2_CASES(SUB2); \ SET_SLOT(res, Matrix_xSym, x1); \ UNPROTECT(2); /* x1, x0 */ \ } if (mj) { for (ki = 0; ki < ni; ++ki) { nnz += pp0[pi[ki]] - pp0[pi[ki] - 1]; pp1[ki] = (int) nnz; } #define SUB2_LOOP(_MASK_) \ do { \ for (ki = 0; ki < ni; ++ki) { \ k = pp0[pi[ki] - 1]; \ kend = pp0[pi[ki]]; \ d = kend - k; \ if (d) { \ Matrix_memcpy(pj1, pj0 + k, d, sizeof(int)); \ pj1 += d; \ _MASK_(Matrix_memcpy(px1, px0 + k, d, sizeof(*px1))); \ _MASK_(px1 += d); \ } \ } \ } while (0) SUB2_FINISH; #undef SUB2_LOOP } else { int *workA, *workB, *workC; size_t lwork = (size_t) n + n + nj; Matrix_Calloc(workA, lwork, int); workB = workA + n; workC = workB + n; /* workA[ j] : size of the set { kj : pj[kj] - 1 == j } workB[ j] : smallest ki such that pj[kj] - 1 == j workC[kj] : smallest kj' > kj such that pj[kj'] == pj[kj] */ int i_, j_, j_prev = n; for (kj = nj - 1; kj >= 0; --kj) { j_ = pj[kj] - 1; ++workA[j_]; workC[kj] = workB[j_]; workB[j_] = kj; if (j_ > j_prev) doSort = 1; j_prev = j_; } for (ki = 0; ki < ni; ++ki) { i_ = (mi) ? ki : pi[ki] - 1; k = pp0[i_]; kend = pp0[i_ + 1]; while (k < kend) { nnz += workA[pj0[k]]; ++k; } pp1[ki] = (int) nnz; } #define SUB2_LOOP(_MASK_) \ do { \ for (ki = 0; ki < ni; ++ki) { \ i_ = (mi) ? ki : pi[ki] - 1; \ k = pp0[i_]; \ kend = pp0[i_ + 1]; \ while (k < kend) { \ j_ = pj0[k]; \ d = workA[j_]; \ kj = workB[j_]; \ while (d--) { \ *(pj1++) = kj; \ _MASK_(*(px1++) = px0[k]); \ kj = workC[kj]; \ } \ ++k; \ } \ } \ } while (0) SUB2_FINISH; #undef SUB2_LOOP Matrix_Free(workA, lwork); } #undef SUB2_FINISH #undef SUB2 SET_SLOT(res, Matrix_pSym, p1); SET_SLOT(res, Matrix_jSym, j1); UNPROTECT(4); /* j1, p1, j0, p0 */ if (doSort) sort_cr(res, cl); if (cl[1] == 's' && (keep == -1 || keep == 1)) { /* defined in ./sparse.c : */ SEXP sparse_force_symmetric(SEXP, const char *, char); res = sparse_force_symmetric(res, cl_, (keep == 1) ? 'U' : 'L'); } UNPROTECT(2); /* x, res */ return res; } static SEXP diagonalMatrix_subscript_2ary(SEXP x, SEXP i, SEXP j, const char *cl) { SUB2_START; int nonunit = 1, keep = 0; SEXP diag = PROTECT(GET_SLOT(x, Matrix_diagSym)); nonunit = *CHAR(STRING_ELT(diag, 0)) == 'N'; UNPROTECT(1); /* diag */ char cl_[] = ".gCMatrix"; cl_[0] = cl[0]; if (!(mi || mj) && ni == nj) { keep = keep_di(pi, pj, ni, nonunit, 0, m); if (keep > 0) { cl_[1] = 'd'; cl_[2] = 'i'; } } SEXP res = PROTECT(newObject(cl_)); PROTECT(dim = GET_SLOT(res, Matrix_DimSym)); pdim = INTEGER(dim); pdim[0] = (int) ni; pdim[1] = (int) nj; UNPROTECT(1); /* dim */ if (keep > 1) { PROTECT(diag = GET_SLOT(res, Matrix_diagSym)); SEXP diag_ = PROTECT(mkChar("U")); SET_STRING_ELT(diag, 0, diag_); UNPROTECT(2); /* diag_, diag */ } else if (keep > 0) { SEXP x0 = PROTECT(GET_SLOT(x, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), ni)); int j_; #define SUB2(_CTYPE_, _PTR_, _NA_, _ZERO_, _ONE_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ while (ni--) \ *(px1++) = \ (*(pi++) != (j_ = *(pj++))) \ ? _ZERO_ \ : ((nonunit) ? px0[j_ - 1] : _ONE_); \ } while (0) SUB2_CASES(SUB2); #undef SUB2 SET_SLOT(res, Matrix_xSym, x1); UNPROTECT(2); /* x0, x1 */ } else { SEXP x0 = PROTECT(GET_SLOT(x, Matrix_xSym)); char *work = NULL; int j_; if (nonunit) { Matrix_Calloc(work, n, char); #define SUB2_WORK(_CTYPE_, _PTR_, _ISNZ_) \ do { \ _CTYPE_ *px0 = _PTR_(x0); \ for (j_ = 0; j_ < n; ++j_) \ work[j_] = _ISNZ_(px0[j_]); \ } while (0) switch (cl[0]) { case 'n': SUB2_WORK(int, LOGICAL, ISNZ_PATTERN); break; case 'l': SUB2_WORK(int, LOGICAL, ISNZ_LOGICAL); break; case 'i': SUB2_WORK(int, INTEGER, ISNZ_INTEGER); break; case 'd': SUB2_WORK(double, REAL, ISNZ_REAL); break; case 'z': SUB2_WORK(Rcomplex, COMPLEX, ISNZ_COMPLEX); break; default: break; } #undef SUB2_WORK } SEXP p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) nj + 1)); int *pp1 = INTEGER(p1); *(pp1++) = 0; for (kj = 0; kj < nj; ++kj) { pp1[kj] = 0; j_ = (mj) ? kj : pj[kj] - 1; if (!nonunit || work[j_]) { if (mi) { for (ki = 0; ki < ni; ++ki) if (ki == j_) ++pp1[kj]; } else { for (ki = 0; ki < ni; ++ki) if (pi[ki] - 1 == j_) ++pp1[kj]; } if (pp1[kj] > INT_MAX - pp1[kj - 1]) { if (nonunit) Matrix_Free(work, n); error(_("%s too dense for %s; would have more than %s nonzero entries"), "x[i,j]", "[CR]sparseMatrix", "2^31-1"); } } pp1[kj] += pp1[kj-1]; } SEXP i1 = PROTECT(allocVector(INTSXP, pp1[nj - 1])), x1 = PROTECT(allocVector(TYPEOF(x0), pp1[nj - 1])); int *pi1 = INTEGER(i1); #define SUB2(_CTYPE_, _PTR_, _NA_, _ZERO_, _ONE_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ for (kj = 0; kj < nj; ++kj) { \ j_ = (mj) ? kj : pj[kj] - 1; \ if (!nonunit || work[j_]) { \ for (ki = 0; ki < ni; ++ki) { \ if (((mi) ? ki : pi[ki] - 1) == j_) { \ *(pi1++) = ki; \ *(px1++) = (nonunit) ? px0[j_] : _ONE_; \ } \ } \ } \ } \ } while (0) SUB2_CASES(SUB2); #undef SUB2 SET_SLOT(res, Matrix_pSym, p1); SET_SLOT(res, Matrix_iSym, i1); SET_SLOT(res, Matrix_xSym, x1); UNPROTECT(4); /* x1, x0, i1, p1 */ if (nonunit) Matrix_Free(work, n); } UNPROTECT(1); /* res */ return res; } static SEXP indMatrix_subscript_2ary(SEXP x, SEXP i, SEXP j, const char *cl) { PROTECT_INDEX pidA; PROTECT_WITH_INDEX(x, &pidA); PROTECT_INDEX pidB; SEXP perm0 = GET_SLOT(x, Matrix_permSym); int *pperm0 = INTEGER(perm0); PROTECT_WITH_INDEX(perm0, &pidB); SEXP margin = PROTECT(GET_SLOT(x, Matrix_marginSym)); int mg = INTEGER(margin)[0] - 1; SEXP dim = PROTECT(GET_SLOT(x, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[mg], n = pdim[!mg]; UNPROTECT(1); /* dim */ if (mg) { SEXP i_tmp = i; i = j; j = i_tmp; } int ki, kj, mi = i == R_NilValue, mj = j == R_NilValue, ni = (mi) ? m : LENGTH(i), nj = (mj) ? n : LENGTH(j), *pi = (mi) ? NULL : INTEGER(i), *pj = (mj) ? NULL : INTEGER(j), isP = cl[0] == 'p'; if (!mi) { isP = isP && ni == m; if (isP) { char *work; Matrix_Calloc(work, m, char); --work; /* now 1-indexed */ for (ki = 0; ki < ni; ++ki) { if (work[pi[ki]]) { isP = 0; break; } work[pi[ki]] = 1; } ++work; /* now 0-indexed */ Matrix_Free(work, m); } x = newObject((isP) ? "pMatrix" : "indMatrix"); REPROTECT(x, pidA); PROTECT(dim = GET_SLOT(x, Matrix_DimSym)); pdim = INTEGER(dim); pdim[ mg] = ni; pdim[!mg] = n; UNPROTECT(1); /* dim */ if (mg) SET_SLOT(x, Matrix_marginSym, margin); SEXP perm1 = PROTECT(allocVector(INTSXP, ni)); int *pperm1 = INTEGER(perm1); --pperm0; /* now 1-indexed */ for (ki = 0; ki < ni; ++ki) pperm1[ki] = pperm0[pi[ki]]; SET_SLOT(x, Matrix_permSym, perm1); UNPROTECT(1); /* perm1 */ perm0 = perm1; pperm0 = pperm1; REPROTECT(perm0, pidB); m = ni; } if (!mj) { isP = isP && nj == n; if (isP) { char *work; Matrix_Calloc(work, nj, char); --work; /* now 1-indexed */ for (kj = 0; kj < nj; ++kj) { if (work[pj[kj]]) { isP = 0; break; } work[pj[kj]] = 1; } ++work; /* now 0-indexed */ Matrix_Free(work, nj); } x = newObject((isP) ? "pMatrix" : ((!mg) ? "ngCMatrix" : "ngRMatrix")); REPROTECT(x, pidA); PROTECT(dim = GET_SLOT(x, Matrix_DimSym)); pdim = INTEGER(dim); pdim[ mg] = m; pdim[!mg] = nj; UNPROTECT(1); /* dim */ if (isP) { SEXP perm1 = PROTECT(allocVector(INTSXP, nj)); int *pperm1 = INTEGER(perm1), *work; Matrix_Calloc(work, nj, int); --work; /* now 1-indexed */ for (kj = 0; kj < nj; ++kj) work[pj[kj]] = kj + 1; for (kj = 0; kj < nj; ++kj) pperm1[kj] = work[pperm0[kj]]; ++work; /* now 0-indexed */ Matrix_Free(work, nj); SET_SLOT(x, Matrix_permSym, perm1); UNPROTECT(1); /* perm1 */ } else { int *workA, *workB, *workC; size_t lwork = (size_t) n + n + m; Matrix_Calloc(workA, lwork, int); workB = workA + n; workC = workB + n; --workA; /* now 1-indexed */ --workB; /* now 1-indexed */ SEXP p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) nj + 1)); int *pp1 = INTEGER(p1), k, kend; /* 1. Compute old column counts in 'workA' */ for (k = 0; k < m; ++k) ++workA[pperm0[k]]; /* 2. Compute new column pointers in 'pp1' */ *(pp1++) = 0; for (kj = 0; kj < nj; ++kj) { pp1[kj] = workA[pj[kj]]; if (pp1[kj] > INT_MAX - pp1[kj - 1]) error(_("%s too dense for %s; would have more than %s nonzero entries"), \ "x[i,j]", "[CR]sparseMatrix", "2^31-1"); \ pp1[kj] += pp1[kj - 1]; } /* 3. Compute old column pointers in 'workB' and copy to 'workA' */ workB[1] = 0; for (k = 1; k < n; ++k) { workB[k + 1] = workB[k] + workA[k]; workA[k] = workB[k]; } workA[n] = workB[n]; /* 4. Sort old row indices into 'workC' */ for (k = 0; k < m; ++k) workC[workA[pperm0[k]]++] = k; SEXP i1 = PROTECT(allocVector(INTSXP, pp1[nj - 1])); int *pi1 = INTEGER(i1), pos; /* 5. Copy row indices from 'workC' to 'pi1' */ k = 0; for (kj = 0; kj < nj; ++kj) { kend = pp1[kj]; pos = workB[pj[kj]]; while (k < kend) pi1[k++] = workC[pos++]; } ++workA; /* now 0-indexed */ Matrix_Free(workA, lwork); SET_SLOT(x, Matrix_pSym, p1); SET_SLOT(x, (!mg) ? Matrix_iSym : Matrix_jSym, i1); UNPROTECT(2); /* i1, p1 */ } n = nj; } #undef SUB2_CASES #undef SUB2_START #undef SUB2_START_EXTRA UNPROTECT(3); /* margin, perm0, x */ return x; } /* x[i,j,drop=FALSE] with 'i' and 'j' of type "integer" and length not exceeding 2^31-1 {'i' in 1:m or NA, 'j' in 1:n or NA} ... but _not_ handling 'Dimnames' */ SEXP R_subscript_2ary(SEXP x, SEXP i, SEXP j) { if (i == R_NilValue && j == R_NilValue) return x; static const char *valid[] = { VALID_NONVIRTUAL_MATRIX, "" }; int ivalid = R_check_class_etc(x, valid); if (ivalid < 0) ERROR_INVALID_CLASS(x, __func__); ivalid += VALID_NONVIRTUAL_SHIFT(ivalid, 0); const char *cl = valid[ivalid]; validObject(x, cl); switch (cl[2]) { case 'e': case 'y': case 'r': return unpackedMatrix_subscript_2ary(x, i, j, cl); case 'p': return packedMatrix_subscript_2ary(x, i, j, cl); default: break; } static SEXP anyNA = NULL; if (!anyNA) anyNA = install("anyNA"); SEXP call = PROTECT(lang2(anyNA, R_NilValue)), value; #define ERROR_IF_ANYNA(_I_) \ do { \ if ((_I_) != R_NilValue) { \ SETCADR(call, _I_); \ PROTECT(value = eval(call, R_BaseEnv)); \ if (asLogical(value)) \ error(_("NA subscripts in %s not supported for '%s' inheriting from %s"), \ "x[i,j]", "x", "sparseMatrix"); \ UNPROTECT(1); \ } \ } while (0) ERROR_IF_ANYNA(i); ERROR_IF_ANYNA(j); #undef ERROR_IF_ANYNA UNPROTECT(1); switch (cl[2]) { case 'C': return CsparseMatrix_subscript_2ary(x, i, j, cl); case 'R': return RsparseMatrix_subscript_2ary(x, i, j, cl); case 'T': { char cl_[] = "..CMatrix"; cl_[0] = cl[0]; cl_[1] = cl[1]; /* defined in ./coerce.c : */ SEXP sparse_as_Csparse(SEXP, const char *); SEXP sparse_as_Tsparse(SEXP, const char *); x = sparse_as_Csparse(x, cl); PROTECT(x); x = CsparseMatrix_subscript_2ary(x, i, j, cl_); UNPROTECT(1); PROTECT(x); x = sparse_as_Tsparse(x, valid[R_check_class_etc(x, valid)]); UNPROTECT(1); return x; } case 'i': return diagonalMatrix_subscript_2ary(x, i, j, cl); default: return indMatrix_subscript_2ary(x, i, j, cl); } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/kappa.h����������������������������������������������������������������������������������0000644�0001751�0000144�00000001027�14503212600�013561� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_KAPPA_H #define MATRIX_KAPPA_H #include SEXP dgeMatrix_norm(SEXP, SEXP); SEXP dsyMatrix_norm(SEXP, SEXP); SEXP dspMatrix_norm(SEXP, SEXP); SEXP dtrMatrix_norm(SEXP, SEXP); SEXP dtpMatrix_norm(SEXP, SEXP); SEXP dgeMatrix_rcond(SEXP, SEXP, SEXP); SEXP dsyMatrix_rcond(SEXP, SEXP, SEXP); SEXP dspMatrix_rcond(SEXP, SEXP, SEXP); SEXP dpoMatrix_rcond(SEXP, SEXP, SEXP); SEXP dppMatrix_rcond(SEXP, SEXP, SEXP); SEXP dtrMatrix_rcond(SEXP, SEXP); SEXP dtpMatrix_rcond(SEXP, SEXP); #endif /* MATRIX_KAPPA_H */ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/dense.h����������������������������������������������������������������������������������0000644�0001751�0000144�00000002227�14503222575�013602� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_DENSE_H #define MATRIX_DENSE_H #include SEXP dense_band(SEXP, const char *, int, int); SEXP R_dense_band(SEXP, SEXP, SEXP); SEXP dense_diag_get(SEXP, const char *, int); SEXP R_dense_diag_get(SEXP, SEXP); SEXP dense_diag_set(SEXP, const char *, SEXP, int); SEXP R_dense_diag_set(SEXP, SEXP); SEXP dense_transpose(SEXP, const char *); SEXP R_dense_transpose(SEXP); SEXP dense_force_symmetric(SEXP, const char *, char); SEXP R_dense_force_symmetric(SEXP, SEXP); SEXP dense_symmpart(SEXP, const char *); SEXP R_dense_symmpart(SEXP); SEXP dense_skewpart(SEXP, const char *); SEXP R_dense_skewpart(SEXP); int dense_is_symmetric(SEXP, const char *, int); SEXP R_dense_is_symmetric(SEXP, SEXP); int dense_is_triangular(SEXP, const char *, int); SEXP R_dense_is_triangular(SEXP, SEXP); int dense_is_diagonal(SEXP, const char *); SEXP R_dense_is_diagonal(SEXP); SEXP dense_marginsum(SEXP, const char *, int, int, int); SEXP R_dense_marginsum(SEXP, SEXP, SEXP, SEXP); SEXP dense_sum(SEXP, const char *, int); SEXP R_dense_sum(SEXP, SEXP); SEXP dense_prod(SEXP, const char *, int); SEXP R_dense_prod(SEXP, SEXP); #endif /* MATRIX_DENSE_H */ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/cs-etc.h���������������������������������������������������������������������������������0000644�0001751�0000144�00000005046�14552026002�013653� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_CS_ETC_H #define MATRIX_CS_ETC_H #include #include "SuiteSparse/CXSparse/Include/cs.h" #define MCS_PATTERN 0 #define MCS_REAL 1 #define MCS_COMPLEX 2 #define MCS_XTYPE_GET( ) Matrix_cs_xtype #define MCS_XTYPE_SET(_VALUE_) Matrix_cs_xtype = _VALUE_ extern int Matrix_cs_xtype; typedef struct Matrix_cs_sparse { int nzmax; int m; int n; int *p; int *i; void *x; /* (double *) or (double _Complex *) */ int nz; int xtype; /* Matrix-only */ } Matrix_cs; typedef struct Matrix_cs_symbolic { int *pinv; int *q; int *parent; int *cp; int *leftmost; int m2; double lnz; double unz; } Matrix_css; typedef struct Matrix_cs_numeric { Matrix_cs *L; /* (cs_di *) or (cs_ci *) */ Matrix_cs *U; /* (cs_di *) or (cs_ci *) */ int *pinv; double *B; } Matrix_csn; typedef struct Matrix_cs_dmperm_results { int *p; int *q; int *r; int *s; int nb; int rr[5]; int cc[5]; } Matrix_csd; Matrix_cs *M2CXS(SEXP, int); SEXP CXS2M(Matrix_cs *, int, char); /* Wrappers for the functions that we use at least once : */ Matrix_csd *Matrix_cs_dfree (Matrix_csd *); Matrix_csd *Matrix_cs_dmperm (const Matrix_cs *, int); int Matrix_cs_dropzeros (Matrix_cs *); void *Matrix_cs_free (void *); int Matrix_cs_happly (const Matrix_cs *, int, double, void *); int Matrix_cs_ipvec (const int *, const void *, void *, int); int Matrix_cs_lsolve (const Matrix_cs *, void *); Matrix_csn *Matrix_cs_lu (const Matrix_cs *, const Matrix_css *, double); int Matrix_cs_lusol (int, const Matrix_cs *, void *, double); Matrix_csn *Matrix_cs_nfree (Matrix_csn *); Matrix_cs *Matrix_cs_permute (const Matrix_cs *, const int *, const int *, int); int *Matrix_cs_pinv (const int *, int); int Matrix_cs_pvec (const int *, const void *, void *, int); Matrix_csn *Matrix_cs_qr (const Matrix_cs *, const Matrix_css *); int Matrix_cs_qrsol (int, const Matrix_cs *, void *); Matrix_css *Matrix_cs_sfree (Matrix_css *); Matrix_cs *Matrix_cs_spalloc (int, int, int, int, int); Matrix_cs *Matrix_cs_speye (int, int, int, int); Matrix_cs *Matrix_cs_spfree (Matrix_cs *); int Matrix_cs_sprealloc (Matrix_cs *, int); int Matrix_cs_spsolve (Matrix_cs *, const Matrix_cs *, int, int *, void *, const int *, int); Matrix_css *Matrix_cs_sqr (int, const Matrix_cs *, int); Matrix_cs *Matrix_cs_transpose (const Matrix_cs *, int); int Matrix_cs_usolve (const Matrix_cs *, void *); #endif /* MATRIX_CS_ETC_H */ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/cholmod-etc.c����������������������������������������������������������������������������0000644�0001751�0000144�00000025706�14552026002�014673� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Mdefines.h" #include "idz.h" #include "cholmod-etc.h" cholmod_common c ; cholmod_common cl; cholmod_factor *M2CHF(SEXP obj, int values) { cholmod_factor *L = (cholmod_factor *) R_alloc(1, sizeof(cholmod_factor)); memset(L, 0, sizeof(cholmod_factor)); SEXP dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)), type = PROTECT(GET_SLOT(obj, install("type"))), perm = PROTECT(GET_SLOT(obj, Matrix_permSym)), colcount = PROTECT(GET_SLOT(obj, install("colcount"))), x = PROTECT(getAttrib(obj, Matrix_xSym)); L->n = INTEGER(dim)[0]; L->minor = L->n; /* FIXME: could be wrong for obj <- new(...) */ L->ordering = INTEGER(type)[0]; if (L->ordering != CHOLMOD_NATURAL) L->Perm = INTEGER(perm); else { /* cholmod_check_factor allows L->Perm == NULL, but cholmod_copy_factor does not test, so it segfaults ... */ int n = (int) L->n, *Perm = (int *) R_alloc(L->n, sizeof(int)); for (int j = 0; j < n; ++j) Perm[j] = j; L->Perm = Perm; } L->ColCount = INTEGER(colcount); L->is_super = INTEGER(type)[2]; if (L->is_super) { L->is_ll = 1; L->is_monotonic = 1; SEXP super = PROTECT(GET_SLOT(obj, install("super"))), pi = PROTECT(GET_SLOT(obj, install("pi"))), px = PROTECT(GET_SLOT(obj, install("px"))), s = PROTECT(GET_SLOT(obj, install("s"))); L->super = INTEGER(super); L->pi = INTEGER(pi); L->px = INTEGER(px); L->s = INTEGER(s); L->nsuper = LENGTH(super) - 1; L->ssize = ((int *) L->pi)[L->nsuper]; L->xsize = ((int *) L->px)[L->nsuper]; L->maxcsize = INTEGER(type)[4]; L->maxesize = INTEGER(type)[5]; UNPROTECT(4); } else { L->is_ll = INTEGER(type)[1]; L->is_monotonic = INTEGER(type)[3]; if (values && x != R_NilValue) { SEXP p = PROTECT(GET_SLOT(obj, Matrix_pSym)), i = PROTECT(GET_SLOT(obj, Matrix_iSym)), nz = PROTECT(GET_SLOT(obj, install("nz"))), nxt = PROTECT(GET_SLOT(obj, install("nxt"))), prv = PROTECT(GET_SLOT(obj, install("prv"))); L->p = INTEGER(p); L->i = INTEGER(i); L->nz = INTEGER(nz); L->next = INTEGER(nxt); L->prev = INTEGER(prv); L->nzmax = ((int *) L->p)[L->n]; UNPROTECT(5); } } L->itype = CHOLMOD_INT; L->dtype = CHOLMOD_DOUBLE; if (values && x != R_NilValue) { switch (TYPEOF(x)) { case CPLXSXP: L->x = COMPLEX(x); L->xtype = CHOLMOD_COMPLEX; break; case REALSXP: L->x = REAL(x); L->xtype = CHOLMOD_REAL; break; default: ERROR_INVALID_TYPE(x, __func__); break; } } UNPROTECT(5); return L; } cholmod_sparse *M2CHS(SEXP obj, int values) { cholmod_sparse *A = (cholmod_sparse *) R_alloc(1, sizeof(cholmod_sparse)); memset(A, 0, sizeof(cholmod_sparse)); SEXP dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)), p = PROTECT(GET_SLOT(obj, Matrix_pSym)), i = PROTECT(GET_SLOT(obj, Matrix_iSym)), x = PROTECT(getAttrib(obj, Matrix_xSym)); A->nrow = INTEGER(dim)[0]; A->ncol = INTEGER(dim)[1]; A->p = INTEGER(p); A->i = INTEGER(i); A->nzmax = ((int *) A->p)[A->ncol]; A->stype = 0; A->itype = CHOLMOD_INT; A->xtype = CHOLMOD_PATTERN; A->dtype = CHOLMOD_DOUBLE; A->sorted = 1; A->packed = 1; if (values && x != R_NilValue) { switch (TYPEOF(x)) { case CPLXSXP: A->x = COMPLEX(x); A->xtype = CHOLMOD_COMPLEX; break; case REALSXP: A->x = REAL(x); A->xtype = CHOLMOD_REAL; break; default: ERROR_INVALID_TYPE(x, __func__); break; } } UNPROTECT(4); return A; } cholmod_dense *M2CHD(SEXP obj, int trans) { cholmod_dense *A = (cholmod_dense *) R_alloc(1, sizeof(cholmod_dense)); memset(A, 0, sizeof(cholmod_dense)); SEXP dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)), x = PROTECT(GET_SLOT(obj, Matrix_xSym)); int m = INTEGER(dim)[0], n = INTEGER(dim)[1]; A->nrow = ((trans) ? n : m); A->ncol = ((trans) ? m : n); A->nzmax = A->nrow * A->ncol; A->d = A->nrow; A->dtype = CHOLMOD_DOUBLE; switch (TYPEOF(x)) { case CPLXSXP: { Rcomplex *px = COMPLEX(x); if (!trans) A->x = px; else { Rcomplex *py = R_Calloc(A->nzmax, Rcomplex); ztranspose2(py, px, m, n); A->x = py; /* NB: caller must do R_Free(A->x) */ } A->xtype = CHOLMOD_COMPLEX; break; } case REALSXP: { double *px = REAL(x); if (!trans) A->x = px; else { double *py = R_Calloc(A->nzmax, double); dtranspose2(py, px, m, n); A->x = py; /* NB: caller must do R_Free(A->x) */ } A->xtype = CHOLMOD_REAL; break; } default: ERROR_INVALID_TYPE(x, __func__); break; } UNPROTECT(2); return A; } SEXP CHF2M(cholmod_factor *L, int values) { if (L->itype != CHOLMOD_INT) error(_("wrong '%s'"), "itype"); if (values && L->xtype != CHOLMOD_REAL && L->xtype != CHOLMOD_COMPLEX) error(_("wrong '%s'"), "xtype"); if (values && L->dtype != CHOLMOD_DOUBLE) error(_("wrong '%s'"), "dtype"); if (L->n > INT_MAX) error(_("dimensions cannot exceed %s"), "2^31-1"); if (L->super) { if (L->maxcsize > INT_MAX) error(_("'%s' would overflow type \"%s\""), "maxcsize", "integer"); } else { if (L->n == INT_MAX) error(_("n+1 would overflow type \"%s\""), "integer"); } if (L->minor < L->n) { if (L->is_ll) error(_("leading principal minor of order %d is not positive"), (int) L->minor + 1); else error(_("leading principal minor of order %d is zero"), (int) L->minor + 1); } char cl[] = ".CHM....."; cl[0] = (!values) ? 'n' : ((L->xtype == CHOLMOD_COMPLEX) ? 'z' : 'd'); memcpy(cl + 4, (L->is_super) ? "super" : "simpl", 5); SEXP obj = PROTECT(newObject(cl)), dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)); INTEGER(dim)[0] = INTEGER(dim)[1] = (int) L->n; if (L->ordering != CHOLMOD_NATURAL) { SEXP perm = PROTECT(allocVector(INTSXP, L->n)); Matrix_memcpy(INTEGER(perm), L->Perm, L->n, sizeof(int)); SET_SLOT(obj, Matrix_permSym, perm); UNPROTECT(1); } SEXP type = PROTECT(allocVector(INTSXP, 6)), colcount = PROTECT(allocVector(INTSXP, L->n)); INTEGER(type)[0] = L->ordering; INTEGER(type)[1] = (L->is_super) ? 1 : L->is_ll; INTEGER(type)[2] = (L->is_super) ? 1 : 0; INTEGER(type)[3] = (L->is_super) ? 1 : L->is_monotonic; INTEGER(type)[4] = (L->is_super) ? (int) L->maxcsize : 0; INTEGER(type)[5] = (L->is_super) ? (int) L->maxesize : 0; Matrix_memcpy(INTEGER(colcount), L->ColCount, L->n, sizeof(int)); SET_SLOT(obj, install("type"), type); SET_SLOT(obj, install("colcount"), colcount); if (L->is_super) { SEXP super = PROTECT(allocVector(INTSXP, L->nsuper + 1)), pi = PROTECT(allocVector(INTSXP, L->nsuper + 1)), px = PROTECT(allocVector(INTSXP, L->nsuper + 1)), s = PROTECT(allocVector(INTSXP, L->ssize)); Matrix_memcpy(INTEGER(super), L->super, L->nsuper + 1, sizeof(int)); Matrix_memcpy(INTEGER(pi), L->pi, L->nsuper + 1, sizeof(int)); Matrix_memcpy(INTEGER(px), L->px, L->nsuper + 1, sizeof(int)); Matrix_memcpy(INTEGER(s), L->s, L->ssize, sizeof(int)); SET_SLOT(obj, install("super"), super); SET_SLOT(obj, install("pi"), pi); SET_SLOT(obj, install("px"), px); SET_SLOT(obj, install("s"), s); UNPROTECT(4); } else if (values) { SEXP p = PROTECT(allocVector(INTSXP, L->n + 1)), i = PROTECT(allocVector(INTSXP, L->nzmax)), nz = PROTECT(allocVector(INTSXP, L->n)), nxt = PROTECT(allocVector(INTSXP, L->n + 2)), prv = PROTECT(allocVector(INTSXP, L->n + 2)); Matrix_memcpy(INTEGER(p), L->p, L->n + 1, sizeof(int)); Matrix_memcpy(INTEGER(i), L->i, L->nzmax, sizeof(int)); Matrix_memcpy(INTEGER(nz), L->nz, L->n, sizeof(int)); Matrix_memcpy(INTEGER(nxt), L->next, L->n + 2, sizeof(int)); Matrix_memcpy(INTEGER(prv), L->prev, L->n + 2, sizeof(int)); SET_SLOT(obj, Matrix_pSym, p); SET_SLOT(obj, Matrix_iSym, i); SET_SLOT(obj, install("nz"), nz); SET_SLOT(obj, install("nxt"), nxt); SET_SLOT(obj, install("prv"), prv); UNPROTECT(5); } if (values) { SEXP x; R_xlen_t nx = (R_xlen_t) ((L->is_super) ? L->xsize : L->nzmax); if (L->xtype == CHOLMOD_COMPLEX) { PROTECT(x = allocVector(CPLXSXP, nx)); Matrix_memcpy(COMPLEX(x), L->x, nx, sizeof(Rcomplex)); } else { PROTECT(x = allocVector(REALSXP, nx)); Matrix_memcpy(REAL(x), L->x, nx, sizeof(double)); } SET_SLOT(obj, Matrix_xSym, x); UNPROTECT(1); } UNPROTECT(4); return obj; } SEXP CHS2M(cholmod_sparse *A, int values, char shape) { cholmod_sparse *A_ = A; if (A->itype != CHOLMOD_INT) error(_("wrong '%s'"), "itype"); if (values && A->xtype != CHOLMOD_REAL && A->xtype != CHOLMOD_COMPLEX) error(_("wrong '%s'"), "xtype"); if (values && A->dtype != CHOLMOD_DOUBLE) error(_("wrong '%s'"), "dtype"); if (A->nrow > INT_MAX || A->ncol > INT_MAX) error(_("dimensions cannot exceed %s"), "2^31-1"); if (!A->sorted) cholmod_sort(A, &c); if (!A->packed || A->stype != 0) A = cholmod_copy(A, A->stype, 1, &c); char cl[] = "..CMatrix"; cl[0] = (!values) ? 'n' : ((A->xtype == CHOLMOD_COMPLEX) ? 'z' : 'd'); cl[1] = shape; int m = (int) A->nrow, n = (int) A->ncol, nnz = ((int *) A->p)[A->ncol]; R_xlen_t n1a = (R_xlen_t) n + 1; SEXP obj = PROTECT(newObject(cl)), dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)), p = PROTECT(allocVector(INTSXP, n1a)), i = PROTECT(allocVector(INTSXP, nnz)); INTEGER(dim)[0] = m; INTEGER(dim)[1] = n; Matrix_memcpy(INTEGER(p), A->p, n1a, sizeof(int)); Matrix_memcpy(INTEGER(i), A->i, nnz, sizeof(int)); SET_SLOT(obj, Matrix_pSym, p); SET_SLOT(obj, Matrix_iSym, i); if (values) { SEXP x; if (A->xtype == CHOLMOD_COMPLEX) { PROTECT(x = allocVector(CPLXSXP, nnz)); Matrix_memcpy(COMPLEX(x), A->x, nnz, sizeof(Rcomplex)); } else { PROTECT(x = allocVector(REALSXP, nnz)); Matrix_memcpy(REAL(x), A->x, nnz, sizeof(double)); } SET_SLOT(obj, Matrix_xSym, x); UNPROTECT(1); } if (A != A_) cholmod_free_sparse(&A, &c); UNPROTECT(4); return obj; } SEXP CHD2M(cholmod_dense *A, int trans, char shape) { if (A->xtype != CHOLMOD_REAL && A->xtype != CHOLMOD_COMPLEX) error(_("wrong '%s'"), "xtype"); if (A->dtype != CHOLMOD_DOUBLE) error(_("wrong '%s'"), "dtype"); if (A->d != A->nrow) /* MJ: currently no need to support this case */ error(_("leading dimension not equal to number of rows")); if (A->nrow > INT_MAX || A->ncol > INT_MAX) error(_("dimensions cannot exceed %s"), "2^31-1"); int m = (int) A->nrow, n = (int) A->ncol; if ((Matrix_int_fast64_t) m * n > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); char cl[] = "...Matrix"; cl[0] = (A->xtype == CHOLMOD_COMPLEX) ? 'z' : 'd'; cl[1] = shape; cl[2] = (shape == 'g') ? 'e' : ((shape == 's') ? 'y' : ((shape == 'p') ? 'o' : 'r')); SEXP obj = PROTECT(newObject(cl)), dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)); INTEGER(dim)[0] = (trans) ? n : m; INTEGER(dim)[1] = (trans) ? m : n; SEXP x; if (A->xtype == CHOLMOD_COMPLEX) { PROTECT(x = allocVector(CPLXSXP, (R_xlen_t) m * n)); Rcomplex *px = COMPLEX(x), *py = (Rcomplex *) A->x; if (!trans) Matrix_memcpy(px, py, (R_xlen_t) m * n, sizeof(Rcomplex)); else ztranspose2(px, py, m, n); } else { PROTECT(x = allocVector(REALSXP, (R_xlen_t) m * n)); double *px = REAL(x), *py = (double *) A->x; if (!trans) Matrix_memcpy(px, py, (R_xlen_t) m * n, sizeof(double)); else dtranspose2(px, py, m, n); } SET_SLOT(obj, Matrix_xSym, x); UNPROTECT(3); return obj; } ����������������������������������������������������������Matrix/src/solve.h����������������������������������������������������������������������������������0000644�0001751�0000144�00000001032�14504476335�013633� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_SOLVE_H #define MATRIX_SOLVE_H #include SEXP denseLU_solve(SEXP, SEXP); SEXP BunchKaufman_solve(SEXP, SEXP); SEXP Cholesky_solve(SEXP, SEXP); SEXP dtrMatrix_solve(SEXP, SEXP); SEXP sparseLU_solve(SEXP, SEXP, SEXP); #if 0 /* MJ: we use 'sparseQR_matmult' instead */ SEXP sparseQR_solve(SEXP, SEXP, SEXP); #endif SEXP CHMfactor_solve(SEXP, SEXP, SEXP, SEXP); SEXP dtCMatrix_solve(SEXP, SEXP, SEXP); SEXP sparseQR_matmult(SEXP, SEXP, SEXP, SEXP, SEXP); #endif /* MATRIX_SOLVE_H */ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/determinant.h����������������������������������������������������������������������������0000644�0001751�0000144�00000000577�14505043347�015024� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_DETERMINANT_H #define MATRIX_DETERMINANT_H #include SEXP denseLU_determinant(SEXP, SEXP); SEXP BunchKaufman_determinant(SEXP, SEXP); SEXP Cholesky_determinant(SEXP, SEXP); SEXP sparseLU_determinant(SEXP, SEXP); SEXP sparseQR_determinant(SEXP, SEXP); SEXP CHMfactor_determinant(SEXP, SEXP, SEXP); #endif /* MATRIX_DETERMINANT_H */ ���������������������������������������������������������������������������������������������������������������������������������Matrix/src/solve.c����������������������������������������������������������������������������������0000644�0001751�0000144�00000071012�14567652435�013641� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Lapack-etc.h" #include "cs-etc.h" #include "cholmod-etc.h" #include "Mdefines.h" #include "idz.h" #include "solve.h" static void solveDN(SEXP rdn, SEXP adn, SEXP bdn) { SEXP s; if (!isNull(s = VECTOR_ELT(adn, 1))) SET_VECTOR_ELT(rdn, 0, s); if (!isNull(s = VECTOR_ELT(bdn, 1))) SET_VECTOR_ELT(rdn, 1, s); PROTECT(adn = getAttrib(adn, R_NamesSymbol)); PROTECT(bdn = getAttrib(bdn, R_NamesSymbol)); if(!isNull(adn) || !isNull(bdn)) { PROTECT(s = allocVector(STRSXP, 2)); if (!isNull(adn)) SET_STRING_ELT(s, 0, STRING_ELT(adn, 1)); if (!isNull(bdn)) SET_STRING_ELT(s, 1, STRING_ELT(bdn, 1)); setAttrib(rdn, R_NamesSymbol, s); UNPROTECT(1); } UNPROTECT(2); return; } SEXP denseLU_solve(SEXP a, SEXP b) { #define SOLVE_START \ SEXP adim = GET_SLOT(a, Matrix_DimSym); \ int *padim = INTEGER(adim), m = padim[0], n = padim[1]; \ if (m != n) \ error(_("'%s' is not square"), "a"); \ if (!isNull(b)) { \ SEXP bdim = GET_SLOT(b, Matrix_DimSym); \ int *pbdim = INTEGER(bdim); \ if (pbdim[0] != m) \ error(_("dimensions of '%s' and '%s' are inconsistent"), \ "a", "b"); \ n = pbdim[1]; \ } #define SOLVE_FINISH \ SEXP rdimnames = PROTECT(GET_SLOT(r, Matrix_DimNamesSym)), \ adimnames = PROTECT(GET_SLOT(a, Matrix_DimNamesSym)); \ if (isNull(b)) \ revDN(rdimnames, adimnames); \ else { \ SEXP bdimnames = PROTECT(GET_SLOT(b, Matrix_DimNamesSym)); \ solveDN(rdimnames, adimnames, bdimnames); \ UNPROTECT(1); /* bdimnames */ \ } \ UNPROTECT(2); /* adimnames, rdimnames */ SOLVE_START; SEXP ax = PROTECT(GET_SLOT(a, Matrix_xSym)); char rcl[] = ".geMatrix"; rcl[0] = (TYPEOF(ax) == CPLXSXP) ? 'z' : 'd'; SEXP r = PROTECT(newObject(rcl)); SEXP rdim = GET_SLOT(r, Matrix_DimSym); int *prdim = INTEGER(rdim); prdim[0] = m; prdim[1] = n; if (m > 0) { SEXP apivot = PROTECT(GET_SLOT(a, Matrix_permSym)), rx; int info; if (isNull(b)) { rx = duplicate(ax); PROTECT(rx); int lwork = -1; #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(ax) == CPLXSXP) { Rcomplex work0, *work = &work0; F77_CALL(zgetri)(&m, COMPLEX(rx), &m, INTEGER(apivot), work, &lwork, &info); ERROR_LAPACK_1(zgetri, info); lwork = (int) work0.r; work = (Rcomplex *) R_alloc((size_t) lwork, sizeof(Rcomplex)); F77_CALL(zgetri)(&m, COMPLEX(rx), &m, INTEGER(apivot), work, &lwork, &info); ERROR_LAPACK_2(zgetri, info, 2, U); } else { #endif double work0, *work = &work0; F77_CALL(dgetri)(&m, REAL(rx), &m, INTEGER(apivot), work, &lwork, &info); ERROR_LAPACK_1(dgetri, info); lwork = (int) work0; work = (double *) R_alloc((size_t) lwork, sizeof(double )); F77_CALL(dgetri)(&m, REAL(rx), &m, INTEGER(apivot), work, &lwork, &info); ERROR_LAPACK_2(dgetri, info, 2, U); #ifdef MATRIX_ENABLE_ZMATRIX } #endif } else { SEXP bx = PROTECT(GET_SLOT(b, Matrix_xSym)); rx = duplicate(bx); UNPROTECT(1); /* bx */ PROTECT(rx); #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(ax) == CPLXSXP) { F77_CALL(zgetrs)("N", &m, &n, COMPLEX(ax), &m, INTEGER(apivot), COMPLEX(rx), &m, &info FCONE); ERROR_LAPACK_1(zgetrs, info); } else { #endif F77_CALL(dgetrs)("N", &m, &n, REAL(ax), &m, INTEGER(apivot), REAL(rx), &m, &info FCONE); ERROR_LAPACK_1(dgetrs, info); #ifdef MATRIX_ENABLE_ZMATRIX } #endif } SET_SLOT(r, Matrix_xSym, rx); UNPROTECT(2); /* rx, apivot */ } SOLVE_FINISH; UNPROTECT(2); /* r, ax */ return r; } SEXP BunchKaufman_solve(SEXP a, SEXP b) { SOLVE_START; SEXP ax = PROTECT(GET_SLOT(a, Matrix_xSym)); int unpacked = (Matrix_int_fast64_t) m * m <= R_XLEN_T_MAX && XLENGTH(ax) == (R_xlen_t) m * m; char rcl[] = "...Matrix"; rcl[0] = (TYPEOF(ax) == CPLXSXP) ? 'z' : 'd'; if (!isNull(b)) { rcl[1] = 'g'; rcl[2] = 'e'; } else { rcl[1] = 's'; rcl[2] = (unpacked) ? 'y' : 'p'; } SEXP r = PROTECT(newObject(rcl)); SEXP rdim = GET_SLOT(r, Matrix_DimSym); int *prdim = INTEGER(rdim); prdim[0] = m; prdim[1] = n; SEXP auplo = GET_SLOT(a, Matrix_uploSym); char aul = CHAR(STRING_ELT(auplo, 0))[0]; if (isNull(b) && aul != 'U') { PROTECT(auplo); SET_SLOT(r, Matrix_uploSym, auplo); UNPROTECT(1); /* auplo */ } if (m > 0) { SEXP apivot = PROTECT(GET_SLOT(a, Matrix_permSym)), rx; int info; if (isNull(b)) { rx = duplicate(ax); PROTECT(rx); #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(ax) == CPLXSXP) { Rcomplex *work = (Rcomplex *) R_alloc((size_t) m, sizeof(Rcomplex)); if (unpacked) { F77_CALL(zsytri)(&aul, &m, COMPLEX(rx), &m, INTEGER(apivot), work, &info FCONE); ERROR_LAPACK_2(zsytri, info, 2, D); } else { F77_CALL(zsptri)(&aul, &m, COMPLEX(rx), INTEGER(apivot), work, &info FCONE); ERROR_LAPACK_2(zsptri, info, 2, D); } } else { #endif double *work = (double *) R_alloc((size_t) m, sizeof(double )); if (unpacked) { F77_CALL(dsytri)(&aul, &m, REAL(rx), &m, INTEGER(apivot), work, &info FCONE); ERROR_LAPACK_2(dsytri, info, 2, D); } else { F77_CALL(dsptri)(&aul, &m, REAL(rx), INTEGER(apivot), work, &info FCONE); ERROR_LAPACK_2(dsptri, info, 2, D); } #ifdef MATRIX_ENABLE_ZMATRIX } #endif } else { SEXP bx = PROTECT(GET_SLOT(b, Matrix_xSym)); rx = duplicate(bx); UNPROTECT(1); /* bx */ PROTECT(rx); #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(ax) == CPLXSXP) { if (unpacked) { F77_CALL(zsytrs)(&aul, &m, &n, COMPLEX(ax), &m, INTEGER(apivot), COMPLEX(rx), &m, &info FCONE); ERROR_LAPACK_1(zsytrs, info); } else { F77_CALL(zsptrs)(&aul, &m, &n, COMPLEX(ax), INTEGER(apivot), COMPLEX(rx), &m, &info FCONE); ERROR_LAPACK_1(zsptrs, info); } } else { #endif if (unpacked) { F77_CALL(dsytrs)(&aul, &m, &n, REAL(ax), &m, INTEGER(apivot), REAL(rx), &m, &info FCONE); ERROR_LAPACK_1(dsytrs, info); } else { F77_CALL(dsptrs)(&aul, &m, &n, REAL(ax), INTEGER(apivot), REAL(rx), &m, &info FCONE); ERROR_LAPACK_1(dsptrs, info); } #ifdef MATRIX_ENABLE_ZMATRIX } #endif } SET_SLOT(r, Matrix_xSym, rx); UNPROTECT(2); /* rx, apivot */ } SOLVE_FINISH; UNPROTECT(2); /* r, ax */ return r; } SEXP Cholesky_solve(SEXP a, SEXP b) { SOLVE_START; SEXP ax = PROTECT(GET_SLOT(a, Matrix_xSym)); int unpacked = (Matrix_int_fast64_t) m * m <= R_XLEN_T_MAX && XLENGTH(ax) == (R_xlen_t) m * m; char rcl[] = "...Matrix"; rcl[0] = (TYPEOF(ax) == CPLXSXP) ? 'z' : 'd'; if (!isNull(b)) { rcl[1] = 'g'; rcl[2] = 'e'; } else { rcl[1] = 'p'; rcl[2] = (unpacked) ? 'o' : 'p'; } SEXP r = PROTECT(newObject(rcl)); SEXP rdim = GET_SLOT(r, Matrix_DimSym); int *prdim = INTEGER(rdim); prdim[0] = m; prdim[1] = n; SEXP auplo = GET_SLOT(a, Matrix_uploSym); char aul = CHAR(STRING_ELT(auplo, 0))[0]; if (isNull(b) && aul != 'U') { PROTECT(auplo); SET_SLOT(r, Matrix_uploSym, auplo); UNPROTECT(1); /* auplo */ } if (m > 0) { SEXP rx, aperm = PROTECT(getAttrib(a, Matrix_permSym)); int info, pivoted = TYPEOF(aperm) == INTSXP && LENGTH(aperm) > 0; if (isNull(b)) { rx = duplicate(ax); PROTECT(rx); #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(ax) == CPLXSXP) { if (unpacked) { F77_CALL(zpotri)(&aul, &m, COMPLEX(rx), &m, &info FCONE); ERROR_LAPACK_2(zpotri, info, 2, L); if (pivoted) zsymperm2(COMPLEX(rx), n, aul, INTEGER(aperm), 1, 1); } else { F77_CALL(zpptri)(&aul, &m, COMPLEX(rx), &info FCONE); ERROR_LAPACK_2(zpptri, info, 2, L); if (pivoted) { /* FIXME: zsymperm2 supporting packed matrices */ double *work; size_t lwork = (size_t) n * n; Matrix_Calloc(work, lwork, Rcomplex); zunpack1 (work, COMPLEX(rx), n, aul, 'N'); zsymperm2(work, n, aul, INTEGER(aperm), 1, 1); zpack2 (COMPLEX(rx), work, n, aul, 'N'); Matrix_Free(work, lwork); } } } else { #endif if (unpacked) { F77_CALL(dpotri)(&aul, &m, REAL(rx), &m, &info FCONE); ERROR_LAPACK_2(dpotri, info, 2, L); if (pivoted) dsymperm2( REAL(rx), n, aul, INTEGER(aperm), 1, 1); } else { F77_CALL(dpptri)(&aul, &m, REAL(rx), &info FCONE); ERROR_LAPACK_2(dpptri, info, 2, L); if (pivoted) { /* FIXME: dsymperm2 supporting packed matrices */ double *work; size_t lwork = (size_t) n * n; Matrix_Calloc(work, lwork, double); dunpack1 (work, REAL(rx), n, aul, 'N'); dsymperm2(work, n, aul, INTEGER(aperm), 1, 1); dpack2 ( REAL(rx), work, n, aul, 'N'); Matrix_Free(work, lwork); } } #ifdef MATRIX_ENABLE_ZMATRIX } #endif } else { SEXP bx = PROTECT(GET_SLOT(b, Matrix_xSym)); rx = duplicate(bx); UNPROTECT(1); /* bx */ PROTECT(rx); #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(ax) == CPLXSXP) { if (pivoted) zrowperm2(COMPLEX(rx), m, n, INTEGER(aperm), 1, 0); if (unpacked) { F77_CALL(zpotrs)(&aul, &m, &n, COMPLEX(ax), &m, COMPLEX(rx), &m, &info FCONE); ERROR_LAPACK_1(zpotrs, info); } else { F77_CALL(zpptrs)(&aul, &m, &n, COMPLEX(ax), COMPLEX(rx), &m, &info FCONE); ERROR_LAPACK_1(zpptrs, info); } if (pivoted) zrowperm2(COMPLEX(rx), m, n, INTEGER(aperm), 1, 1); } else { #endif if (pivoted) drowperm2( REAL(rx), m, n, INTEGER(aperm), 1, 0); if (unpacked) { F77_CALL(dpotrs)(&aul, &m, &n, REAL(ax), &m, REAL(rx), &m, &info FCONE); ERROR_LAPACK_1(dpotrs, info); } else { F77_CALL(dpptrs)(&aul, &m, &n, REAL(ax), REAL(rx), &m, &info FCONE); ERROR_LAPACK_1(dpptrs, info); } if (pivoted) drowperm2( REAL(rx), m, n, INTEGER(aperm), 1, 1); #ifdef MATRIX_ENABLE_ZMATRIX } #endif } SET_SLOT(r, Matrix_xSym, rx); UNPROTECT(2); /* rx, aperm */ } SOLVE_FINISH; UNPROTECT(2); /* r, ax */ return r; } SEXP dtrMatrix_solve(SEXP a, SEXP b) { SOLVE_START; SEXP ax = PROTECT(GET_SLOT(a, Matrix_xSym)); int unpacked = (Matrix_int_fast64_t) m * m <= R_XLEN_T_MAX && XLENGTH(ax) == (R_xlen_t) m * m; char rcl[] = "...Matrix"; rcl[0] = (TYPEOF(ax) == CPLXSXP) ? 'z' : 'd'; if (!isNull(b)) { rcl[1] = 'g'; rcl[2] = 'e'; } else { rcl[1] = 't'; rcl[2] = (unpacked) ? 'r' : 'p'; } SEXP r = PROTECT(newObject(rcl)); SEXP rdim = GET_SLOT(r, Matrix_DimSym); int *prdim = INTEGER(rdim); prdim[0] = m; prdim[1] = n; SEXP auplo = GET_SLOT(a, Matrix_uploSym); char aul = CHAR(STRING_ELT(auplo, 0))[0]; if (isNull(b) && aul != 'U') { PROTECT(auplo); SET_SLOT(r, Matrix_uploSym, auplo); UNPROTECT(1); /* auplo */ } SEXP adiag = GET_SLOT(a, Matrix_diagSym); char adi = CHAR(STRING_ELT(adiag, 0))[0]; if (isNull(b) && adi != 'N') { PROTECT(adiag); SET_SLOT(r, Matrix_diagSym, adiag); UNPROTECT(1); /* adiag */ } if (m > 0) { SEXP rx; int info; if (isNull(b)) { rx = duplicate(ax); PROTECT(rx); #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(ax) == CPLXSXP) { if (unpacked) { F77_CALL(ztrtri)(&aul, &adi, &m, COMPLEX(rx), &m, &info FCONE FCONE); ERROR_LAPACK_2(ztrtri, info, 2, A); } else { F77_CALL(ztptri)(&aul, &adi, &m, COMPLEX(rx), &info FCONE FCONE); ERROR_LAPACK_2(ztptri, info, 2, A); } } else { #endif if (unpacked) { F77_CALL(dtrtri)(&aul, &adi, &m, REAL(rx), &m, &info FCONE FCONE); ERROR_LAPACK_2(dtrtri, info, 2, A); } else { F77_CALL(dtptri)(&aul, &adi, &m, REAL(rx), &info FCONE FCONE); ERROR_LAPACK_2(dtptri, info, 2, A); } #ifdef MATRIX_ENABLE_ZMATRIX } #endif } else { SEXP bx = PROTECT(GET_SLOT(b, Matrix_xSym)); rx = duplicate(bx); UNPROTECT(1); /* bx */ PROTECT(rx); #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(ax) == CPLXSXP) { if (unpacked) { F77_CALL(ztrtrs)(&aul, "N", &adi, &m, &n, COMPLEX(ax), &m, COMPLEX(rx), &m, &info FCONE FCONE FCONE); ERROR_LAPACK_1(ztrtrs, info); } else { F77_CALL(ztptrs)(&aul, "N", &adi, &m, &n, COMPLEX(ax), COMPLEX(rx), &m, &info FCONE FCONE FCONE); ERROR_LAPACK_1(ztptrs, info); } } else { #endif if (unpacked) { F77_CALL(dtrtrs)(&aul, "N", &adi, &m, &n, REAL(ax), &m, REAL(rx), &m, &info FCONE FCONE FCONE); ERROR_LAPACK_1(dtrtrs, info); } else { // https://bugs.r-project.org/show_bug.cgi?id=18534 F77_CALL(dtptrs)(&aul, "N", &adi, &m, &n, REAL(ax), REAL(rx), &m, &info # ifdef usePR18534fix FCONE FCONE FCONE); # else FCONE FCONE); # endif ERROR_LAPACK_1(dtptrs, info); } #ifdef MATRIX_ENABLE_ZMATRIX } #endif } SET_SLOT(r, Matrix_xSym, rx); UNPROTECT(1); /* rx */ } SOLVE_FINISH; UNPROTECT(2); /* r, ax */ return r; } #define IF_COMPLEX(_IF_, _ELSE_) \ ((MCS_XTYPE_GET() == MCS_COMPLEX) ? (_IF_) : (_ELSE_)) SEXP sparseLU_solve(SEXP a, SEXP b, SEXP sparse) { #define ERROR_SOLVE_OOM(_ACL_, _BCL_) \ error(_("%s(<%s>, <%s>) failed: out of memory"), "solve", _ACL_, _BCL_) SOLVE_START; SEXP r, aL = PROTECT(GET_SLOT(a, Matrix_LSym)), aU = PROTECT(GET_SLOT(a, Matrix_USym)), ap = PROTECT(GET_SLOT(a, Matrix_pSym)), aq = PROTECT(GET_SLOT(a, Matrix_qSym)); int i, j, *pap = (LENGTH(ap)) ? INTEGER(ap) : NULL, *paq = (LENGTH(aq)) ? INTEGER(aq) : NULL; Matrix_cs *L = M2CXS(aL, 1), *U = M2CXS(aU, 1); MCS_XTYPE_SET(L->xtype); if (!asLogical(sparse)) { char rcl[] = ".geMatrix"; rcl[0] = IF_COMPLEX('z', 'd'); PROTECT(r = newObject(rcl)); SEXP rdim = GET_SLOT(r, Matrix_DimSym); int *prdim = INTEGER(rdim); prdim[0] = m; prdim[1] = n; R_xlen_t mn = (R_xlen_t) m * n; SEXP rx = PROTECT(allocVector(IF_COMPLEX(CPLXSXP, REALSXP), mn)); if (isNull(b)) { #define SOLVE_DENSE_1(_CTYPE_, _PTR_, _ONE_) \ do { \ _CTYPE_ *prx = _PTR_(rx), \ *work = (_CTYPE_ *) R_alloc((size_t) m, sizeof(_CTYPE_)); \ Matrix_memset(prx, 0, mn, sizeof(_CTYPE_)); \ for (j = 0; j < n; ++j) { \ prx[j] = _ONE_; \ Matrix_cs_pvec(pap, prx, work, m); \ Matrix_cs_lsolve(L, work); \ Matrix_cs_usolve(U, work); \ Matrix_cs_ipvec(paq, work, prx, m); \ prx += m; \ } \ } while (0) #ifdef MATRIX_ENABLE_ZMATRIX if (MCS_XTYPE_GET() == MCS_COMPLEX) SOLVE_DENSE_1(Rcomplex, COMPLEX, Matrix_zone); else #endif SOLVE_DENSE_1(double, REAL, 1.0); #undef SOLVE_DENSE_1 } else { SEXP bx = PROTECT(GET_SLOT(b, Matrix_xSym)); #define SOLVE_DENSE_2(_CTYPE_, _PTR_) \ do { \ _CTYPE_ *prx = _PTR_(rx), *pbx = _PTR_(bx), \ *work = (_CTYPE_ *) R_alloc((size_t) m, sizeof(_CTYPE_)); \ for (j = 0; j < n; ++j) { \ Matrix_cs_pvec(pap, pbx, work, m); \ Matrix_cs_lsolve(L, work); \ Matrix_cs_usolve(U, work); \ Matrix_cs_ipvec(paq, work, prx, m); \ prx += m; \ pbx += m; \ } \ } while (0) #ifdef MATRIX_ENABLE_ZMATRIX if (MCS_XTYPE_GET() == MCS_COMPLEX) SOLVE_DENSE_2(Rcomplex, COMPLEX); else #endif SOLVE_DENSE_2(double, REAL); #undef SOLVE_DENSE_2 UNPROTECT(1); /* bx */ } SET_SLOT(r, Matrix_xSym, rx); UNPROTECT(1); /* rx */ } else { Matrix_cs *B = NULL, *X = NULL; if (isNull(b)) { B = Matrix_cs_speye(m, m, 1, 0); if (B && pap) for (i = 0; i < m; ++i) B->i[pap[i]] = i; } else { B = M2CXS(b, 1); if (B && pap) { int *papinv = Matrix_cs_pinv(pap, m); if (!papinv) ERROR_SOLVE_OOM("sparseLU", ".gCMatrix"); B = Matrix_cs_permute(B, papinv, NULL, 1); papinv = Matrix_cs_free(papinv); } } if (!B) ERROR_SOLVE_OOM("sparseLU", ".gCMatrix"); int Bfr = isNull(b) || pap; int k, top, nz, nzmax, *iwork = (int *) R_alloc((size_t) 2 * m, sizeof(int)); #define SOLVE_SPARSE_TRIANGULAR(_CTYPE_, _A_, _ALO_, _BFR_, _ACL_, _BCL_) \ do { \ X = Matrix_cs_spalloc(m, n, B->nzmax, 1, 0); \ if (!X) { \ if (_BFR_) \ B = Matrix_cs_spfree(B); \ ERROR_SOLVE_OOM(_ACL_, _BCL_); \ } \ _CTYPE_ *X__x = (_CTYPE_ *) X->x; \ X->p[0] = nz = 0; \ nzmax = X->nzmax; \ for (j = 0, k = 0; j < n; ++j) { \ top = Matrix_cs_spsolve(_A_, B, j, iwork, work, NULL, _ALO_); \ if (m - top > INT_MAX - nz) { \ if (_BFR_) \ B = Matrix_cs_spfree(B); \ X = Matrix_cs_spfree(X); \ error(_("attempt to construct %s with more than %s nonzero elements"), \ "sparseMatrix", "2^31-1"); \ } \ nz += m - top; \ if (nz > nzmax) { \ nzmax = (nz <= INT_MAX / 2) ? 2 * nz : INT_MAX; \ if (!Matrix_cs_sprealloc(X, nzmax)) { \ if (_BFR_) \ B = Matrix_cs_spfree(B); \ X = Matrix_cs_spfree(X); \ ERROR_SOLVE_OOM(_ACL_, _BCL_); \ } \ X__x = (_CTYPE_ *) X->x; \ } \ X->p[j + 1] = nz; \ if (_ALO_) { \ for (i = top; i < m; ++i) { \ X->i[k] = iwork[i] ; \ X__x[k] = work[iwork[i]]; \ ++k; \ } \ } else { \ for (i = m - 1; i >= top; --i) { \ X->i[k] = iwork[i] ; \ X__x[k] = work[iwork[i]]; \ ++k; \ } \ } \ } \ if (_BFR_) \ B = Matrix_cs_spfree(B); \ B = X; \ } while (0) #define SOLVE_SPARSE(_CTYPE_) \ do { \ _CTYPE_ *work = (_CTYPE_ *) R_alloc((size_t) m, sizeof(_CTYPE_)); \ SOLVE_SPARSE_TRIANGULAR(_CTYPE_, L, 1, Bfr, \ "sparseLU", ".gCMatrix"); \ SOLVE_SPARSE_TRIANGULAR(_CTYPE_, U, 0, 1, \ "sparseLU", ".gCMatrix"); \ } while (0) #ifdef MATRIX_ENABLE_ZMATRIX if (MCS_XTYPE_GET() == MCS_COMPLEX) SOLVE_SPARSE(Rcomplex); else #endif SOLVE_SPARSE(double); #undef SOLVE_SPARSE if (paq) { X = Matrix_cs_permute(B, paq, NULL, 1); B = Matrix_cs_spfree(B); if (!X) ERROR_SOLVE_OOM("sparseLU", ".gCMatrix"); B = X; } /* Drop zeros from B and sort it : */ Matrix_cs_dropzeros(B); X = Matrix_cs_transpose(B, 1); B = Matrix_cs_spfree(B); if (!X) ERROR_SOLVE_OOM("sparseLU", ".gCMatrix"); B = Matrix_cs_transpose(X, 1); X = Matrix_cs_spfree(X); if (!B) ERROR_SOLVE_OOM("sparseLU", ".gCMatrix"); PROTECT(r = CXS2M(B, 1, 'g')); B = Matrix_cs_spfree(B); } SOLVE_FINISH; UNPROTECT(5); /* r, aq, ap, aU, aL */ return r; } static int strmatch(const char *x, const char **valid) { int i = 0; while (valid[i][0] != '\0') { if (strcmp(x, valid[i]) == 0) return i; ++i; } return -1; } SEXP CHMfactor_solve(SEXP a, SEXP b, SEXP sparse, SEXP system) { static const char *valid[] = { "A", "LDLt", "LD", "DLt", "L", "Lt", "D", "P", "Pt", "" }; int ivalid = -1; if (TYPEOF(system) != STRSXP || LENGTH(system) < 1 || (system = STRING_ELT(system, 0)) == NA_STRING || (ivalid = strmatch(CHAR(system), valid)) < 0) error(_("invalid '%s' to '%s'"), "system", __func__); SOLVE_START; SEXP r; int j; cholmod_factor *L = M2CHF(a, 1); if (!asLogical(sparse)) { cholmod_dense *B = NULL, *X = NULL; if (isNull(b)) { B = cholmod_allocate_dense(m, n, m, L->xtype, &c); if (!B) ERROR_SOLVE_OOM("CHMfactor", ".geMatrix"); R_xlen_t m1a = (R_xlen_t) m + 1; #define EYE(_CTYPE_, _ONE_) \ do { \ _CTYPE_ *B__x = (_CTYPE_ *) B->x; \ Matrix_memset(B__x, 0, (R_xlen_t) m * n, sizeof(_CTYPE_)); \ for (j = 0; j < n; ++j) { \ *B__x = _ONE_; \ B__x += m1a; \ } \ } while (0) #ifdef MATRIX_ENABLE_ZMATRIX if (L->xtype == CHOLMOD_COMPLEX) EYE(Rcomplex, Matrix_zone); else #endif EYE(double, 1.0); #undef EYE X = cholmod_solve(ivalid, L, B, &c); cholmod_free_dense(&B, &c); if (!X) ERROR_SOLVE_OOM("CHMfactor", ".geMatrix"); PROTECT(r = CHD2M(X, 0, (ivalid < 2) ? 'p' : ((ivalid < 7) ? 't' : 'g'))); } else { B = M2CHD(b, 0); X = cholmod_solve(ivalid, L, B, &c); if (!X) ERROR_SOLVE_OOM("CHMfactor", ".geMatrix"); PROTECT(r = CHD2M(X, 0, 'g')); } cholmod_free_dense(&X, &c); } else { cholmod_sparse *B = NULL, *X = NULL; if (isNull(b)) { B = cholmod_speye(m, n, L->xtype, &c); if (!B) ERROR_SOLVE_OOM("CHMfactor", ".gCMatrix"); X = cholmod_spsolve(ivalid, L, B, &c); cholmod_free_sparse(&B, &c); if (X && ivalid < 7) { if (!X->sorted) cholmod_sort(X, &c); B = cholmod_copy(X, (ivalid == 2 || ivalid == 4) ? -1 : 1, 1, &c); cholmod_free_sparse(&X, &c); X = B; } if (!X) ERROR_SOLVE_OOM("CHMfactor", ".gCMatrix"); PROTECT(r = CHS2M(X, 1, (ivalid < 2) ? 's' : ((ivalid < 7) ? 't' : 'g'))); } else { B = M2CHS(b, 1); X = cholmod_spsolve(ivalid, L, B, &c); if (!X) ERROR_SOLVE_OOM("CHMfactor", ".gCMatrix"); PROTECT(r = CHS2M(X, 1, 'g')); } cholmod_free_sparse(&X, &c); } if (isNull(b) && (ivalid == 2 || ivalid == 4)) { SEXP uplo = PROTECT(mkString("L")); SET_SLOT(r, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } SOLVE_FINISH; UNPROTECT(1); /* r */ return r; } SEXP dtCMatrix_solve(SEXP a, SEXP b, SEXP sparse) { SOLVE_START; SEXP r, auplo = PROTECT(GET_SLOT(a, Matrix_uploSym)); char aul = *CHAR(STRING_ELT(auplo, 0)); int i, j; Matrix_cs *A = M2CXS(a, 1); MCS_XTYPE_SET(A->xtype); if (!asLogical(sparse)) { char rcl[] = "...Matrix"; rcl[0] = IF_COMPLEX('z', 'd'); rcl[1] = (isNull(b)) ? 't' : 'g'; rcl[2] = (isNull(b)) ? 'r' : 'e'; PROTECT(r = newObject(rcl)); SEXP rdim = GET_SLOT(r, Matrix_DimSym); int *prdim = INTEGER(rdim); prdim[0] = m; prdim[1] = n; R_xlen_t mn = (R_xlen_t) m * n; SEXP rx = PROTECT(allocVector(IF_COMPLEX(CPLXSXP, REALSXP), mn)); if (isNull(b)) { #define SOLVE_DENSE_1(_CTYPE_, _PTR_, _ONE_) \ do { \ _CTYPE_ *prx = _PTR_(rx); \ Matrix_memset(prx, 0, mn, sizeof(_CTYPE_)); \ for (j = 0; j < n; ++j) { \ prx[j] = _ONE_; \ if (aul == 'U') \ Matrix_cs_usolve(A, prx); \ else \ Matrix_cs_lsolve(A, prx); \ prx += m; \ } \ } while (0) #ifdef MATRIX_ENABLE_ZMATRIX if (MCS_XTYPE_GET() == MCS_COMPLEX) SOLVE_DENSE_1(Rcomplex, COMPLEX, Matrix_zone); else #endif SOLVE_DENSE_1(double, REAL, 1.0); #undef SOLVE_DENSE_1 } else { SEXP bx = PROTECT(GET_SLOT(b, Matrix_xSym)); #define SOLVE_DENSE_2(_CTYPE_, _PTR_) \ do { \ _CTYPE_ *prx = _PTR_(rx), *pbx = _PTR_(bx); \ Matrix_memcpy(prx, pbx, mn, sizeof(_CTYPE_)); \ for (j = 0; j < n; ++j) { \ if (aul == 'U') \ Matrix_cs_usolve(A, prx); \ else \ Matrix_cs_lsolve(A, prx); \ prx += m; \ } \ } while (0) #ifdef MATRIX_ENABLE_ZMATRIX if (MCS_XTYPE_GET() == MCS_COMPLEX) SOLVE_DENSE_2(Rcomplex, COMPLEX); else #endif SOLVE_DENSE_2(double, REAL); #undef SOLVE_DENSE_2 UNPROTECT(1); /* bx */ } SET_SLOT(r, Matrix_xSym, rx); UNPROTECT(1); /* rx */ } else { Matrix_cs *B = NULL, *X = NULL; if (isNull(b)) B = Matrix_cs_speye(m, m, 1, 0); else B = M2CXS(b, 1); if (!B) ERROR_SOLVE_OOM("sparseLU", ".gCMatrix"); int k, top, nz, nzmax, *iwork = (int *) R_alloc((size_t) 2 * m, sizeof(int)); #define SOLVE_SPARSE(_CTYPE_) \ do { \ _CTYPE_ *work = (_CTYPE_ *) R_alloc((size_t) m, sizeof(_CTYPE_)); \ SOLVE_SPARSE_TRIANGULAR(_CTYPE_, A, aul != 'U', isNull(b), \ ".tCMatrix", ".gCMatrix"); \ } while (0) #ifdef MATRIX_ENABLE_ZMATRIX if (MCS_XTYPE_GET() == MCS_COMPLEX) SOLVE_SPARSE(Rcomplex); else #endif SOLVE_SPARSE(double); #undef SOLVE_SPARSE /* Drop zeros from B and sort it : */ Matrix_cs_dropzeros(B); X = Matrix_cs_transpose(B, 1); B = Matrix_cs_spfree(B); if (!X) ERROR_SOLVE_OOM(".tCMatrix", ".gCMatrix"); B = Matrix_cs_transpose(X, 1); X = Matrix_cs_spfree(X); if (!B) ERROR_SOLVE_OOM(".tCMatrix", ".gCMatrix"); PROTECT(r = CXS2M(B, 1, (isNull(b)) ? 't' : 'g')); B = Matrix_cs_spfree(B); } if (isNull(b)) SET_SLOT(r, Matrix_uploSym, auplo); SOLVE_FINISH; UNPROTECT(2); /* r, auplo */ return r; } SEXP sparseQR_matmult(SEXP qr, SEXP y, SEXP op, SEXP complete, SEXP yxjj) { SEXP V = PROTECT(GET_SLOT(qr, Matrix_VSym)); Matrix_cs *V_ = M2CXS(V, 1); MCS_XTYPE_SET(V_->xtype); SEXP beta = PROTECT(GET_SLOT(qr, Matrix_betaSym)); double *pbeta = REAL(beta); SEXP p = PROTECT(GET_SLOT(qr, Matrix_pSym)); int *pp = (LENGTH(p) > 0) ? INTEGER(p) : NULL; int m = V_->m, r = V_->n, n, i, j, op_ = asInteger(op), nprotect = 5; SEXP yx; if (isNull(y)) { n = (asLogical(complete)) ? m : r; R_xlen_t mn = (R_xlen_t) m * n, m1a = (R_xlen_t) m + 1; PROTECT(yx = allocVector(IF_COMPLEX(CPLXSXP, REALSXP), mn)); #define EYE(_CTYPE_, _PTR_, _ONE_) \ do { \ _CTYPE_ *pyx = _PTR_(yx); \ Matrix_memset(pyx, 0, mn, sizeof(_CTYPE_)); \ if (isNull(yxjj)) { \ for (j = 0; j < n; ++j) { \ *pyx = _ONE_; \ pyx += m1a; \ } \ } else if (TYPEOF(yxjj) == TYPEOF(yx) && XLENGTH(yxjj) >= n) { \ _CTYPE_ *pyxjj = _PTR_(yxjj); \ for (j = 0; j < n; ++j) { \ *pyx = *pyxjj; \ pyx += m1a; \ pyxjj += 1; \ } \ } else \ error(_("invalid '%s' to '%s'"), "yxjj", __func__); \ } while (0) #ifdef MATRIX_ENABLE_ZMATRIX if (MCS_XTYPE_GET() == MCS_COMPLEX) EYE(Rcomplex, COMPLEX, Matrix_zone); else #endif EYE(double, REAL, 1.0); #undef EYE } else { SEXP ydim = GET_SLOT(y, Matrix_DimSym); int *pydim = INTEGER(ydim); if (pydim[0] != m) error(_("dimensions of '%s' and '%s' are inconsistent"), "qr", "y"); n = pydim[1]; PROTECT(yx = GET_SLOT(y, Matrix_xSym)); } char acl[] = ".geMatrix"; acl[0] = IF_COMPLEX('z', 'd'); SEXP a = PROTECT(newObject(acl)); SEXP adim = GET_SLOT(a, Matrix_DimSym); int *padim = INTEGER(adim); padim[0] = (op_ != 0) ? m : r; padim[1] = n; SEXP ax; if (isNull(y) && padim[0] == m) ax = yx; else { R_xlen_t mn = (R_xlen_t) padim[0] * padim[1]; PROTECT(ax = allocVector(IF_COMPLEX(CPLXSXP, REALSXP), mn)); ++nprotect; } #define MATMULT(_CTYPE_, _PTR_) \ do { \ _CTYPE_ *pyx = _PTR_(yx), *pax = _PTR_(ax), *work = NULL; \ if (op_ < 5) \ work = (_CTYPE_ *) R_alloc((size_t) m, sizeof(_CTYPE_)); \ switch (op_) { \ case 0: /* qr.coef : A = P2 R1^{-1} Q1' P1 y */ \ { \ SEXP R = PROTECT(GET_SLOT(qr, Matrix_RSym)), \ q = PROTECT(GET_SLOT(qr, Matrix_qSym)); \ Matrix_cs *R_ = M2CXS(R, 1); \ int *pq = (LENGTH(q) > 0) ? INTEGER(q) : NULL; \ for (j = 0; j < n; ++j) { \ Matrix_cs_pvec(pp, pyx, work, m); \ for (i = 0; i < r; ++i) \ Matrix_cs_happly(V_, i, pbeta[i], work); \ Matrix_cs_usolve(R_, work); \ Matrix_cs_ipvec(pq, work, pax, r); \ pyx += m; \ pax += r; \ } \ UNPROTECT(2); /* q, R */ \ break; \ } \ case 1: /* qr.fitted : A = P1' Q1 Q1' P1 y */ \ for (j = 0; j < n; ++j) { \ Matrix_cs_pvec(pp, pyx, work, m); \ for (i = 0; i < r; ++i) \ Matrix_cs_happly(V_, i, pbeta[i], work); \ if (r < m) \ Matrix_memset(work + r, 0, m - r, sizeof(_CTYPE_)); \ for (i = r - 1; i >= 0; --i) \ Matrix_cs_happly(V_, i, pbeta[i], work); \ Matrix_cs_ipvec(pp, work, pax, m); \ pyx += m; \ pax += m; \ } \ break; \ case 2: /* qr.resid : A = P1' Q2 Q2' P1 y */ \ for (j = 0; j < n; ++j) { \ Matrix_cs_pvec(pp, pyx, work, m); \ for (i = 0; i < r; ++i) \ Matrix_cs_happly(V_, i, pbeta[i], work); \ if (r > 0) \ Matrix_memset(work, 0, r, sizeof(_CTYPE_)); \ for (i = r - 1; i >= 0; --i) \ Matrix_cs_happly(V_, i, pbeta[i], work); \ Matrix_cs_ipvec(pp, work, pax, m); \ pyx += m; \ pax += m; \ } \ break; \ case 3: /* qr.qty {w/ perm.} : A = Q' P1 y */ \ for (j = 0; j < n; ++j) { \ Matrix_cs_pvec(pp, pyx, work, m); \ Matrix_memcpy(pax, work, m, sizeof(_CTYPE_)); \ for (i = 0; i < r; ++i) \ Matrix_cs_happly(V_, i, pbeta[i], pax); \ pyx += m; \ pax += m; \ } \ break; \ case 4: /* qr.qy {w/ perm.} : A = P1' Q y */ \ for (j = 0; j < n; ++j) { \ Matrix_memcpy(work, pyx, m, sizeof(_CTYPE_)); \ for (i = r - 1; i >= 0; --i) \ Matrix_cs_happly(V_, i, pbeta[i], work); \ Matrix_cs_ipvec(pp, work, pax, m); \ pyx += m; \ pax += m; \ } \ break; \ case 5: /* qr.qty {w/o perm.} : A = Q' y */ \ if (ax != yx) \ Matrix_memcpy(pax, pyx, (R_xlen_t) m * n, sizeof(_CTYPE_)); \ for (j = 0; j < n; ++j) { \ for (i = 0; i < r; ++i) \ Matrix_cs_happly(V_, i, pbeta[i], pax); \ pax += m; \ } \ break; \ case 6: /* qr.qy {w/o perm.} : A = Q y */ \ if (ax != yx) \ Matrix_memcpy(pax, pyx, (R_xlen_t) m * n, sizeof(_CTYPE_)); \ for (j = 0; j < n; ++j) { \ for (i = r - 1; i >= 0; --i) \ Matrix_cs_happly(V_, i, pbeta[i], pax); \ pax += m; \ } \ break; \ default: \ error(_("invalid '%s' to '%s'"), "op", __func__); \ break; \ } \ } while (0) #ifdef MATRIX_ENABLE_ZMATRIX if (MCS_XTYPE_GET() == MCS_COMPLEX) MATMULT(Rcomplex, COMPLEX); else #endif MATMULT(double, REAL); SET_SLOT(a, Matrix_xSym, ax); UNPROTECT(nprotect); /* ax, a, yx, p, beta, V */ return a; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/idz.h������������������������������������������������������������������������������������0000644�0001751�0000144�00000003264�14574054152�013276� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_IDZ_H #define MATRIX_IDZ_H #include #define IDZ \ TEMPLATE(i, int); \ TEMPLATE(d, double); \ TEMPLATE(z, Rcomplex); #define TEMPLATE(_PREFIX_, _CTYPE_) \ void _PREFIX_ ## \ rowperm2(_CTYPE_ *, int, int, int *, int, int) IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_) \ void _PREFIX_ ## \ symperm2(_CTYPE_ *, int, char, int *, int, int) IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_) \ void _PREFIX_ ## \ pack2(_CTYPE_ *, const _CTYPE_ *, int, char, char) IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_) \ void _PREFIX_ ## \ unpack1(_CTYPE_ *, const _CTYPE_ *, int, char, char) IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_) \ void _PREFIX_ ## \ transpose2(_CTYPE_ *, const _CTYPE_ *, int, int) IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_) \ void _PREFIX_ ## \ transpose1(_CTYPE_ *, const _CTYPE_ *, int, char) IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_) \ void _PREFIX_ ## \ syforce2(_CTYPE_ *, int, char) IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_) \ void _PREFIX_ ## \ trforce2(_CTYPE_ *, int, int, char, char) IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_) \ void _PREFIX_ ## \ band2(_CTYPE_ *, int, int, int, int, char) IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_) \ void _PREFIX_ ## \ band1(_CTYPE_ *, int, int, int, char, char) IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_) \ void _PREFIX_ ## \ dcpy2(_CTYPE_ *, const _CTYPE_ *, int, R_xlen_t, char, char) IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_) \ void _PREFIX_ ## \ dcpy1(_CTYPE_ *, const _CTYPE_ *, int, R_xlen_t, char, char, char) IDZ #undef TEMPLATE #undef IDZ #endif /* MATRIX_IDZ_H */ ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/perm.h�����������������������������������������������������������������������������������0000644�0001751�0000144�00000000346�14503225712�013443� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_PERM_H #define MATRIX_PERM_H #include SEXP R_isPerm(SEXP, SEXP); SEXP R_signPerm(SEXP, SEXP); SEXP R_invertPerm(SEXP, SEXP, SEXP); SEXP R_asPerm(SEXP, SEXP, SEXP, SEXP); #endif /* MATRIX_PERM_H */ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/init.c�����������������������������������������������������������������������������������0000644�0001751�0000144�00000023772�14575137654�013466� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Mdefines.h" #include "Csparse.h" #include "attrib.h" #include "bind.h" #include "cholmod-common.h" #include "coerce.h" #include "dense.h" #include "determinant.h" #include "expm.h" #include "factor.h" #include "kappa.h" #include "matmult.h" #include "objects.h" #include "perm.h" #include "solve.h" #include "sparse.h" #include "subassign.h" #include "subscript.h" #include "utils-R.h" #include "validity.h" #include "vector.h" #include #include #include "Msymbols.h" Rcomplex Matrix_zzero, Matrix_zone, Matrix_zna; #define CALLDEF(name, n) {#name, (DL_FUNC) &name, n} #define EXTDEF(name, n) {#name, (DL_FUNC) &name, n} #define RREGDEF(name ) R_RegisterCCallable("Matrix", #name, (DL_FUNC) name) static R_CallMethodDef CallEntries[] = { CALLDEF(R_all0, 1), CALLDEF(R_any0, 1), CALLDEF(compressed_non_0_ij, 2), CALLDEF(Matrix_expand_pointers, 1), CALLDEF(m_encodeInd, 4), CALLDEF(m_encodeInd2, 5), CALLDEF(Matrix_rle_i, 2), CALLDEF(Matrix_rle_d, 2), CALLDEF(CsparseMatrix_validate_maybe_sorting, 1), CALLDEF(dgCMatrix_lusol, 2), CALLDEF(dgCMatrix_qrsol, 3), CALLDEF(dgCMatrix_cholsol, 2), CALLDEF(dtCMatrix_diag, 2), CALLDEF(Csparse_dmperm, 3), CALLDEF(Csparse_writeMM, 2), CALLDEF(nCsparse_subassign, 4), CALLDEF(lCsparse_subassign, 4), CALLDEF(iCsparse_subassign, 4), CALLDEF(dCsparse_subassign, 4), CALLDEF(zCsparse_subassign, 4), CALLDEF(Matrix_validate, 1), CALLDEF(MatrixFactorization_validate, 1), CALLDEF(nMatrix_validate, 1), CALLDEF(lMatrix_validate, 1), CALLDEF(iMatrix_validate, 1), CALLDEF(dMatrix_validate, 1), CALLDEF(zMatrix_validate, 1), CALLDEF(generalMatrix_validate, 1), CALLDEF(symmetricMatrix_validate, 1), CALLDEF(triangularMatrix_validate, 1), CALLDEF(diagonalMatrix_validate, 1), CALLDEF(indMatrix_validate, 1), CALLDEF(pMatrix_validate, 1), CALLDEF(CsparseMatrix_validate, 1), CALLDEF(RsparseMatrix_validate, 1), CALLDEF(TsparseMatrix_validate, 1), CALLDEF(sCMatrix_validate, 1), CALLDEF(tCMatrix_validate, 1), CALLDEF(sRMatrix_validate, 1), CALLDEF(tRMatrix_validate, 1), CALLDEF(sTMatrix_validate, 1), CALLDEF(tTMatrix_validate, 1), CALLDEF(xgCMatrix_validate, 1), CALLDEF(xsCMatrix_validate, 1), CALLDEF(xtCMatrix_validate, 1), CALLDEF(xgRMatrix_validate, 1), CALLDEF(xsRMatrix_validate, 1), CALLDEF(xtRMatrix_validate, 1), CALLDEF(xgTMatrix_validate, 1), CALLDEF(xsTMatrix_validate, 1), CALLDEF(xtTMatrix_validate, 1), CALLDEF(unpackedMatrix_validate, 1), CALLDEF(packedMatrix_validate, 1), CALLDEF(dpoMatrix_validate, 1), CALLDEF(dppMatrix_validate, 1), CALLDEF(corMatrix_validate, 1), CALLDEF(copMatrix_validate, 1), CALLDEF(sparseVector_validate, 1), CALLDEF(lsparseVector_validate, 1), CALLDEF(isparseVector_validate, 1), CALLDEF(dsparseVector_validate, 1), CALLDEF(zsparseVector_validate, 1), CALLDEF(denseLU_validate, 1), CALLDEF(sparseLU_validate, 1), CALLDEF(sparseQR_validate, 1), CALLDEF(BunchKaufman_validate, 1), CALLDEF(pBunchKaufman_validate, 1), CALLDEF(Cholesky_validate, 1), CALLDEF(pCholesky_validate, 1), CALLDEF(CHMfactor_validate, 1), CALLDEF(CHMsimpl_validate, 1), CALLDEF(CHMsuper_validate, 1), CALLDEF(dCHMsimpl_validate, 1), CALLDEF(dCHMsuper_validate, 1), CALLDEF(Schur_validate, 1), CALLDEF(R_Dim_validate, 1), CALLDEF(R_DimNames_validate, 2), CALLDEF(R_DimNames_fixup, 1), CALLDEF(R_DimNames_is_symmetric, 1), CALLDEF(R_symDN, 1), CALLDEF(R_revDN, 1), CALLDEF(R_Matrix_nonvirtual, 2), CALLDEF(R_Matrix_kind, 1), CALLDEF(R_Matrix_shape, 1), CALLDEF(R_Matrix_repr, 1), CALLDEF(R_index_triangle, 4), CALLDEF(R_index_diagonal, 3), CALLDEF(R_nnz, 3), CALLDEF(R_isPerm, 2), CALLDEF(R_signPerm, 2), CALLDEF(R_invertPerm, 3), CALLDEF(R_asPerm, 4), CALLDEF(R_set_factor, 4), CALLDEF(R_subscript_1ary, 2), CALLDEF(R_subscript_1ary_mat, 2), CALLDEF(R_subscript_2ary, 3), CALLDEF(R_dense_band, 3), CALLDEF(R_dense_diag_get, 2), CALLDEF(R_dense_diag_set, 2), CALLDEF(R_dense_transpose, 1), CALLDEF(R_dense_force_symmetric, 2), CALLDEF(R_dense_symmpart, 1), CALLDEF(R_dense_skewpart, 1), CALLDEF(R_dense_is_symmetric, 2), CALLDEF(R_dense_is_triangular, 2), CALLDEF(R_dense_is_diagonal, 1), CALLDEF(R_dense_marginsum, 4), CALLDEF(R_dense_sum, 2), CALLDEF(R_dense_prod, 2), CALLDEF(R_sparse_drop0, 2), CALLDEF(R_sparse_diag_U2N, 1), CALLDEF(R_sparse_diag_N2U, 1), CALLDEF(R_sparse_band, 3), CALLDEF(R_sparse_diag_get, 2), CALLDEF(R_sparse_diag_set, 2), CALLDEF(R_sparse_transpose, 2), CALLDEF(R_sparse_force_symmetric, 2), CALLDEF(R_sparse_symmpart, 1), CALLDEF(R_sparse_skewpart, 1), CALLDEF(R_sparse_is_symmetric, 2), CALLDEF(R_sparse_is_triangular, 2), CALLDEF(R_sparse_is_diagonal, 1), CALLDEF(R_sparse_marginsum, 5), CALLDEF(R_sparse_sum, 2), CALLDEF(R_sparse_prod, 2), CALLDEF(Tsparse_aggregate, 1), CALLDEF(R_dense_matmult, 4), CALLDEF(R_sparse_matmult, 6), CALLDEF(R_diagonal_matmult, 5), CALLDEF(dgeMatrix_expm, 1), CALLDEF(dgeMatrix_trf, 2), CALLDEF(dsyMatrix_trf, 2), CALLDEF(dspMatrix_trf, 2), CALLDEF(dpoMatrix_trf, 4), CALLDEF(dppMatrix_trf, 2), CALLDEF(dgeMatrix_sch, 3), CALLDEF(dgCMatrix_trf, 4), CALLDEF(dgCMatrix_orf, 3), CALLDEF(dpCMatrix_trf, 5), CALLDEF(BunchKaufman_expand, 2), CALLDEF(denseLU_determinant, 2), CALLDEF(BunchKaufman_determinant, 2), CALLDEF(Cholesky_determinant, 2), CALLDEF(sparseLU_determinant, 2), CALLDEF(sparseQR_determinant, 2), CALLDEF(CHMfactor_determinant, 3), CALLDEF(denseLU_solve, 2), CALLDEF(BunchKaufman_solve, 2), CALLDEF(Cholesky_solve, 2), CALLDEF(dtrMatrix_solve, 2), CALLDEF(sparseLU_solve, 3), CALLDEF(CHMfactor_solve, 4), CALLDEF(dtCMatrix_solve, 3), CALLDEF(sparseQR_matmult, 5), CALLDEF(CHMfactor_diag_get, 2), CALLDEF(CHMfactor_update, 3), CALLDEF(CHMfactor_updown, 3), CALLDEF(dgeMatrix_norm, 2), CALLDEF(dsyMatrix_norm, 2), CALLDEF(dspMatrix_norm, 2), CALLDEF(dtrMatrix_norm, 2), CALLDEF(dtpMatrix_norm, 2), CALLDEF(dgeMatrix_rcond, 3), CALLDEF(dsyMatrix_rcond, 3), CALLDEF(dspMatrix_rcond, 3), CALLDEF(dpoMatrix_rcond, 3), CALLDEF(dppMatrix_rcond, 3), CALLDEF(dtrMatrix_rcond, 2), CALLDEF(dtpMatrix_rcond, 2), CALLDEF(v2spV, 1), CALLDEF(CR2spV, 1), CALLDEF(R_vector_as_dense, 8), CALLDEF(R_matrix_as_dense, 5), CALLDEF(R_sparse_as_dense, 2), CALLDEF(R_diagonal_as_dense, 5), CALLDEF(R_index_as_dense, 2), CALLDEF(R_vector_as_sparse, 8), CALLDEF(R_matrix_as_sparse, 5), CALLDEF(R_dense_as_sparse, 2), CALLDEF(R_diagonal_as_sparse, 5), CALLDEF(R_index_as_sparse, 3), CALLDEF(R_dense_as_kind, 2), CALLDEF(R_sparse_as_kind, 2), CALLDEF(R_diagonal_as_kind, 2), CALLDEF(R_index_as_kind, 2), CALLDEF(R_dense_as_general, 1), CALLDEF(R_sparse_as_general, 1), CALLDEF(R_dense_as_unpacked, 1), CALLDEF(R_dense_as_packed, 3), CALLDEF(R_sparse_as_Csparse, 1), CALLDEF(R_sparse_as_Rsparse, 1), CALLDEF(R_sparse_as_Tsparse, 1), CALLDEF(R_Matrix_as_vector, 1), CALLDEF(R_Matrix_as_matrix, 1), CALLDEF(R_Matrix_as_unpacked, 1), CALLDEF(R_Matrix_as_packed, 1), CALLDEF(R_Matrix_as_Csparse, 1), CALLDEF(R_Matrix_as_Rsparse, 1), CALLDEF(R_Matrix_as_Tsparse, 1), CALLDEF(R_Matrix_as_kind, 3), CALLDEF(R_Matrix_as_general, 2), CALLDEF(R_Matrix_version, 0), CALLDEF(R_cholmod_common_envini, 1), {NULL, NULL, 0} }; static const R_ExternalMethodDef ExtEntries[] = { EXTDEF(Mmatrix, 7), EXTDEF(R_bind, -1), {NULL, NULL, 0} }; void attribute_visible R_init_Matrix(DllInfo *info) { R_registerRoutines(info, NULL, CallEntries, NULL, ExtEntries); R_useDynamicSymbols(info, FALSE); /* These are callable from other packages' C code: */ /* CHOLMOD: */ RREGDEF(cholmod_aat); RREGDEF(cholmod_add); RREGDEF(cholmod_allocate_dense); RREGDEF(cholmod_allocate_sparse); RREGDEF(cholmod_allocate_triplet); RREGDEF(cholmod_analyze); RREGDEF(cholmod_analyze_p); RREGDEF(cholmod_band_inplace); RREGDEF(cholmod_change_factor); RREGDEF(cholmod_copy); RREGDEF(cholmod_copy_dense); RREGDEF(cholmod_copy_factor); RREGDEF(cholmod_copy_sparse); RREGDEF(cholmod_defaults); RREGDEF(cholmod_dense_to_sparse); RREGDEF(cholmod_factor_to_sparse); RREGDEF(cholmod_factorize); RREGDEF(cholmod_factorize_p); RREGDEF(cholmod_finish); RREGDEF(cholmod_free_dense); RREGDEF(cholmod_free_factor); RREGDEF(cholmod_free_sparse); RREGDEF(cholmod_free_triplet); RREGDEF(cholmod_nnz); RREGDEF(cholmod_scale); RREGDEF(cholmod_sdmult); RREGDEF(cholmod_solve); RREGDEF(cholmod_solve2); RREGDEF(cholmod_sort); RREGDEF(cholmod_sparse_to_dense); RREGDEF(cholmod_sparse_to_triplet); RREGDEF(cholmod_speye); RREGDEF(cholmod_spsolve); RREGDEF(cholmod_ssmult); RREGDEF(cholmod_start); RREGDEF(cholmod_submatrix); RREGDEF(cholmod_transpose); RREGDEF(cholmod_triplet_to_sparse); RREGDEF(cholmod_updown); RREGDEF(cholmod_vertcat); /* Matrix: */ RREGDEF(sexp_as_cholmod_factor); RREGDEF(sexp_as_cholmod_sparse); RREGDEF(sexp_as_cholmod_triplet); RREGDEF(sexp_as_cholmod_dense); RREGDEF(numeric_as_cholmod_dense); RREGDEF(cholmod_factor_as_sexp); RREGDEF(cholmod_sparse_as_sexp); RREGDEF(cholmod_triplet_as_sexp); RREGDEF(cholmod_dense_as_sexp); RREGDEF(cholmod_factor_ldetA); RREGDEF(cholmod_factor_update); Matrix_DimNamesSym = install("Dimnames"); Matrix_DimSym = install("Dim"); Matrix_LSym = install("L"); Matrix_QSym = install("Q"); Matrix_RSym = install("R"); Matrix_TSym = install("T"); Matrix_USym = install("U"); Matrix_VSym = install("V"); Matrix_betaSym = install("beta"); Matrix_diagSym = install("diag"); Matrix_factorsSym = install("factors"); Matrix_iSym = install("i"); Matrix_jSym = install("j"); Matrix_lengthSym = install("length"); Matrix_marginSym = install("margin"); Matrix_pSym = install("p"); Matrix_permSym = install("perm"); Matrix_qSym = install("q"); Matrix_sdSym = install("sd"); Matrix_uploSym = install("uplo"); Matrix_xSym = install("x"); Matrix_zzero.r = 0.0; Matrix_zone.r = 1.0; Matrix_zna.r = NA_REAL; Matrix_zzero.i = 0.0; Matrix_zone.i = 0.0; Matrix_zna.i = NA_REAL; R_cholmod_start(&c); return; } void R_unload_Matrix(DllInfo *info) { R_cholmod_finish(&c); return; } ������Matrix/src/sparse.c���������������������������������������������������������������������������������0000644�0001751�0000144�00000272731�14574054152�014007� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include /* fabs, hypot */ #include "Mdefines.h" #include "sparse.h" SEXP sparse_drop0(SEXP from, const char *class, double tol) { if (class[0] == 'n') return from; SEXP to, x0 = PROTECT(GET_SLOT(from, Matrix_xSym)); #define TOLBASED_ISNZ_REAL(_X_) \ (ISNA_REAL(_X_) || fabs(_X_) > tol) #define TOLBASED_ISNZ_COMPLEX(_X_) \ (ISNA_COMPLEX(_X_) || hypot((_X_).r, (_X_).i) > tol) #define DROP0_CASES(_DO_) \ do { \ switch (class[0]) { \ case 'l': \ _DO_(int, LOGICAL, ISNZ_LOGICAL); \ break; \ case 'i': \ _DO_(int, INTEGER, ISNZ_INTEGER); \ break; \ case 'd': \ if (tol > 0.0) \ _DO_(double, REAL, TOLBASED_ISNZ_REAL); \ else \ _DO_(double, REAL, ISNZ_REAL); \ break; \ case 'z': \ if (tol > 0.0) \ _DO_(Rcomplex, COMPLEX, TOLBASED_ISNZ_COMPLEX); \ else \ _DO_(Rcomplex, COMPLEX, ISNZ_COMPLEX); \ break; \ default: \ break; \ } \ } while (0) if (class[2] != 'T') { SEXP p0 = PROTECT(GET_SLOT(from, Matrix_pSym)); int *pp0 = INTEGER(p0), k, n = (int) (XLENGTH(p0) - 1), nnz0 = pp0[n], nnz1 = 0; #undef DROP0_LOOP1 #define DROP0_LOOP1(_CTYPE_, _PTR_, _ISNZ_) \ do { \ _CTYPE_ *px0 = _PTR_(x0); \ for (k = 0; k < nnz0; ++k) { \ if (_ISNZ_(*px0)) \ ++nnz1; \ ++px0; \ } \ } while (0) DROP0_CASES(DROP0_LOOP1); if (nnz1 == nnz0) { UNPROTECT(2); /* p0, x0 */ return from; } PROTECT(to = newObject(class)); SEXP iSym = (class[2] == 'C') ? Matrix_iSym : Matrix_jSym, i0 = PROTECT(GET_SLOT(from, iSym)), p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) n + 1)), i1 = PROTECT(allocVector(INTSXP, nnz1)), x1 = PROTECT(allocVector(TYPEOF(x0), nnz1)); int *pi0 = INTEGER(i0), *pp1 = INTEGER(p1), *pi1 = INTEGER(i1), j, kend; pp0++; *(pp1++) = 0; SET_SLOT(to, Matrix_pSym, p1); SET_SLOT(to, iSym, i1); SET_SLOT(to, Matrix_xSym, x1); #undef DROP0_LOOP2 #define DROP0_LOOP2(_CTYPE_, _PTR_, _ISNZ_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ for (j = 0, k = 0; j < n; ++j) { \ pp1[j] = pp1[j - 1]; \ kend = pp0[j]; \ while (k < kend) { \ if (_ISNZ_(*px0)) { \ ++pp1[j]; \ *(pi1++) = *pi0; \ *(px1++) = *px0; \ } \ ++k; ++pi0; ++px0; \ } \ } \ } while (0) DROP0_CASES(DROP0_LOOP2); UNPROTECT(7); /* x1, i1, p1, i0, to, p0, x0 */ } else { R_xlen_t k, nnz0 = XLENGTH(x0), nnz1 = 0; DROP0_CASES(DROP0_LOOP1); if (nnz1 == nnz0) { UNPROTECT(1); /* x0 */ return from; } PROTECT(to = newObject(class)); SEXP i0 = PROTECT(GET_SLOT(from, Matrix_iSym)), j0 = PROTECT(GET_SLOT(from, Matrix_jSym)), i1 = PROTECT(allocVector(INTSXP, nnz1)), j1 = PROTECT(allocVector(INTSXP, nnz1)), x1 = PROTECT(allocVector(TYPEOF(x0), nnz1)); int *pi0 = INTEGER(i0), *pj0 = INTEGER(j0), *pi1 = INTEGER(i1), *pj1 = INTEGER(j1); SET_SLOT(to, Matrix_iSym, i1); SET_SLOT(to, Matrix_jSym, j1); SET_SLOT(to, Matrix_xSym, x1); #undef DROP0_LOOP2 #define DROP0_LOOP2(_CTYPE_, _PTR_, _ISNZ_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ for (k = 0; k < nnz0; ++k) { \ if (_ISNZ_(*px0)) { \ *(pi1++) = *pi0; \ *(pj1++) = *pj0; \ *(px1++) = *px0; \ } \ ++pi0; ++pj0; ++px0; \ } \ } while (0) DROP0_CASES(DROP0_LOOP2); UNPROTECT(7); /* x1, j1, i1, j0, i0, to, x0 */ } PROTECT(to); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; if (m != n || n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); char ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); char di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N') SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } else { SEXP factors = PROTECT(GET_SLOT(from, Matrix_factorsSym)); if (LENGTH(factors) > 0) SET_SLOT(to, Matrix_factorsSym, factors); UNPROTECT(1); /* factors */ } #undef TOLBASED_ISNZ_REAL #undef TOLBASED_ISNZ_COMPLEX #undef DROP0_CASES #undef DROP0_LOOP1 #undef DROP0_LOOP2 UNPROTECT(1); /* to */ return to; } /* drop0(<[CRT]sparseMatrix>, tol) */ SEXP R_sparse_drop0(SEXP from, SEXP tol) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); double tol_; if (TYPEOF(tol) != REALSXP || LENGTH(tol) < 1 || ISNAN(tol_ = REAL(tol)[0])) error(_("'%s' is not a number"), "tol"); return sparse_drop0(from, valid[ivalid], tol_); } SEXP sparse_diag_U2N(SEXP from, const char *class) { if (class[1] != 't') return from; SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); char di = *CHAR(STRING_ELT(diag, 0)); UNPROTECT(1); /* diag */ if (di == 'N') return from; SEXP val = PROTECT(ScalarLogical(1)); from = R_sparse_diag_set(from, val); UNPROTECT(1); /* val */ return from; } /* diagU2N(<[CRT]sparseMatrix>), parallel to R-level ..diagU2N(), though that is more general, working for _all_ Matrix */ SEXP R_sparse_diag_U2N(SEXP from) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); return sparse_diag_U2N(from, valid[ivalid]); } SEXP sparse_diag_N2U(SEXP from, const char *class) { if (class[1] != 't') return from; SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); char di = *CHAR(STRING_ELT(diag, 0)); UNPROTECT(1); /* diag */ if (di != 'N') return from; SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int n = INTEGER(dim)[0]; UNPROTECT(1); /* dim */ if (n == 0) PROTECT(from = duplicate(from)); else { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); char ul = *CHAR(STRING_ELT(uplo, 0)); UNPROTECT(1); /* uplo */ if (ul == 'U') PROTECT(from = sparse_band(from, class, 1, n - 1)); else PROTECT(from = sparse_band(from, class, 1 - n, -1)); } PROTECT(diag = mkString("U")); SET_SLOT(from, Matrix_diagSym, diag); UNPROTECT(2); /* diag, from */ return from; } /* diagN2U(<[CRT]sparseMatrix>), parallel to R-level ..diagN2U(), though that is more general, working for _all_ Matrix */ SEXP R_sparse_diag_N2U(SEXP from) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); return sparse_diag_N2U(from, valid[ivalid]); } SEXP sparse_band(SEXP from, const char *class, int a, int b) { SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; UNPROTECT(1); /* dim */ /* Need tri[ul](<0-by-0>) and tri[ul](<1-by-1>) to be triangularMatrix */ if (a <= 1 - m && b >= n - 1 && (class[1] == 't' || m != n || m > 1 || n > 1)) return from; int ge = 0, sy = 0, tr = 0; ge = m != n || !((tr = a >= 0 || b <= 0 || class[1] == 't') || (sy = a == -b && class[1] == 's')); char ul0 = 'U', ul1 = 'U', di = 'N'; if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); ul0 = *CHAR(STRING_ELT(uplo, 0)); UNPROTECT(1); /* uplo */ if (class[1] == 't') { /* Be fast if band contains entire triangle */ if ((ul0 == 'U') ? (a <= 0 && b >= n - 1) : (b >= 0 && a <= 1 - m)) return from; else if (a <= 0 && b >= 0) { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); di = *CHAR(STRING_ELT(diag, 0)); UNPROTECT(1); /* diag */ } } } /* band(, a, b) is equivalent to t(band(t(), -b, -a)) ! */ if (class[2] == 'R') { int r; r = m; m = n; n = r; r = a; a = -b; b = -r; ul0 = (ul0 == 'U') ? 'L' : 'U'; from = sparse_transpose(from, class, 1); } PROTECT(from); char cl[] = "...Matrix"; cl[0] = class[0]; cl[1] = (ge) ? 'g' : ((tr) ? 't' : 's'); cl[2] = (class[2] == 'R') ? 'C' : class[2]; SEXP to = PROTECT(newObject(cl)); dim = GET_SLOT(to, Matrix_DimSym); pdim = INTEGER(dim); pdim[0] = m; pdim[1] = n; SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); if (class[1] != 's' || sy) SET_SLOT(to, Matrix_DimNamesSym, dimnames); else set_symmetrized_DimNames(to, dimnames, -1); UNPROTECT(1); /* dimnames */ if (!ge) { ul1 = (tr && class[1] != 't') ? ((a >= 0) ? 'U' : 'L') : ul0; if (ul1 != 'U') { SEXP uplo = PROTECT(mkString("L")); SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } if (di != 'N') { SEXP diag = PROTECT(mkString("U")); SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } } /* It remains to set some subset of 'p', 'i', 'j', 'x' ... */ #define BAND_CASES \ do { \ switch (class[0]) { \ case 'l': \ BAND_SUBCASES(int, LOGICAL, SHOW); \ break; \ case 'i': \ BAND_SUBCASES(int, INTEGER, SHOW); \ break; \ case 'd': \ BAND_SUBCASES(double, REAL, SHOW); \ break; \ case 'z': \ BAND_SUBCASES(Rcomplex, COMPLEX, SHOW); \ break; \ default: \ break; \ } \ } while (0) if (class[2] != 'T') { SEXP p0 = PROTECT(GET_SLOT(from, Matrix_pSym)), i0 = PROTECT(GET_SLOT(from, Matrix_iSym)), p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) n + 1)); int *pp0 = INTEGER(p0), *pi0 = INTEGER(i0), *pp1 = INTEGER(p1), d, j, k, kend, nnz0 = pp0[n], nnz1 = 0; pp0++; *(pp1++) = 0; SET_SLOT(to, Matrix_pSym, p1); if (class[1] == 's' && !sy) { Matrix_memset(pp1, 0, n, sizeof(int)); for (j = 0, k = 0; j < n; ++j) { kend = pp0[j]; while (k < kend) { if ((d = j - pi0[k]) >= a && d <= b) ++pp1[j]; if (d != 0 && -d >= a && -d <= b) ++pp1[pi0[k]]; ++k; } } for (j = 0; j < n; ++j) { nnz1 += pp1[j]; pp1[j] = nnz1; } } else { for (j = 0, k = 0; j < n; ++j) { kend = pp0[j]; while (k < kend) { if ((d = j - pi0[k]) >= a && d <= b) ++nnz1; ++k; } pp1[j] = nnz1; } } if (nnz1 == nnz0 && (class[1] != 's' || sy)) { /* No need to allocate in this case: band has all nonzero elements */ SET_SLOT(to, Matrix_iSym, i0); if (class[0] != 'n') { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)); SET_SLOT(to, Matrix_xSym, x0); UNPROTECT(1); /* x0 */ } if (class[2] == 'R') to = sparse_transpose(to, cl, 1); UNPROTECT(5); /* p1, i0, p0, to, from */ return to; } SEXP i1 = PROTECT(allocVector(INTSXP, nnz1)); int *pi1 = INTEGER(i1); SET_SLOT(to, Matrix_iSym, i1); #undef BAND_SUBCASES #define BAND_SUBCASES(_CTYPE_, _PTR_, _MASK_) \ do { \ _MASK_(_CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1)); \ if (class[1] == 's' && !sy) { \ int *pp1_; \ Matrix_Calloc(pp1_, n, int); \ Matrix_memcpy(pp1_, pp1 - 1, n, sizeof(int)); \ for (j = 0, k = 0; j < n; ++j) { \ kend = pp0[j]; \ while (k < kend) { \ if ((d = j - pi0[k]) >= a && d <= b) { \ pi1[pp1_[j]] = pi0[k]; \ _MASK_(px1[pp1_[j]] = px0[k]); \ ++pp1_[j]; \ } \ if (d != 0 && -d >= a && -d <= b) { \ pi1[pp1_[pi0[k]]] = j; \ _MASK_(px1[pp1_[pi0[k]]] = px0[k]); \ ++pp1_[pi0[k]]; \ } \ ++k; \ } \ } \ Matrix_Free(pp1_, n); \ } else { \ for (j = 0, k = 0; j < n; ++j) { \ kend = pp0[j]; \ while (k < kend) { \ if ((d = j - pi0[k]) >= a && d <= b) { \ *(pi1++) = pi0[k]; \ _MASK_(*(px1++) = px0[k]); \ } \ ++k; \ } \ } \ } \ } while (0) if (class[0] == 'n') BAND_SUBCASES(int, LOGICAL, HIDE); else { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), nnz1)); SET_SLOT(to, Matrix_xSym, x1); BAND_CASES; UNPROTECT(2); /* x1, x0 */ } if (class[2] == 'R') to = sparse_transpose(to, cl, 1); } else { SEXP i0 = PROTECT(GET_SLOT(from, Matrix_iSym)), j0 = PROTECT(GET_SLOT(from, Matrix_jSym)); int *pi0 = INTEGER(i0), *pj0 = INTEGER(j0), d; R_xlen_t k, nnz0 = XLENGTH(i0), nnz1 = 0; if (class[1] == 's' && !sy) { for (k = 0; k < nnz0; ++k) { if ((d = pj0[k] - pi0[k]) >= a && d <= b) ++nnz1; if (d != 0 && -d >= a && -d <= b) ++nnz1; } } else { for (k = 0; k < nnz0; ++k) { if ((d = pj0[k] - pi0[k]) >= a && d <= b) ++nnz1; } } if (nnz1 == nnz0 && (class[1] != 's' || sy)) { /* No need to allocate in this case: band has all nonzero elements */ SET_SLOT(to, Matrix_iSym, i0); SET_SLOT(to, Matrix_jSym, j0); if (class[0] != 'n') { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)); SET_SLOT(to, Matrix_xSym, x0); UNPROTECT(1); /* x0 */ } UNPROTECT(4); /* j0, i0, to, from */ return to; } SEXP i1 = PROTECT(allocVector(INTSXP, nnz1)), j1 = PROTECT(allocVector(INTSXP, nnz1)); int *pi1 = INTEGER(i1), *pj1 = INTEGER(j1); SET_SLOT(to, Matrix_iSym, i1); SET_SLOT(to, Matrix_jSym, j1); #undef BAND_SUBCASES #define BAND_SUBCASES(_CTYPE_, _PTR_, _MASK_) \ do { \ _MASK_(_CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1)); \ if (class[1] == 's' && !sy) { \ for (k = 0; k < nnz0; ++k) { \ if ((d = pj0[k] - pi0[k]) >= a && d <= b) { \ *(pi1++) = pi0[k]; \ *(pj1++) = pj0[k]; \ _MASK_(*(px1++) = px0[k]); \ } \ if (d != 0 && -d >= a && -d <= b) { \ *(pi1++) = pj0[k]; \ *(pj1++) = pi0[k]; \ _MASK_(*(px1++) = px0[k]); \ } \ } \ } else { \ for (k = 0; k < nnz0; ++k) { \ if ((d = pj0[k] - pi0[k]) >= a && d <= b) { \ *(pi1++) = pi0[k]; \ *(pj1++) = pj0[k]; \ _MASK_(*(px1++) = px0[k]); \ } \ } \ } \ } while (0) if (class[0] == 'n') BAND_SUBCASES(int, LOGICAL, HIDE); else { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), nnz1)); SET_SLOT(to, Matrix_xSym, x1); BAND_CASES; UNPROTECT(2); /* x1, x0 */ } } #undef BAND_CASES #undef BAND_SUBCASES UNPROTECT(6); return to; } /* band(<[CRT]sparseMatrix>, k1, k2), tri[ul](<[CRT]sparseMatrix>, k) */ /* NB: argument validation more or less copied from R_dense_band() */ SEXP R_sparse_band(SEXP from, SEXP k1, SEXP k2) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; UNPROTECT(1); int a, b; if (k1 == R_NilValue) // tril() a = -m ; // was (m > 0) ? 1 - m : 0; else if ((a = asInteger(k1)) == NA_INTEGER || a < -m || a > n) error(_("'%s' (%d) must be an integer from %s (%d) to %s (%d)"), "k1", a, "-Dim[1]", -m, "Dim[2]", n); if (k2 == R_NilValue) // triu() b = n; // was (n > 0) ? n - 1 : 0; else if ((b = asInteger(k2)) == NA_INTEGER || b < -m || b > n) error(_("'%s' (%d) must be an integer from %s (%d) to %s (%d)"), "k2", b, "-Dim[1]", -m, "Dim[2]", n); else if (b < a) error(_("'%s' (%d) must be less than or equal to '%s' (%d)"), "k1", a, "k2", b); return sparse_band(from, valid[ivalid], a, b); } SEXP sparse_diag_get(SEXP obj, const char *class, int names) { SEXP dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1], r = (m < n) ? m : n; UNPROTECT(1); /* dim */ char ul = 'U', di = 'N'; if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(obj, Matrix_uploSym)); ul = *CHAR(STRING_ELT(uplo, 0)); UNPROTECT(1); /* uplo */ if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(obj, Matrix_diagSym)); di = *CHAR(STRING_ELT(diag, 0)); UNPROTECT(1); /* diag */ } } SEXP res = PROTECT(allocVector(kindToType(class[0]), r)); #define DG_CASES \ do { \ switch (class[0]) { \ case 'n': \ case 'l': \ DG_LOOP(int, LOGICAL, SHOW, FIRSTOF, INCREMENT_LOGICAL, 0, 1); \ break; \ case 'i': \ DG_LOOP(int, INTEGER, SHOW, FIRSTOF, INCREMENT_INTEGER, 0, 1); \ break; \ case 'd': \ DG_LOOP(double, REAL, SHOW, FIRSTOF, INCREMENT_REAL, 0.0, 1.0); \ break; \ case 'z': \ DG_LOOP(Rcomplex, COMPLEX, SHOW, FIRSTOF, INCREMENT_COMPLEX, Matrix_zzero, Matrix_zone); \ break; \ default: \ break; \ } \ } while (0) if (di != 'N') { int j; #undef DG_LOOP #define DG_LOOP(_CTYPE_, _PTR_, _MASK_, _REPLACE_, _INCREMENT_, _ZERO_, _ONE_) \ do { \ _CTYPE_ *pres = _PTR_(res); \ for (j = 0; j < r; ++j) \ *(pres++) = _ONE_; \ } while (0) DG_CASES; } else if (class[2] != 'T') { SEXP iSym = (class[2] == 'C') ? Matrix_iSym : Matrix_jSym, p0 = PROTECT(GET_SLOT(obj, Matrix_pSym)), i0 = PROTECT(GET_SLOT(obj, iSym)); int j, k, kend, *pp0 = INTEGER(p0), *pi0 = INTEGER(i0); pp0++; #undef DG_LOOP #define DG_LOOP(_CTYPE_, _PTR_, _MASK_, _REPLACE_, _INCREMENT_, _ZERO_, _ONE_) \ do { \ _MASK_(_CTYPE_ *px0 = _PTR_(x0)); \ _CTYPE_ *pres = _PTR_(res); \ if (class[1] == 'g') { \ for (j = 0, k = 0; j < r; ++j) { \ pres[j] = _ZERO_; \ kend = pp0[j]; \ while (k < kend) { \ if (pi0[k] != j) \ ++k; \ else { \ pres[j] = _REPLACE_(px0[k], 1); \ k = kend; \ } \ } \ } \ } else if ((class[2] == 'C') == (ul != 'U')) { \ for (j = 0, k = 0; j < r; ++j) { \ kend = pp0[j]; \ pres[j] = (k < kend && pi0[k] == j) \ ? _REPLACE_(px0[k], 1) : _ZERO_; \ k = kend; \ } \ } else { \ for (j = 0, k = 0; j < r; ++j) { \ kend = pp0[j]; \ pres[j] = (k < kend && pi0[kend - 1] == j) \ ? _REPLACE_(px0[kend - 1], 1) : _ZERO_; \ k = kend; \ } \ } \ } while (0) if (class[0] == 'n') { DG_LOOP(int, LOGICAL, HIDE, SECONDOF, , 0, 1); } else { SEXP x0 = PROTECT(GET_SLOT(obj, Matrix_xSym)); DG_CASES; UNPROTECT(1); /* x0 */ } UNPROTECT(2); /* i0, p0 */ } else { SEXP i0 = PROTECT(GET_SLOT(obj, Matrix_iSym)), j0 = PROTECT(GET_SLOT(obj, Matrix_jSym)); int *pi0 = INTEGER(i0), *pj0 = INTEGER(j0); R_xlen_t k, nnz0 = XLENGTH(i0); #undef DG_LOOP #define DG_LOOP(_CTYPE_, _PTR_, _MASK_, _REPLACE_, _INCREMENT_, _ZERO_, _ONE_) \ do { \ _MASK_(_CTYPE_ *px0 = _PTR_(x0)); \ _CTYPE_ *pres = _PTR_(res); \ Matrix_memset(pres, 0, r, sizeof(_CTYPE_)); \ for (k = 0; k < nnz0; ++k) { \ if (*pi0 == *pj0) \ _INCREMENT_(pres[*pi0], (*px0)); \ ++pi0; ++pj0; _MASK_(++px0); \ } \ } while (0) if (class[0] == 'n') DG_LOOP(int, LOGICAL, HIDE, SECONDOF, INCREMENT_PATTERN, 0, 1); else { SEXP x0 = PROTECT(GET_SLOT(obj, Matrix_xSym)); DG_CASES; UNPROTECT(1); /* x0 */ } UNPROTECT(2); /* j0, i0 */ } #undef DG_CASES #undef DG_LOOP if (names) { /* NB: The logic here must be adjusted once the validity method for 'symmetricMatrix' enforces symmetric 'Dimnames' */ SEXP dn = PROTECT(GET_SLOT(obj, Matrix_DimNamesSym)), rn = VECTOR_ELT(dn, 0), cn = VECTOR_ELT(dn, 1); if (cn == R_NilValue) { if (class[1] == 's' && rn != R_NilValue) setAttrib(res, R_NamesSymbol, rn); } else { if (class[1] == 's') setAttrib(res, R_NamesSymbol, cn); else if (rn != R_NilValue && (rn == cn || equal_character_vectors(rn, cn, r))) setAttrib(res, R_NamesSymbol, (r == m) ? rn : cn); } UNPROTECT(1); /* dn */ } UNPROTECT(1); /* res */ return res; } /* diag(<[CRT]sparseMatrix>, names=) */ SEXP R_sparse_diag_get(SEXP obj, SEXP names) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) ERROR_INVALID_CLASS(obj, __func__); int names_; if (TYPEOF(names) != LGLSXP || LENGTH(names) < 1 || (names_ = LOGICAL(names)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "names", "TRUE", "FALSE"); return sparse_diag_get(obj, valid[ivalid], names_); } SEXP sparse_diag_set(SEXP from, const char *class, SEXP value) { SEXP to = PROTECT(newObject(class)); int v = LENGTH(value) != 1, full = 0; SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1], r = (m < n) ? m : n; if (m != n || n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ char ul = 'U', di = 'N'; if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); di = *CHAR(STRING_ELT(diag, 0)); UNPROTECT(1); /* diag */ } } #define DS_CASES \ do { \ switch (class[0]) { \ case 'n': \ case 'l': \ DS_LOOP(int, LOGICAL, SHOW, ISNZ_LOGICAL); \ break; \ case 'i': \ DS_LOOP(int, INTEGER, SHOW, ISNZ_INTEGER); \ break; \ case 'd': \ DS_LOOP(double, REAL, SHOW, ISNZ_REAL); \ break; \ case 'z': \ DS_LOOP(Rcomplex, COMPLEX, SHOW, ISNZ_COMPLEX); \ break; \ default: \ break; \ } \ } while (0) if (class[2] != 'T') { int n_ = (class[2] == 'C') ? n : m; SEXP iSym = (class[2] == 'C') ? Matrix_iSym : Matrix_jSym, p0 = PROTECT(GET_SLOT(from, Matrix_pSym)), i0 = PROTECT(GET_SLOT(from, iSym)), p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) n_ + 1)); SET_SLOT(to, Matrix_pSym, p1); int *pp0 = INTEGER(p0), *pp1 = INTEGER(p1), *pi0 = INTEGER(i0), j, k, kend, nd0 = 0, nd1 = 0; pp0++; *(pp1++) = 0; if (class[1] == 'g') { for (j = 0, k = 0; j < r; ++j) { kend = pp0[j]; while (k < kend) { if (pi0[k] < j) ++k; else { if (pi0[k] == j) ++nd0; k = kend; } } pp1[j] = kend - nd0; } for (j = r; j < n_; ++j) pp1[j] = pp0[j] - nd0; } else if (di != 'N') { for (j = 0; j < n_; ++j) pp1[j] = pp0[j]; } else if ((class[2] == 'C') == (ul == 'U')) { for (j = 0, k = 0; j < n_; ++j) { kend = pp0[j]; if (k < kend && pi0[kend - 1] == j) ++nd0; k = kend; pp1[j] = kend - nd0; } } else { for (j = 0, k = 0; j < n_; ++j) { kend = pp0[j]; if (k < kend && pi0[k] == j) ++nd0; k = kend; pp1[j] = kend - nd0; } } #undef DS_LOOP #define DS_LOOP(_CTYPE_, _PTR_, _MASK_, _ISNZ_) \ do { \ _CTYPE_ *pvalue = _PTR_(value); \ if (v) { \ for (j = 0; j < r; ++j) { \ if (_ISNZ_(pvalue[j])) \ ++nd1; \ pp1[j] += nd1; \ } \ for (j = r; j < n_; ++j) \ pp1[j] += nd1; \ } else if (_ISNZ_(pvalue[0])) { \ full = 1; \ for (j = 0; j < r; ++j) \ pp1[j] += ++nd1; \ for (j = r; j < n_; ++j) \ pp1[j] += nd1; \ } \ } while (0) DS_CASES; if (nd1 - nd0 > INT_MAX - pp0[n_ - 1]) error(_("%s cannot exceed %s"), "p[length(p)]", "2^31-1"); SEXP i1 = PROTECT(allocVector(INTSXP, pp1[n_ - 1])); SET_SLOT(to, iSym, i1); int *pi1 = INTEGER(i1); #undef DS_LOOP #define DS_LOOP(_CTYPE_, _PTR_, _MASK_, _ISNZ_) \ do { \ _MASK_(_CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1)); \ _CTYPE_ *pvalue = _PTR_(value); \ for (j = 0, k = 0; j < r; ++j) { \ kend = pp0[j]; \ while (k < kend && pi0[k] < j) { \ *(pi1++) = pi0[k] ; \ _MASK_(*(px1++) = px0[k]); \ ++k; \ } \ if (k < kend && pi0[k] == j) \ ++k; \ if ((v) ? _ISNZ_(pvalue[j]) : full) { \ *(pi1++) = j ; \ _MASK_(*(px1++) = (v) ? pvalue[j] : pvalue[0]); \ } \ while (k < kend) { \ *(pi1++) = pi0[k] ; \ _MASK_(*(px1++) = px0[k]); \ ++k; \ } \ } \ for (j = r; j < n_; ++j) { \ kend = pp0[j]; \ while (k < kend) { \ *(pi1++) = pi0[k] ; \ _MASK_(*(px1++) = px0[k]); \ ++k; \ } \ } \ } while (0) if (class[0] == 'n') DS_LOOP(int, LOGICAL, HIDE, ISNZ_LOGICAL); else { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), pp1[n_ - 1])); SET_SLOT(to, Matrix_xSym, x1); DS_CASES; UNPROTECT(2); /* x1, x0 */ } UNPROTECT(4); /* i1, p1, i0, p0 */ } else { SEXP i0 = PROTECT(GET_SLOT(from, Matrix_iSym)), j0 = PROTECT(GET_SLOT(from, Matrix_jSym)); int *pi0 = INTEGER(i0), *pj0 = INTEGER(j0), j, nd0 = 0, nd1 = 0; R_xlen_t k, nnz0 = XLENGTH(i0), nnz1 = nnz0; if (di == 'N') for (k = 0; k < nnz0; ++k) if (pi0[k] == pj0[k]) ++nd0; #undef DS_LOOP #define DS_LOOP(_CTYPE_, _PTR_, _MASK_, _ISNZ_) \ do { \ _CTYPE_ *pvalue = _PTR_(value); \ if (v) { \ for (j = 0; j < r; ++j) \ if (_ISNZ_(pvalue[j])) \ ++nd1; \ } else if (_ISNZ_(pvalue[0])) { \ full = 1; \ nd1 = r; \ } \ } while (0) DS_CASES; if (nd1 - nd0 > R_XLEN_T_MAX - nnz0) error(_("%s cannot exceed %s"), "length(i)", "R_XLEN_T_MAX"); nnz1 += nd1 - nd0; SEXP i1 = PROTECT(allocVector(INTSXP, nnz1)), j1 = PROTECT(allocVector(INTSXP, nnz1)); SET_SLOT(to, Matrix_iSym, i1); SET_SLOT(to, Matrix_jSym, j1); int *pi1 = INTEGER(i1), *pj1 = INTEGER(j1); #undef DS_LOOP #define DS_LOOP(_CTYPE_, _PTR_, _MASK_, _ISNZ_) \ do { \ _MASK_(_CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1)); \ _CTYPE_ *pvalue = _PTR_(value); \ for (k = 0; k < nnz0; ++k) { \ if (pi0[k] != pj0[k]) { \ *(pi1++) = pi0[k]; \ *(pj1++) = pj0[k]; \ _MASK_(*(px1++) = px0[k]); \ } \ } \ if (v) { \ for (j = 0; j < r; ++j) { \ if (_ISNZ_(pvalue[j])) { \ *(pi1++) = *(pj1++) = j; \ _MASK_(*(px1++) = pvalue[j]); \ } \ } \ } else if (full) { \ for (j = 0; j < r; ++j) { \ *(pi1++) = *(pj1++) = j; \ _MASK_(*(px1++) = pvalue[0]); \ } \ } \ } while (0) if (class[0] == 'n') DS_LOOP(int, LOGICAL, HIDE, ISNZ_LOGICAL); else { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), nnz1)); SET_SLOT(to, Matrix_xSym, x1); DS_CASES; UNPROTECT(2); /* x1, x0 */ } UNPROTECT(4); /* j1, i1, j0, i0 */ } #undef DS_CASES #undef DS_LOOP UNPROTECT(1); /* to */ return to; } /* diag(<[CRT]sparseMatrix>) <- value */ SEXP R_sparse_diag_set(SEXP from, SEXP value) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *class = valid[ivalid]; SEXPTYPE tx = kindToType(class[0]), tv = TYPEOF(value); switch (tv) { case LGLSXP: case INTSXP: case REALSXP: case CPLXSXP: break; default: error(_("replacement diagonal has incompatible type \"%s\""), type2char(tv)); break; } SEXP dim = GET_SLOT(from, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1], r = (m < n) ? m : n; R_xlen_t len = XLENGTH(value); if (len != 1 && len != r) error(_("replacement diagonal has wrong length")); if (tv <= tx) { PROTECT(from); PROTECT(value = coerceVector(value, tx)); } else { /* defined in ./coerce.c : */ SEXP sparse_as_kind(SEXP, const char *, char); #ifndef MATRIX_ENABLE_IMATRIX if (tv == INTSXP) { PROTECT(from = sparse_as_kind(from, class, 'd')); PROTECT(value = coerceVector(value, REALSXP)); } else { #endif PROTECT(from = sparse_as_kind(from, class, typeToKind(tv))); PROTECT(value); #ifndef MATRIX_ENABLE_IMATRIX } #endif class = valid[R_check_class_etc(from, valid)]; } from = sparse_diag_set(from, class, value); UNPROTECT(2); return from; } SEXP sparse_transpose(SEXP from, const char *class, int lazy) { SEXP to; if (class[2] == 'T' || !lazy) PROTECT(to = newObject(class)); else { char cl[] = "...Matrix"; cl[0] = class[0]; cl[1] = class[1]; cl[2] = (class[2] == 'C') ? 'R' : 'C'; PROTECT(to = newObject(cl)); } SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; if (m != n) { UNPROTECT(1); /* dim */ PROTECT(dim = GET_SLOT(to, Matrix_DimSym)); pdim = INTEGER(dim); pdim[0] = n; pdim[1] = m; } else if (n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); if (class[1] == 's') SET_SLOT(to, Matrix_DimNamesSym, dimnames); else set_reversed_DimNames(to, dimnames); UNPROTECT(1); /* dimnames */ if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); char ul = *CHAR(STRING_ELT(uplo, 0)); UNPROTECT(1); /* uplo */ if (ul == 'U') { PROTECT(uplo = mkString("L")); SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); char di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N') SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } else { SEXP factors = PROTECT(GET_SLOT(from, Matrix_factorsSym)); if (LENGTH(factors) > 0) SET_SLOT(to, Matrix_factorsSym, factors); UNPROTECT(1); /* factors */ } } /* It remains to set some subset of 'p', 'i', 'j', and 'x' ... */ if (class[2] == 'T') { /* No need to allocate in this case: need only reverse 'i' and 'j' */ SEXP i0 = PROTECT(GET_SLOT(from, Matrix_iSym)), j0 = PROTECT(GET_SLOT(from, Matrix_jSym)); SET_SLOT(to, Matrix_iSym, j0); SET_SLOT(to, Matrix_jSym, i0); UNPROTECT(2); /* j0, i0 */ if (class[0] != 'n') { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)); SET_SLOT(to, Matrix_xSym, x0); UNPROTECT(1); /* x */ } UNPROTECT(1); /* to */ return to; } /* Now dealing only with [CR]sparseMatrix ... */ SEXP iSym = (class[2] == 'C') ? Matrix_iSym : Matrix_jSym, p0 = PROTECT(GET_SLOT(from, Matrix_pSym)), i0 = PROTECT(GET_SLOT(from, iSym)); if (lazy) { /* No need to allocate in this case: need only reverse 'i' and 'j' */ SEXP jSym = (class[2] == 'C') ? Matrix_jSym : Matrix_iSym; SET_SLOT(to, Matrix_pSym, p0); SET_SLOT(to, jSym, i0); UNPROTECT(2); /* i0, p0 */ if (class[0] != 'n') { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)); SET_SLOT(to, Matrix_xSym, x0); UNPROTECT(1); /* x */ } UNPROTECT(1); /* to */ return to; } int m_ = (class[2] == 'C') ? m : n, n_ = (class[2] == 'C') ? n : m; SEXP p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) m_ + 1)), i1 = PROTECT(allocVector(INTSXP, INTEGER(p0)[n_])); SET_SLOT(to, Matrix_pSym, p1); SET_SLOT(to, iSym, i1); /* defined in ./coerce.c : */ void trans(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, int, int); if (class[0] == 'n') trans(p0, i0, NULL, p1, i1, NULL, m_, n_); else { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), INTEGER(p0)[n_])); SET_SLOT(to, Matrix_xSym, x1); trans(p0, i0, x0, p1, i1, x1, m_, n_); UNPROTECT(2); /* x1, x0 */ } UNPROTECT(5); /* i1, p1, i0, p0, to */ return to; } /* t(<[CRT]sparseMatrix>) */ SEXP R_sparse_transpose(SEXP from, SEXP lazy) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); int lazy_; if (TYPEOF(lazy) != LGLSXP || LENGTH(lazy) < 1 || (lazy_ = LOGICAL(lazy)[0]) == NA_LOGICAL) error(_("invalid '%s' to '%s'"), "lazy", __func__); return sparse_transpose(from, valid[ivalid], lazy_); } SEXP sparse_force_symmetric(SEXP from, const char *class, char ul) { char ul0 = 'U', ul1 = 'U'; if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); ul0 = ul1 = *CHAR(STRING_ELT(uplo, 0)); UNPROTECT(1); /* uplo */ } if (ul != '\0') ul1 = ul; if (class[1] == 's') { /* .s[CRT]Matrix */ if (ul0 == ul1) return from; SEXP to = PROTECT(sparse_transpose(from, class, 0)); if (class[0] == 'z') { /* Need _conjugate_ transpose */ SEXP x1 = PROTECT(GET_SLOT(to, Matrix_xSym)); conjugate(x1); UNPROTECT(1); /* x1 */ } UNPROTECT(1) /* to */; return to; } /* Now handling just .[gt][CRT]Matrix ... */ char cl[] = ".s.Matrix"; cl[0] = class[0]; cl[2] = class[2]; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) error(_("attempt to symmetrize a non-square matrix")); if (n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); set_symmetrized_DimNames(to, dimnames, -1); UNPROTECT(1); /* dimnames */ if (ul1 != 'U') { SEXP uplo = PROTECT(mkString("L")); SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } char di = 'N'; if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); di = *CHAR(STRING_ELT(diag, 0)); UNPROTECT(1); /* diag */ } /* It remains to set some subset of 'p', 'i', 'j', and 'x' ... */ #define FS_CASES \ do { \ switch (class[0]) { \ case 'l': \ FS_SUBCASES(int, LOGICAL, SHOW, 1); \ break; \ case 'i': \ FS_SUBCASES(int, INTEGER, SHOW, 1); \ break; \ case 'd': \ FS_SUBCASES(double, REAL, SHOW, 1.0); \ break; \ case 'z': \ FS_SUBCASES(Rcomplex, COMPLEX, SHOW, Matrix_zone); \ break; \ default: \ break; \ } \ } while (0) if (class[1] == 't' && di == 'N' && ul0 == ul1) { /* No need to allocate in this case: we have the triangle we want */ if (class[2] != 'T') { SEXP p0 = PROTECT(GET_SLOT(from, Matrix_pSym)); SET_SLOT(to, Matrix_pSym, p0); UNPROTECT(1); /* p0 */ } if (class[2] != 'R') { SEXP i0 = PROTECT(GET_SLOT(from, Matrix_iSym)); SET_SLOT(to, Matrix_iSym, i0); UNPROTECT(1); /* i0 */ } if (class[2] != 'C') { SEXP j0 = PROTECT(GET_SLOT(from, Matrix_jSym)); SET_SLOT(to, Matrix_jSym, j0); UNPROTECT(1); /* j0 */ } if (class[0] != 'n') { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)); SET_SLOT(to, Matrix_xSym, x0); UNPROTECT(1); /* x0 */ } UNPROTECT(1); /* to */ return to; } else if (class[2] != 'T') { /* Symmetrizing square .[gt][CR]Matrix ... */ SEXP iSym = (class[2] == 'C') ? Matrix_iSym : Matrix_jSym, p0 = PROTECT(GET_SLOT(from, Matrix_pSym)), p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) n + 1)), i0 = PROTECT(GET_SLOT(from, iSym)); int j, k, kend, *pp0 = INTEGER(p0), *pp1 = INTEGER(p1), *pi0 = INTEGER(i0), nnz0 = pp0[n], nnz1 = 0; pp0++; *(pp1++) = 0; SET_SLOT(to, Matrix_pSym, p1); /* Counting number of nonzero elements in triangle, by "column" ... */ if (class[1] == 't') { if (di != 'N') { /* Have triangular matrix with unit diagonal */ if (ul0 != ul1) { /* Returning identity matrix */ for (j = 0; j < n; ++j) pp1[j] = ++nnz1; } else { /* Returning symmetric matrix with unit diagonal */ for (j = 0; j < n; ++j) pp1[j] = ++nnz1 + pp0[j]; nnz1 += nnz0; } } else if (ul0 == ((class[2] == 'C') ? 'U' : 'L')) { /* Have triangular matrix with non-unit "trailing" diagonal and returning diagonal part */ for (j = 0; j < n; ++j) { if (pp0[j - 1] < pp0[j] && pi0[pp0[j] - 1] == j) ++nnz1; pp1[j] = nnz1; } } else { /* Have triangular matrix with non-unit "leading" diagonal and returning diagonal part */ for (j = 0; j < n; ++j) { if (pp0[j - 1] < pp0[j] && pi0[pp0[j - 1]] == j) ++nnz1; pp1[j] = nnz1; } } } else if (ul1 == ((class[2] == 'C') ? 'U' : 'L')) { /* Have general matrix and returning upper triangle */ for (j = 0, k = 0; j < n; ++j) { kend = pp0[j]; while (k < kend) { if (pi0[k] <= j) ++nnz1; ++k; } pp1[j] = nnz1; } } else { /* Have general matrix and returning lower triangle */ for (j = 0, k = 0; j < n; ++j) { kend = pp0[j]; while (k < kend) { if (pi0[k] >= j) ++nnz1; ++k; } pp1[j] = nnz1; } } /* Now allocating and filling out slots ... */ SEXP i1 = PROTECT(allocVector(INTSXP, nnz1)); int *pi1 = INTEGER(i1); SET_SLOT(to, iSym, i1); #undef FS_SUBCASES #define FS_SUBCASES(_CTYPE_, _PTR_, _MASK_, _ONE_) \ do { \ _MASK_(_CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1)); \ if (class[1] == 't') { \ if (di != 'N') { \ /* Have triangular matrix with unit diagonal */ \ if (ul0 != ul1) { \ /* Returning identity matrix */ \ for (j = 0; j < n; ++j) { \ *(pi1++) = j; \ _MASK_(*(px1++) = _ONE_); \ } \ } else if (ul0 == ((class[2] == 'C') ? 'U' : 'L')) { \ /* Returning symmetric matrix */ \ /* with unit "trailing" diagonal */ \ for (j = 0, k = 0; j < n; ++j) { \ kend = pp0[j]; \ while (k < kend) { \ *(pi1++) = pi0[k]; \ _MASK_(*(px1++) = px0[k]); \ ++k; \ } \ *(pi1++) = j; \ _MASK_(*(px1++) = _ONE_); \ } \ } else { \ /* Returning symmetric matrix */ \ /* with unit "leading" diagonal */ \ for (j = 0, k = 0; j < n; ++j) { \ *(pi1++) = j; \ _MASK_(*(px1++) = _ONE_); \ kend = pp0[j]; \ while (k < kend) { \ *(pi1++) = pi0[k]; \ _MASK_(*(px1++) = px0[k]); \ ++k; \ } \ } \ } \ } else if (ul0 == ((class[2] == 'C') ? 'U' : 'L')) { \ /* Have triangular matrix with non-unit "trailing" */ \ /* diagonal and returning diagonal part */ \ for (j = 0; j < n; ++j) { \ if (pp0[j - 1] < pp0[j] && pi0[pp0[j] - 1] == j) { \ *(pi1++) = j; \ _MASK_(*(px1++) = px0[pp0[j] - 1]); \ } \ } \ } else { \ /* Have triangular matrix with non-unit "leading" */ \ /* diagonal and returning diagonal part */ \ for (j = 0; j < n; ++j) { \ if (pp0[j - 1] < pp0[j] && pi0[pp0[j - 1]] == j) { \ *(pi1++) = j; \ _MASK_(*(px1++) = px0[pp0[j - 1]]); \ } \ } \ } \ } else if (ul1 == ((class[2] == 'C') ? 'U' : 'L')) { \ /* Have general matrix and returning upper triangle */ \ for (j = 0, k = 0; j < n; ++j) { \ kend = pp0[j]; \ while (k < kend) { \ if (pi0[k] <= j) { \ *(pi1++) = pi0[k]; \ _MASK_(*(px1++) = px0[k]); \ } \ ++k; \ } \ } \ } else { \ /* Have general matrix and returning lower triangle */ \ for (j = 0, k = 0; j < n; ++j) { \ kend = pp0[j]; \ while (k < kend) { \ if (pi0[k] >= j) { \ *(pi1++) = pi0[k]; \ _MASK_(*(px1++) = px0[k]); \ } \ ++k; \ } \ } \ } \ } while (0) if (class[0] == 'n') FS_SUBCASES(int, LOGICAL, HIDE, 1); else { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), nnz1)); SET_SLOT(to, Matrix_xSym, x1); FS_CASES; UNPROTECT(2); /* x1, x0 */ } } else { /* Symmetrizing square .[gt]TMatrix ... */ SEXP i0 = PROTECT(GET_SLOT(from, Matrix_iSym)), j0 = PROTECT(GET_SLOT(from, Matrix_jSym)); int *pi0 = INTEGER(i0), *pj0 = INTEGER(j0); R_xlen_t j, k, nnz0 = XLENGTH(i0), nnz1 = 0; /* Counting number of nonzero elements in triangle ... */ if (class[1] == 't' && di != 'N') nnz1 = (ul0 == ul1) ? n + nnz0 : n; else { if (ul1 == 'U') { for (k = 0; k < nnz0; ++k) if (pi0[k] <= pj0[k]) ++nnz1; } else { for (k = 0; k < nnz0; ++k) if (pi0[k] >= pj0[k]) ++nnz1; } } /* Now allocating and filling out slots ... */ SEXP i1 = PROTECT(allocVector(INTSXP, nnz1)), j1 = PROTECT(allocVector(INTSXP, nnz1)); int *pi1 = INTEGER(i1), *pj1 = INTEGER(j1); SET_SLOT(to, Matrix_iSym, i1); SET_SLOT(to, Matrix_jSym, j1); #undef FS_SUBCASES #define FS_SUBCASES(_CTYPE_, _PTR_, _MASK_, _ONE_) \ do { \ _MASK_(_CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1)); \ if (class[1] == 't' && di != 'N') { \ if (ul0 == ul1) { \ Matrix_memcpy(pi1, pi0, nnz0, sizeof(int)); \ Matrix_memcpy(pj1, pj0, nnz0, sizeof(int)); \ _MASK_(Matrix_memcpy(px1, px0, nnz0, sizeof(_CTYPE_))); \ pi1 += nnz0; \ pj1 += nnz0; \ _MASK_(px1 += nnz0); \ } \ for (j = 0; j < n; ++j) { \ *(pi1++) = *(pj1++) = j; \ _MASK_(*(px1++) = _ONE_); \ } \ } else { \ if (ul1 == 'U') { \ for (k = 0; k < nnz0; ++k) { \ if (pi0[k] <= pj0[k]) { \ *(pi1++) = pi0[k]; \ *(pj1++) = pj0[k]; \ _MASK_(*(px1++) = px0[k]); \ } \ } \ } else { \ for (k = 0; k < nnz0; ++k) { \ if (pi0[k] <= pj0[k]) { \ *(pi1++) = pi0[k]; \ *(pj1++) = pj0[k]; \ _MASK_(*(px1++) = px0[k]); \ } \ } \ } \ } \ } while (0) if (class[0] == 'n') FS_SUBCASES(int, LOGICAL, HIDE, 1); else { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), nnz1)); SET_SLOT(to, Matrix_xSym, x1); FS_CASES; UNPROTECT(2); /* x1, x0 */ } } #undef FS_CASES #undef FS_SUBCASES UNPROTECT(5); return to; } /* forceSymmetric(<[CRT]sparseMatrix>, uplo) */ SEXP R_sparse_force_symmetric(SEXP from, SEXP uplo) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); char ul = '\0'; if (uplo != R_NilValue) { if (TYPEOF(uplo) != STRSXP || LENGTH(uplo) < 1 || (uplo = STRING_ELT(uplo, 0)) == NA_STRING || ((ul = *CHAR(uplo)) != 'U' && ul != 'L')) error(_("invalid '%s' to '%s'"), "uplo", __func__); } return sparse_force_symmetric(from, valid[ivalid], ul); } SEXP sparse_symmpart(SEXP from, const char *class) { if (class[0] != 'z' && class[0] != 'd') { /* defined in ./coerce.c : */ SEXP sparse_as_kind(SEXP, const char *, char); from = sparse_as_kind(from, class, 'd'); } if (class[0] != 'z' && class[1] == 's') return from; PROTECT_INDEX pid; PROTECT_WITH_INDEX(from, &pid); char cl[] = ".s.Matrix"; cl[0] = (class[0] != 'z') ? 'd' : 'z'; cl[2] = class[2]; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) error(_("attempt to get symmetric part of non-square matrix")); if (n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); if (class[1] == 's') SET_SLOT(to, Matrix_DimNamesSym, dimnames); else set_symmetrized_DimNames(to, dimnames, -1); UNPROTECT(1); /* dimnames */ char ul = 'U', di = 'N'; if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); di = *CHAR(STRING_ELT(diag, 0)); UNPROTECT(1); /* diag */ } } else if (class[2] == 'R') { SEXP uplo = PROTECT(mkString("L")); ul = 'L'; SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } if (class[2] != 'T') { SEXP iSym = (class[2] == 'C') ? Matrix_iSym : Matrix_jSym, p0 = PROTECT(GET_SLOT(from, Matrix_pSym)), i0 = PROTECT(GET_SLOT(from, iSym)), x0 = PROTECT(GET_SLOT(from, Matrix_xSym)); int j, k, kend, *pp0 = INTEGER(p0) + 1, *pi0 = INTEGER(i0), nnz = pp0[n - 1]; if (class[1] == 'g') { cl[1] = 'g'; REPROTECT(from = sparse_transpose(from, cl, 0), pid); SEXP p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) n + 1)), p0_ = PROTECT(GET_SLOT(from, Matrix_pSym)), i0_ = PROTECT(GET_SLOT(from, iSym)), x0_ = PROTECT(GET_SLOT(from, Matrix_xSym)); int k_, kend_, *pp0_ = INTEGER(p0_) + 1, *pi0_ = INTEGER(i0_), *pp1 = INTEGER(p1); *(pp1++) = 0; for (j = 0, k = 0, k_ = 0; j < n; ++j) { kend = pp0[j]; kend_ = pp0_[j]; pp1[j] = pp1[j - 1]; while (k < kend) { if (pi0[k] > j) k = kend; else { while (k_ < kend_ && pi0_[k_] < pi0[k]) { ++pp1[j]; ++k_; } ++pp1[j]; if (k_ < kend_ && pi0_[k_] == pi0[k]) ++k_; ++k; } } while (k_ < kend_) { if (pi0_[k_] > j) k_ = kend_; else { ++pp1[j]; ++k_; } } } SEXP i1 = PROTECT(allocVector(INTSXP, pp1[n - 1])), x1 = PROTECT(allocVector(kindToType(cl[0]), pp1[n - 1])); int *pi1 = INTEGER(i1); #undef SP_LOOP #define SP_LOOP(_CTYPE_, _PTR_, _ASSIGN_, _INCREMENT_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1), \ *px0_ = _PTR_(x0_); \ for (j = 0, k = 0, k_ = 0; j < n; ++j) { \ kend = pp0[j]; \ kend_ = pp0_[j]; \ while (k < kend) { \ if (pi0[k] > j) \ k = kend; \ else { \ while (k_ < kend_ && pi0_[k_] < pi0[k]) { \ *pi1 = pi0_[k_]; \ _ASSIGN_((*px1), 0.5 * px0_[k_]); \ ++k_; ++pi1; ++px1; \ } \ *pi1 = pi0[k]; \ _ASSIGN_((*px1), 0.5 * px0[k]); \ if (k_ < kend_ && pi0_[k_] == pi0[k]) { \ _INCREMENT_((*px1), 0.5 * px0_[k_]); \ ++k_; \ } \ ++k; ++pi1; ++px1; \ } \ } \ while (k_ < kend_) { \ if (pi0_[k_] > j) \ k_ = kend_; \ else { \ *pi1 = pi0_[k_]; \ _ASSIGN_((*px1), 0.5 * px0_[k_]); \ ++k_; ++pi1; ++px1; \ } \ } \ } \ } while (0) if (cl[0] == 'd') SP_LOOP(double, REAL, ASSIGN_REAL, INCREMENT_REAL); else SP_LOOP(Rcomplex, COMPLEX, ASSIGN_COMPLEX, INCREMENT_COMPLEX); SET_SLOT(to, Matrix_pSym, p1); SET_SLOT(to, iSym, i1); SET_SLOT(to, Matrix_xSym, x1); UNPROTECT(6); /* x1, i1, p1, x0_, i0_, p0_ */ } else if (class[1] == 't') { int leading = (class[2] == 'C') == (ul != 'U'); if (di == 'N') { SEXP x1 = PROTECT(allocVector(kindToType(cl[0]), nnz)); #undef SP_LOOP #define SP_LOOP(_CTYPE_, _PTR_, _ASSIGN_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ if (leading) { \ for (j = 0, k = 0; j < n; ++j) { \ kend = pp0[j]; \ if (k < kend) { \ if (pi0[k] == j) \ *px1 = *px0; \ else \ _ASSIGN_((*px1), 0.5 * (*px0)); \ ++k, ++px0; ++px1; \ while (k < kend) { \ _ASSIGN_((*px1), 0.5 * (*px0)); \ ++k; ++px0; ++px1; \ } \ } \ } \ } else { \ for (j = 0, k = 0; j < n; ++j) { \ kend = pp0[j]; \ if (k < kend) { \ while (k < kend - 1) { \ _ASSIGN_((*px1), 0.5 * (*px0)); \ ++k; ++px0; ++px1; \ } \ if (pi0[k] == j) \ *px1 = *px0; \ else \ _ASSIGN_((*px1), 0.5 * (*px0)); \ ++k; ++px0; ++px1; \ } \ } \ } \ } while (0) if (cl[0] == 'd') SP_LOOP(double, REAL, ASSIGN_REAL); else SP_LOOP(Rcomplex, COMPLEX, ASSIGN_COMPLEX); SET_SLOT(to, Matrix_pSym, p0); SET_SLOT(to, iSym, i0); SET_SLOT(to, Matrix_xSym, x1); UNPROTECT(1); /* x1 */ } else { nnz += n; SEXP p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) n + 1)), i1 = PROTECT(allocVector(INTSXP, nnz)), x1 = PROTECT(allocVector(kindToType(cl[0]), nnz)); int *pp1 = INTEGER(p1), *pi1 = INTEGER(i1); *(pp1++) = 0; #undef SP_LOOP #define SP_LOOP(_CTYPE_, _PTR_, _ASSIGN_, _ONE_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ if (leading) { \ for (j = 0, k = 0; j < n; ++j) { \ kend = pp0[j]; \ pp1[j] = pp1[j - 1] + kend - k + 1; \ *pi1 = j; \ _ASSIGN_((*px1), _ONE_); \ ++pi1, ++px1; \ while (k < kend) { \ *pi1 = *pi0; \ _ASSIGN_((*px1), 0.5 * (*px0)); \ ++k; ++pi0; ++pi1; ++px0; ++px1; \ } \ } \ } else { \ for (j = 0, k = 0; j < n; ++j) { \ kend = pp0[j]; \ pp1[j] = pp1[j - 1] + kend - k + 1; \ while (k < kend) { \ *pi1 = *pi0; \ _ASSIGN_((*px1), 0.5 * (*px0)); \ ++k; ++pi0; ++pi1; ++px0; ++px1; \ } \ *pi1 = j; \ _ASSIGN_((*px1), _ONE_); \ ++pi1; ++px1; \ } \ } \ } while (0) if (cl[0] == 'd') SP_LOOP(double, REAL, ASSIGN_REAL, 1.0); else SP_LOOP(Rcomplex, COMPLEX, ASSIGN_COMPLEX, Matrix_zone); SET_SLOT(to, Matrix_pSym, p1); SET_SLOT(to, iSym, i1); SET_SLOT(to, Matrix_xSym, x1); UNPROTECT(3); /* p1, i1, x1 */ } } else { SET_SLOT(to, Matrix_pSym, p0); SET_SLOT(to, iSym, i0); if (cl[0] == 'd') SET_SLOT(to, Matrix_xSym, x0); else { /* Symmetric part of Hermitian matrix is real part */ SEXP x1 = PROTECT(duplicate(x0)); zeroIm(x1); SET_SLOT(to, Matrix_xSym, x1); UNPROTECT(1); /* x1 */ } } UNPROTECT(3); /* x0, i0, p0 */ } else { SEXP i0 = PROTECT(GET_SLOT(from, Matrix_iSym)), j0 = PROTECT(GET_SLOT(from, Matrix_jSym)), x0 = PROTECT(GET_SLOT(from, Matrix_xSym)); int *pi0 = INTEGER(i0), *pj0 = INTEGER(j0); R_xlen_t k, nnz = XLENGTH(i0); if (class[1] == 'g') { SEXP i1 = PROTECT(allocVector(INTSXP, nnz)), j1 = PROTECT(allocVector(INTSXP, nnz)), x1 = PROTECT(allocVector(kindToType(cl[0]), nnz)); int *pi1 = INTEGER(i1), *pj1 = INTEGER(j1); #undef SP_LOOP #define SP_LOOP(_CTYPE_, _PTR_, _ASSIGN_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ for (k = 0; k < nnz; ++k) { \ if (*pi0 == *pj0) { \ *pi1 = *pi0; \ *pj1 = *pj0; \ *px1 = *px0; \ } else if (*pi0 < *pj0) { \ *pi1 = *pi0; \ *pj1 = *pj0; \ _ASSIGN_((*px1), 0.5 * (*px0)); \ } else { \ *pi1 = *pj0; \ *pj1 = *pi0; \ _ASSIGN_((*px1), 0.5 * (*px0)); \ } \ ++pi0; ++pi1; ++pj0; ++pj1; ++px0; ++px1; \ } \ } while (0) if (cl[0] == 'd') SP_LOOP(double, REAL, ASSIGN_REAL); else SP_LOOP(Rcomplex, COMPLEX, ASSIGN_COMPLEX); SET_SLOT(to, Matrix_iSym, i1); SET_SLOT(to, Matrix_jSym, j1); SET_SLOT(to, Matrix_xSym, x1); UNPROTECT(3); /* x1, j1, i1 */ } else if (class[1] == 't') { if (di == 'N') { SEXP x1 = PROTECT(allocVector(kindToType(cl[0]), nnz)); #undef SP_LOOP #define SP_LOOP(_CTYPE_, _PTR_, _ASSIGN_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ for (k = 0; k < nnz; ++k) { \ if (*pi0 == *pj0) \ *px1 = *px0; \ else \ _ASSIGN_((*px1), 0.5 * (*px0)); \ ++px0; ++px1; \ } \ } while (0) if (cl[0] == 'd') SP_LOOP(double, REAL, ASSIGN_REAL); else SP_LOOP(Rcomplex, COMPLEX, ASSIGN_COMPLEX); SET_SLOT(to, Matrix_iSym, i0); SET_SLOT(to, Matrix_jSym, j0); SET_SLOT(to, Matrix_xSym, x1); UNPROTECT(1); /* x1 */ } else { SEXP i1 = PROTECT(allocVector(INTSXP, nnz + n)), j1 = PROTECT(allocVector(INTSXP, nnz + n)), x1 = PROTECT(allocVector(kindToType(cl[0]), nnz + n)); int j, *pi1 = INTEGER(i1), *pj1 = INTEGER(j1); #undef SP_LOOP #define SP_LOOP(_CTYPE_, _PTR_, _ASSIGN_, _ONE_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ for (k = 0; k < nnz; ++k) { \ *pi1 = *pi0; \ *pj1 = *pj0; \ _ASSIGN_((*px1), 0.5 * (*px0)); \ ++pi0; ++pi1; ++pj0; ++pj1; ++px0; ++px1; \ } \ for (j = 0; j < n; ++j) { \ *pi1 = *pj1 = j; \ _ASSIGN_((*px1), _ONE_); \ ++pi1; ++pj1; ++px1; \ } \ } while (0) if (cl[0] == 'd') SP_LOOP(double, REAL, ASSIGN_REAL, 1.0); else SP_LOOP(Rcomplex, COMPLEX, ASSIGN_COMPLEX, Matrix_zone); SET_SLOT(to, Matrix_iSym, i1); SET_SLOT(to, Matrix_jSym, j1); SET_SLOT(to, Matrix_xSym, x1); UNPROTECT(3); /* x1, j1, i1 */ } } else { SET_SLOT(to, Matrix_iSym, i0); SET_SLOT(to, Matrix_jSym, j0); if (cl[0] == 'd') SET_SLOT(to, Matrix_xSym, x0); else { /* Symmetric part of Hermitian matrix is real part */ SEXP x1 = PROTECT(duplicate(x0)); zeroIm(x1); SET_SLOT(to, Matrix_xSym, x1); UNPROTECT(1); /* x1 */ } } UNPROTECT(3); /* x0, j0, i1 */ } UNPROTECT(2); /* to, from */ return to; } /* symmpart(<[CRT]sparseMatrix>) */ SEXP R_sparse_symmpart(SEXP from) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); return sparse_symmpart(from, valid[ivalid]); } SEXP sparse_skewpart(SEXP from, const char *class) { if (class[0] != 'z' && class[0] != 'd') { /* defined in ./coerce.c : */ SEXP sparse_as_kind(SEXP, const char *, char); from = sparse_as_kind(from, class, 'd'); } PROTECT_INDEX pid; PROTECT_WITH_INDEX(from, &pid); char cl[] = "...Matrix"; cl[0] = (class[0] != 'z') ? 'd' : 'z'; cl[1] = (class[1] != 's') ? 'g' : 's'; cl[2] = class[2]; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) error(_("attempt to get skew-symmetric part of non-square matrix")); if (n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); if (class[1] == 's') SET_SLOT(to, Matrix_DimNamesSym, dimnames); else set_symmetrized_DimNames(to, dimnames, -1); UNPROTECT(1); /* dimnames */ if (class[1] == 's') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); char ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ /* Skew-symmetric part of Hermitian matrix is imaginary part */ if (class[0] != 'z') { if (class[2] != 'T') { SEXP p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) n + 1)); int *pp1 = INTEGER(p1); Matrix_memset(pp1, 0, (R_xlen_t) n + 1, sizeof(int)); SET_SLOT(to, Matrix_pSym, p1); UNPROTECT(1); /* p1 */ } } else { if (class[2] != 'T') { SEXP p0 = PROTECT(GET_SLOT(from, Matrix_pSym)); SET_SLOT(to, Matrix_pSym, p0); UNPROTECT(1); /* p0 */ } if (class[2] != 'R') { SEXP i0 = PROTECT(GET_SLOT(from, Matrix_iSym)); SET_SLOT(to, Matrix_iSym, i0); UNPROTECT(1); /* i0 */ } if (class[2] != 'C') { SEXP j0 = PROTECT(GET_SLOT(from, Matrix_jSym)); SET_SLOT(to, Matrix_jSym, j0); UNPROTECT(1); /* j0 */ } SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = PROTECT(duplicate(x0)); zeroRe(x1); SET_SLOT(to, Matrix_xSym, x1); UNPROTECT(2); /* x1, x0 */ } } else if (class[2] != 'T') { SEXP iSym = (class[2] == 'C') ? Matrix_iSym : Matrix_jSym, p0 = PROTECT(GET_SLOT(from, Matrix_pSym)), i0 = PROTECT(GET_SLOT(from, iSym)), x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) n + 1)); int j, k, kend, k_, kend_, *pp0 = INTEGER(p0), *pi0 = INTEGER(i0), *pp1 = INTEGER(p1); pp0++; *(pp1++) = 0; REPROTECT(from = sparse_transpose(from, cl, 0), pid); SEXP p0_ = PROTECT(GET_SLOT(from, Matrix_pSym)), i0_ = PROTECT(GET_SLOT(from, iSym)), x0_ = PROTECT(GET_SLOT(from, Matrix_xSym)); int *pp0_ = INTEGER(p0_), *pi0_ = INTEGER(i0_), *pp1_; pp0_++; Matrix_Calloc(pp1_, n, int); for (j = 0, k = 0, k_ = 0; j < n; ++j) { kend = pp0[j]; kend_ = pp0_[j]; while (k < kend) { if (pi0[k] >= j) k = kend; else { while (k_ < kend_ && pi0_[k_] < pi0[k]) { ++pp1_[j]; ++pp1_[pi0_[k_]]; ++k_; } ++pp1_[j]; ++pp1_[pi0[k]]; if (k_ < kend_ && pi0_[k_] == pi0[k]) ++k_; ++k; } } while (k_ < kend_) { if (pi0_[k_] >= j) k_ = kend_; else { ++pp1_[j]; ++pp1_[pi0_[k_]]; ++k_; } } } for (j = 0; j < n; ++j) { pp1[j] = pp1[j - 1] + pp1_[j]; pp1_[j] = pp1[j - 1]; } SEXP i1 = PROTECT(allocVector(INTSXP, pp1[n - 1])), x1 = PROTECT(allocVector(kindToType(cl[0]), pp1[n - 1])); int *pi1 = INTEGER(i1); #undef SP_LOOP #define SP_LOOP(_CTYPE_, _PTR_, _ASSIGN_, _INCREMENT_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1), \ *px0_ = _PTR_(x0_); \ for (j = 0, k = 0, k_ = 0; j < n; ++j) { \ kend = pp0[j]; \ kend_ = pp0_[j]; \ while (k < kend) { \ if (pi0[k] >= j) \ k = kend; \ else { \ while (k_ < kend_ && pi0_[k_] < pi0[k]) { \ pi1[pp1_[j]] = pi0_[k_]; \ _ASSIGN_(px1[pp1_[j]], -0.5 * px0_[k_]); \ pi1[pp1_[pi0_[k_]]] = j; \ _ASSIGN_(px1[pp1_[pi0_[k_]]], -px1[pp1_[j]]); \ ++pp1_[j]; \ ++pp1_[pi0_[k_]]; \ ++k_; \ } \ pi1[pp1_[j]] = pi0[k]; \ _ASSIGN_(px1[pp1_[j]], 0.5 * px0[k]); \ if (k_ < kend_ && pi0_[k_] == pi0[k]) { \ _INCREMENT_(px1[pp1_[j]], -0.5 * px0_[k_]); \ ++k_; \ } \ pi1[pp1_[pi0[k]]] = j; \ _ASSIGN_(px1[pp1_[pi0[k]]], -px1[pp1_[j]]); \ ++pp1_[j]; \ ++pp1_[pi0[k]]; \ ++k; \ } \ } \ while (k_ < kend_) { \ if (pi0_[k_] >= j) \ k_ = kend_; \ else { \ pi1[pp1_[j]] = pi0_[k_]; \ _ASSIGN_(px1[pp1_[j]], -0.5 * px0_[k_]); \ pi1[pp1_[pi0_[k_]]] = j; \ _ASSIGN_(px1[pp1_[pi0_[k_]]], -px1[pp1_[j]]); \ ++pp1_[j]; \ ++pp1_[pi0_[k_]]; \ ++k_; \ } \ } \ } \ } while (0) if (cl[0] == 'd') SP_LOOP(double, REAL, ASSIGN_REAL, INCREMENT_REAL); else SP_LOOP(Rcomplex, COMPLEX, ASSIGN_COMPLEX, INCREMENT_COMPLEX); Matrix_Free(pp1_, n); SET_SLOT(to, Matrix_pSym, p1); SET_SLOT(to, iSym, i1); SET_SLOT(to, Matrix_xSym, x1); UNPROTECT(9); /* x1, i1, p1, x0, i0, p0, x0_, i0_, p0_ */ } else { SEXP i0 = PROTECT(GET_SLOT(from, Matrix_iSym)), j0 = PROTECT(GET_SLOT(from, Matrix_jSym)), x0 = PROTECT(GET_SLOT(from, Matrix_xSym)); int *pi0 = INTEGER(i0), *pj0 = INTEGER(j0); R_xlen_t k, nnz0 = XLENGTH(i0), nnz1 = nnz0; for (k = 0; k < nnz0; ++k) if (pi0[k] == pj0[k]) --nnz1; nnz1 *= 2; SEXP i1 = PROTECT(allocVector(INTSXP, nnz1)), j1 = PROTECT(allocVector(INTSXP, nnz1)), x1 = PROTECT(allocVector(kindToType(cl[0]), nnz1)); int *pi1 = INTEGER(i1), *pj1 = INTEGER(j1); #undef SP_LOOP #define SP_LOOP(_CTYPE_, _PTR_, _ASSIGN_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ for (k = 0; k < nnz0; ++k) { \ if (*pi0 != *pj0) { \ *pi1 = *pi0; \ *pj1 = *pj0; \ _ASSIGN_((*px1), 0.5 * (*px0)); \ ++pi1; ++pj1; ++px1; \ *pi1 = *pj0; \ *pj1 = *pi0; \ _ASSIGN_((*px1), -0.5 * (*px0)); \ ++pi1; ++pj1; ++px1; \ } \ ++pi0; ++pj0; ++px0; \ } \ } while (0) if (cl[0] == 'd') SP_LOOP(double, REAL, ASSIGN_REAL); else SP_LOOP(Rcomplex, COMPLEX, ASSIGN_COMPLEX); SET_SLOT(to, Matrix_iSym, i1); SET_SLOT(to, Matrix_jSym, j1); SET_SLOT(to, Matrix_xSym, x1); UNPROTECT(6); /* x1, j1, i1, x0, j0, i0 */ } #undef SP_LOOP UNPROTECT(2); /* to, from */ return to; } /* skewpart(<[CRT]sparseMatrix>) */ SEXP R_sparse_skewpart(SEXP from) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); return sparse_skewpart(from, valid[ivalid]); } int sparse_is_symmetric(SEXP obj, const char *class, int checkDN) { if (class[1] == 's') return 1; if (checkDN) { SEXP dimnames = GET_SLOT(obj, Matrix_DimNamesSym); if (!DimNames_is_symmetric(dimnames)) return 0; } if (class[1] == 't') return sparse_is_diagonal(obj, class); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) return 0; if (n <= 1) return 1; if (class[2] == 'T') { /* defined in ./coerce.c : */ SEXP sparse_as_Csparse(SEXP, const char *); obj = sparse_as_Csparse(obj, class); } PROTECT(obj); SEXP iSym = (class[2] != 'R') ? Matrix_iSym : Matrix_jSym, p0 = PROTECT(GET_SLOT(obj, Matrix_pSym)), i0 = PROTECT(GET_SLOT(obj, iSym)); int i, j, k, kend, *pp_, *pp0 = INTEGER(p0) + 1, *pi0 = INTEGER(i0); Matrix_Calloc(pp_, n, int); Matrix_memcpy(pp_, pp0 - 1, n, sizeof(int)); int ans = 0; #define IS_LOOP(_CTYPE_, _PTR_, _MASK_, _NOTREAL_, _NOTCONJ_) \ do { \ _MASK_(_CTYPE_ *px0 = _PTR_(x0)); \ for (j = 0, k = 0; j < n; ++j) { \ kend = pp0[j]; \ while (k < kend) { \ i = pi0[k]; \ if (i >= j) { \ if (i == j) { \ if (_NOTREAL_(px0[k])) \ goto finish; \ ++pp_[j]; \ } \ k = kend; \ } else { \ if (pp_[i] == pp0[i] || pi0[pp_[i]] != j || \ _NOTCONJ_(px0[k], px0[pp_[i]])) \ goto finish; \ ++pp_[i]; \ ++pp_[j]; \ ++k; \ } \ } \ } \ } while (0) #undef NOTCONJ_PATTERN #define NOTCONJ_PATTERN(_X_, _Y_) 0 /* For all X[i,j], i >= j, we require: o that X[j,i] exists o that X[j,i] == Conj(X[i,j]) o that Im(X[j,i]) == 0 if i == j */ if (class[0] == 'n') IS_LOOP(int, LOGICAL, HIDE, NOTREAL_PATTERN, NOTCONJ_PATTERN); else { SEXP x0 = GET_SLOT(obj, Matrix_xSym); switch (class[0]) { case 'l': IS_LOOP(int, LOGICAL, SHOW, NOTREAL_LOGICAL, NOTCONJ_LOGICAL); break; case 'i': IS_LOOP(int, INTEGER, SHOW, NOTREAL_INTEGER, NOTCONJ_INTEGER); break; case 'd': IS_LOOP(double, REAL, SHOW, NOTREAL_REAL, NOTCONJ_REAL); break; case 'z': IS_LOOP(Rcomplex, COMPLEX, SHOW, NOTREAL_COMPLEX, NOTCONJ_COMPLEX); break; default: break; } } /* We further require that the upper and lower triangles have the same number of entries ... */ for (j = 0; j < n; ++j) if (pp_[j] != pp0[j]) goto finish; ans = 1; finish: Matrix_Free(pp_, n); UNPROTECT(3); /* i0, p0, obj */ #undef IS_LOOP return ans; } /* isSymmetric(<[CRT]sparseMatrix>, checkDN, tol = 0) NB: requires symmetric nonzero pattern TODO: support 'tol', 'scale' arguments and bypass all.equal ?? */ SEXP R_sparse_is_symmetric(SEXP obj, SEXP checkDN) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) ERROR_INVALID_CLASS(obj, __func__); int checkDN_; if (TYPEOF(checkDN) != LGLSXP || LENGTH(checkDN) < 1 || (checkDN_ = LOGICAL(checkDN)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "checkDN", "TRUE", "FALSE"); return ScalarLogical(sparse_is_symmetric(obj, valid[ivalid], checkDN_)); } int sparse_is_triangular(SEXP obj, const char *class, int upper) { if (class[1] == 't') { SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); if (upper == NA_LOGICAL || (upper != 0) == (ul == 'U')) return (ul == 'U') ? 1 : -1; else if (sparse_is_diagonal(obj, class)) return (ul == 'U') ? -1 : 1; else return 0; } if (class[1] == 's') { if (!sparse_is_diagonal(obj, class)) return 0; SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); if (upper == NA_LOGICAL) return (ul == 'U') ? 1 : -1; else return (upper != 0) ? 1 : -1; } SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) return 0; if (n <= 1) return (upper != 0) ? 1 : -1; if (class[2] != 'T') { SEXP iSym = (class[2] == 'C') ? Matrix_iSym : Matrix_jSym, p0 = PROTECT(GET_SLOT(obj, Matrix_pSym)), i0 = PROTECT(GET_SLOT(obj, iSym)); UNPROTECT(2); /* i0, p0 */ int j, k, kend, *pp0 = INTEGER(p0) + 1, *pi0 = INTEGER(i0); if (upper == NA_LOGICAL) { /* Examine last entry in each "column" */ for (j = 0, k = 0; j < n; ++j) { kend = pp0[j]; if (k < kend && pi0[kend - 1] > j) break; k = kend; } if (j == n) return (class[2] == 'C') ? 1 : -1; /* Examine first entry in each "column" */ for (j = 0, k = 0; j < n; ++j) { kend = pp0[j]; if (k < kend && pi0[k] < j) break; k = kend; } if (j == n) return (class[2] == 'C') ? -1 : 1; return 0; } else if ((class[2] == 'C') == (upper != 0)) { /* Examine last entry in each "column" */ for (j = 0, k = 0; j < n; ++j) { kend = pp0[j]; if (k < kend && pi0[kend - 1] > j) return 0; k = kend; } return (class[2] == 'C') ? 1 : -1; } else { /* Examine first entry in each "column" */ for (j = 0, k = 0; j < n; ++j) { kend = pp0[j]; if (k < kend && pi0[k] < j) return 0; k = kend; } return (class[2] == 'C') ? -1 : 1; } } else { SEXP i0 = PROTECT(GET_SLOT(obj, Matrix_iSym)), j0 = PROTECT(GET_SLOT(obj, Matrix_jSym)); UNPROTECT(2); /* i0, j0 */ int *pi0 = INTEGER(i0), *pj0 = INTEGER(j0); R_xlen_t k, nnz0 = XLENGTH(i0); if (upper == NA_LOGICAL) { for (k = 0; k < nnz0; ++k) if (pi0[k] > pj0[k]) break; if (k == nnz0) return 1; for (k = 0; k < nnz0; ++k) if (pi0[k] < pj0[k]) break; if (k == nnz0) return -1; return 0; } else if (upper != 0) { for (k = 0; k < nnz0; ++k) if (pi0[k] > pj0[k]) return 0; return 1; } else { for (k = 0; k < nnz0; ++k) if (pi0[k] < pj0[k]) return 0; return -1; } } } /* isTriangular(<[CRT]sparseMatrix>, upper) NB: requires triangular nonzero pattern */ SEXP R_sparse_is_triangular(SEXP obj, SEXP upper) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) ERROR_INVALID_CLASS(obj, __func__); if (TYPEOF(upper) != LGLSXP || LENGTH(upper) < 1) error(_("'%s' must be %s or %s or %s"), "upper", "TRUE", "FALSE", "NA"); int upper_ = LOGICAL(upper)[0]; int ans_ = sparse_is_triangular(obj, valid[ivalid], upper_); SEXP ans = allocVector(LGLSXP, 1); LOGICAL(ans)[0] = ans_ != 0; if (upper_ == NA_LOGICAL && ans_ != 0) { PROTECT(ans); static SEXP kindSym = NULL; SEXP kindVal = PROTECT(mkString((ans_ > 0) ? "U" : "L")); if (!kindSym) kindSym = install("kind"); setAttrib(ans, kindSym, kindVal); UNPROTECT(2); } return ans; } int sparse_is_diagonal(SEXP obj, const char *class) { SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) return 0; if (n <= 1) return 1; if (class[2] != 'T') { SEXP iSym = (class[2] == 'C') ? Matrix_iSym : Matrix_jSym, p0 = PROTECT(GET_SLOT(obj, Matrix_pSym)), i0 = PROTECT(GET_SLOT(obj, iSym)); UNPROTECT(2); /* i0, p0 */ int j, k, kend, *pp0 = INTEGER(p0) + 1, *pi0 = INTEGER(i0); for (j = 0, k = 0; j < n; ++j) { kend = pp0[j]; if (kend - k > 1 || (kend - k == 1 && pi0[k] != j)) return 0; k = kend; } return 1; } else { SEXP i0 = PROTECT(GET_SLOT(obj, Matrix_iSym)), j0 = PROTECT(GET_SLOT(obj, Matrix_jSym)); UNPROTECT(2); /* i0, j0 */ int *pi0 = INTEGER(i0), *pj0 = INTEGER(j0); R_xlen_t k, nnz0 = XLENGTH(i0); for (k = 0; k < nnz0; ++k) if (*(pi0++) != *(pj0++)) return 0; return 1; } } /* isDiagonal(<[CRT]sparseMatrix>) NB: requires diagonal nonzero pattern */ SEXP R_sparse_is_diagonal(SEXP obj) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) ERROR_INVALID_CLASS(obj, __func__); return ScalarLogical(sparse_is_diagonal(obj, valid[ivalid])); } #define MAP(_I_) work[_I_] #define NOMAP(_I_) _I_ #define CAST_PATTERN(_X_) 1 #define CAST_LOGICAL(_X_) (_X_ != 0) #define CAST_INTEGER(_X_) _X_ #define CAST_REAL(_X_) _X_ #define CAST_COMPLEX(_X_) _X_ #define SUM_CASES(_MAP_) \ do { \ if (class[0] == 'n') { \ if (mean) \ SUM_LOOP(int, LOGICAL, double, REAL, HIDE, \ 0.0, 1.0, NA_REAL, ISNA_PATTERN, \ _MAP_, CAST_PATTERN, INCREMENT_REAL, SCALE2_REAL); \ else \ SUM_LOOP(int, LOGICAL, int, INTEGER, HIDE, \ 0, 1, NA_INTEGER, ISNA_PATTERN, \ _MAP_, CAST_PATTERN, INCREMENT_INTEGER, SCALE2_REAL); \ } else { \ SEXP x0 = PROTECT(GET_SLOT(obj, Matrix_xSym)); \ switch (class[0]) { \ case 'l': \ if (mean) \ SUM_LOOP(int, LOGICAL, double, REAL, SHOW, \ 0.0, 1.0, NA_REAL, ISNA_LOGICAL, \ _MAP_, CAST_LOGICAL, INCREMENT_REAL, SCALE2_REAL); \ else \ SUM_LOOP(int, LOGICAL, int, INTEGER, SHOW, \ 0, 1, NA_INTEGER, ISNA_LOGICAL, \ _MAP_, CAST_LOGICAL, INCREMENT_INTEGER, SCALE2_REAL); \ break; \ case 'i': \ SUM_LOOP(int, INTEGER, double, REAL, SHOW, \ 0.0, 1.0, NA_REAL, ISNA_INTEGER, \ _MAP_, CAST_INTEGER, INCREMENT_REAL, SCALE2_REAL); \ break; \ case 'd': \ SUM_LOOP(double, REAL, double, REAL, SHOW, \ 0.0, 1.0, NA_REAL, ISNA_REAL, \ _MAP_, CAST_REAL, INCREMENT_REAL, SCALE2_REAL); \ break; \ case 'z': \ SUM_LOOP(Rcomplex, COMPLEX, Rcomplex, COMPLEX, SHOW, \ Matrix_zzero, Matrix_zone, Matrix_zna, ISNA_COMPLEX, \ _MAP_, CAST_COMPLEX, INCREMENT_COMPLEX, SCALE2_COMPLEX); \ break; \ default: \ break; \ } \ UNPROTECT(1); /* x0 */ \ } \ } while (0) #define SUM_TYPEOF(c) (c == 'z') ? CPLXSXP : ((mean || c == 'd' || c == 'i') ? REALSXP : INTSXP) static void Csparse_colsum(SEXP obj, const char *class, int m, int n, char di, int narm, int mean, SEXP res) { int narm_ = narm && mean && class[0] != 'n'; SEXP p0 = PROTECT(GET_SLOT(obj, Matrix_pSym)); int *pp0 = INTEGER(p0) + 1, j, k, kend, nnz1 = n, count = -1; if (IS_S4_OBJECT(res)) { if (di == 'N') { nnz1 = 0; for (j = 0; j < n; ++j) if (pp0[j - 1] < pp0[j]) ++nnz1; } SEXP j1 = PROTECT(allocVector(INTSXP, nnz1)), x1 = PROTECT(allocVector(SUM_TYPEOF(class[0]), nnz1)); SET_SLOT(res, Matrix_iSym, j1); SET_SLOT(res, Matrix_xSym, x1); int *pj1 = INTEGER(j1); if (di != 'N') for (j = 0; j < n; ++j) *(pj1++) = j + 1; else for (j = 0; j < n; ++j) if (pp0[j - 1] < pp0[j]) *(pj1++) = j + 1; #define SUM_LOOP(_CTYPE0_, _PTR0_, _CTYPE1_, _PTR1_, _MASK_, \ _ZERO_, _ONE_, _NA_, _ISNA_, \ _MAP_, _CAST_, _INCREMENT_, _SCALE2_) \ do { \ _MASK_(_CTYPE0_ *px0 = _PTR0_(x0)); \ _CTYPE1_ *px1 = _PTR1_(x1) , tmp; \ for (j = 0, k = 0; j < n; ++j) { \ kend = pp0[j]; \ if (k < kend || nnz1 == n) { \ *px1 = (di != 'N') ? _ONE_ : _ZERO_; \ if (mean) \ count = m; \ while (k < kend) { \ if (_ISNA_(*px0)) { \ if (!narm) \ *px1 = _NA_; \ else if (narm_) \ --count; \ } else { \ tmp = _CAST_(*px0); \ _INCREMENT_((*px1), tmp); \ } \ _MASK_(++px0); \ ++k; \ } \ if (mean) \ _SCALE2_((*px1), count); \ ++px1; \ } \ } \ } while (0) SUM_CASES(MAP); UNPROTECT(2); /* x1, j1 */ } else { SEXP x1 = res; SUM_CASES(NOMAP); } #undef SUM_LOOP UNPROTECT(1); /* p0 */ return; } static void Csparse_rowsum(SEXP obj, const char *class, int m, int n, char di, int narm, int mean, SEXP res, SEXP iSym) { int narm_ = narm && mean && class[0] != 'n'; SEXP p0 = PROTECT(GET_SLOT(obj, Matrix_pSym)), i0 = PROTECT(GET_SLOT(obj, iSym)); int *pp0 = INTEGER(p0) + 1, *pi0 = INTEGER(i0), i, j, k, kend, nnz0 = pp0[n - 1], nnz1 = m; if (IS_S4_OBJECT(res)) { int *work; Matrix_Calloc(work, m, int); if (di != 'N') for (i = 0; i < m; ++i) work[i] = i; else { if (class[1] != 's') { for (k = 0; k < nnz0; ++k) ++work[pi0[k]]; } else { for (j = 0, k = 0; j < n; ++j) { kend = pp0[j]; while (k < kend) { ++work[pi0[k]]; if (pi0[k] != j) ++work[ j]; ++k; } } } nnz1 = 0; for (i = 0; i < m; ++i) work[i] = (work[i]) ? nnz1++ : -1; } SEXP i1 = PROTECT(allocVector(INTSXP, nnz1)), x1 = PROTECT(allocVector(SUM_TYPEOF(class[0]), nnz1)); SET_SLOT(res, Matrix_iSym, i1); SET_SLOT(res, Matrix_xSym, x1); int *pi1 = INTEGER(i1); if (narm_) for (i = 0; i < nnz1; ++i) pi1[i] = n; #define SUM_LOOP(_CTYPE0_, _PTR0_, _CTYPE1_, _PTR1_, _MASK_, \ _ZERO_, _ONE_, _NA_, _ISNA_, \ _MAP_, _CAST_, _INCREMENT_, _SCALE2_) \ do { \ _MASK_(_CTYPE0_ *px0 = _PTR0_(x0)); \ _CTYPE1_ *px1 = _PTR1_(x1) ; \ _CTYPE1_ tmp = (di != 'N') ? _ONE_ : _ZERO_; \ for (i = 0; i < nnz1; ++i) \ px1[i] = tmp; \ if (class[1] != 's') { \ for (k = 0; k < nnz0; ++k) { \ if (_ISNA_(px0[k])) { \ if (!narm) \ px1[_MAP_(pi0[k])] = _NA_; \ else if (narm_) \ --pi1[_MAP_(pi0[k])]; \ } else { \ tmp = _CAST_(px0[k]); \ _INCREMENT_(px1[_MAP_(pi0[k])], tmp); \ } \ } \ } else { \ int off; \ for (j = 0, k = 0; j < n; ++j) { \ kend = pp0[j]; \ while (k < kend) { \ off = pi0[k] != j; \ if (_ISNA_(px0[k])) { \ if (!narm) { \ px1[_MAP_(pi0[k])] = _NA_; \ if (off) \ px1[_MAP_( j)] = _NA_; \ } else if (narm_) { \ --pi1[_MAP_(pi0[k])]; \ if (off) \ --pi1[_MAP_( j)]; \ } \ } else { \ tmp = _CAST_(px0[k]); \ _INCREMENT_(px1[_MAP_(pi0[k])], tmp); \ if (off) \ _INCREMENT_(px1[_MAP_( j)], tmp); \ } \ ++k; \ } \ } \ } \ if (mean) { \ if (narm_) \ for (i = 0; i < nnz1; ++i) \ _SCALE2_(px1[i], pi1[i]); \ else \ for (i = 0; i < nnz1; ++i) \ _SCALE2_(px1[i], n); \ } \ } while (0) SUM_CASES(MAP); for (i = 0; i < m; ++i) if (work[i] >= 0) *(pi1++) = i + 1; Matrix_Free(work, m); UNPROTECT(2); /* x1, i1 */ } else { SEXP x1 = res; int *pi1 = NULL; if (narm_) { Matrix_Calloc(pi1, m, int); for (i = 0; i < m; ++i) pi1[i] = n; } SUM_CASES(NOMAP); if (narm_) Matrix_Free(pi1, m); } #undef SUM_LOOP UNPROTECT(2); /* i0, p0 */ return; } static void Tsparse_colsum(SEXP obj, const char *class, int m, int n, char di, int narm, int mean, SEXP res, SEXP iSym, SEXP jSym) { int narm_ = narm && mean && class[0] != 'n'; if (narm_) obj = Tsparse_aggregate(obj); PROTECT(obj); SEXP i0 = PROTECT(GET_SLOT(obj, iSym)), j0 = PROTECT(GET_SLOT(obj, jSym)); int *pi0 = INTEGER(i0), *pj0 = INTEGER(j0), j, nnz1 = n; R_xlen_t k, nnz0 = XLENGTH(i0); if (IS_S4_OBJECT(res)) { int *work; Matrix_Calloc(work, n, int); if (di != 'N') for (j = 0; j < n; ++j) work[j] = j; else { if (class[1] != 's') { for (k = 0; k < nnz0; ++k) ++work[pj0[k]]; } else { for (k = 0; k < nnz0; ++k) { ++work[pj0[k]]; if (pi0[k] != pj0[k]) ++work[pi0[k]]; } } nnz1 = 0; for (j = 0; j < n; ++j) work[j] = (work[j]) ? nnz1++ : -1; } SEXP j1 = PROTECT(allocVector(INTSXP, nnz1)), x1 = PROTECT(allocVector(SUM_TYPEOF(class[0]), nnz1)); SET_SLOT(res, Matrix_iSym, j1); SET_SLOT(res, Matrix_xSym, x1); int *pj1 = INTEGER(j1); if (narm_) for (j = 0; j < nnz1; ++j) pj1[j] = m; #define SUM_LOOP(_CTYPE0_, _PTR0_, _CTYPE1_, _PTR1_, _MASK_, \ _ZERO_, _ONE_, _NA_, _ISNA_, \ _MAP_, _CAST_, _INCREMENT_, _SCALE2_) \ do { \ _MASK_(_CTYPE0_ *px0 = _PTR0_(x0)); \ _CTYPE1_ *px1 = _PTR1_(x1) ; \ _CTYPE1_ tmp = (di != 'N') ? _ONE_ : _ZERO_; \ for (j = 0; j < nnz1; ++j) \ px1[j] = tmp; \ if (class[1] != 's') { \ for (k = 0; k < nnz0; ++k) { \ if (_ISNA_(px0[k])) { \ if (!narm) \ px1[_MAP_(pj0[k])] = _NA_; \ else if (narm_) \ --pj1[_MAP_(pj0[k])]; \ } else { \ tmp = _CAST_(px0[k]); \ _INCREMENT_(px1[_MAP_(pj0[k])], tmp); \ } \ } \ } else { \ int off; \ for (k = 0; k < nnz0; ++k) { \ off = pi0[k] != pj0[k]; \ if (_ISNA_(px0[k])) { \ if (!narm) { \ px1[_MAP_(pj0[k])] = _NA_; \ if (off) \ px1[_MAP_(pi0[k])] = _NA_; \ } else if (narm_) { \ --pj1[_MAP_(pj0[k])]; \ if (off) \ --pj1[_MAP_(pi0[k])]; \ } \ } else { \ tmp = _CAST_(px0[k]); \ _INCREMENT_(px1[_MAP_(pj0[k])], tmp); \ if (off) \ _INCREMENT_(px1[_MAP_(pi0[k])], tmp); \ } \ } \ } \ if (mean) { \ if (narm_) \ for (j = 0; j < nnz1; ++j) \ _SCALE2_(px1[j], pj1[j]); \ else \ for (j = 0; j < nnz1; ++j) \ _SCALE2_(px1[j], m); \ } \ } while (0) SUM_CASES(MAP); for (j = 0; j < n; ++j) if (work[j] >= 0) *(pj1++) = j + 1; Matrix_Free(work, n); UNPROTECT(2); /* x1, j1 */ } else { SEXP x1 = res; int *pj1 = NULL; if (narm_) Matrix_Calloc(pj1, n, int); SUM_CASES(NOMAP); if (narm_) Matrix_Free(pj1, n); } #undef SUM_LOOP UNPROTECT(3); /* j0, i0, obj */ return; } SEXP sparse_marginsum(SEXP obj, const char *class, int margin, int narm, int mean, int sparse) { SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1], r = (margin == 0) ? m : n; SEXP res; SEXPTYPE type = SUM_TYPEOF(class[0]); if (sparse) { char cl[] = ".sparseVector"; cl[0] = (type == CPLXSXP) ? 'z' : ((type == REALSXP) ? 'd' : 'i'); PROTECT(res = newObject(cl)); SEXP length = PROTECT(ScalarInteger(r)); SET_SLOT(res, Matrix_lengthSym, length); UNPROTECT(1); /* length */ } else { PROTECT(res = allocVector(type, r)); SEXP dimnames = (class[1] != 's') ? GET_SLOT(obj, Matrix_DimNamesSym) : get_symmetrized_DimNames(obj, -1), marnames = VECTOR_ELT(dimnames, margin); if (marnames != R_NilValue) { PROTECT(marnames); setAttrib(res, R_NamesSymbol, marnames); UNPROTECT(1); /* marnames */ } } char di = 'N'; if (class[1] == 't') { SEXP diag = GET_SLOT(obj, Matrix_diagSym); di = *CHAR(STRING_ELT(diag, 0)); } if (margin == 0) { if (class[2] == 'C') { Csparse_rowsum(obj, class, m, n, di, narm, mean, res, Matrix_iSym); } else if (class[2] == 'R') { if (class[1] != 's') Csparse_colsum(obj, class, n, m, di, narm, mean, res); else Csparse_rowsum(obj, class, n, m, di, narm, mean, res, Matrix_jSym); } else { Tsparse_colsum(obj, class, n, m, di, narm, mean, res, Matrix_jSym, Matrix_iSym); } } else { if (class[2] == 'C') { if (class[1] != 's') Csparse_colsum(obj, class, m, n, di, narm, mean, res); else Csparse_rowsum(obj, class, m, n, di, narm, mean, res, Matrix_iSym); } else if (class[2] == 'R') { Csparse_rowsum(obj, class, n, m, di, narm, mean, res, Matrix_jSym); } else { Tsparse_colsum(obj, class, m, n, di, narm, mean, res, Matrix_iSym, Matrix_jSym); } } UNPROTECT(1); /* res */ return res; } /* (row|col)(Sums|Means)(<[CRT]sparseMatrix>) */ SEXP R_sparse_marginsum(SEXP obj, SEXP margin, SEXP narm, SEXP mean, SEXP sparse) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) ERROR_INVALID_CLASS(obj, __func__); int margin_; if (TYPEOF(margin) != INTSXP || LENGTH(margin) < 1 || ((margin_ = INTEGER(margin)[0]) != 0 && margin_ != 1)) error(_("'%s' must be %d or %d"), "margin", 0, 1); int narm_; if (TYPEOF(narm) != LGLSXP || LENGTH(narm) < 1 || (narm_ = LOGICAL(narm)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "narm", "TRUE", "FALSE"); int mean_; if (TYPEOF(mean) != LGLSXP || LENGTH(mean) < 1 || (mean_ = LOGICAL(mean)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "mean", "TRUE", "FALSE"); int sparse_; if (TYPEOF(sparse) != LGLSXP || LENGTH(sparse) < 1 || (sparse_ = LOGICAL(sparse)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "sparse", "TRUE", "FALSE"); return sparse_marginsum(obj, valid[ivalid], margin_, narm_, mean_, sparse_); } #undef SUM_CASES #undef SUM_TYPEOF #define TRY_INCREMENT(_LABEL_) \ do { \ if ((s >= 0) \ ? ( t <= MATRIX_INT_FAST64_MAX - s) \ : (-t <= s - MATRIX_INT_FAST64_MIN)) { \ s += t; \ t = 0; \ count = 0; \ } else { \ over = 1; \ goto _LABEL_; \ } \ } while (0) #define LONGDOUBLE_AS_DOUBLE(v) \ (v > DBL_MAX) ? R_PosInf : ((v < -DBL_MAX) ? R_NegInf : (double) v); SEXP sparse_sum(SEXP obj, const char *class, int narm) { if (class[2] == 'T') obj = Tsparse_aggregate(obj); PROTECT(obj); SEXP res; if (!narm && (class[0] == 'l' || class[0] == 'i')) { SEXP x = GET_SLOT(obj, Matrix_xSym); int *px = (class[0] == 'l') ? LOGICAL(x) : INTEGER(x); R_xlen_t nx = XLENGTH(x); while (nx--) { if (*px == NA_INTEGER) { res = allocVector(INTSXP, 1); INTEGER(res)[0] = NA_INTEGER; UNPROTECT(1); /* obj */ return res; } ++px; } } SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; char di = 'N'; if (class[1] == 't') { SEXP diag = GET_SLOT(obj, Matrix_diagSym); di = *CHAR(STRING_ELT(diag, 0)); } int symmetric = class[1] == 's'; if (class[2] != 'T') { SEXP iSym = (class[2] == 'C') ? Matrix_iSym : Matrix_jSym, p = PROTECT(GET_SLOT(obj, Matrix_pSym)), i = PROTECT(GET_SLOT(obj, iSym)); int *pp = INTEGER(p) + 1, *pi = INTEGER(i), j_, k = 0, kend, n_ = (class[2] == 'C') ? n : m; if (class[0] == 'n') { Matrix_int_fast64_t nnz = pp[n_ - 1]; if (di != 'N') nnz += n; if (symmetric) { SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); nnz *= 2; for (j_ = 0; j_ < n_; ++j_) { kend = pp[j_]; if (k < kend && pi[(ul == 'U') ? kend - 1 : k] == j_) --nnz; k = kend; } } if (nnz <= INT_MAX) { res = allocVector(INTSXP, 1); INTEGER(res)[0] = (int) nnz; } else { res = allocVector(REALSXP, 1); REAL(res)[0] = (double) nnz; } UNPROTECT(3); /* i, p, obj */ return res; } SEXP x = GET_SLOT(obj, Matrix_xSym); UNPROTECT(2); /* i, p */ if (class[0] == 'z') { Rcomplex *px = COMPLEX(x); long double zr = (di == 'N') ? 0.0L : n, zi = 0.0L; for (j_ = 0; j_ < n_; ++j_) { kend = pp[j_]; while (k < kend) { if (!(narm && (ISNAN(px[k].r) || ISNAN(px[k].i)))) { zr += (symmetric && pi[k] != j_) ? 2.0L * px[k].r : px[k].r; zi += (symmetric && pi[k] != j_) ? 2.0L * px[k].i : px[k].i; } ++k; } } res = allocVector(CPLXSXP, 1); COMPLEX(res)[0].r = LONGDOUBLE_AS_DOUBLE(zr); COMPLEX(res)[0].i = LONGDOUBLE_AS_DOUBLE(zi); } else if (class[0] == 'd') { double *px = REAL(x); long double zr = (di == 'N') ? 0.0L : n; for (j_ = 0; j_ < n_; ++j_) { kend = pp[j_]; while (k < kend) { if (!(narm && ISNAN(px[k]))) zr += (symmetric && pi[k] != j_) ? 2.0L * px[k] : px[k]; ++k; } } res = allocVector(REALSXP, 1); REAL(res)[0] = LONGDOUBLE_AS_DOUBLE(zr); } else { int *px = (class[0] == 'l') ? LOGICAL(x) : INTEGER(x); Matrix_int_fast64_t s = (di == 'N') ? 0LL : n, t = 0LL; unsigned int count = 0; int over = 0; for (j_ = 0; j_ < n_; ++j_) { kend = pp[j_]; while (k < kend) { if (!narm || px[k] != NA_INTEGER) { int d = (symmetric && pi[k] != j_) ? 2 : 1; if (count > UINT_MAX - d) TRY_INCREMENT(ifoverC); t += (d == 2) ? 2LL * px[k] : px[k]; count += d; } ++k; } } TRY_INCREMENT(ifoverC); ifoverC: if (over) { long double zr = (long double) s + (long double) t; for (; j_ < n_; ++j_) { kend = pp[j_]; while (k < kend) { if (!narm || px[k] != NA_INTEGER) zr += (symmetric && pi[k] != j_) ? 2.0L * px[k] : px[k]; ++k; } } res = allocVector(REALSXP, 1); REAL(res)[0] = LONGDOUBLE_AS_DOUBLE(zr); } else if (s > INT_MIN && s <= INT_MAX) { res = allocVector(INTSXP, 1); INTEGER(res)[0] = (int) s; } else { res = allocVector(REALSXP, 1); REAL(res)[0] = (double) s; } } } else { SEXP i = PROTECT(GET_SLOT(obj, Matrix_iSym)), j = PROTECT(GET_SLOT(obj, Matrix_jSym)); int *pi = INTEGER(i), *pj = INTEGER(j); R_xlen_t k, kend = XLENGTH(i); if (class[0] == 'n') { Matrix_int_fast64_t nnz = (Matrix_int_fast64_t) kend; if (di != 'N') nnz += n; if (symmetric) { nnz *= 2; for (k = 0; k < kend; ++k) if (pi[k] == pj[k]) --nnz; } if (nnz <= INT_MAX) { res = allocVector(INTSXP, 1); INTEGER(res)[0] = (int) nnz; } else { res = allocVector(REALSXP, 1); REAL(res)[0] = (double) nnz; } UNPROTECT(3); /* j, i, obj */ return res; } SEXP x = GET_SLOT(obj, Matrix_xSym); UNPROTECT(2); /* j, i */ if (class[0] == 'z') { Rcomplex *px = COMPLEX(x); long double zr = (di == 'N') ? 0.0L : n, zi = 0.0L; for (k = 0; k < kend; ++k) if (!(narm && (ISNAN(px[k].r) || ISNAN(px[k].i)))) { zr += (symmetric && pi[k] != pj[k]) ? 2.0L * px[k].r : px[k].r; zi += (symmetric && pi[k] != pj[k]) ? 2.0L * px[k].i : px[k].i; } res = allocVector(CPLXSXP, 1); COMPLEX(res)[0].r = LONGDOUBLE_AS_DOUBLE(zr); COMPLEX(res)[0].i = LONGDOUBLE_AS_DOUBLE(zi); } else if (class[0] == 'd') { double *px = REAL(x); long double zr = (di == 'N') ? 0.0L : n; for (k = 0; k < kend; ++k) if (!(narm && ISNAN(px[k]))) zr += (symmetric && pi[k] != pj[k]) ? 2.0L * px[k] : px[k]; res = allocVector(REALSXP, 1); REAL(res)[0] = LONGDOUBLE_AS_DOUBLE(zr); } else { int *px = (class[0] == 'i') ? INTEGER(x) : LOGICAL(x); Matrix_int_fast64_t s = (di == 'N') ? 0LL : n, t = 0LL; unsigned int count = 0; int over = 0; for (k = 0; k < kend; ++k) { if (!narm || px[k] != NA_INTEGER) { int d = (symmetric && pi[k] != pj[k]) ? 2 : 1; if (count > UINT_MAX - d) TRY_INCREMENT(ifoverT); t += (d == 2) ? 2LL * px[k] : px[k]; count += d; } } TRY_INCREMENT(ifoverT); ifoverT: if (over) { long double zr = (long double) s + (long double) t; for (; k < kend; ++k) if (!(narm && px[k] == NA_INTEGER)) zr += (symmetric && pi[k] != pj[k]) ? 2.0L * px[k] : px[k]; res = allocVector(REALSXP, 1); REAL(res)[0] = LONGDOUBLE_AS_DOUBLE(zr); } else if (s > INT_MIN && s <= INT_MAX) { res = allocVector(INTSXP, 1); INTEGER(res)[0] = (int) s; } else { res = allocVector(REALSXP, 1); REAL(res)[0] = (double) s; } } } UNPROTECT(1); /* obj */ return res; } /* sum(<[CRT]sparseMatrix>) */ SEXP R_sparse_sum(SEXP obj, SEXP narm) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) ERROR_INVALID_CLASS(obj, __func__); int narm_; if (TYPEOF(narm) != LGLSXP || LENGTH(narm) < 1 || (narm_ = LOGICAL(narm)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "narm", "TRUE", "FALSE"); return sparse_sum(obj, valid[ivalid], narm_); } SEXP sparse_prod(SEXP obj, const char *class, int narm) { if (class[2] == 'T') obj = Tsparse_aggregate(obj); PROTECT(obj); SEXP res = PROTECT(allocVector((class[0] == 'z') ? CPLXSXP : REALSXP, 1)); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; char ul = 'U', di = 'N'; if (class[1] != 'g') { SEXP uplo = GET_SLOT(obj, Matrix_uploSym); ul = *CHAR(STRING_ELT(uplo, 0)); if (class[1] == 't') { SEXP diag = GET_SLOT(obj, Matrix_diagSym); di = *CHAR(STRING_ELT(diag, 0)); } } int symmetric = (class[1] != 's') ? 0 : (((class[2] == 'C') == (ul == 'U')) ? 1 : -1); long double zr = 1.0L, zi = 0.0L; Matrix_int_fast64_t mn = (Matrix_int_fast64_t) m * n, nnz, nnzmax = (symmetric) ? (mn + n) / 2 : mn; if (class[2] != 'T') { SEXP iSym = (class[2] == 'C') ? Matrix_iSym : Matrix_jSym, p = PROTECT(GET_SLOT(obj, Matrix_pSym)), i = PROTECT(GET_SLOT(obj, iSym)); int *pp = INTEGER(p) + 1, *pi = INTEGER(i), i_, j_, k = 0, kend, m_ = (class[2] == 'C') ? m : n, n_ = (class[2] == 'C') ? n : m, seen0 = 0; nnz = pp[n_ - 1]; if (di != 'N') nnz += n; if (class[0] == 'n') { REAL(res)[0] = (nnz == nnzmax) ? 1.0 : 0.0; UNPROTECT(4); /* i, p, res, obj */ return res; } SEXP x = GET_SLOT(obj, Matrix_xSym); UNPROTECT(2); /* i, p */ if (class[0] == 'z') { Rcomplex *px = COMPLEX(x); long double zr0, zi0; for (j_ = 0; j_ < n_; ++j_) { kend = pp[j_]; if (seen0 || kend - k == m_) { while (k < kend) { if (!(narm && (ISNAN(px[k].r) || ISNAN(px[k].i)))) { zr0 = zr; zi0 = zi; zr = zr0 * px[k].r - zi0 * px[k].i; zi = zr0 * px[k].i + zi0 * px[k].r; if (symmetric && pi[k] != j_) { zr0 = zr; zi0 = zi; zr = zr0 * px[k].r - zi0 * px[k].i; zi = zr0 * px[k].i + zi0 * px[k].r; } } ++k; } } else { int i0 = (symmetric >= 0) ? 0 : j_, i1 = (symmetric <= 0) ? m_ : j_ + 1; for (i_ = i0; i_ < i1; ++i_) { if (seen0 || (k < kend && pi[k] == i_)) { if (k >= kend) break; if (!(narm && (ISNAN(px[k].r) || ISNAN(px[k].i)))) { zr0 = zr; zi0 = zi; zr = zr0 * px[k].r - zi0 * px[k].i; zi = zr0 * px[k].i + zi0 * px[k].r; if (symmetric && pi[k] != j_) { zr0 = zr; zi0 = zi; zr = zr0 * px[k].r - zi0 * px[k].i; zi = zr0 * px[k].i + zi0 * px[k].r; } } ++k; } else if (di == 'N' || i_ != j_) { zr *= 0.0L; zi *= 0.0L; seen0 = 1; } } } } } else if (class[0] == 'd') { double *px = REAL(x); for (j_ = 0; j_ < n_; ++j_) { kend = pp[j_]; if (seen0 || kend - k == m_) { while (k < kend) { if (!(narm && ISNAN(px[k]))) zr *= (symmetric && pi[k] != j_) ? (long double) px[k] * px[k] : px[k]; ++k; } } else { int i0 = (symmetric >= 0) ? 0 : j_, i1 = (symmetric <= 0) ? m_ : j_ + 1; for (i_ = i0; i_ < i1; ++i_) { if (seen0 || (k < kend && pi[k] == i_)) { if (k >= kend) break; if (!(narm && ISNAN(px[k]))) zr *= (symmetric && pi[k] != j_) ? (long double) px[k] * px[k] : px[k]; ++k; } else if (di == 'N' || i_ != j_) { zr *= 0.0L; seen0 = 1; } } } } } else { int *px = (class[0] == 'l') ? LOGICAL(x) : INTEGER(x); for (j_ = 0; j_ < n_; ++j_) { kend = pp[j_]; if (seen0 || kend - k == m_) { while (k < kend) { if (px[k] != NA_INTEGER) zr *= (symmetric && pi[k] != j_) ? (long double) px[k] * px[k] : px[k]; else if (!narm) zr *= NA_REAL; ++k; } } else { int i0 = (symmetric >= 0) ? 0 : j_, i1 = (symmetric <= 0) ? m_ : j_ + 1; for (i_ = i0; i_ < i1; ++i_) { if (seen0 || (k < kend && pi[k] == i_)) { if (k >= kend) break; if (px[k] != NA_INTEGER) zr *= (symmetric && pi[k] != j_) ? (long double) px[k] * px[k] : px[k]; else if (!narm) zr *= NA_REAL; ++k; } else if (di == 'N' || i_ != j_) { zr *= 0.0L; seen0 = 1; } } } } } } else { SEXP i = PROTECT(GET_SLOT(obj, Matrix_iSym)), j = PROTECT(GET_SLOT(obj, Matrix_jSym)); int *pi = INTEGER(i), *pj = INTEGER(j); R_xlen_t k, kend = XLENGTH(i); nnz = (Matrix_int_fast64_t) kend; if (di != 'N') nnz += n; if (class[0] == 'n') { REAL(res)[0] = (nnz == nnzmax) ? 1.0 : 0.0; UNPROTECT(4); /* j, i, res, obj */ return res; } if (nnz < nnzmax) zr = 0.0; SEXP x = GET_SLOT(obj, Matrix_xSym); UNPROTECT(2); /* j, i */ if (class[0] == 'z') { Rcomplex *px = COMPLEX(x); long double zr0, zi0; for (k = 0; k < kend; ++k) if (!(narm && (ISNAN(px[k].r) || ISNAN(px[k].i)))) { zr0 = zr; zi0 = zi; zr = zr0 * px[k].r - zi0 * px[k].i; zi = zr0 * px[k].i + zi0 * px[k].r; if (symmetric && pi[k] != pj[k]) { zr0 = zr; zi0 = zi; zr = zr0 * px[k].r - zi0 * px[k].i; zi = zr0 * px[k].i + zi0 * px[k].r; } } } else if (class[0] == 'd') { double *px = REAL(x); for (k = 0; k < kend; ++k) if (!(narm && ISNAN(px[k]))) zr *= (symmetric && pi[k] != pj[k]) ? (long double) px[k] * px[k] : px[k]; } else { int *px = (class[0] == 'l') ? LOGICAL(x) : INTEGER(x); for (k = 0; k < kend; ++k) if (px[k] != NA_INTEGER) zr *= (symmetric && pi[k] != pj[k]) ? (long double) px[k] * px[k] : px[k]; else if (!narm) zr *= NA_REAL; } } if (class[0] == 'z') { COMPLEX(res)[0].r = LONGDOUBLE_AS_DOUBLE(zr); COMPLEX(res)[0].i = LONGDOUBLE_AS_DOUBLE(zi); } else REAL(res)[0] = LONGDOUBLE_AS_DOUBLE(zr); UNPROTECT(2); /* res, obj */ return res; } /* prod(<[CRT]sparseMatrix>) */ SEXP R_sparse_prod(SEXP obj, SEXP narm) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) ERROR_INVALID_CLASS(obj, __func__); int narm_; if (TYPEOF(narm) != LGLSXP || LENGTH(narm) < 1 || (narm_ = LOGICAL(narm)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "narm", "TRUE", "FALSE"); return sparse_prod(obj, valid[ivalid], narm_); } #undef TRY_INCREMENT #undef LONGDOUBLE_AS_DOUBLE SEXP Tsparse_aggregate(SEXP from) { static const char *valid[] = { VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *cl = valid[ivalid]; SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; UNPROTECT(1); /* dim */ SEXP to, i0 = PROTECT(GET_SLOT(from, Matrix_iSym)), j0 = PROTECT(GET_SLOT(from, Matrix_jSym)), i1 = NULL, j1 = NULL; /* defined in ./coerce.c : */ void taggr(SEXP, SEXP, SEXP, SEXP *, SEXP *, SEXP *, int, int); if (cl[0] == 'n') { taggr(j0, i0, NULL, &j1, &i1, NULL, n, m); if (!i1) { UNPROTECT(2); /* j0, i0 */ return from; } PROTECT(i1); PROTECT(j1); PROTECT(to = newObject(cl)); SET_SLOT(to, Matrix_iSym, i1); SET_SLOT(to, Matrix_jSym, j1); UNPROTECT(5); /* to, j1, i1, j0, i0 */ } else { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = NULL; taggr(j0, i0, x0, &j1, &i1, &x1, n, m); if (!i1) { UNPROTECT(3); /* x0, j0, i0 */ return from; } PROTECT(i1); PROTECT(j1); PROTECT(x1); PROTECT(to = newObject(cl)); SET_SLOT(to, Matrix_iSym, i1); SET_SLOT(to, Matrix_jSym, j1); SET_SLOT(to, Matrix_xSym, x1); UNPROTECT(7); /* to, x1, j1, i1, x0, j0, i0 */ } PROTECT(to); if (m != n || n > 0) { PROTECT(dim = GET_SLOT(to, Matrix_DimSym)); pdim = INTEGER(dim); pdim[0] = m; pdim[1] = n; UNPROTECT(1); /* dim */ } SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ if (cl[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); char ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } if (cl[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); char di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N') SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } else { SEXP factors = PROTECT(GET_SLOT(from, Matrix_factorsSym)); if (LENGTH(factors) > 0) SET_SLOT(to, Matrix_factorsSym, factors); UNPROTECT(1); /* factors */ } UNPROTECT(1); /* to */ return to; } ���������������������������������������Matrix/src/t_subassign.c����������������������������������������������������������������������������0000644�0001751�0000144�00000032115�14575137654�015033� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*------ Definition of a template for [diln]Csparse_subassign(...) : * * -------- ~~~~~~~~~~~~~~~~~~~~~~ * i.e., included several times from ./Csparse.c * ~~~~~~~~~~~ * _slot_kind : use the integer codes matching x_slot_kind in ./Csparse.c */ #ifdef _d_Csp_ # define Csparse_subassign dCsparse_subassign # define x_CLASSES "dgCMatrix",/* 0 */ "dtCMatrix" /* 1 */ # define sparseVECTOR "dsparseVector" # define slot_kind_x 0 # define _DOUBLE_x # define _has_x_slot_ # undef _d_Csp_ #elif defined (_l_Csp_) # define Csparse_subassign lCsparse_subassign # define x_CLASSES "lgCMatrix",/* 0 */ "ltCMatrix" /* 1 */ # define sparseVECTOR "lsparseVector" # define slot_kind_x 1 # define _LGL_x # define _has_x_slot_ # undef _l_Csp_ #elif defined (_i_Csp_) # define Csparse_subassign iCsparse_subassign # define x_CLASSES "igCMatrix",/* 0 */ "itCMatrix" /* 1 */ # define sparseVECTOR "isparseVector" # define slot_kind_x 2 # define _INT_x # define _has_x_slot_ # undef _i_Csp_ #elif defined (_n_Csp_) # define Csparse_subassign nCsparse_subassign # define x_CLASSES "ngCMatrix",/* 0 */ "ntCMatrix" /* 1 */ # define sparseVECTOR "nsparseVector" # define slot_kind_x -1 # define _INT_x /* withOUT 'x' slot -- CARE! we assume that this is the *ONLY* case w/o x slot */ # undef _n_Csp_ #elif defined (_z_Csp_) // # error "zgC* not yet implemented" # define Csparse_subassign zCsparse_subassign # define x_CLASSES "zgCMatrix",/* 0 */ "ztCMatrix" /* 1 */ # define sparseVECTOR "zsparseVector" # define slot_kind_x 3 # define _CPLX_x # define _has_x_slot_ # undef _z_Csp_ #else # error "no valid _[dilnz]gC_ option" #endif // ------------------------------------------------- #ifdef _DOUBLE_x # define Type_x double # define Type_x_0_init(_VAR_) double _VAR_ = 0. # define Type_x_1_init(_VAR_) double _VAR_ = 1. # define STYP_x REAL # define SXP_x REALSXP #undef _DOUBLE_x #elif defined (_LGL_x) # define Type_x int # define Type_x_0_init(_VAR_) int _VAR_ = 0 # define Type_x_1_init(_VAR_) int _VAR_ = 1 # define STYP_x LOGICAL # define SXP_x LGLSXP #undef _LGL_x #elif defined (_INT_x) # define Type_x int # define Type_x_0_init(_VAR_) int _VAR_ = 0 # define Type_x_1_init(_VAR_) int _VAR_ = 1 # define STYP_x INTEGER # define SXP_x INTSXP #undef _INT_x #elif defined (_CPLX_x) # define Type_x Rcomplex # define Type_x_0_init(_VAR_) Rcomplex _VAR_; _VAR_.r = _VAR_.i = 0. # define Type_x_1_init(_VAR_) Rcomplex _VAR_; _VAR_.r = 1.; _VAR_.i = 0. # define STYP_x COMPLEX # define SXP_x CPLXSXP #else # error "invalid macro logic" #endif /** * Subassignment: x[i,j] <- value * * @param x * @param i_ integer row index 0-origin vector (as returned from R .ind.prep2()) * @param j_ integer column index 0-origin vector * @param value must be a [dln]sparseVector {which is recycled if needed} * * @return a Csparse matrix like x, but with the values replaced */ SEXP Csparse_subassign(SEXP x, SEXP i_, SEXP j_, SEXP value) { static const char *valid_cM [] = { // the only ones, for "the moment". FIXME: extend (!) x_CLASSES, ""}, // value: assume a "dsparseVector" for now -- slots: (i, length, x) *valid_spv[] = { sparseVECTOR, // = "the one with the same slot-class" // all others: ctype_v slot_kind "nsparseVector",// 1 -1 "lsparseVector",// 2 1 "isparseVector",// 3 2 "dsparseVector",// 4 0 "zsparseVector",// 5 3 ""}; int ctype_x = R_check_class_etc(x, valid_cM), ctype_v = R_check_class_etc(value, valid_spv); if (ctype_x < 0) error(_("invalid class of 'x' in Csparse_subassign()")); if (ctype_v < 0) error(_("invalid class of 'value' in Csparse_subassign()")); Rboolean value_is_nsp = ctype_v == 1; #ifndef _has_x_slot_ // i.e. "n.CMatrix" : sparseVECTOR == "nsparseVector" if(!value_is_nsp) value_is_nsp = (ctype_v == 0); #endif SEXP islot = GET_SLOT(x, Matrix_iSym), dimslot = GET_SLOT(x, Matrix_DimSym), i_cp = PROTECT(coerceVector(i_, INTSXP)), j_cp = PROTECT(coerceVector(j_, INTSXP)); // for d.CMatrix and l.CMatrix but not n.CMatrix: int *dims = INTEGER(dimslot), ncol = dims[1], /* nrow = dims[0], */ *i = INTEGER(i_cp), len_i = LENGTH(i_cp), *j = INTEGER(j_cp), len_j = LENGTH(j_cp), k, nnz_x = LENGTH(islot); int nnz = nnz_x; #define MATRIX_SUBASSIGN_VERBOSE // Temporary hack for debugging --- remove eventually -- FIXME #ifdef MATRIX_SUBASSIGN_VERBOSE Rboolean verbose = i[0] < 0; if(verbose) { i[0] = -i[0]; REprintf("Csparse_subassign() x[i,j] <- val; x is \"%s\"; value \"%s\" is_nsp=%d\n", valid_cM[ctype_x], valid_spv[ctype_v], (int)value_is_nsp); } #endif SEXP val_i_slot, val_x_slot; val_i_slot = PROTECT(coerceVector(GET_SLOT(value, Matrix_iSym), REALSXP)); double *val_i = REAL(val_i_slot); int nnz_val = LENGTH(GET_SLOT(value, Matrix_iSym)), n_prot = 4; Type_x *val_x = NULL; if(!value_is_nsp) { if(ctype_v) { // matrix 'x' and 'value' are of different kinds switch((enum x_slot_kind) slot_kind_x) { case x_pattern:// "n" case x_logical:// "l" if(ctype_v >= 3) warning(_("x[] <- val: val is coerced to logical for \"%s\" x"), valid_cM[ctype_x]); break; case x_integer: if(ctype_v >= 4) error(_("x[] <- val: val should be integer or logical, is coerced to integer, for \"%s\" x"), valid_cM[ctype_x]); break; case x_double: case x_complex: // coercion should be tried (and fail for complex -> double) below break; default: error(_("programming error in Csparse_subassign() should never happen")); } // otherwise: "coerce" : as(., ) : val_x_slot = PROTECT(coerceVector(GET_SLOT(value, Matrix_xSym), SXP_x)); n_prot++; val_x = STYP_x(val_x_slot); } else { val_x = STYP_x( GET_SLOT(value, Matrix_xSym)); } } int64_t len_val = (int64_t) asReal(GET_SLOT(value, Matrix_lengthSym)); /* llen_i = (int64_t) len_i; */ SEXP ans; /* Instead of simple "duplicate": PROTECT(ans = duplicate(x)) , build up: */ // Assuming that ans will have the same basic Matrix type as x : ans = PROTECT(newObject(valid_cM[ctype_x])); SET_SLOT(ans, Matrix_DimSym, duplicate(dimslot)); SET_SLOT(ans, Matrix_DimNamesSym, duplicate(GET_SLOT(x, Matrix_DimNamesSym))); SET_SLOT(ans, Matrix_pSym, duplicate(GET_SLOT(x, Matrix_pSym))); SEXP r_pslot = GET_SLOT(ans, Matrix_pSym); // and assign the i- and x- slots at the end, as they are potentially modified // not just in content, but also in their *length* int *rp = INTEGER(r_pslot), *ri = R_Calloc(nnz_x, int); // to contain the final i - slot Memcpy(ri, INTEGER(islot), nnz_x); Type_x_0_init(z_ans); Type_x_1_init(one_ans); #ifdef _has_x_slot_ Type_x *rx = R_Calloc(nnz_x, Type_x); // to contain the final x - slot Memcpy(rx, STYP_x(GET_SLOT(x, Matrix_xSym)), nnz_x); #endif // NB: nnz_x : will always be the "current allocated length" of (i, x) slots // -- nnz : the current *used* length; always nnz <= nnz_x int jj, j_val = 0; // in "running" conceptionally through all value[i+ jj*len_i] // values, we are "below"/"before" the (j_val)-th non-zero one. // e.g. if value = (0,0,...,0), have nnz_val == 0, j_val must remain == 0 int64_t ii_val;// == "running" index (i + jj*len_i) % len_val for value[] for(jj = 0, ii_val=0; jj < len_j; jj++) { int j__ = j[jj]; /* int64_t j_l = jj * llen_i; */ R_CheckUserInterrupt(); for(int ii = 0; ii < len_i; ii++, ii_val++) { int i__ = i[ii], p1, p2; if(nnz_val && ii_val >= len_val) { // "recycle" indexing into value[] ii_val -= len_val; // = (ii + jj*len_i) % len_val j_val = 0; } int64_t ii_v1;//= ii_val + 1; Type_x v, /* := value[(ii + j_l) % len_val] = .sparseVector_sub((ii + j_l) % len_val, nnz_val, val_i, val_x, len_val) */ M_ij; int ind; Rboolean have_entry = FALSE; // note that rp[]'s may have *changed* even when 'j' remained! // "FIXME": do this only *when* rp[] has changed p1 = rp[j__], p2 = rp[j__ + 1]; // v := value[(ii + j_l) % len_val] = value[ii_val] v = z_ans; if(j_val < nnz_val) { // maybe find v := non-zero value[ii_val] ii_v1 = ii_val + 1; if(ii_v1 < val_i[j_val]) { // typical case: are still in zero-stretch // v = z_ans (== 0) } else if(ii_v1 == val_i[j_val]) { // have a match v = (value_is_nsp) ? one_ans : val_x[j_val]; j_val++;// from now on, look at the next non-zero entry } else { // ii_v1 > val_i[j_val] REprintf("programming thinko in Csparse_subassign(*, i=%d,j=%d): ii_v=%lld, v@i[j_val=%d]=%g\n", i__,j__, (long long)ii_v1, j_val, val_i[j_val]); j_val++;// from now on, look at the next non-zero entry } } // --------------- M_ij := getM(i., j.) -------------------------------- M_ij = z_ans; // as in ./t_sparseVector.c for(ind = p1; ind < p2; ind++) { if(ri[ind] >= i__) { if(ri[ind] == i__) { #ifdef _has_x_slot_ M_ij = rx[ind]; #else M_ij = 1; #endif #ifdef MATRIX_SUBASSIGN_VERBOSE if(verbose) REprintf("have entry x[%d, %d] = %g\n", i__, j__, # ifdef _CPLX_x (double)M_ij.r); # else (double)M_ij); # endif #endif have_entry = TRUE; } else { // ri[ind] > i__ #ifdef MATRIX_SUBASSIGN_VERBOSE if(verbose) REprintf("@i > i__ = %d --> ind-- = %d\n", i__, ind); #endif } break; } } //-- R: if(getM(i., j.) != (v <- getV(ii, jj))) // if(contents differ) ==> value needs to be changed : #ifdef _CPLX_x if(M_ij.r != v.r || M_ij.i != v.i) { #else if(M_ij != v) { #endif #ifdef MATRIX_SUBASSIGN_VERBOSE if(verbose) REprintf("setting x[%d, %d] <- %g", i__,j__, # ifdef _CPLX_x (double) v.r); # else (double) v); # endif #endif // (otherwise: nothing to do): // setM(i__, j__, v) // ---------------------------------------------------------- #ifndef _has_x_slot_ if(v == z_ans) { // Case I ----- remove x[i, j] = M_ij which we know is *non*-zero // BUT it is more efficient (memory-management!) *NOT* to remove, /// but --- in the case of x slot put a 0 zero there, and only at the very end drop them, // currently using drop0() in R code // we know : have_entry = TRUE ; // ri[ind] == i__; M_ij = rx[ind]; #ifdef MATRIX_SUBASSIGN_VERBOSE if(verbose) REprintf(" rm ind=%d\n", ind); #endif // remove the 'ind'-th element from x@i and x@x : nnz-- ; for(k=ind; k < nnz; k++) { ri[k] = ri[k+1]; #ifdef _has_x_slot_ rx[k] = rx[k+1]; #endif } for(k=j__ + 1; k <= ncol; k++) { rp[k] = rp[k] - 1; } } else #endif if(have_entry) { // Case II ----- replace (non-empty) x[i,j] by v ------- #ifdef MATRIX_SUBASSIGN_VERBOSE if(verbose) REprintf(" repl. ind=%d\n", ind); #endif #ifdef _has_x_slot_ rx[ind] = v; #endif } else { // Case III ----- v != 0 : insert v into "empty" x[i,j] ---- // extend the i and x slot by one entry : --------------------- if(nnz+1 > nnz_x) { // need to reallocate: #ifdef MATRIX_SUBASSIGN_VERBOSE if(verbose) REprintf(" R_Realloc()ing: nnz_x=%d", nnz_x); #endif // do it "only" 1x,..4x at the very most increasing by the // nnz-length of "value": nnz_x += (1 + nnz_val / 4); #ifdef MATRIX_SUBASSIGN_VERBOSE if(verbose) REprintf("(nnz_v=%d) --> %d ", nnz_val, nnz_x); #endif // C doc on realloc() says that the old content is *preserve*d ri = R_Realloc(ri, nnz_x, int); #ifdef _has_x_slot_ rx = R_Realloc(rx, nnz_x, Type_x); #endif } // 3) fill them ... int i1 = ind; #ifdef MATRIX_SUBASSIGN_VERBOSE if(verbose) REprintf(" INSERT p12=(%d,%d) -> ind=%d -> i1 = %d\n", p1,p2, ind, i1); #endif // shift the "upper values" *before* the insertion: for(int l = nnz-1; l >= i1; l--) { ri[l+1] = ri[l]; #ifdef _has_x_slot_ rx[l+1] = rx[l]; #endif } ri[i1] = i__; #ifdef _has_x_slot_ rx[i1] = v; #endif nnz++; // the columns j "right" of the current one : for(k=j__ + 1; k <= ncol; k++) rp[k]++; } } #ifdef MATRIX_SUBASSIGN_VERBOSE else if(verbose) REprintf("M_ij == v = %g\n", # ifdef _CPLX_x (double) v.r); # else (double) v); # endif #endif }// for( ii ) }// for( jj ) if(ctype_x == 1) { // triangularMatrix: copy the 'diag' and 'uplo' slots SET_SLOT(ans, Matrix_uploSym, duplicate(GET_SLOT(x, Matrix_uploSym))); SET_SLOT(ans, Matrix_diagSym, duplicate(GET_SLOT(x, Matrix_diagSym))); } // now assign the i- and x- slots, free memory and return : PROTECT(islot = allocVector(INTSXP, nnz)); Memcpy(INTEGER(islot), ri, nnz); SET_SLOT(ans, Matrix_iSym, islot); UNPROTECT(1); #ifdef _has_x_slot_ PROTECT(islot = allocVector(SXP_x, nnz)); Memcpy(STYP_x(islot), rx, nnz); SET_SLOT(ans, Matrix_xSym, islot); UNPROTECT(1); R_Free(rx); #endif R_Free(ri); UNPROTECT(n_prot); return ans; } #undef Csparse_subassign #undef x_CLASSES #undef sparseVECTOR #undef Type_x #undef STYP_x #undef SXP_x #undef Type_x_0_init #undef Type_x_1_init #undef _has_x_slot_ #undef slot_kind_x #ifdef _CPLX_x # undef _CPLX_x #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/attrib.h���������������������������������������������������������������������������������0000644�0001751�0000144�00000000337�14503225712�013765� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_ATTRIB_H #define MATRIX_ATTRIB_H #include SEXP R_DimNames_is_symmetric(SEXP); SEXP R_symDN(SEXP); SEXP R_revDN(SEXP); SEXP R_set_factor(SEXP, SEXP, SEXP, SEXP); #endif /* MATRIX_ATTRIB_H */ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/cholmod-etc.h����������������������������������������������������������������������������0000644�0001751�0000144�00000000770�14552026002�014672� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_CHOLMOD_ETC_H #define MATRIX_CHOLMOD_ETC_H #include #include "SuiteSparse/SuiteSparse_config/SuiteSparse_config.h" #include "SuiteSparse/CHOLMOD/Include/cholmod.h" extern cholmod_common c ; extern cholmod_common cl; cholmod_factor *M2CHF(SEXP, int); cholmod_sparse *M2CHS(SEXP, int); cholmod_dense *M2CHD(SEXP, int); SEXP CHF2M(cholmod_factor *, int); SEXP CHS2M(cholmod_sparse *, int, char); SEXP CHD2M(cholmod_dense *, int, char); #endif /* MATRIX_CHOLMOD_ETC_H */ ��������Matrix/src/Mdefines.h�������������������������������������������������������������������������������0000644�0001751�0000144�00000022220�14574651213�014234� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_MDEFINES_H #define MATRIX_MDEFINES_H #include "version.h" #define Matrix_Domain "Matrix" #define Matrix_CallocThreshold 8192 #define Matrix_ErrorBufferSize 4096 /* NB: system headers should come before R headers */ #ifdef __GLIBC__ /* ensure that strdup() and others are declared when string.h is included : */ # define _POSIX_C_SOURCE 200809L #endif #include #include #include #include #ifdef INT_FAST64_MAX typedef int_fast64_t Matrix_int_fast64_t; # define MATRIX_INT_FAST64_MIN INT_FAST64_MIN # define MATRIX_INT_FAST64_MAX INT_FAST64_MAX #else typedef long long Matrix_int_fast64_t; # define MATRIX_INT_FAST64_MIN LLONG_MIN # define MATRIX_INT_FAST64_MAX LLONG_MAX #endif #ifndef STRICT_R_HEADERS # define STRICT_R_HEADERS #endif #include #include /* Copy and paste from WRE : */ #ifdef ENABLE_NLS # include # define _(String) dgettext(Matrix_Domain, String) #else # define _(String) (String) # define dngettext(Domain, String, StringP, N) ((N == 1) ? String : StringP) #endif /* Copy and paste from Defn.h : */ /* 'alloca' is neither C99 nor POSIX */ #ifdef __GNUC__ /* This covers GNU, Clang and Intel compilers */ /* #undef needed in case some other header, e.g. malloc.h, already did this */ # undef alloca # define alloca(x) __builtin_alloca((x)) #else # ifdef HAVE_ALLOCA_H /* This covers native compilers on Solaris and AIX */ # include # endif /* It might have been defined via some other standard header, e.g. stdlib.h */ # if !HAVE_DECL_ALLOCA extern void *alloca(size_t); # endif #endif #define Matrix_Calloc(_VAR_, _N_, _CTYPE_) \ do { \ if (_N_ >= Matrix_CallocThreshold) \ _VAR_ = R_Calloc(_N_, _CTYPE_); \ else { \ _VAR_ = (_CTYPE_ *) alloca((size_t) (_N_) * sizeof(_CTYPE_)); \ R_CheckStack(); \ memset(_VAR_, 0, (size_t) (_N_) * sizeof(_CTYPE_)); \ } \ } while (0) #define Matrix_Free(_VAR_, _N_) \ do { \ if (_N_ >= Matrix_CallocThreshold) \ R_Free(_VAR_); \ } while (0) /* Copy and paste from now-deprecated Rdefines.h : */ #ifndef R_DEFINES_H # define GET_SLOT(x, what) R_do_slot(x, what) # define SET_SLOT(x, what, value) R_do_slot_assign(x, what, value) #endif /* Often used symbols, defined in ./init.c */ extern #include "Msymbols.h" /* Often used numbers, defined in ./init.c */ extern Rcomplex Matrix_zzero, Matrix_zone, Matrix_zna; /* 0+0i, 1+0i, NA+NAi */ #define MINOF(x, y) ((x < y) ? x : y) #define MAXOF(x, y) ((x < y) ? y : x) #define FIRSTOF(x, y) (x) #define SECONDOF(x, y) (y) #define ISNA_PATTERN(_X_) (0) #define ISNA_LOGICAL(_X_) ((_X_) == NA_LOGICAL) #define ISNA_INTEGER(_X_) ((_X_) == NA_INTEGER) #define ISNA_REAL(_X_) (ISNAN(_X_)) #define ISNA_COMPLEX(_X_) (ISNAN((_X_).r) || ISNAN((_X_).i)) #define ISNZ_PATTERN(_X_) ((_X_) != 0) #define ISNZ_LOGICAL(_X_) ((_X_) != 0) #define ISNZ_INTEGER(_X_) ((_X_) != 0) #define ISNZ_REAL(_X_) ((_X_) != 0.0) #define ISNZ_COMPLEX(_X_) ((_X_).r != 0.0 || (_X_).i != 0.0) #define STRICTLY_ISNZ_PATTERN(_X_) \ ( ISNZ_PATTERN(_X_)) #define STRICTLY_ISNZ_LOGICAL(_X_) \ (!ISNA_LOGICAL(_X_) && ISNZ_LOGICAL(_X_)) #define STRICTLY_ISNZ_INTEGER(_X_) \ (!ISNA_INTEGER(_X_) && ISNZ_INTEGER(_X_)) #define STRICTLY_ISNZ_REAL(_X_) \ (!ISNA_REAL( _X_) && ISNZ_REAL( _X_)) #define STRICTLY_ISNZ_COMPLEX(_X_) \ (!ISNA_COMPLEX(_X_) && ISNZ_COMPLEX(_X_)) #define NOTREAL_PATTERN(_X_) 0 #define NOTREAL_LOGICAL(_X_) 0 #define NOTREAL_INTEGER(_X_) 0 #define NOTREAL_REAL(_X_) 0 #define NOTREAL_COMPLEX(_X_) (_X_.i != 0.0) #define NOTCONJ_PATTERN(_X_, _Y_) \ ((_X_ != 0) != (_Y_ != 0)) #define NOTCONJ_LOGICAL(_X_, _Y_) \ (_X_ != _Y_) #define NOTCONJ_INTEGER(_X_, _Y_) \ (_X_ != _Y_) #define NOTCONJ_REAL(_X_, _Y_) \ ((ISNAN(_X_)) ? !ISNAN(_Y_) : ISNAN(_Y_) || _X_ != _Y_) #define NOTCONJ_COMPLEX(_X_, _Y_) \ (((ISNAN(_X_.r)) ? !ISNAN(_Y_.r) : ISNAN(_Y_.r) || _X_.r != _Y_.r) || \ ((ISNAN(_X_.i)) ? !ISNAN(_Y_.i) : ISNAN(_Y_.i) || _X_.r != -_Y_.r)) #define INCREMENT_PATTERN(_X_, _Y_) \ do { \ _X_ = 1; \ } while (0) #define INCREMENT_LOGICAL(_X_, _Y_) \ do { \ if (_Y_ == NA_LOGICAL) { \ if (_X_ == 0) \ _X_ = NA_LOGICAL; \ } else if (_Y_ != 0) \ _X_ = 1; \ } while (0) #define INCREMENT_INTEGER(_X_, _Y_) \ do { \ if (_X_ != NA_INTEGER) { \ if (_Y_ == NA_INTEGER) \ _X_ = NA_INTEGER; \ else if ((_Y_ < 0) \ ? (_X_ <= INT_MIN - _Y_) \ : (_X_ > INT_MAX - _Y_)) { \ warning(_("NAs produced by integer overflow")); \ _X_ = NA_INTEGER; \ } else \ _X_ += _Y_; \ } \ } while (0) #define INCREMENT_REAL(_X_, _Y_) \ do { \ _X_ += _Y_; \ } while (0) #define INCREMENT_COMPLEX(_X_, _Y_) \ do { \ _X_.r += _Y_.r; \ _X_.i += _Y_.i; \ } while (0) #define ASSIGN_REAL(_X_, _Y_) \ do { _X_ = _Y_ ; } while (0) #define ASSIGN_COMPLEX(_X_, _Y_) \ do { _X_.r = _Y_.r; _X_.i = _Y_.i; } while (0) #define SCALE1_REAL(_X_, _A_) \ do { _X_ *= _A_; } while (0) #define SCALE1_COMPLEX(_X_, _A_) \ do { _X_.r *= _A_; _X_.i *= _A_; } while (0) #define SCALE2_REAL(_X_, _A_) \ do { _X_ /= _A_; } while (0) #define SCALE2_COMPLEX(_X_, _A_) \ do { _X_.r /= _A_; _X_.i /= _A_; } while (0) #define PACKED_AR21_UP(i, j) \ ((R_xlen_t) ((i) + ((Matrix_int_fast64_t) (j) * ( (j) + 1)) / 2)) #define PACKED_AR21_LO(i, j, m2) \ ((R_xlen_t) ((i) + ((Matrix_int_fast64_t) (j) * ((m2) - (j) - 1)) / 2)) #define PACKED_LENGTH(m) \ ((R_xlen_t) ((m) + ((Matrix_int_fast64_t) (m) * ( (m) - 1)) / 2)) #define SHOW(...) __VA_ARGS__ #define HIDE(...) #define ERROR_INVALID_TYPE(_X_, _FUNC_) \ error(_("invalid type \"%s\" in '%s'"), \ type2char(TYPEOF(_X_)), _FUNC_) #define ERROR_INVALID_CLASS(_X_, _FUNC_) \ do { \ if (!OBJECT(_X_)) \ ERROR_INVALID_TYPE(_X_, _FUNC_); \ else { \ SEXP class = PROTECT(getAttrib(_X_, R_ClassSymbol)); \ error(_("invalid class \"%s\" in '%s'"), \ CHAR(STRING_ELT(class, 0)), _FUNC_); \ UNPROTECT(1); \ } \ } while (0) #define VALID_NONVIRTUAL_MATRIX \ /* 0 */ "dpoMatrix", "dppMatrix", \ /* 2 */ "corMatrix", "copMatrix", \ /* 4 */ "pMatrix", "indMatrix", \ /* 6 */ "ngCMatrix", "ngRMatrix", "ngTMatrix", "ngeMatrix", "ndiMatrix", \ /* 11 */ "nsCMatrix", "nsRMatrix", "nsTMatrix", "nsyMatrix", "nspMatrix", \ /* 16 */ "ntCMatrix", "ntRMatrix", "ntTMatrix", "ntrMatrix", "ntpMatrix", \ /* 21 */ "lgCMatrix", "lgRMatrix", "lgTMatrix", "lgeMatrix", "ldiMatrix", \ /* 26 */ "lsCMatrix", "lsRMatrix", "lsTMatrix", "lsyMatrix", "lspMatrix", \ /* 31 */ "ltCMatrix", "ltRMatrix", "ltTMatrix", "ltrMatrix", "ltpMatrix", \ /* 36 */ "igCMatrix", "igRMatrix", "igTMatrix", "igeMatrix", "idiMatrix", \ /* 41 */ "isCMatrix", "isRMatrix", "isTMatrix", "isyMatrix", "ispMatrix", \ /* 46 */ "itCMatrix", "itRMatrix", "itTMatrix", "itrMatrix", "itpMatrix", \ /* 51 */ "dgCMatrix", "dgRMatrix", "dgTMatrix", "dgeMatrix", "ddiMatrix", \ /* 56 */ "dsCMatrix", "dsRMatrix", "dsTMatrix", "dsyMatrix", "dspMatrix", \ /* 61 */ "dtCMatrix", "dtRMatrix", "dtTMatrix", "dtrMatrix", "dtpMatrix", \ /* 66 */ "zgCMatrix", "zgRMatrix", "zgTMatrix", "zgeMatrix", "zdiMatrix", \ /* 71 */ "zsCMatrix", "zsRMatrix", "zsTMatrix", "zsyMatrix", "zspMatrix", \ /* 76 */ "ztCMatrix", "ztRMatrix", "ztTMatrix", "ztrMatrix", "ztpMatrix" #define VALID_NONVIRTUAL_VECTOR \ /* 81 */ "nsparseVector", "lsparseVector", "isparseVector", \ "dsparseVector", "zsparseVector" #define VALID_NONVIRTUAL VALID_NONVIRTUAL_MATRIX, VALID_NONVIRTUAL_VECTOR /* dpoMatrix->dsyMatrix, etc. */ #define VALID_NONVIRTUAL_SHIFT(i, pToInd) \ ((i >= 5) ? 0 : ((i >= 4) ? pToInd != 0 : ((i >= 2) ? 57 : 59))) #define VALID_DENSE \ "ngeMatrix", "nsyMatrix", "nspMatrix", "ntrMatrix", "ntpMatrix", \ "lgeMatrix", "lsyMatrix", "lspMatrix", "ltrMatrix", "ltpMatrix", \ "igeMatrix", "isyMatrix", "ispMatrix", "itrMatrix", "itpMatrix", \ "dgeMatrix", "dsyMatrix", "dspMatrix", "dtrMatrix", "dtpMatrix", \ "zgeMatrix", "zsyMatrix", "zspMatrix", "ztrMatrix", "ztpMatrix" #define VALID_CSPARSE \ "ngCMatrix", "nsCMatrix", "ntCMatrix", \ "lgCMatrix", "lsCMatrix", "ltCMatrix", \ "igCMatrix", "isCMatrix", "itCMatrix", \ "dgCMatrix", "dsCMatrix", "dtCMatrix", \ "zgCMatrix", "zsCMatrix", "ztCMatrix" #define VALID_RSPARSE \ "ngRMatrix", "nsRMatrix", "ntRMatrix", \ "lgRMatrix", "lsRMatrix", "ltRMatrix", \ "igRMatrix", "isRMatrix", "itRMatrix", \ "dgRMatrix", "dsRMatrix", "dtRMatrix", \ "zgRMatrix", "zsRMatrix", "ztRMatrix" #define VALID_TSPARSE \ "ngTMatrix", "nsTMatrix", "ntTMatrix", \ "lgTMatrix", "lsTMatrix", "ltTMatrix", \ "igTMatrix", "isTMatrix", "itTMatrix", \ "dgTMatrix", "dsTMatrix", "dtTMatrix", \ "zgTMatrix", "zsTMatrix", "ztTMatrix" #define VALID_DIAGONAL \ "ndiMatrix", "ldiMatrix", "idiMatrix", "ddiMatrix", "zdiMatrix" /* What we want declared "everywhere" : */ #include "utils.h" SEXP newObject(const char *); void validObject(SEXP, const char *); char typeToKind(SEXPTYPE); SEXPTYPE kindToType(char); size_t kindToSize(char); int DimNames_is_trivial(SEXP); int DimNames_is_symmetric(SEXP); void symDN(SEXP, SEXP, int); void revDN(SEXP, SEXP); SEXP get_symmetrized_DimNames(SEXP, int); SEXP get_reversed_DimNames(SEXP); void set_symmetrized_DimNames(SEXP, SEXP, int); void set_reversed_DimNames(SEXP, SEXP); #endif /* MATRIX_MDEFINES_H */ ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/utils.c����������������������������������������������������������������������������������0000644�0001751�0000144�00000007676�14504647603�013660� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include /* vsnprintf */ #include "Mdefines.h" #include "utils.h" /* memset() but passing length and size rather than their product which can overflow size_t ... hence _safer_ than Memzero() */ void *Matrix_memset(void *dest, int ch, R_xlen_t length, size_t size) { if (dest && length > 0 && size > 0) { char *dest_ = (char *) dest; size_t N = SIZE_MAX / size; #if (SIZE_MAX < R_XLEN_T_MAX) R_xlen_t S_M = (R_xlen_t) SIZE_MAX; if (length <= S_M) { #endif /* 'length' is representable as size_t : */ size_t n = (size_t) length; if (n <= N) memset(dest_, ch, n * size); else { size_t d = N * size; while (n > N) { memset(dest_, ch, d); dest_ += d; n -= d; } memset(dest_, ch, n * size); } #if (SIZE_MAX < R_XLEN_T_MAX) } else { /* 'length' would overflow size_t : */ size_t n, d = N * size; while (length > S_M) { n = SIZE_MAX; while (n > N) { memset(dest_, ch, d); dest_ += d; n -= d; } memset(dest_, ch, n * size); length -= S_M; } n = (size_t) length; while (n > N) { memset(dest_, ch, d); dest_ += d; n -= d; } memset(dest_, ch, n * size); } #endif } return dest; } /* memcpy() but passing length and size rather than their product which can overflow size_t ... hence _safer_ than Memcpy() */ void *Matrix_memcpy(void *dest, const void *src, R_xlen_t length, size_t size) { if (dest && src && length > 0 && size > 0) { char *dest_ = (char *) dest; const char *src_ = (const char *) src; size_t N = SIZE_MAX / size; #if (SIZE_MAX < R_XLEN_T_MAX) R_xlen_t S_M = (R_xlen_t) SIZE_MAX; if (length <= S_M) { #endif /* 'length' is representable as size_t : */ size_t n = (size_t) length; if (n <= N) memcpy(dest_, src_, n * size); else { size_t d = N * size; while (n > N) { memcpy(dest_, src_, d); dest_ += d; src_ += d; n -= d; } memcpy(dest_, src_, n * size); } #if (SIZE_MAX < R_XLEN_T_MAX) } else { /* 'length' would overflow size_t : */ size_t n, d = N * size; while (length > S_M) { n = SIZE_MAX; while (n > N) { memcpy(dest_, src_, d); dest_ += d; src_ += d; n -= d; } memcpy(dest_, src_, n * size); length -= S_M; } n = (size_t) length; while (n > N) { memcpy(dest_, src_, d); dest_ += d; n -= d; } memcpy(dest_, src_, n * size); } #endif } return dest; } char *Matrix_sprintf(const char *format, ...) { char *buf = R_alloc(Matrix_ErrorBufferSize, sizeof(char)); va_list args; va_start(args, format); vsnprintf(buf, Matrix_ErrorBufferSize, format, args); va_end(args); return buf; } int equal_character_vectors(SEXP s1, SEXP s2, int n) { /* FIXME? not distinguishing between NA_STRING and "NA" */ for (int i = 0; i < n; ++i) if (strcmp(CHAR(STRING_ELT(s1, i)), CHAR(STRING_ELT(s2, i))) != 0) return 0; return 1; } void conjugate(SEXP x) { Rcomplex *px = COMPLEX(x); R_xlen_t nx = XLENGTH(x); while (nx--) { (*px).i = -(*px).i; ++px; } return; } void zeroRe(SEXP x) { Rcomplex *px = COMPLEX(x); R_xlen_t nx = XLENGTH(x); while (nx--) { (*px).r = 0.0; ++px; } return; } void zeroIm(SEXP x) { Rcomplex *px = COMPLEX(x); R_xlen_t nx = XLENGTH(x); while (nx--) { (*px).i = 0.0; ++px; } return; } void naToOne(SEXP x) { R_xlen_t i, n = XLENGTH(x); switch (TYPEOF(x)) { case LGLSXP: { int *px = LOGICAL(x); for (i = 0; i < n; ++i, ++px) if (*px == NA_LOGICAL) *px = 1; break; } case INTSXP: { int *px = INTEGER(x); for (i = 0; i < n; ++i, ++px) if (*px == NA_INTEGER) *px = 1; break; } case REALSXP: { double *px = REAL(x); for (i = 0; i < n; ++i, ++px) if (ISNAN(*px)) *px = 1.0; break; } case CPLXSXP: { Rcomplex *px = COMPLEX(x); for (i = 0; i < n; ++i, ++px) if (ISNAN((*px).r) || ISNAN((*px).i)) *px = Matrix_zone; break; } default: ERROR_INVALID_TYPE(x, __func__); break; } return; } ������������������������������������������������������������������Matrix/src/kappa.c����������������������������������������������������������������������������������0000644�0001751�0000144�00000032554�14567652435�013615� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Lapack-etc.h" #include "Mdefines.h" #include "kappa.h" static char La_norm_type(SEXP s) { #define ARGNAME "type" if (TYPEOF(s) != STRSXP) error(_("argument '%s' is not of type \"%s\""), ARGNAME, "character"); if (LENGTH(s) == 0) error(_("argument '%s' has length %d"), ARGNAME, 0); const char *type = CHAR(STRING_ELT(s, 0)); if (type[0] == '\0' || type[1] != '\0') error(_("argument '%s' (\"%s\") does not have string length %d"), ARGNAME, type, 1); char t = '\0'; switch (type[0]) { case 'M': case 'm': t = 'M'; break; case 'O': case 'o': case '1': t = 'O'; break; case 'I': case 'i': t = 'I'; break; case 'F': case 'f': case 'E': case 'e': t = 'F'; break; default: error(_("argument '%s' (\"%s\") is not \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", or \"%s\""), ARGNAME, type, "M", "O", "1", "I", "F", "E"); break; } return t; #undef ARGNAME } static char La_rcond_type(SEXP s) { #define ARGNAME "norm" if (TYPEOF(s) != STRSXP) error(_("argument '%s' is not of type \"%s\""), ARGNAME, "character"); if (LENGTH(s) == 0) error(_("argument '%s' has length %d"), ARGNAME, 0); const char *type = CHAR(STRING_ELT(s, 0)); if (type[0] == '\0' || type[1] != '\0') error(_("argument '%s' (\"%s\") does not have string length %d"), ARGNAME, type, 1); char t = '\0'; switch (type[0]) { case 'O': case 'o': case '1': t = 'O'; break; case 'I': case 'i': t = 'I'; break; default: error(_("argument '%s' (\"%s\") is not \"%s\", \"%s\", or \"%s\""), ARGNAME, type, "O", "1", "I"); break; } return t; #undef ARGNAME } SEXP dgeMatrix_norm(SEXP obj, SEXP type) { char t = La_norm_type(type); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; if (m == 0 || n == 0) return ScalarReal(0.0); SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)); double norm, *work = NULL; if (t == 'I') work = (double *) R_alloc((size_t) m, sizeof(double)); #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) norm = F77_CALL(zlange)(&t, &m, &n, COMPLEX(x), &m, work FCONE); else #endif norm = F77_CALL(dlange)(&t, &m, &n, REAL(x), &m, work FCONE); UNPROTECT(1); /* x */ return ScalarReal(norm); } SEXP dsyMatrix_norm(SEXP obj, SEXP type) { char t = La_norm_type(type); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int n = INTEGER(dim)[1]; if (n == 0) return ScalarReal(0.0); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)); double norm, *work = NULL; if (t == 'O' || t == 'I') work = (double *) R_alloc((size_t) n, sizeof(double)); #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) norm = F77_CALL(zlansy)(&t, &ul, &n, COMPLEX(x), &n, work FCONE FCONE); else #endif norm = F77_CALL(dlansy)(&t, &ul, &n, REAL(x), &n, work FCONE FCONE); UNPROTECT(1); /* x */ return ScalarReal(norm); } SEXP dspMatrix_norm(SEXP obj, SEXP type) { char t = La_norm_type(type); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int n = INTEGER(dim)[1]; if (n == 0) return ScalarReal(0.0); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = CHAR(STRING_ELT(uplo, 0))[0]; SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)); double norm, *work = NULL; if (t == 'O' || t == 'I') work = (double *) R_alloc((size_t) n, sizeof(double)); #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) norm = F77_CALL(zlansp)(&t, &ul, &n, COMPLEX(x), work FCONE FCONE); else #endif norm = F77_CALL(dlansp)(&t, &ul, &n, REAL(x), work FCONE FCONE); UNPROTECT(1); /* x */ return ScalarReal(norm); } SEXP dtrMatrix_norm(SEXP obj, SEXP type) { char t = La_norm_type(type); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int n = INTEGER(dim)[0]; if (n == 0) return ScalarReal(0.0); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = CHAR(STRING_ELT(uplo, 0))[0]; SEXP diag = GET_SLOT(obj, Matrix_diagSym); char di = CHAR(STRING_ELT(diag, 0))[0]; SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)); double norm, *work = NULL; if (t == 'I') work = (double *) R_alloc((size_t) n, sizeof(double)); #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) norm = F77_CALL(zlantr)(&t, &ul, &di, &n, &n, COMPLEX(x), &n, work FCONE FCONE FCONE); else #endif norm = F77_CALL(dlantr)(&t, &ul, &di, &n, &n, REAL(x), &n, work FCONE FCONE FCONE); UNPROTECT(1); /* x */ return ScalarReal(norm); } SEXP dtpMatrix_norm(SEXP obj, SEXP type) { char t = La_norm_type(type); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int n = INTEGER(dim)[0]; if (n == 0) return ScalarReal(0.0); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = CHAR(STRING_ELT(uplo, 0))[0]; SEXP diag = GET_SLOT(obj, Matrix_diagSym); char di = CHAR(STRING_ELT(diag, 0))[0]; SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)); double norm, *work = NULL; if (t == 'I') work = (double *) R_alloc((size_t) n, sizeof(double)); #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) norm = F77_CALL(zlantp)(&t, &ul, &di, &n, COMPLEX(x), work FCONE FCONE FCONE); else #endif norm = F77_CALL(dlantp)(&t, &ul, &di, &n, REAL(x), work FCONE FCONE FCONE); UNPROTECT(1); /* x */ return ScalarReal(norm); } SEXP dgeMatrix_rcond(SEXP obj, SEXP trf, SEXP type) { char t = La_rcond_type(type); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; if (m != n) error(_("%s(%s) is undefined: '%s' is not square"), "rcond", "x", "x"); if (n == 0) return(ScalarReal(R_PosInf)); SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), y = PROTECT(GET_SLOT(trf, Matrix_xSym)); double norm, rcond; int info; double * work = (double *) R_alloc((size_t) 4 * n, sizeof(double)); #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) { double *rwork = (double *) R_alloc((size_t) 2 * n, sizeof(double)); norm = F77_CALL(zlange)(&t, &n, &n, COMPLEX(x), &n, work FCONE); F77_CALL(zgecon)(&t, &n, COMPLEX(y), &n, &norm, &rcond, (Rcomplex *) work, rwork, &info FCONE); } else { #endif int *iwork = (int *) R_alloc((size_t) n, sizeof(int )); norm = F77_CALL(dlange)(&t, &n, &n, REAL(x), &n, work FCONE); F77_CALL(dgecon)(&t, &n, REAL(y), &n, &norm, &rcond, (double *) work, iwork, &info FCONE); #ifdef MATRIX_ENABLE_ZMATRIX } #endif UNPROTECT(2); /* x, y */ return ScalarReal(rcond); } SEXP dsyMatrix_rcond(SEXP obj, SEXP trf, SEXP type) { char t = La_rcond_type(type); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int n = INTEGER(dim)[0]; if (n == 0) return(ScalarReal(R_PosInf)); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = CHAR(STRING_ELT(uplo, 0))[0]; SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), y = PROTECT(GET_SLOT(trf, Matrix_xSym)), pivot = PROTECT(GET_SLOT(trf, Matrix_permSym)); double norm, rcond; int info; #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) { double * work = (double *) R_alloc((size_t) 4 * n, sizeof(double)); norm = F77_CALL(zlansy)(&t, &ul, &n, COMPLEX(x), &n, work FCONE FCONE); F77_CALL(zsycon)( &ul, &n, COMPLEX(y), &n, INTEGER(pivot), &norm, &rcond, (Rcomplex *) work, &info FCONE); } else { #endif double * work = (double *) R_alloc((size_t) 2 * n, sizeof(double)); int *iwork = (int *) R_alloc((size_t) n, sizeof(int )); norm = F77_CALL(dlansy)(&t, &ul, &n, REAL(x), &n, work FCONE FCONE); F77_CALL(dsycon)( &ul, &n, REAL(y), &n, INTEGER(pivot), &norm, &rcond, (double *) work, iwork, &info FCONE); #ifdef MATRIX_ENABLE_ZMATRIX } #endif UNPROTECT(3); /* x, y, pivot */ return ScalarReal(rcond); } SEXP dspMatrix_rcond(SEXP obj, SEXP trf, SEXP type) { char t = La_rcond_type(type); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int n = INTEGER(dim)[0]; if (n == 0) return(ScalarReal(R_PosInf)); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = CHAR(STRING_ELT(uplo, 0))[0]; SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), y = PROTECT(GET_SLOT(trf, Matrix_xSym)), pivot = PROTECT(GET_SLOT(trf, Matrix_permSym)); double norm, rcond; int info; #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) { double * work = (double *) R_alloc((size_t) 4 * n, sizeof(double)); norm = F77_CALL(zlansp)(&t, &ul, &n, COMPLEX(x), work FCONE FCONE); F77_CALL(zspcon)( &ul, &n, COMPLEX(y), INTEGER(pivot), &norm, &rcond, (Rcomplex *) work, &info FCONE); } else { #endif double * work = (double *) R_alloc((size_t) 2 * n, sizeof(double)); int *iwork = (int *) R_alloc((size_t) n, sizeof(int )); norm = F77_CALL(dlansp)(&t, &ul, &n, REAL(x), work FCONE FCONE); F77_CALL(dspcon)( &ul, &n, REAL(y), INTEGER(pivot), &norm, &rcond, (double *) work, iwork, &info FCONE); #ifdef MATRIX_ENABLE_ZMATRIX } #endif UNPROTECT(3); /* x, y, pivot */ return ScalarReal(rcond); } SEXP dpoMatrix_rcond(SEXP obj, SEXP trf, SEXP type) { char t = La_rcond_type(type); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int n = INTEGER(dim)[0]; if (n == 0) return(ScalarReal(R_PosInf)); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = CHAR(STRING_ELT(uplo, 0))[0]; SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), y = PROTECT(GET_SLOT(trf, Matrix_xSym)); double norm, rcond; int info; #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) { double * work = (double *) R_alloc((size_t) 4 * n, sizeof(double)); double *rwork = (double *) R_alloc((size_t) n, sizeof(double)); norm = F77_CALL(zlansy)(&t, &ul, &n, COMPLEX(x), &n, work FCONE FCONE); F77_CALL(zpocon)( &ul, &n, COMPLEX(y), &n, &norm, &rcond, (Rcomplex *) work, rwork, &info FCONE); } else { #endif double * work = (double *) R_alloc((size_t) 3 * n, sizeof(double)); int *iwork = (int *) R_alloc((size_t) n, sizeof(int )); norm = F77_CALL(dlansy)(&t, &ul, &n, REAL(x), &n, work FCONE FCONE); F77_CALL(dpocon)( &ul, &n, REAL(y), &n, &norm, &rcond, (double *) work, iwork, &info FCONE); #ifdef MATRIX_ENABLE_ZMATRIX } #endif UNPROTECT(2); /* x, y */ return ScalarReal(rcond); } SEXP dppMatrix_rcond(SEXP obj, SEXP trf, SEXP type) { char t = La_rcond_type(type); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int n = INTEGER(dim)[0]; if (n == 0) return(ScalarReal(R_PosInf)); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = CHAR(STRING_ELT(uplo, 0))[0]; SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), y = PROTECT(GET_SLOT(trf, Matrix_xSym)); double norm, rcond; int info; #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) { double * work = (double *) R_alloc((size_t) 4 * n, sizeof(double)); double *rwork = (double *) R_alloc((size_t) n, sizeof(double)); norm = F77_CALL(zlansp)(&t, &ul, &n, COMPLEX(x), work FCONE FCONE); F77_CALL(zppcon)( &ul, &n, COMPLEX(y), &norm, &rcond, (Rcomplex *) work, rwork, &info FCONE); } else { #endif double * work = (double *) R_alloc((size_t) 3 * n, sizeof(double)); int *iwork = (int *) R_alloc((size_t) n, sizeof(int )); norm = F77_CALL(dlansp)(&t, &ul, &n, REAL(x), work FCONE FCONE); F77_CALL(dppcon)( &ul, &n, REAL(y), &norm, &rcond, (double *) work, iwork, &info FCONE); #ifdef MATRIX_ENABLE_ZMATRIX } #endif UNPROTECT(2); /* x, y */ return ScalarReal(rcond); } SEXP dtrMatrix_rcond(SEXP obj, SEXP type) { char t = La_rcond_type(type); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int n = INTEGER(dim)[0]; if (n == 0) return(ScalarReal(R_PosInf)); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = CHAR(STRING_ELT(uplo, 0))[0]; SEXP diag = GET_SLOT(obj, Matrix_diagSym); char di = CHAR(STRING_ELT(diag, 0))[0]; SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)); double rcond; int info; #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) { double * work = (double *) R_alloc((size_t) 4 * n, sizeof(double)); double *rwork = (double *) R_alloc((size_t) n, sizeof(double)); F77_CALL(ztrcon)(&t, &ul, &di, &n, COMPLEX(x), &n, &rcond, (Rcomplex *) work, rwork, &info FCONE FCONE FCONE); } else { #endif double * work = (double *) R_alloc((size_t) 3 * n, sizeof(double)); int *iwork = (int *) R_alloc((size_t) n, sizeof(int )); F77_CALL(dtrcon)(&t, &ul, &di, &n, REAL(x), &n, &rcond, (double *) work, iwork, &info FCONE FCONE FCONE); #ifdef MATRIX_ENABLE_ZMATRIX } #endif UNPROTECT(1); /* x */ return ScalarReal(rcond); } SEXP dtpMatrix_rcond(SEXP obj, SEXP type) { char t = La_rcond_type(type); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int n = INTEGER(dim)[0]; if (n == 0) return(ScalarReal(R_PosInf)); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = CHAR(STRING_ELT(uplo, 0))[0]; SEXP diag = GET_SLOT(obj, Matrix_diagSym); char di = CHAR(STRING_ELT(diag, 0))[0]; SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)); double rcond; int info; #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) { double * work = (double *) R_alloc((size_t) 4 * n, sizeof(double)); double *rwork = (double *) R_alloc((size_t) n, sizeof(double)); F77_CALL(ztpcon)(&t, &ul, &di, &n, COMPLEX(x), &rcond, (Rcomplex *) work, rwork, &info FCONE FCONE FCONE); } else { #endif double * work = (double *) R_alloc((size_t) 3 * n, sizeof(double)); int *iwork = (int *) R_alloc((size_t) n, sizeof(int )); F77_CALL(dtpcon)(&t, &ul, &di, &n, REAL(x), &rcond, (double *) work, iwork, &info FCONE FCONE FCONE); #ifdef MATRIX_ENABLE_ZMATRIX } #endif UNPROTECT(1); /* x */ return ScalarReal(rcond); } ����������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/bind.c�����������������������������������������������������������������������������������0000644�0001751�0000144�00000056334�14574054152�013425� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Mdefines.h" #include "coerce.h" #include "bind.h" static const char *valid[] = { VALID_NONVIRTUAL_MATRIX, "" }; static SEXP tagWasVector = NULL; static void scanArgs(SEXP args, SEXP exprs, int margin, int level, int *rdim, int *rdimnames, char *kind, char *repr) { SEXP a, e, s, tmp; int nS4 = 0, nDense = 0, anyCsparse = 0, anyRsparse = 0, anyTsparse = 0, anyDiagonal = 0, anyN = 0, anyL = 0, anyI = 0, anyD = 0, anyZ = 0, i, ivalid, *sdim; R_xlen_t slen; const char *scl; rdim[!margin] = -1; rdim[ margin] = 0; rdimnames[0] = rdimnames[1] = 0; for (a = args; a != R_NilValue; a = CDR(a)) { s = CAR(a); if (s == R_NilValue) continue; if (TYPEOF(s) == S4SXP) { ++nS4; ivalid = R_check_class_etc(s, valid); if (ivalid < 0) { if (margin) ERROR_INVALID_CLASS(s, "cbind.Matrix"); else ERROR_INVALID_CLASS(s, "rbind.Matrix"); } scl = valid[ivalid + VALID_NONVIRTUAL_SHIFT(ivalid, 1)]; tmp = GET_SLOT(s, Matrix_DimSym); sdim = INTEGER(tmp); if (rdim[!margin] < 0) rdim[!margin] = sdim[!margin]; else if (sdim[!margin] != rdim[!margin]) { if (margin) error(_("number of rows of matrices must match")); else error(_("number of columns of matrices must match")); } if (sdim[margin] > INT_MAX - rdim[margin]) error(_("dimensions cannot exceed %s"), "2^31-1"); rdim[margin] += sdim[margin]; if (!rdimnames[0] || !rdimnames[1]) { tmp = GET_SLOT(s, Matrix_DimNamesSym); if (scl[1] == 's') { if (VECTOR_ELT(tmp, 0) != R_NilValue || VECTOR_ELT(tmp, 1) != R_NilValue) rdimnames[0] = rdimnames[1] = 1; } else for (i = 0; i < 2; ++i) if (!rdimnames[i] && VECTOR_ELT(tmp, i) != R_NilValue) rdimnames[i] = 1; } switch (scl[0]) { case 'n': anyN = 1; break; case 'l': anyL = 1; break; case 'i': if (scl[2] != 'd') anyI = 1; break; case 'd': anyD = 1; break; case 'z': anyZ = 1; break; default: break; } switch (scl[2]) { case 'e': case 'y': case 'r': case 'p': ++nDense; break; case 'C': anyCsparse = 1; break; case 'R': anyRsparse = 1; break; case 'T': { /* defined in ./sparse.c : */ SEXP Tsparse_aggregate(SEXP); SETCAR(a, Tsparse_aggregate(s)); anyTsparse = 1; break; } case 'i': anyDiagonal = 1; break; case 'd': if (INTEGER(GET_SLOT(s, Matrix_marginSym))[0] - 1 != margin) { anyN = 1; if (margin) anyCsparse = 1; else anyRsparse = 1; } break; default: break; } } else { switch (TYPEOF(s)) { case LGLSXP: anyL = 1; break; case INTSXP: anyI = 1; break; case REALSXP: anyD = 1; break; case CPLXSXP: anyZ = 1; break; default: if (margin) ERROR_INVALID_TYPE(s, "cbind.Matrix"); else ERROR_INVALID_TYPE(s, "rbind.Matrix"); break; } tmp = getAttrib(s, R_DimSymbol); if (TYPEOF(tmp) == INTSXP && LENGTH(tmp) == 2) { sdim = INTEGER(tmp); if (rdim[!margin] < 0) rdim[!margin] = sdim[!margin]; else if (rdim[!margin] != sdim[!margin]) { if (margin) error(_("number of rows of matrices must match")); else error(_("number of columns of matrices must match")); } if (sdim[margin] > INT_MAX - rdim[margin]) error(_("dimensions cannot exceed %s"), "2^31-1"); rdim[margin] += sdim[margin]; if (!rdimnames[0] || !rdimnames[1]) { tmp = getAttrib(s, R_DimNamesSymbol); if (tmp != R_NilValue) for (i = 0; i < 2; ++i) if (!rdimnames[i] && VECTOR_ELT(tmp, i) != R_NilValue) rdimnames[i] = 1; } } } } if (rdim[!margin] < 0) { /* Arguments are all vectors or NULL */ R_xlen_t maxlen = -1; for (a = args; a != R_NilValue; a = CDR(a)) { s = CAR(a); if (s == R_NilValue) continue; slen = XLENGTH(s); if (slen > INT_MAX) error(_("dimensions cannot exceed %s"), "2^31-1"); else if (slen > maxlen) maxlen = slen; } if (maxlen < 0) /* Arguments are all NULL */ return; rdim[!margin] = (int) maxlen; } for (a = args, e = exprs; a != R_NilValue; a = CDR(a), e = CDR(e)) { s = CAR(a); if ((s == R_NilValue && rdim[!margin] > 0) || TYPEOF(s) == S4SXP) continue; if (s == R_NilValue) rdim[margin] += 1; else { tmp = getAttrib(s, R_DimSymbol); if (TYPEOF(tmp) == INTSXP && LENGTH(tmp) == 2) continue; slen = XLENGTH(s); if (slen == 0 && rdim[!margin] > 0) continue; if (rdim[margin] == INT_MAX) error(_("dimensions cannot exceed %s"), "2^31-1"); rdim[margin] += 1; if (slen > rdim[!margin] || rdim[!margin] % (int) slen) { if (margin) warning(_("number of rows of result is not a multiple of vector length")); else warning(_("number of columns of result is not a multiple of vector length")); } if (!rdimnames[!margin] && slen == rdim[!margin]) { tmp = getAttrib(s, R_NamesSymbol); if (tmp != R_NilValue) rdimnames[!margin] = 1; } } if (!rdimnames[margin]) { if (TAG(a) != R_NilValue || level == 2 || (level == 1 && TYPEOF(CAR(e)) == SYMSXP)) rdimnames[margin] = 1; } } if (anyZ) *kind = 'z'; #ifndef MATRIX_ENABLE_IMATRIX else if (anyD || anyI) *kind = 'd'; #else else if (anyD) *kind = 'd'; else if (anyI) *kind = 'i'; #endif else if (anyL) *kind = 'l'; else if (anyN) *kind = 'n'; else *kind = '\0'; if (nDense == nS4) *repr = 'e'; else if (nDense == 0) { if (anyCsparse && anyRsparse) *repr = (margin) ? 'C' : 'R'; else if (anyCsparse) *repr = 'C'; else if (anyRsparse) *repr = 'R'; else if (anyTsparse) *repr = 'T'; else if (anyDiagonal) *repr = (margin) ? 'C' : 'R'; else *repr = '\0'; } else { /* The length of the result is at most INT_MAX * INT_MAX, which cannot overflow Matrix_int_fast64_t as long as R builds require sizeof(int) equal to 4 */ Matrix_int_fast64_t nnz = 0, len = 0, snnz = 0, slen = 0; for (a = args; a != R_NilValue && nnz < INT_MAX; a = CDR(a)) { s = CAR(a); if (TYPEOF(s) != S4SXP) continue; ivalid = R_check_class_etc(s, valid); scl = valid[ivalid + VALID_NONVIRTUAL_SHIFT(ivalid, 1)]; PROTECT(tmp = GET_SLOT(s, Matrix_DimSym)); sdim = INTEGER(tmp); slen = (Matrix_int_fast64_t) sdim[0] * sdim[1]; switch (scl[2]) { case 'e': case 'y': case 'r': case 'p': snnz = (scl[1] != 't') ? slen : ((slen + sdim[0]) / 2); break; case 'C': case 'R': { SEXP p = PROTECT(GET_SLOT(s, Matrix_pSym)); int *pp = INTEGER(p), n = sdim[(scl[2] == 'C') ? 1 : 0]; snnz = pp[n]; if (scl[1] == 's') { SEXP iSym = (scl[2] == 'C') ? Matrix_iSym : Matrix_jSym, i = PROTECT(GET_SLOT(s, iSym)); int *pi = INTEGER(i), j; snnz *= 2; if (*CHAR(STRING_ELT(GET_SLOT(s, Matrix_uploSym), 0)) == 'U') { for (j = 0; j < n; ++j) if (pp[j] < pp[j + 1] && pi[pp[j + 1] - 1] == j) --snnz; } else { for (j = 0; j < n; ++j) if (pp[j] < pp[j + 1] && pi[pp[j]] == j) --snnz; } UNPROTECT(1); } else if (scl[1] == 't' && *CHAR(STRING_ELT(GET_SLOT(s, Matrix_diagSym), 0)) != 'N') snnz += sdim[0]; UNPROTECT(1); break; } case 'T': { SEXP i = PROTECT(GET_SLOT(s, Matrix_iSym)); snnz = XLENGTH(i); if (scl[1] == 's') { SEXP j = PROTECT(GET_SLOT(s, Matrix_jSym)); int *pi = INTEGER(i), *pj = INTEGER(j); R_xlen_t k = XLENGTH(i); snnz *= 2; while (k--) if (*(pi++) == *(pj++)) --snnz; UNPROTECT(1); } else if (scl[1] == 't' && *CHAR(STRING_ELT(GET_SLOT(s, Matrix_diagSym), 0)) != 'N') snnz += sdim[0]; UNPROTECT(1); break; } case 'i': snnz = sdim[0]; break; case 'd': snnz = XLENGTH(GET_SLOT(s, Matrix_permSym)); break; default: break; } nnz += snnz; len += slen; UNPROTECT(1); } if (nnz > INT_MAX || nnz > len / 2) *repr = 'e'; else if (anyCsparse && anyRsparse) *repr = (margin) ? 'C' : 'R'; else if (anyCsparse) *repr = 'C'; else if (anyRsparse) *repr = 'R'; else if (anyTsparse) *repr = 'T'; else *repr = (margin) ? 'C' : 'R'; } return; } static void coerceArgs(SEXP args, int margin, int *rdim, char kind, char repr) { SEXP a, s, t, tmp; int ivalid, isM; char scl_[] = "...Matrix"; const char *scl; for (a = args; a != R_NilValue; a = CDR(a)) { s = CAR(a); t = TAG(a); SET_TAG(a, R_NilValue); /* to be replaced only if 's' is a vector */ if (s == R_NilValue) continue; PROTECT_INDEX pid; PROTECT_WITH_INDEX(s, &pid); if (TYPEOF(s) == S4SXP) { ivalid = R_check_class_etc(s, valid); scl = valid[ivalid + VALID_NONVIRTUAL_SHIFT(ivalid, 1)]; switch (scl[2]) { case 'e': case 'y': case 'r': case 'p': switch (repr) { case 'e': REPROTECT(s = dense_as_kind(s, scl, kind, 0), pid); scl_[0] = kind; scl_[1] = scl[1]; scl_[2] = scl[2]; REPROTECT(s = dense_as_general( s, scl_, kindToType(kind) == kindToType(scl[0])), pid); break; case 'C': case 'R': case 'T': REPROTECT(s = dense_as_sparse(s, scl, repr), pid); scl_[0] = scl[0]; scl_[1] = scl[1]; scl_[2] = repr; REPROTECT(s = sparse_as_kind(s, scl_, kind), pid); scl_[0] = kind; REPROTECT(s = sparse_as_general(s, scl_), pid); break; default: break; } break; case 'C': case 'R': case 'T': REPROTECT(s = sparse_as_kind(s, scl, kind), pid); scl_[0] = kind; scl_[1] = scl[1]; scl_[2] = scl[2]; REPROTECT(s = sparse_as_general(s, scl_), pid); scl_[1] = 'g'; switch (repr) { case 'e': REPROTECT(s = sparse_as_dense(s, scl_, 0), pid); break; case 'C': REPROTECT(s = sparse_as_Csparse(s, scl_), pid); break; case 'R': REPROTECT(s = sparse_as_Rsparse(s, scl_), pid); break; case 'T': REPROTECT(s = sparse_as_Tsparse(s, scl_), pid); break; default: break; } break; case 'i': switch (repr) { case 'e': REPROTECT(s = diagonal_as_dense(s, scl_, kind, 'g', 0, '\0'), pid); break; case 'C': case 'R': case 'T': REPROTECT(s = diagonal_as_sparse(s, scl_, kind, 'g', repr, '\0'), pid); break; default: break; } break; case 'd': switch (repr) { case 'e': REPROTECT(s = index_as_dense(s, scl, kind), pid); break; case 'C': case 'R': case 'T': REPROTECT(s = index_as_sparse(s, scl, kind, repr), pid); break; default: break; } break; default: break; } } else { tmp = getAttrib(s, R_DimSymbol); isM = TYPEOF(tmp) == INTSXP && LENGTH(tmp) == 2; if (!isM) { if (rdim[!margin] > 0 && XLENGTH(s) == 0) { UNPROTECT(1); continue; } SET_TAG(a, (t != R_NilValue) ? t : tagWasVector); } if (TYPEOF(s) != kindToType(kind)) REPROTECT(s = coerceVector(s, kindToType(kind)), pid); if (repr != 'e') { if (!isM && XLENGTH(s) != rdim[!margin]) { static SEXP replen = NULL; if (!replen) replen = install("rep_len"); SEXP lengthout = PROTECT(ScalarInteger(rdim[!margin])), call = PROTECT(lang3(replen, s, lengthout)); REPROTECT(s = eval(call, R_GlobalEnv), pid); UNPROTECT(2); } scl_[1] = 'g'; scl_[2] = repr; REPROTECT(s = matrix_as_sparse(s, scl_, '\0', '\0', !margin), pid); } } SETCAR(a, s); UNPROTECT(1); } return; } static void bindArgs(SEXP args, int margin, SEXP res, int *rdim, char kind, char repr) { SEXP a, s; #define BIND_CASES(_BIND_) \ do { \ switch (kind) { \ case 'l': \ _BIND_(int, LOGICAL, SHOW); \ break; \ case 'i': \ _BIND_(int, INTEGER, SHOW); \ break; \ case 'd': \ _BIND_(double, REAL, SHOW); \ break; \ case 'z': \ _BIND_(Rcomplex, COMPLEX, SHOW); \ break; \ default: \ break; \ } \ } while (0) if (repr == 'e') { if (rdim[0] == 0 || rdim[1] == 0) return; int k, m = rdim[0], n = rdim[1]; R_xlen_t mn = (R_xlen_t) m * n; SEXP x = PROTECT(allocVector(kindToType(kind), mn)), tmp; SET_SLOT(res, Matrix_xSym, x); #define BIND_E(_CTYPE_, _PTR_, _MASK_) \ do { \ _CTYPE_ *px = _PTR_(x), *ps; \ for (a = args; a != R_NilValue; a = CDR(a)) { \ s = CAR(a); \ if (s == R_NilValue) \ continue; \ if (TYPEOF(s) != S4SXP) \ tmp = getAttrib(s, R_DimSymbol); \ else { \ s = GET_SLOT(s, Matrix_xSym); \ tmp = NULL; \ } \ mn = XLENGTH(s); \ ps = _PTR_(s); \ if (margin) { \ if (!tmp || (TYPEOF(tmp) == INTSXP && LENGTH(tmp) == 2)) { \ Matrix_memcpy(px, ps, mn, sizeof(_CTYPE_)); \ px += mn; \ } else if (mn >= m) { \ Matrix_memcpy(px, ps, m , sizeof(_CTYPE_)); \ px += m; \ } else if (mn == 1) { \ _CTYPE_ v = ps[0]; \ for (k = 0; k < m; ++k) \ *(px++) = v; \ } else { \ int mn_ = (int) mn; \ for (k = 0; k < rdim[0]; ++k) \ *(px++) = ps[k % mn_]; \ } \ } else { \ _CTYPE_ *py = px; \ if (!tmp || (TYPEOF(tmp) == INTSXP && LENGTH(tmp) == 2)) { \ m = (int) (mn / n); \ for (k = 0; k < n; ++k) { \ Matrix_memcpy(py, ps, m, sizeof(_CTYPE_)); \ py += rdim[0]; \ ps += m; \ } \ px += m; \ } else if (mn >= n) { \ for (k = 0; k < n; ++k) { \ *py = *ps; \ py += rdim[0]; \ ps += 1; \ } \ px += 1; \ } else if (mn == 1) { \ _CTYPE_ v = ps[0]; \ for (k = 0; k < n; ++k) { \ *py = v; \ py += rdim[0]; \ } \ px += 1; \ } else { \ int mn_ = (int) mn; \ for (k = 0; k < n; ++k) { \ *py = ps[k % mn_]; \ py += rdim[0]; \ } \ px += 1; \ } \ } \ } \ } while (0) if (kind == 'n') BIND_E(int, LOGICAL, SHOW); else BIND_CASES(BIND_E); UNPROTECT(1); } else if ((repr == 'C' && margin) || (repr == 'R' && !margin)) { SEXP p = PROTECT(allocVector(INTSXP, (R_xlen_t) rdim[margin] + 1)); int *pp = INTEGER(p); SET_SLOT(res, Matrix_pSym, p); if (rdim[0] == 0 || rdim[1] == 0) { Matrix_memset(pp, 0, (R_xlen_t) rdim[margin] + 1, sizeof(int)); UNPROTECT(1); return; } SEXP sp; int *psp, j, n, nnz = 0; *(pp++) = nnz = 0; for (a = args; a != R_NilValue; a = CDR(a)) { s = CAR(a); if (s == R_NilValue) continue; sp = GET_SLOT(s, Matrix_pSym); psp = INTEGER(sp); n = (int) (XLENGTH(sp) - 1); if (psp[n] > INT_MAX - nnz) error(_("%s cannot exceed %s"), "p[length(p)]", "2^31-1"); for (j = 0; j < n; ++j) *(pp++) = nnz = nnz + (psp[j + 1] - psp[j]); } SEXP i = PROTECT(allocVector(INTSXP, nnz)), si, iSym = (repr == 'C') ? Matrix_iSym : Matrix_jSym; int *pi = INTEGER(i), *psi; SET_SLOT(res, iSym, i); #define BIND_C1R0(_CTYPE_, _PTR_, _MASK_) \ do { \ _MASK_(_CTYPE_ *px = _PTR_(x), *psx); \ for (a = args; a != R_NilValue; a = CDR(a)) { \ s = CAR(a); \ if (s == R_NilValue) \ continue; \ PROTECT(sp = GET_SLOT(s, Matrix_pSym)); \ PROTECT(si = GET_SLOT(s, iSym)); \ _MASK_(PROTECT(sx = GET_SLOT(s, Matrix_xSym))); \ psp = INTEGER(sp); \ psi = INTEGER(si); \ _MASK_(psx = _PTR_(sx)); \ n = (int) (XLENGTH(sp) - 1); \ Matrix_memcpy(pi, psi, psp[n], sizeof(int)); \ _MASK_(Matrix_memcpy(px, psx, psp[n], sizeof(_CTYPE_))); \ pi += psp[n]; \ _MASK_(px += psp[n]); \ _MASK_(UNPROTECT(1)); \ UNPROTECT(2); \ } \ } while (0) if (kind == 'n') BIND_C1R0(int, LOGICAL, HIDE); else { SEXP x = PROTECT(allocVector(kindToType(kind), nnz)), sx; SET_SLOT(res, Matrix_xSym, x); BIND_CASES(BIND_C1R0); UNPROTECT(1); } UNPROTECT(2); } else if ((repr == 'C' && !margin) || (repr == 'R' && margin)) { SEXP p = PROTECT(allocVector(INTSXP, (R_xlen_t) rdim[!margin] + 1)); int *pp = INTEGER(p); SET_SLOT(res, Matrix_pSym, p); Matrix_memset(pp, 0, (R_xlen_t) rdim[!margin] + 1, sizeof(int)); if (rdim[0] == 0 || rdim[1] == 0) { UNPROTECT(1); return; } SEXP sp; int *psp, j, n = rdim[!margin]; ++pp; for (a = args; a != R_NilValue; a = CDR(a)) { s = CAR(a); if (s == R_NilValue) continue; sp = GET_SLOT(s, Matrix_pSym); psp = INTEGER(sp) + 1; if (n > 0 && psp[n - 1] > INT_MAX - pp[n - 1]) error(_("%s cannot exceed %s"), "p[length(p)]", "2^31-1"); for (j = 0; j < n; ++j) pp[j] += psp[j]; } --pp; int nnz = pp[n]; SEXP i = PROTECT(allocVector(INTSXP, nnz)), si, iSym = (repr == 'C') ? Matrix_iSym : Matrix_jSym; int *pi = INTEGER(i), *psi, *work, k, kend, pos = 0; SET_SLOT(res, iSym, i); Matrix_Calloc(work, n, int); Matrix_memcpy(work, pp, n, sizeof(int)); #define BIND_C0R1(_CTYPE_, _PTR_, _MASK_) \ do { \ _MASK_(_CTYPE_ *px = _PTR_(x), *psx); \ for (a = args; a != R_NilValue; a = CDR(a)) { \ s = CAR(a); \ if (s == R_NilValue) \ continue; \ PROTECT(sp = GET_SLOT(s, Matrix_pSym)); \ PROTECT(si = GET_SLOT(s, iSym)); \ _MASK_(PROTECT(sx = GET_SLOT(s, Matrix_xSym))); \ psp = INTEGER(sp); \ psi = INTEGER(si); \ _MASK_(psx = _PTR_(sx)); \ for (j = 0, k = 0; j < n; ++j) { \ kend = psp[j + 1]; \ while (k < kend) { \ pi[work[j]] = *(psi++) + pos; \ _MASK_(px[work[j]] = *(psx++)); \ work[j]++; \ ++k; \ } \ } \ _MASK_(UNPROTECT(1)); \ UNPROTECT(2); \ pos += INTEGER(GET_SLOT(s, Matrix_DimSym))[margin]; \ } \ } while (0) if (kind == 'n') BIND_C0R1(int, LOGICAL, HIDE); else { SEXP x = PROTECT(allocVector(kindToType(kind), nnz)), sx; SET_SLOT(res, Matrix_xSym, x); BIND_CASES(BIND_C0R1); UNPROTECT(1); } UNPROTECT(2); Matrix_Free(work, n); } else if (repr == 'T') { if (rdim[0] == 0 || rdim[1] == 0) return; R_xlen_t k, nnz = 0; for (a = args; a != R_NilValue; a = CDR(a)) { s = CAR(a); if (s == R_NilValue) continue; k = XLENGTH(GET_SLOT(s, Matrix_iSym)); if (k > R_XLEN_T_MAX - nnz) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); nnz += k; } SEXP si, sj, i = PROTECT(allocVector(INTSXP, nnz)), j = PROTECT(allocVector(INTSXP, nnz)); int *psi, *psj, *pi = INTEGER(i), *pj = INTEGER(j), pos = 0; SET_SLOT(res, Matrix_iSym, i); SET_SLOT(res, Matrix_jSym, j); #define BIND_T(_CTYPE_, _PTR_, _MASK_) \ do { \ _MASK_(_CTYPE_ *px = _PTR_(x), *psx); \ for (a = args; a != R_NilValue; a = CDR(a)) { \ s = CAR(a); \ if (s == R_NilValue) \ continue; \ PROTECT(si = GET_SLOT(s, Matrix_iSym)); \ PROTECT(sj = GET_SLOT(s, Matrix_jSym)); \ _MASK_(PROTECT(sx = GET_SLOT(s, Matrix_xSym))); \ psi = INTEGER(si); \ psj = INTEGER(sj); \ _MASK_(psx = _PTR_(sx)); \ k = XLENGTH(si); \ if (margin) { \ while (k--) { \ *(pi++) = *(psi++); \ *(pj++) = *(psj++) + pos; \ _MASK_(*(px++) = *(psx++)); \ } \ } else { \ while (k--) { \ *(pi++) = *(psi++) + pos; \ *(pj++) = *(psj++); \ _MASK_(*(px++) = *(psx++)); \ } \ } \ _MASK_(UNPROTECT(1)); \ UNPROTECT(2); \ pos += INTEGER(GET_SLOT(s, Matrix_DimSym))[margin]; \ } \ } while (0) if (kind == 'n') BIND_T(int, LOGICAL, HIDE); else { SEXP x = PROTECT(allocVector(kindToType(kind), nnz)), sx; SET_SLOT(res, Matrix_xSym, x); BIND_CASES(BIND_T); UNPROTECT(1); } UNPROTECT(2); } else { SEXP p = PROTECT(allocVector(INTSXP, rdim[margin])), sp; int *pp = INTEGER(p); for (a = args; a != R_NilValue; a = CDR(a)) { s = CAR(a); if (s == R_NilValue) continue; sp = GET_SLOT(s, Matrix_permSym); Matrix_memcpy(pp, INTEGER(sp), LENGTH(sp), sizeof(int)); pp += LENGTH(sp); } SET_SLOT(res, Matrix_permSym, p); UNPROTECT(1); if (margin) INTEGER(GET_SLOT(res, Matrix_marginSym))[0] = 2; } #undef BIND_CASES #undef BIND_E #undef BIND_C1R0 #undef BIND_C0R1 #undef BIND_T return; } static SEXP bind(SEXP args, SEXP exprs, int margin, int level) { if (!tagWasVector) tagWasVector = install(".__WAS_VECTOR__."); /* for now, a hack */ int rdim[2], rdimnames[2]; char kind = '\0', repr = '\0'; scanArgs(args, exprs, margin, level, rdim, rdimnames, &kind, &repr); if (rdim[!margin] < 0) /* Arguments are all NULL */ return R_NilValue; if (repr == 'e' && (Matrix_int_fast64_t) rdim[0] * rdim[1] > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); char rcl[] = "...Matrix"; if (kind == '\0' || repr == '\0') { if (kind != repr) error(_("should never happen ...")); rcl[0] = 'i'; rcl[1] = 'n'; rcl[2] = 'd'; } else { rcl[0] = kind; rcl[1] = 'g'; rcl[2] = repr; coerceArgs(args, margin, rdim, kind, repr); } SEXP res = PROTECT(newObject(rcl)); bindArgs(args, margin, res, rdim, kind, repr); SEXP dim = PROTECT(GET_SLOT(res, Matrix_DimSym)); INTEGER(dim)[0] = rdim[0]; INTEGER(dim)[1] = rdim[1]; UNPROTECT(1); if (rdimnames[0] || rdimnames[1]) { SEXP dimnames = PROTECT(GET_SLOT(res, Matrix_DimNamesSym)), marnames = R_NilValue, nms[2], nms_, a, e, s, tmp; int i, ivalid, r = -1, pos = 0, nprotect = 1; const char *scl; if (rdimnames[margin]) { PROTECT(marnames = allocVector(STRSXP, rdim[margin])); ++nprotect; SET_VECTOR_ELT(dimnames, margin, marnames); } for (a = args, e = exprs; a != R_NilValue; a = CDR(a), e = CDR(e)) { s = CAR(a); if (s == R_NilValue && rdim[!margin] > 0) continue; nms[0] = nms[1] = R_NilValue; if (TYPEOF(s) == S4SXP) { ivalid = R_check_class_etc(s, valid); scl = valid[ivalid + VALID_NONVIRTUAL_SHIFT(ivalid, 1)]; tmp = GET_SLOT(s, Matrix_DimSym); r = INTEGER(tmp)[margin]; tmp = GET_SLOT(s, Matrix_DimNamesSym); if (scl[1] == 's') { if ((nms_ = VECTOR_ELT(tmp, 1)) != R_NilValue || (nms_ = VECTOR_ELT(tmp, 0)) != R_NilValue) nms[0] = nms[1] = nms_; } else for (i = 0; i < 2; ++i) nms[i] = VECTOR_ELT(tmp, i); } else { tmp = getAttrib(s, R_DimSymbol); if (TYPEOF(tmp) == INTSXP && LENGTH(tmp) == 2) { r = INTEGER(tmp)[margin]; tmp = getAttrib(s, R_DimNamesSymbol); if (tmp != R_NilValue) for (i = 0; i < 2; ++i) nms[i] = VECTOR_ELT(tmp, i); } else if (rdim[!margin] == 0 || XLENGTH(s) > 0) { r = 1; if (rdim[!margin] > 0 && XLENGTH(s) == rdim[!margin]) nms[!margin] = getAttrib(s, R_NamesSymbol); } } if (TAG(a) != R_NilValue) { /* only if 's' is or was a vector */ if (TAG(a) != tagWasVector) nms[margin] = coerceVector(TAG(a), STRSXP); else if (level == 2) { PROTECT(nms_ = allocVector(EXPRSXP, 1)); SET_VECTOR_ELT(nms_, 0, CAR(e)); nms[margin] = coerceVector(nms_, STRSXP); UNPROTECT(1); } else if (level == 1 && TYPEOF(CAR(e)) == SYMSXP) nms[margin] = coerceVector(CAR(e), STRSXP); } if (rdimnames[!margin] && nms[!margin] != R_NilValue) { SET_VECTOR_ELT(dimnames, !margin, nms[!margin]); rdimnames[!margin] = 0; if (!rdimnames[margin]) break; } if (rdimnames[ margin] && nms[ margin] != R_NilValue) for (i = 0; i < r; ++i) SET_STRING_ELT(marnames, pos + i, STRING_ELT(nms[margin], i)); pos += r; } UNPROTECT(nprotect); } UNPROTECT(1); return res; } SEXP R_bind(SEXP args) { SEXP level, margin, exprs; args = CDR(args); level = CAR(args); args = CDR(args); margin = CAR(args); args = CDR(args); exprs = CAR(args); return bind(CDR(args), CDR(exprs), asInteger(margin), asInteger(level)); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/vector.c���������������������������������������������������������������������������������0000644�0001751�0000144�00000012313�14575137654�014012� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Mdefines.h" #include "vector.h" SEXP v2spV(SEXP from) { SEXP to = NULL, length = NULL, i = NULL, x = NULL; R_xlen_t n_ = XLENGTH(from); #define V2SPV(_KIND_, _NZ_, \ _CTYPE1_, _SEXPTYPE1_, _PTR1_, \ _CTYPE2_, _SEXPTYPE2_, _PTR2_) \ do { \ PROTECT(to = newObject(#_KIND_ "sparseVector")); \ _CTYPE1_ *py = _PTR1_(from); \ for (k = 0; k < n; ++k) \ if (_NZ_(py[k])) \ ++nnz; \ PROTECT(i = allocVector(_SEXPTYPE2_, nnz)); \ PROTECT(x = allocVector(_SEXPTYPE1_, nnz)); \ _CTYPE2_ *pi = _PTR2_(i); \ _CTYPE1_ *px = _PTR1_(x); \ for (k = 0; k < n; ++k) { \ if (_NZ_(py[k])) { \ *(pi++) = (_CTYPE2_) (k + 1); \ *(px++) = py[k]; \ } \ } \ } while (0) #define V2SPV_CASES(_CTYPE2_, _SEXPTYPE2_, _PTR2_) \ do { \ switch (TYPEOF(from)) { \ case LGLSXP: \ V2SPV(l, ISNZ_LOGICAL, int, LGLSXP, LOGICAL, \ _CTYPE2_, _SEXPTYPE2_, _PTR2_); \ break; \ case INTSXP: \ V2SPV(i, ISNZ_INTEGER, int, INTSXP, INTEGER, \ _CTYPE2_, _SEXPTYPE2_, _PTR2_); \ break; \ case REALSXP: \ V2SPV(d, ISNZ_REAL, double, REALSXP, REAL, \ _CTYPE2_, _SEXPTYPE2_, _PTR2_); \ break; \ case CPLXSXP: \ V2SPV(z, ISNZ_COMPLEX, Rcomplex, CPLXSXP, COMPLEX, \ _CTYPE2_, _SEXPTYPE2_, _PTR2_); \ break; \ default: \ ERROR_INVALID_TYPE(from, __func__); \ break; \ } \ } while (0) if (n_ <= INT_MAX) { int k, n = (int) n_, nnz = 0; PROTECT(length = ScalarInteger(n)); V2SPV_CASES(int, INTSXP, INTEGER); } else { R_xlen_t k, n = n_, nnz = 0; PROTECT(length = ScalarReal((double) n)); V2SPV_CASES(double, REALSXP, REAL); } #undef V2SPV_CASES #undef V2SPV SET_SLOT(to, Matrix_lengthSym, length); SET_SLOT(to, Matrix_iSym, i); SET_SLOT(to, Matrix_xSym, x); UNPROTECT(4); /* x, i, length, to */ return to; } SEXP CR2spV(SEXP from) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *cl = valid[ivalid]; SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; Matrix_int_fast64_t mn = (Matrix_int_fast64_t) m * n; UNPROTECT(1); /* dim */ if (mn > 0x1.0p+53) error(_("%s length cannot exceed %s"), "sparseVector", "2^53"); /* defined in ./coerce.c : */ SEXP sparse_as_general(SEXP, const char *); PROTECT(from = sparse_as_general(from, cl)); char vcl[] = ".sparseVector"; vcl[0] = cl[0]; SEXP to = PROTECT(newObject(vcl)); SEXP p = PROTECT(GET_SLOT(from, Matrix_pSym)); int *pp = INTEGER(p), nnz = (cl[2] == 'C') ? pp[n] : pp[m]; SEXP vlength, vi; if (mn <= INT_MAX) { PROTECT(vlength = ScalarInteger(m * n)); PROTECT(vi = allocVector(INTSXP, nnz)); } else { PROTECT(vlength = ScalarReal((double) m * n)); PROTECT(vi = allocVector(REALSXP, nnz)); } SET_SLOT(to, Matrix_lengthSym, vlength); SET_SLOT(to, Matrix_iSym, vi); if (cl[2] == 'C') { SEXP i = PROTECT(GET_SLOT(from, Matrix_iSym)); int *pi = INTEGER(i), k, kend, j; if (TYPEOF(vi) == INTSXP) { int *pvi = INTEGER(vi), mj1a = 1; for (j = 0, k = 0; j < n; ++j) { kend = *(++pp); while (k < kend) { *(pvi++) = mj1a + *(pi++); ++k; } mj1a += m; } } else { double *pvi = REAL(vi), mj1a = 1.0, m_ = (double) m; for (j = 0, k = 0; j < n; ++j) { kend = *(++pp); while (k < kend) { *(pvi++) = mj1a + (double) *(pi++); ++k; } mj1a += m_; } } if (cl[0] != 'n') { SEXP vx = PROTECT(GET_SLOT(from, Matrix_xSym)); SET_SLOT(to, Matrix_xSym, vx); UNPROTECT(1); /* vx */ } UNPROTECT(1); /* i */ } else { SEXP j = PROTECT(GET_SLOT(from, Matrix_jSym)); int *pj = INTEGER(j), k, kend, tmp, *work; Matrix_Calloc(work, n, int); for (k = 0; k < nnz; ++k) work[pj[k]]++; nnz = 0; for (k = 0; k < n; ++k) { tmp = work[k]; work[k] = nnz; nnz += tmp; } #define R2SPV(_CTYPE_, _PTR_, _MASK_) \ do { \ _MASK_(_CTYPE_ *px = _PTR_(x )); \ _MASK_(_CTYPE_ *pvx = _PTR_(vx)); \ if (TYPEOF(vi) == INTSXP) { \ int *pvi = INTEGER(vi), i; \ k = 0; \ for (i = 1; i <= m; i += 1) { \ kend = *(++pp); \ while (k < kend) { \ pvi[work[pj[k]]] = m * pj[k] + i; \ _MASK_(pvx[work[pj[k]]] = px[k]); \ work[pj[k++]]++; \ } \ } \ } else { \ double *pvi = REAL(vi), i_, m_ = (double) m; \ k = 0; \ for (i_ = 1.0; i_ <= m_; i_ += 1.0) { \ kend = *(++pp); \ while (k < kend) { \ pvi[work[pj[k]]] = m_ * pj[k] + i_; \ _MASK_(pvx[work[pj[k]]] = px[k]); \ work[pj[k++]]++; \ } \ } \ } \ } while (0) if (cl[0] == 'n') R2SPV(, , HIDE); else { SEXP x = PROTECT(GET_SLOT(from, Matrix_xSym)), vx = PROTECT(allocVector(TYPEOF(x), XLENGTH(x))); switch (TYPEOF(x)) { case LGLSXP: R2SPV(int, LOGICAL, SHOW); break; case INTSXP: R2SPV(int, INTEGER, SHOW); break; case REALSXP: R2SPV(double, REAL, SHOW); break; case CPLXSXP: R2SPV(Rcomplex, COMPLEX, SHOW); break; default: break; } SET_SLOT(to, Matrix_xSym, vx); UNPROTECT(2); /* vx, x */ } #undef R2SV UNPROTECT(1); /* j */ Matrix_Free(work, n); } UNPROTECT(5); /* vi, vlength, p, to, from */ return to; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/coerce.c���������������������������������������������������������������������������������0000644�0001751�0000144�00000340711�14574054152�013744� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include /* trunc */ #include "Mdefines.h" #include "idz.h" #include "coerce.h" SEXP vector_as_dense(SEXP from, const char *zzz, char ul, char di, int m, int n, int byrow, SEXP dimnames) { SEXPTYPE tf = TYPEOF(from); char cl[] = "...Matrix"; cl[0] = (zzz[0] == '.') ? typeToKind(tf) : ((zzz[0] == ',') ? ((tf == CPLXSXP) ? 'z' : 'd') : zzz[0]); cl[1] = zzz[1]; cl[2] = zzz[2]; #ifndef MATRIX_ENABLE_IMATRIX if (cl[0] == 'i') cl[0] = 'd'; #endif SEXPTYPE tt = kindToType(cl[0]); PROTECT(from = coerceVector(from, tt)); if (cl[1] != 'g' && m != n) error(_("attempt to construct non-square %s"), (cl[1] == 's') ? "symmetricMatrix" : "triangularMatrix"); Matrix_int_fast64_t mn = (Matrix_int_fast64_t) m * n; if (((cl[2] != 'p') ? mn : (mn + n) / 2) > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); SEXP to = PROTECT(newObject(cl)); SEXP dim = GET_SLOT(to, Matrix_DimSym); int *pdim = INTEGER(dim); pdim[0] = m; pdim[1] = n; if (cl[1] != 's') SET_SLOT(to, Matrix_DimNamesSym, dimnames); else set_symmetrized_DimNames(to, dimnames, -1); if (cl[1] != 'g' && ul != 'U') { SEXP uplo = PROTECT(mkString("L")); SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); } if (cl[1] == 't' && di != 'N') { SEXP diag = PROTECT(mkString("U")); SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); } /* FIXME: add argument 'new' and conditionally avoid allocation */ SEXP x = PROTECT(allocVector(tt, (cl[2] != 'p') ? mn : (mn + n) / 2)); R_xlen_t k, r = XLENGTH(from); int i, j, recycle = r < mn; #define VAD_SUBCASES(_PREFIX_, _CTYPE_, _PTR_, _NA_) \ do { \ _CTYPE_ *dest = _PTR_(x), *src = _PTR_(from); \ if (r == 0) { \ while (mn-- > 0) \ *(dest++) = _NA_; \ } else if (r == 1) { \ while (mn-- > 0) \ *(dest++) = *src; \ } else if (cl[2] != 'p') { \ if (!recycle) { \ if (!byrow) \ Matrix_memcpy(dest, src, mn, sizeof(_CTYPE_)); \ else \ _PREFIX_ ## transpose2(dest, src, n, m); \ } else { \ if (!byrow) { \ k = 0; \ while (mn-- > 0) { \ if (k == r) k = 0; \ *(dest++) = src[k++]; \ } \ } else { \ for (j = 0; j < n; ++j) { \ k = j; \ for (i = 0; i < m; ++i) { \ k %= r; \ *(dest++) = src[k]; \ k += n; \ } \ } \ } \ } \ } else if (ul == 'U') { \ if (!byrow) { \ k = 0; \ for (j = 0; j < n; ++j) { \ for (i = 0; i <= j; ++i) { \ if (recycle) k %= r; \ *(dest++) = src[k++]; \ } \ k += n - j - 1; \ } \ } else { \ for (j = 0; j < n; ++j) { \ k = j; \ for (i = 0; i <= j; ++i) { \ if (recycle) k %= r; \ *(dest++) = src[k]; \ k += n; \ } \ } \ } \ } else { \ if (!byrow) { \ k = 0; \ for (j = 0; j < n; ++j) { \ for (i = j; i < n; ++i) { \ if (recycle) k %= r; \ *(dest++) = src[k++]; \ } \ k += j + 1; \ } \ } else { \ R_xlen_t d = 0; \ for (j = 0; j < n; ++j) { \ k = j + d; \ for (i = 0; i <= j; ++i) { \ if (recycle) k %= r; \ *(dest++) = src[k]; \ k += n; \ } \ d += n; \ } \ } \ } \ } while (0) switch (tt) { case LGLSXP: VAD_SUBCASES(i, int, LOGICAL, NA_LOGICAL); break; case INTSXP: VAD_SUBCASES(i, int, INTEGER, NA_INTEGER); break; case REALSXP: VAD_SUBCASES(d, double, REAL, NA_REAL); break; case CPLXSXP: VAD_SUBCASES(z, Rcomplex, COMPLEX, Matrix_zna); break; default: break; } #undef VAD_SUBCASES SET_SLOT(to, Matrix_xSym, x); UNPROTECT(3); return to; } SEXP R_vector_as_dense(SEXP from, SEXP zzz, SEXP uplo, SEXP diag, SEXP m, SEXP n, SEXP byrow, SEXP dimnames) { switch (TYPEOF(from)) { case LGLSXP: case INTSXP: case REALSXP: case CPLXSXP: break; default: ERROR_INVALID_TYPE(from, __func__); break; } const char *zzz_; if (TYPEOF(zzz) != STRSXP || LENGTH(zzz) < 1 || (zzz = STRING_ELT(zzz, 0)) == NA_STRING || (zzz_ = CHAR(zzz))[0] == '\0' || (zzz_ )[1] == '\0' || !((zzz_[1] == 'g' && (zzz_[2] == 'e' )) || (zzz_[1] == 's' && (zzz_[2] == 'y' || zzz_[2] == 'p')) || (zzz_[1] == 't' && (zzz_[2] == 'r' || zzz_[2] == 'p')))) error(_("second argument of '%s' does not specify a subclass of %s"), __func__, "denseMatrix"); char ul = 'U', di = 'N'; if (zzz_[1] != 'g') { if (TYPEOF(uplo) != STRSXP || LENGTH(uplo) < 1 || (uplo = STRING_ELT(uplo, 0)) == NA_STRING || ((ul = *CHAR(uplo)) != 'U' && ul != 'L')) error(_("'%s' must be \"%s\" or \"%s\""), "uplo", "U", "L"); } if (zzz_[1] == 't') { if (TYPEOF(diag) != STRSXP || LENGTH(diag) < 1 || (diag = STRING_ELT(diag, 0)) == NA_STRING || ((di = *CHAR(diag)) != 'N' && di != 'U')) error(_("'%s' must be \"%s\" or \"%s\""), "diag", "N", "U"); } int m_ = -1; if (m != R_NilValue) { if (TYPEOF(m) == INTSXP) { int tmp; if (LENGTH(m) >= 1 && (tmp = INTEGER(m)[0]) != NA_INTEGER && tmp >= 0) m_ = tmp; } else if (TYPEOF(m) == REALSXP) { double tmp; if (LENGTH(m) >= 1 && !ISNAN(tmp = REAL(m)[0]) && tmp >= 0.0) { if (trunc(tmp) > INT_MAX) error(_("dimensions cannot exceed %s"), "2^31-1"); m_ = (int) tmp; } } if (m_ < 0) error(_("invalid '%s' to '%s'"), "m", __func__); } int n_ = -1; if (n != R_NilValue) { if (TYPEOF(n) == INTSXP) { int tmp; if (LENGTH(n) >= 1 && (tmp = INTEGER(n)[0]) != NA_INTEGER && tmp >= 0) n_ = tmp; } else if (TYPEOF(n) == REALSXP) { double tmp; if (LENGTH(n) >= 1 && !ISNAN(tmp = REAL(n)[0]) && tmp >= 0.0) { if (trunc(tmp) > INT_MAX) error(_("dimensions cannot exceed %s"), "2^31-1"); n_ = (int) tmp; } } if (n_ < 0) error(_("invalid '%s' to '%s'"), "n", __func__); } int byrow_; if (TYPEOF(byrow) != LGLSXP || LENGTH(byrow) < 1 || (byrow_ = LOGICAL(byrow)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "byrow", "TRUE", "FALSE"); if (dimnames != R_NilValue) if (TYPEOF(dimnames) != VECSXP || LENGTH(dimnames) != 2) error(_("invalid '%s' to '%s'"), "dimnames", __func__); R_xlen_t vlen_ = XLENGTH(from); if (zzz_[1] != 'g' && (m_ < 0) != (n_ < 0)) { if (m_ < 0) m_ = n_; else n_ = m_; } else if (m_ < 0 && n_ < 0) { if (vlen_ > INT_MAX) error(_("dimensions cannot exceed %s"), "2^31-1"); m_ = (int) vlen_; n_ = 1; } else if (m_ < 0) { if (vlen_ > (Matrix_int_fast64_t) INT_MAX * n_) { if (n_ == 0) error(_("nonempty vector supplied for empty matrix")); else error(_("dimensions cannot exceed %s"), "2^31-1"); } m_ = (n_ == 0) ? 0 : vlen_ / n_ + (vlen_ % n_ != 0); } else if (n_ < 0) { if (vlen_ > (Matrix_int_fast64_t) m_ * INT_MAX) { if (m_ == 0) error(_("nonempty vector supplied for empty matrix")); else error(_("dimensions cannot exceed %s"), "2^31-1"); } n_ = (m_ == 0) ? 0 : vlen_ / m_ + (vlen_ % m_ != 0); } Matrix_int_fast64_t mlen_ = (Matrix_int_fast64_t) m_ * n_; if (vlen_ <= 1) /* do nothing */ ; else if (mlen_ == 0) warning(_("nonempty vector supplied for empty matrix")); else if (vlen_ > mlen_) warning(_("vector length (%lld) exceeds matrix length (%d * %d)"), (long long) vlen_, m_, n_); else if (mlen_ % vlen_ != 0) warning(_("matrix length (%d * %d) is not a multiple of vector length (%lld)"), m_, n_, (long long) vlen_); return vector_as_dense(from, zzz_, ul, di, m_, n_, byrow_, dimnames); } SEXP matrix_as_dense(SEXP from, const char *zzz, char ul, char di, int trans, int new) { SEXPTYPE tf = TYPEOF(from); char cl[] = "...Matrix"; cl[0] = (zzz[0] == '.') ? typeToKind(tf) : ((zzz[0] == ',') ? ((tf == CPLXSXP) ? 'z' : 'd') : zzz[0]); cl[1] = zzz[1]; cl[2] = zzz[2]; #ifndef MATRIX_ENABLE_IMATRIX if (cl[0] == 'i') cl[0] = 'd'; #endif SEXPTYPE tt = kindToType(cl[0]); PROTECT(from = coerceVector(from, tt)); SEXP to = PROTECT(newObject(cl)); int nprotect = 2; SEXP dim = getAttrib(from, R_DimSymbol), dimnames; int *pdim, isM, m, n, doDN; R_xlen_t mn = XLENGTH(from); isM = TYPEOF(dim) == INTSXP && LENGTH(dim) == 2; if (isM) { pdim = INTEGER(dim); m = pdim[0]; n = pdim[1]; if (m != n || n > 0) { dim = GET_SLOT(to, Matrix_DimSym); pdim = INTEGER(dim); pdim[0] = m; pdim[1] = n; } PROTECT(dimnames = getAttrib(from, R_DimNamesSymbol)); ++nprotect; doDN = dimnames != R_NilValue; } else { if (mn > INT_MAX) error(_("dimensions cannot exceed %s"), "2^31-1"); dim = GET_SLOT(to, Matrix_DimSym); pdim = INTEGER(dim); if (trans) { pdim[0] = m = 1; pdim[1] = n = (int) mn; } else { pdim[0] = m = (int) mn; pdim[1] = n = 1; } SEXP nms = PROTECT(getAttrib(from, R_NamesSymbol)); ++nprotect; doDN = nms != R_NilValue; if (doDN) { PROTECT(dimnames = allocVector(VECSXP, 2)); ++nprotect; SET_VECTOR_ELT(dimnames, trans ? 1 : 0, nms); } } if (cl[1] != 'g' && m != n) error(_("attempt to construct non-square %s"), (cl[1] == 's') ? "symmetricMatrix" : "triangularMatrix"); if (doDN) { if (cl[1] != 's') SET_SLOT(to, Matrix_DimNamesSym, dimnames); else set_symmetrized_DimNames(to, dimnames, -1); } if (cl[1] != 'g' && ul != 'U') { SEXP uplo = PROTECT(mkString("L")); SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } if (cl[1] == 't' && di != 'N') { SEXP diag = PROTECT(mkString("U")); SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } SEXP x; if (cl[2] != 'p') { if (new <= 0 || (new <= 1 && ATTRIB(from) == R_NilValue) || !MAYBE_REFERENCED(from)) { if (ATTRIB(from) != R_NilValue && new >= 1) { /* 'from' has attributes and no references : */ SET_ATTRIB(from, R_NilValue); if (OBJECT(from)) SET_OBJECT(from, 0); } x = from; } else { PROTECT(x = allocVector(tt, mn)); ++nprotect; switch (tt) { case LGLSXP: Matrix_memcpy(LOGICAL(x), LOGICAL(from), mn, sizeof(int)); break; case INTSXP: Matrix_memcpy(INTEGER(x), INTEGER(from), mn, sizeof(int)); break; case REALSXP: Matrix_memcpy(REAL(x), REAL(from), mn, sizeof(double)); break; case CPLXSXP: Matrix_memcpy(COMPLEX(x), COMPLEX(from), mn, sizeof(Rcomplex)); break; default: break; } } } else { PROTECT(x = allocVector(tt, (mn - n) / 2 + n)); ++nprotect; switch (tt) { case LGLSXP: ipack2(LOGICAL(x), LOGICAL(from), n, ul, di); break; case INTSXP: ipack2(INTEGER(x), INTEGER(from), n, ul, di); break; case REALSXP: dpack2(REAL(x), REAL(from), n, ul, di); break; case CPLXSXP: zpack2(COMPLEX(x), COMPLEX(from), n, ul, di); break; default: break; } } SET_SLOT(to, Matrix_xSym, x); UNPROTECT(nprotect); return to; } /* as(, ".(ge|sy|sp|tr|tp)Matrix") */ SEXP R_matrix_as_dense(SEXP from, SEXP zzz, SEXP uplo, SEXP diag, SEXP trans) { switch (TYPEOF(from)) { case LGLSXP: case INTSXP: case REALSXP: case CPLXSXP: break; default: ERROR_INVALID_TYPE(from, __func__); break; } const char *zzz_; if (TYPEOF(zzz) != STRSXP || LENGTH(zzz) < 1 || (zzz = STRING_ELT(zzz, 0)) == NA_STRING || (zzz_ = CHAR(zzz))[0] == '\0' || (zzz_ )[1] == '\0' || !((zzz_[1] == 'g' && (zzz_[2] == 'e' )) || (zzz_[1] == 's' && (zzz_[2] == 'y' || zzz_[2] == 'p')) || (zzz_[1] == 't' && (zzz_[2] == 'r' || zzz_[2] == 'p')))) error(_("second argument of '%s' does not specify a subclass of %s"), __func__, "denseMatrix"); char ul = 'U', di = 'N'; if (zzz_[1] != 'g') { if (TYPEOF(uplo) != STRSXP || LENGTH(uplo) < 1 || (uplo = STRING_ELT(uplo, 0)) == NA_STRING || ((ul = *CHAR(uplo)) != 'U' && ul != 'L')) error(_("'%s' must be \"%s\" or \"%s\""), "uplo", "U", "L"); } if (zzz_[1] == 't') { if (TYPEOF(diag) != STRSXP || LENGTH(diag) < 1 || (diag = STRING_ELT(diag, 0)) == NA_STRING || ((di = *CHAR(diag)) != 'N' && di != 'U')) error(_("'%s' must be \"%s\" or \"%s\""), "diag", "N", "U"); } int trans_; if (TYPEOF(trans) != LGLSXP || LENGTH(trans) < 1 || (trans_ = LOGICAL(trans)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "trans", "TRUE", "FALSE"); return matrix_as_dense(from, zzz_, ul, di, trans_, 1); } SEXP sparse_as_dense(SEXP from, const char *class, int packed) { packed = packed && class[1] != 'g'; char cl[] = "...Matrix"; cl[0] = class[0]; cl[1] = class[1]; cl[2] = (packed) ? 'p' : ((class[1] == 'g') ? 'e' : ((class[1] == 's') ? 'y' : 'r')); SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; Matrix_int_fast64_t len = (Matrix_int_fast64_t) m * n; if (packed) len = (len + n) / 2; if (len > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); if (class[2] != 'C' && packed && len > R_XLEN_T_MAX) error(_("coercing n-by-n %s to %s is not supported for n*n exceeding %s"), "[RT]sparseMatrix", "packedMatrix", "R_XLEN_T_MAX"); double bytes = (double) len * kindToSize(cl[0]); if (bytes > 0x1.0p+30 /* 1 GiB */) warning(_("sparse->dense coercion: allocating vector of size %0.1f GiB"), 0x1.0p-30 * bytes); if (m != n || n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ char ul = 'U', di = 'N'; if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N') SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } } /* It remains to fill 'x' ... */ SEXP x1 = PROTECT(allocVector(kindToType(class[0]), (R_xlen_t) len)), p0, i0, j0; int *pp, *pi, *pj, nprotect = 2; p0 = i0 = j0 = NULL; pp = pi = pj = NULL; SET_SLOT(to, Matrix_xSym, x1); if (class[2] != 'T') { PROTECT(p0 = GET_SLOT(from, Matrix_pSym)); ++nprotect; pp = INTEGER(p0) + 1; } if (class[2] != 'R') { PROTECT(i0 = GET_SLOT(from, Matrix_iSym)); ++nprotect; pi = INTEGER(i0); } if (class[2] != 'C') { PROTECT(j0 = GET_SLOT(from, Matrix_jSym)); ++nprotect; pj = INTEGER(j0); } #define SAD_CASES \ do { \ switch (class[0]) { \ case 'l': \ SAD_SUBCASES(int, LOGICAL, SHOW, FIRSTOF, INCREMENT_LOGICAL, 1); \ break; \ case 'i': \ SAD_SUBCASES(int, INTEGER, SHOW, FIRSTOF, INCREMENT_INTEGER, 1); \ break; \ case 'd': \ SAD_SUBCASES(double, REAL, SHOW, FIRSTOF, INCREMENT_REAL, 1.0); \ break; \ case 'z': \ SAD_SUBCASES(Rcomplex, COMPLEX, SHOW, FIRSTOF, INCREMENT_COMPLEX, Matrix_zone); \ break; \ default: \ break; \ } \ } while (0) #define SAD_SUBCASES(_CTYPE_, _PTR_, _MASK_, _REPLACE_, _INCREMENT_, _ONE_) \ do { \ _MASK_(_CTYPE_ *px0 = _PTR_(x0)); \ _CTYPE_ *px1 = _PTR_(x1) ; \ Matrix_memset(px1, 0, len, sizeof(_CTYPE_)); \ if (!packed) { \ /* .(ge|sy|tr)Matrix */ \ SAD_SUBSUBCASES(SAD_LOOP_C2NP, SAD_LOOP_R2NP, SAD_LOOP_T2NP, \ _MASK_, _REPLACE_, _INCREMENT_); \ if (class[1] == 't' && di != 'N') { \ px1 = _PTR_(x1); \ R_xlen_t n1a = (R_xlen_t) n + 1; \ for (int d = 0; d < n; ++d, px1 += n1a) \ *px1 = _ONE_; \ } \ } else if (ul == 'U') { \ /* upper triangular .(sp|tp)Matrix */ \ SAD_SUBSUBCASES(SAD_LOOP_C2UP, SAD_LOOP_R2UP, SAD_LOOP_T2UP, \ _MASK_, _REPLACE_, _INCREMENT_); \ if (class[1] == 't' && di != 'N') { \ px1 = _PTR_(x1); \ for (int d = 0; d < n; px1 += (++d) + 1) \ *px1 = _ONE_; \ } \ } else { \ /* lower triangular .(sp|tp)Matrix */ \ SAD_SUBSUBCASES(SAD_LOOP_C2LP, SAD_LOOP_R2LP, SAD_LOOP_T2LP, \ _MASK_, _REPLACE_, _INCREMENT_); \ if (class[1] == 't' && di != 'N') { \ px1 = _PTR_(x1); \ for (int d = 0; d < n; px1 += n - (d++)) \ *px1 = _ONE_; \ } \ } \ } while (0) #define SAD_SUBSUBCASES(_LOOP_C_, _LOOP_R_, _LOOP_T_, _MASK_, _REPLACE_, _INCREMENT_) \ do { \ switch (class[2]) { \ case 'C': \ { \ int j, k, kend; \ _LOOP_C_(_MASK_, _REPLACE_, _INCREMENT_); \ break; \ } \ case 'R': \ { \ int i, k, kend; \ _LOOP_R_(_MASK_, _REPLACE_, _INCREMENT_); \ break; \ } \ case 'T': \ { \ R_xlen_t index, k, nnz = XLENGTH(i0); \ _LOOP_T_(_MASK_, _REPLACE_, _INCREMENT_); \ break; \ } \ default: \ break; \ } \ } while (0) #define SAD_LOOP_C2NP(_MASK_, _REPLACE_, _INCREMENT_) \ do { \ for (j = 0, k = 0; j < n; ++j, px1 += m) { \ kend = pp[j]; \ while (k < kend) { \ px1[*pi] = _REPLACE_(*px0, 1); \ ++k; ++pi; _MASK_(++px0); \ } \ } \ } while (0) #define SAD_LOOP_C2UP(_MASK_, _REPLACE_, _INCREMENT_) \ do { \ for (j = 0, k = 0; j < n; px1 += (++j)) { \ kend = pp[j]; \ while (k < kend) { \ px1[*pi] = _REPLACE_(*px0, 1); \ ++k; ++pi; _MASK_(++px0); \ } \ } \ } while (0) #define SAD_LOOP_C2LP(_MASK_, _REPLACE_, _INCREMENT_) \ do { \ for (j = 0, k = 0; j < n; px1 += n - (j++)) { \ kend = pp[j]; \ while (k < kend) { \ px1[*pi - j] = _REPLACE_(*px0, 1); \ ++k; ++pi; _MASK_(++px0); \ } \ } \ } while (0) #define SAD_LOOP_R2NP(_MASK_, _REPLACE_, _INCREMENT_) \ do { \ R_xlen_t m1 = (R_xlen_t) m; \ for (i = 0, k = 0; i < m; ++i, ++px1) { \ kend = pp[i]; \ while (k < kend) { \ px1[m1 * *pj] = _REPLACE_(*px0, 1); \ ++k; ++pj; _MASK_(++px0); \ } \ } \ } while (0) #define SAD_LOOP_R2UP(_MASK_, _REPLACE_, _INCREMENT_) \ do { \ for (i = 0, k = 0; i < n; ++i) { \ kend = pp[i]; \ while (k < kend) { \ px1[PACKED_AR21_UP(i, *pj)] = _REPLACE_(*px0, 1); \ ++k; ++pj; _MASK_(++px0); \ } \ } \ } while (0) #define SAD_LOOP_R2LP(_MASK_, _REPLACE_, _INCREMENT_) \ do { \ R_xlen_t n2 = (R_xlen_t) n * 2; \ for (i = 0, k = 0; i < n; ++i) { \ kend = pp[i]; \ while (k < kend) { \ px1[PACKED_AR21_LO(i, *pj, n2)] = _REPLACE_(*px0, 1); \ ++k; ++pj; _MASK_(++px0); \ } \ } \ } while (0) #define SAD_LOOP_T2NP(_MASK_, _REPLACE_, _INCREMENT_) \ do { \ R_xlen_t m1 = (R_xlen_t) m; \ for (k = 0; k < nnz; ++k) { \ index = m1 * *pj + *pi; \ _INCREMENT_(px1[index], (*px0)); \ ++pi; ++pj; _MASK_(++px0); \ } \ } while (0) #define SAD_LOOP_T2UP(_MASK_, _REPLACE_, _INCREMENT_) \ do { \ for (k = 0; k < nnz; ++k) { \ index = PACKED_AR21_UP(*pi, *pj); \ _INCREMENT_(px1[index], (*px0)); \ ++pi; ++pj; _MASK_(++px0); \ } \ } while (0) #define SAD_LOOP_T2LP(_MASK_, _REPLACE_, _INCREMENT_) \ do { \ R_xlen_t n2 = (R_xlen_t) n * 2; \ for (k = 0; k < nnz; ++k) { \ index = PACKED_AR21_LO(*pi, *pj, n2); \ _INCREMENT_(px1[index], (*px0)); \ ++pi; ++pj; _MASK_(++px0); \ } \ } while (0) if (class[0] == 'n') SAD_SUBCASES(int, LOGICAL, HIDE, SECONDOF, INCREMENT_PATTERN, 1); else { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)); SAD_CASES; UNPROTECT(1); /* x0 */ } #undef SAD_CASES #undef SAD_SUBCASES #undef SAD_SUBSUBCASES #undef SAD_LOOP_C2NP #undef SAD_LOOP_C2UP #undef SAD_LOOP_C2LP #undef SAD_LOOP_R2NP #undef SAD_LOOP_R2UP #undef SAD_LOOP_R2LP #undef SAD_LOOP_T2NP #undef SAD_LOOP_T2UP #undef SAD_LOOP_T2LP UNPROTECT(nprotect); return to; } /* as(<[CRT]sparseMatrix>, "(un)?packedMatrix") */ SEXP R_sparse_as_dense(SEXP from, SEXP packed) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); int packed_; if (TYPEOF(packed) != LGLSXP || LENGTH(packed) < 1 || (packed_ = LOGICAL(packed)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "packed", "TRUE", "FALSE"); return sparse_as_dense(from, valid[ivalid], packed_); } SEXP diagonal_as_dense(SEXP from, const char *class, char kind, char shape, int packed, char ul) { char cl[] = "...Matrix"; cl[0] = (kind == '.') ? class[0] : ((kind == ',') ? ((class[0] == 'z') ? 'z' : 'd') : kind); cl[1] = shape; cl[2] = (cl[1] == 'g') ? 'e' : ((packed) ? 'p' : ((cl[1] == 's') ? 'y' : 'r')); SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int n = INTEGER(dim)[0]; Matrix_int_fast64_t len = (Matrix_int_fast64_t) n * n; if (len > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); double bytes = (double) len * kindToSize(cl[0]); if (bytes > 0x1.0p+30 /* 1 GiB */) warning(_("sparse->dense coercion: allocating vector of size %0.1f GiB"), 0x1.0p-30 * bytes); if (n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); if (cl[1] == 's') set_symmetrized_DimNames(to, dimnames, -1); else SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ if (cl[1] != 'g' && ul != 'U') { SEXP uplo = PROTECT(mkString("L")); SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); char di = *CHAR(STRING_ELT(diag, 0)); if (cl[1] == 't' && di != 'N') SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)); if (class[0] != cl[0]) { if (class[0] == 'n' && cl[0] == 'l') x0 = duplicate(x0); else x0 = coerceVector(x0, kindToType(cl[0])); if (class[0] == 'n') naToOne(x0); UNPROTECT(1); /* x0 */ PROTECT(x0); } SEXP x1 = PROTECT(allocVector(TYPEOF(x0), (R_xlen_t) len)); SET_SLOT(to, Matrix_xSym, x1); #define DAD_SUBCASES(_PREFIX_, _CTYPE_, _PTR_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ Matrix_memset(px1, 0, (R_xlen_t) len, sizeof(_CTYPE_)); \ if (di == 'N' || cl[1] != 't') { \ if (cl[2] != 'p') \ _PREFIX_ ## dcpy2(px1, px0, n, n, ul, di); \ else \ _PREFIX_ ## dcpy1(px1, px0, n, n, ul, ul, di); \ } \ } while (0) switch (cl[0]) { case 'n': case 'l': DAD_SUBCASES(i, int, LOGICAL); break; case 'i': DAD_SUBCASES(i, int, INTEGER); break; case 'd': DAD_SUBCASES(d, double, REAL); break; case 'z': DAD_SUBCASES(z, Rcomplex, COMPLEX); break; default: break; } #undef DAD_CASES #undef DAD_SUBCASES UNPROTECT(3); /* x1, x0, to */ return to; } /* as(, ".(ge|sy|sp|tr|tp)Matrix") */ SEXP R_diagonal_as_dense(SEXP from, SEXP kind, SEXP shape, SEXP packed, SEXP uplo) { static const char *valid[] = { VALID_DIAGONAL, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); char kind_; if (TYPEOF(kind) != STRSXP || LENGTH(kind) < 1 || (kind = STRING_ELT(kind, 0)) == NA_STRING || (kind_ = CHAR(kind)[0]) == '\0') error(_("invalid '%s' to '%s'"), "kind", __func__); char shape_; if (TYPEOF(shape) != STRSXP || LENGTH(shape) < 1 || (shape = STRING_ELT(shape, 0)) == NA_STRING || ((shape_ = CHAR(shape)[0]) != 'g' && shape_ != 's' && shape_ != 't')) error(_("invalid '%s' to '%s'"), "shape", __func__); int packed_ = 0; if (shape_ != 'g') { if (TYPEOF(packed) != LGLSXP || LENGTH(packed) < 1 || (packed_ = LOGICAL(packed)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "packed", "TRUE", "FALSE"); } char ul = 'U'; if (shape_ != 'g') { if (TYPEOF(uplo) != STRSXP || LENGTH(uplo) < 1 || (uplo = STRING_ELT(uplo, 0)) == NA_STRING || ((ul = *CHAR(uplo)) != 'U' && ul != 'L')) error(_("'%s' must be \"%s\" or \"%s\""), "uplo", "U", "L"); } return diagonal_as_dense(from, valid[ivalid], kind_, shape_, packed_, ul); } SEXP index_as_dense(SEXP from, const char *class, char kind) { SEXP margin = PROTECT(GET_SLOT(from, Matrix_marginSym)); int mg = INTEGER(margin)[0] - 1; UNPROTECT(1); /* margin */ char cl[] = ".geMatrix"; cl[0] = (kind == '.') ? 'n' : ((kind == ',') ? 'd' : kind); SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; Matrix_int_fast64_t len = (Matrix_int_fast64_t) m * n; if (len > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); double bytes = (double) len * kindToSize(cl[0]); if (bytes > 0x1.0p+30 /* 1 GiB */) warning(_("sparse->dense coercion: allocating vector of size %0.1f GiB"), 0x1.0p-30 * bytes); if (m != n || n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ SEXP perm = PROTECT(GET_SLOT(from, Matrix_permSym)); int *pperm = INTEGER(perm); SEXP x = PROTECT(allocVector(kindToType(cl[0]), (R_xlen_t) len)); SET_SLOT(to, Matrix_xSym, x); #define IAD_SUBCASES(_CTYPE_, _PTR_, _ONE_) \ do { \ _CTYPE_ *px = _PTR_(x); \ Matrix_memset(px, 0, (R_xlen_t) len, sizeof(_CTYPE_)); \ if (mg == 0) { \ R_xlen_t m1 = (R_xlen_t) m; \ for (int i = 0; i < m; ++i) \ px[i + m1 * (*(pperm++) - 1)] = _ONE_; \ } else { \ for (int j = 0; j < n; ++j, px += m) \ px[ *(pperm++) - 1 ] = _ONE_; \ } \ } while (0) switch (cl[0]) { case 'n': case 'l': IAD_SUBCASES(int, LOGICAL, 1); break; case 'i': IAD_SUBCASES(int, INTEGER, 1); break; case 'd': IAD_SUBCASES(double, REAL, 1.0); break; case 'z': IAD_SUBCASES(Rcomplex, COMPLEX, Matrix_zone); break; default: break; } #undef IAD_SUBCASES UNPROTECT(3); /* x, perm, to */ return to; } /* as(, ".geMatrix") */ SEXP R_index_as_dense(SEXP from, SEXP kind) { static const char *valid[] = { "indMatrix", "pMatrix" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); char kind_; if (TYPEOF(kind) != STRSXP || LENGTH(kind) < 1 || (kind = STRING_ELT(kind, 0)) == NA_STRING || (kind_ = CHAR(kind)[0]) == '\0') error(_("invalid '%s' to '%s'"), "kind", __func__); return index_as_dense(from, valid[ivalid], kind_); } SEXP vector_as_sparse(SEXP from, const char *zzz, char ul, char di, int m, int n, int byrow, SEXP dimnames) { SEXP length0 = GET_SLOT(from, Matrix_lengthSym); Matrix_int_fast64_t r = (Matrix_int_fast64_t) ((TYPEOF(length0) == INTSXP) ? INTEGER(length0)[0] : REAL(length0)[0]); SEXP i0 = PROTECT(GET_SLOT(from, Matrix_iSym)), x0 = getAttrib(from, Matrix_xSym); SEXPTYPE tf = TYPEOF(x0); char cl[] = "...Matrix"; cl[0] = (zzz[0] == '.') ? ((x0 == R_NilValue) ? 'n' : typeToKind(tf)) : ((zzz[0] == ',') ? ((tf == CPLXSXP) ? 'z' : 'd') : zzz[0]); cl[1] = zzz[1]; cl[2] = (byrow) ? 'R' : 'C'; #ifndef MATRIX_ENABLE_IMATRIX if (cl[0] == 'i') cl[0] = 'd'; #endif SEXPTYPE tt = kindToType(cl[0]); if (x0 != R_NilValue) { PROTECT(x0); x0 = coerceVector(x0, tt); UNPROTECT(1); /* x0 */ } PROTECT(x0); if (cl[1] != 'g' && m != n) error(_("attempt to construct non-square %s"), (cl[1] == 's') ? "symmetricMatrix" : "triangularMatrix"); SEXP to = PROTECT(newObject(cl)); SEXP dim = GET_SLOT(to, Matrix_DimSym); int *pdim = INTEGER(dim); pdim[0] = m; pdim[1] = n; if (cl[1] != 's') SET_SLOT(to, Matrix_DimNamesSym, dimnames); else set_symmetrized_DimNames(to, dimnames, -1); if (cl[1] != 'g' && ul != 'U') { SEXP uplo = PROTECT(mkString("L")); SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } if (cl[1] == 't' && di != 'N') { SEXP diag = PROTECT(mkString("U")); SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } Matrix_int_fast64_t pos, mn = (Matrix_int_fast64_t) m * n, nnz1 = 0; R_xlen_t k = 0, nnz0 = XLENGTH(i0); #define VAS_SUBCASES(...) \ do { \ switch (TYPEOF(i0)) { \ case INTSXP: \ { \ int *pi0 = INTEGER(i0); \ VAS_SUBSUBCASES(__VA_ARGS__); \ break; \ } \ case REALSXP: \ { \ double *pi0 = REAL(i0); \ VAS_SUBSUBCASES(__VA_ARGS__); \ break; \ } \ default: \ break; \ } \ } while (0) #define VAS_SUBSUBCASES() \ do { \ if (nnz0 == 0) \ /* do nothing */ ; \ else if (cl[1] == 'g') { \ if (r == 0) \ nnz1 = mn; \ else if (r == mn) \ nnz1 = nnz0; \ else if (r > mn) \ while (k < nnz0 && (Matrix_int_fast64_t) pi0[k++] <= mn) \ nnz1++; \ else { \ Matrix_int_fast64_t mn_mod_r = mn % r; \ nnz1 = nnz0 * (mn / r); \ while (k < nnz0 && (Matrix_int_fast64_t) pi0[k++] <= mn_mod_r) \ nnz1++; \ } \ } \ else if (cl[1] == 's' || di == 'N') { \ if (r == 0) \ nnz1 = (mn + n) / 2; \ else if (r >= mn) { \ if ((ul == 'U') == !byrow) { \ while (k < nnz0 && (pos = (Matrix_int_fast64_t) pi0[k++] - 1) < mn) \ if (pos % n <= pos / n) \ ++nnz1; \ } else { \ while (k < nnz0 && (pos = (Matrix_int_fast64_t) pi0[k++] - 1) < mn) \ if (pos % n >= pos / n) \ ++nnz1; \ } \ } \ else { \ Matrix_int_fast64_t a = 0; \ if ((ul == 'U') == !byrow) { \ while (a < mn) { \ k = 0; \ while (k < nnz0 && (pos = a + pi0[k++] - 1) < mn) \ if (pos % n <= pos / n) \ ++nnz1; \ a += r; \ } \ } else { \ while (a < mn) { \ k = 0; \ while (k < nnz0 && (pos = a + pi0[k++] - 1) < mn) \ if (pos % n >= pos / n) \ ++nnz1; \ a += r; \ } \ } \ } \ } \ else { \ if (r == 0) \ nnz1 = (mn - n) / 2; \ else if (r >= mn) { \ if ((ul == 'U') == !byrow) { \ while (k < nnz0 && (pos = (Matrix_int_fast64_t) pi0[k++] - 1) < mn) \ if (pos % n < pos / n) \ ++nnz1; \ } else { \ while (k < nnz0 && (pos = (Matrix_int_fast64_t) pi0[k++] - 1) < mn) \ if (pos % n > pos / n) \ ++nnz1; \ } \ } \ else { \ Matrix_int_fast64_t a = 0; \ if ((ul == 'U') == !byrow) { \ while (a < mn) { \ k = 0; \ while (k < nnz0 && (pos = a + pi0[k++] - 1) < mn) \ if (pos % n < pos / n) \ ++nnz1; \ a += r; \ } \ } else { \ while (a < mn) { \ k = 0; \ while (k < nnz0 && (pos = a + pi0[k++] - 1) < mn) \ if (pos % n > pos / n) \ ++nnz1; \ a += r; \ } \ } \ } \ } \ } while (0) VAS_SUBCASES(); #undef VAS_SUBSUBCASES if (nnz1 > INT_MAX) error(_("attempt to construct %s with more than %s nonzero entries"), "sparseMatrix", "2^31-1"); int i_, j_, m_ = (byrow) ? n : m, n_ = (byrow) ? m : n; SEXP iSym = (byrow) ? Matrix_jSym : Matrix_iSym, p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) n_ + 1)), i1 = PROTECT(allocVector(INTSXP, nnz1)); SET_SLOT(to, Matrix_pSym, p1); SET_SLOT(to, iSym, i1); int *pp1 = INTEGER(p1) + 1, *pi1 = INTEGER(i1); Matrix_memset(pp1 - 1, 0, (R_xlen_t) n + 1, sizeof(int)); k = 0; #define VAS_SUBSUBCASES(_MASK0_, _MASK1_, _REPLACE_, _CTYPE_, _PTR_, _ONE_, _NA_) \ do { \ _MASK0_(_CTYPE_ *px0 = _PTR_(x0)); \ _MASK1_(_CTYPE_ *px1 = _PTR_(x1)); \ if (nnz1 == 0) \ /* do nothing */ ; \ else if (cl[1] == 'g') { \ if (r == 0) { \ for (j_ = 0; j_ < n_; ++j_) { \ pp1[j_] = m; \ for (i_ = 0; i_ < m_; ++i_) { \ *(pi1++) = i_; \ _MASK1_(*(px1++) = _NA_); \ } \ } \ } \ else if (r >= mn) { \ while (k < nnz0 && (pos = (Matrix_int_fast64_t) pi0[k] - 1) < mn) { \ ++pp1[pos / m_]; \ *(pi1++) = pos % m_; \ _MASK1_(*(px1++) = _REPLACE_(px0[k], _ONE_)); \ ++k; \ } \ } \ else { \ Matrix_int_fast64_t a = 0; \ while (a < mn) { \ k = 0; \ while (k < nnz0 && (pos = a + pi0[k] - 1) < mn) { \ ++pp1[pos / m_]; \ *(pi1++) = pos % m_; \ _MASK1_(*(px1++) = _REPLACE_(px0[k], _ONE_)); \ ++k; \ } \ a += r; \ } \ } \ } \ else if (cl[1] == 's' || di == 'N') { \ if (r == 0) { \ if ((ul == 'U') == !byrow) { \ for (j_ = 0; j_ < n_; ++j_) { \ pp1[j_] = j_ + 1; \ for (i_ = 0; i_ <= j_; ++i_) { \ *(pi1++) = i_; \ _MASK1_(*(px1++) = _NA_); \ } \ } \ } else { \ for (j_ = 0; j_ < n_; ++j_) { \ pp1[j_] = n_ - j_; \ for (i_ = j_; i_ < n_; ++i_) { \ *(pi1++) = i_; \ _MASK1_(*(px1++) = _NA_); \ } \ } \ } \ } \ else if (r >= mn) { \ if ((ul == 'U') == !byrow) { \ while (k < nnz0 && (pos = (Matrix_int_fast64_t) pi0[k] - 1) < mn) { \ if ((i_ = pos % n_) <= (j_ = pos / n_)) { \ ++pp1[j_]; \ *(pi1++) = i_; \ _MASK1_(*(px1++) = _REPLACE_(px0[k], _ONE_)); \ } \ ++k; \ } \ } else { \ while (k < nnz0 && (pos = (Matrix_int_fast64_t) pi0[k] - 1) < mn) { \ if ((i_ = pos % n_) >= (j_ = pos / n_)) { \ ++pp1[j_]; \ *(pi1++) = i_; \ _MASK1_(*(px1++) = _REPLACE_(px0[k], _ONE_)); \ } \ ++k; \ } \ } \ } \ else { \ Matrix_int_fast64_t a = 0; \ if ((ul == 'U') == !byrow) { \ while (a < mn) { \ k = 0; \ while (k < nnz0 && (pos = a + pi0[k] - 1) < mn) { \ if ((i_ = pos % n) <= (j_ = pos / n)) { \ ++pp1[j_]; \ *(pi1++) = i_; \ _MASK1_(*(px1++) = _REPLACE_(px0[k], _ONE_)); \ } \ ++k; \ } \ a += r; \ } \ } else { \ while (a < mn) { \ k = 0; \ while (k < nnz0 && (pos = a + pi0[k] - 1) < mn) { \ if ((i_ = pos % n) >= (j_ = pos / n)) { \ ++pp1[j_]; \ *(pi1++) = i_; \ _MASK1_(*(px1++) = _REPLACE_(px0[k], _ONE_)); \ } \ ++k; \ } \ a += r; \ } \ } \ } \ } \ else { \ if (r == 0) { \ if ((ul == 'U') == !byrow) { \ for (j_ = 0; j_ < n_; ++j_) { \ pp1[j_] = j_; \ for (i_ = 0; i_ < j_; ++i_) { \ *(pi1++) = i_; \ _MASK1_(*(px1++) = _NA_); \ } \ } \ } else { \ for (j_ = 0; j_ < n_; ++j_) { \ pp1[j_] = n_ - j_ - 1; \ for (i_ = j_ + 1; i_ < n_; ++i_) { \ *(pi1++) = i_; \ _MASK1_(*(px1++) = _NA_); \ } \ } \ } \ } \ else if (r >= mn) { \ if ((ul == 'U') == !byrow) { \ while (k < nnz0 && (pos = (Matrix_int_fast64_t) pi0[k] - 1) < mn) { \ if ((i_ = pos % n_) < (j_ = pos / n_)) { \ ++pp1[j_]; \ *(pi1++) = i_; \ _MASK1_(*(px1++) = _REPLACE_(px0[k], _ONE_)); \ } \ ++k; \ } \ } else { \ while (k < nnz0 && (pos = (Matrix_int_fast64_t) pi0[k] - 1) < mn) { \ if ((i_ = pos % n_) > (j_ = pos / n_)) { \ ++pp1[j_]; \ *(pi1++) = i_; \ _MASK1_(*(px1++) = _REPLACE_(px0[k], _ONE_)); \ } \ ++k; \ } \ } \ } \ else { \ Matrix_int_fast64_t a = 0; \ if ((ul == 'U') == !byrow) { \ while (a < mn) { \ k = 0; \ while (k < nnz0 && (pos = a + pi0[k] - 1) < mn) { \ if ((i_ = pos % n) < (j_ = pos / n)) { \ ++pp1[j_]; \ *(pi1++) = i_; \ _MASK1_(*(px1++) = _REPLACE_(px0[k], _ONE_)); \ } \ ++k; \ } \ a += r; \ } \ } else { \ while (a < mn) { \ k = 0; \ while (k < nnz0 && (pos = a + pi0[k] - 1) < mn) { \ if ((i_ = pos % n) > (j_ = pos / n)) { \ ++pp1[j_]; \ *(pi1++) = i_; \ _MASK1_(*(px1++) = _REPLACE_(px0[k], _ONE_)); \ } \ ++k; \ } \ a += r; \ } \ } \ } \ } \ } while (0) if (cl[0] == 'n') VAS_SUBCASES(HIDE, HIDE, , , , , ); else { SEXP x1 = PROTECT(allocVector(kindToType(cl[0]), nnz1)); switch (cl[0]) { case 'l': if (x0 == R_NilValue) VAS_SUBCASES(HIDE, SHOW, SECONDOF, int, LOGICAL, 1, NA_LOGICAL); else VAS_SUBCASES(SHOW, SHOW, FIRSTOF, int, LOGICAL, 1, NA_LOGICAL); break; case 'i': if (x0 == R_NilValue) VAS_SUBCASES(HIDE, SHOW, SECONDOF, int, INTEGER, 1, NA_INTEGER); else VAS_SUBCASES(SHOW, SHOW, FIRSTOF, int, INTEGER, 1, NA_INTEGER); break; case 'd': if (x0 == R_NilValue) VAS_SUBCASES(HIDE, SHOW, SECONDOF, double, REAL, 1.0, NA_REAL); else VAS_SUBCASES(SHOW, SHOW, FIRSTOF, double, REAL, 1.0, NA_REAL); break; case 'z': if (x0 == R_NilValue) VAS_SUBCASES(HIDE, SHOW, SECONDOF, Rcomplex, COMPLEX, Matrix_zone, Matrix_zna); else VAS_SUBCASES(SHOW, SHOW, FIRSTOF, Rcomplex, COMPLEX, Matrix_zone, Matrix_zna); break; default: break; } SET_SLOT(to, Matrix_xSym, x1); UNPROTECT(1); /* x1 */ } #undef VAS_SUBCASES #undef VAS_SUBSUBCASES for (j_ = 0; j_ < n_; ++j_) pp1[j_] += pp1[j_ - 1]; switch (zzz[2]) { case 'C': to = sparse_as_Csparse(to, cl); break; case 'R': to = sparse_as_Rsparse(to, cl); break; case 'T': to = sparse_as_Tsparse(to, cl); break; default: break; } UNPROTECT(5); /* i1, p1, to, x0, i0 */ return to; } SEXP R_vector_as_sparse(SEXP from, SEXP zzz, SEXP uplo, SEXP diag, SEXP m, SEXP n, SEXP byrow, SEXP dimnames) { static const char *valid[] = { VALID_NONVIRTUAL_VECTOR, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *zzz_; if (TYPEOF(zzz) != STRSXP || LENGTH(zzz) < 1 || (zzz = STRING_ELT(zzz, 0)) == NA_STRING || (zzz_ = CHAR(zzz))[0] == '\0' || (zzz_[1] != 'g' && zzz_[1] != 's' && zzz_[1] != 't') || (zzz_[2] != 'C' && zzz_[2] != 'R' && zzz_[2] != 'T')) error(_("second argument of '%s' does not specify a subclass of %s"), __func__, "[CRT]sparseMatrix"); char ul = 'U', di = 'N'; if (zzz_[1] != 'g') { if (TYPEOF(uplo) != STRSXP || LENGTH(uplo) < 1 || (uplo = STRING_ELT(uplo, 0)) == NA_STRING || ((ul = *CHAR(uplo)) != 'U' && ul != 'L')) error(_("'%s' must be \"%s\" or \"%s\""), "uplo", "U", "L"); } if (zzz_[1] == 't') { if (TYPEOF(diag) != STRSXP || LENGTH(diag) < 1 || (diag = STRING_ELT(diag, 0)) == NA_STRING || ((di = *CHAR(diag)) != 'N' && di != 'U')) error(_("'%s' must be \"%s\" or \"%s\""), "diag", "N", "U"); } int m_ = -1; if (m != R_NilValue) { if (TYPEOF(m) == INTSXP) { int tmp; if (LENGTH(m) >= 1 && (tmp = INTEGER(m)[0]) != NA_INTEGER && tmp >= 0) m_ = tmp; } else if (TYPEOF(m) == REALSXP) { double tmp; if (LENGTH(m) >= 1 && !ISNAN(tmp = REAL(m)[0]) && tmp >= 0.0) { if (trunc(tmp) > INT_MAX) error(_("dimensions cannot exceed %s"), "2^31-1"); m_ = (int) tmp; } } if (m_ < 0) error(_("invalid '%s' to '%s'"), "m", __func__); } int n_ = -1; if (n != R_NilValue) { if (TYPEOF(n) == INTSXP) { int tmp; if (LENGTH(n) >= 1 && (tmp = INTEGER(n)[0]) != NA_INTEGER && tmp >= 0) n_ = tmp; } else if (TYPEOF(n) == REALSXP) { double tmp; if (LENGTH(n) >= 1 && !ISNAN(tmp = REAL(n)[0]) && tmp >= 0.0) { if (trunc(tmp) > INT_MAX) error(_("dimensions cannot exceed %s"), "2^31-1"); n_ = (int) tmp; } } if (n_ < 0) error(_("invalid '%s' to '%s'"), "n", __func__); } int byrow_; if (TYPEOF(byrow) != LGLSXP || LENGTH(byrow) < 1 || (byrow_ = LOGICAL(byrow)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "byrow", "TRUE", "FALSE"); if (dimnames != R_NilValue) if (TYPEOF(dimnames) != VECSXP || LENGTH(dimnames) != 2) error(_("invalid '%s' to '%s'"), "dimnames", __func__); SEXP tmp = GET_SLOT(from, Matrix_lengthSym); Matrix_int_fast64_t vlen_ = (Matrix_int_fast64_t) ((TYPEOF(tmp) == INTSXP) ? INTEGER(tmp)[0] : REAL(tmp)[0]); if (zzz_[1] != 'g' && (m_ < 0) != (n_ < 0)) { if (m_ < 0) m_ = n_; else n_ = m_; } else if (m_ < 0 && n_ < 0) { if (vlen_ > INT_MAX) error(_("dimensions cannot exceed %s"), "2^31-1"); m_ = (int) vlen_; n_ = 1; } else if (m_ < 0) { if (vlen_ > (Matrix_int_fast64_t) INT_MAX * n_) { if (n_ == 0) error(_("nonempty vector supplied for empty matrix")); else error(_("dimensions cannot exceed %s"), "2^31-1"); } m_ = (n_ == 0) ? 0 : vlen_ / n_ + (vlen_ % n_ != 0); } else if (n_ < 0) { if (vlen_ > (Matrix_int_fast64_t) m_ * INT_MAX) { if (m_ == 0) error(_("nonempty vector supplied for empty matrix")); else error(_("dimensions cannot exceed %s"), "2^31-1"); } n_ = (m_ == 0) ? 0 : vlen_ / m_ + (vlen_ % m_ != 0); } Matrix_int_fast64_t mlen_ = (Matrix_int_fast64_t) m_ * n_; if (vlen_ <= 1) /* do nothing */ ; else if (mlen_ == 0) warning(_("nonempty vector supplied for empty matrix")); else if (vlen_ > mlen_) warning(_("vector length (%lld) exceeds matrix length (%d * %d)"), (long long) vlen_, m_, n_); else if (mlen_ % vlen_ != 0) warning(_("matrix length (%d * %d) is not a multiple of vector length (%lld)"), m_, n_, (long long) vlen_); return vector_as_sparse(from, zzz_, ul, di, m_, n_, byrow_, dimnames); } SEXP matrix_as_sparse(SEXP from, const char *zzz, char ul, char di, int trans) { char cl[] = "...Matrix"; cl[0] = typeToKind(TYPEOF(from)); cl[1] = zzz[1]; cl[2] = (zzz[1] == 'g') ? 'e' : ((zzz[1] == 's') ? 'y' : 'r'); #ifndef MATRIX_ENABLE_IMATRIX if (cl[0] == 'i') cl[0] = 'd'; #endif PROTECT_INDEX pid; PROTECT_WITH_INDEX(from, &pid); REPROTECT(from = matrix_as_dense(from, cl, ul, di, trans, 0), pid); REPROTECT(from = dense_as_sparse(from, cl, zzz[2]), pid); cl[2] = zzz[2]; REPROTECT(from = sparse_as_kind(from, cl, zzz[0]), pid); UNPROTECT(1); return from; } /* as(, ".[gst][CRT]Matrix") */ SEXP R_matrix_as_sparse(SEXP from, SEXP zzz, SEXP uplo, SEXP diag, SEXP trans) { switch (TYPEOF(from)) { case LGLSXP: case INTSXP: case REALSXP: case CPLXSXP: break; default: ERROR_INVALID_TYPE(from, __func__); break; } const char *zzz_; if (TYPEOF(zzz) != STRSXP || LENGTH(zzz) < 1 || (zzz = STRING_ELT(zzz, 0)) == NA_STRING || (zzz_ = CHAR(zzz))[0] == '\0' || (zzz_[1] != 'g' && zzz_[1] != 's' && zzz_[1] != 't') || (zzz_[2] != 'C' && zzz_[2] != 'R' && zzz_[2] != 'T')) error(_("second argument of '%s' does not specify a subclass of %s"), __func__, "[CRT]sparseMatrix"); char ul = 'U', di = 'N'; if (zzz_[1] != 'g') { if (TYPEOF(uplo) != STRSXP || LENGTH(uplo) < 1 || (uplo = STRING_ELT(uplo, 0)) == NA_STRING || ((ul = *CHAR(uplo)) != 'U' && ul != 'L')) error(_("'%s' must be \"%s\" or \"%s\""), "uplo", "U", "L"); } if (zzz_[1] == 't') { if (TYPEOF(diag) != STRSXP || LENGTH(diag) < 1 || (diag = STRING_ELT(diag, 0)) == NA_STRING || ((di = *CHAR(diag)) != 'N' && di != 'U')) error(_("'%s' must be \"%s\" or \"%s\""), "diag", "N", "U"); } int trans_; if (TYPEOF(trans) != LGLSXP || LENGTH(trans) < 1 || (trans_ = LOGICAL(trans)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "trans", "TRUE", "FALSE"); return matrix_as_sparse(from, zzz_, ul, di, trans_); } SEXP dense_as_sparse(SEXP from, const char *class, char repr) { char cl[] = "...Matrix"; cl[0] = class[0]; cl[1] = class[1]; cl[2] = repr; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; if (m != n || n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ char ul = 'U', di = 'N'; if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N') SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } } SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), p1, i1, j1; int i, j, *pp, *pi, *pj; R_xlen_t nnz = 0; p1 = i1 = j1 = NULL; pp = pi = pj = NULL; #define DAS_CASES(_MASK_) \ do { \ switch (class[0]) { \ case 'l': \ DAS_SUBCASES(int, LOGICAL, _MASK_, ISNZ_LOGICAL); \ break; \ case 'i': \ DAS_SUBCASES(int, INTEGER, _MASK_, ISNZ_INTEGER); \ break; \ case 'd': \ DAS_SUBCASES(double, REAL, _MASK_, ISNZ_REAL); \ break; \ case 'z': \ DAS_SUBCASES(Rcomplex, COMPLEX, _MASK_, ISNZ_COMPLEX); \ break; \ default: \ break; \ } \ } while (0) #define DAS_SUBCASES(_CTYPE_, _PTR_, _MASK_, _ISNZ_) \ do { \ _CTYPE_ *px0 = _PTR_(x0) ; \ _MASK_(_CTYPE_ *px1 = _PTR_(x1)); \ if (class[1] == 'g') \ /* .geMatrix */ \ DAS_SUBSUBCASES(DAS_LOOP_GEN2C, DAS_LOOP_GEN2R, DAS_LOOP_GEN2C, \ _MASK_, _ISNZ_); \ else if (class[2] != 'p' && di == 'N') \ /* .syMatrix, non-unit diagonal .trMatrix */ \ DAS_SUBSUBCASES(DAS_LOOP_TRN2C, DAS_LOOP_TRN2R, DAS_LOOP_TRN2C, \ _MASK_, _ISNZ_); \ else if (class[2] != 'p') \ /* unit diagonal .trMatrix */ \ DAS_SUBSUBCASES(DAS_LOOP_TRU2C, DAS_LOOP_TRU2R, DAS_LOOP_TRU2C, \ _MASK_, _ISNZ_); \ else if (di == 'N') \ /* .spMatrix, non-unit diagonal .tpMatrix */ \ DAS_SUBSUBCASES(DAS_LOOP_TPN2C, DAS_LOOP_TPN2R, DAS_LOOP_TPN2C, \ _MASK_, _ISNZ_); \ else \ /* unit diagonal .tpMatrix */ \ DAS_SUBSUBCASES(DAS_LOOP_TPU2C, DAS_LOOP_TPU2R, DAS_LOOP_TPU2C, \ _MASK_, _ISNZ_); \ } while (0) #undef DAS_SUBSUBCASES #define DAS_SUBSUBCASES(_LOOP_C_, _LOOP_R_, _LOOP_T_, _MASK_, _ISNZ_) \ do { \ switch (cl[2]) { \ case 'C': \ _LOOP_C_(_ISNZ_, ++nnz, DAS_VALID2C); \ break; \ case 'R': \ _LOOP_R_(_ISNZ_, ++nnz, DAS_VALID2R); \ break; \ case 'T': \ _LOOP_T_(_ISNZ_, ++nnz, DAS_VALID2T); \ break; \ default: \ break; \ } \ } while (0) #define DAS_LOOP_GEN2C(_ISNZ_, _DO_INNER_, _DO_OUTER_) \ do { \ for (j = 0; j < n; ++j) { \ for (i = 0; i < m; ++i, ++px0) \ if (_ISNZ_(*px0)) _DO_INNER_; \ _DO_OUTER_; \ } \ } while (0) #define DAS_LOOP_GEN2R(_ISNZ_, _DO_INNER_, _DO_OUTER_) \ do { \ R_xlen_t mn1s = (R_xlen_t) m * n - 1; \ for (i = 0; i < m; ++i, px0 -= mn1s) { \ for (j = 0; j < n; ++j, px0 += m) \ if (_ISNZ_(*px0)) _DO_INNER_; \ _DO_OUTER_; \ } \ } while (0) #define DAS_LOOP_TRN2C(_ISNZ_, _DO_INNER_, _DO_OUTER_) \ do { \ if (ul == 'U') { \ for (j = 0; j < n; px0 += n - (++j)) { \ for (i = 0; i <= j; ++i, ++px0) \ if (_ISNZ_(*px0)) _DO_INNER_; \ _DO_OUTER_; \ } \ } else { \ for (j = 0; j < n; px0 += (++j)) { \ for (i = j; i < n; ++i, ++px0) \ if (_ISNZ_(*px0)) _DO_INNER_; \ _DO_OUTER_; \ } \ } \ } while (0) #define DAS_LOOP_TRN2R(_ISNZ_, _DO_INNER_, _DO_OUTER_) \ do { \ R_xlen_t d; \ if (ul == 'U') { \ d = (R_xlen_t) n * n - 1; \ for (i = 0; i < n; ++i, px0 -= (d -= n)) { \ for (j = i; j < n; ++j, px0 += n) \ if (_ISNZ_(*px0)) _DO_INNER_; \ _DO_OUTER_; \ } \ } else { \ d = -1; \ for (i = 0; i < n; ++i, px0 -= (d += n)) { \ for (j = 0; j <= i; ++j, px0 += n) \ if (_ISNZ_(*px0)) _DO_INNER_; \ _DO_OUTER_; \ } \ } \ } while (0) #define DAS_LOOP_TRU2C(_ISNZ_, _DO_INNER_, _DO_OUTER_) \ do { \ if (ul == 'U') { \ px0 += n; \ for (j = 1; j < n; ++j) { \ for (i = 0; i < j; ++i, ++px0) \ if (_ISNZ_(*px0)) _DO_INNER_; \ _DO_OUTER_; \ px0 += n - j; \ } \ } else { \ for (j = 0; j < n; ++j) { \ px0 += j + 1; \ for (i = j + 1; i < n; ++i, ++px0) \ if (_ISNZ_(*px0)) _DO_INNER_; \ _DO_OUTER_; \ } \ } \ } while (0) #define DAS_LOOP_TRU2R(_ISNZ_, _DO_INNER_, _DO_OUTER_) \ do { \ R_xlen_t d; \ if (ul == 'U') { \ d = (R_xlen_t) n * (n - 1) - 1; \ for (i = 0; i < n; ++i) { \ for (j = i + 1; j < n; ++j) { \ px0 += n; \ if (_ISNZ_(*px0)) _DO_INNER_; \ } \ _DO_OUTER_; \ px0 -= (d -= n); \ } \ } else { \ ++px0; \ d = -1; \ for (i = 1; i < n; ++i) { \ for (j = 0; j < i; ++j) { \ if (_ISNZ_(*px0)) _DO_INNER_; \ px0 += n; \ } \ _DO_OUTER_; \ px0 -= (d += n); \ } \ } \ } while (0) #define DAS_LOOP_TPN2C(_ISNZ_, _DO_INNER_, _DO_OUTER_) \ do { \ if (ul == 'U') { \ for (j = 0; j < n; ++j) { \ for (i = 0; i <= j; ++i, ++px0) \ if (_ISNZ_(*px0)) _DO_INNER_; \ _DO_OUTER_; \ } \ } else { \ for (j = 0; j < n; ++j) { \ for (i = j; i < n; ++i, ++px0) \ if (_ISNZ_(*px0)) _DO_INNER_; \ _DO_OUTER_; \ } \ } \ } while (0) #define DAS_LOOP_TPN2R(_ISNZ_, _DO_INNER_, _DO_OUTER_) \ do { \ R_xlen_t d; \ if (ul == 'U') { \ d = PACKED_LENGTH(n) - 1; \ for (i = 0; i < n; px0 -= (d -= (++i))) { \ for (j = i; j < n; px0 += (++j)) \ if (_ISNZ_(*px0)) _DO_INNER_; \ _DO_OUTER_; \ } \ } else { \ d = -1; \ for (i = 0; i < n; px0 -= (d += n - (++i))) { \ for (j = 0; j <= i; px0 += n - (++j)) \ if (_ISNZ_(*px0)) _DO_INNER_; \ _DO_OUTER_; \ } \ } \ } while (0) #define DAS_LOOP_TPU2C(_ISNZ_, _DO_INNER_, _DO_OUTER_) \ do { \ if (ul == 'U') { \ for (j = 1; j < n; ++j) { \ ++px0; \ for (i = 0; i < j; ++i, ++px0) \ if (_ISNZ_(*px0)) _DO_INNER_; \ _DO_OUTER_; \ } \ } else { \ for (j = 0; j < n; ++j) { \ ++px0; \ for (i = j + 1; i < n; ++i, ++px0) \ if (_ISNZ_(*px0)) _DO_INNER_; \ _DO_OUTER_; \ } \ } \ } while (0) #define DAS_LOOP_TPU2R(_ISNZ_, _DO_INNER_, _DO_OUTER_) \ do { \ R_xlen_t d; \ if (ul == 'U') { \ d = PACKED_LENGTH(n - 1) - 1; \ for (i = 0; i < n; ++i) { \ for (j = i + 1; j < n; ++j) { \ px0 += j; \ if (_ISNZ_(*px0)) _DO_INNER_; \ } \ _DO_OUTER_; \ px0 -= (d -= i + 1); \ } \ } else { \ ++px0; \ d = -1; \ for (i = 1; i < n; ++i) { \ for (j = 0; j < i; ++j) { \ if (_ISNZ_(*px0)) _DO_INNER_; \ px0 += n - j - 1; \ } \ _DO_OUTER_; \ px0 -= (d += n - i); \ } \ } \ } while (0) #define DAS_VALID2T \ if (nnz > INT_MAX) \ error(_("attempt to construct %s with more than %s nonzero entries"), \ "sparseMatrix", "2^31-1") #define DAS_VALID2C \ do { DAS_VALID2T; else *(pp++) = (int) nnz; } while (0) #define DAS_VALID2R DAS_VALID2C /* First we loop over the _nontrivial part_ of the denseMatrix 'from', by row ('R' case) or by column ('C' and 'T' cases), counting the nonzero entries and filling the 'p' slot of the result accordingly ('C' and 'R' cases) ... */ int nprotect = 2; if (cl[2] != 'T') { int r = (cl[2] == 'C') ? n : m; PROTECT(p1 = allocVector(INTSXP, (R_xlen_t) r + 1)); ++nprotect; SET_SLOT(to, Matrix_pSym, p1); pp = INTEGER(p1); *(pp++) = 0; if (r > 0 && di != 'N' && ul == ((cl[2] == 'C') ? 'U' : 'L')) *(pp++) = 0; /* first row or column skipped in these loops */ } if (class[0] == 'n') DAS_SUBCASES(int, LOGICAL, HIDE, ISNZ_LOGICAL); else DAS_CASES(HIDE); if (cl[2] != 'R') { PROTECT(i1 = allocVector(INTSXP, nnz)); ++nprotect; SET_SLOT(to, Matrix_iSym, i1); pi = INTEGER(i1); } if (cl[2] != 'C') { PROTECT(j1 = allocVector(INTSXP, nnz)); ++nprotect; SET_SLOT(to, Matrix_jSym, j1); pj = INTEGER(j1); } #undef DAS_SUBSUBCASES #define DAS_SUBSUBCASES(_LOOP_C_, _LOOP_R_, _LOOP_T_, _MASK_, _ISNZ_) \ do { \ switch (repr) { \ case 'C': \ _LOOP_C_(_ISNZ_, \ do { \ *(pi++) = i; \ _MASK_(*(px1++) = *px0); \ } while (0), ); \ break; \ case 'R': \ _LOOP_R_(_ISNZ_, \ do { \ *(pj++) = j; \ _MASK_(*(px1++) = *px0); \ } while (0), ); \ break; \ case 'T': \ _LOOP_T_(_ISNZ_, \ do { \ *(pi++) = i; \ *(pj++) = j; \ _MASK_(*(px1++) = *px0); \ } while (0), ); \ break; \ default: \ break; \ } \ } while (0) /* Then we loop back over the same entries in order to fill the 'i', 'j', and 'x' slots of the result (whichever exist) ... */ if (class[0] == 'n') DAS_SUBCASES(int, LOGICAL, HIDE, ISNZ_LOGICAL); else { SEXP x1 = PROTECT(allocVector(TYPEOF(x0), nnz)); SET_SLOT(to, Matrix_xSym, x1); DAS_CASES(SHOW); UNPROTECT(1); /* x1 */ } #undef DAS_CASES #undef DAS_SUBCASES #undef DAS_SUBSUBCASES #undef DAS_VALID2C #undef DAS_VALID2R #undef DAS_VALID2T #undef DAS_LOOP_GEN2C #undef DAS_LOOP_GEN2R #undef DAS_LOOP_TRN2C #undef DAS_LOOP_TRN2R #undef DAS_LOOP_TRU2C #undef DAS_LOOP_TRU2R #undef DAS_LOOP_TPN2C #undef DAS_LOOP_TPN2R #undef DAS_LOOP_TPU2C #undef DAS_LOOP_TPU2R UNPROTECT(nprotect); return to; } /* as(, "[CRT]sparseMatrix") */ SEXP R_dense_as_sparse(SEXP from, SEXP repr) { static const char *valid[] = { VALID_DENSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); char repr_; if (TYPEOF(repr) != STRSXP || LENGTH(repr) < 1 || (repr = STRING_ELT(repr, 0)) == NA_STRING || ((repr_ = CHAR(repr)[0]) != 'C' && repr_ != 'R' && repr_ != 'T')) error(_("invalid '%s' to '%s'"), "repr", __func__); return dense_as_sparse(from, valid[ivalid], repr_); } SEXP diagonal_as_sparse(SEXP from, const char *class, char kind, char shape, char repr, char ul) { char cl[] = "...Matrix"; cl[0] = (kind == '.') ? class[0] : ((kind == ',') ? ((class[0] == 'z') ? 'z' : 'd') : kind); cl[1] = shape; cl[2] = repr; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int n = INTEGER(dim)[0]; if (n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); if (cl[1] == 's') set_symmetrized_DimNames(to, dimnames, -1); else SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ if (cl[1] != 'g' && ul != 'U') { SEXP uplo = PROTECT(mkString("L")); SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); char di = *CHAR(STRING_ELT(diag, 0)); if (cl[1] == 't' && di != 'N') SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ if (cl[1] == 't' && di != 'N') { if (cl[2] != 'T') { SEXP p = PROTECT(allocVector(INTSXP, (R_xlen_t) n + 1)); SET_SLOT(to, Matrix_pSym, p); Matrix_memset(INTEGER(p), 0, (R_xlen_t) n + 1, sizeof(int)); UNPROTECT(1); /* p */ } UNPROTECT(1); /* to */ return to; } #define DAS_CASES(_MASK_) \ do { \ switch (cl[0]) { \ case 'l': \ DAS_LOOP(int, LOGICAL, _MASK_, ISNZ_LOGICAL, 1); \ break; \ case 'i': \ DAS_LOOP(int, INTEGER, _MASK_, ISNZ_INTEGER, 1); \ break; \ case 'd': \ DAS_LOOP(double, REAL, _MASK_, ISNZ_REAL, 1.0); \ break; \ case 'z': \ DAS_LOOP(Rcomplex, COMPLEX, _MASK_, ISNZ_COMPLEX, Matrix_zone); \ break; \ default: \ break; \ } \ } while (0) SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)); if (class[0] != cl[0]) { if (class[0] == 'n' && cl[0] == 'l') x0 = duplicate(x0); else x0 = coerceVector(x0, kindToType(cl[0])); if (class[0] == 'n') naToOne(x0); UNPROTECT(1); /* x0 */ PROTECT(x0); } int d, nnz; if (cl[2] != 'T') { SEXP p = PROTECT(allocVector(INTSXP, (R_xlen_t) n + 1)); SET_SLOT(to, Matrix_pSym, p); int *pp = INTEGER(p); *(pp++) = 0; if (di == 'N') { nnz = 0; #undef DAS_LOOP #define DAS_LOOP(_CTYPE_, _PTR_, _MASK_, _ISNZ_, _ONE_) \ do { \ _CTYPE_ *px0 = _PTR_(x0); \ for (d = 0; d < n; ++d) { \ if (_ISNZ_(*px0)) \ ++nnz; \ *(pp++) = nnz; \ ++px0; \ } \ } while (0) if (cl[0] == 'n') DAS_LOOP(int, LOGICAL, HIDE, ISNZ_LOGICAL, 1); else DAS_CASES(SHOW); } else { nnz = n; for (d = 1; d <= n; ++d) *(pp++) = d; } UNPROTECT(1); /* p */ } else { if (di == 'N') { nnz = 0; #undef DAS_LOOP #define DAS_LOOP(_CTYPE_, _PTR_, _MASK_, _ISNZ_, _ONE_) \ do { \ _CTYPE_ *px0 = _PTR_(x0); \ for (d = 0; d < n; ++d) { \ if (_ISNZ_(*px0)) \ ++nnz; \ ++px0; \ } \ } while (0) if (cl[0] == 'n') DAS_LOOP(int, LOGICAL, HIDE, ISNZ_LOGICAL, 1); else DAS_CASES(SHOW); } else nnz = n; } SEXP i1 = PROTECT(allocVector(INTSXP, nnz)); if (cl[2] != 'T') SET_SLOT(to, (cl[2] == 'C') ? Matrix_iSym : Matrix_jSym, i1); else { SET_SLOT(to, Matrix_iSym, i1); SET_SLOT(to, Matrix_jSym, i1); } int *pi1 = INTEGER(i1); #undef DAS_LOOP #define DAS_LOOP(_CTYPE_, _PTR_, _MASK_, _ISNZ_, _ONE_) \ do { \ _MASK_(_CTYPE_ *px1 = _PTR_(x1)); \ if (di == 'N') { \ _CTYPE_ *px0 = _PTR_(x0); \ for (d = 0; d < n; ++d) { \ if (_ISNZ_(*px0)) { \ *(pi1++) = d; \ _MASK_(*(px1++) = *px0); \ } \ ++px0; \ } \ } else { \ for (d = 0; d < n; ++d) { \ *(pi1++) = d; \ _MASK_(*(px1++) = _ONE_); \ } \ } \ } while (0) if (cl[0] == 'n') DAS_LOOP(int, LOGICAL, HIDE, ISNZ_LOGICAL, 1); else if (di == 'N' && nnz == n) { SET_SLOT(to, Matrix_xSym, x0); DAS_CASES(HIDE); } else { SEXP x1 = PROTECT(allocVector(TYPEOF(x0), nnz)); SET_SLOT(to, Matrix_xSym, x1); DAS_CASES(SHOW); UNPROTECT(1); /* x1 */ } UNPROTECT(3); /* i1, x0, to */ return to; } /* as(, ".[gst][CRT]Matrix") */ SEXP R_diagonal_as_sparse(SEXP from, SEXP kind, SEXP shape, SEXP repr, SEXP uplo) { static const char *valid[] = { VALID_DIAGONAL, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); char kind_; if (TYPEOF(kind) != STRSXP || LENGTH(kind) < 1 || (kind = STRING_ELT(kind, 0)) == NA_STRING || (kind_ = CHAR(kind)[0]) == '\0') error(_("invalid '%s' to '%s'"), "kind", __func__); char shape_; if (TYPEOF(shape) != STRSXP || LENGTH(shape) < 1 || (shape = STRING_ELT(shape, 0)) == NA_STRING || ((shape_ = CHAR(shape)[0]) != 'g' && shape_ != 's' && shape_ != 't')) error(_("invalid '%s' to '%s'"), "shape", __func__); char repr_; if (TYPEOF(repr) != STRSXP || LENGTH(repr) < 1 || (repr = STRING_ELT(repr, 0)) == NA_STRING || ((repr_ = CHAR(repr)[0]) != 'C' && repr_ != 'R' && repr_ != 'T')) error(_("invalid '%s' to '%s'"), "repr", __func__); char ul = 'U'; if (shape_ != 'g') { if (TYPEOF(uplo) != STRSXP || LENGTH(uplo) < 1 || (uplo = STRING_ELT(uplo, 0)) == NA_STRING || ((ul = *CHAR(uplo)) != 'U' && ul != 'L')) error(_("'%s' must be \"%s\" or \"%s\""), "uplo", "U", "L"); } return diagonal_as_sparse(from, valid[ivalid], kind_, shape_, repr_, ul); } SEXP index_as_sparse(SEXP from, const char *class, char kind, char repr) { SEXP margin = PROTECT(GET_SLOT(from, Matrix_marginSym)); int mg = INTEGER(margin)[0] - 1; UNPROTECT(1); /* margin */ char cl[] = ".g.Matrix"; cl[0] = (kind == '.') ? 'n' : ((kind == ',') ? 'd' : kind); cl[2] = (repr == '.') ? ((mg == 0) ? 'R' : 'C') : repr; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1], r = (mg == 0) ? m : n, s = (mg == 0) ? n : m; if (m != n || n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ SEXP perm = PROTECT(GET_SLOT(from, Matrix_permSym)); int *pperm = INTEGER(perm); if (cl[2] == 'T') { SEXP i = PROTECT(allocVector(INTSXP, r)), j = PROTECT(allocVector(INTSXP, r)); int k, *pi = INTEGER(i), *pj = INTEGER(j); for (k = 0; k < r; ++k) { *(pi++) = k; *(pj++) = *(pperm++) - 1; } SET_SLOT(to, Matrix_iSym, (mg == 0) ? i : j); SET_SLOT(to, Matrix_jSym, (mg == 0) ? j : i); } else if ((cl[2] == 'C') == (mg != 0)) { SEXP p = PROTECT(allocVector(INTSXP, (R_xlen_t) r + 1)), i = PROTECT(allocVector(INTSXP, r)); int k, *pp = INTEGER(p), *pi = INTEGER(i); for (k = 0; k < r; ++k) { *(pp++) = k; *(pi++) = *(pperm++) - 1; } *pp = r; SET_SLOT(to, Matrix_pSym, p); SET_SLOT(to, (mg != 0) ? Matrix_iSym : Matrix_jSym, i); } else { SEXP p = PROTECT(allocVector(INTSXP, (R_xlen_t) s + 1)); int k, *pp = INTEGER(p); Matrix_memset(pp, 0, (R_xlen_t) s + 1, sizeof(int)); for (k = 0; k < r; ++k) ++pp[pperm[k]]; for (k = 0; k < s; ++k) pp[k + 1] += pp[k]; SEXP j = PROTECT(allocVector(INTSXP, r)); int *pj = INTEGER(j), *work; Matrix_Calloc(work, s, int); Matrix_memcpy(work, pp, s, sizeof(int)); --work; for (k = 0; k < r; ++k) pj[work[pperm[k]]++] = k; ++work; Matrix_Free(work, s); SET_SLOT(to, Matrix_pSym, p); SET_SLOT(to, (mg != 0) ? Matrix_jSym : Matrix_iSym, j); } UNPROTECT(2); if (cl[0] != 'n') { SEXP x = PROTECT(allocVector(kindToType(cl[0]), r)); SET_SLOT(to, Matrix_xSym, x); #define IAS_SUBCASES(_CTYPE_, _PTR_, _ONE_) \ do { \ _CTYPE_ *px = _PTR_(x); \ for (int k = 0; k < r; ++k) \ *(px++) = _ONE_; \ } while (0) switch (cl[0]) { case 'l': IAS_SUBCASES(int, LOGICAL, 1); break; case 'i': IAS_SUBCASES(int, INTEGER, 1); break; case 'd': IAS_SUBCASES(double, REAL, 1.0); break; case 'z': IAS_SUBCASES(Rcomplex, COMPLEX, Matrix_zone); break; default: break; } UNPROTECT(1); /* x */ } #undef IAS_SUBCASES UNPROTECT(2); /* perm, to */ return to; } /* as(, ".g[CRT]Matrix") */ SEXP R_index_as_sparse(SEXP from, SEXP kind, SEXP repr) { static const char *valid[] = { "indMatrix", "pMatrix" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); char kind_; if (TYPEOF(kind) != STRSXP || LENGTH(kind) < 1 || (kind = STRING_ELT(kind, 0)) == NA_STRING || (kind_ = CHAR(kind)[0]) == '\0') error(_("invalid '%s' to '%s'"), "kind", __func__); char repr_; if (TYPEOF(repr) != STRSXP || LENGTH(repr) < 1 || (repr = STRING_ELT(repr, 0)) == NA_STRING || ((repr_ = CHAR(repr)[0]) != '.' && repr_ != 'C' && repr_ != 'R' && repr_ != 'T')) error(_("invalid '%s' to '%s'"), "repr", __func__); return index_as_sparse(from, valid[ivalid], kind_, repr_); } SEXP dense_as_kind(SEXP from, const char *class, char kind, int new) { if (kind == '.') kind = class[0]; else if (kind == ',') kind = (class[0] == 'z') ? 'z' : 'd'; if (kind == class[0]) return from; SEXPTYPE tt = kindToType(kind); char cl[] = "...Matrix"; cl[0] = kind; cl[1] = class[1]; cl[2] = class[2]; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; if (m != n || n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); char ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); char di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N') SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } } PROTECT_INDEX pid; SEXP x; PROTECT_WITH_INDEX(x = GET_SLOT(from, Matrix_xSym), &pid); if (TYPEOF(x) != tt) { REPROTECT(x = coerceVector(x, tt), pid); if (class[0] == 'n') /* n->[idz] */ naToOne(x); } else if (new) { REPROTECT(x = duplicate(x), pid); if (class[0] == 'n') /* n->l */ naToOne(x); } else { if (class[0] == 'n') { /* n->l */ R_xlen_t i, len = XLENGTH(x); int *px = LOGICAL(x); for (i = 0; i < len; ++i, ++px) { if (*px == NA_LOGICAL) { REPROTECT(x = duplicate(x), pid); naToOne(x); break; } } } } SET_SLOT(to, Matrix_xSym, x); UNPROTECT(2); /* x, to */ return to; } /* as(, "[nlidz]Matrix") */ SEXP R_dense_as_kind(SEXP from, SEXP kind) { static const char *valid[] = { VALID_DENSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); char kind_; if (TYPEOF(kind) != STRSXP || LENGTH(kind) < 1 || (kind = STRING_ELT(kind, 0)) == NA_STRING || (kind_ = CHAR(kind)[0]) == '\0') error(_("invalid '%s' to '%s'"), "kind", __func__); return dense_as_kind(from, valid[ivalid], kind_, 0); } SEXP sparse_as_kind(SEXP from, const char *class, char kind) { if (kind == '.') kind = class[0]; else if (kind == ',') kind = (class[0] == 'z') ? 'z' : 'd'; if (kind == class[0]) return from; SEXPTYPE tt = kindToType(kind); if (class[2] == 'T' && (class[0] == 'n' || class[0] == 'l') && kind != 'n' && kind != 'l') { /* defined in ./sparse.c : */ SEXP Tsparse_aggregate(SEXP); from = Tsparse_aggregate(from); } PROTECT(from); char cl[] = "...Matrix"; cl[0] = kind; cl[1] = class[1]; cl[2] = class[2]; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; if (m != n || n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); char ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); char di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N') SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } } R_xlen_t nnz = -1; if (class[2] != 'T') { SEXP p = PROTECT(GET_SLOT(from, Matrix_pSym)); SET_SLOT(to, Matrix_pSym, p); nnz = INTEGER(p)[XLENGTH(p) - 1]; UNPROTECT(1); /* p */ } if (class[2] != 'R') { SEXP i = PROTECT(GET_SLOT(from, Matrix_iSym)); SET_SLOT(to, Matrix_iSym, i); if (nnz < 1) nnz = XLENGTH(i); UNPROTECT(1); /* i */ } if (class[2] != 'C') { SEXP j = PROTECT(GET_SLOT(from, Matrix_jSym)); SET_SLOT(to, Matrix_jSym, j); UNPROTECT(1); /* j */ } if (class[0] == 'n') { SEXP x = PROTECT(allocVector(tt, nnz)); switch (tt) { case LGLSXP: { int *px = LOGICAL(x); while (nnz--) *(px++) = 1; break; } case INTSXP: { int *px = INTEGER(x); while (nnz--) *(px++) = 1; break; } case REALSXP: { double *px = REAL(x); while (nnz--) *(px++) = 1.0; break; } case CPLXSXP: { Rcomplex *px = COMPLEX(x); while (nnz--) *(px++) = Matrix_zone; break; } default: break; } SET_SLOT(to, Matrix_xSym, x); UNPROTECT(1); /* x */ } else if (kind != 'n') { PROTECT_INDEX pid; SEXP x; PROTECT_WITH_INDEX(x = GET_SLOT(from, Matrix_xSym), &pid); REPROTECT(x = coerceVector(x, tt), pid); SET_SLOT(to, Matrix_xSym, x); UNPROTECT(1); /* x */ } UNPROTECT(2); /* to, from */ return to; } /* as(, "[nlidz]Matrix") */ SEXP R_sparse_as_kind(SEXP from, SEXP kind) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); char kind_; if (TYPEOF(kind) != STRSXP || LENGTH(kind) < 1 || (kind = STRING_ELT(kind, 0)) == NA_STRING || (kind_ = CHAR(kind)[0]) == '\0') error(_("invalid '%s' to '%s'"), "kind", __func__); return sparse_as_kind(from, valid[ivalid], kind_); } SEXP diagonal_as_kind(SEXP from, const char *class, char kind) { if (kind == '.') kind = class[0]; else if (kind == ',') kind = (class[0] == 'z') ? 'z' : 'd'; if (kind == class[0]) return from; SEXPTYPE tt = kindToType(kind); char cl[] = ".diMatrix"; cl[0] = kind; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int n = INTEGER(dim)[0]; if (n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); char di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N') SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ if (di == 'N') { PROTECT_INDEX pid; SEXP x; PROTECT_WITH_INDEX(x = GET_SLOT(from, Matrix_xSym), &pid); if (TYPEOF(x) == tt) { if (class[0] == 'n') { /* n->l */ R_xlen_t i, len = XLENGTH(x); int *px = LOGICAL(x); for (i = 0; i < len; ++i, ++px) { if (*px == NA_LOGICAL) { REPROTECT(x = duplicate(x), pid); naToOne(x); break; } } } } else { REPROTECT(x = coerceVector(x, tt), pid); if (class[0] == 'n') /* n->[idz] */ naToOne(x); } SET_SLOT(to, Matrix_xSym, x); UNPROTECT(1); /* x */ } UNPROTECT(1); /* to */ return to; } /* as(, "[nlidz]Matrix") */ SEXP R_diagonal_as_kind(SEXP from, SEXP kind) { static const char *valid[] = { VALID_DIAGONAL, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); char kind_; if (TYPEOF(kind) != STRSXP || LENGTH(kind) < 1 || (kind = STRING_ELT(kind, 0)) == NA_STRING || (kind_ = CHAR(kind)[0]) == '\0') error(_("invalid '%s' to '%s'"), "kind", __func__); return diagonal_as_kind(from, valid[ivalid], kind_); } SEXP index_as_kind(SEXP from, const char *class, char kind) { return index_as_sparse(from, class, kind, '.'); } /* as(, "[nlidz]Matrix") */ SEXP R_index_as_kind(SEXP from, SEXP kind) { static const char *valid[] = { "indMatrix", "pMatrix" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); char kind_; if (TYPEOF(kind) != STRSXP || LENGTH(kind) < 1 || (kind = STRING_ELT(kind, 0)) == NA_STRING || (kind_ = CHAR(kind)[0]) == '\0') error(_("invalid '%s' to '%s'"), "kind", __func__); return index_as_kind(from, valid[ivalid], kind_); } SEXP dense_as_general(SEXP from, const char *class, int new) { if (class[1] == 'g') return from; char cl[] = ".geMatrix"; cl[0] = class[0]; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int n = INTEGER(dim)[0]; if (n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); if (class[1] != 's') SET_SLOT(to, Matrix_DimNamesSym, dimnames); else set_symmetrized_DimNames(to, dimnames, -1); UNPROTECT(1); /* dimnames */ SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); char ul = *CHAR(STRING_ELT(uplo, 0)), di = 'N'; UNPROTECT(1); /* uplo */ if (class[1] == 's') { SEXP factors = PROTECT(GET_SLOT(from, Matrix_factorsSym)); if (LENGTH(factors) > 0) SET_SLOT(to, Matrix_factorsSym, factors); UNPROTECT(1); /* factors */ } else { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); di = *CHAR(STRING_ELT(diag, 0)); UNPROTECT(1); /* diag */ } if ((Matrix_int_fast64_t) n * n > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = x0; int nprotect = 2; if (class[2] == 'p' || new) { PROTECT(x1 = allocVector(TYPEOF(x0), (R_xlen_t) n * n)); ++nprotect; } SET_SLOT(to, Matrix_xSym, x1); #define DAG_SUBCASES(_PREFIX_, _CTYPE_, _PTR_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ if (class[2] == 'p') \ _PREFIX_ ## unpack1(px1, px0, n, ul, di); \ else if (new) \ Matrix_memcpy(px1, px0, (R_xlen_t) n * n, sizeof(_CTYPE_)); \ if (class[1] == 's') \ _PREFIX_ ## syforce2(px1, n, ul); \ else \ _PREFIX_ ## trforce2(px1, n, n, ul, di); \ } while (0) switch (class[0]) { case 'n': case 'l': DAG_SUBCASES(i, int, LOGICAL); break; case 'i': DAG_SUBCASES(i, int, INTEGER); break; case 'd': DAG_SUBCASES(d, double, REAL); break; case 'z': DAG_SUBCASES(z, Rcomplex, COMPLEX); break; default: break; } #undef DAG_CASES #undef DAG_SUBCASES UNPROTECT(nprotect); return to; } /* as(, "generaMatrix") */ SEXP R_dense_as_general(SEXP from) { static const char *valid[] = { VALID_DENSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); return dense_as_general(from, valid[ivalid], 1); } SEXP sparse_as_general(SEXP from, const char *class) { if (class[1] == 'g') return from; char cl[] = ".g.Matrix"; cl[0] = class[0]; cl[2] = class[2]; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int n = INTEGER(dim)[0]; if (n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); if (class[1] == 's') set_symmetrized_DimNames(to, dimnames, -1); else SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ if (class[1] == 's') { SEXP factors = PROTECT(GET_SLOT(from, Matrix_factorsSym)); if (LENGTH(factors) > 0) SET_SLOT(to, Matrix_factorsSym, factors); UNPROTECT(1); /* factors */ } else { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); char di = *CHAR(STRING_ELT(diag, 0)); UNPROTECT(1); /* diag */ if (di == 'N') { if (class[2] != 'T') { SEXP p = PROTECT(GET_SLOT(from, Matrix_pSym)); SET_SLOT(to, Matrix_pSym, p); UNPROTECT(1); /* p */ } if (class[2] != 'R') { SEXP i = PROTECT(GET_SLOT(from, Matrix_iSym)); SET_SLOT(to, Matrix_iSym, i); UNPROTECT(1); /* i */ } if (class[2] != 'C') { SEXP j = PROTECT(GET_SLOT(from, Matrix_jSym)); SET_SLOT(to, Matrix_jSym, j); UNPROTECT(1); /* j */ } if (class[0] != 'n') { SEXP x = PROTECT(GET_SLOT(from, Matrix_xSym)); SET_SLOT(to, Matrix_xSym, x); UNPROTECT(1); /* x */ } UNPROTECT(1); /* to */ return to; } } SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); char ul = *CHAR(STRING_ELT(uplo, 0)); UNPROTECT(1); /* uplo */ #define ASSIGN_COMPLEX_JJ(_X_, _Y_) \ do { _X_.r = _Y_.r; _X_.i = 0.0; } while (0) #define ASSIGN_COMPLEX_JI(_X_, _Y_) \ do { _X_.r = _Y_.r; _X_.i = -_Y_.i; } while (0) #define SAG_CASES \ do { \ switch (class[0]) { \ case 'l': \ SAG_SUBCASES(int, LOGICAL, SHOW, 1, \ ASSIGN_REAL, ASSIGN_REAL); \ break; \ case 'i': \ SAG_SUBCASES(int, INTEGER, SHOW, 1, \ ASSIGN_REAL, ASSIGN_REAL); \ break; \ case 'd': \ SAG_SUBCASES(double, REAL, SHOW, 1.0, \ ASSIGN_REAL, ASSIGN_REAL); \ break; \ case 'z': \ SAG_SUBCASES(Rcomplex, COMPLEX, SHOW, Matrix_zone, \ ASSIGN_COMPLEX_JJ, ASSIGN_COMPLEX_JI); \ break; \ default: \ break; \ } \ } while (0) if (class[2] != 'T') { SEXP iSym = (class[2] == 'C') ? Matrix_iSym : Matrix_jSym, p0 = PROTECT(GET_SLOT(from, Matrix_pSym)), p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) n + 1)), i0 = PROTECT(GET_SLOT(from, iSym)); int j, k, kend, *pp0 = INTEGER(p0), *pp1 = INTEGER(p1), *pi0 = INTEGER(i0); SET_SLOT(to, Matrix_pSym, p1); pp0++; *(pp1++) = 0; if (class[1] == 's') { Matrix_memset(pp1, 0, n, sizeof(int)); for (j = 0, k = 0; j < n; ++j) { kend = pp0[j]; while (k < kend) { if (pi0[k] != j) ++pp1[pi0[k]]; ++k; } } for (j = 1; j < n; ++j) pp1[j] += pp1[j - 1]; if (pp1[n - 1] > INT_MAX - pp0[n - 1]) error(_("attempt to construct %s with more than %s nonzero entries"), "sparseMatrix", "2^31-1"); for (j = 0; j < n; ++j) pp1[j] += pp0[j]; } else { if (n > INT_MAX - pp0[n - 1]) error(_("attempt to construct %s with more than %s nonzero entries"), "sparseMatrix", "2^31-1"); for (j = 0; j < n; ++j) pp1[j] = pp0[j] + j + 1; } SEXP i1 = PROTECT(allocVector(INTSXP, pp1[n - 1])); int *pi1 = INTEGER(i1); SET_SLOT(to, iSym, i1); #undef SAG_SUBCASES #define SAG_SUBCASES(_CTYPE_, _PTR_, _MASK_, _ONE_, _ASSIGN_JJ_, _ASSIGN_JI_) \ do { \ _MASK_(_CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1)); \ if (class[1] == 's') { \ int *pp1_; \ Matrix_Calloc(pp1_, n, int); \ Matrix_memcpy(pp1_, pp1 - 1, n, sizeof(int)); \ for (j = 0, k = 0; j < n; ++j) { \ kend = pp0[j]; \ while (k < kend) { \ if (pi0[k] == j) { \ pi1[pp1_[j]] = pi0[k]; \ _MASK_(_ASSIGN_JJ_(px1[pp1_[j]], px0[k])); \ ++pp1_[j]; \ } else { \ pi1[pp1_[j]] = pi0[k]; \ _MASK_(px1[pp1_[j]] = px0[k]); \ ++pp1_[j]; \ pi1[pp1_[pi0[k]]] = j; \ _MASK_(_ASSIGN_JI_(px1[pp1_[pi0[k]]], px0[k])); \ ++pp1_[pi0[k]]; \ } \ ++k; \ } \ } \ Matrix_Free(pp1_, n); \ } else if (ul == ((class[2] == 'C') ? 'U' : 'L')) { \ for (j = 0, k = 0; j < n; ++j) { \ kend = pp0[j]; \ while (k < kend) { \ *(pi1++) = *(pi0++); \ _MASK_(*(px1++) = *(px0++)); \ ++k; \ } \ *(pi1++) = j; \ _MASK_(*(px1++) = _ONE_); \ } \ } else { \ for (j = 0, k = 0; j < n; ++j) { \ kend = pp0[j]; \ *(pi1++) = j; \ _MASK_(*(px1++) = _ONE_); \ while (k < kend) { \ *(pi1++) = *(pi0++); \ _MASK_(*(px1++) = *(px0++)); \ ++k; \ } \ } \ } \ } while (0) if (class[0] == 'n') SAG_SUBCASES(int, LOGICAL, HIDE, 1, ASSIGN_REAL, ASSIGN_REAL); else { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), pp1[n - 1])); SET_SLOT(to, Matrix_xSym, x1); SAG_CASES; UNPROTECT(2); /* x1, x0 */ } } else { SEXP i0 = PROTECT(GET_SLOT(from, Matrix_iSym)), j0 = PROTECT(GET_SLOT(from, Matrix_jSym)); int *pi0 = INTEGER(i0), *pj0 = INTEGER(j0); R_xlen_t nnz0 = XLENGTH(i0), nnz1; if (class[1] == 's') { nnz1 = nnz0; for (R_xlen_t k = 0; k < nnz0; ++k) if (pi0[k] == pj0[k]) --nnz1; } else nnz1 = n; if (nnz1 > R_XLEN_T_MAX - nnz0) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); nnz1 += nnz0; SEXP i1 = PROTECT(allocVector(INTSXP, nnz1)), j1 = PROTECT(allocVector(INTSXP, nnz1)); int *pi1 = INTEGER(i1), *pj1 = INTEGER(j1); SET_SLOT(to, Matrix_iSym, i1); SET_SLOT(to, Matrix_jSym, j1); #undef SAG_SUBCASES #define SAG_SUBCASES(_CTYPE_, _PTR_, _MASK_, _ONE_, _ASSIGN_JJ_, _ASSIGN_JI_) \ do { \ _MASK_(_CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1)); \ if (class[1] == 's') { \ for (R_xlen_t k = 0; k < nnz0; ++k) { \ if (*pi0 == *pj0) { \ *(pi1++) = *pi0; \ *(pj1++) = *pj0; \ _MASK_(_ASSIGN_JJ_((*px1), (*px0))); \ _MASK_(++px1); \ } else { \ *(pi1++) = *pi0; \ *(pj1++) = *pj0; \ _MASK_(*px1 = *px0); \ _MASK_(++px1); \ *(pi1++) = *pj0; \ *(pj1++) = *pi0; \ _MASK_(_ASSIGN_JI_((*px1), (*px0))); \ _MASK_(++px1); \ } \ ++pi0; ++pj0; _MASK_(++px0); \ } \ } else { \ Matrix_memcpy(pi1, pi0, nnz0, sizeof(int)); \ Matrix_memcpy(pj1, pj0, nnz0, sizeof(int)); \ _MASK_(Matrix_memcpy(px1, px0, nnz0, sizeof(_CTYPE_))); \ pi1 += nnz0; \ pj1 += nnz0; \ _MASK_(px1 += nnz0); \ for (int d = 0; d < n; ++d) { \ *(pi1++) = *(pj1++) = d; \ _MASK_(*(px1++) = _ONE_); \ } \ } \ } while (0) if (class[0] == 'n') SAG_SUBCASES(int, LOGICAL, HIDE, 1, ASSIGN_REAL, ASSIGN_REAL); else { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), nnz1)); SET_SLOT(to, Matrix_xSym, x1); SAG_CASES; UNPROTECT(2); /* x1, x0 */ } } #undef SAG_CASES #undef SAG_SUBCASES UNPROTECT(5); return to; } /* as(<[CRT]sparseMatrix>, "generalMatrix") */ SEXP R_sparse_as_general(SEXP from) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); return sparse_as_general(from, valid[ivalid]); } SEXP dense_as_unpacked(SEXP from, const char *class) { if (class[2] != 'p') return from; char cl[] = "...Matrix"; cl[0] = class[0]; cl[1] = class[1]; switch (class[1]) { case 's': cl[2] = 'y'; break; case 'p': cl[2] = 'o'; break; case 'o': case 't': cl[2] = 'r'; break; default: break; } SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int n = INTEGER(dim)[0]; if ((Matrix_int_fast64_t) n * n > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); if (n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); char ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ if (cl[1] != 't') { SEXP factors = PROTECT(GET_SLOT(from, Matrix_factorsSym)); if (LENGTH(factors) > 0) SET_SLOT(to, Matrix_factorsSym, factors); UNPROTECT(1); /* factors */ if (cl[1] == 'o') { SEXP sd = PROTECT(GET_SLOT(from, Matrix_sdSym)); if (LENGTH(sd) > 0) SET_SLOT(to, Matrix_sdSym, sd); UNPROTECT(1); /* sd */ } } else { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); char di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N') SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), (R_xlen_t) n * n)); SET_SLOT(to, Matrix_xSym, x1); #define UNPACK(_PREFIX_, _CTYPE_, _PTR_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ Matrix_memset(px1, 0, (R_xlen_t) n * n, sizeof(_CTYPE_)); \ _PREFIX_ ## unpack1(px1, px0, n, ul, 'N'); \ } while (0) switch (cl[0]) { case 'n': case 'l': UNPACK(i, int, LOGICAL); break; case 'i': UNPACK(i, int, INTEGER); break; case 'c': case 'd': UNPACK(d, double, REAL); break; case 'z': UNPACK(z, Rcomplex, COMPLEX); break; default: break; } #undef UNPACK UNPROTECT(3); /* x1, x0, to */ return to; } /* as(, "unpackedMatrix") */ SEXP R_dense_as_unpacked(SEXP from) { static const char *valid[] = { "dpoMatrix", "dppMatrix", "corMatrix", "copMatrix", VALID_DENSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); return dense_as_unpacked(from, valid[ivalid]); } SEXP dense_as_packed(SEXP from, const char *class, char ul, char di) { if (class[2] == 'p') return from; int ge = class[1] == 'g'; char cl[] = "...Matrix"; cl[0] = class[0]; cl[1] = (ge) ? ((di == '\0') ? 's' : 't') : class[1]; cl[2] = 'p'; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) error(_("attempt to pack non-square matrix")); if (n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ if (ge) { if (ul != 'U') { SEXP uplo = PROTECT(mkString("L")); SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } if (cl[1] == 't' && di != 'N') { SEXP diag = PROTECT(mkString("U")); SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } } else { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ if (cl[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N') SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } else { SEXP factors = PROTECT(GET_SLOT(from, Matrix_factorsSym)); if (LENGTH(factors) > 0) SET_SLOT(to, Matrix_factorsSym, factors); UNPROTECT(1); /* factors */ if (cl[1] == 'o') { SEXP sd = PROTECT(GET_SLOT(from, Matrix_sdSym)); if (LENGTH(sd) > 0) SET_SLOT(to, Matrix_sdSym, sd); UNPROTECT(1); /* sd */ } } } SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), PACKED_LENGTH(n))); SET_SLOT(to, Matrix_xSym, x1); #define PACK(_PREFIX_, _CTYPE_, _PTR_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ _PREFIX_ ## pack2(px1, px0, n, ul, 'N'); \ } while (0) switch (cl[0]) { case 'n': case 'l': PACK(i, int, LOGICAL); break; case 'i': PACK(i, int, INTEGER); break; case 'c': case 'd': PACK(d, double, REAL); break; case 'z': PACK(z, Rcomplex, COMPLEX); break; default: break; } #undef PACK UNPROTECT(3); /* x1, x0, to */ return to; } /* as(, "packedMatrix") */ SEXP R_dense_as_packed(SEXP from, SEXP uplo, SEXP diag) { static const char *valid[] = { "dpoMatrix", "dppMatrix", "corMatrix", "copMatrix", VALID_DENSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); char ul = 'U', di = '\0'; if (valid[ivalid][1] == 'g') { if (TYPEOF(uplo) != STRSXP || LENGTH(uplo) < 1 || (uplo = STRING_ELT(uplo, 0)) == NA_STRING || ((ul = *CHAR(uplo)) != 'U' && ul != 'L')) error(_("'%s' must be \"%s\" or \"%s\""), "uplo", "U", "L"); if (diag != R_NilValue) { if (TYPEOF(diag) != STRSXP || LENGTH(diag) < 1 || (diag = STRING_ELT(diag, 0)) == NA_STRING || ((di = *CHAR(diag)) != 'N' && ul != 'U')) error(_("'%s' must be \"%s\" or \"%s\""), "diag", "N", "U"); } } return dense_as_packed(from, valid[ivalid], ul, di); } void trans(SEXP p0, SEXP i0, SEXP x0, SEXP p1, SEXP i1, SEXP x1, int m, int n) { int *pp0 = INTEGER(p0), *pp1 = INTEGER(p1), *pi0 = INTEGER(i0), *pi1 = INTEGER(i1), i, j, k, kend, nnz = pp0[n]; Matrix_memset(pp1, 0, (R_xlen_t) m + 1, sizeof(int)); ++pp0; ++pp1; for (k = 0; k < nnz; ++k) ++pp1[pi0[k]]; for (i = 0; i < m; ++i) pp1[i] += pp1[i - 1]; int *pp1_; Matrix_Calloc(pp1_, m, int); Matrix_memcpy(pp1_, pp1 - 1, m, sizeof(int)); #define TRANS_LOOP(_CTYPE_, _PTR_, _MASK_) \ do { \ _MASK_(_CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1)); \ for (j = 0, k = 0; j < n; ++j) { \ kend = pp0[j]; \ while (k < kend) { \ i = pi0[k]; \ pi1[pp1_[i]] = j; \ _MASK_(px1[pp1_[i]] = px0[k]); \ ++pp1_[i]; \ ++k; \ } \ } \ } while (0) if (!(x0 && x1) || TYPEOF(x0) != TYPEOF(x1)) TRANS_LOOP(int, LOGICAL, HIDE); else { switch (TYPEOF(x0)) { case LGLSXP: TRANS_LOOP(int, LOGICAL, SHOW); break; case INTSXP: TRANS_LOOP(int, INTEGER, SHOW); break; case REALSXP: TRANS_LOOP(double, REAL, SHOW); break; case CPLXSXP: TRANS_LOOP(Rcomplex, COMPLEX, SHOW); break; default: break; } } #undef TRANS_LOOP Matrix_Free(pp1_, m); return; } void tsort(SEXP i0, SEXP j0, SEXP x0, SEXP *p1, SEXP *i1, SEXP *x1, int m, int n) { R_xlen_t nnz0 = XLENGTH(i0), nnz1 = 0; if (nnz0 > INT_MAX) error(_("unable to aggregate %s with '%s' and '%s' slots of length exceeding %s"), "TsparseMatrix", "i", "j", "2^31-1"); /* FIXME: test for overflow and throw error only in that case */ PROTECT(*p1 = allocVector(INTSXP, (R_xlen_t) n + 1)); int *pi0 = INTEGER(i0), *pj0 = INTEGER(j0), *pp1 = INTEGER(*p1), *pi1, i, j, r = (m < n) ? n : m; R_xlen_t k, kstart, kend, kend_; *(pp1++) = 0; int *workA, *workB, *workC, *pj_; size_t lwork = (size_t) m + r + m + nnz0; Matrix_Calloc(workA, lwork, int); workB = workA + m; workC = workB + r; pj_ = workC + m; #define TSORT_LOOP(_CTYPE_, _PTR_, _MASK_, _INCREMENT_) \ do { \ _MASK_(_CTYPE_ *px0 = _PTR_(x0), *px1, *px_); \ _MASK_(Matrix_Calloc(px_, nnz0, _CTYPE_)); \ \ /* 1. Tabulate column indices in workA[i] */ \ \ for (k = 0; k < nnz0; ++k) \ ++workA[pi0[k]]; \ \ /* 2. Compute cumulative sum in workA[i], copying to workB[i] */ \ /* */ \ /* workA[i]: number of column indices listed for row i, */ \ /* incl. duplicates */ \ \ for (i = 1; i < m; ++i) \ workA[i] += (workB[i] = workA[i - 1]); \ \ /* 3. Group column indices and data by row in pj_[k], px_[k] */ \ /* */ \ /* workA[i]: number of column indices listed for row <= i, */ \ /* incl. duplicates */ \ /* workB[i]: number of column indices listed for row < i, */ \ /* incl. duplicates */ \ \ for (k = 0; k < nnz0; ++k) { \ pj_[workB[pi0[k]]] = pj0[k] ; \ _MASK_(px_[workB[pi0[k]]] = px0[k]); \ ++workB[pi0[k]]; \ } \ \ /* 4. Gather _unique_ column indices at the front of each group, */ \ /* aggregating data accordingly; record in workC[i] where */ \ /* the unique column indices stop and the duplicates begin */ \ /* */ \ /* workB[.]: unused */ \ /* pj_[k]: column indices grouped by row, */ \ /* incl. duplicates, unsorted */ \ /* px_[k]: corresponding data */ \ \ k = 0; \ for (j = 0; j < n; ++j) \ workB[j] = -1; \ for (i = 0; i < m; ++i) { \ kstart = kend_ = k; \ kend = workA[i]; \ while (k < kend) { \ if (workB[pj_[k]] < kstart) { \ /* Have not yet seen this column index */ \ workB[pj_[k]] = kend_; \ pj_[kend_] = pj_[k] ; \ _MASK_(px_[kend_] = px_[k]); \ ++kend_; \ } else { \ /* Have already seen this column index */ \ _MASK_(_INCREMENT_(px_[workB[pj_[k]]], px_[k])); \ } \ ++k; \ } \ workC[i] = kend_; \ nnz1 += kend_ - kstart; \ } \ \ /* 5. Tabulate _unique_ column indices in workB[j] */ \ /* */ \ /* workC[i]: pointer to first non-unique column index in row i */ \ /* pi_[k]: column indices grouped by row, */ \ /* with unique indices in front, */ \ /* i.e., in positions workA[i - 1] <= k < workC[i] */ \ /* px_[k]: corresponding data, "cumulated" appropriately */ \ \ k = 0; \ Matrix_memset(workB, 0, n, sizeof(int)); \ for (i = 0; i < m; ++i) { \ kend_ = workC[i]; \ while (k < kend_) { \ ++workB[pj_[k]]; \ ++k; \ } \ k = workA[i]; \ } \ \ /* 6. Compute cumulative sum in pp1[j], copying to workB[j] */ \ /* */ \ /* workB[j]: number of nonzero elements in column j */ \ \ for (j = 0; j < n; ++j) { \ pp1[j] = pp1[j - 1] + workB[j]; \ workB[j] = pp1[j - 1]; \ } \ \ PROTECT(*i1 = allocVector( INTSXP, nnz1)) ; \ _MASK_(PROTECT(*x1 = allocVector(TYPEOF(x0), nnz1))); \ pi1 = INTEGER(*i1) ; \ _MASK_(px1 = _PTR_(*x1)); \ \ /* 7. Pop unique (i,j) pairs from the unsorted stacks 0 <= i < m */ \ /* onto new stacks 0 <= j < n, which will be sorted */ \ /* */ \ /* workB[j]: number of nonzero elements in columns < j */ \ /* pp1[j]: number of nonzero elements in columns <= j */ \ \ k = 0; \ for (i = 0; i < m; ++i) { \ kend_ = workC[i]; \ while (k < kend_) { \ pi1[workB[pj_[k]]] = i; \ _MASK_(px1[workB[pj_[k]]] = px_[k]); \ ++workB[pj_[k]]; \ ++k; \ } \ k = workA[i]; \ } \ \ _MASK_(Matrix_Free(px_, nnz0)); \ _MASK_(UNPROTECT(1)); /* *px1 */ \ UNPROTECT(1) ; /* *pi1 */ \ } while (0) if (!x0) TSORT_LOOP(int, LOGICAL, HIDE, INCREMENT_PATTERN); else { switch (TYPEOF(x0)) { case LGLSXP: TSORT_LOOP(int, LOGICAL, SHOW, INCREMENT_LOGICAL); break; case INTSXP: TSORT_LOOP(int, INTEGER, SHOW, INCREMENT_INTEGER); break; case REALSXP: TSORT_LOOP(double, REAL, SHOW, INCREMENT_REAL); break; case CPLXSXP: TSORT_LOOP(Rcomplex, COMPLEX, SHOW, INCREMENT_COMPLEX); break; default: break; } } #undef TSORT_LOOP Matrix_Free(workA, lwork); UNPROTECT(1); /* *p1 */ return; } void taggr(SEXP i0, SEXP j0, SEXP x0, SEXP *i1, SEXP *j1, SEXP *x1, int m, int n) { R_xlen_t nnz0 = XLENGTH(i0), nnz1 = 0; if (nnz0 > INT_MAX) error(_("unable to aggregate %s with '%s' and '%s' slots of length exceeding %s"), "TsparseMatrix", "i", "j", "2^31-1"); /* FIXME: test for overflow and throw error only in that case */ int *pi0 = INTEGER(i0), *pj0 = INTEGER(j0), *pi1, *pj1, i, j, r = (m < n) ? n : m; R_xlen_t k, kstart, kend, kend_; int *workA, *workB, *workC, *pj_; size_t lwork = (size_t) m + r + m + nnz0; Matrix_Calloc(workA, lwork, int); workB = workA + m; workC = workB + r; pj_ = workC + m; #define TAGGR_LOOP(_CTYPE_, _PTR_, _MASK_, _INCREMENT_) \ do { \ _MASK_(_CTYPE_ *px0 = _PTR_(x0), *px1, *px_); \ _MASK_(Matrix_Calloc(px_, nnz0, _CTYPE_)); \ \ /* 1. Tabulate column indices in workA[i] */ \ \ for (k = 0; k < nnz0; ++k) \ ++workA[pi0[k]]; \ \ /* 2. Compute cumulative sum in workA[i], copying to workB[i] */ \ /* */ \ /* workA[i]: number of column indices listed for row i, */ \ /* incl. duplicates */ \ \ for (i = 1; i < m; ++i) \ workA[i] += (workB[i] = workA[i - 1]); \ \ /* 3. Group column indices and data by row in pj_[k], px_[k] */ \ /* */ \ /* workA[i]: number of column indices listed for row <= i, */ \ /* incl. duplicates */ \ /* workB[i]: number of column indices listed for row < i, */ \ /* incl. duplicates */ \ \ for (k = 0; k < nnz0; ++k) { \ pj_[workB[pi0[k]]] = pj0[k] ; \ _MASK_(px_[workB[pi0[k]]] = px0[k]); \ ++workB[pi0[k]]; \ } \ \ /* 4. Gather _unique_ column indices at the front of each group, */ \ /* aggregating data accordingly; record in workC[i] where */ \ /* the unique column indices stop and the duplicates begin */ \ /* */ \ /* workB[.]: unused */ \ /* pj_[k]: column indices grouped by row, */ \ /* incl. duplicates, unsorted */ \ /* px_[k]: corresponding data */ \ \ k = 0; \ for (j = 0; j < n; ++j) \ workB[j] = -1; \ for (i = 0; i < m; ++i) { \ kstart = kend_ = k; \ kend = workA[i]; \ while (k < kend) { \ if (workB[pj_[k]] < kstart) { \ /* Have not yet seen this column index */ \ workB[pj_[k]] = kend_; \ pj_[kend_] = pj_[k] ; \ _MASK_(px_[kend_] = px_[k]); \ ++kend_; \ } else { \ /* Have already seen this column index */ \ _MASK_(_INCREMENT_(px_[workB[pj_[k]]], px_[k])); \ } \ ++k; \ } \ workC[i] = kend_; \ nnz1 += kend_ - kstart; \ } \ if (nnz1 != nnz0) { \ PROTECT(*i1 = allocVector( INTSXP, nnz1)) ; \ PROTECT(*j1 = allocVector( INTSXP, nnz1)) ; \ _MASK_(PROTECT(*x1 = allocVector(TYPEOF(x0), nnz1))); \ pi1 = INTEGER(*i1) ; \ pj1 = INTEGER(*j1) ; \ _MASK_(px1 = _PTR_(*x1)); \ \ k = 0; \ for (i = 0; i < m; ++i) { \ kend_ = workC[i]; \ while (k < kend_) { \ *(pi1++) = i ; \ *(pj1++) = pj_[k] ; \ _MASK_(*(px1++) = px_[k]); \ ++k; \ } \ k = workA[i]; \ } \ \ _MASK_(UNPROTECT(1)); /* *px1 */ \ UNPROTECT(2) ; /* *pj1, *px1 */ \ } \ _MASK_(Matrix_Free(px_, nnz0)); \ } while (0) if (!x0) TAGGR_LOOP(int, LOGICAL, HIDE, ); else { switch (TYPEOF(x0)) { case LGLSXP: TAGGR_LOOP(int, LOGICAL, SHOW, INCREMENT_LOGICAL); break; case INTSXP: TAGGR_LOOP(int, INTEGER, SHOW, INCREMENT_INTEGER); break; case REALSXP: TAGGR_LOOP(double, REAL, SHOW, INCREMENT_REAL); break; case CPLXSXP: TAGGR_LOOP(Rcomplex, COMPLEX, SHOW, INCREMENT_COMPLEX); break; default: break; } } #undef TAGGR_LOOP Matrix_Free(workA, lwork); return; } SEXP sparse_as_Csparse(SEXP from, const char *class) { if (class[2] == 'C') return from; char cl[] = "..CMatrix"; cl[0] = class[0]; cl[1] = class[1]; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; if (m != n || n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); char ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); char di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N') SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } else { SEXP factors = PROTECT(GET_SLOT(from, Matrix_factorsSym)); if (LENGTH(factors) > 0) SET_SLOT(to, Matrix_factorsSym, factors); UNPROTECT(1); /* factors */ } if (class[2] == 'R') { SEXP p0 = PROTECT(GET_SLOT(from, Matrix_pSym)), j0 = PROTECT(GET_SLOT(from, Matrix_jSym)), p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) n + 1)), i1 = PROTECT(allocVector(INTSXP, INTEGER(p0)[m])); SET_SLOT(to, Matrix_pSym, p1); SET_SLOT(to, Matrix_iSym, i1); if (class[0] == 'n') trans(p0, j0, NULL, p1, i1, NULL, n, m); else { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), INTEGER(p0)[m])); SET_SLOT(to, Matrix_xSym, x1); trans(p0, j0, x0, p1, i1, x1, n, m); UNPROTECT(2); /* x1, x0 */ } UNPROTECT(4); /* i1, p1, j0, p0 */ } else { SEXP i0 = PROTECT(GET_SLOT(from, Matrix_iSym)), j0 = PROTECT(GET_SLOT(from, Matrix_jSym)), p1 = NULL, i1 = NULL; if (class[0] == 'n') { tsort(i0, j0, NULL, &p1, &i1, NULL, m, n); PROTECT(p1); PROTECT(i1); SET_SLOT(to, Matrix_pSym, p1); SET_SLOT(to, Matrix_iSym, i1); UNPROTECT(2); /* i1, p1 */ } else { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = NULL; tsort(i0, j0, x0, &p1, &i1, &x1, m, n); PROTECT(p1); PROTECT(i1); PROTECT(x1); SET_SLOT(to, Matrix_pSym, p1); SET_SLOT(to, Matrix_iSym, i1); SET_SLOT(to, Matrix_xSym, x1); UNPROTECT(4); /* x1, i1, p1, x0 */ } UNPROTECT(2); /* j0, i0 */ } UNPROTECT(1); /* to */ return to; } /* as(<[CRT]sparseMatrix>, "CsparseMatrix") */ SEXP R_sparse_as_Csparse(SEXP from) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); return sparse_as_Csparse(from, valid[ivalid]); } SEXP sparse_as_Rsparse(SEXP from, const char *class) { if (class[2] == 'R') return from; char cl[] = "..RMatrix"; cl[0] = class[0]; cl[1] = class[1]; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; if (m != n || n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); char ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); char di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N') SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } else { SEXP factors = PROTECT(GET_SLOT(from, Matrix_factorsSym)); if (LENGTH(factors) > 0) SET_SLOT(to, Matrix_factorsSym, factors); UNPROTECT(1); /* factors */ } if (class[2] == 'C') { SEXP p0 = PROTECT(GET_SLOT(from, Matrix_pSym)), i0 = PROTECT(GET_SLOT(from, Matrix_iSym)), p1 = PROTECT(allocVector(INTSXP, (R_xlen_t) m + 1)), j1 = PROTECT(allocVector(INTSXP, INTEGER(p0)[n])); SET_SLOT(to, Matrix_pSym, p1); SET_SLOT(to, Matrix_jSym, j1); if (class[0] == 'n') trans(p0, i0, NULL, p1, j1, NULL, m, n); else { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), INTEGER(p0)[n])); SET_SLOT(to, Matrix_xSym, x1); trans(p0, i0, x0, p1, j1, x1, m, n); UNPROTECT(2); /* x1, x0 */ } UNPROTECT(4); /* j1, p1, i0, p0 */ } else { SEXP i0 = PROTECT(GET_SLOT(from, Matrix_iSym)), j0 = PROTECT(GET_SLOT(from, Matrix_jSym)), p1 = NULL, j1 = NULL; if (class[0] == 'n') { tsort(j0, i0, NULL, &p1, &j1, NULL, n, m); PROTECT(p1); PROTECT(j1); SET_SLOT(to, Matrix_pSym, p1); SET_SLOT(to, Matrix_jSym, j1); UNPROTECT(2); /* j1, p1 */ } else { SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = NULL; tsort(j0, i0, x0, &p1, &j1, &x1, n, m); PROTECT(p1); PROTECT(j1); PROTECT(x1); SET_SLOT(to, Matrix_pSym, p1); SET_SLOT(to, Matrix_jSym, j1); SET_SLOT(to, Matrix_xSym, x1); UNPROTECT(4); /* x1, j1, p1, x0 */ } UNPROTECT(2); /* j0, i0 */ } UNPROTECT(1); /* to */ return to; } /* as(<[CRT]sparseMatrix>, "RsparseMatrix") */ SEXP R_sparse_as_Rsparse(SEXP from) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); return sparse_as_Rsparse(from, valid[ivalid]); } SEXP sparse_as_Tsparse(SEXP from, const char *class) { if (class[2] == 'T') return from; char cl[] = "..TMatrix"; cl[0] = class[0]; cl[1] = class[1]; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; if (m != n || n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); char ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); char di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N') SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } else { SEXP factors = PROTECT(GET_SLOT(from, Matrix_factorsSym)); if (LENGTH(factors) > 0) SET_SLOT(to, Matrix_factorsSym, factors); UNPROTECT(1); /* factors */ } SEXP iSym = (class[2] == 'C') ? Matrix_iSym : Matrix_jSym, jSym = (class[2] == 'C') ? Matrix_jSym : Matrix_iSym, p = PROTECT(GET_SLOT(from, Matrix_pSym)), i = PROTECT(GET_SLOT(from, iSym)); int *pp = INTEGER(p), *pi, r = (class[2] == 'C') ? n : m, nnz = pp[r]; if (XLENGTH(i) == nnz) { SET_SLOT(to, iSym, i); UNPROTECT(1); /* i */ } else { SEXP i_ = PROTECT(allocVector(INTSXP, nnz)); Matrix_memcpy(INTEGER(i_), INTEGER(i), nnz, sizeof(int)); SET_SLOT(to, iSym, i_); UNPROTECT(2); /* i_, i */ } PROTECT(i = allocVector(INTSXP, nnz)); SET_SLOT(to, jSym, i); pi = INTEGER(i); ++pp; int j, k, kend; for (j = 0, k = 0; j < r; ++j) { kend = pp[j]; while (k < kend) pi[k++] = j; } UNPROTECT(2); /* i, p */ if (class[0] != 'n') { SEXP x = PROTECT(GET_SLOT(from, Matrix_xSym)); if (XLENGTH(x) == nnz) SET_SLOT(to, Matrix_xSym, x); else { SEXP x_ = PROTECT(allocVector(TYPEOF(x), nnz)); SET_SLOT(to, Matrix_xSym, x_); switch (class[0]) { case 'l': Matrix_memcpy(LOGICAL(x_), LOGICAL(x), nnz, sizeof(int)); break; case 'i': Matrix_memcpy(INTEGER(x_), INTEGER(x), nnz, sizeof(int)); break; case 'd': Matrix_memcpy(REAL(x_), REAL(x), nnz, sizeof(double)); break; case 'z': Matrix_memcpy(COMPLEX(x_), COMPLEX(x), nnz, sizeof(Rcomplex)); break; default: break; } UNPROTECT(1); /* x_ */ } UNPROTECT(1); /* x */ } UNPROTECT(1); /* to */ return to; } /* as(<[CRT]sparseMatrix>, "TsparseMatrix") */ SEXP R_sparse_as_Tsparse(SEXP from) { static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); return sparse_as_Tsparse(from, valid[ivalid]); } /* as(, "vector") */ SEXP R_Matrix_as_vector(SEXP from) { static const char *valid[] = { VALID_NONVIRTUAL_MATRIX, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *cl = valid[ivalid + VALID_NONVIRTUAL_SHIFT(ivalid, 1)]; SEXP to = NULL; PROTECT_INDEX pid; PROTECT_WITH_INDEX(from, &pid); switch (cl[2]) { case 'e': to = GET_SLOT(from, Matrix_xSym); if (cl[0] == 'n') { R_xlen_t len = XLENGTH(to); int *px = LOGICAL(to); while (len--) if (*(px++) == NA_LOGICAL) { PROTECT(to); to = duplicate(to); UNPROTECT(1); break; } } break; case 'y': case 'r': case 'p': REPROTECT(from = dense_as_general(from, cl, 1), pid); to = GET_SLOT(from, Matrix_xSym); break; case 'C': case 'R': case 'T': REPROTECT(from = sparse_as_dense(from, cl, 0), pid); REPROTECT(from = dense_as_general(from, cl, 0), pid); to = GET_SLOT(from, Matrix_xSym); break; case 'i': REPROTECT(from = diagonal_as_dense(from, cl, '.', 'g', 0, '\0'), pid); to = GET_SLOT(from, Matrix_xSym); break; case 'd': REPROTECT(from = index_as_dense(from, cl, 'n'), pid); to = GET_SLOT(from, Matrix_xSym); break; default: break; } switch (cl[2]) { case 'e': case 'y': case 'r': case 'p': case 'i': if (cl[0] == 'n') { PROTECT(to); naToOne(to); UNPROTECT(1); } break; default: break; } UNPROTECT(1); /* from */ return to; } /* as(, "matrix") */ SEXP R_Matrix_as_matrix(SEXP from) { static const char *valid[] = { VALID_NONVIRTUAL_MATRIX, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *cl = valid[ivalid + VALID_NONVIRTUAL_SHIFT(ivalid, 1)]; SEXP to = NULL; PROTECT_INDEX pid; PROTECT_WITH_INDEX(from, &pid); switch (cl[2]) { case 'e': PROTECT(to = GET_SLOT(from, Matrix_xSym)); to = duplicate(to); UNPROTECT(1); break; case 'y': case 'r': case 'p': REPROTECT(from = dense_as_general(from, cl, 1), pid); to = GET_SLOT(from, Matrix_xSym); break; case 'C': case 'R': case 'T': REPROTECT(from = sparse_as_dense(from, cl, 0), pid); REPROTECT(from = dense_as_general(from, cl, 0), pid); to = GET_SLOT(from, Matrix_xSym); break; case 'i': REPROTECT(from = diagonal_as_dense(from, cl, '.', 'g', 0, '\0'), pid); to = GET_SLOT(from, Matrix_xSym); break; case 'd': REPROTECT(from = index_as_dense(from, cl, 'n'), pid); to = GET_SLOT(from, Matrix_xSym); break; default: break; } PROTECT(to); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); setAttrib(to, R_DimSymbol, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); if (!DimNames_is_trivial(dimnames)) setAttrib(to, R_DimNamesSymbol, dimnames); UNPROTECT(1); /* dimnames */ switch (cl[2]) { case 'e': case 'y': case 'r': case 'p': case 'i': if (cl[0] == 'n') naToOne(to); break; default: break; } UNPROTECT(2); /* to, from */ return to; } /* as(, "unpackedMatrix") */ SEXP R_Matrix_as_unpacked(SEXP from) { static const char *valid[] = { VALID_NONVIRTUAL_MATRIX, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *cl = valid[ivalid + VALID_NONVIRTUAL_SHIFT(ivalid, 1)]; switch (cl[2]) { case 'e': case 'y': case 'r': return from; case 'p': return dense_as_unpacked(from, valid[ivalid]); case 'C': case 'R': case 'T': return sparse_as_dense(from, cl, 0); case 'i': return diagonal_as_dense(from, cl, '.', 't', 0, 'U'); case 'd': return index_as_dense(from, cl, 'n'); default: return R_NilValue; } } /* as(, "packedMatrix") */ SEXP R_Matrix_as_packed(SEXP from) { static const char *valid[] = { VALID_NONVIRTUAL_MATRIX, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *cl = valid[ivalid + VALID_NONVIRTUAL_SHIFT(ivalid, 1)]; if (cl[1] == 'g' || cl[2] == 'd') error(_("attempt to pack a %s"), "generalMatrix"); switch (cl[2]) { case 'y': case 'r': return dense_as_packed(from, valid[ivalid], '\0', '\0'); case 'p': return from; case 'C': case 'R': case 'T': return sparse_as_dense(from, cl, 1); case 'i': return diagonal_as_dense(from, cl, '.', 't', 1, 'U'); default: return R_NilValue; } } /* as(, "CsparseMatrix") */ SEXP R_Matrix_as_Csparse(SEXP from) { static const char *valid[] = { VALID_NONVIRTUAL_MATRIX, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *cl = valid[ivalid + VALID_NONVIRTUAL_SHIFT(ivalid, 1)]; switch (cl[2]) { case 'e': case 'y': case 'r': case 'p': return dense_as_sparse(from, cl, 'C'); case 'C': case 'R': case 'T': return sparse_as_Csparse(from, cl); case 'i': return diagonal_as_sparse(from, cl, '.', 't', 'C', 'U'); case 'd': return index_as_sparse(from, cl, 'n', 'C'); default: return R_NilValue; } } /* as(, "RsparseMatrix") */ SEXP R_Matrix_as_Rsparse(SEXP from) { static const char *valid[] = { VALID_NONVIRTUAL_MATRIX, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *cl = valid[ivalid + VALID_NONVIRTUAL_SHIFT(ivalid, 1)]; switch (cl[2]) { case 'e': case 'y': case 'r': case 'p': return dense_as_sparse(from, cl, 'R'); case 'C': case 'R': case 'T': return sparse_as_Rsparse(from, cl); case 'i': return diagonal_as_sparse(from, cl, '.', 't', 'R', 'U'); case 'd': return index_as_sparse(from, cl, 'n', 'R'); default: return R_NilValue; } } /* as(, "TsparseMatrix") */ SEXP R_Matrix_as_Tsparse(SEXP from) { static const char *valid[] = { VALID_NONVIRTUAL_MATRIX, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *cl = valid[ivalid + VALID_NONVIRTUAL_SHIFT(ivalid, 1)]; switch (cl[2]) { case 'e': case 'y': case 'r': case 'p': return dense_as_sparse(from, cl, 'T'); case 'C': case 'R': case 'T': return sparse_as_Tsparse(from, cl); case 'i': return diagonal_as_sparse(from, cl, '.', 't', 'T', 'U'); case 'd': return index_as_sparse(from, cl, 'n', 'T'); default: return R_NilValue; } } /* as(, "[nldiz]Matrix") */ SEXP R_Matrix_as_kind(SEXP from, SEXP kind, SEXP sparse) { static const char *valid[] = { VALID_NONVIRTUAL_MATRIX, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *cl = valid[ivalid + VALID_NONVIRTUAL_SHIFT(ivalid, 1)]; char kind_; if (TYPEOF(kind) != STRSXP || LENGTH(kind) < 1 || (kind = STRING_ELT(kind, 0)) == NA_STRING || (kind_ = CHAR(kind)[0]) == '\0') error(_("invalid '%s' to '%s'"), "kind", __func__); if (TYPEOF(sparse) != LGLSXP || LENGTH(sparse) < 1) error(_("'%s' must be %s or %s or %s"), "sparse", "TRUE", "FALSE", "NA"); int sparse_ = LOGICAL(sparse)[0]; switch (cl[2]) { case 'e': case 'y': case 'r': case 'p': if (sparse_ == NA_LOGICAL || !sparse_) from = dense_as_kind(from, cl, kind_, 0); else { from = dense_as_sparse(from, cl, 'C'); PROTECT(from); char cl_[] = "..CMatrix"; cl_[0] = cl[0]; cl_[1] = cl[1]; from = sparse_as_kind(from, cl_, kind_); UNPROTECT(1); } return from; case 'C': case 'R': case 'T': from = sparse_as_kind(from, cl, kind_); if (sparse_ != NA_LOGICAL && !sparse_) { PROTECT(from); char cl_[] = "...Matrix"; cl_[0] = (kind_ == '.') ? cl[0] : ((kind_ == ',') ? ((cl[0] == 'z') ? 'z' : 'd') : kind_); cl_[1] = cl[1]; cl_[2] = cl[2]; from = sparse_as_dense(from, cl_, 0); UNPROTECT(1); } return from; case 'i': if (sparse_ == NA_LOGICAL) from = diagonal_as_kind(from, cl, kind_); else if (sparse_) from = diagonal_as_sparse(from, cl, kind_, 't', 'C', 'U'); else from = diagonal_as_dense(from, cl, kind_, 't', 0, 'U'); return from; case 'd': if (sparse_ == NA_LOGICAL || sparse_) from = index_as_sparse(from, cl, kind_, '.'); else from = index_as_dense(from, cl, kind_); return from; default: return R_NilValue; } } /* as(as(, "[nlidz]Matrix"), "generalMatrix") */ SEXP R_Matrix_as_general(SEXP from, SEXP kind) { static const char *valid[] = { VALID_NONVIRTUAL_MATRIX, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *cl = valid[ivalid + VALID_NONVIRTUAL_SHIFT(ivalid, 1)]; char kind_; if (TYPEOF(kind) != STRSXP || LENGTH(kind) < 1 || (kind = STRING_ELT(kind, 0)) == NA_STRING || (kind_ = CHAR(kind)[0]) == '\0') error(_("invalid '%s' to '%s'"), "kind", __func__); switch (cl[2]) { case 'e': case 'y': case 'r': case 'p': { char cl_[] = "...Matrix"; cl_[0] = (kind_ == '.') ? cl[0] : ((kind_ == ',') ? ((cl[0] == 'z') ? 'z' : 'd') : kind_); cl_[1] = cl[1]; cl_[2] = cl[2]; from = dense_as_kind(from, cl, cl_[0], 1); PROTECT(from); from = dense_as_general(from, cl_, cl[0] == cl_[0]); UNPROTECT(1); return from; } case 'C': case 'R': case 'T': { char cl_[] = "...Matrix"; cl_[0] = (kind_ == '.') ? cl[0] : ((kind_ == ',') ? ((cl[0] == 'z') ? 'z' : 'd') : kind_); cl_[1] = cl[1]; cl_[2] = cl[2]; from = sparse_as_kind(from, cl, cl_[0]); PROTECT(from); from = sparse_as_general(from, cl_); UNPROTECT(1); return from; } case 'i': return diagonal_as_sparse(from, cl, kind_, 'g', 'C', '\0'); case 'd': /* indMatrix extends generalMatrix, but we typically do want this: */ return index_as_sparse(from, cl, kind_, '.'); default: return R_NilValue; } } �������������������������������������������������������Matrix/src/Msymbols.h�������������������������������������������������������������������������������0000644�0001751�0000144�00000000521�14574651213�014307� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������SEXP Matrix_DimNamesSym, Matrix_DimSym, Matrix_LSym, Matrix_QSym, Matrix_RSym, Matrix_TSym, Matrix_USym, Matrix_VSym, Matrix_betaSym, Matrix_diagSym, Matrix_factorsSym, Matrix_iSym, Matrix_jSym, Matrix_lengthSym, Matrix_marginSym, Matrix_pSym, Matrix_permSym, Matrix_qSym, Matrix_sdSym, Matrix_uploSym, Matrix_xSym; �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/factor.h���������������������������������������������������������������������������������0000644�0001751�0000144�00000001136�14575137654�013774� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_FACTOR_H #define MATRIX_FACTOR_H #include SEXP dgeMatrix_trf(SEXP, SEXP); SEXP dsyMatrix_trf(SEXP, SEXP); SEXP dspMatrix_trf(SEXP, SEXP); SEXP dpoMatrix_trf(SEXP, SEXP, SEXP, SEXP); SEXP dppMatrix_trf(SEXP, SEXP); SEXP dgeMatrix_sch(SEXP, SEXP, SEXP); SEXP dgCMatrix_trf(SEXP, SEXP, SEXP, SEXP); SEXP dgCMatrix_orf(SEXP, SEXP, SEXP); SEXP dpCMatrix_trf(SEXP, SEXP, SEXP, SEXP, SEXP); SEXP BunchKaufman_expand(SEXP, SEXP); SEXP CHMfactor_diag_get(SEXP, SEXP); SEXP CHMfactor_update(SEXP, SEXP, SEXP); SEXP CHMfactor_updown(SEXP, SEXP, SEXP); #endif /* MATRIX_FACTOR_H */ ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/dense.c����������������������������������������������������������������������������������0000644�0001751�0000144�00000164514�14574054152�013607� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Mdefines.h" #include "idz.h" #include "dense.h" SEXP dense_band(SEXP from, const char *class, int a, int b) { /* defined in ./coerce.c : */ SEXP dense_as_general(SEXP, const char *, int); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; UNPROTECT(1); /* dim */ /* Need tri[ul](<0-by-0>) and tri[ul](<1-by-1>) to be triangularMatrix */ if (a <= 1 - m && b >= n - 1 && (class[1] == 't' || m != n || m > 1 || n > 1)) return from; int ge = 0, sy = 0, tr = 0; ge = m != n || !((tr = a >= 0 || b <= 0 || class[1] == 't') || (sy = a == -b && class[1] == 's')); #define BAND_CASES(_DO_) \ do { \ switch (class[0]) { \ case 'n': \ case 'l': \ _DO_(i, int, LOGICAL); \ break; \ case 'i': \ _DO_(i, int, INTEGER); \ break; \ case 'd': \ _DO_(d, double, REAL); \ break; \ case 'z': \ _DO_(z, Rcomplex, COMPLEX); \ break; \ default: \ break; \ } \ } while (0) #define BAND2(_PREFIX_, _CTYPE_, _PTR_) \ _PREFIX_ ## band2(_PTR_(x1), m, n, a, b, di) #define BAND1(_PREFIX_, _CTYPE_, _PTR_) \ _PREFIX_ ## band1(_PTR_(x1), n, a, b, ul1, di) #define DCPY2(_PREFIX_, _CTYPE_, _PTR_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ Matrix_memset(px1, 0, XLENGTH(x1), sizeof(_CTYPE_)); \ if (a <= 0 && b >= 0) \ _PREFIX_ ## dcpy2(px1, px0, n, XLENGTH(x1), 'U', di); \ } while (0) #define DCPY1(_PREFIX_, _CTYPE_, _PTR_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ Matrix_memset(px1, 0, XLENGTH(x1), sizeof(_CTYPE_)); \ if (a <= 0 && b >= 0) \ _PREFIX_ ## dcpy1(px1, px0, n, XLENGTH(x1), ul1, ul0, di); \ } while (0) char ul0 = 'U', ul1 = 'U', di = 'N'; if (class[1] != 'g') { if (ge) { PROTECT(from = dense_as_general(from, class, 1)); SEXP x1 = PROTECT(GET_SLOT(from, Matrix_xSym)); BAND_CASES(BAND2); UNPROTECT(2); /* x1, from */ return from; } SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); ul0 = *CHAR(STRING_ELT(uplo, 0)); UNPROTECT(1); /* uplo */ if (class[1] == 't') { /* Be fast if band contains entire triangle */ if ((ul0 == 'U') ? (a <= 0 && b >= n - 1) : (b >= 0 && a <= 1 - m)) return from; else if (a <= 0 && b >= 0) { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); di = *CHAR(STRING_ELT(diag, 0)); UNPROTECT(1); /* diag */ } } } char cl[] = "...Matrix"; cl[0] = class[0]; cl[1] = (ge) ? 'g' : ((sy) ? 's' : 't') ; cl[2] = (ge) ? 'e' : ((class[2] != 'p') ? ((sy) ? 'y' : 'r') : 'p'); SEXP to = PROTECT(newObject(cl)); dim = GET_SLOT(to, Matrix_DimSym); pdim = INTEGER(dim); pdim[0] = m; pdim[1] = n; SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); if (class[1] != 's' || sy) SET_SLOT(to, Matrix_DimNamesSym, dimnames); else set_symmetrized_DimNames(to, dimnames, -1); UNPROTECT(1); /* dimnames */ SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1; if (ge) { PROTECT(x1 = duplicate(x0)); if (ATTRIB(x1) != R_NilValue) { SET_ATTRIB(x1, R_NilValue); if (OBJECT(x1)) SET_OBJECT(x1, 0); } SET_SLOT(to, Matrix_xSym, x1); BAND_CASES(BAND2); UNPROTECT(3); /* x1, x0, to */ return to; } /* Returning .(sy|sp|tr|tp)Matrix ... */ ul1 = (tr && class[1] != 't') ? ((a >= 0) ? 'U' : 'L') : ul0; if (ul1 != 'U') { SEXP uplo = PROTECT(mkString("L")); SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } if (di != 'N') { SEXP diag = PROTECT(mkString("U")); SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } if (tr && class[1] == 't') { if ((ul0 == 'U') ? (b <= 0) : (a >= 0)) { /* Result is either a diagonal matrix or a zero matrix : */ PROTECT(x1 = allocVector(TYPEOF(x0), XLENGTH(x0))); if (class[2] != 'p') BAND_CASES(DCPY2); else BAND_CASES(DCPY1); } else { PROTECT(x1 = duplicate(x0)); if (class[2] != 'p') BAND_CASES(BAND2); else BAND_CASES(BAND1); } } else { if (sy || (tr && (class[1] == 'g' || ul0 == ul1 || n <= 1))) { PROTECT(x1 = duplicate(x0)); if (ATTRIB(x1) != R_NilValue) { SET_ATTRIB(x1, R_NilValue); if (OBJECT(x1)) SET_OBJECT(x1, 0); } } else { /* Band is "opposite" the stored triangle : */ PROTECT(from = dense_transpose(from, class)); x1 = GET_SLOT(from, Matrix_xSym); UNPROTECT(1); PROTECT(x1); } if (class[2] != 'p') BAND_CASES(BAND2); else BAND_CASES(BAND1); } SET_SLOT(to, Matrix_xSym, x1); #undef BAND_CASES #undef BAND2 #undef BAND1 #undef DCPY2 #undef DCPY1 UNPROTECT(3); /* x1, x0, to */ return to; } /* band(, k1, k2), tri[ul](, k) */ /* NB: argument validation more or less copied by R_sparse_band() */ SEXP R_dense_band(SEXP from, SEXP k1, SEXP k2) { if (!IS_S4_OBJECT(from)) { /* defined in ./coerce.c : */ SEXP matrix_as_dense(SEXP, const char *, char, char, int, int); from = matrix_as_dense(from, ".ge", '\0', '\0', 0, 0); } PROTECT(from); static const char *valid[] = { VALID_DENSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; UNPROTECT(1); int a, b; if (k1 == R_NilValue) // tril() a = -m ; // was (m > 0) ? 1 - m : 0; else if ((a = asInteger(k1)) == NA_INTEGER || a < -m || a > n) error(_("'%s' (%d) must be an integer from %s (%d) to %s (%d)"), "k1", a, "-Dim[1]", -m, "Dim[2]", n); if (k2 == R_NilValue) // triu() b = n; // was (n > 0) ? n - 1 : 0; else if ((b = asInteger(k2)) == NA_INTEGER || b < -m || b > n) error(_("'%s' (%d) must be an integer from %s (%d) to %s (%d)"), "k2", b, "-Dim[1]", -m, "Dim[2]", n); else if (b < a) error(_("'%s' (%d) must be less than or equal to '%s' (%d)"), "k1", a, "k2", b); from = dense_band(from, valid[ivalid], a, b); UNPROTECT(1); return from; } SEXP dense_diag_get(SEXP obj, const char *class, int names) { SEXP dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1], r = (m < n) ? m : n, j; UNPROTECT(1); /* dim */ char ul = 'U', di = 'N'; if (class[1] != 'g') { if (class[2] == 'p') { SEXP uplo = PROTECT(GET_SLOT(obj, Matrix_uploSym)); ul = *CHAR(STRING_ELT(uplo, 0)); UNPROTECT(1); /* uplo */ } if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(obj, Matrix_diagSym)); di = *CHAR(STRING_ELT(diag, 0)); UNPROTECT(1); /* diag */ } } SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), res = PROTECT(allocVector(TYPEOF(x), r)); #define DG_LOOP(_CTYPE_, _PTR_, _ONE_) \ do { \ _CTYPE_ *pres = _PTR_(res), *px = _PTR_(x); \ if (di == 'U') \ for (j = 0; j < r; ++j) \ *(pres++) = _ONE_; \ else if (class[2] != 'p') { \ R_xlen_t m1a = (R_xlen_t) m + 1; \ for (j = 0; j < r; ++j, px += m1a) \ *(pres++) = *px; \ } \ else if (ul == 'U') \ for (j = 0; j < n; px += (++j) + 1) \ *(pres++) = *px; \ else \ for (j = 0; j < n; px += n - (j++)) \ *(pres++) = *px; \ } while (0) switch (class[0]) { case 'n': case 'l': DG_LOOP(int, LOGICAL, 1); break; case 'i': DG_LOOP(int, INTEGER, 1); break; case 'd': DG_LOOP(double, REAL, 1.0); break; case 'z': DG_LOOP(Rcomplex, COMPLEX, Matrix_zone); break; default: break; } if (names) { /* NB: The logic here must be adjusted once the validity method for 'symmetricMatrix' enforces symmetric 'Dimnames' */ SEXP dn = PROTECT(GET_SLOT(obj, Matrix_DimNamesSym)), rn = VECTOR_ELT(dn, 0), cn = VECTOR_ELT(dn, 1); if (cn == R_NilValue) { if (class[1] == 's' && rn != R_NilValue) setAttrib(res, R_NamesSymbol, rn); } else { if (class[1] == 's') setAttrib(res, R_NamesSymbol, cn); else if (rn != R_NilValue && (rn == cn || equal_character_vectors(rn, cn, r))) setAttrib(res, R_NamesSymbol, (r == m) ? rn : cn); } UNPROTECT(1); /* dn */ } #undef DG_LOOP UNPROTECT(2); /* x, res */ return res; } SEXP R_dense_diag_get(SEXP obj, SEXP names) { static const char *valid[] = { VALID_DENSE, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) ERROR_INVALID_CLASS(obj, __func__); int names_; if (TYPEOF(names) != LGLSXP || LENGTH(names) < 1 || (names_ = LOGICAL(names)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "names", "TRUE", "FALSE"); return dense_diag_get(obj, valid[ivalid], names_); } SEXP dense_diag_set(SEXP from, const char *class, SEXP value, int new) { SEXP to = PROTECT(newObject(class)); int v = LENGTH(value) != 1; SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1], r = (m < n) ? m : n, j; if (m != n || n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); SET_SLOT(to, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ char ul = 'U'; if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } SEXP x = PROTECT(GET_SLOT(from, Matrix_xSym)); if (new) { x = duplicate(x); UNPROTECT(1); /* x */ PROTECT(x); } SET_SLOT(to, Matrix_xSym, x); #define DS_LOOP(_CTYPE_, _PTR_) \ do { \ _CTYPE_ *px = _PTR_(x), *pvalue = _PTR_(value); \ if (class[2] != 'p') { \ R_xlen_t m1a = (R_xlen_t) m + 1; \ if (v) \ for (j = 0; j < r; ++j, px += m1a) \ *px = *(pvalue++); \ else \ for (j = 0; j < r; ++j, px += m1a) \ *px = *pvalue; \ } else if (ul == 'U') { \ if (v) \ for (j = 0; j < n; px += (++j) + 1) \ *px = *(pvalue++); \ else \ for (j = 0; j < n; px += (++j) + 1) \ *px = *pvalue; \ } else { \ if (v) \ for (j = 0; j < n; px += n - (j++)) \ *px = *(pvalue++); \ else \ for (j = 0; j < n; px += n - (j++)) \ *px = *pvalue; \ } \ } while (0) switch (class[0]) { case 'n': case 'l': DS_LOOP(int, LOGICAL); break; case 'i': DS_LOOP(int, INTEGER); break; case 'd': DS_LOOP(double, REAL); break; case 'z': DS_LOOP(Rcomplex, COMPLEX); break; default: break; } #undef DS_LOOP UNPROTECT(2); /* x, to */ return to; } SEXP R_dense_diag_set(SEXP from, SEXP value) { static const char *valid[] = { VALID_DENSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *class = valid[ivalid]; SEXPTYPE tx = kindToType(class[0]), tv = TYPEOF(value); switch (tv) { case LGLSXP: case INTSXP: case REALSXP: case CPLXSXP: break; default: error(_("replacement diagonal has incompatible type \"%s\""), type2char(tv)); break; } SEXP dim = GET_SLOT(from, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1], r = (m < n) ? m : n; R_xlen_t len = XLENGTH(value); if (len != 1 && len != r) error(_("replacement diagonal has wrong length")); int new = 1; if (tv <= tx) { PROTECT(from); PROTECT(value = coerceVector(value, tx)); } else { /* defined in ./coerce.c : */ SEXP dense_as_kind(SEXP, const char *, char, int); #ifndef MATRIX_ENABLE_IMATRIX if (tv == INTSXP) { PROTECT(from = dense_as_kind(from, class, 'd', 0)); PROTECT(value = coerceVector(value, REALSXP)); } else { #endif PROTECT(from = dense_as_kind(from, class, typeToKind(tv), 0)); PROTECT(value); #ifndef MATRIX_ENABLE_IMATRIX } #endif class = valid[R_check_class_etc(from, valid)]; new = 0; } from = dense_diag_set(from, class, value, new); UNPROTECT(2); return from; } SEXP dense_transpose(SEXP from, const char *class) { SEXP to = PROTECT(newObject(class)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1], i, j; if (m != n) { UNPROTECT(1); /* dim */ PROTECT(dim = GET_SLOT(to, Matrix_DimSym)); pdim = INTEGER(dim); pdim[0] = n; pdim[1] = m; } else if (n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); if (class[1] == 's' || class[1] == 'p' || class[1] == 'o') SET_SLOT(to, Matrix_DimNamesSym, dimnames); else set_reversed_DimNames(to, dimnames); UNPROTECT(1); /* dimnames */ char ul = 'U'; if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); ul = *CHAR(STRING_ELT(uplo, 0)); UNPROTECT(1); /* uplo */ if (ul == 'U') { PROTECT(uplo = mkString("L")); SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); char di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N') SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } else { SEXP factors = PROTECT(GET_SLOT(from, Matrix_factorsSym)); if (LENGTH(factors) > 0) SET_SLOT(to, Matrix_factorsSym, factors); UNPROTECT(1); /* factors */ if (class[1] == 'o' && n > 0) { SEXP sd = PROTECT(GET_SLOT(from, Matrix_sdSym)); SET_SLOT(to, Matrix_sdSym, sd); UNPROTECT(1); /* sd */ } } } SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = PROTECT(allocVector(TYPEOF(x0), XLENGTH(x0))); SET_SLOT(to, Matrix_xSym, x1); #define TRANS_LOOP(_CTYPE_, _PTR_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ if (class[2] != 'p') { \ R_xlen_t mn1s = XLENGTH(x0) - 1; \ for (j = 0; j < m; ++j, px0 -= mn1s) \ for (i = 0; i < n; ++i, px0 += m) \ *(px1++) = *px0; \ } else if (ul == 'U') { \ for (j = 0; j < n; ++j) \ for (i = j; i < n; ++i) \ *(px1++) = *(px0 + PACKED_AR21_UP(j, i)); \ } else { \ R_xlen_t n2 = (R_xlen_t) n * 2; \ for (j = 0; j < n; ++j) \ for (i = 0; i <= j; ++i) \ *(px1++) = *(px0 + PACKED_AR21_LO(j, i, n2)); \ } \ } while (0) switch (class[0]) { case 'n': case 'l': TRANS_LOOP(int, LOGICAL); break; case 'i': TRANS_LOOP(int, INTEGER); break; case 'c': case 'd': TRANS_LOOP(double, REAL); break; case 'z': TRANS_LOOP(Rcomplex, COMPLEX); break; default: break; } #undef TRANS_LOOP UNPROTECT(3); /* x1, x0, to */ return to; } SEXP R_dense_transpose(SEXP from) { static const char *valid[] = { "dpoMatrix", "dppMatrix", "corMatrix", "copMatrix", VALID_DENSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); return dense_transpose(from, valid[ivalid]); } SEXP dense_force_symmetric(SEXP from, const char *class, char ul) { char ul0 = 'U', ul1 = 'U', di = 'N'; if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); ul0 = ul1 = *CHAR(STRING_ELT(uplo, 0)); UNPROTECT(1); /* uplo */ if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); di = *CHAR(STRING_ELT(diag, 0)); UNPROTECT(1); /* diag */ } } if (ul != '\0') ul1 = ul; if (class[1] == 's') { /* .s[yp]Matrix */ if (ul0 == ul1) return from; SEXP to = PROTECT(dense_transpose(from, class)); if (class[0] == 'z') { /* Need _conjugate_ transpose */ SEXP x1 = PROTECT(GET_SLOT(to, Matrix_xSym)); conjugate(x1); UNPROTECT(1); /* x1 */ } UNPROTECT(1) /* to */; return to; } /* Now handling just .(ge|tr|tp)Matrix ... */ char cl[] = ".s.Matrix"; cl[0] = class[0]; cl[2] = (class[2] != 'p') ? 'y' : 'p'; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) error(_("attempt to symmetrize a non-square matrix")); if (n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); set_symmetrized_DimNames(to, dimnames, -1); UNPROTECT(1); /* dimnames */ if (ul1 != 'U') { SEXP uplo = PROTECT(mkString("L")); SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)); if (class[1] == 'g' || ul0 == ul1) SET_SLOT(to, Matrix_xSym, x0); else { SEXP x1 = PROTECT(allocVector(TYPEOF(x0), XLENGTH(x0))); SET_SLOT(to, Matrix_xSym, x1); R_xlen_t len = XLENGTH(x1); #define DCPY(_PREFIX_, _CTYPE_, _PTR_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ Matrix_memset(px1, 0, len, sizeof(_CTYPE_)); \ if (class[2] != 'p') \ _PREFIX_ ## dcpy2(px1, px0, n, len, '\0', di); \ else \ _PREFIX_ ## dcpy1(px1, px0, n, len, ul1, ul0, di); \ } while (0) switch (class[0]) { case 'n': case 'l': DCPY(i, int, LOGICAL); break; case 'i': DCPY(i, int, INTEGER); break; case 'd': DCPY(d, double, REAL); break; case 'z': DCPY(z, Rcomplex, COMPLEX); break; default: break; } #undef DCPY UNPROTECT(1); /* x1 */ } UNPROTECT(2); /* x0, to */ return to; } SEXP R_dense_force_symmetric(SEXP from, SEXP uplo) { static const char *valid[] = { VALID_DENSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); char ul = '\0'; if (uplo != R_NilValue) { if (TYPEOF(uplo) != STRSXP || LENGTH(uplo) < 1 || (uplo = STRING_ELT(uplo, 0)) == NA_STRING || ((ul = *CHAR(uplo)) != 'U' && ul != 'L')) error(_("invalid '%s' to '%s'"), "uplo", __func__); } return dense_force_symmetric(from, valid[ivalid], ul); } SEXP dense_symmpart(SEXP from, const char *class) { if (class[0] != 'z' && class[0] != 'd') { /* defined in ./coerce.c : */ SEXP dense_as_kind(SEXP, const char *, char, int); from = dense_as_kind(from, class, 'd', 0); } if (class[0] != 'z' && class[1] == 's') return from; PROTECT(from); char cl[] = ".s.Matrix"; cl[0] = (class[0] != 'z') ? 'd' : 'z'; cl[2] = (class[2] != 'p') ? 'y' : 'p'; SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) error(_("attempt to get symmetric part of non-square matrix")); if (n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); if (class[1] == 's') SET_SLOT(to, Matrix_DimNamesSym, dimnames); else set_symmetrized_DimNames(to, dimnames, -1); UNPROTECT(1); /* dimnames */ char ul = 'U', di = 'N'; if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ if (class[1] == 't') { SEXP diag = PROTECT(GET_SLOT(from, Matrix_diagSym)); di = *CHAR(STRING_ELT(diag, 0)); UNPROTECT(1); /* diag */ } } SEXP x = PROTECT(GET_SLOT(from, Matrix_xSym)); if (class[0] == 'z' || class[0] == 'd') { x = duplicate(x); UNPROTECT(1); /* x */ PROTECT(x); } SET_SLOT(to, Matrix_xSym, x); if (class[1] == 's') { /* Symmetric part of Hermitian matrix is real part */ zeroIm(x); UNPROTECT(3); /* x, to, from */ return to; } int i, j; #define SP_LOOP(_CTYPE_, _PTR_, _INCREMENT_, _SCALE1_, _ONE_) \ do { \ _CTYPE_ *px = _PTR_(x); \ if (class[1] == 'g') { \ _CTYPE_ *py = px; \ for (j = 0; j < n; ++j) { \ for (i = j + 1; i < n; ++i) { \ px += n; \ py += 1; \ _INCREMENT_((*px), (*py)); \ _SCALE1_((*px), 0.5); \ } \ px = (py += j + 2); \ } \ } else if (class[2] != 'p') { \ if (ul == 'U') { \ for (j = 0; j < n; ++j) { \ for (i = 0; i < j; ++i) { \ _SCALE1_((*px), 0.5); \ px += 1; \ } \ px += n - j; \ } \ } else { \ for (j = 0; j < n; ++j) { \ px += j + 1; \ for (i = j + 1; i < n; ++i) { \ _SCALE1_((*px), 0.5); \ px += 1; \ } \ } \ } \ if (di != 'N') { \ R_xlen_t n1a = (R_xlen_t) n + 1; \ px = _PTR_(x); \ for (j = 0; j < n; ++j, px += n1a) \ *px = _ONE_; \ } \ } else { \ if (ul == 'U') { \ for (j = 0; j < n; ++j) { \ for (i = 0; i < j; ++i) { \ _SCALE1_((*px), 0.5); \ px += 1; \ } \ px += 1; \ } \ if (di != 'N') { \ px = _PTR_(x); \ for (j = 0; j < n; px += (++j) + 1) \ *px = _ONE_; \ } \ } else { \ for (j = 0; j < n; ++j) { \ px += 1; \ for (i = j + 1; i < n; ++i) { \ _SCALE1_((*px), 0.5); \ px += 1; \ } \ } \ if (di != 'N') { \ px = _PTR_(x); \ for (j = 0; j < n; px += n - (j++)) \ *px = _ONE_; \ } \ } \ } \ } while (0) if (cl[0] == 'd') SP_LOOP(double, REAL, INCREMENT_REAL, SCALE1_REAL, 1.0); else SP_LOOP(Rcomplex, COMPLEX, INCREMENT_COMPLEX, SCALE1_COMPLEX, Matrix_zone); #undef SP_LOOP UNPROTECT(3); /* x, to, from */ return to; } SEXP R_dense_symmpart(SEXP from) { static const char *valid[] = { VALID_DENSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); return dense_symmpart(from, valid[ivalid]); } SEXP dense_skewpart(SEXP from, const char *class) { if (class[0] != 'z' && class[0] != 'd') { /* defined in ./coerce.c : */ SEXP dense_as_kind(SEXP, const char *, char, int); from = dense_as_kind(from, class, 'd', 0); } PROTECT(from); char cl[] = "...Matrix"; cl[0] = (class[0] != 'z') ? 'd' : 'z'; cl[1] = (class[1] != 's') ? 'g' : 's'; cl[2] = (class[1] != 's') ? 'e' : ((class[0] != 'z') ? 'C' : ((class[2] != 'p') ? 'y' : 'p')); SEXP to = PROTECT(newObject(cl)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) error(_("attempt to get skew-symmetric part of non-square matrix")); if (n > 0) SET_SLOT(to, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(from, Matrix_DimNamesSym)); if (class[1] == 's') SET_SLOT(to, Matrix_DimNamesSym, dimnames); else set_symmetrized_DimNames(to, dimnames, -1); UNPROTECT(1); /* dimnames */ char ul = 'U'; if (class[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT(from, Matrix_uploSym)); ul = *CHAR(STRING_ELT(uplo, 0)); if (class[1] == 's' && ul != 'U') SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } if (class[1] == 's' && class[0] != 'z') { /* Skew-symmetric part of Hermitian matrix is imaginary part */ SEXP p = PROTECT(allocVector(INTSXP, (R_xlen_t) n + 1)); int *pp = INTEGER(p); Matrix_memset(pp, 0, (R_xlen_t) n + 1, sizeof(int)); SET_SLOT(to, Matrix_pSym, p); UNPROTECT(3); /* p, to, from */ return to; } SEXP x0 = PROTECT(GET_SLOT(from, Matrix_xSym)), x1 = x0; if (class[1] == 's') { /* Skew-symmetric part of Hermitian matrix is imaginary part */ x1 = duplicate(x1); UNPROTECT(1); /* x1 */ PROTECT(x1); SET_SLOT(to, Matrix_xSym, x1); zeroRe(x1); UNPROTECT(3); /* x1, to, from */ return to; } if (class[2] == 'p' || class[0] == 'z' || class[0] == 'd') { if ((Matrix_int_fast64_t) n * n > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); x1 = allocVector(TYPEOF(x0), (R_xlen_t) n * n); } PROTECT(x1); SET_SLOT(to, Matrix_xSym, x1); int i, j; R_xlen_t upos = 0, lpos = 0; #define SP_LOOP(_CTYPE_, _PTR_, _INCREMENT_, _ASSIGN_, _ZERO_) \ do { \ _CTYPE_ *px0 = _PTR_(x0), *px1 = _PTR_(x1); \ if (class[1] == 'g') { \ for (j = 0; j < n; ++j) { \ lpos = j; \ for (i = 0; i < j; ++i) { \ _ASSIGN_(px1[upos], 0.5 * px0[upos]); \ _INCREMENT_(px1[upos], -0.5 * px0[lpos]); \ _ASSIGN_(px1[lpos], -px1[upos]); \ upos += 1; \ lpos += n; \ } \ px1[upos] = _ZERO_; \ upos += n - j; \ } \ } else if (class[2] != 'p') { \ if (ul == 'U') { \ for (j = 0; j < n; ++j) { \ lpos = j; \ for (i = 0; i < j; ++i) { \ _ASSIGN_(px1[upos], 0.5 * px0[upos]); \ _ASSIGN_(px1[lpos], -px1[upos]); \ upos += 1; \ lpos += n; \ } \ px1[upos] = _ZERO_; \ upos += n - j; \ } \ } else { \ for (j = 0; j < n; ++j) { \ upos = lpos; \ px1[lpos] = _ZERO_; \ for (i = j + 1; i < n; ++i) { \ upos += n; \ lpos += 1; \ _ASSIGN_(px1[lpos], 0.5 * px0[lpos]); \ _ASSIGN_(px1[upos], -px1[lpos]); \ } \ lpos += j + 2; \ } \ } \ } else { \ if (ul == 'U') { \ for (j = 0; j < n; ++j, ++px0) { \ lpos = j; \ for (i = 0; i < j; ++i, ++px0) { \ _ASSIGN_(px1[upos], 0.5 * (*px0)); \ _ASSIGN_(px1[lpos], -px1[upos]); \ upos += 1; \ lpos += n; \ } \ px1[upos] = _ZERO_; \ upos += n - j; \ } \ } else { \ for (j = 0; j < n; ++j, ++px0) { \ upos = lpos; \ px1[lpos] = _ZERO_; \ for (i = j + 1; i < n; ++i, ++px0) { \ upos += n; \ lpos += 1; \ _ASSIGN_(px1[lpos], 0.5 * (*px0)); \ _ASSIGN_(px1[upos], -px1[lpos]); \ } \ lpos += j + 2; \ } \ } \ } \ } while (0) if (cl[0] == 'd') SP_LOOP(double, REAL, INCREMENT_REAL, ASSIGN_REAL, 0.0); else SP_LOOP(Rcomplex, COMPLEX, INCREMENT_COMPLEX, ASSIGN_COMPLEX, Matrix_zzero); #undef SP_LOOP UNPROTECT(4); /* x1, x0, to, from */ return to; } SEXP R_dense_skewpart(SEXP from) { static const char *valid[] = { VALID_DENSE, "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); return dense_skewpart(from, valid[ivalid]); } int dense_is_symmetric(SEXP obj, const char *class, int checkDN) { if (class[1] == 's') return 1; if (checkDN) { SEXP dimnames = GET_SLOT(obj, Matrix_DimNamesSym); if (!DimNames_is_symmetric(dimnames)) return 0; } if (class[1] == 't') return dense_is_diagonal(obj, class); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) return 0; if (n <= 1) return 1; SEXP x = GET_SLOT(obj, Matrix_xSym); int i, j; #define IS_LOOP(_CTYPE_, _PTR_, _NOTREAL_, _NOTCONJ_) \ do { \ _CTYPE_ *px = _PTR_(x), *py = px; \ for (j = 0; j < n; px = (py += (++j) + 1)) { \ if (_NOTREAL_((*px))) \ return 0; \ for (i = j + 1; i < n; ++i) { \ px += n; \ py += 1; \ if (_NOTCONJ_((*px), (*py))) \ return 0; \ } \ } \ return 1; \ } while (0) switch (class[0]) { case 'n': IS_LOOP(int, LOGICAL, NOTREAL_PATTERN, NOTCONJ_PATTERN); break; case 'l': IS_LOOP(int, LOGICAL, NOTREAL_LOGICAL, NOTCONJ_LOGICAL); break; case 'i': IS_LOOP(int, INTEGER, NOTREAL_INTEGER, NOTCONJ_INTEGER); break; case 'd': IS_LOOP(double, REAL, NOTREAL_REAL, NOTCONJ_REAL); break; case 'z': IS_LOOP(Rcomplex, COMPLEX, NOTREAL_COMPLEX, NOTCONJ_COMPLEX); break; default: break; } #undef IS_LOOP return 0; } SEXP R_dense_is_symmetric(SEXP obj, SEXP checkDN) { if (!IS_S4_OBJECT(obj)) { /* defined in ./coerce.c : */ SEXP matrix_as_dense(SEXP, const char *, char, char, int, int); obj = matrix_as_dense(obj, ".ge", '\0', '\0', 0, 0); } PROTECT(obj); static const char *valid[] = { VALID_DENSE, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) ERROR_INVALID_CLASS(obj, __func__); int checkDN_; if (TYPEOF(checkDN) != LGLSXP || LENGTH(checkDN) < 1 || (checkDN_ = LOGICAL(checkDN)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "checkDN", "TRUE", "FALSE"); SEXP ans = ScalarLogical(dense_is_symmetric(obj, valid[ivalid], checkDN_)); UNPROTECT(1); return ans; } int dense_is_triangular(SEXP obj, const char *class, int upper) { if (class[1] == 't') { SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); if (upper == NA_LOGICAL || (upper != 0) == (ul == 'U')) return (ul == 'U') ? 1 : -1; else if (dense_is_diagonal(obj, class)) return (ul == 'U') ? -1 : 1; else return 0; } if (class[1] == 's') { if (!dense_is_diagonal(obj, class)) return 0; SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); if (upper == NA_LOGICAL) return (ul == 'U') ? 1 : -1; else return (upper != 0) ? 1 : -1; } SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) return 0; if (n <= 1) return (upper != 0) ? 1 : -1; SEXP x = GET_SLOT(obj, Matrix_xSym); int i, j; #define IT_LOOP(_CTYPE_, _PTR_, _ISNZ_) \ do { \ _CTYPE_ *px; \ if (upper == NA_LOGICAL) { \ px = _PTR_(x); \ for (j = 0; j < n; px += (++j)) { \ px += 1; \ for (i = j + 1; i < n; ++i, px += 1) { \ if (_ISNZ_(*px)) { \ j = n; \ break; \ } \ } \ } \ if (j == n) \ return 1; \ px = _PTR_(x); \ for (j = 0; j < n; px += n - (++j)) { \ for (i = 0; i < j; ++i, px += 1) { \ if (_ISNZ_(*px)) { \ j = n; \ break; \ } \ } \ px += 1; \ } \ if (j == n) \ return -1; \ return 0; \ } else if (upper != 0) { \ px = _PTR_(x); \ for (j = 0; j < n; px += (++j)) { \ px += 1; \ for (i = j + 1; i < n; ++i, px += 1) \ if (_ISNZ_(*px)) \ return 0; \ } \ return 1; \ } else { \ px = _PTR_(x); \ for (j = 0; j < n; px += n - (++j)) { \ for (i = 0; i < j; ++i, px += 1) \ if (_ISNZ_(*px)) \ return 0; \ px += 1; \ } \ return -1; \ } \ } while (0) switch (class[0]) { case 'n': IT_LOOP(int, LOGICAL, ISNZ_PATTERN); break; case 'l': IT_LOOP(int, LOGICAL, ISNZ_LOGICAL); break; case 'i': IT_LOOP(int, INTEGER, ISNZ_INTEGER); break; case 'd': IT_LOOP(double, REAL, ISNZ_REAL); break; case 'z': IT_LOOP(Rcomplex, COMPLEX, ISNZ_COMPLEX); break; default: break; } #undef IT_LOOP return 0; } SEXP R_dense_is_triangular(SEXP obj, SEXP upper) { if (!IS_S4_OBJECT(obj)) { /* defined in ./coerce.c : */ SEXP matrix_as_dense(SEXP, const char *, char, char, int, int); obj = matrix_as_dense(obj, ".ge", '\0', '\0', 0, 0); } PROTECT(obj); static const char *valid[] = { VALID_DENSE, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) ERROR_INVALID_CLASS(obj, __func__); if (TYPEOF(upper) != LGLSXP || LENGTH(upper) < 1) error(_("'%s' must be %s or %s or %s"), "upper", "TRUE", "FALSE", "NA"); int upper_ = LOGICAL(upper)[0]; int ans_ = dense_is_triangular(obj, valid[ivalid], upper_); SEXP ans = allocVector(LGLSXP, 1); LOGICAL(ans)[0] = ans_ != 0; if (upper_ == NA_LOGICAL && ans_ != 0) { PROTECT(ans); static SEXP kindSym = NULL; SEXP kindVal = PROTECT(mkString((ans_ > 0) ? "U" : "L")); if (!kindSym) kindSym = install("kind"); setAttrib(ans, kindSym, kindVal); UNPROTECT(2); } UNPROTECT(1); return ans; } int dense_is_diagonal(SEXP obj, const char *class) { SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) return 0; if (n <= 1) return 1; char ul = 'U'; if (class[1] != 'g') { SEXP uplo = GET_SLOT(obj, Matrix_uploSym); ul = *CHAR(STRING_ELT(uplo, 0)); } SEXP x = GET_SLOT(obj, Matrix_xSym); int i, j; #define ID_LOOP(_CTYPE_, _PTR_, _ISNZ_) \ do { \ _CTYPE_ *px = _PTR_(x); \ if (class[1] == 'g') { \ for (j = 0; j < n; ++j) { \ for (i = 0; i < j; ++i) { \ if (_ISNZ_(*px)) \ return 0; \ px += 1; \ } \ px += 1; \ for (i = j + 1; i < n; ++i) { \ if (_ISNZ_(*px)) \ return 0; \ px += 1; \ } \ } \ } else if (class[2] != 'p') { \ if (ul == 'U') { \ for (j = 0; j < n; ++j) { \ for (i = 0; i < j; ++i) { \ if (_ISNZ_(*px)) \ return 0; \ px += 1; \ } \ px += n - j; \ } \ } else { \ for (j = 0; j < n; ++j) { \ px += j + 1; \ for (i = j + 1; i < n; ++i) { \ if (_ISNZ_(*px)) \ return 0; \ px += 1; \ } \ } \ } \ } else { \ if (ul == 'U') { \ for (j = 0; j < n; ++j) { \ for (i = 0; i < j; ++i) { \ if (_ISNZ_(*px)) \ return 0; \ px += 1; \ } \ px += 1; \ } \ } else { \ for (j = 0; j < n; ++j) { \ px += 1; \ for (i = j + 1; i < n; ++i) { \ if (_ISNZ_(*px)) \ return 0; \ px += 1; \ } \ } \ } \ } \ return 1; \ } while (0) switch (class[0]) { case 'n': ID_LOOP(int, LOGICAL, ISNZ_PATTERN); break; case 'l': ID_LOOP(int, LOGICAL, ISNZ_LOGICAL); break; case 'i': ID_LOOP(int, INTEGER, ISNZ_INTEGER); break; case 'd': ID_LOOP(double, REAL, ISNZ_REAL); break; case 'z': ID_LOOP(Rcomplex, COMPLEX, ISNZ_COMPLEX); break; default: break; } #undef ID_LOOP return 0; } SEXP R_dense_is_diagonal(SEXP obj) { if (!IS_S4_OBJECT(obj)) { /* defined in ./coerce.c : */ SEXP matrix_as_dense(SEXP, const char *, char, char, int, int); obj = matrix_as_dense(obj, ".ge", '\0', '\0', 0, 0); } PROTECT(obj); static const char *valid[] = { VALID_DENSE, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) ERROR_INVALID_CLASS(obj, __func__); SEXP ans = ScalarLogical(dense_is_diagonal(obj, valid[ivalid])); UNPROTECT(1); return ans; } #define CAST_PATTERN(_X_) (_X_ != 0) #define CAST_LOGICAL(_X_) (_X_ != 0) #define CAST_INTEGER(_X_) _X_ #define CAST_REAL(_X_) _X_ #define CAST_COMPLEX(_X_) _X_ #define SUM_CASES \ do { \ switch (class[0]) { \ case 'n': \ if (mean) \ SUM_LOOP(int, LOGICAL, double, REAL, \ 0.0, 1.0, NA_REAL, ISNA_PATTERN, \ CAST_PATTERN, INCREMENT_REAL, SCALE2_REAL); \ else \ SUM_LOOP(int, LOGICAL, int, INTEGER, \ 0, 1, NA_INTEGER, ISNA_PATTERN, \ CAST_PATTERN, INCREMENT_INTEGER, SCALE2_REAL); \ break; \ case 'l': \ if (mean) \ SUM_LOOP(int, LOGICAL, double, REAL, \ 0.0, 1.0, NA_REAL, ISNA_LOGICAL, \ CAST_LOGICAL, INCREMENT_REAL, SCALE2_REAL); \ else \ SUM_LOOP(int, LOGICAL, int, INTEGER, \ 0, 1, NA_INTEGER, ISNA_LOGICAL, \ CAST_LOGICAL, INCREMENT_INTEGER, SCALE2_REAL); \ break; \ case 'i': \ SUM_LOOP(int, INTEGER, double, REAL, \ 0.0, 1.0, NA_REAL, ISNA_INTEGER, \ CAST_INTEGER, INCREMENT_REAL, SCALE2_REAL); \ break; \ case 'd': \ SUM_LOOP(double, REAL, double, REAL, \ 0.0, 1.0, NA_REAL, ISNA_REAL, \ CAST_REAL, INCREMENT_REAL, SCALE2_REAL); \ break; \ case 'z': \ SUM_LOOP(Rcomplex, COMPLEX, Rcomplex, COMPLEX, \ Matrix_zzero, Matrix_zone, Matrix_zna, ISNA_COMPLEX, \ CAST_COMPLEX, INCREMENT_COMPLEX, SCALE2_COMPLEX); \ break; \ default: \ break; \ } \ } while (0) #define SUM_TYPEOF(c) (c == 'z') ? CPLXSXP : ((mean || c == 'd' || c == 'i') ? REALSXP : INTSXP) static void dense_colsum(SEXP x, const char *class, int m, int n, char ul, char di, int narm, int mean, SEXP res) { int i, j, count = -1, narm_ = narm && mean && class[0] != 'n', unpacked = class[2] != 'p'; #define SUM_LOOP(_CTYPE0_, _PTR0_, _CTYPE1_, _PTR1_, \ _ZERO_, _ONE_, _NA_, _ISNA_, \ _CAST_, _INCREMENT_, _SCALE2_) \ do { \ _CTYPE0_ *px0 = _PTR0_( x); \ _CTYPE1_ *px1 = _PTR1_(res), tmp; \ if (class[1] == 'g') { \ for (j = 0; j < n; ++j) { \ *px1 = _ZERO_; \ SUM_KERNEL(for (i = 0; i < m; ++i), _NA_, _ISNA_, \ _CAST_, _INCREMENT_, _SCALE2_); \ px1 += 1; \ } \ } else if (di == 'N') { \ if (ul == 'U') { \ for (j = 0; j < n; ++j) { \ *px1 = _ZERO_; \ SUM_KERNEL(for (i = 0; i <= j; ++i), _NA_, _ISNA_, \ _CAST_, _INCREMENT_, _SCALE2_); \ if (unpacked) \ px0 += n - j - 1; \ px1 += 1; \ } \ } else { \ for (j = 0; j < n; ++j) { \ if (unpacked) \ px0 += j; \ *px1 = _ZERO_; \ SUM_KERNEL(for (i = j; i < n; ++i), _NA_, _ISNA_, \ _CAST_, _INCREMENT_, _SCALE2_); \ px1 += 1; \ } \ } \ } else { \ if (ul == 'U') { \ for (j = 0; j < n; ++j) { \ *px1 = _ONE_; \ SUM_KERNEL(for (i = 0; i < j; ++i), _NA_, _ISNA_, \ _CAST_, _INCREMENT_, _SCALE2_); \ ++px0; \ if (unpacked) \ px0 += n - j - 1; \ px1 += 1; \ } \ } else { \ for (j = 0; j < n; ++j) { \ if (unpacked) \ px0 += j; \ ++px0; \ *px1 = _ONE_; \ SUM_KERNEL(for (i = j + 1; i < n; ++i), _NA_, _ISNA_, \ _CAST_, _INCREMENT_, _SCALE2_); \ px1 += 1; \ } \ } \ } \ } while (0) #define SUM_KERNEL(_FOR_, _NA_, _ISNA_, _CAST_, _INCREMENT_, _SCALE2_) \ do { \ if (mean) \ count = m; \ _FOR_ { \ if (_ISNA_(*px0)) { \ if (!narm) \ *px1 = _NA_; \ else if (narm_) \ --count; \ } else { \ tmp = _CAST_(*px0); \ _INCREMENT_((*px1), tmp); \ } \ ++px0; \ } \ if (mean) \ _SCALE2_((*px1), count); \ } while (0) SUM_CASES; #undef SUM_LOOP #undef SUM_KERNEL return; } static void dense_rowsum(SEXP x, const char *class, int m, int n, char ul, char di, int narm, int mean, SEXP res) { int i, j, *count = NULL, narm_ = narm && mean && class[0] != 'n', unpacked = class[2] != 'p', symmetric = class[1] == 's'; if (narm_) { Matrix_Calloc(count, m, int); for (i = 0; i < m; ++i) count[i] = n; } #define SUM_LOOP(_CTYPE0_, _PTR0_, _CTYPE1_, _PTR1_, \ _ZERO_, _ONE_, _NA_, _ISNA_, \ _CAST_, _INCREMENT_, _SCALE2_) \ do { \ _CTYPE0_ *px0 = _PTR0_( x); \ _CTYPE1_ *px1 = _PTR1_(res), tmp = (di == 'N') ? _ZERO_ : _ONE_; \ for (i = 0; i < m; ++i) \ px1[i] = tmp; \ if (class[1] == 'g') { \ for (j = 0; j < n; ++j) \ SUM_KERNEL(for (i = 0; i < m; ++i), _NA_, _ISNA_, \ _CAST_, _INCREMENT_); \ } else if (class[1] == 's' || di == 'N') { \ if (ul == 'U') { \ for (j = 0; j < n; ++j) { \ SUM_KERNEL(for (i = 0; i <= j; ++i), _NA_, _ISNA_, \ _CAST_, _INCREMENT_); \ if (unpacked) \ px0 += n - j - 1; \ } \ } else { \ for (j = 0; j < n; ++j) { \ if (unpacked) \ px0 += j; \ SUM_KERNEL(for (i = j; i < n; ++i), _NA_, _ISNA_, \ _CAST_, _INCREMENT_); \ } \ } \ } else { \ if (ul == 'U') { \ for (j = 0; j < n; ++j) { \ SUM_KERNEL(for (i = 0; i < j; ++i), _NA_, _ISNA_, \ _CAST_, _INCREMENT_); \ ++px0; \ if (unpacked) \ px0 += n - j - 1; \ } \ } else { \ for (j = 0; j < n; ++j) { \ if (unpacked) \ px0 += j; \ ++px0; \ SUM_KERNEL(for (i = j + 1; i < n; ++i), _NA_, _ISNA_, \ _CAST_, _INCREMENT_); \ } \ } \ } \ if (mean) { \ if (narm_) \ for (i = 0; i < m; ++i) \ _SCALE2_(px1[i], count[i]); \ else \ for (i = 0; i < m; ++i) \ _SCALE2_(px1[i], n); \ } \ } while (0) #define SUM_KERNEL(_FOR_, _NA_, _ISNA_, _CAST_, _INCREMENT_) \ do { \ _FOR_ { \ int again = symmetric && i != j; \ if (_ISNA_(*px0)) { \ if (!narm) { \ px1[i] = _NA_; \ if (again) \ px1[j] = _NA_; \ } else if (narm_) { \ --count[i]; \ if (again) \ --count[j]; \ } \ } else { \ tmp = _CAST_(*px0); \ _INCREMENT_(px1[i], tmp); \ if (again) \ _INCREMENT_(px1[j], tmp); \ } \ ++px0; \ } \ } while (0) SUM_CASES; #undef SUM_LOOP #undef SUM_KERNEL if (narm_) Matrix_Free(count, m); return; } SEXP dense_marginsum(SEXP obj, const char *class, int margin, int narm, int mean) { SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1], r = (margin == 0) ? m : n; SEXP res = PROTECT(allocVector(SUM_TYPEOF(class[0]), r)), x = PROTECT(GET_SLOT(obj, Matrix_xSym)); SEXP dimnames = (class[1] != 's') ? GET_SLOT(obj, Matrix_DimNamesSym) : get_symmetrized_DimNames(obj, -1), marnames = VECTOR_ELT(dimnames, margin); if (marnames != R_NilValue) { PROTECT(marnames); setAttrib(res, R_NamesSymbol, marnames); UNPROTECT(1); /* marnames */ } char ul = 'U', di = 'N'; if (class[1] != 'g') { SEXP uplo = GET_SLOT(obj, Matrix_uploSym); ul = *CHAR(STRING_ELT(uplo, 0)); if (class[1] == 't') { SEXP diag = GET_SLOT(obj, Matrix_diagSym); di = *CHAR(STRING_ELT(diag, 0)); } } if (margin == 0 || class[1] == 's') dense_rowsum(x, class, m, n, ul, di, narm, mean, res); else dense_colsum(x, class, m, n, ul, di, narm, mean, res); UNPROTECT(2); /* x, res */ return res; } /* (row|col)(Sums|Means)() */ SEXP R_dense_marginsum(SEXP obj, SEXP margin, SEXP narm, SEXP mean) { static const char *valid[] = { VALID_DENSE, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) ERROR_INVALID_CLASS(obj, __func__); int margin_; if (TYPEOF(margin) != INTSXP || LENGTH(margin) < 1 || ((margin_ = INTEGER(margin)[0]) != 0 && margin_ != 1)) error(_("'%s' must be %d or %d"), "margin", 0, 1); int narm_; if (TYPEOF(narm) != LGLSXP || LENGTH(narm) < 1 || (narm_ = LOGICAL(narm)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "narm", "TRUE", "FALSE"); int mean_; if (TYPEOF(mean) != LGLSXP || LENGTH(mean) < 1 || (mean_ = LOGICAL(mean)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "mean", "TRUE", "FALSE"); return dense_marginsum(obj, valid[ivalid], margin_, narm_, mean_); } #undef SUM_CASES #undef SUM_TYPEOF #define TRY_INCREMENT(_LABEL_) \ do { \ if ((s >= 0) \ ? ( t <= MATRIX_INT_FAST64_MAX - s) \ : (-t <= s - MATRIX_INT_FAST64_MIN)) { \ s += t; \ t = 0; \ count = 0; \ } else { \ over = 1; \ goto _LABEL_; \ } \ } while (0) #define LONGDOUBLE_AS_DOUBLE(v) \ (v > DBL_MAX) ? R_PosInf : ((v < -DBL_MAX) ? R_NegInf : (double) v); SEXP dense_sum(SEXP obj, const char *class, int narm) { SEXP res; SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; char ul = 'U', di = 'N'; if (class[1] != 'g') { SEXP uplo = GET_SLOT(obj, Matrix_uploSym); ul = *CHAR(STRING_ELT(uplo, 0)); if (class[1] == 't') { SEXP diag = GET_SLOT(obj, Matrix_diagSym); di = *CHAR(STRING_ELT(diag, 0)); } } SEXP x = GET_SLOT(obj, Matrix_xSym); int i, j, unpacked = class[2] != 'p', symmetric = class[1] == 's'; #define SUM_LOOP \ do { \ if (class[1] == 'g') { \ for (j = 0; j < n; ++j) \ SUM_KERNEL(for (i = 0; i < m; ++i)); \ } else if (class[1] == 's' || di == 'N') { \ if (ul == 'U') { \ for (j = 0; j < n; ++j) { \ SUM_KERNEL(for (i = 0; i <= j; ++i)); \ if (unpacked) \ px += m - j - 1; \ } \ } else { \ for (j = 0; j < n; ++j) { \ if (unpacked) \ px += j; \ SUM_KERNEL(for (i = j; i < m; ++i)); \ } \ } \ } else { \ if (ul == 'U') { \ for (j = 0; j < n; ++j) { \ SUM_KERNEL(for (i = 0; i < j; ++i)); \ ++px; \ if (unpacked) \ px += m - j - 1; \ } \ } else { \ for (j = 0; j < n; ++j) { \ if (unpacked) \ px += j; \ ++px; \ SUM_KERNEL(for (i = j + 1; i < m; ++i)); \ } \ } \ } \ } while (0) if (class[0] == 'n') { int *px = LOGICAL(x); Matrix_int_fast64_t s = (di == 'N') ? 0LL : n; #define SUM_KERNEL(_FOR_) \ do { \ _FOR_ { \ if (*px != 0) \ s += (symmetric && i != j) ? 2 : 1; \ ++px; \ } \ } while (0) SUM_LOOP; #undef SUM_KERNEL if (s <= INT_MAX) { res = allocVector(INTSXP, 1); INTEGER(res)[0] = (int) s; } else { res = allocVector(REALSXP, 1); REAL(res)[0] = (double) s; } return res; } if (!narm && (class[0] == 'l' || class[0] == 'i')) { int *px = (class[0] == 'l') ? LOGICAL(x) : INTEGER(x); #define SUM_KERNEL(_FOR_) \ do { \ _FOR_ { \ if (*px == NA_INTEGER) { \ res = allocVector(INTSXP, 1); \ INTEGER(res)[0] = NA_INTEGER; \ return res; \ } \ ++px; \ } \ } while (0) SUM_LOOP; #undef SUM_KERNEL } if (class[0] == 'z') { Rcomplex *px = COMPLEX(x); long double zr = (di == 'N') ? 0.0L : n, zi = 0.0L; #define SUM_KERNEL(_FOR_) \ do { \ _FOR_ { \ if (!(narm && (ISNAN((*px).r) || ISNAN((*px).i)))) { \ zr += (symmetric && i != j) \ ? 2.0L * (*px).r : (*px).r; \ zi += (symmetric && i != j) \ ? 2.0L * (*px).i : (*px).i; \ } \ ++px; \ } \ } while (0) SUM_LOOP; #undef SUM_KERNEL res = allocVector(CPLXSXP, 1); COMPLEX(res)[0].r = LONGDOUBLE_AS_DOUBLE(zr); COMPLEX(res)[0].i = LONGDOUBLE_AS_DOUBLE(zi); } else if (class[0] == 'd') { double *px = REAL(x); long double zr = (di == 'N') ? 0.0L : n; #define SUM_KERNEL(_FOR_) \ do { \ _FOR_ { \ if (!(narm && ISNAN(*px))) \ zr += (symmetric && i != j) \ ? 2.0L * *px : *px; \ ++px; \ } \ } while (0) SUM_LOOP; #undef SUM_KERNEL res = allocVector(REALSXP, 1); REAL(res)[0] = LONGDOUBLE_AS_DOUBLE(zr); } else { int *px = (class[0] == 'i') ? INTEGER(x) : LOGICAL(x); Matrix_int_fast64_t s = (di == 'N') ? 0LL : n, t = 0LL; unsigned int count = 0; int over = 0; #define SUM_KERNEL(_FOR_) \ do { \ _FOR_ { \ if (!(narm && *px == NA_INTEGER)) { \ int d = (symmetric && i != j) ? 2 : 1; \ if (count > UINT_MAX - d) \ TRY_INCREMENT(ifover); \ t += (d == 2) ? 2LL * *px : *px; \ count += d; \ } \ ++px; \ } \ } while (0) SUM_LOOP; #undef SUM_KERNEL TRY_INCREMENT(ifover); ifover: if (over) { long double zr = (di == 'N') ? 0.0L : n; /* FIXME: wasteful */ px = (class[0] == 'i') ? INTEGER(x) : LOGICAL(x); #define SUM_KERNEL(_FOR_) \ do { \ _FOR_ { \ if (!(narm && *px == NA_INTEGER)) \ zr += (symmetric && i != j) \ ? 2.0L * *px : *px; \ ++px; \ } \ } while (0) SUM_LOOP; #undef SUM_KERNEL res = allocVector(REALSXP, 1); REAL(res)[0] = LONGDOUBLE_AS_DOUBLE(zr); } else if (s > INT_MIN && s <= INT_MAX) { res = allocVector(INTSXP, 1); INTEGER(res)[0] = (int) s; } else { res = allocVector(REALSXP, 1); REAL(res)[0] = (double) s; } } #undef SUM_LOOP return res; } /* sum() */ SEXP R_dense_sum(SEXP obj, SEXP narm) { static const char *valid[] = { VALID_DENSE, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) ERROR_INVALID_CLASS(obj, __func__); int narm_; if (TYPEOF(narm) != LGLSXP || LENGTH(narm) < 1 || (narm_ = LOGICAL(narm)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "narm", "TRUE", "FALSE"); return dense_sum(obj, valid[ivalid], narm_); } SEXP dense_prod(SEXP obj, const char *class, int narm) { SEXP res = PROTECT(allocVector((class[0] == 'z') ? CPLXSXP : REALSXP, 1)); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; char ul = 'U', di = 'N'; if (class[1] != 'g') { SEXP uplo = GET_SLOT(obj, Matrix_uploSym); ul = *CHAR(STRING_ELT(uplo, 0)); if (class[1] == 't') { SEXP diag = GET_SLOT(obj, Matrix_diagSym); di = *CHAR(STRING_ELT(diag, 0)); } } SEXP x = GET_SLOT(obj, Matrix_xSym); int i, j, unpacked = class[2] != 'p', symmetric = class[1] == 's'; long double zr = 1.0L, zi = 0.0L; #define PROD_LOOP \ do { \ if (class[1] == 'g') { \ for (j = 0; j < n; ++j) \ PROD_KERNEL(for (i = 0; i < m; ++i)); \ } else if (class[1] == 's') { \ if (ul == 'U') { \ for (j = 0; j < n; ++j) { \ PROD_KERNEL(for (i = 0; i <= j; ++i)); \ if (unpacked) \ px += m - j - 1; \ } \ } else { \ for (j = 0; j < n; ++j) { \ if (unpacked) \ px += j; \ PROD_KERNEL(for (i = j; i < m; ++i)); \ } \ } \ } else if (di == 'N') { \ if (ul == 'U') { \ for (j = 0; j < n; ++j) { \ if (j == 1) { zr *= 0.0L; zi *= 0.0L; } \ PROD_KERNEL(for (i = 0; i <= j; ++i)); \ if (unpacked) \ px += m - j - 1; \ } \ } else { \ for (j = 0; j < n; ++j) { \ if (j == 1) { zr *= 0.0L; zi *= 0.0L; } \ if (unpacked) \ px += j; \ PROD_KERNEL(for (i = j; i < m; ++i)); \ } \ } \ } else { \ if (ul == 'U') { \ for (j = 0; j < n; ++j) { \ if (j == 1) { zr *= 0.0L; zi *= 0.0L; } \ PROD_KERNEL(for (i = 0; i < j; ++i)); \ ++px; \ if (unpacked) \ px += m - j - 1; \ } \ } else { \ for (j = 0; j < n; ++j) { \ if (j == 1) { zr *= 0.0L; zi *= 0.0L; } \ if (unpacked) \ px += j; \ ++px; \ PROD_KERNEL(for (i = j + 1; i < m; ++i)); \ } \ } \ } \ } while (0) if (class[0] == 'n') { int *px = LOGICAL(x); if (class[1] == 't') REAL(res)[0] = (n > 1 || (n == 1 && *px == 0)) ? 0.0 : 1.0; else { #define PROD_KERNEL(_FOR_) \ do { \ _FOR_ { \ if (*px == 0) { \ REAL(res)[0] = 0.0; \ UNPROTECT(1); /* res */ \ return res; \ } \ ++px; \ } \ } while (0) PROD_LOOP; #undef PROD_KERNEL REAL(res)[0] = 1.0; } UNPROTECT(1); /* res */ return res; } if (class[0] == 'z') { Rcomplex *px = COMPLEX(x); long double zr0, zi0; #define PROD_KERNEL(_FOR_) \ do { \ _FOR_ { \ if (!(narm && (ISNAN((*px).r) || ISNAN((*px).i)))) { \ zr0 = zr; zi0 = zi; \ zr = zr0 * (*px).r - zi0 * (*px).i; \ zi = zr0 * (*px).i + zi0 * (*px).r; \ if (symmetric && i != j) { \ zr0 = zr; zi0 = zi; \ zr = zr0 * (*px).r - zi0 * (*px).i; \ zi = zr0 * (*px).i + zi0 * (*px).r; \ } \ } \ ++px; \ } \ } while (0) PROD_LOOP; #undef PROD_KERNEL } else if (class[0] == 'd') { double *px = REAL(x); #define PROD_KERNEL(_FOR_) \ do { \ _FOR_ { \ if (!(narm && ISNAN(*px))) \ zr *= (symmetric && i != j) \ ? (long double) *px * *px : *px; \ ++px; \ } \ } while (0) PROD_LOOP; #undef PROD_KERNEL } else { int *px = (class[0] == 'l') ? LOGICAL(x) : INTEGER(x); #define PROD_KERNEL(_FOR_) \ do { \ _FOR_ { \ if (*px != NA_INTEGER) \ zr *= (symmetric && i != j) \ ? (long double) *px * *px : *px; \ else if (!narm) \ zr *= NA_REAL; \ ++px; \ } \ } while (0) PROD_LOOP; #undef PROD_KERNEL } #undef PROD_LOOP if (class[0] == 'z') { COMPLEX(res)[0].r = LONGDOUBLE_AS_DOUBLE(zr); COMPLEX(res)[0].i = LONGDOUBLE_AS_DOUBLE(zi); } else REAL(res)[0] = LONGDOUBLE_AS_DOUBLE(zr); UNPROTECT(1); /* res */ return res; } /* prod() */ SEXP R_dense_prod(SEXP obj, SEXP narm) { static const char *valid[] = { VALID_DENSE, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) ERROR_INVALID_CLASS(obj, __func__); int narm_; if (TYPEOF(narm) != LGLSXP || LENGTH(narm) < 1 || (narm_ = LOGICAL(narm)[0]) == NA_LOGICAL) error(_("'%s' must be %s or %s"), "narm", "TRUE", "FALSE"); return dense_prod(obj, valid[ivalid], narm_); } #undef TRY_INCREMENT #undef LONGDOUBLE_AS_DOUBLE /* MJ: unused */ #if 0 /** * Perform a left cyclic shift of columns j to k in the upper triangular * matrix x, then restore it to upper triangular form with Givens rotations. * The algorithm is based on the Fortran routine DCHEX from Linpack. * * The lower triangle of x is not modified. * * @param x Matrix stored in column-major order * @param ldx leading dimension of x * @param j column number (0-based) that will be shifted to position k * @param k last column number (0-based) to be shifted * @param cosines cosines of the Givens rotations * @param sines sines of the Givens rotations * * @return 0 for success */ static int left_cyclic(double *x, int ldx, int j, int k, double *cosines, double *sines) { if (j < 0) error(_("incorrect left cyclic shift, j (%d) < 0"), j); if (j >= k) error(_("incorrect left cyclic shift, j (%d) >= k (%d)"), j, k); if (ldx < k) error(_("incorrect left cyclic shift, k (%d) > ldx (%d)"), k, ldx); double *lastcol = (double *) R_alloc((size_t) k + 1, sizeof(double)); int i; /* keep a copy of column j */ for (i = 0; i <= j; i++) lastcol[i] = x[i + j*ldx]; /* For safety, zero the rest */ for (i = j+1; i <= k; i++) lastcol[i] = 0.; for (int jj = j+1, ind = 0; jj <= k; jj++, ind++) { /* columns to be shifted */ int diagind = jj*(ldx+1); // ind == (jj-j) - 1 double tmp = x[diagind], cc, ss; /* Calculate the Givens rotation. */ /* This modified the super-diagonal element */ F77_CALL(drotg)(x+diagind-1, &tmp, cosines+ind, sines+ind); cc = cosines[ind]; ss = sines[ind]; /* Copy column jj+1 to column jj. */ for (i = 0; i < jj; i++) x[i + (jj-1)*ldx] = x[i+jj*ldx]; /* Apply rotation to columns up to k */ for (i = jj; i < k; i++) { tmp = cc*x[(jj-1)+i*ldx] + ss*x[jj+i*ldx]; x[jj+i*ldx] = cc*x[jj+i*ldx] - ss*x[(jj-1)+i*ldx]; x[(jj-1)+i*ldx] = tmp; } /* Apply rotation to lastcol */ lastcol[jj] = -ss*lastcol[jj-1]; lastcol[jj-1] *= cc; } /* Copy lastcol to column k */ for(i = 0; i <= k; i++) x[i+k*ldx] = lastcol[i]; return 0; } static SEXP getGivens(double *x, int ldx, int jmin, int rank) { int shiftlen = (rank - jmin) - 1; SEXP ans = PROTECT(allocVector(VECSXP, 4)), nms, cosines, sines; SET_VECTOR_ELT(ans, 0, ScalarInteger(jmin)); SET_VECTOR_ELT(ans, 1, ScalarInteger(rank)); SET_VECTOR_ELT(ans, 2, cosines = allocVector(REALSXP, shiftlen)); SET_VECTOR_ELT(ans, 3, sines = allocVector(REALSXP, shiftlen)); setAttrib(ans, R_NamesSymbol, nms = allocVector(STRSXP, 4)); SET_STRING_ELT(nms, 0, mkChar("jmin")); SET_STRING_ELT(nms, 1, mkChar("rank")); SET_STRING_ELT(nms, 2, mkChar("cosines")); SET_STRING_ELT(nms, 3, mkChar("sines")); if (left_cyclic(x, ldx, jmin, rank - 1, REAL(cosines), REAL(sines))) error(_("unknown error in getGivens")); UNPROTECT(1); return ans; } static SEXP checkGivens(SEXP X, SEXP jmin, SEXP rank) { if (!(isReal(X) && isMatrix(X))) error(_("X must be a numeric (double precision) matrix")); SEXP ans = PROTECT(allocVector(VECSXP, 2)), Xcp = PROTECT(duplicate(X)); int Xdims = INTEGER(getAttrib(X, R_DimSymbol)); SET_VECTOR_ELT(ans, 0, Xcp); SET_VECTOR_ELT(ans, 1, getGivens(REAL(Xcp), Xdims[0], asInteger(jmin), asInteger(rank))); UNPROTECT(2); return ans; } SEXP lsq_dense_chol(SEXP X, SEXP y) { if (!(isReal(X) && isMatrix(X))) error(_("X must be a numeric (double precision) matrix")); if (!(isReal(y) && isMatrix(y))) error(_("y must be a numeric (double precision) matrix")); int *Xdims = INTEGER(getAttrib(X, R_DimSymbol)), *ydims = INTEGER(getAttrib(y, R_DimSymbol)); if (Xdims[0] != ydim[0]) error(_("number of rows in y (%d) does not match " "number of rows in X (%d)"), ydims[0], Xdims[0]); int n = Xdims[0], p = Xdims[1], k = ydims[1]; if (p < 1 || k < 1) return allocMatrix(REALSXP, p, k); SEXP ans = PROTECT(allocMatrix(REALSXP, p, k)); double d_one = 1.0, d_zero = 0.0, *xpx = (double *) R_alloc((size_t) p * p, sizeof(double)); int info; F77_CALL(dgemm)("T", "N", &p, &k, &n, &d_one, REAL(X), &n, REAL(y), &n, &d_zero, REAL(ans), &p FCONE FCONE); F77_CALL(dsyrk)("U", "T", &p, &n, &d_one, REAL(X), &n, &d_zero, xpx, &p FCONE FCONE); F77_CALL(dposv)("U", &p, &k, xpx, &p, REAL(ans), &p, &info FCONE); if (info) error(_("LAPACK dposv returned error code %d"), info); UNPROTECT(1); return ans; } SEXP lsq_dense_qr(SEXP X, SEXP y) { if (!(isReal(X) && isMatrix(X))) error(_("X must be a numeric (double precision) matrix")); if (!(isReal(y) && isMatrix(y))) error(_("y must be a numeric (double precision) matrix")); int *Xdims = INTEGER(getAttrib(X, R_DimSymbol)), *ydims = INTEGER(getAttrib(y, R_DimSymbol)); if (Xdims[0] != ydim[0]) error(_("number of rows in y (%d) does not match " "number of rows in X (%d)"), ydims[0], Xdims[0]); int n = Xdims[0], p = Xdims[1], k = ydims[1]; if (p < 1 || k < 1) return allocMatrix(REALSXP, p, k); SEXP ans = PROTECT(duplicate(y)); double *xvals = (double *) R_alloc((size_t) n * p, sizeof(double)), *work, tmp; int lwork = -1, info; Memcpy(xvals, REAL(X), (size_t) n * p); F77_CALL(dgels)("N", &n, &p, &k, xvals, &n, REAL(ans), &n, &tmp, &lwork, &info FCONE); if (info) error(_("LAPACK dgels returned error code %d"), info); lwork = (int) tmp; work = (double *) R_alloc((size_t) lwork, sizeof(double)); F77_CALL(dgels)("N", &n, &p, &k, xvals, &n, REAL(ans), &n, work, &lwork, &info FCONE); if (info) error(_("LAPACK dgels returned error code %d"), info); UNPROTECT(1); return ans; } /* Rank-Correcting/Adapting LAPACK QR Decomposition * From Doug Bates' initial import; __unused__ * * Provides a qr() with 'rcond' and rank reduction while(rcond < tol), * possibly via Givens rotations but WITHOUT PIVOTING * * .Call(Matrix:::lapack_qr, A, 1e-17) * --> ~/R/MM/Pkg-ex/Matrix/qr-rank-deficient.R * * TODO: export as Matrix::qrNoPiv() or qr1() or similar */ SEXP lapack_qr(SEXP Xin, SEXP tl) { if (!(isReal(Xin) && isMatrix(Xin))) error(_("X must be a real (numeric) matrix")); double tol = asReal(tl); if (tol < 0.0) error(_("tol, given as %g, must be >= 0"), tol); if (tol > 1.0) error(_("tol, given as %g, must be <= 1"), tol); SEXP ans = PROTECT(allocVector(VECSXP, 5)), X, qraux, pivot; int *Xdims = INTEGER(getAttrib(Xin, R_DimSymbol)), n = Xdims[0], p = Xdims[1], /* size of triangular part of decomposition : */ trsz = (n < p) ? n : p, i; SET_VECTOR_ELT(ans, 0, X = duplicate(Xin)); SET_VECTOR_ELT(ans, 2, qraux = allocVector(REALSXP, trsz)); SET_VECTOR_ELT(ans, 3, pivot = allocVector(INTSXP, p)); for (i = 0; i < p; i++) INTEGER(pivot)[i] = i + 1; SEXP nms, Givens = PROTECT(allocVector(VECSXP, trsz - 1)); setAttrib(ans, R_NamesSymbol, nms = allocVector(STRSXP, 5)); SET_STRING_ELT(nms, 0, mkChar("qr")); SET_STRING_ELT(nms, 1, mkChar("rank")); SET_STRING_ELT(nms, 2, mkChar("qraux")); SET_STRING_ELT(nms, 3, mkChar("pivot")); SET_STRING_ELT(nms, 4, mkChar("Givens")); int rank = trsz, nGivens = 0; double rcond = 0.0; if (n > 0 && p > 0) { double *xpt = REAL(X), *work, tmp; int *iwork, lwork, info; lwork = -1; F77_CALL(dgeqrf)(&n, &p, xpt, &n, REAL(qraux), &tmp, &lwork, &info); if (info) error(_("LAPACK dgeqrf returned error code %d"), info); lwork = (int) tmp; work = (double *) R_alloc(((size_t) lwork < (size_t) 3 * trsz) ? (size_t) 3 * trsz : (size_t) lwork, sizeof(double)); F77_CALL(dgeqrf)(&n, &p, xpt, &n, REAL(qraux), work, &lwork, &info); if (info) error(_("LAPACK dgeqrf returned error code %d"), info); iwork = (int *) R_alloc((size_t) trsz, sizeof(int)); F77_CALL(dtrcon)("1", "U", "N", &rank, xpt, &n, &rcond, work, iwork, &info FCONE FCONE FCONE); if (info) error(_("LAPACK dtrcon returned error code %d"), info); while (rcond < tol) { /* check diagonal elements */ double el, minabs = (xpt[0] < 0.0) ? -xpt[0]: xpt[0]; int jmin = 0; for (i = 1; i < rank; i++) { el = xpt[i*n]; // had i*(n+1) which looks wrong to MM if (el < 0.0) el = -el; if (el < minabs) { jmin = i; minabs = el; } } if (jmin < (rank - 1)) { SET_VECTOR_ELT(Givens, nGivens, getGivens(xpt, n, jmin, rank)); nGivens++; } // otherwise jmin == (rank - 1), so just "drop that column" rank--; // new rcond := ... for reduced rank F77_CALL(dtrcon)("1", "U", "N", &rank, xpt, &n, &rcond, work, iwork, &info FCONE FCONE FCONE); if (info) error(_("LAPACK dtrcon returned error code %d"), info); } } SEXP Gcpy; SET_VECTOR_ELT(ans, 1, ScalarInteger(rank)); SET_VECTOR_ELT(ans, 4, Gcpy = allocVector(VECSXP, nGivens)); for (i = 0; i < nGivens; i++) SET_VECTOR_ELT(Gcpy, i, VECTOR_ELT(Givens, i)); setAttrib(ans, install("useLAPACK"), ScalarLogical(1)); setAttrib(ans, install("rcond"), ScalarReal(rcond)); UNPROTECT(2); return ans; } #endif /* MJ */ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/utils.h����������������������������������������������������������������������������������0000644�0001751�0000144�00000000640�14504647603�013645� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_UTILS_H #define MATRIX_UTILS_H #include /* size_t */ #include void *Matrix_memset(void *, int, R_xlen_t, size_t); void *Matrix_memcpy(void *, const void *, R_xlen_t, size_t); char *Matrix_sprintf(const char *, ...); int equal_character_vectors(SEXP, SEXP, int); void conjugate(SEXP); void zeroRe(SEXP); void zeroIm(SEXP); void naToOne(SEXP); #endif /* MATRIX_UTILS_H */ ������������������������������������������������������������������������������������������������Matrix/src/version.h��������������������������������������������������������������������������������0000644�0001751�0000144�00000000750�14567652435�014204� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_VERSION_H #define MATRIX_VERSION_H /* (version)_{10} = (major minor patch)_{256} */ #define MATRIX_PACKAGE_VERSION 67328 #define MATRIX_PACKAGE_MAJOR 1 #define MATRIX_PACKAGE_MINOR 7 #define MATRIX_PACKAGE_PATCH 0 #define MATRIX_ABI_VERSION 2 /* (version)_{10} = (major minor patch)_{256} */ #define MATRIX_SUITESPARSE_VERSION 460288 #define MATRIX_SUITESPARSE_MAJOR 7 #define MATRIX_SUITESPARSE_MINOR 6 #define MATRIX_SUITESPARSE_PATCH 0 #endif /* MATRIX_VERSION_H */ ������������������������Matrix/src/subassign.h������������������������������������������������������������������������������0000644�0001751�0000144�00000000546�14574651213�014507� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_SUBASSIGN_H #define MATRIX_SUBASSIGN_H #include SEXP nCsparse_subassign(SEXP, SEXP, SEXP, SEXP); SEXP lCsparse_subassign(SEXP, SEXP, SEXP, SEXP); SEXP iCsparse_subassign(SEXP, SEXP, SEXP, SEXP); SEXP dCsparse_subassign(SEXP, SEXP, SEXP, SEXP); SEXP zCsparse_subassign(SEXP, SEXP, SEXP, SEXP); #endif /* MATRIX_SUBASSIGN_H */ ����������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/cs-etc.c���������������������������������������������������������������������������������0000644�0001751�0000144�00000025207�14516234475�013666� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Mdefines.h" #include "cs-etc.h" int Matrix_cs_xtype; /* flag indicating use of cs_di_* or cs_ci_* */ Matrix_cs *M2CXS(SEXP obj, int values) { Matrix_cs *A = (Matrix_cs *) R_alloc(1, sizeof(Matrix_cs)); memset(A, 0, sizeof(Matrix_cs)); SEXP dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)), p = PROTECT(GET_SLOT(obj, Matrix_pSym)), i = PROTECT(GET_SLOT(obj, Matrix_iSym)), x = PROTECT(getAttrib(obj, Matrix_xSym)); A->m = INTEGER(dim)[0]; A->n = INTEGER(dim)[1]; A->p = INTEGER(p); A->i = INTEGER(i); A->nzmax = LENGTH(i); A->nz = -1; A->xtype = MCS_PATTERN; if (values && x != R_NilValue) { switch (TYPEOF(x)) { case CPLXSXP: A->xtype = MCS_COMPLEX; A->x = COMPLEX(x); break; case REALSXP: A->xtype = MCS_REAL; A->x = REAL(x); break; default: ERROR_INVALID_TYPE(x, __func__); break; } } UNPROTECT(4); return A; } SEXP CXS2M(Matrix_cs *A, int values, char shape) { if (values && A->xtype != MCS_REAL && A->xtype != MCS_COMPLEX) error(_("wrong '%s'"), "xtype"); char cl[] = "..CMatrix"; cl[0] = (!values || A->xtype == MCS_PATTERN) ? 'n' : ((A->xtype == MCS_COMPLEX) ? 'z' : 'd'); cl[1] = shape; int nnz = A->p[A->n]; R_xlen_t np1 = (R_xlen_t) A->n + 1; SEXP obj = PROTECT(newObject(cl)), dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)), p = PROTECT(allocVector(INTSXP, np1)), i = PROTECT(allocVector(INTSXP, nnz)); INTEGER(dim)[0] = A->m; INTEGER(dim)[1] = A->n; Matrix_memcpy(INTEGER(p), A->p, np1, sizeof(int)); Matrix_memcpy(INTEGER(i), A->i, nnz, sizeof(int)); SET_SLOT(obj, Matrix_pSym, p); SET_SLOT(obj, Matrix_iSym, i); if (cl[0] != 'n') { SEXP x; if (cl[0] == 'z') { PROTECT(x = allocVector(CPLXSXP, nnz)); Matrix_memcpy(COMPLEX(x), A->x, nnz, sizeof(Rcomplex)); } else { PROTECT(x = allocVector(REALSXP, nnz)); Matrix_memcpy(REAL(x), A->x, nnz, sizeof(double)); } SET_SLOT(obj, Matrix_xSym, x); UNPROTECT(1); } UNPROTECT(4); return obj; } /* Wrappers for the functions that we use at least once : */ Matrix_csd *Matrix_cs_dfree(Matrix_csd *D) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return (Matrix_csd *) cs_ci_dfree((cs_cid *) D); else return (Matrix_csd *) cs_di_dfree((cs_did *) D); #else return (Matrix_csd *) cs_dfree((csd *) D); #endif } Matrix_csd *Matrix_cs_dmperm(const Matrix_cs *A, int seed) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return (Matrix_csd *) cs_ci_dmperm((cs_ci *) A, seed); else return (Matrix_csd *) cs_di_dmperm((cs_di *) A, seed); #else return (Matrix_csd *) cs_dmperm((cs *) A, seed); #endif } int Matrix_cs_dropzeros(Matrix_cs *A) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return cs_ci_dropzeros((cs_ci *) A); else return cs_di_dropzeros((cs_di *) A); #else return cs_dropzeros((cs *) A); #endif } void *Matrix_cs_free(void *p) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return cs_ci_free(p); else return cs_di_free(p); #else return cs_free(p); #endif } int Matrix_cs_happly(const Matrix_cs *V, int i, double beta, void *x) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return cs_ci_happly((cs_ci *) V, i, beta, (double _Complex *) x); else return cs_di_happly((cs_di *) V, i, beta, (double *) x); #else return cs_happly((cs *) V, i, beta, (double *) x); #endif } int Matrix_cs_ipvec(const int *p, const void *b, void *x, int n) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return cs_ci_ipvec(p, (double _Complex *) b, (double _Complex *) x, n); else return cs_di_ipvec(p, (double *) b, (double *) x, n); #else return cs_ipvec(p, (double *) b, (double *) x, n); #endif } int Matrix_cs_lsolve(const Matrix_cs *L, void *x) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return cs_ci_lsolve((cs_ci *) L, (double _Complex *) x); else return cs_di_lsolve((cs_di *) L, (double *) x); #else return cs_lsolve((cs *) L, (double *) x); #endif } Matrix_csn *Matrix_cs_lu(const Matrix_cs *A, const Matrix_css *S, double tol) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return (Matrix_csn *) cs_ci_lu((cs_ci *) A, (cs_cis *) S, tol); else return (Matrix_csn *) cs_di_lu((cs_di *) A, (cs_dis *) S, tol); #else return (Matrix_csn *) cs_lu((cs *) A, (css *) S, tol); #endif } int Matrix_cs_lusol(int order, const Matrix_cs *A, void *b, double tol) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return cs_ci_lusol(order, (cs_ci *) A, (double _Complex *) b, tol); else return cs_di_lusol(order, (cs_di *) A, (double *) b, tol); #else return cs_lusol(order, (cs *) A, (double *) b, tol); #endif } Matrix_csn *Matrix_cs_nfree(Matrix_csn *N) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return (Matrix_csn *) cs_ci_nfree((cs_cin *) N); else return (Matrix_csn *) cs_di_nfree((cs_din *) N); #else return (Matrix_csn *) cs_nfree((csn *) N); #endif } Matrix_cs *Matrix_cs_permute(const Matrix_cs *A, const int *pinv, const int *q, int values) { Matrix_cs *B = NULL; #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) { cs_ci *tmp = cs_ci_permute((cs_ci *) A, pinv, q, values); B = (Matrix_cs *) cs_ci_calloc(1, sizeof(Matrix_cs)); memcpy(B, tmp, sizeof(cs_ci)); tmp = cs_ci_free(tmp); } else { cs_di *tmp = cs_di_permute((cs_di *) A, pinv, q, values); B = (Matrix_cs *) cs_di_calloc(1, sizeof(Matrix_cs)); memcpy(B, tmp, sizeof(cs_di)); tmp = cs_di_free(tmp); } #else cs *tmp = cs_permute((cs *) A, pinv, q, values); B = (Matrix_cs *) cs_calloc(1, sizeof(Matrix_cs)); memcpy(B, tmp, sizeof(cs )); tmp = cs_free(tmp); #endif B->xtype = MCS_XTYPE_GET(); return B; } int *Matrix_cs_pinv(const int *p, int n) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return cs_ci_pinv(p, n); else return cs_di_pinv(p, n); #else return cs_pinv(p, n); #endif } int Matrix_cs_pvec(const int *p, const void *b, void *x, int n) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return cs_ci_pvec(p, (double _Complex *) b, (double _Complex *) x, n); else return cs_di_pvec(p, (double *) b, (double *) x, n); #else return cs_pvec(p, (double *) b, (double *) x, n); #endif } Matrix_csn *Matrix_cs_qr(const Matrix_cs *A, const Matrix_css *S) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return (Matrix_csn *) cs_ci_qr((cs_ci *) A, (cs_cis *) S); else return (Matrix_csn *) cs_di_qr((cs_di *) A, (cs_dis *) S); #else return (Matrix_csn *) cs_qr((cs *) A, (css *) S); #endif } int Matrix_cs_qrsol(int order, const Matrix_cs *A, void *b) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return cs_ci_qrsol(order, (cs_ci *) A, (double _Complex *) b); else return cs_di_qrsol(order, (cs_di *) A, (double *) b); #else return cs_qrsol(order, (cs *) A, (double *) b); #endif } Matrix_css *Matrix_cs_sfree(Matrix_css *S) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return (Matrix_css *) cs_ci_sfree((cs_cis *) S); else return (Matrix_css *) cs_di_sfree((cs_dis *) S); #else return (Matrix_css *) cs_sfree((css *) S); #endif } Matrix_cs *Matrix_cs_spalloc(int m, int n, int nzmax, int values, int triplet) { Matrix_cs *B = NULL; #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) { cs_ci *tmp = cs_ci_spalloc(m, n, nzmax, values, triplet); B = (Matrix_cs *) cs_ci_calloc(1, sizeof(Matrix_cs)); memcpy(B, tmp, sizeof(cs_ci)); tmp = cs_ci_free(tmp); } else { cs_di *tmp = cs_di_spalloc(m, n, nzmax, values, triplet); B = (Matrix_cs *) cs_di_calloc(1, sizeof(Matrix_cs)); memcpy(B, tmp, sizeof(cs_di)); tmp = cs_di_free(tmp); } #else cs *tmp = cs_spalloc(m, n, nzmax, values, triplet); B = (Matrix_cs *) cs_calloc(1, sizeof(Matrix_cs)); memcpy(B, tmp, sizeof(cs )); tmp = cs_free(tmp); #endif B->xtype = MCS_XTYPE_GET(); return B; } Matrix_cs *Matrix_cs_speye(int m, int n, int values, int triplet) { int k, d = (m < n) ? m : n; Matrix_cs *B = Matrix_cs_spalloc(m, n, d, values, triplet); if (!B) return NULL; int *B__p = B->p, *B__i = B->i; for (k = 0; k < d; ++k) B__p[k] = B__i[k] = k; if (!triplet) for (k = d; k <= n; ++k) B__p[k] = d; if (values) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) { double _Complex *B__x = (double _Complex *) B->x; for (k = 0; k < d; ++k) B__x[k] = 1.0; } else { #endif double *B__x = (double *) B->x; for (k = 0; k < d; ++k) B__x[k] = 1.0; #ifdef CXSPARSE } #endif } return B; } Matrix_cs *Matrix_cs_spfree(Matrix_cs *A) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return (Matrix_cs *) cs_ci_spfree((cs_ci *) A); else return (Matrix_cs *) cs_di_spfree((cs_di *) A); #else return (Matrix_cs *) cs_spfree((cs *) A); #endif } int Matrix_cs_sprealloc(Matrix_cs *A, int nzmax) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return cs_ci_sprealloc((cs_ci *) A, nzmax); else return cs_di_sprealloc((cs_di *) A, nzmax); #else return cs_sprealloc((cs *) A, nzmax); #endif } int Matrix_cs_spsolve(Matrix_cs *L, const Matrix_cs *B, int k, int *xi, void *x, const int *pinv, int lo) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return cs_ci_spsolve((cs_ci *) L, (cs_ci *) B, k, xi, (double _Complex *) x, pinv, lo); else return cs_di_spsolve((cs_di *) L, (cs_di *) B, k, xi, (double *) x, pinv, lo); #else return cs_spsolve((cs *) L, (cs *) B, k, xi, (double *) x, pinv, lo); #endif } Matrix_css *Matrix_cs_sqr(int order, const Matrix_cs *A, int qr) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return (Matrix_css *) cs_ci_sqr(order, (cs_ci *) A, qr); else return (Matrix_css *) cs_di_sqr(order, (cs_di *) A, qr); #else return (Matrix_css *) cs_sqr(order, (cs *) A, qr); #endif } Matrix_cs *Matrix_cs_transpose(const Matrix_cs *A, int values) { Matrix_cs *B = NULL; #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) { cs_ci *tmp = cs_ci_transpose((cs_ci *) A, values); B = (Matrix_cs *) cs_ci_calloc(1, sizeof(Matrix_cs)); memcpy(B, tmp, sizeof(cs_ci)); tmp = cs_ci_free(tmp); } else { cs_di *tmp = cs_di_transpose((cs_di *) A, values); B = (Matrix_cs *) cs_di_calloc(1, sizeof(Matrix_cs)); memcpy(B, tmp, sizeof(cs_di)); tmp = cs_di_free(tmp); } #else cs *tmp = cs_transpose((cs *) A, values); B = (Matrix_cs *) cs_calloc(1, sizeof(Matrix_cs)); memcpy(B, tmp, sizeof(cs )); tmp = cs_free(tmp); #endif B->xtype = MCS_XTYPE_GET(); return B; } int Matrix_cs_usolve(const Matrix_cs *U, void *x) { #ifdef CXSPARSE if (MCS_XTYPE_GET() == MCS_COMPLEX) return cs_ci_usolve((cs_ci *) U, (double _Complex *) x); else return cs_di_usolve((cs_di *) U, (double *) x); #else return cs_usolve((cs *) U, (double *) x); #endif } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/sparse.h���������������������������������������������������������������������������������0000644�0001751�0000144�00000002707�14503212600�013770� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_SPARSE_H #define MATRIX_SPARSE_H #include SEXP sparse_drop0(SEXP, const char *, double); SEXP R_sparse_drop0(SEXP, SEXP); SEXP sparse_diag_U2N(SEXP, const char *); SEXP R_sparse_diag_U2N(SEXP); SEXP sparse_diag_N2U(SEXP, const char *); SEXP R_sparse_diag_N2U(SEXP); SEXP sparse_band(SEXP, const char *, int, int); SEXP R_sparse_band(SEXP, SEXP, SEXP); SEXP sparse_diag_get(SEXP, const char *, int); SEXP R_sparse_diag_get(SEXP, SEXP); SEXP sparse_diag_set(SEXP, const char *, SEXP); SEXP R_sparse_diag_set(SEXP, SEXP); SEXP sparse_transpose(SEXP, const char *, int); SEXP R_sparse_transpose(SEXP, SEXP); SEXP sparse_force_symmetric(SEXP, const char *, char); SEXP R_sparse_force_symmetric(SEXP, SEXP); SEXP sparse_symmpart(SEXP, const char *); SEXP R_sparse_symmpart(SEXP); SEXP sparse_skewpart(SEXP, const char *); SEXP R_sparse_skewpart(SEXP); int sparse_is_symmetric(SEXP, const char *, int); SEXP R_sparse_is_symmetric(SEXP, SEXP); int sparse_is_triangular(SEXP, const char *, int); SEXP R_sparse_is_triangular(SEXP, SEXP); int sparse_is_diagonal(SEXP, const char *); SEXP R_sparse_is_diagonal(SEXP); SEXP sparse_marginsum(SEXP, const char *, int, int, int, int); SEXP R_sparse_marginsum(SEXP, SEXP, SEXP, SEXP, SEXP); SEXP sparse_sum(SEXP, const char *, int); SEXP R_sparse_sum(SEXP, SEXP); SEXP sparse_prod(SEXP, const char *, int); SEXP R_sparse_prod(SEXP, SEXP); SEXP Tsparse_aggregate(SEXP); #endif /* MATRIX_SPARSE_H */ ���������������������������������������������������������Matrix/src/objects.h��������������������������������������������������������������������������������0000644�0001751�0000144�00000000342�14511521056�014124� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_OBJECTS_H #define MATRIX_OBJECTS_H #include SEXP R_Matrix_nonvirtual(SEXP, SEXP); SEXP R_Matrix_kind (SEXP); SEXP R_Matrix_shape(SEXP); SEXP R_Matrix_repr (SEXP); #endif /* MATRIX_OBJECTS_H */ ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/Lapack-etc.h�����������������������������������������������������������������������������0000644�0001751�0000144�00000003757�14510016544�014454� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_LAPACK_ETC_H #define MATRIX_LAPACK_ETC_H /* Copy and paste from WRE : */ // before any R headers, or define in PKG_CPPFLAGS #ifndef USE_FC_LEN_T # define USE_FC_LEN_T #endif #include #ifdef PR18534fixed # define usePR18534fix #endif #include #ifndef FCONE # define FCONE #endif #define ERROR_LAPACK_1(_ROUTINE_, _INFO_) \ do { \ if ((_INFO_) < 0) \ error(_("LAPACK routine '%s': argument %d had illegal value"), \ #_ROUTINE_, -(_INFO_)); \ } while (0) #define ERROR_LAPACK_2(_ROUTINE_, _INFO_, _WARN_, _LETTER_) \ do { \ ERROR_LAPACK_1(_ROUTINE_, _INFO_); \ if ((_INFO_) > 0 && (_WARN_) > 0) { \ if (_WARN_ > 1) \ error (_("LAPACK routine '%s': matrix is exactly singular, %s[i,i]=0, i=%d"), \ #_ROUTINE_, #_LETTER_, (_INFO_)); \ else \ warning(_("LAPACK routine '%s': matrix is exactly singular, %s[i,i]=0, i=%d"), \ #_ROUTINE_, #_LETTER_, (_INFO_)); \ } \ } while (0) #define ERROR_LAPACK_3(_ROUTINE_, _INFO_, _WARN_, _NPROTECT_) \ do { \ ERROR_LAPACK_1(_ROUTINE_, _INFO_); \ if ((_INFO_) > 0 && (_WARN_) > 0) { \ if (_WARN_ > 1) \ error (_("LAPACK routine '%s': leading principal minor of order %d is not positive"), \ #_ROUTINE_, (_INFO_)); \ else { \ warning(_("LAPACK routine '%s': leading principal minor of order %d is not positive"), \ #_ROUTINE_, (_INFO_)); \ UNPROTECT(_NPROTECT_); \ return ScalarInteger(_INFO_); \ } \ } \ } while (0) #define ERROR_LAPACK_4(_ROUTINE_, _INFO_, _RANK_, _WARN_) \ do { \ ERROR_LAPACK_1(_ROUTINE_, _INFO_); \ if ((_INFO_) > 0 && (_WARN_) > 0) { \ if (_WARN_ > 1) \ error (_("LAPACK routine '%s': matrix is rank deficient or not positive definite, the _computed_ rank is %d"), \ #_ROUTINE_, (_RANK_)); \ else \ warning(_("LAPACK routine '%s': matrix is rank deficient or not positive definite, the _computed_ rank is %d"), \ #_ROUTINE_, (_RANK_)); \ } \ } while (0) #endif /* MATRIX_LAPACK_ETC_H */ �����������������Matrix/src/subassign.c������������������������������������������������������������������������������0000644�0001751�0000144�00000001001�14575137654�014476� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Mdefines.h" #include "subassign.h" enum x_slot_kind { x_unknown = -2, /* NA */ x_pattern = -1, /* n */ x_double = 0, /* d */ x_logical = 1, /* l */ x_integer = 2, /* i */ x_complex = 3}; /* z */ /* x[i, j] <- value where x=<.[gt]CMatrix> and value=<.sparseVector> */ #define _n_Csp_ #include "t_subassign.c" #define _l_Csp_ #include "t_subassign.c" #define _i_Csp_ #include "t_subassign.c" #define _d_Csp_ #include "t_subassign.c" #define _z_Csp_ #include "t_subassign.c" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/Csparse.c��������������������������������������������������������������������������������0000644�0001751�0000144�00000025666�14575137654�014127� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Mdefines.h" #include "cs-etc.h" #include "cholmod-etc.h" #include "Csparse.h" /* .validateCsparse(x, sort.if.needed = TRUE) */ SEXP CsparseMatrix_validate_maybe_sorting(SEXP x) { #define MKMS(_FORMAT_, ...) mkString(Matrix_sprintf(_FORMAT_, __VA_ARGS__)) /* defined in ./cholmod-common.c : */ SEXP checkpi(SEXP p, SEXP i, int m, int n); SEXP dim = GET_SLOT(x, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; SEXP p = PROTECT(GET_SLOT(x, Matrix_pSym)), i = PROTECT(GET_SLOT(x, Matrix_iSym)), cpi = PROTECT(checkpi(p, i, m, n)); if (TYPEOF(cpi) == LGLSXP && !LOGICAL(cpi)[0]) { cholmod_sparse *A = M2CHS(x, 1); A->sorted = 0; if (!cholmod_sort(A, &c)) error(_("'%s' failed"), "cholmod_sort"); int *pp = (int *) A->p, *pi = (int *) A->i, i0, ik, j, k, kend; for (j = 1, k = 0; j <= n; ++j) { kend = pp[j]; i0 = -1; while (k < kend) { ik = pi[k]; if (ik <= i0) { UNPROTECT(3); /* cpi, i, p */ return MKMS(_("'%s' slot is not increasing within columns after sorting"), "i"); } i0 = ik; ++k; } } LOGICAL(cpi)[0] = 1; } UNPROTECT(3); /* cpi, i, p */ return cpi; } /* TODO: support NCOL(b) > 1 */ SEXP dgCMatrix_lusol(SEXP a, SEXP b) { Matrix_cs *A = M2CXS(a, 1); MCS_XTYPE_SET(MCS_REAL); PROTECT(b = (TYPEOF(b) == REALSXP) ? duplicate(b) : coerceVector(b, REALSXP)); if (A->m != A->n || A->m <= 0) error(_("'%s' is empty or not square"), "a"); if (LENGTH(b) != A->m) error(_("dimensions of '%s' and '%s' are inconsistent"), "a", "b"); if (!Matrix_cs_lusol(1, A, REAL(b), 1e-07)) error(_("'%s' failed"), "cs_lusol"); UNPROTECT(1); return b; } /* called from package MatrixModels's R code : */ /* TODO: support NCOL(b) > 1 */ /* TODO: give result list(L, coef, Xty, resid) */ SEXP dgCMatrix_qrsol(SEXP a, SEXP b, SEXP order) { /* FIXME? 'cs_qrsol' supports underdetermined systems. */ /* We should only require LENGTH(b) = max(m, n). */ int order_ = asInteger(order); if (order_ < 0 || order_ > 3) order_ = 0; Matrix_cs *A = M2CXS(a, 1); MCS_XTYPE_SET(MCS_REAL); PROTECT(b = (TYPEOF(b) == REALSXP) ? duplicate(b) : coerceVector(b, REALSXP)); if (LENGTH(b) != A->m) error(_("dimensions of '%s' and '%s' are inconsistent"), "a", "b"); if (A->n <= 0 || A->n > A->m) error(_("%s(%s, %s) requires m-by-n '%s' with m >= n > 0"), "dgCMatrix_qrsol", "a", "b", "a"); if (!Matrix_cs_qrsol(order_, A, REAL(b))) error(_("'%s' failed"), "cs_qrsol"); if (A->n < A->m) { SEXP tmp = allocVector(REALSXP, A->n); Matrix_memcpy(REAL(tmp), REAL(b), A->n, sizeof(double)); b = tmp; } UNPROTECT(1); return b; } /* called from package MatrixModels's R code : */ /* TODO: support NCOL(b) > 1 */ SEXP dgCMatrix_cholsol(SEXP at, SEXP b) { /* Find least squares solution of A * X = B, given A' and B : */ cholmod_sparse *At = M2CHS(at, 1); PROTECT(b = coerceVector(b, REALSXP)); if (LENGTH(b) != At->ncol) error(_("dimensions of '%s' and '%s' are inconsistent"), "at", "b"); if (At->ncol <= 0 || At->ncol < At->nrow) error(_("%s(%s, %s) requires m-by-n '%s' with n >= m > 0"), "dgCMatrix_cholsol", "at", "b", "at"); double zero[] = { 0.0, 0.0 }, one[] = {1.0, 0.0}, mone[] = { -1.0, 0.0 }; /* L * L' = A' * A */ cholmod_factor *L = cholmod_analyze(At, &c); if (!cholmod_factorize(At, L, &c)) error(_("'%s' failed"), "cholmod_factorize"); cholmod_dense *B = (cholmod_dense *) R_alloc(1, sizeof(cholmod_dense)); memset(B, 0, sizeof(cholmod_dense)); B->nrow = B->d = B->nzmax = LENGTH(b); B->ncol = 1; B->x = REAL(b); B->dtype = CHOLMOD_DOUBLE; B->xtype = CHOLMOD_REAL; /* A' * B = 1 * A' * B + 0 * */ cholmod_dense *AtB = cholmod_allocate_dense( At->nrow, 1, At->nrow, CHOLMOD_REAL, &c); if (!cholmod_sdmult(At, 0, one, zero, B, AtB, &c)) error(_("'%s' failed"), "cholmod_sdmult"); /* C := solve(A' * A, A' * B) = solve(L', solve(L, A' * B)) */ cholmod_dense *C = cholmod_solve(CHOLMOD_A, L, AtB, &c); if (!C) error(_("'%s' failed"), "cholmod_solve"); /* R := A * A' * C - B = 1 * (A')' * A' * X + (-1) * B */ cholmod_dense *R = cholmod_copy_dense(B, &c); if (!cholmod_sdmult(At, 1, mone, one, C, R, &c)) error(_("'%s' failed"), "cholmod_sdmult"); const char *nms[] = {"L", "coef", "Xty", "resid", ""}; SEXP ans = PROTECT(Rf_mkNamed(VECSXP, nms)), tmp; /* L : */ PROTECT(tmp = CHF2M(L, 1)); SET_VECTOR_ELT(ans, 0, tmp); /* coef : */ PROTECT(tmp = allocVector(REALSXP, At->nrow)); Matrix_memcpy(REAL(tmp), C->x, At->nrow, sizeof(double)); SET_VECTOR_ELT(ans, 1, tmp); /* Xty : */ PROTECT(tmp = allocVector(REALSXP, At->nrow)); Matrix_memcpy(REAL(tmp), AtB->x, At->nrow, sizeof(double)); SET_VECTOR_ELT(ans, 2, tmp); /* resid : */ PROTECT(tmp = allocVector(REALSXP, At->ncol)); Matrix_memcpy(REAL(tmp), R->x, At->ncol, sizeof(double)); SET_VECTOR_ELT(ans, 3, tmp); cholmod_free_factor(& L, &c); cholmod_free_dense (&AtB, &c); cholmod_free_dense (& C, &c); cholmod_free_dense (& R, &c); UNPROTECT(6); return ans; } static int strmatch(const char *x, const char **valid) { int i = 0; while (valid[i][0] != '\0') { if (strcmp(x, valid[i]) == 0) return i; ++i; } return -1; } /* (diag(obj)) where obj=dCHMsimpl (LDLt) or obj=dtCMatrix (nonunit) */ SEXP dtCMatrix_diag(SEXP obj, SEXP op) { static const char *valid[] = { /* 0 */ "trace", /* 1 */ "sumLog", /* 2 */ "prod", /* 3 */ "min", /* 4 */ "max", /* 5 */ "range", /* 6 */ "diag", /* 7 */ "diagBack", ""}; int ivalid = -1; if (TYPEOF(op) != STRSXP || LENGTH(op) < 1 || (op = STRING_ELT(op, 0)) == NA_STRING || (ivalid = strmatch(CHAR(op), valid)) < 0) error(_("invalid '%s' to '%s'"), "op", __func__); SEXP uplo = getAttrib(obj, Matrix_uploSym); char ul = (TYPEOF(uplo) == STRSXP && LENGTH(uplo) > 0) ? *CHAR(STRING_ELT(uplo, 0)) : 'L'; SEXP p = PROTECT(GET_SLOT(obj, Matrix_pSym)); int *pp = INTEGER(p) + 1, j, k = 0, kend, n = (int) (XLENGTH(p) - 1), len = (ivalid < 5) ? 1 : ((ivalid < 6) ? 2 : n); SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)); double *px = REAL(x), tmp; SEXP ans = PROTECT(allocVector(REALSXP, len)); double *pans = REAL(ans); switch (ivalid) { case 0: /* trace */ pans[0] = 0.0; for (j = 0; j < n; ++j) { kend = pp[j]; if (k < kend) pans[0] += px[(ul == 'U') ? kend - 1 : k]; k = kend; } break; case 1: /* sumLog */ pans[0] = 0.0; for (j = 0; j < n; ++j) { kend = pp[j]; if (k < kend) pans[0] += log(px[(ul == 'U') ? kend - 1 : k]); k = kend; } break; case 2: /* prod */ pans[0] = 1.0; for (j = 0; j < n; ++j) { kend = pp[j]; if (k < kend) pans[0] *= px[(ul == 'U') ? kend - 1 : k]; else pans[0] *= 0.0; k = kend; } break; case 3: /* min */ pans[0] = R_PosInf; for (j = 0; j < n; ++j) { kend = pp[j]; tmp = (k < kend) ? px[(ul == 'U') ? kend - 1 : k] : 0.0; if (ISNAN(tmp)) { pans[0] = tmp; break; } else if (tmp < pans[0]) pans[0] = tmp; k = kend; } break; case 4: /* max */ pans[0] = R_NegInf; for (j = 0; j < n; ++j) { kend = pp[j]; tmp = (k < kend) ? px[(ul == 'U') ? kend - 1 : k] : 0.0; if (ISNAN(tmp)) { pans[0] = tmp; break; } else if (tmp > pans[0]) pans[0] = tmp; k = kend; } break; case 5: /* range */ pans[0] = R_PosInf; pans[1] = R_NegInf; for (j = 0; j < n; ++j) { kend = pp[j]; tmp = (k < kend) ? px[(ul == 'U') ? kend - 1 : k] : 0.0; if (ISNAN(tmp)) { pans[0] = pans[1] = tmp; break; } else if (tmp < pans[0]) pans[0] = tmp; else if (tmp > pans[1]) pans[1] = tmp; k = kend; } break; case 6: /* diag */ case 7: /* diagBack */ { int *pperm = NULL; if (ivalid == 7) { SEXP perm = getAttrib(obj, Matrix_permSym); if (TYPEOF(perm) == INTSXP && LENGTH(perm) == n) pperm = INTEGER(perm); } for (j = 0; j < n; ++j) { kend = pp[j]; pans[(pperm) ? pperm[j] : j] = (k < kend) ? px[(ul == 'U') ? kend - 1 : k] : 0.0; k = kend; } break; } default: break; } UNPROTECT(3); return ans; } /* dmperm(x, nAns, seed) */ SEXP Csparse_dmperm(SEXP x, SEXP nans, SEXP seed) { Matrix_cs *A = M2CXS(x, 0); MCS_XTYPE_SET(A->xtype); Matrix_csd *D = Matrix_cs_dmperm(A, asInteger(seed)); if (!D) return R_NilValue; /* MJ: why not an error ... ? */ int len = asInteger(nans); if (len < 0) len = 0; else if (len > 6) len = 6; SEXP nms = PROTECT(allocVector(STRSXP, len)), ans = PROTECT(allocVector(VECSXP, len)), tmp; int k = len - 1; switch (len) { case 6: SET_STRING_ELT(nms, k, mkChar("cc5")); tmp = allocVector(INTSXP, 5); memcpy(INTEGER(tmp), D->cc, 5 * sizeof(int)); SET_VECTOR_ELT(ans, k, tmp); k--; case 5: SET_STRING_ELT(nms, k, mkChar("rr5")); tmp = allocVector(INTSXP, 5); memcpy(INTEGER(tmp), D->rr, 5 * sizeof(int)); SET_VECTOR_ELT(ans, k, tmp); k--; case 4: SET_STRING_ELT(nms, k, mkChar("s")); tmp = allocVector(INTSXP, D->nb + 1); memcpy(INTEGER(tmp), D->s, (D->nb + 1) * sizeof(int)); SET_VECTOR_ELT(ans, k, tmp); k--; case 3: SET_STRING_ELT(nms, k, mkChar("r")); tmp = allocVector(INTSXP, D->nb + 1); memcpy(INTEGER(tmp), D->r, (D->nb + 1) * sizeof(int)); SET_VECTOR_ELT(ans, k, tmp); k--; case 2: SET_STRING_ELT(nms, k, mkChar("q")); tmp = allocVector(INTSXP, A->n); for (int j = 0, *q0 = D->q, *q1 = INTEGER(tmp); j < A->n; ++j) q1[j] = q0[j] + 1; SET_VECTOR_ELT(ans, k, tmp); k--; case 1: SET_STRING_ELT(nms, k, mkChar("p")); tmp = allocVector(INTSXP, A->m); for (int i = 0, *p0 = D->p, *p1 = INTEGER(tmp); i < A->m; ++i) p1[i] = p0[i] + 1; SET_VECTOR_ELT(ans, k, tmp); k--; default: break; } D = Matrix_cs_dfree(D); setAttrib(ans, R_NamesSymbol, nms); UNPROTECT(2); return ans; } /* writeMM(obj, file) */ SEXP Csparse_writeMM(SEXP obj, SEXP file) { static const char *valid[] = { VALID_CSPARSE, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) ERROR_INVALID_CLASS(obj, __func__); const char *class = valid[ivalid]; PROTECT_INDEX pid; PROTECT_WITH_INDEX(obj, &pid); if (class[0] == 'l' || class[1] == 'i') { /* defined in ./coerce.c : */ SEXP sparse_as_kind(SEXP, const char *, char); REPROTECT(obj = sparse_as_kind(obj, class, 'd'), pid); class = valid[R_check_class_etc(obj, valid)]; } if (class[1] == 't') { /* defined in ./coerce.c : */ SEXP sparse_as_general(SEXP, const char *); REPROTECT(obj = sparse_as_general(obj, class), pid); class = valid[R_check_class_etc(obj, valid)]; } cholmod_sparse *A = M2CHS(obj, 1); if (class[1] == 's') { SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); A->stype = (ul == 'U') ? 1 : -1; } const char *filename = CHAR(asChar(file)); FILE *f = fopen(filename, "w"); if (!f) error(_("failed to open file \"%s\" for writing"), filename); if (!cholmod_write_sparse(f, A, (cholmod_sparse *) NULL, (char *) NULL, &c)) error(_("'%s' failed"), "cholmod_write_sparse"); fclose(f); UNPROTECT(1); return R_NilValue; } ��������������������������������������������������������������������������Matrix/src/Makevars���������������������������������������������������������������������������������0000644�0001751�0000144�00000002314�14552026002�014013� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ssdir = SuiteSparse sslib = $(sslib1) $(sslib2) $(sslib3) $(sslib4) $(sslib5) $(sslib6) $(sslib7) sslib1 = $(ssdir)/CHOLMOD/CHOLMOD.a sslib2 = $(ssdir)/CCOLAMD/CCOLAMD.a sslib3 = $(ssdir)/CAMD/CAMD.a sslib4 = $(ssdir)/COLAMD/COLAMD.a sslib5 = $(ssdir)/AMD/AMD.a sslib6 = $(ssdir)/CXSparse/CXSparse.a sslib7 = $(ssdir)/SuiteSparse_config/SuiteSparse_config.a ssenv = \ CC="$(CC)" \ CPPFLAGS="$(CPPFLAGS) -I\"$(R_INCLUDE_DIR)\" -DNDEBUG -DNPRINT -DNTIMER" \ CFLAGS="$(CFLAGS) $(CPICFLAGS) $(C_VISIBILITY)" \ AR="$(AR)" \ RANLIB="$(RANLIB)" PKG_CPPFLAGS = -I"$(ssdir)/SuiteSparse_config" PKG_CFLAGS = $(C_VISIBILITY) PKG_LIBS = $(sslib) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) $(SHLIB): $(sslib) ## NB: INSTALL does not clean subdirectories between subarchitectures $(sslib1) : cd $(@D) && $(MAKE) clean all $(ssenv) $(sslib2) : cd $(@D) && $(MAKE) clean all $(ssenv) $(sslib3) : cd $(@D) && $(MAKE) clean all $(ssenv) $(sslib4) : cd $(@D) && $(MAKE) clean all $(ssenv) $(sslib5) : cd $(@D) && $(MAKE) clean all $(ssenv) $(sslib6) : cd $(@D) && $(MAKE) clean all $(ssenv) $(sslib7) : cd $(@D) && $(MAKE) clean all $(ssenv) include ../inst/scripts/sources.mk OBJECTS = $(sources:.c=.o) include ../inst/scripts/rules.mk ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/bind.h�����������������������������������������������������������������������������������0000644�0001751�0000144�00000000165�14503212600�013403� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_BIND_H #define MATRIX_BIND_H #include SEXP R_bind(SEXP); #endif /* MATRIX_BIND_H */ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/perm.c�����������������������������������������������������������������������������������0000644�0001751�0000144�00000010205�14503225712�013431� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Mdefines.h" #include "perm.h" int isPerm(const int *p, int n, int off) { int res = 1; if (n <= 0) return res; int i, j; char *work; Matrix_Calloc(work, n, char); for (i = 0; i < n; ++i) { if (p[i] == NA_INTEGER || (j = p[i] - off) < 0 || j >= n || work[j]) { res = 0; break; } work[j] = 1; } Matrix_Free(work, n); return res; } int signPerm(const int *p, int n, int off) { if (!isPerm(p, n, off)) error(_("attempt to get sign of non-permutation")); int sign = 1; if (n <= 0) return sign; int i, pos = 0; char *work; Matrix_Calloc(work, n, char); while (pos < n) { work[pos] = 1; i = p[pos] - off; while (!work[i]) { /* transposition */ sign = -sign; work[i] = 1; i = p[i] - off; } while (pos < n && work[pos]) ++pos; } Matrix_Free(work, n); return sign; } void invertPerm(const int *p, int *ip, int n, int off, int ioff) { if (!isPerm(p, n, off)) error(_("attempt to invert non-permutation")); int j; for (j = 0; j < n; ++j) ip[p[j] - off] = j + ioff; return; } void asPerm(const int *p, int *ip, int m, int n, int off, int ioff) { int i, j, tmp; for (i = 0; i < n; ++i) ip[i] = i + ioff; for (i = 0; i < m; ++i) { j = p[i] - off; if (j < 0 || j >= n) error(_("invalid transposition vector")); if (j != i) { tmp = ip[j]; ip[j] = ip[i]; ip[i] = tmp; } } return; } SEXP R_isPerm(SEXP p, SEXP off) { if (TYPEOF(p) != INTSXP) error(_("'%s' is not of type \"%s\""), "p", "integer"); if (TYPEOF(off) != INTSXP) error(_("'%s' is not of type \"%s\""), "off", "integer"); if (XLENGTH(off) != 1) error(_("'%s' does not have length %d"), "off", 1); int off_ = INTEGER(off)[0]; if (off_ == NA_INTEGER) error(_("'%s' is NA"), "off"); R_xlen_t n_ = XLENGTH(p); if (n_ > INT_MAX) return ScalarLogical(0); return ScalarLogical(isPerm(INTEGER(p), (int) n_, off_)); } SEXP R_signPerm(SEXP p, SEXP off) { if (TYPEOF(p) != INTSXP) error(_("'%s' is not of type \"%s\""), "p", "integer"); if (TYPEOF(off) != INTSXP) error(_("'%s' is not of type \"%s\""), "off", "integer"); if (XLENGTH(off) != 1) error(_("'%s' does not have length %d"), "off", 1); int off_ = INTEGER(off)[0]; if (off_ == NA_INTEGER) error(_("'%s' is NA"), "off"); R_xlen_t n_ = XLENGTH(p); if (n_ > INT_MAX) error(_("attempt to get sign of non-permutation")); return ScalarInteger(signPerm(INTEGER(p), (int) n_, off_)); } SEXP R_invertPerm(SEXP p, SEXP off, SEXP ioff) { if (TYPEOF(p) != INTSXP) error(_("'%s' is not of type \"%s\""), "p", "integer"); if (TYPEOF(off) != INTSXP || TYPEOF(ioff) != INTSXP) error(_("'%s' or '%s' is not of type \"%s\""), "off", "ioff", "integer"); if (XLENGTH(off) != 1 || XLENGTH(ioff) != 1) error(_("'%s' or '%s' does not have length %d"), "off", "ioff", 1); int off_ = INTEGER(off)[0], ioff_ = INTEGER(ioff)[0]; if (off_ == NA_INTEGER || ioff_ == NA_INTEGER) error(_("'%s' or '%s' is NA"), "off", "ioff"); R_xlen_t n_ = XLENGTH(p); if (n_ > INT_MAX) error(_("attempt to invert non-permutation")); SEXP ip = PROTECT(allocVector(INTSXP, n_)); invertPerm(INTEGER(p), INTEGER(ip), (int) n_, off_, ioff_); UNPROTECT(1); return ip; } SEXP R_asPerm(SEXP p, SEXP off, SEXP ioff, SEXP n) { if (TYPEOF(p) != INTSXP) error(_("'%s' is not of type \"%s\""), "p", "integer"); R_xlen_t m_ = XLENGTH(p); if (m_ > INT_MAX) error(_("'%s' has length exceeding %s"), "p", "2^31-1"); if (TYPEOF(off) != INTSXP || TYPEOF(ioff) != INTSXP) error(_("'%s' or '%s' is not of type \"%s\""), "off", "ioff", "integer"); if (XLENGTH(off) != 1 || XLENGTH(ioff) != 1) error(_("'%s' or '%s' does not have length %d"), "off", "ioff", 1); int off_ = INTEGER(off)[0], ioff_ = INTEGER(ioff)[0]; if (off_ == NA_INTEGER || ioff_ == NA_INTEGER) error(_("'%s' or '%s' is NA"), "off", "ioff"); if (TYPEOF(n) != INTSXP) error(_("'%s' is not of type \"%s\""), "n", "integer"); if (XLENGTH(n) != 1) error(_("'%s' does not have length %d"), "n", 1); int n_ = INTEGER(n)[0]; if (n_ == NA_INTEGER || n_ < m_) error(_("'%s' is NA or less than %s"), "n", "length(p)"); SEXP ip = PROTECT(allocVector(INTSXP, n_)); asPerm(INTEGER(p), INTEGER(ip), (int) m_, n_, off_, ioff_); UNPROTECT(1); return ip; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/matmult.h��������������������������������������������������������������������������������0000644�0001751�0000144�00000000413�14575137654�014176� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_MATMULT_H #define MATRIX_MATMULT_H #include SEXP R_dense_matmult(SEXP, SEXP, SEXP, SEXP); SEXP R_sparse_matmult(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); SEXP R_diagonal_matmult(SEXP, SEXP, SEXP, SEXP, SEXP); #endif /* MATRIX_MATMULT_H */ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/objects.c��������������������������������������������������������������������������������0000644�0001751�0000144�00000006412�14574756126�014144� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Mdefines.h" #include "objects.h" SEXP newObject(const char *what) { SEXP class = PROTECT(R_do_MAKE_CLASS(what)), obj = R_do_new_object(class); UNPROTECT(1); return obj; } char typeToKind(SEXPTYPE type) { switch (type) { case LGLSXP: return 'l'; case INTSXP: return 'i'; case REALSXP: return 'd'; case CPLXSXP: return 'z'; default: error(_("unexpected type \"%s\" in '%s'"), type2char(type), __func__); return '\0'; } } SEXPTYPE kindToType(char kind) { switch (kind) { case 'n': case 'l': return LGLSXP; case 'i': return INTSXP; case 'd': return REALSXP; case 'z': return CPLXSXP; default: error(_("unexpected kind \"%c\" in '%s'"), kind, __func__); return NILSXP; } } size_t kindToSize(char kind) { switch (kind) { case 'n': case 'l': case 'i': return sizeof(int); case 'd': return sizeof(double); case 'z': return sizeof(Rcomplex); default: error(_("unexpected kind \"%c\" in '%s'"), kind, __func__); return 0; } } const char *Matrix_nonvirtual(SEXP obj, int strict) { if (!IS_S4_OBJECT(obj)) return ""; static const char *valid[] = { VALID_NONVIRTUAL, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) return ""; if (!strict) ivalid += VALID_NONVIRTUAL_SHIFT(ivalid, 1); return valid[ivalid]; } char Matrix_kind(SEXP obj) { if (IS_S4_OBJECT(obj)) { static const char *valid[] = { VALID_NONVIRTUAL, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) return '\0'; ivalid += VALID_NONVIRTUAL_SHIFT(ivalid, 1); const char *cl = valid[ivalid]; return (cl[2] == 'd') ? 'n' : cl[0]; } else { switch (TYPEOF(obj)) { case LGLSXP: return 'l'; case INTSXP: return 'i'; case REALSXP: return 'd'; case CPLXSXP: return 'z'; default: return '\0'; } } } char Matrix_shape(SEXP obj) { if (!IS_S4_OBJECT(obj)) return '\0'; static const char *valid[] = { VALID_NONVIRTUAL, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) return '\0'; ivalid += VALID_NONVIRTUAL_SHIFT(ivalid, 1); const char *cl = valid[ivalid]; return (cl[3] != 'M') ? 'g' : ((cl[2] == 'd') ? 'i' : cl[1]); } char Matrix_repr(SEXP obj) { if (!IS_S4_OBJECT(obj)) return '\0'; static const char *valid[] = { VALID_NONVIRTUAL_MATRIX, "" }; int ivalid = R_check_class_etc(obj, valid); if (ivalid < 0) return '\0'; ivalid += VALID_NONVIRTUAL_SHIFT(ivalid, 1); const char *cl = valid[ivalid]; switch (cl[2]) { case 'e': case 'y': case 'r': return 'u'; /* unpackedMatrix */ case 'p': return 'p'; /* packedMatrix */ case 'C': return 'C'; /* CsparseMatrix */ case 'R': return 'R'; /* RsparseMatrix */ case 'T': return 'T'; /* TsparseMatrix */ case 'i': return 'd'; /* diagonalMatrix */ case 'd': return 'i'; /* indMatrix */ default: return '\0'; } } SEXP R_Matrix_nonvirtual(SEXP obj, SEXP strict) { return mkString(Matrix_nonvirtual(obj, asLogical(strict))); } #define RETURN_AS_STRSXP(_C_) \ do { \ char c = _C_; \ if (!c) \ return mkString(""); \ else { \ char s[] = { c, '\0' }; \ return mkString(s); \ } \ } while (0) SEXP R_Matrix_kind(SEXP obj) { RETURN_AS_STRSXP(Matrix_kind (obj)); } SEXP R_Matrix_shape(SEXP obj) { RETURN_AS_STRSXP(Matrix_shape(obj)); } SEXP R_Matrix_repr(SEXP obj) { RETURN_AS_STRSXP(Matrix_repr (obj)); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/Csparse.h��������������������������������������������������������������������������������0000644�0001751�0000144�00000000567�14574651213�014114� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_CSPARSE_H #define MATRIX_CSPARSE_H #include SEXP CsparseMatrix_validate_maybe_sorting(SEXP); SEXP dgCMatrix_lusol(SEXP, SEXP); SEXP dgCMatrix_qrsol(SEXP, SEXP, SEXP); SEXP dgCMatrix_cholsol(SEXP, SEXP); SEXP dtCMatrix_diag(SEXP, SEXP); SEXP Csparse_dmperm(SEXP, SEXP, SEXP); SEXP Csparse_writeMM(SEXP, SEXP); #endif /* MATRIX_CSPARSE_H */ �����������������������������������������������������������������������������������������������������������������������������������������Matrix/src/validity.h�������������������������������������������������������������������������������0000644�0001751�0000144�00000004026�14575137654�014344� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_VALIDITY_H #define MATRIX_VALIDITY_H #include char* Dim_validate(SEXP); SEXP R_Dim_validate(SEXP); char* DimNames_validate(SEXP, int[]); SEXP R_DimNames_validate(SEXP, SEXP); SEXP R_DimNames_fixup(SEXP); SEXP Matrix_validate(SEXP); SEXP MatrixFactorization_validate(SEXP); SEXP nMatrix_validate(SEXP); SEXP lMatrix_validate(SEXP); SEXP iMatrix_validate(SEXP); SEXP dMatrix_validate(SEXP); SEXP zMatrix_validate(SEXP); SEXP generalMatrix_validate(SEXP); SEXP symmetricMatrix_validate(SEXP); SEXP triangularMatrix_validate(SEXP); SEXP diagonalMatrix_validate(SEXP); SEXP indMatrix_validate(SEXP); SEXP pMatrix_validate(SEXP); SEXP CsparseMatrix_validate(SEXP); SEXP RsparseMatrix_validate(SEXP); SEXP TsparseMatrix_validate(SEXP); SEXP sCMatrix_validate(SEXP); SEXP tCMatrix_validate(SEXP); SEXP sRMatrix_validate(SEXP); SEXP tRMatrix_validate(SEXP); SEXP sTMatrix_validate(SEXP); SEXP tTMatrix_validate(SEXP); SEXP xgCMatrix_validate(SEXP); SEXP xsCMatrix_validate(SEXP); SEXP xtCMatrix_validate(SEXP); SEXP xgRMatrix_validate(SEXP); SEXP xsRMatrix_validate(SEXP); SEXP xtRMatrix_validate(SEXP); SEXP xgTMatrix_validate(SEXP); SEXP xsTMatrix_validate(SEXP); SEXP xtTMatrix_validate(SEXP); SEXP unpackedMatrix_validate(SEXP); SEXP packedMatrix_validate(SEXP); SEXP dpoMatrix_validate(SEXP); SEXP dppMatrix_validate(SEXP); SEXP corMatrix_validate(SEXP); SEXP copMatrix_validate(SEXP); SEXP sparseVector_validate(SEXP); SEXP lsparseVector_validate(SEXP); SEXP isparseVector_validate(SEXP); SEXP dsparseVector_validate(SEXP); SEXP zsparseVector_validate(SEXP); SEXP denseLU_validate(SEXP); SEXP sparseLU_validate(SEXP); SEXP sparseQR_validate(SEXP); SEXP BunchKaufman_validate(SEXP); SEXP pBunchKaufman_validate(SEXP); SEXP Cholesky_validate(SEXP); SEXP pCholesky_validate(SEXP); SEXP CHMfactor_validate(SEXP); SEXP CHMsimpl_validate(SEXP); SEXP CHMsuper_validate(SEXP); SEXP dCHMsimpl_validate(SEXP); SEXP dCHMsuper_validate(SEXP); SEXP Schur_validate(SEXP); void validObject(SEXP, const char *); #endif /* MATRIX_VALIDITY_H */ ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/matmult.c��������������������������������������������������������������������������������0000644�0001751�0000144�00000127064�14575137654�014205� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Lapack-etc.h" #include "cholmod-etc.h" #include "Mdefines.h" #include "idz.h" #include "coerce.h" #include "dense.h" #include "sparse.h" #include "matmult.h" static void matmultDim(SEXP x, SEXP y, int *xtrans, int *ytrans, int *ztrans, int *m, int *n, int *v) { *xtrans = (*xtrans) ? 1 : 0; *ytrans = (*ytrans) ? 1 : 0; *ztrans = (*ztrans) ? 1 : 0; if (y == R_NilValue) { SEXP xdim = (TYPEOF(x) == S4SXP) ? GET_SLOT(x, Matrix_DimSym) : getAttrib(x, R_DimSymbol); if (TYPEOF(xdim) == INTSXP && LENGTH(xdim) == 2) { *v = 0; *m = *n = INTEGER(xdim)[(*xtrans) ? 1 : 0]; } else if (XLENGTH(x) <= INT_MAX) { *v = 1; *m = *n = (*xtrans) ? 1 : LENGTH(x); } else error(_("dimensions cannot exceed %s"), "2^31-1"); *ytrans = (*xtrans) ? 0 : 1; } else { /* MJ: So that I don't lose my mind ... : */ if (*ztrans) { int tmp = !(*xtrans); *xtrans = !(*ytrans); *ytrans = tmp; SEXP s = x; x = y; y = s; } SEXP xdim = (TYPEOF(x) == S4SXP) ? GET_SLOT(x, Matrix_DimSym) : getAttrib(x, R_DimSymbol), ydim = (TYPEOF(y) == S4SXP) ? GET_SLOT(y, Matrix_DimSym) : getAttrib(y, R_DimSymbol); int xm, xn, ym, yn, x2, y2; xm = xn = ym = yn = -1; x2 = TYPEOF(xdim) == INTSXP && LENGTH(xdim) == 2; y2 = TYPEOF(ydim) == INTSXP && LENGTH(ydim) == 2; if (x2) { int *pxdim = INTEGER(xdim); xm = pxdim[0]; xn = pxdim[1]; } else if (XLENGTH(x) > INT_MAX) error(_("dimensions cannot exceed %s"), "2^31-1"); if (y2) { int *pydim = INTEGER(ydim); ym = pydim[0]; yn = pydim[1]; } else if (XLENGTH(y) > INT_MAX) error(_("dimensions cannot exceed %s"), "2^31-1"); /* MJ: R's do_matprod behaves quite asymmetrically ... what a pain */ if (x2 && y2) *v = 0; else if (y2) { *v = (*ztrans) ? 2 : 1; int k = (*ytrans) ? yn : ym, xl = LENGTH(x); if (k == xl || (k == 1 && !(*xtrans))) { xm = (int) xl; xn = 1; *xtrans = (k == xl) ? 1 : 0; } } else if (x2) { *v = (*ztrans) ? 1 : 2; int k = (*xtrans) ? xm : xn, yl = LENGTH(y); if (*ytrans) { if (xm == 1 || xn == 1) { ym = (int) yl; yn = 1; *ytrans = (((*xtrans) ? xn : xm) == 1) ? 0 : 1; } } else { if (k == yl || k == 1) { ym = (int) yl; yn = 1; *ytrans = (k == yl) ? 0 : 1; } } } else { *v = 3; int xl = LENGTH(x), yl = LENGTH(y); if (*xtrans) { xm = xl; xn = 1; ym = yl; yn = 1; *ytrans = xl == 1; } else if (*ytrans) { xm = xl; xn = 1; ym = yl; yn = 1; /* *xtrans = 0; */ } else { xm = 1; xn = xl; ym = (xl == 1) ? 1 : yl; yn = (xl == 1) ? yl : 1; } } if (((*xtrans) ? xm : xn) != ((*ytrans) ? yn : ym)) error(_("non-conformable arguments")); *m = (*xtrans) ? xn : xm; *n = (*ytrans) ? ym : yn; if (*ztrans) { int tmp = !(*xtrans); *xtrans = !(*ytrans); *ytrans = tmp; tmp = *m; *m = *n; *n = tmp; } } return; } static void matmultDN(SEXP dest, SEXP asrc, int ai, SEXP bsrc, int bi) { SEXP s; if (!isNull(s = VECTOR_ELT(asrc, ai))) SET_VECTOR_ELT(dest, 0, s); if (!isNull(s = VECTOR_ELT(bsrc, bi))) SET_VECTOR_ELT(dest, 1, s); PROTECT(asrc = getAttrib(asrc, R_NamesSymbol)); PROTECT(bsrc = getAttrib(bsrc, R_NamesSymbol)); if (!isNull(asrc) || !isNull(bsrc)) { SEXP destnms = PROTECT(allocVector(STRSXP, 2)); if (!isNull(asrc) && *CHAR(s = STRING_ELT(asrc, ai)) != '\0') SET_STRING_ELT(destnms, 0, s); if (!isNull(bsrc) && *CHAR(s = STRING_ELT(bsrc, bi)) != '\0') SET_STRING_ELT(destnms, 1, s); setAttrib(dest, R_NamesSymbol, destnms); UNPROTECT(1); } UNPROTECT(2); return; } /* op() * op() */ static SEXP dgeMatrix_matmult(SEXP a, SEXP b, int atrans, int btrans) { SEXP adim = GET_SLOT(a, Matrix_DimSym); int *padim = INTEGER(adim), am = padim[0], an = padim[1], rm = (atrans) ? an : am, rk = (atrans) ? am : an; if (b == R_NilValue) { if ((Matrix_int_fast64_t) rm * rm > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); SEXP ax = PROTECT(GET_SLOT(a, Matrix_xSym)); char rcl[] = ".poMatrix"; rcl[0] = (TYPEOF(ax) == CPLXSXP) ? 'z' : 'd'; SEXP r = PROTECT(newObject(rcl)); SEXP rdim = GET_SLOT(r, Matrix_DimSym); int *prdim = INTEGER(rdim); prdim[0] = prdim[1] = rm; SEXP adimnames = PROTECT(GET_SLOT(a, Matrix_DimNamesSym)), rdimnames = PROTECT(GET_SLOT(r, Matrix_DimNamesSym)); symDN(rdimnames, adimnames, (atrans) ? 1 : 0); UNPROTECT(2); /* rdimnames, adimnames */ if (rm > 0) { SEXP rx = PROTECT(allocVector(TYPEOF(ax), (R_xlen_t) rm * rm)); #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(ax) == CPLXSXP) { Rcomplex *prx = COMPLEX(rx); Matrix_memset(prx, 0, (R_xlen_t) rm * rm, sizeof(Rcomplex)); if (rk > 0) { Rcomplex *pax = COMPLEX(ax), zero = Matrix_zzero, one = Matrix_zone; F77_CALL(zsyrk)( "U", (atrans) ? "T" : "N", &rm, &rk, &one, pax, &am, &zero, prx, &rm FCONE FCONE); } } else { #endif double *prx = REAL(rx); Matrix_memset(prx, 0, (R_xlen_t) rm * rm, sizeof(double)); if (rk > 0) { double *pax = REAL(ax), zero = 0.0, one = 1.0; F77_CALL(dsyrk)( "U", (atrans) ? "T" : "N", &rm, &rk, &one, pax, &am, &zero, prx, &rm FCONE FCONE); } #ifdef MATRIX_ENABLE_ZMATRIX } #endif SET_SLOT(r, Matrix_xSym, rx); UNPROTECT(1); /* rx */ } UNPROTECT(2); /* r, ax */ return r; } else { SEXP bdim = GET_SLOT(b, Matrix_DimSym); int *pbdim = INTEGER(bdim), bm = pbdim[0], bn = pbdim[1], rn = (btrans) ? bm : bn; if (rk != ((btrans) ? bn : bm)) error(_("non-conformable arguments")); if ((Matrix_int_fast64_t) rm * rn > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); SEXP ax = PROTECT(GET_SLOT(a, Matrix_xSym)); char rcl[] = ".geMatrix"; rcl[0] = (TYPEOF(ax) == CPLXSXP) ? 'z' : 'd'; SEXP r = PROTECT(newObject(rcl)); SEXP rdim = GET_SLOT(r, Matrix_DimSym); int *prdim = INTEGER(rdim); prdim[0] = rm; prdim[1] = rn; SEXP adimnames = PROTECT(GET_SLOT(a, Matrix_DimNamesSym)), bdimnames = PROTECT(GET_SLOT(b, Matrix_DimNamesSym)), rdimnames = PROTECT(GET_SLOT(r, Matrix_DimNamesSym)); matmultDN(rdimnames, adimnames, (atrans) ? 1 : 0, bdimnames, (btrans) ? 0 : 1); UNPROTECT(3); /* rdimnames, bdimnames, adimnames */ if (rm > 0 && rn > 0) { SEXP rx = PROTECT(allocVector(TYPEOF(ax), (R_xlen_t) rm * rn)); #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(ax) == CPLXSXP) { Rcomplex *prx = COMPLEX(rx); if (rk == 0) Matrix_memset(prx, 0, (R_xlen_t) rm * rn, sizeof(Rcomplex)); else { SEXP bx = PROTECT(GET_SLOT(b, Matrix_xSym)); Rcomplex *pax = COMPLEX(ax), *pbx = COMPLEX(bx), zero = Matrix_zzero, one = Matrix_zone; F77_CALL(zgemm)( (atrans) ? "T" : "N", (btrans) ? "T" : "N", &rm, &rn, &rk, &one, pax, &am, pbx, &bm, &zero, prx, &rm FCONE FCONE); UNPROTECT(1); /* bx */ } } else { #endif double *prx = REAL(rx); if (rk == 0) Matrix_memset(prx, 0, (R_xlen_t) rm * rn, sizeof(double)); else { SEXP bx = PROTECT(GET_SLOT(b, Matrix_xSym)); double *pax = REAL(ax), *pbx = REAL(bx), zero = 0.0, one = 1.0; F77_CALL(dgemm)( (atrans) ? "T" : "N", (btrans) ? "T" : "N", &rm, &rn, &rk, &one, pax, &am, pbx, &bm, &zero, prx, &rm FCONE FCONE); UNPROTECT(1); /* bx */ } #ifdef MATRIX_ENABLE_ZMATRIX } #endif SET_SLOT(r, Matrix_xSym, rx); UNPROTECT(1); /* rx */ } UNPROTECT(2); /* r, ax */ return r; } } /* * op() or op() * */ static SEXP dsyMatrix_matmult(SEXP a, SEXP b, int aleft, int btrans) { SEXP adim = GET_SLOT(a, Matrix_DimSym); int rk = INTEGER(adim)[0]; SEXP bdim = GET_SLOT(b, Matrix_DimSym); int *pbdim = INTEGER(bdim), bm = pbdim[0], bn = pbdim[1], rm = (btrans) ? bn : bm, rn = (btrans) ? bm : bn; if (rk != ((aleft == btrans) ? bn : bm)) error(_("non-conformable arguments")); if ((Matrix_int_fast64_t) rm * rn > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); SEXP ax = PROTECT(GET_SLOT(a, Matrix_xSym)); char rcl[] = ".geMatrix"; rcl[0] = (TYPEOF(ax) == CPLXSXP) ? 'z' : 'd'; SEXP r = PROTECT(newObject(rcl)); SEXP rdim = GET_SLOT(r, Matrix_DimSym); int *prdim = INTEGER(rdim); prdim[0] = rm; prdim[1] = rn; SEXP adimnames = PROTECT(get_symmetrized_DimNames(a, -1)), bdimnames = PROTECT(GET_SLOT(b, Matrix_DimNamesSym)), rdimnames = PROTECT(GET_SLOT(r, Matrix_DimNamesSym)); if (aleft) matmultDN(rdimnames, adimnames, 0, bdimnames, !btrans); else matmultDN(rdimnames, bdimnames, btrans, adimnames, 1); UNPROTECT(3); /* rdimnames, bdimnames, adimnames */ if (rm > 0 && rn > 0) { SEXP auplo = PROTECT(GET_SLOT(a, Matrix_uploSym)), bx = PROTECT(GET_SLOT(b, Matrix_xSym)), rx = PROTECT(allocVector(TYPEOF(ax), (R_xlen_t) rm * rn)); char aul = *CHAR(STRING_ELT(auplo, 0)); int i, d = (aleft) ? rn : rm, binc = (aleft) ? bm : 1, bincp = (aleft) ? 1 : bm, rinc = (aleft) ? 1 : rm, rincp = (aleft) ? rm : 1; #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(ax) == CPLXSXP) { Rcomplex *pax = COMPLEX(ax), *pbx = COMPLEX(bx), *prx = COMPLEX(rx), zero = Matrix_zero, one = Matrix_zone; if (!btrans) F77_CALL(zsymm)( (aleft) ? "L" : "R", &aul, &rm, &rn, &one, pax, &rk, pbx, &bm, &zero, prx, &rm FCONE FCONE); else { for (i = 0; i < d; ++i) { F77_CALL(zsymv)( &aul, &rk, &one, pax, &rk, pbx, &binc, &zero, prx, &rinc FCONE); pbx += bincp; prx += rincp; } } } else { #endif double *pax = REAL(ax), *pbx = REAL(bx), *prx = REAL(rx), zero = 0.0, one = 1.0; if (!btrans) F77_CALL(dsymm)( (aleft) ? "L" : "R", &aul, &rm, &rn, &one, pax, &rk, pbx, &bm, &zero, prx, &rm FCONE FCONE); else { for (i = 0; i < d; ++i) { F77_CALL(dsymv)( &aul, &rk, &one, pax, &rk, pbx, &binc, &zero, prx, &rinc FCONE); pbx += bincp; prx += rincp; } } #ifdef MATRIX_ENABLE_ZMATRIX } #endif SET_SLOT(r, Matrix_xSym, rx); UNPROTECT(3); /* rx, bx, auplo */ } UNPROTECT(2); /* r, ax */ return r; } /* * op() or op() * */ static SEXP dspMatrix_matmult(SEXP a, SEXP b, int aleft, int btrans) { SEXP adim = GET_SLOT(a, Matrix_DimSym); int rk = INTEGER(adim)[0]; SEXP bdim = GET_SLOT(b, Matrix_DimSym); int *pbdim = INTEGER(bdim), bm = pbdim[0], bn = pbdim[1], rm = (btrans) ? bn : bm, rn = (btrans) ? bm : bn; if (rk != ((aleft == btrans) ? bn : bm)) error(_("non-conformable arguments")); if ((Matrix_int_fast64_t) rm * rn > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); SEXP ax = PROTECT(GET_SLOT(a, Matrix_xSym)); char rcl[] = ".geMatrix"; rcl[0] = (TYPEOF(ax) == CPLXSXP) ? 'z' : 'd'; SEXP r = PROTECT(newObject(rcl)); SEXP rdim = GET_SLOT(r, Matrix_DimSym); int *prdim = INTEGER(rdim); prdim[0] = rm; prdim[1] = rn; SEXP adimnames = PROTECT(get_symmetrized_DimNames(a, -1)), bdimnames = PROTECT(GET_SLOT(b, Matrix_DimNamesSym)), rdimnames = PROTECT(GET_SLOT(r, Matrix_DimNamesSym)); if (aleft) matmultDN(rdimnames, adimnames, 0, bdimnames, !btrans); else matmultDN(rdimnames, bdimnames, btrans, adimnames, 1); UNPROTECT(3); /* rdimnames, bdimnames, adimnames */ if (rm > 0 && rn > 0) { SEXP auplo = PROTECT(GET_SLOT(a, Matrix_uploSym)), bx = PROTECT(GET_SLOT(b, Matrix_xSym)), rx = PROTECT(allocVector(REALSXP, (R_xlen_t) rm * rn)); char aul = *CHAR(STRING_ELT(auplo, 0)); int i, d = (aleft) ? rn : rm, binc = (aleft == btrans) ? bm : 1, bincp = (aleft == btrans) ? 1 : bm, rinc = (aleft ) ? 1 : rm, rincp = (aleft ) ? rm : 1; #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(ax) == CPLXSXP) { Rcomplex *pax = COMPLEX(ax), *pbx = COMPLEX(bx), *prx = COMPLEX(rx), zero = Matrix_zzero, one = Matrix_zone; for (i = 0; i < d; ++i) { F77_CALL(zspmv)( &aul, &rk, &one, pax, pbx, &binc, &zero, prx, &rinc FCONE); pbx += bincp; prx += rincp; } } else { #endif double *pax = REAL(ax), *pbx = REAL(bx), *prx = REAL(rx), zero = 0.0, one = 1.0; for (i = 0; i < d; ++i) { F77_CALL(dspmv)( &aul, &rk, &one, pax, pbx, &binc, &zero, prx, &rinc FCONE); pbx += bincp; prx += rincp; } #ifdef MATRIX_ENABLE_ZMATRIX } #endif SET_SLOT(r, Matrix_xSym, rx); UNPROTECT(3); /* rx, bx, auplo */ } UNPROTECT(2); /* r, ax */ return r; } /* op() * op() or op() * op() */ static SEXP dtrMatrix_matmult(SEXP a, SEXP b, int aleft, int atrans, int btrans, int triangular) { SEXP adim = GET_SLOT(a, Matrix_DimSym); int rk = INTEGER(adim)[0]; SEXP bdim = GET_SLOT(b, Matrix_DimSym); int *pbdim = INTEGER(bdim), bm = pbdim[0], bn = pbdim[1], rm = (btrans) ? bn : bm, rn = (btrans) ? bm : bn; if (rk != ((aleft == btrans) ? bn : bm)) error(_("non-conformable arguments")); if ((Matrix_int_fast64_t) rm * rn > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); SEXP ax = PROTECT(GET_SLOT(a, Matrix_xSym)); char rcl[] = "...Matrix"; rcl[0] = (TYPEOF(ax) == CPLXSXP) ? 'z' : 'd'; rcl[1] = (triangular > 0) ? 't' : 'g'; rcl[2] = (triangular > 0) ? 'r' : 'e'; SEXP r = PROTECT(newObject(rcl)); SEXP rdim = GET_SLOT(r, Matrix_DimSym); int *prdim = INTEGER(rdim); prdim[0] = rm; prdim[1] = rn; SEXP adimnames = PROTECT(GET_SLOT(a, Matrix_DimNamesSym)), bdimnames = PROTECT(GET_SLOT(b, Matrix_DimNamesSym)), rdimnames = PROTECT(GET_SLOT(r, Matrix_DimNamesSym)); if (aleft) matmultDN(rdimnames, adimnames, atrans, bdimnames, !btrans); else matmultDN(rdimnames, bdimnames, btrans, adimnames, !atrans); UNPROTECT(3); /* rdimnames, bdimnames, adimnames */ SEXP auplo = GET_SLOT(a, Matrix_uploSym); char aul = *CHAR(STRING_ELT(auplo, 0)); if (triangular > 0 && ((atrans) ? aul == 'U' : aul != 'U')) { if (atrans) auplo = mkString("L"); PROTECT(auplo); SET_SLOT(r, Matrix_uploSym, auplo); UNPROTECT(1); /* auplo */ } SEXP adiag = GET_SLOT(a, Matrix_diagSym); char adi = *CHAR(STRING_ELT(adiag, 0)); if (triangular > 1 && adi != 'N') { PROTECT(adiag); SET_SLOT(r, Matrix_diagSym, adiag); UNPROTECT(1); /* adiag */ } if (rm > 0 && rn > 0) { SEXP bx = PROTECT(GET_SLOT(b, Matrix_xSym)), rx = PROTECT(allocVector(TYPEOF(ax), (R_xlen_t) rm * rn)); #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(ax) == CPLXSXP) { Rcomplex *pax = COMPLEX(ax), *pbx = COMPLEX(bx), *prx = COMPLEX(rx), one = Matrix_zone; if (!btrans) Matrix_memcpy(prx, pbx, (R_xlen_t) bm * bn, sizeof(Rcomplex)); else ztranspose2(prx, pbx, bm, bn); F77_CALL(ztrmm)( (aleft) ? "L" : "R", &aul, (atrans) ? "T" : "N", &adi, &rm, &rn, &one, pax, &rk, prx, &rm FCONE FCONE FCONE FCONE); } else { #endif double *pax = REAL(ax), *pbx = REAL(bx), *prx = REAL(rx), one = 1.0; if (!btrans) Matrix_memcpy(prx, pbx, (R_xlen_t) bm * bn, sizeof(double)); else dtranspose2(prx, pbx, bm, bn); F77_CALL(dtrmm)( (aleft) ? "L" : "R", &aul, (atrans) ? "T" : "N", &adi, &rm, &rn, &one, pax, &rk, prx, &rm FCONE FCONE FCONE FCONE); #ifdef MATRIX_ENABLE_ZMATRIX } #endif SET_SLOT(r, Matrix_xSym, rx); UNPROTECT(2); /* rx, bx */ } UNPROTECT(2); /* r, ax */ return r; } /* op() * op() or op() * op() */ static SEXP dtpMatrix_matmult(SEXP a, SEXP b, int aleft, int atrans, int btrans, int triangular) { SEXP adim = GET_SLOT(a, Matrix_DimSym); int rk = INTEGER(adim)[0]; SEXP bdim = GET_SLOT(b, Matrix_DimSym); int *pbdim = INTEGER(bdim), bm = pbdim[0], bn = pbdim[1], rm = (btrans) ? bn : bm, rn = (btrans) ? bm : bn; if (rk != ((aleft == btrans) ? bn : bm)) error(_("non-conformable arguments")); if ((Matrix_int_fast64_t) rm * rn > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); SEXP ax = PROTECT(GET_SLOT(a, Matrix_xSym)); char rcl[] = "...Matrix"; rcl[0] = (TYPEOF(ax) == CPLXSXP) ? 'z' : 'd'; rcl[1] = (triangular > 0) ? 't' : 'g'; rcl[2] = (triangular > 0) ? 'r' : 'e'; SEXP r = PROTECT(newObject(rcl)); SEXP rdim = GET_SLOT(r, Matrix_DimSym); int *prdim = INTEGER(rdim); prdim[0] = rm; prdim[1] = rn; SEXP adimnames = PROTECT(GET_SLOT(a, Matrix_DimNamesSym)), bdimnames = PROTECT(GET_SLOT(b, Matrix_DimNamesSym)), rdimnames = PROTECT(GET_SLOT(r, Matrix_DimNamesSym)); if (aleft) matmultDN(rdimnames, adimnames, atrans, bdimnames, !btrans); else matmultDN(rdimnames, bdimnames, btrans, adimnames, !atrans); UNPROTECT(3); /* rdimnames, bdimnames, adimnames */ SEXP auplo = GET_SLOT(a, Matrix_uploSym); char aul = *CHAR(STRING_ELT(auplo, 0)); if (triangular > 0 && ((atrans) ? aul == 'U' : aul != 'U')) { if (atrans) auplo = mkString("L"); PROTECT(auplo); SET_SLOT(r, Matrix_uploSym, auplo); UNPROTECT(1); /* auplo */ } SEXP adiag = GET_SLOT(a, Matrix_diagSym); char adi = *CHAR(STRING_ELT(adiag, 0)); if (triangular > 1 && adi != 'N') { PROTECT(adiag); SET_SLOT(r, Matrix_diagSym, adiag); UNPROTECT(1); /* adiag */ } if (rm > 0 && rn > 0) { SEXP bx = PROTECT(GET_SLOT(b, Matrix_xSym)), rx = PROTECT(allocVector(REALSXP, (R_xlen_t) rm * rn)); int i, rinc = (aleft) ? 1 : rm, rincp = (aleft) ? rm : 1; #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(ax) == CPLXSXP) { Rcomplex *pax = COMPLEX(ax), *pbx = COMPLEX(bx), *prx = COMPLEX(rx); if (!btrans) Matrix_memcpy(prx, pbx, (R_xlen_t) bm * bn, sizeof(Rcomplex)); else ztranspose2(prx, pbx, bm, bn); for (i = 0; i < rn; ++i) { F77_CALL(ztpmv)( &aul, (aleft == atrans) ? "T" : "N", &adi, &rk, pax, prx, &rinc FCONE FCONE FCONE); prx += rincp; } } else { #endif double *pax = REAL(ax), *pbx = REAL(bx), *prx = REAL(rx); if (!btrans) Matrix_memcpy(prx, pbx, (R_xlen_t) bm * bn, sizeof(double)); else dtranspose2(prx, pbx, bm, bn); for (i = 0; i < rn; ++i) { F77_CALL(dtpmv)( &aul, (aleft == atrans) ? "T" : "N", &adi, &rk, pax, prx, &rinc FCONE FCONE FCONE); prx += rincp; } #ifdef MATRIX_ENABLE_ZMATRIX } #endif SET_SLOT(r, Matrix_xSym, rx); UNPROTECT(2); /* rx, bx */ } UNPROTECT(2); /* r, ax */ return r; } SEXP R_dense_matmult(SEXP x, SEXP y, SEXP xtrans, SEXP ytrans) { int xtrans_ = LOGICAL(xtrans)[0], ytrans_ = LOGICAL(ytrans)[0], ztrans_ = 0, m, n, v; matmultDim(x, y, &xtrans_, &ytrans_, &ztrans_, &m, &n, &v); PROTECT_INDEX xpid, ypid; PROTECT_WITH_INDEX(x, &xpid); PROTECT_WITH_INDEX(y, &ypid); if (TYPEOF(x) != S4SXP) { REPROTECT(x = matrix_as_dense(x, ",ge", '\0', '\0', xtrans_, 0), xpid); if (v == 1) { /* Vector: discard names and don't transpose again */ SET_VECTOR_ELT(GET_SLOT(x, Matrix_DimNamesSym), (xtrans_) ? 1 : 0, R_NilValue); xtrans_ = 0; } } if (TYPEOF(y) != S4SXP && y != R_NilValue) { REPROTECT(y = matrix_as_dense(y, ",ge", '\0', '\0', ytrans_, 0), ypid); if (v == 2) { /* Vector: discard names and don't transpose again */ SET_VECTOR_ELT(GET_SLOT(y, Matrix_DimNamesSym), (ytrans_) ? 1 : 0, R_NilValue); ytrans_ = 0; } } static const char *valid[] = { VALID_DENSE, "" }; const char *xcl = NULL, *ycl = NULL; int ivalid; ivalid = R_check_class_etc(x, valid); if (ivalid < 0) ERROR_INVALID_CLASS(x, __func__); xcl = valid[ivalid]; if (y != R_NilValue) { ivalid = R_check_class_etc(y, valid); if (ivalid < 0) ERROR_INVALID_CLASS(y, __func__); ycl = valid[ivalid]; } char kind = (xcl[0] == 'z' || (y != R_NilValue && ycl[0] == 'z')) ? 'z' : 'd'; if (xcl[0] != kind) { REPROTECT(x = dense_as_kind(x, xcl, kind, 0), xpid); xcl = valid[R_check_class_etc(x, valid)]; } if (y != R_NilValue) { if (ycl[0] != kind) { REPROTECT(y = dense_as_kind(y, ycl, kind, 0), ypid); ycl = valid[R_check_class_etc(y, valid)]; } } if (y == R_NilValue) { REPROTECT(x = dense_as_general(x, xcl, 1), xpid); x = dgeMatrix_matmult(x, y, xtrans_, !xtrans_); } else if (xcl[1] == 'g' && ycl[1] == 'g') { x = dgeMatrix_matmult(x, y, xtrans_, ytrans_); } else if (xcl[1] == 'g' || ycl[1] == 'g') { x = (xcl[1] == 'g') ? ((ycl[1] == 's') ? ((ycl[2] != 'p') ? dsyMatrix_matmult(y, x, 0, xtrans_) : dspMatrix_matmult(y, x, 0, xtrans_)) : ((ycl[2] != 'p') ? dtrMatrix_matmult(y, x, 0, ytrans_, xtrans_, 0) : dtpMatrix_matmult(y, x, 0, ytrans_, xtrans_, 0))) : ((xcl[1] == 's') ? ((xcl[2] != 'p') ? dsyMatrix_matmult(x, y, 1, ytrans_) : dspMatrix_matmult(x, y, 1, ytrans_)) : ((xcl[2] != 'p') ? dtrMatrix_matmult(x, y, 1, xtrans_, ytrans_, 0) : dtpMatrix_matmult(x, y, 1, xtrans_, ytrans_, 0))); } else if (xcl[1] == 's' && ycl[1] == 's') { if (xcl[2] == 'p' && ycl[2] == 'p') { REPROTECT(y = dense_as_general(y, ycl, 1), ypid); x = dspMatrix_matmult(x, y, 1, ytrans_); } else if (xcl[2] == 'p') { REPROTECT(x = dense_as_general(x, xcl, 1), xpid); x = dsyMatrix_matmult(y, x, 0, xtrans_); } else { REPROTECT(y = dense_as_general(y, ycl, 1), ypid); x = dsyMatrix_matmult(x, y, 1, ytrans_); } } else if (xcl[1] == 's' || ycl[1] == 's') { if (xcl[1] == 's') { REPROTECT(x = dense_as_general(x, xcl, 1), xpid); x = (ycl[2] != 'p') ? dtrMatrix_matmult(y, x, 0, ytrans_, 0, 0) : dtpMatrix_matmult(y, x, 0, ytrans_, 0, 0); } else { REPROTECT(y = dense_as_general(y, ycl, 1), ypid); x = (xcl[2] != 'p') ? dtrMatrix_matmult(x, y, 1, xtrans_, 0, 0) : dtpMatrix_matmult(x, y, 1, xtrans_, 0, 0); } } else { SEXP xuplo = PROTECT(GET_SLOT(x, Matrix_uploSym)), yuplo = PROTECT(GET_SLOT(y, Matrix_uploSym)), xdiag = PROTECT(GET_SLOT(x, Matrix_diagSym)), ydiag = PROTECT(GET_SLOT(y, Matrix_diagSym)); char xul = *CHAR(STRING_ELT(xuplo, 0)), yul = *CHAR(STRING_ELT(yuplo, 0)), xdi = *CHAR(STRING_ELT(xdiag, 0)), ydi = *CHAR(STRING_ELT(ydiag, 0)); if (xtrans_) xul = (xul == 'U') ? 'L' : 'U'; if (ytrans_) yul = (yul == 'U') ? 'L' : 'U'; int triangular = (xul != yul) ? 0 : ((xdi != ydi || xdi == 'N') ? 1 : 2); UNPROTECT(4); /* ydiag, xdiag, yuplo, xuplo */ if (xcl[2] == 'p' && ycl[2] == 'p') { REPROTECT(y = dense_as_general(y, ycl, 1), ypid); x = dtpMatrix_matmult(x, y, 1, xtrans_, ytrans_, triangular); } else if (xcl[2] == 'p') { REPROTECT(x = dense_as_general(x, xcl, 1), xpid); x = dtrMatrix_matmult(y, x, 0, ytrans_, xtrans_, triangular); } else { REPROTECT(y = dense_as_general(y, ycl, 1), ypid); x = dtrMatrix_matmult(x, y, 1, xtrans_, ytrans_, triangular); } } UNPROTECT(2); /* y, x */ return x; } /* boolean: op(op(<.gC>) & op(<.gC>)) */ /* numeric: op(op() * op()) */ static SEXP dgCMatrix_dgCMatrix_matmult(SEXP x, SEXP y, int xtrans, int ytrans, int ztrans, int triangular, int boolean) { PROTECT_INDEX zpid; SEXP z; char zcl[] = "..CMatrix"; zcl[0] = (boolean) ? 'n' : 'd'; if (y == R_NilValue) { zcl[1] = 's'; cholmod_sparse *X = M2CHS(x, !boolean); if (X->xtype == CHOLMOD_COMPLEX) error(_("'%s' does not support complex matrices"), "cholmod_aat"); if (xtrans) X = cholmod_transpose(X, !boolean, &c); cholmod_sparse *Z = cholmod_aat(X, (int *) NULL, 0, !boolean, &c); if (xtrans) cholmod_free_sparse(&X, &c); if (!Z->sorted) cholmod_sort(Z, &c); X = cholmod_copy(Z, (ztrans) ? -1 : 1, 1, &c); cholmod_free_sparse(&Z, &c); Z = X; PROTECT_WITH_INDEX(z = CHS2M(Z, !boolean, zcl[1]), &zpid); cholmod_free_sparse(&Z, &c); SEXP xdimnames = PROTECT(GET_SLOT(x, Matrix_DimNamesSym)), zdimnames = PROTECT(GET_SLOT(z, Matrix_DimNamesSym)); symDN(zdimnames, xdimnames, (xtrans) ? 1 : 0); UNPROTECT(2); /* zdimnames, xdimnames */ if (ztrans) { SEXP uplo = PROTECT(mkString("L")); SET_SLOT(z, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } } else { zcl[1] = (triangular != 0) ? 't' : 'g'; cholmod_sparse *X = M2CHS(x, !boolean), *Y = M2CHS(y, !boolean); if (X->xtype == CHOLMOD_COMPLEX || Y->xtype == CHOLMOD_COMPLEX) error(_("'%s' does not support complex matrices"), "cholmod_ssmult"); if (((xtrans) ? X->nrow : X->ncol) != ((ytrans) ? Y->ncol : Y->nrow)) error(_("non-conformable arguments")); if (xtrans) X = cholmod_transpose(X, !boolean, &c); if (ytrans) Y = cholmod_transpose(Y, !boolean, &c); cholmod_sparse *Z = cholmod_ssmult(X, Y, 0, !boolean, 1, &c); if (xtrans) cholmod_free_sparse(&X, &c); if (ytrans) cholmod_free_sparse(&Y, &c); PROTECT_WITH_INDEX(z = CHS2M(Z, !boolean, zcl[1]), &zpid); cholmod_free_sparse(&Z, &c); SEXP xdimnames = PROTECT(GET_SLOT(x, Matrix_DimNamesSym)), ydimnames = PROTECT(GET_SLOT(y, Matrix_DimNamesSym)), zdimnames = PROTECT(GET_SLOT(z, Matrix_DimNamesSym)); matmultDN(zdimnames, xdimnames, (xtrans) ? 1 : 0, ydimnames, (ytrans) ? 0 : 1); UNPROTECT(3); /* zdimnames, ydimnames, xdimnames */ if (triangular < 0) { SEXP uplo = PROTECT(mkString("L")); SET_SLOT(z, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } if (triangular < -1 || triangular > 1) REPROTECT(z = sparse_diag_N2U(z, zcl), zpid); } if (ztrans) REPROTECT(z = sparse_transpose(z, zcl, 1), zpid); UNPROTECT(1); /* z */ return z; } /* op(op() * op()) */ static SEXP dgCMatrix_dgeMatrix_matmult(SEXP x, SEXP y, int xtrans, int ytrans, int ztrans, int triangular, int symmetric) { SEXP z; char zcl[] = "...Matrix"; cholmod_sparse *X = M2CHS(x, 1); cholmod_dense *Y = M2CHD(y, ytrans); zcl[0] = (X->xtype == CHOLMOD_COMPLEX || Y->xtype == CHOLMOD_COMPLEX) ? 'z' : 'd'; zcl[1] = (triangular) ? 't' : 'g'; zcl[2] = (triangular) ? 'r' : 'e'; X->stype = symmetric; if (((xtrans) ? X->nrow : X->ncol) != Y->nrow) { if (ytrans) R_Free(Y->x); error(_("non-conformable arguments")); } int m = (int) ((xtrans) ? X->ncol : X->nrow), n = (int) Y->ncol; if ((Matrix_int_fast64_t) m * n > R_XLEN_T_MAX) { if (ytrans) R_Free(Y->x); error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); } cholmod_dense *Z = (cholmod_dense *) R_alloc(1, sizeof(cholmod_dense)); memset(Z, 0, sizeof(cholmod_dense)); Z->nrow = (size_t) m; Z->ncol = (size_t) n; Z->d = Z->nrow; Z->nzmax = Z->nrow * Z->ncol; Z->xtype = Y->xtype; Z->dtype = Y->dtype; double alpha[2] = { 1.0, 0.0 }, beta[2] = { 0.0, 0.0 }; if (ztrans) { if (Z->xtype == CHOLMOD_COMPLEX) Z->x = R_Calloc(Z->nzmax, Rcomplex); else Z->x = R_Calloc(Z->nzmax, double); cholmod_sdmult(X, xtrans, alpha, beta, Y, Z, &c); PROTECT(z = CHD2M(Z, ztrans, zcl[1])); R_Free(Z->x); } else { PROTECT(z = newObject(zcl)); SEXP zdim = GET_SLOT(z, Matrix_DimSym); INTEGER(zdim)[0] = m; INTEGER(zdim)[1] = n; SEXP zx; if (Z->xtype == CHOLMOD_COMPLEX) { PROTECT(zx = allocVector(CPLXSXP, (R_xlen_t) m * n)); Z->x = COMPLEX(zx); } else { PROTECT(zx = allocVector(REALSXP, (R_xlen_t) m * n)); Z->x = REAL(zx); } cholmod_sdmult(X, xtrans, alpha, beta, Y, Z, &c); SET_SLOT(z, Matrix_xSym, zx); UNPROTECT(1); /* zx */ } if (ytrans) R_Free(Y->x); SEXP xdimnames = (symmetric) ? PROTECT(get_symmetrized_DimNames(x, -1)) : PROTECT(GET_SLOT(x, Matrix_DimNamesSym)), ydimnames = PROTECT(GET_SLOT(y, Matrix_DimNamesSym)), zdimnames = PROTECT(GET_SLOT(z, Matrix_DimNamesSym)); if (ztrans) matmultDN(zdimnames, ydimnames, (ytrans) ? 0 : 1, xdimnames, (xtrans) ? 1 : 0); else matmultDN(zdimnames, xdimnames, (xtrans) ? 1 : 0, ydimnames, (ytrans) ? 0 : 1); UNPROTECT(3); /* zdimnames, ydimnames, xdimnames */ if (triangular != 0 && ztrans == (triangular > 0)) { SEXP uplo = PROTECT(mkString("L")); SET_SLOT(z, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ } if (triangular < -1 || triangular > 1) { SEXP diag = PROTECT(mkString("U")); SET_SLOT(z, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } UNPROTECT(1); /* z */ return z; } SEXP R_sparse_matmult(SEXP x, SEXP y, SEXP xtrans, SEXP ytrans, SEXP ztrans, SEXP boolean) { if (TYPEOF(boolean) != LGLSXP || LENGTH(boolean) < 1) error(_("invalid '%s' to '%s'"), "boolean", __func__); int boolean_ = LOGICAL(boolean)[0]; int xtrans_ = LOGICAL(xtrans)[0], ytrans_ = LOGICAL(ytrans)[0], ztrans_ = LOGICAL(ztrans)[0], m, n, v; matmultDim(x, y, &xtrans_, &ytrans_, &ztrans_, &m, &n, &v); PROTECT_INDEX xpid, ypid; PROTECT_WITH_INDEX(x, &xpid); PROTECT_WITH_INDEX(y, &ypid); if (TYPEOF(x) != S4SXP) { if (boolean_ == NA_LOGICAL || !boolean_) REPROTECT(x = matrix_as_dense( x, ",ge", '\0', '\0', xtrans_, 0), xpid); else if (!xtrans_) REPROTECT(x = matrix_as_sparse(x, "ngC", '\0', '\0', xtrans_ ), xpid); else REPROTECT(x = matrix_as_sparse(x, "ngR", '\0', '\0', xtrans_ ), xpid); if (v == 1) { /* Discard names and don't transpose again */ SET_VECTOR_ELT(GET_SLOT(x, Matrix_DimNamesSym), (xtrans_) ? 1 : 0, R_NilValue); xtrans_ = 0; } } if (TYPEOF(y) != S4SXP && y != R_NilValue) { if (boolean_ == NA_LOGICAL || !boolean_) REPROTECT(y = matrix_as_dense( y, ",ge", '\0', '\0', ytrans_, 0), ypid); else if (!ytrans_) REPROTECT(y = matrix_as_sparse(y, "ngC", '\0', '\0', ytrans_ ), ypid); else REPROTECT(y = matrix_as_sparse(y, "ngR", '\0', '\0', ytrans_ ), ypid); if (v == 2) { /* Discard names and don't transpose again */ SET_VECTOR_ELT(GET_SLOT(y, Matrix_DimNamesSym), (ytrans_) ? 1 : 0, R_NilValue); ytrans_ = 0; } } static const char *valid[] = { VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, VALID_DENSE, "" }; const char *xcl = NULL, *ycl = NULL; int ivalid; ivalid = R_check_class_etc(x, valid); if (ivalid < 0) ERROR_INVALID_CLASS(x, __func__); xcl = valid[ivalid]; if (y != R_NilValue) { ivalid = R_check_class_etc(y, valid); if (ivalid < 0) ERROR_INVALID_CLASS(y, __func__); ycl = valid[ivalid]; } if (boolean_ == NA_LOGICAL) boolean_ = xcl[0] == 'n' && (y == R_NilValue || ycl[0] == 'n'); char kind = (boolean_) ? 'n' : ((xcl[0] == 'z' || (y != R_NilValue && ycl[0] == 'z')) ? 'z' : 'd'); if (xcl[2] != 'C' && xtrans_) { if (xcl[2] != 'R' && xcl[2] != 'T') { REPROTECT(x = dense_as_sparse(x, xcl, 'R'), xpid); xcl = valid[R_check_class_etc(x, valid)]; } if (xcl[1] != 's' || xcl[1] != 'T') { REPROTECT(x = sparse_transpose(x, xcl, 1), xpid); xcl = valid[R_check_class_etc(x, valid)]; } xtrans_ = 0; } if (xcl[2] != 'C') { if (xcl[2] != 'R' && xcl[2] != 'T') REPROTECT(x = dense_as_sparse(x, xcl, 'C'), xpid); else REPROTECT(x = sparse_as_Csparse(x, xcl), xpid); xcl = valid[R_check_class_etc(x, valid)]; } if (xcl[1] == 's') xtrans_ = 0; if (xcl[0] != kind) { if (boolean_) REPROTECT(x = sparse_drop0(x, xcl, 0.0), xpid); else { REPROTECT(x = sparse_as_kind(x, xcl, kind), xpid); xcl = valid[R_check_class_etc(x, valid)]; } } if (y == R_NilValue) { REPROTECT(x = sparse_as_general(x, xcl), xpid); x = dgCMatrix_dgCMatrix_matmult( x, y, xtrans_, !xtrans_, ztrans_, 0, boolean_); UNPROTECT(2); /* y, x */ return x; } int triangular = 0; if (xcl[1] == 't' && ycl[1] == 't') { SEXP xuplo = PROTECT(GET_SLOT(x, Matrix_uploSym)), yuplo = PROTECT(GET_SLOT(y, Matrix_uploSym)), xdiag = PROTECT(GET_SLOT(x, Matrix_diagSym)), ydiag = PROTECT(GET_SLOT(y, Matrix_diagSym)); char xul = *CHAR(STRING_ELT(xuplo, 0)), yul = *CHAR(STRING_ELT(yuplo, 0)), xdi = *CHAR(STRING_ELT(xdiag, 0)), ydi = *CHAR(STRING_ELT(ydiag, 0)); if (xtrans_) xul = (xul == 'U') ? 'L' : 'U'; if (ytrans_) yul = (yul == 'U') ? 'L' : 'U'; triangular = (xul != yul) ? 0 : ((xdi != ydi || xdi == 'N') ? 1 : 2); if (xul != 'U') triangular = -triangular; UNPROTECT(4); /* ydiag, xdiag, yuplo, xuplo */ } if (!boolean_ && ycl[2] != 'C' && ycl[2] != 'R' && ycl[2] != 'T') { int symmetric = xcl[1] == 's'; if (symmetric) { SEXP xuplo = PROTECT(GET_SLOT(x, Matrix_uploSym)); char xul = *CHAR(STRING_ELT(xuplo, 0)); if (xul != 'U') symmetric = -1; UNPROTECT(1); /* xuplo */ } if (ycl[0] != kind) { REPROTECT(y = dense_as_kind(y, ycl, kind, 0), ypid); ycl = valid[R_check_class_etc(y, valid)]; } REPROTECT(y = dense_as_general(y, ycl, 1), ypid); if (xcl[1] == 't') REPROTECT(x = sparse_diag_U2N(x, xcl), xpid); x = dgCMatrix_dgeMatrix_matmult( x, y, xtrans_, ytrans_, ztrans_, triangular, symmetric); UNPROTECT(2); /* y, x */ return x; } if (ycl[2] != 'C' && ytrans_) { if (ycl[2] != 'R' && ycl[2] != 'T') { REPROTECT(y = dense_as_sparse(y, ycl, 'R'), ypid); ycl = valid[R_check_class_etc(y, valid)]; } if (ycl[1] != 's' || ycl[1] != 'T') { REPROTECT(y = sparse_transpose(y, ycl, 1), ypid); ycl = valid[R_check_class_etc(y, valid)]; } ytrans_ = 0; } if (ycl[2] != 'C') { if (ycl[2] != 'R' && ycl[2] != 'T') REPROTECT(y = dense_as_sparse(y, ycl, 'C'), ypid); else REPROTECT(y = sparse_as_Csparse(y, ycl), ypid); ycl = valid[R_check_class_etc(y, valid)]; } if (ycl[1] == 's') ytrans_ = 0; if (ycl[0] != kind) { if (boolean_) REPROTECT(y = sparse_drop0(y, ycl, 0.0), ypid); else { REPROTECT(y = sparse_as_kind(y, ycl, kind), ypid); ycl = valid[R_check_class_etc(y, valid)]; } } REPROTECT(x = sparse_as_general(x, xcl), xpid); REPROTECT(y = sparse_as_general(y, ycl), ypid); x = dgCMatrix_dgCMatrix_matmult( x, y, xtrans_, ytrans_, ztrans_, triangular, boolean_); UNPROTECT(2); /* y, x */ return x; } #define MULTIPLY_COMPLEX(_X_, _D_) \ do { \ tmp = (_X_); \ (_X_).r = tmp.r * (_D_).r - tmp.i * (_D_).i; \ (_X_).i = tmp.r * (_D_).i + tmp.i * (_D_).r; \ } while (0) #define MULTIPLY_REAL(_X_, _D_) \ (_X_) = (_X_) * (_D_) #define MULTIPLY_LOGICAL(_X_, _D_) \ (_X_) = (_X_) && (_D_) #define SCALE_CASES(_J_) \ do { \ switch (TYPEOF(d)) { \ case CPLXSXP: \ { \ Rcomplex tmp; \ SCALE(Rcomplex, COMPLEX, MULTIPLY_COMPLEX, _J_); \ break; \ } \ case REALSXP: \ SCALE(double, REAL, MULTIPLY_REAL, _J_); \ break; \ default: \ SCALE(int, LOGICAL, MULTIPLY_LOGICAL, _J_); \ break; \ } \ } while (0) static void dense_colscale(SEXP obj, SEXP d, int m, int n, char uplo, char diag) { SEXP x = GET_SLOT(obj, Matrix_xSym); int i, j, packed = XLENGTH(x) < (R_xlen_t) m * n; #define SCALE(_CTYPE_, _PTR_, _OP_, _J_) \ do { \ _CTYPE_ *px = _PTR_(x), *pd = _PTR_(d); \ if (uplo == '\0') { \ for (j = 0; j < n; ++j) { \ for (i = 0; i < m; ++i) { \ _OP_(*px, pd[_J_]); \ ++px; \ } \ } \ } else if (uplo == 'U') { \ for (j = 0; j < n; ++j) { \ for (i = 0; i <= j; ++i) { \ _OP_(*px, pd[_J_]); \ ++px; \ } \ if (!packed) \ px += m - j - 1; \ } \ } else { \ for (j = 0; j < n; ++j) { \ if (!packed) \ px += j; \ for (i = j; i < m; ++i) { \ _OP_(*px, pd[_J_]); \ ++px; \ } \ } \ } \ if (diag != '\0' && diag != 'N') { \ px = _PTR_(x); \ if (!packed) { \ R_xlen_t m1a = (R_xlen_t) m + 1; \ for (j = 0; j < n; ++j, px += m1a, pd += 1) \ *px = *pd; \ } else if (uplo == 'U') { \ for (j = 0; j < n; px += (++j)+1, pd += 1) \ *px = *pd; \ } else { \ for (j = 0; j < n; px += m-(j++), pd += 1) \ *px = *pd; \ } \ } \ } while (0) SCALE_CASES(j); return; } static void dense_rowscale(SEXP obj, SEXP d, int m, int n, char uplo, char diag) { SEXP x = GET_SLOT(obj, Matrix_xSym); int i, j, packed = XLENGTH(x) < (R_xlen_t) m * n; SCALE_CASES(i); #undef SCALE return; } /* boolean: & or & */ /* numeric: * or * */ static void Csparse_colscale(SEXP obj, SEXP d) { SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), p = PROTECT(GET_SLOT(obj, Matrix_pSym)); int *pp = INTEGER(p) + 1, n = (int) (XLENGTH(p) - 1), j, k = 0, kend; UNPROTECT(2); /* p, x */ #define SCALE(_CTYPE_, _PTR_, _OP_, _J_) \ do { \ _CTYPE_ *px = _PTR_(x), *pd = _PTR_(d); \ for (j = 0; j < n; ++j) { \ kend = pp[j]; \ while (k < kend) { \ _OP_(*px, *pd); \ ++px; \ ++k; \ } \ ++pd; \ } \ } while (0) SCALE_CASES(); #undef SCALE return; } /* boolean: & or & */ /* numeric: * or * */ static void Csparse_rowscale(SEXP obj, SEXP d, SEXP iSym) { SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), p = PROTECT(GET_SLOT(obj, Matrix_pSym)), i = PROTECT(GET_SLOT(obj, iSym)); int *pi = INTEGER(i), k, nnz = INTEGER(p)[XLENGTH(p) - 1]; UNPROTECT(3); /* i, p, x */ #define SCALE(_CTYPE_, _PTR_, _OP_, _J_) \ do { \ _CTYPE_ *px = _PTR_(x), *pd = _PTR_(d); \ for (k = 0; k < nnz; ++k) { \ _OP_(*px, pd[*pi]); \ ++px; \ ++pi; \ } \ } while (0) SCALE_CASES(); return; } /* boolean: & or & */ /* numeric: * or * */ static void Tsparse_rowscale(SEXP obj, SEXP d, SEXP iSym) { SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), i = PROTECT(GET_SLOT(obj, iSym)); int *pi = INTEGER(i); R_xlen_t k, nnz = XLENGTH(i); UNPROTECT(2); /* i, x */ SCALE_CASES(); #undef SCALE return; } SEXP R_diagonal_matmult(SEXP x, SEXP y, SEXP xtrans, SEXP ytrans, SEXP boolean) { SEXP x_ = x, y_ = y; /* for later pointer comparison */ if (TYPEOF(boolean) != LGLSXP || LENGTH(boolean) < 1) error(_("invalid '%s' to '%s'"), "boolean", __func__); int boolean_ = LOGICAL(boolean)[0]; int xtrans_ = LOGICAL(xtrans)[0], ytrans_ = LOGICAL(ytrans)[0], ztrans_ = 0, m, n, v; matmultDim(x, y, &xtrans_, &ytrans_, &ztrans_, &m, &n, &v); PROTECT_INDEX xpid, ypid; PROTECT_WITH_INDEX(x, &xpid); PROTECT_WITH_INDEX(y, &ypid); if (TYPEOF(x) != S4SXP) { if (boolean_ == NA_LOGICAL || !boolean_) REPROTECT(x = matrix_as_dense(x, ",ge", '\0', '\0', xtrans_, 2), xpid); else REPROTECT(x = matrix_as_dense(x, "nge", '\0', '\0', xtrans_, 2), xpid); if (v == 1) { /* Vector: discard names and don't transpose again */ SET_VECTOR_ELT(GET_SLOT(x, Matrix_DimNamesSym), (xtrans_) ? 1 : 0, R_NilValue); xtrans_ = 0; } } if (TYPEOF(y) != S4SXP) { if (boolean_ == NA_LOGICAL || !boolean_) REPROTECT(y = matrix_as_dense(y, ",ge", '\0', '\0', ytrans_, 2), ypid); else REPROTECT(y = matrix_as_dense(y, "nge", '\0', '\0', ytrans_, 2), ypid); if (v == 2) { /* Vector: discard names and don't transpose again */ SET_VECTOR_ELT(GET_SLOT(y, Matrix_DimNamesSym), (ytrans_) ? 1 : 0, R_NilValue); ytrans_ = 0; } } static const char *valid[] = { VALID_DIAGONAL, VALID_CSPARSE, VALID_RSPARSE, VALID_TSPARSE, VALID_DENSE, "" }; const char *xcl = NULL, *ycl = NULL; int ivalid; ivalid = R_check_class_etc(x, valid); if (ivalid < 0) ERROR_INVALID_CLASS(x, __func__); xcl = valid[ivalid]; if (xcl[1] == 's') xtrans_ = 0; ivalid = R_check_class_etc(y, valid); if (ivalid < 0) ERROR_INVALID_CLASS(y, __func__); ycl = valid[ivalid]; if (ycl[1] == 's') ytrans_ = 0; if (boolean_ == NA_LOGICAL) boolean_ = xcl[0] == 'n' && ycl[0] == 'n'; char kind = (boolean_) ? 'n' : ((xcl[0] == 'z' || ycl[0] == 'z') ? 'z' : 'd'); int margin = -1, unit = -1; if (xcl[2] == 'i') { margin = 0; unit = *CHAR(STRING_ELT(GET_SLOT(x, Matrix_diagSym), 0)) != 'N'; } else if (ycl[2] == 'i') { margin = 1; unit = *CHAR(STRING_ELT(GET_SLOT(y, Matrix_diagSym), 0)) != 'N'; } else error(_("should never happen ...")); char ks = (boolean_) ? 'l' : kind, kd = kind; switch (xcl[2]) { case 'i': if (!unit && xcl[0] != ks) { REPROTECT(x = diagonal_as_kind(x, xcl, ks), xpid); xcl = valid[R_check_class_etc(x, valid)]; } break; case 'C': case 'R': case 'T': if (xcl[0] != ks) { REPROTECT(x = sparse_as_kind(x, xcl, ks), xpid); xcl = valid[R_check_class_etc(x, valid)]; } if (!unit && xcl[1] == 's') { REPROTECT(x = sparse_as_general(x, xcl), xpid); xcl = valid[R_check_class_etc(x, valid)]; } else if (!unit && xcl[1] == 't') REPROTECT(x = sparse_diag_U2N(x, xcl), xpid); if (xtrans_) { REPROTECT(x = sparse_transpose(x, xcl, 0), xpid); xtrans_ = 0; } break; default: if (xcl[0] != kd) { REPROTECT(x = dense_as_kind(x, xcl, kd, 1), xpid); xcl = valid[R_check_class_etc(x, valid)]; } if (!unit && xcl[1] == 's') { REPROTECT(x = dense_as_general(x, xcl, x == x_), xpid); xcl = valid[R_check_class_etc(x, valid)]; } if (xtrans_) { REPROTECT(x = dense_transpose(x, xcl), xpid); xtrans_ = 0; } break; } switch (ycl[2]) { case 'i': if (!unit && ycl[0] != ks) { REPROTECT(y = diagonal_as_kind(y, ycl, ks), ypid); ycl = valid[R_check_class_etc(y, valid)]; } break; case 'C': case 'R': case 'T': if (ycl[0] != ks) { REPROTECT(y = sparse_as_kind(y, ycl, ks), ypid); ycl = valid[R_check_class_etc(y, valid)]; } if (!unit && ycl[1] == 's') { REPROTECT(y = sparse_as_general(y, ycl), ypid); ycl = valid[R_check_class_etc(y, valid)]; } else if (!unit && ycl[1] == 't') REPROTECT(y = sparse_diag_U2N(y, ycl), ypid); if (ytrans_) { REPROTECT(y = sparse_transpose(y, ycl, 0), ypid); ytrans_ = 0; } break; default: if (ycl[0] != kd) { REPROTECT(y = dense_as_kind(y, ycl, kd, 1), ypid); ycl = valid[R_check_class_etc(y, valid)]; } if (!unit && ycl[1] == 's') { REPROTECT(y = dense_as_general(y, ycl, y == y_), ypid); ycl = valid[R_check_class_etc(y, valid)]; } if (ytrans_) { REPROTECT(y = dense_transpose(y, ycl), ypid); ytrans_ = 0; } break; } SEXP z; PROTECT_INDEX zpid; const char *zcl = (margin == 0) ? ycl : xcl; PROTECT_WITH_INDEX(z = newObject(zcl), &zpid); SEXP zdim = PROTECT(GET_SLOT(z, Matrix_DimSym)); int *pzdim = INTEGER(zdim); pzdim[0] = m; pzdim[1] = n; UNPROTECT(1); /* zdim */ SEXP xdimnames = PROTECT(GET_SLOT(x, Matrix_DimNamesSym)), ydimnames = PROTECT(GET_SLOT(y, Matrix_DimNamesSym)), zdimnames = PROTECT(GET_SLOT(z, Matrix_DimNamesSym)); matmultDN(zdimnames, xdimnames, (xtrans_) ? 1 : 0, ydimnames, (ytrans_) ? 0 : 1); UNPROTECT(3); /* zdimnames, ydimnames, xdimnames */ char ul = '\0', di = '\0'; if (zcl[1] != 'g') { SEXP uplo = PROTECT(GET_SLOT((margin == 0) ? y : x, Matrix_uploSym)); ul = *CHAR(STRING_ELT(uplo, 0)); if (ul != 'U') SET_SLOT(z, Matrix_uploSym, uplo); UNPROTECT(1); /* uplo */ if (zcl[1] == 't') { SEXP diag = PROTECT(GET_SLOT((margin == 0) ? y : x, Matrix_diagSym)); di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N' && unit) SET_SLOT(z, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ } } if (zcl[2] == 'C' || zcl[2] == 'R' || zcl[2] == 'T') { if (zcl[2] != 'T') { SEXP p = PROTECT(GET_SLOT((margin == 0) ? y : x, Matrix_pSym)); SET_SLOT(z, Matrix_pSym, p); UNPROTECT(1); /* p */ } if (zcl[2] != 'R') { SEXP i = PROTECT(GET_SLOT((margin == 0) ? y : x, Matrix_iSym)); SET_SLOT(z, Matrix_iSym, i); UNPROTECT(1); /* i */ } if (zcl[2] != 'C') { SEXP j = PROTECT(GET_SLOT((margin == 0) ? y : x, Matrix_jSym)); SET_SLOT(z, Matrix_jSym, j); UNPROTECT(1); /* j */ } } SEXP x0 = PROTECT(GET_SLOT((margin == 0) ? y : x, Matrix_xSym)); if (unit || ((margin == 0) ? y != y_ : x != x_)) SET_SLOT(z, Matrix_xSym, x0); else { SEXP x1 = PROTECT(allocVector(TYPEOF(x0), XLENGTH(x0))); switch (kind) { case 'z': Matrix_memcpy(COMPLEX(x1), COMPLEX(x0), XLENGTH(x0), sizeof(Rcomplex)); break; case 'd': Matrix_memcpy( REAL(x1), REAL(x0), XLENGTH(x0), sizeof( double)); break; default: Matrix_memcpy(LOGICAL(x1), LOGICAL(x0), XLENGTH(x0), sizeof( int)); break; } SET_SLOT(z, Matrix_xSym, x1); UNPROTECT(1); /* x1 */ } UNPROTECT(1); /* x0 */ if (!unit) { SEXP d = PROTECT(GET_SLOT((margin == 0) ? x : y, Matrix_xSym)); switch (zcl[2]) { case 'C': if (margin == 0) Csparse_rowscale(z, d, Matrix_iSym); else Csparse_colscale(z, d); break; case 'R': if (margin == 0) Csparse_colscale(z, d); else Csparse_rowscale(z, d, Matrix_jSym); break; case 'T': if (margin == 0) Tsparse_rowscale(z, d, Matrix_iSym); else Tsparse_rowscale(z, d, Matrix_jSym); break; default: if (margin == 0) dense_rowscale(z, d, m, n, ul, di); else dense_colscale(z, d, m, n, ul, di); break; } UNPROTECT(1); /* d */ } if (boolean_ && (zcl[2] == 'C' || zcl[2] == 'R' || zcl[2] == 'T')) { REPROTECT(z = sparse_drop0(z, zcl, 0.0), zpid); REPROTECT(z = sparse_as_kind(z, zcl, 'n'), zpid); } UNPROTECT(3); /* z, y, x */ return z; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/subscript.h������������������������������������������������������������������������������0000644�0001751�0000144�00000000354�14503212600�014505� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_SUBSCRIPT_H #define MATRIX_SUBSCRIPT_H #include SEXP R_subscript_1ary (SEXP, SEXP); SEXP R_subscript_1ary_mat(SEXP, SEXP); SEXP R_subscript_2ary (SEXP, SEXP, SEXP); #endif /* MATRIX_SUBSCRIPT_H */ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/coerce.h���������������������������������������������������������������������������������0000644�0001751�0000144�00000004605�14512156155�013746� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_COERCE_H #define MATRIX_COERCE_H #include SEXP vector_as_dense(SEXP, const char *, char, char, int, int, int, SEXP); SEXP R_vector_as_dense(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); SEXP matrix_as_dense(SEXP, const char *, char, char, int, int); SEXP R_matrix_as_dense(SEXP, SEXP, SEXP, SEXP, SEXP); SEXP sparse_as_dense(SEXP, const char *, int); SEXP R_sparse_as_dense(SEXP, SEXP); SEXP diagonal_as_dense(SEXP, const char *, char, char, int, char); SEXP R_diagonal_as_dense(SEXP, SEXP, SEXP, SEXP, SEXP); SEXP index_as_dense(SEXP, const char *, char); SEXP R_index_as_dense(SEXP, SEXP); SEXP vector_as_sparse(SEXP, const char *, char, char, int, int, int, SEXP); SEXP R_vector_as_sparse(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); SEXP matrix_as_sparse(SEXP, const char *, char, char, int); SEXP R_matrix_as_sparse(SEXP, SEXP, SEXP, SEXP, SEXP); SEXP dense_as_sparse(SEXP, const char *, char); SEXP R_dense_as_sparse(SEXP, SEXP); SEXP diagonal_as_sparse(SEXP, const char *, char, char, char, char); SEXP R_diagonal_as_sparse(SEXP, SEXP, SEXP, SEXP, SEXP); SEXP index_as_sparse(SEXP, const char *, char, char); SEXP R_index_as_sparse(SEXP, SEXP, SEXP); SEXP dense_as_kind(SEXP, const char *, char, int); SEXP R_dense_as_kind(SEXP, SEXP); SEXP sparse_as_kind(SEXP, const char *, char); SEXP R_sparse_as_kind(SEXP, SEXP); SEXP diagonal_as_kind(SEXP, const char *, char); SEXP R_diagonal_as_kind(SEXP, SEXP); SEXP index_as_kind(SEXP, const char *, char); SEXP R_index_as_kind(SEXP, SEXP); SEXP dense_as_general(SEXP, const char *, int); SEXP R_dense_as_general(SEXP); SEXP sparse_as_general(SEXP, const char *); SEXP R_sparse_as_general(SEXP); SEXP dense_as_unpacked(SEXP, const char *); SEXP R_dense_as_unpacked(SEXP); SEXP dense_as_packed(SEXP, const char *, char, char); SEXP R_dense_as_packed(SEXP, SEXP, SEXP); SEXP sparse_as_Csparse(SEXP, const char *); SEXP R_sparse_as_Csparse(SEXP); SEXP sparse_as_Rsparse(SEXP, const char *); SEXP R_sparse_as_Rsparse(SEXP); SEXP sparse_as_Tsparse(SEXP, const char *); SEXP R_sparse_as_Tsparse(SEXP); SEXP R_Matrix_as_vector(SEXP); SEXP R_Matrix_as_matrix(SEXP); SEXP R_Matrix_as_unpacked(SEXP); SEXP R_Matrix_as_packed(SEXP); SEXP R_Matrix_as_Csparse(SEXP); SEXP R_Matrix_as_Rsparse(SEXP); SEXP R_Matrix_as_Tsparse(SEXP); SEXP R_Matrix_as_kind(SEXP, SEXP, SEXP); SEXP R_Matrix_as_general(SEXP, SEXP); #endif /* MATRIX_COERCE_H */ ���������������������������������������������������������������������������������������������������������������������������Matrix/src/t_rle.c����������������������������������������������������������������������������������0000644�0001751�0000144�00000004713�14575137654�013622� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*------ Definition of a template for Matrix_rle_[di](...) : * * -------- ~~~~~~~~~~~~~~~~~~~~~~ * i.e., included several times from ./abIndex.c * ~~~~~~~~~~~ */ /* for all cases with an 'x' slot -- i.e. almost all cases ; * just redefine this in the other cases: */ #ifdef _rle_d_ # define Matrix_RLE_ Matrix_rle_d # define Type_x_ double # define STYP_x_ REAL # define SXP_ans REALSXP #elif defined _rle_i_ # define Matrix_RLE_ Matrix_rle_i # define Type_x_ int # define STYP_x_ INTEGER # define SXP_ans INTSXP #else # error "invalid _rle_ macro logic" #endif /** * RLE (Run Length Encoding) -- only when it's worth * * @param x_ R vector which can be coerced to "double" / "integer" * @param force_ R logical indicating if the result must be "RLE" even when inefficient * * @return NULL or a valid R object of class "rle" */ SEXP Matrix_RLE_(SEXP x_, SEXP force_) { int n = LENGTH(PROTECT(x_ = coerceVector(x_, SXP_ans))); Rboolean no_force = !asLogical(force_); if (no_force && n < 3) { UNPROTECT(1); return R_NilValue; } else { register Type_x_ lv; register int ln, i, c = 0; int n2 = (no_force) ? n / 3 : n; /* upper bound: ==> max RAM requirement 2 x n2, (= 2/3 n); * using 2 instead of 3 would need 50% more time, have max * RAM requirement 2.5x for savings of any size */ Type_x_ *x = STYP_x_(x_), *val; int *len; const char *res_nms[] = {"lengths", "values", ""}; SEXP ans; if(n > 0) { /* needed for force=TRUE */ len = R_Calloc(n2, int); val = R_Calloc(n2, Type_x_); lv = x[0]; ln = 1; for(i = 1; i < n; i++) { if (x[i] == lv) { ln++; } else { val[c] = lv; len[c] = ln; c++; if (no_force && c == n2) { /* reached the "efficiency bound" */ R_Free(len); R_Free(val); UNPROTECT(1); return R_NilValue; } lv = x[i]; ln = 1; } } val[c] = lv; len[c] = ln; c++; } ans = PROTECT(Rf_mkNamed(VECSXP, res_nms)); SET_VECTOR_ELT(ans, 0, allocVector(INTSXP, c)); /* lengths */ SET_VECTOR_ELT(ans, 1, allocVector(SXP_ans, c)); /* values */ if(n > 0) { Memcpy(INTEGER(VECTOR_ELT(ans, 0)), len, c); Memcpy(STYP_x_(VECTOR_ELT(ans, 1)), val, c); } setAttrib(ans, R_ClassSymbol, mkString("rle")); if(n > 0) { R_Free(len); R_Free(val); } UNPROTECT(2); return ans; } } /* Matrix_RLE_() template */ #undef Matrix_RLE_ #undef Type_x_ #undef STYP_x_ #undef SXP_ans �����������������������������������������������������Matrix/src/idz.c������������������������������������������������������������������������������������0000644�0001751�0000144�00000030133�14574054152�013264� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Mdefines.h" #include "idz.h" #define IDZ \ TEMPLATE(i, int, 0 , 1 ) \ TEMPLATE(d, double, 0.0, 1.0) \ TEMPLATE(z, Rcomplex, Matrix_zzero, Matrix_zone) #define TEMPLATE(_PREFIX_, _CTYPE_, _ZERO_, _ONE_) \ static void _PREFIX_ ## \ swap(int n, _CTYPE_ *x, int incx, _CTYPE_ *y, int incy) \ { \ _CTYPE_ tmp; \ while (n--) { \ tmp = *x; \ *x = *y; \ *y = tmp; \ x += incx; \ y += incy; \ } \ return; \ } IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_, _ZERO_, _ONE_) \ static void _PREFIX_ ## \ syswapr(char uplo, int n, _CTYPE_ *x, int k0, int k1) \ { \ _CTYPE_ *x0 = x + (R_xlen_t) k0 * n, *x1 = x + (R_xlen_t) k1 * n, \ tmp; \ if (uplo == 'U') { \ _PREFIX_ ## swap(k0, x0, 1, x1, 1); \ tmp = x0[k0]; \ x0[k0] = x1[k1]; \ x1[k1] = tmp; \ _PREFIX_ ## swap(k1 - k0 - 1, x0 + k0 + n, n, x1 + k0 + 1, 1); \ _PREFIX_ ## swap(n - k1 - 1, x1 + k0 + n, n, x1 + k1 + n, n); \ } else { \ _PREFIX_ ## swap(k0, x + k0, n, x + k1, n); \ tmp = x0[k0]; \ x0[k0] = x1[k1]; \ x1[k1] = tmp; \ _PREFIX_ ## swap(k1 - k0 - 1, x0 + k0 + 1, 1, x0 + k1 + n, n); \ _PREFIX_ ## swap(n - k1 - 1, x0 + k1 + 1, 1, x1 + k1 + 1, 1); \ } \ return; \ } IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_, _ZERO_, _ONE_) \ void _PREFIX_ ## \ rowperm2(_CTYPE_ *x, int m, int n, int *p, int off, int invert) \ { \ int i, k0, k1; \ for (i = 0; i < m; ++i) \ p[i] = -(p[i] - off + 1); \ if (!invert) { \ for (i = 0; i < m; ++i) { \ if (p[i] > 0) \ continue; \ k0 = i; \ p[k0] = -p[k0]; \ k1 = p[k0] - 1; \ while (p[k1] < 0) { \ _PREFIX_ ## swap(n, x + k0, m, x + k1, m); \ k0 = k1; \ p[k0] = -p[k0]; \ k1 = p[k0] - 1; \ } \ } \ } else { \ for (i = 0; i < m; ++i) { \ if (p[i] > 0) \ continue; \ k0 = i; \ p[k0] = -p[k0]; \ k1 = p[k0] - 1; \ while (k1 != k0) { \ _PREFIX_ ## swap(n, x + k0, m, x + k1, m); \ p[k1] = -p[k1]; \ k1 = p[k1] - 1; \ } \ } \ } \ for (i = 0; i < m; ++i) \ p[i] = p[i] + off - 1; \ return; \ } IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_, _ZERO_, _ONE_) \ void _PREFIX_ ## \ symperm2(_CTYPE_ *x, int n, char uplo, int *p, int off, int invert) \ { \ int i, k0, k1; \ for (i = 0; i < n; ++i) \ p[i] = -(p[i] - off + 1); \ if (!invert) { \ for (i = 0; i < n; ++i) { \ if (p[i] > 0) \ continue; \ k0 = i; \ p[k0] = -p[k0]; \ k1 = p[k0] - 1; \ while (p[k1] < 0) { \ if (k0 < k1) \ _PREFIX_ ## syswapr(uplo, n, x, k0, k1); \ else \ _PREFIX_ ## syswapr(uplo, n, x, k1, k0); \ k0 = k1; \ p[k0] = -p[k0]; \ k1 = p[k0] - 1; \ } \ } \ } else { \ for (i = 0; i < n; ++i) { \ if (p[i] > 0) \ continue; \ k0 = i; \ p[k0] = -p[k0]; \ k1 = p[k0] - 1; \ while (k1 != k0) { \ if (k0 < k1) \ _PREFIX_ ## syswapr(uplo, n, x, k0, k1); \ else \ _PREFIX_ ## syswapr(uplo, n, x, k1, k0); \ p[k1] = -p[k1]; \ k1 = p[k1] - 1; \ } \ } \ } \ for (i = 0; i < n; ++i) \ p[i] = p[i] + off - 1; \ return; \ } IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_, _ZERO_, _ONE_) \ void _PREFIX_ ## \ pack2(_CTYPE_ *dest, const _CTYPE_ *src, int n, char uplo, char diag) \ { \ int i, j; \ R_xlen_t dpos = 0, spos = 0; \ if (uplo == 'U') { \ for (j = 0; j < n; spos += n-(++j)) \ for (i = 0; i <= j; ++i) \ dest[dpos++] = src[spos++]; \ if (diag != 'N') { \ dpos = 0; \ for (j = 0; j < n; dpos += (++j)+1) \ dest[dpos] = _ONE_; \ } \ } else { \ for (j = 0; j < n; spos += (++j)) \ for (i = j; i < n; ++i) \ dest[dpos++] = src[spos++]; \ if (diag != 'N') { \ dpos = 0; \ for (j = 0; j < n; dpos += n-(j++)) \ dest[dpos] = _ONE_; \ } \ } \ return; \ } IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_, _ZERO_, _ONE_) \ void _PREFIX_ ## \ unpack1(_CTYPE_ *dest, const _CTYPE_ *src, int n, char uplo, char diag) \ { \ int i, j; \ R_xlen_t dpos = 0, spos = 0; \ if (uplo == 'U') { \ for (j = 0; j < n; dpos += n-(++j)) \ for (i = 0; i <= j; ++i) \ dest[dpos++] = src[spos++]; \ } else { \ for (j = 0; j < n; dpos += (++j)) \ for (i = j; i < n; ++i) \ dest[dpos++] = src[spos++]; \ } \ if (diag != 'N') { \ dpos = 0; \ R_xlen_t n1a = (R_xlen_t) n + 1; \ for (j = 0; j < n; ++j, dpos += n1a) \ dest[dpos] = _ONE_; \ } \ return; \ } IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_, _ZERO_, _ONE_) \ void _PREFIX_ ## \ transpose2(_CTYPE_ *dest, const _CTYPE_ *src, int m, int n) \ { \ R_xlen_t mn1s = (R_xlen_t) m * n - 1; \ int i, j; \ for (j = 0; j < m; ++j, src -= mn1s) \ for (i = 0; i < n; ++i, src += m) \ *(dest++) = *src; \ return; \ } IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_, _ZERO_, _ONE_) \ void _PREFIX_ ## \ transpose1(_CTYPE_ *dest, const _CTYPE_ *src, int n, char uplo) \ { \ int i, j; \ if (uplo == 'U') { \ for (j = 0; j < n; ++j) \ for (i = j; i < n; ++i) \ *(dest++) = *(src + PACKED_AR21_UP(j, i)); \ } else { \ R_xlen_t n2 = (R_xlen_t) n * 2; \ for (j = 0; j < n; ++j) \ for (i = 0; i <= j; ++i) \ *(dest++) = *(src + PACKED_AR21_LO(j, i, n2)); \ } \ return; \ } IDZ #undef TEMPLATE #define ASSIGN_JJ_i(_X_) #define ASSIGN_JJ_d(_X_) #define ASSIGN_JJ_z(_X_) \ _X_.i = 0.0 #define ASSIGN_JI_i(_X_, _Y_) \ _X_ = _Y_ #define ASSIGN_JI_d(_X_, _Y_) \ _X_ = _Y_ #define ASSIGN_JI_z(_X_, _Y_) \ do { \ _X_.r = _Y_.r; \ _X_.i = -_Y_.i; \ } while (0) #define TEMPLATE(_PREFIX_, _CTYPE_, _ZERO_, _ONE_) \ void _PREFIX_ ## \ syforce2(_CTYPE_ *x, int n, char uplo) \ { \ _CTYPE_ *y = x; \ int i, j; \ if (uplo == 'U') { \ for (j = 0; j < n; ++j) { \ ASSIGN_JJ_ ## _PREFIX_((*x)); \ x += 1; \ y += n; \ for (i = j + 1; i < n; ++i) { \ ASSIGN_JI_ ## _PREFIX_((*x), (*y)); \ x += 1; \ y += n; \ } \ x = y = x + j + 1; \ } \ } else { \ for (j = 0; j < n; ++j) { \ ASSIGN_JJ_ ## _PREFIX_((*y)); \ x += 1; \ y += n; \ for (i = j + 1; i < n; ++i) { \ ASSIGN_JI_ ## _PREFIX_((*y), (*x)); \ x += 1; \ y += n; \ } \ x = y = x + j + 1; \ } \ } \ return; \ } IDZ #undef TEMPLATE #undef ASSIGN_JJ_i #undef ASSIGN_JJ_d #undef ASSIGN_JJ_z #undef ASSIGN_JI_i #undef ASSIGN_JI_d #undef ASSIGN_JI_z #define TEMPLATE(_PREFIX_, _CTYPE_, _ZERO_, _ONE_) \ void _PREFIX_ ## \ trforce2(_CTYPE_ *x, int m, int n, char uplo, char diag) \ { \ _CTYPE_ *y = x; \ int i, j, r = (m < n) ? m : n; \ if (uplo == 'U') { \ for (j = 0; j < r; ++j) { \ for (i = j + 1; i < m; ++i) \ *(++x) = _ZERO_; \ x += j + 2; \ } \ } else { \ for (j = 0; j < r; ++j) { \ for (i = 0; i < j; ++i) \ *(x++) = _ZERO_; \ x += m - j; \ } \ for (j = r; j < n; ++j) \ for (i = 0; i < m; ++i) \ *(x++) = _ZERO_; \ } \ if (diag != 'N') { \ R_xlen_t m1a = (R_xlen_t) m + 1; \ for (j = 0; j < r; ++j) { \ *y = _ONE_; \ y += m1a; \ } \ } \ return; \ } IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_, _ZERO_, _ONE_) \ void _PREFIX_ ## \ band2(_CTYPE_ *x, int m, int n, int a, int b, char diag) \ { \ if (m == 0 || n == 0) \ return; \ if (a > b || a >= n || b <= -m) { \ Matrix_memset(x, 0, (R_xlen_t) m * n, sizeof(_CTYPE_)); \ return; \ } \ if (a <= -m) a = 1-m; \ if (b >= n) b = n-1; \ \ int i, j, i0, i1, \ j0 = (a < 0) ? 0 : a, \ j1 = (b < n-m) ? m+b : n; \ \ if (j0 > 0) { \ R_xlen_t dx = (R_xlen_t) m * j0; \ Matrix_memset(x, 0, dx, sizeof(_CTYPE_)); \ x += dx; \ } \ for (j = j0; j < j1; ++j, x += m) { \ i0 = j - b; \ i1 = j - a + 1; \ for (i = 0; i < i0; ++i) \ *(x + i) = _ZERO_; \ for (i = i1; i < m; ++i) \ *(x + i) = _ZERO_; \ } \ if (j1 < n) \ Matrix_memset(x, 0, (R_xlen_t) m * (n - j1), sizeof(_CTYPE_)); \ if (diag != 'N' && a <= 0 && b >= 0) { \ x -= m * (R_xlen_t) j; \ R_xlen_t m1a = (R_xlen_t) m + 1; \ for (j = 0; j < n; ++j, x += m1a) \ *x = _ONE_; \ } \ return; \ } IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_, _ZERO_, _ONE_) \ void _PREFIX_ ## \ band1(_CTYPE_ *x, int n, int a, int b, char uplo, char diag) \ { \ if (n == 0) \ return; \ if (a > b || a >= n || b <= -n) { \ Matrix_memset(x, 0, PACKED_LENGTH(n), sizeof(_CTYPE_)); \ return; \ } \ if (uplo == 'U') { \ if (a < 0) a = 0; \ if (b >= n) b = n-1; \ } else { \ if (b > 0) b = 0; \ if (a <= -n) a = 1-n; \ } \ \ int i, j, i0, i1, \ j0 = (a < 0) ? 0 : a, \ j1 = (b < 0) ? n+b : n; \ \ if (uplo == 'U') { \ if (j0 > 0) { \ R_xlen_t dx; \ Matrix_memset(x, 0, dx = PACKED_LENGTH(j0), \ sizeof(_CTYPE_)); \ x += dx; \ } \ for (j = j0; j < j1; x += (++j)) { \ i0 = j - b; \ i1 = j - a + 1; \ for (i = 0; i < i0; ++i) \ *(x + i) = _ZERO_; \ for (i = i1; i <= j; ++i) \ *(x + i) = _ZERO_; \ } \ if (j1 < n) \ Matrix_memset(x, 0, PACKED_LENGTH(n) - PACKED_LENGTH(j1), \ sizeof(_CTYPE_)); \ if (diag != 'N' && a == 0) { \ x -= PACKED_LENGTH(j); \ for (j = 0; j < n; x += (++j)+1) \ *x = _ONE_; \ } \ } else { \ if (j0 > 0) { \ R_xlen_t dx = PACKED_LENGTH(n) - PACKED_LENGTH(j0); \ Matrix_memset(x, 0, dx, sizeof(_CTYPE_)); \ x += dx; \ } \ for (j = j0; j < j1; x += n-(j++)) { \ i0 = j - b; \ i1 = j - a + 1; \ for (i = j; i < i0; ++i) \ *(x + i - j) = _ZERO_; \ for (i = i1; i < n; ++i) \ *(x + i - j) = _ZERO_; \ } \ if (j1 < n) \ Matrix_memset(x, 0, PACKED_LENGTH(n - j1), \ sizeof(_CTYPE_)); \ if (diag != 'N' && b == 0) { \ x -= PACKED_LENGTH(n) - PACKED_LENGTH(j); \ for (j = 0; j < n; x += n-(j++)) \ *x = _ONE_; \ } \ } \ return; \ } IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_, _ZERO_, _ONE_) \ void _PREFIX_ ## \ dcpy2(_CTYPE_ *dest, const _CTYPE_ *src, int n, R_xlen_t length, \ char uplo, char diag) \ { \ int j; \ R_xlen_t n1a = (R_xlen_t) n + 1; \ if (diag != 'N') { \ for (j = 0; j < n; ++j, dest += n1a) \ *dest = _ONE_; \ } else if (length == n) { \ /* copying from diagonalMatrix */ \ for (j = 0; j < n; ++j, dest += n1a, ++src) \ *dest = *src; \ } else if (length == (n * n1a) / 2) { \ /* copying from packedMatrix */ \ if (uplo == 'U') { \ for (j = 0; j < n; dest += n1a, src += (++j)+1) \ *dest = *src; \ } else { \ for (j = 0; j < n; dest += n1a, src += n-(j++)) \ *dest = *src; \ } \ } else if (length == (R_xlen_t) n * n) { \ /* copying from square unpackedMatrix */ \ for (j = 0; j < n; ++j, dest += n1a, src += n1a) \ *dest = *src; \ } else { \ error(_("incompatible '%s' and '%s' in '%s'"), \ "n", "length", __func__); \ } \ return; \ } IDZ #undef TEMPLATE #define TEMPLATE(_PREFIX_, _CTYPE_, _ZERO_, _ONE_) \ void _PREFIX_ ## \ dcpy1(_CTYPE_ *dest, const _CTYPE_ *src, int n, R_xlen_t length, \ char uplo_dest, char uplo_src, char diag) \ { \ int j; \ if (diag != 'N') { \ if (uplo_dest == 'U') { \ for (j = 0; j < n; dest += (++j)+1) \ *dest = _ONE_; \ } else { \ for (j = 0; j < n; dest += n-(j++)) \ *dest = _ONE_; \ } \ } else if (length == n) { \ /* copying from diagonalMatrix */ \ if (uplo_dest == 'U') { \ for (j = 0; j < n; dest += (++j)+1, ++src) \ *dest = *src; \ } else { \ for (j = 0; j < n; dest += n-(j++), ++src) \ *dest = *src; \ } \ } else if (length == PACKED_LENGTH(n)) { \ /* copying from packedMatrix */ \ if (uplo_dest == 'U') { \ if (uplo_src == 'U') { \ for (j = 0; j < n; src += (++j)+1, dest += j+1) \ *dest = *src; \ } else { \ for (j = 0; j < n; src += n-j, dest += (++j)+1) \ *dest = *src; \ } \ } else { \ if (uplo_src == 'U') { \ for (j = 0; j < n; dest += n-(j++), src += j+1) \ *dest = *src; \ } else { \ for (j = 0; j < n; dest += n-j, src += n-(j++)) \ *dest = *src; \ } \ } \ } else if (length == (R_xlen_t) n * n) { \ /* copying from square unpackedMatrix */ \ R_xlen_t n1a = (R_xlen_t) n + 1; \ if (uplo_dest == 'U') { \ for (j = 0; j < n; dest += (++j)+1, src += n1a) \ *dest = *src; \ } else { \ for (j = 0; j < n; dest += n-(j++), src += n1a) \ *dest = *src; \ } \ } else { \ error(_("incompatible '%s' and '%s' in '%s'"), \ "n", "length", __func__); \ } \ return; \ } IDZ #undef TEMPLATE #undef IDZ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/cholmod-common.c�������������������������������������������������������������������������0000644�0001751�0000144�00000113400�14575137654�015422� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Mdefines.h" #include "cholmod-common.h" /* NB: mostly parallel to CsparseMatrix_validate in ./validity.c */ SEXP checkpi(SEXP p, SEXP i, int m, int n) { #define MKMS(_FORMAT_, ...) mkString(Matrix_sprintf(_FORMAT_, __VA_ARGS__)) if (TYPEOF(p) != INTSXP) return MKMS(_("'%s' slot is not of type \"%s\""), "p", "integer"); if (XLENGTH(p) - 1 != n) return MKMS(_("'%s' slot does not have length %s"), "p", "Dim[2]+1"); int *pp = INTEGER(p); if (pp[0] != 0) return MKMS(_("first element of '%s' slot is not 0"), "p"); int j; for (j = 1; j <= n; ++j) { if (pp[j] == NA_INTEGER) return MKMS(_("'%s' slot contains NA"), "p"); if (pp[j] < pp[j - 1]) return MKMS(_("'%s' slot is not nondecreasing"), "p"); if (pp[j] - pp[j - 1] > m) return MKMS(_("first differences of '%s' slot exceed %s"), "p", "Dim[1]"); } if (TYPEOF(i) != INTSXP) return MKMS(_("'%s' slot is not of type \"%s\""), "i", "integer"); if (XLENGTH(i) < pp[n]) return MKMS(_("'%s' slot has length less than %s"), "i", "p[length(p)]"); int *pi = INTEGER(i), k, kend, ik, i0, sorted = 1; for (j = 1, k = 0; j <= n; ++j) { kend = pp[j]; i0 = -1; while (k < kend) { ik = pi[k]; if (ik == NA_INTEGER) return MKMS(_("'%s' slot contains NA"), "i"); if (ik < 0 || ik >= m) return MKMS(_("'%s' slot has elements not in {%s}"), "i", "0,...,Dim[1]-1"); if (ik < i0) sorted = 0; else if (ik == i0) return MKMS(_("'%s' slot is not increasing within columns after sorting"), "i"); i0 = ik; ++k; } } SEXP ans = allocVector(LGLSXP, 1); LOGICAL(ans)[0] = sorted; return ans; } /** * Coerce from CHMfactor to (cholmod_factor *) * * Sets the members of a pointed-to cholmod_factor struct, using "data" * obtained from slots of a CHMfactor. The result should _not_ be * freed using cholmod_free_factor, as the resulting members point to * memory controlled by R, not by CHOLMOD. * * @param L a pointer to a cholmod_factor struct, to be modified in-place. * @param from an S4 object inheriting from virtual class CHMfactor. * * @return L. */ /* NB: mostly parallel to M2CHF in ./cholmod-etc.c */ cholmod_factor *sexp_as_cholmod_factor(cholmod_factor *L, SEXP from) { static const char *valid[] = { "dCHMsuper", "dCHMsimpl", "nCHMsuper", "nCHMsimpl", "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *class = valid[ivalid]; memset(L, 0, sizeof(cholmod_factor)); SEXP dim = PROTECT(GET_SLOT(from, Matrix_DimSym)), type = PROTECT(GET_SLOT(from, install("type"))), perm = PROTECT(GET_SLOT(from, Matrix_permSym)), colcount = PROTECT(GET_SLOT(from, install("colcount"))); L->n = INTEGER(dim)[0]; L->minor = L->n; /* FIXME: could be wrong for from <- new(...) */ L->ordering = INTEGER(type)[0]; if (L->ordering != CHOLMOD_NATURAL) L->Perm = INTEGER(perm); else { /* cholmod_check_factor allows L->Perm == NULL, but cholmod_copy_factor does not test, so it segfaults ... */ int n = (int) L->n, *Perm = (int *) R_alloc(L->n, sizeof(int)); for (int j = 0; j < n; ++j) Perm[j] = j; L->Perm = Perm; } L->ColCount = INTEGER(colcount); L->is_super = INTEGER(type)[2]; if (L->is_super) { L->is_ll = 1; L->is_monotonic = 1; SEXP super = PROTECT(GET_SLOT(from, install("super"))), pi = PROTECT(GET_SLOT(from, install("pi"))), px = PROTECT(GET_SLOT(from, install("px"))), s = PROTECT(GET_SLOT(from, install("s"))); L->super = INTEGER(super); L->pi = INTEGER(pi); L->px = INTEGER(px); L->s = INTEGER(s); L->nsuper = LENGTH(super) - 1; L->ssize = ((int *) L->pi)[L->nsuper]; L->xsize = ((int *) L->px)[L->nsuper]; L->maxcsize = INTEGER(type)[4]; L->maxesize = INTEGER(type)[5]; UNPROTECT(4); } else { L->is_ll = INTEGER(type)[1]; L->is_monotonic = INTEGER(type)[3]; if (class[0] != 'n') { SEXP p = PROTECT(GET_SLOT(from, Matrix_pSym)), i = PROTECT(GET_SLOT(from, Matrix_iSym)), nz = PROTECT(GET_SLOT(from, install("nz"))), nxt = PROTECT(GET_SLOT(from, install("nxt"))), prv = PROTECT(GET_SLOT(from, install("prv"))); L->p = INTEGER(p); L->i = INTEGER(i); L->nz = INTEGER(nz); L->next = INTEGER(nxt); L->prev = INTEGER(prv); L->nzmax = ((int *) L->p)[L->n]; UNPROTECT(5); } } L->itype = CHOLMOD_INT; L->dtype = CHOLMOD_DOUBLE; if (class[0] != 'n') { SEXP x = GET_SLOT(from, Matrix_xSym); switch (TYPEOF(x)) { case CPLXSXP: L->x = COMPLEX(x); L->xtype = CHOLMOD_COMPLEX; break; case REALSXP: L->x = REAL(x); L->xtype = CHOLMOD_REAL; break; default: ERROR_INVALID_TYPE(x, __func__); break; } } if (!cholmod_check_factor(L, &c)) error(_("'%s' failed in '%s'"), "cholmod_check_factor", __func__); UNPROTECT(4); return L; } /** * Coerce from CsparseMatrix to (cholmod_sparse *) * * Sets the members of a pointed-to cholmod_sparse struct, using "data" * obtained from slots of a CsparseMatrix. The result should _not_ be * freed using cholmod_free_sparse, as the resulting members point to * memory controlled by R, not by CHOLMOD. * * @param A a pointer to a cholmod_sparse struct, to be modified in-place. * @param from an S4 object inheriting from virtual class CsparseMatrix. * @param checkUnit a boolean indicating if the unit diagonal of formally * unit triangular CsparseMatrix should be allocated. * @param sortInPlace a boolean indicating if unsorted CsparseMatrix * should be sorted in place to avoid an allocation. * * @return A. */ /* NB: mostly parallel to M2CHS in ./cholmod-etc.c */ cholmod_sparse *sexp_as_cholmod_sparse(cholmod_sparse *A, SEXP from, Rboolean checkUnit, Rboolean sortInPlace) { /* MJ: Do users really ever pass invalid 'from' ... ? If not, then the code here could be simplified tremendously ... */ static const char *valid[] = { "dgCMatrix", "dsCMatrix", "dtCMatrix", "lgCMatrix", "lsCMatrix", "ltCMatrix", "ngCMatrix", "nsCMatrix", "ntCMatrix", "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *class = valid[ivalid]; memset(A, 0, sizeof(cholmod_sparse)); SEXP dim = GET_SLOT(from, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; SEXP p = PROTECT(GET_SLOT(from, Matrix_pSym)), i = PROTECT(GET_SLOT(from, Matrix_iSym)), cpi = PROTECT(checkpi(p, i, m, n)); if (TYPEOF(cpi) != LGLSXP) error(_("'%s' failed in '%s': %s"), "checkpi", __func__, CHAR(STRING_ELT(cpi, 0))); int *pp = INTEGER(p), *pi = INTEGER(i), sorted = LOGICAL(cpi)[0]; size_t np = (size_t) XLENGTH(p), ni = (size_t) XLENGTH(i); if (!sorted && !sortInPlace) { int *tmp; tmp = (int *) R_alloc(np, sizeof(int)); memcpy(tmp, pp, np * sizeof(int)); pp = tmp; tmp = (int *) R_alloc(ni, sizeof(int)); memcpy(tmp, pi, ni * sizeof(int)); pi = tmp; } A->nrow = m; A->ncol = n; A->p = pp; A->i = pi; A->nzmax = ni; A->stype = 0; A->itype = CHOLMOD_INT; A->xtype = CHOLMOD_PATTERN; A->dtype = CHOLMOD_DOUBLE; A->sorted = LOGICAL(cpi)[0]; A->packed = 1; if (ni > pp[n]) { /* overallocated */ A->packed = 0; int *tmp = (int *) R_alloc(n, sizeof(int)); for (int j = 0; j < n; ++j) tmp[j] = pp[j + 1] - pp[j]; A->nz = tmp; } if (class[1] == 's') { SEXP uplo = GET_SLOT(from, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); A->stype = (ul == 'U') ? 1 : -1; } if (class[0] != 'n') { SEXP x = PROTECT(GET_SLOT(from, Matrix_xSym)); size_t nx = (size_t) XLENGTH(x); switch (class[0]) { case 'l': case 'i': { int *px = (TYPEOF(x) == LGLSXP) ? LOGICAL(x) : INTEGER(x); double *rtmp = (double *) R_alloc(nx, sizeof(double)); for (size_t ix = 0; ix < nx; ++ix) rtmp[ix] = (px[ix] == NA_INTEGER) ? NA_REAL : (double) px[ix]; A->x = rtmp; A->xtype = CHOLMOD_REAL; break; } case 'd': { double *px = REAL(x); if (!sorted && !sortInPlace) { double *rtmp = (double *) R_alloc(nx, sizeof(double)); memcpy(rtmp, px, nx * sizeof(double)); px = rtmp; } A->x = px; A->xtype = CHOLMOD_REAL; break; } case 'z': { Rcomplex *px = COMPLEX(x); if (!sorted && !sortInPlace) { Rcomplex *rtmp = (Rcomplex *) R_alloc(nx, sizeof(Rcomplex)); memcpy(rtmp, px, nx * sizeof(Rcomplex)); px = rtmp; } A->x = px; A->xtype = CHOLMOD_COMPLEX; break; } default: break; } UNPROTECT(1); /* x */ } if (!sorted && !cholmod_sort(A, &c)) error(_("'%s' failed in '%s'"), "cholmod_sort", __func__); if (checkUnit && class[1] == 't' && n > 0) { SEXP diag = GET_SLOT(from, Matrix_diagSym); char di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N') { double one[] = { 1.0, 0.0 }; cholmod_sparse *eye = cholmod_speye(n, n, A->xtype, &c), *A1a = cholmod_add(A, eye, one, one, 1, 1, &c); memcpy(A, A1a, sizeof(cholmod_sparse)); A->p = (int *) R_alloc(A1a->ncol + 1, sizeof(int)); memcpy(A->p, A1a->p, (A1a->ncol + 1) * sizeof(int)); A->i = (int *) R_alloc(A1a->nzmax, sizeof(int)); memcpy(A->i, A1a->i, A1a->nzmax * sizeof(int)); if (A1a->xtype != CHOLMOD_PATTERN) { size_t size = (A1a->xtype == CHOLMOD_REAL) ? sizeof(double) : sizeof(Rcomplex); A->x = R_alloc(A1a->nzmax, size); memcpy(A->x, A1a->x, A1a->nzmax * size); } cholmod_free_sparse(&eye, &c); cholmod_free_sparse(&A1a, &c); } } UNPROTECT(3); /* cpi, i, p */ return A; } /** * Coerce from TsparseMatrix to (cholmod_triplet *) * * Sets the members of a pointed-to cholmod_triplet struct, using "data" * obtained from slots of a TsparseMatrix. The result should _not_ be * freed using cholmod_free_sparse, as the resulting members point to * memory controlled by R, not by CHOLMOD. * * @param A a pointer to a cholmod_triplet struct, to be modified in-place. * @param from an S4 object inheriting from virtual class TsparseMatrix. * @param checkUnit a boolean indicating if the unit diagonal of formally * unit triangular TsparseMatrix should be allocated. * * @return A. */ cholmod_triplet *sexp_as_cholmod_triplet(cholmod_triplet *A, SEXP from, Rboolean checkUnit) { static const char *valid[] = { "dgTMatrix", "dsTMatrix", "dtTMatrix", "lgTMatrix", "lsTMatrix", "ltTMatrix", "ngTMatrix", "nsTMatrix", "ntTMatrix", "" }; int ivalid = R_check_class_etc(from, valid); if (ivalid < 0) ERROR_INVALID_CLASS(from, __func__); const char *class = valid[ivalid]; memset(A, 0, sizeof(cholmod_triplet)); SEXP dim = GET_SLOT(from, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; SEXP i = PROTECT(GET_SLOT(from, Matrix_pSym)), j = PROTECT(GET_SLOT(from, Matrix_iSym)); int *pi = INTEGER(i), *pj = INTEGER(j); size_t nnz0 = (size_t) XLENGTH(i), nnz1 = nnz0; if (checkUnit && class[1] == 't') { SEXP diag = GET_SLOT(from, Matrix_diagSym); char di = *CHAR(STRING_ELT(diag, 0)); if (di != 'N') nnz1 += n; } if (nnz0 < nnz1) { int *tmp; tmp = (int *) R_alloc(nnz1, sizeof(int)); memcpy(tmp, pi, nnz1 * sizeof(int)); pi = tmp; tmp = (int *) R_alloc(nnz1, sizeof(int)); memcpy(tmp, pj, nnz1 * sizeof(int)); pj = tmp; pi += nnz0; pj += nnz0; for (int d = 0; d < n; ++d) *(pi++) = *(pj++) = d; pi -= nnz1; pj -= nnz1; } A->nrow = m; A->ncol = n; A->i = pi; A->j = pj; A->nzmax = nnz1; A->nnz = nnz1; A->stype = 0; A->itype = CHOLMOD_INT; A->xtype = CHOLMOD_PATTERN; A->dtype = CHOLMOD_DOUBLE; if (class[1] == 's') { SEXP uplo = GET_SLOT(from, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); A->stype = (ul == 'U') ? 1 : -1; } if (class[0] != 'n') { SEXP x = PROTECT(GET_SLOT(from, Matrix_xSym)); switch (class[0]) { case 'l': case 'i': { int *px = (TYPEOF(x) == LGLSXP) ? LOGICAL(x) : INTEGER(x); double *rtmp = (double *) R_alloc(nnz1, sizeof(double)); for (size_t k = 0; k < nnz0; ++k) rtmp[k] = (px[k] == NA_INTEGER) ? NA_REAL : (double) px[k]; for (size_t k = nnz0; k < nnz1; ++k) rtmp[k] = 1.0; A->x = rtmp; A->xtype = CHOLMOD_REAL; break; } case 'd': { double *px = REAL(x); if (nnz0 < nnz1) { double *rtmp = (double *) R_alloc(nnz1, sizeof(double)); memcpy(rtmp, px, nnz0 * sizeof(double)); for (size_t k = nnz0; k < nnz1; ++k) rtmp[k] = 1.0; px = rtmp; } A->x = px; A->xtype = CHOLMOD_REAL; break; } case 'z': { Rcomplex *px = COMPLEX(x); if (nnz0 < nnz1) { Rcomplex *rtmp = (Rcomplex *) R_alloc(nnz1, sizeof(Rcomplex)); memcpy(rtmp, px, nnz0 * sizeof(Rcomplex)); for (size_t k = nnz0; k < nnz1; ++k) rtmp[k] = Matrix_zone; px = rtmp; } A->x = px; A->xtype = CHOLMOD_COMPLEX; break; } default: break; } UNPROTECT(1); /* x */ } UNPROTECT(2); /* j, i */ return A; } /** * Coerce from [nlidz]geMatrix or vector to (cholmod_dense *) * * Sets the members of a pointed-to cholmod_dense struct, using "data" * obtained from slots of a [nlidz]geMatrix. The result should _not_ be * freed using cholmod_free_dense, as the resulting members point to * memory controlled by R, not by CHOLMOD. * * @param A a pointer to a cholmod_dense struct, to be modified in-place. * @param from an S4 object inheriting from class [nlidz]geMatrix _or_ * a traditional vector of type "logical", "integer", "double", or * "complex" (to be handled as a 1-column matrix if not a matrix). * * @return A. */ /* NB: mostly parallel to M2CHD in ./cholmod-etc.c */ cholmod_dense *sexp_as_cholmod_dense(cholmod_dense *A, SEXP from) { static const char *valid[] = { "dgeMatrix", "lgeMatrix", "ngeMatrix", "" }; int ivalid = R_check_class_etc(from, valid); memset(A, 0, sizeof(cholmod_dense)); int m, n; if (ivalid < 0) { switch (TYPEOF(from)) { case LGLSXP: case INTSXP: case REALSXP: case CPLXSXP: break; default: ERROR_INVALID_TYPE(from, __func__); break; } SEXP dim = getAttrib(from, R_DimSymbol); if (TYPEOF(dim) == INTSXP && LENGTH(dim) == 2) { m = INTEGER(dim)[0]; n = INTEGER(dim)[1]; } else { m = LENGTH(from); n = 1; } } else { SEXP dim = GET_SLOT(from, Matrix_DimSym); m = INTEGER(dim)[0]; n = INTEGER(dim)[1]; from = GET_SLOT(from, Matrix_xSym); } A->nrow = m; A->ncol = n; A->nzmax = A->nrow * A->ncol; A->d = A->nrow; A->dtype = CHOLMOD_DOUBLE; size_t nx = (size_t) XLENGTH(from); switch (TYPEOF(from)) { case LGLSXP: case INTSXP: { int *px = (TYPEOF(from) == LGLSXP) ? LOGICAL(from) : INTEGER(from), pattern = ivalid == 2; double *rtmp = (double *) R_alloc(nx + 1, sizeof(double)); for (size_t ix = 0; ix < nx; ++ix) rtmp[ix] = (px[ix] == NA_INTEGER) ? ((pattern) ? 1.0 : NA_REAL) : (double) px[ix]; A->x = rtmp; A->xtype = CHOLMOD_REAL; break; } case REALSXP: A->x = REAL(from); A->xtype = CHOLMOD_REAL; break; case CPLXSXP: A->x = COMPLEX(from); A->xtype = CHOLMOD_COMPLEX; break; default: ERROR_INVALID_TYPE(from, __func__); break; } return A; } /** * Coerce from (double *) to (cholmod_dense *) with given dimensions * * An analogue of base::matrix(data, nrow, ncol), * where typeof(data)=="double" and length(data)==nrow*ncol. * * @param A a pointer to a cholmod_dense struct, to be modified in-place. * @param data a pointer to an nrow*ncol*sizeof(double) block of memory. * @param nrow the desired number of rows. * @param ncol the desired number of columns. * * @return A. */ cholmod_dense *numeric_as_cholmod_dense(cholmod_dense *A, double *data, int nrow, int ncol) { memset(A, 0, sizeof(cholmod_dense)); A->nrow = nrow; A->ncol = ncol; A->nzmax = A->nrow * A->ncol; A->d = A->nrow; A->x = data; A->xtype = CHOLMOD_REAL; A->dtype = CHOLMOD_DOUBLE; return A; } /** * Coerce from (cholmod_factor *) to CHMfactor * * Allocates an S4 object inheriting from virtual class CHMfactor * and copies into the slots from members of a pointed-to cholmod_factor * struct. The specific class of the result is determined by struct * members xtype and is_super. * * @param L a pointer to a cholmod_factor struct. * @param doFree a flag indicating if and how to free L before returning. * (0) don't free, (>0) free with cholmod_free_factor, (<0) free with * R_Free. * * @return A CHMfactor. */ /* NB: mostly parallel to CHF2M in ./cholmod-etc.c */ SEXP cholmod_factor_as_sexp(cholmod_factor *L, int doFree) { #define FREE_THEN(_EXPR_) \ do { \ if (doFree != 0) { \ if (doFree < 0) \ R_Free(L); \ else if (L->itype == CHOLMOD_INT) \ cholmod_free_factor(&L, &c); \ else \ cholmod_l_free_factor(&L, &cl); \ _EXPR_; \ } \ } while (0) if (L->itype != CHOLMOD_INT) FREE_THEN(error(_("wrong '%s'"), "itype")); if (L->xtype != CHOLMOD_PATTERN && L->xtype != CHOLMOD_REAL && L->xtype != CHOLMOD_COMPLEX) FREE_THEN(error(_("wrong '%s'"), "xtype")); if (L->dtype != CHOLMOD_DOUBLE) FREE_THEN(error(_("wrong '%s'"), "dtype")); if (L->n > INT_MAX) FREE_THEN(error(_("dimensions cannot exceed %s"), "2^31-1")); if (L->super) { if (L->maxcsize > INT_MAX) FREE_THEN(error(_("'%s' would overflow type \"%s\""), "maxcsize", "integer")); } else { if (L->n == INT_MAX) FREE_THEN(error(_("n+1 would overflow type \"%s\""), "integer")); } if (L->minor < L->n) { if (L->is_ll) FREE_THEN(error(_("leading principal minor of order %d is not positive"), (int) L->minor + 1)); else FREE_THEN(error(_("leading principal minor of order %d is zero"), (int) L->minor + 1)); } char class[] = ".CHM....."; class[0] = (L->xtype == CHOLMOD_PATTERN) ? 'n' : ((L->xtype == CHOLMOD_COMPLEX) ? 'z' : 'd'); memcpy(class + 4, (L->is_super) ? "super" : "simpl", 5); SEXP to = PROTECT(newObject(class)), dim = PROTECT(GET_SLOT(to, Matrix_DimSym)); INTEGER(dim)[0] = INTEGER(dim)[1] = (int) L->n; if (L->ordering != CHOLMOD_NATURAL) { SEXP perm = PROTECT(allocVector(INTSXP, L->n)); memcpy(INTEGER(perm), L->Perm, L->n * sizeof(int)); SET_SLOT(to, Matrix_permSym, perm); UNPROTECT(1); } SEXP type = PROTECT(allocVector(INTSXP, 6)), colcount = PROTECT(allocVector(INTSXP, L->n)); INTEGER(type)[0] = L->ordering; INTEGER(type)[1] = (L->is_super) ? 1 : L->is_ll; INTEGER(type)[2] = (L->is_super) ? 1 : 0; INTEGER(type)[3] = (L->is_super) ? 1 : L->is_monotonic; INTEGER(type)[4] = (L->is_super) ? (int) L->maxcsize : 0; INTEGER(type)[5] = (L->is_super) ? (int) L->maxesize : 0; memcpy(INTEGER(colcount), L->ColCount, L->n * sizeof(int)); SET_SLOT(to, install("type"), type); SET_SLOT(to, install("colcount"), colcount); if (L->is_super) { SEXP super = PROTECT(allocVector(INTSXP, L->nsuper + 1)), pi = PROTECT(allocVector(INTSXP, L->nsuper + 1)), px = PROTECT(allocVector(INTSXP, L->nsuper + 1)), s = PROTECT(allocVector(INTSXP, L->ssize)); memcpy(INTEGER(super), L->super, (L->nsuper + 1) * sizeof(int)); memcpy(INTEGER(pi), L->pi, (L->nsuper + 1) * sizeof(int)); memcpy(INTEGER(px), L->px, (L->nsuper + 1) * sizeof(int)); memcpy(INTEGER(s), L->s, L->ssize * sizeof(int)); SET_SLOT(to, install("super"), super); SET_SLOT(to, install("pi"), pi); SET_SLOT(to, install("px"), px); SET_SLOT(to, install("s"), s); UNPROTECT(4); } else if (L->xtype != CHOLMOD_PATTERN) { SEXP p = PROTECT(allocVector(INTSXP, L->n + 1)), i = PROTECT(allocVector(INTSXP, L->nzmax)), nz = PROTECT(allocVector(INTSXP, L->n)), nxt = PROTECT(allocVector(INTSXP, L->n + 2)), prv = PROTECT(allocVector(INTSXP, L->n + 2)); memcpy(INTEGER(p), L->p, (L->n + 1) * sizeof(int)); memcpy(INTEGER(i), L->i, L->nzmax * sizeof(int)); memcpy(INTEGER(nz), L->nz, L->n * sizeof(int)); memcpy(INTEGER(nxt), L->next, (L->n + 2) * sizeof(int)); memcpy(INTEGER(prv), L->prev, (L->n + 2) * sizeof(int)); SET_SLOT(to, Matrix_pSym, p); SET_SLOT(to, Matrix_iSym, i); SET_SLOT(to, install("nz"), nz); SET_SLOT(to, install("nxt"), nxt); SET_SLOT(to, install("prv"), prv); UNPROTECT(5); } if (L->xtype != CHOLMOD_PATTERN) { SEXP x; R_xlen_t nx = (R_xlen_t) ((L->is_super) ? L->xsize : L->nzmax); if (L->xtype == CHOLMOD_COMPLEX) { PROTECT(x = allocVector(CPLXSXP, nx)); memcpy(COMPLEX(x), L->x, (size_t) nx * sizeof(Rcomplex)); } else { PROTECT(x = allocVector(REALSXP, nx)); memcpy(REAL(x), L->x, (size_t) nx * sizeof(double)); } SET_SLOT(to, Matrix_xSym, x); UNPROTECT(1); } FREE_THEN(); #undef FREE_THEN UNPROTECT(4); return to; } /** * Coerce from (cholmod_sparse *) to CsparseMatrix * * Allocates an S4 object inheriting from virtual class CsparseMatrix * and copies into the slots from members of a pointed-to cholmod_sparse * struct. The specific class of the result is determined by struct * members xtype and stype and by arguments ttype and doLogic. * * @param A a pointer to a cholmod_sparse struct. * @param doFree a flag indicating if and how to free A before returning. * (0) don't free, (>0) free with cholmod_free_sparse, (<0) free with * R_Free. * @param ttype a flag indicating if the result should be a .tCMatrix. * (0) not .tCMatrix, (>0) .tCMatrix with uplo="U", (<0) .tCMatrix * with uplo="L". If ttype=0, then the result is a .gCMatrix or * .sCMatrix depending on stype. (0) .gCMatrix, (>0) .sCMatrix with * uplo="U", (<0) .sCMatrix with uplo="L". * @param doLogic a flag indicating if the result should be a l.CMatrix * if xtype=CHOLMOD_REAL. * @param diagString a null-terminated string or NULL. The diag slot * of a .tCMatrix result is "N" if and only if diagString is NULL * or diagString[0] is 'N'. * @param dimnames an R object specifying the Dimnames slot of the result, * unused if not a list of length 2. * * @return A CsparseMatrix. */ /* NB: mostly parallel to CHS2M in ./cholmod-etc.c */ SEXP cholmod_sparse_as_sexp(cholmod_sparse *A, int doFree, int ttype, int doLogic, const char *diagString, SEXP dimnames) { #define FREE_THEN(_EXPR_) \ do { \ if (doFree != 0) { \ if (doFree < 0) \ R_Free(A_); \ else if (A_->itype == CHOLMOD_INT) \ cholmod_free_sparse(&A_, &c); \ else \ cholmod_l_free_sparse(&A_, &cl); \ _EXPR_; \ } \ } while (0) cholmod_sparse *A_ = A; if (A->itype != CHOLMOD_INT) FREE_THEN(error(_("wrong '%s'"), "itype")); if (A->xtype != CHOLMOD_PATTERN && A->xtype != CHOLMOD_REAL && A->xtype != CHOLMOD_COMPLEX) FREE_THEN(error(_("wrong '%s'"), "xtype")); if (A->dtype != CHOLMOD_DOUBLE) FREE_THEN(error(_("wrong '%s'"), "dtype")); if (A->nrow > INT_MAX || A->ncol > INT_MAX) FREE_THEN(error(_("dimensions cannot exceed %s"), "2^31-1")); if (!A->sorted) cholmod_sort(A, &c); if (!A->packed || A->stype != 0) A = cholmod_copy(A, A->stype, 1, &c); int m = (int) A->nrow, n = (int) A->ncol, nnz = ((int *) A->p)[A->ncol]; R_xlen_t n1a = (R_xlen_t) n + 1; char class[] = "..CMatrix"; class[0] = (A->xtype == CHOLMOD_PATTERN) ? 'n' : ((A->xtype == CHOLMOD_COMPLEX) ? 'z' : ((doLogic) ? 'l' : 'd')); class[1] = (ttype != 0) ? 't' : ((A->stype != 0) ? 's' : 'g'); SEXP to = PROTECT(newObject(class)), dim = PROTECT(GET_SLOT(to, Matrix_DimSym)), p = PROTECT(allocVector(INTSXP, n1a)), i = PROTECT(allocVector(INTSXP, nnz)); INTEGER(dim)[0] = m; INTEGER(dim)[1] = n; memcpy(INTEGER(p), A->p, (size_t) n1a * sizeof(int)); memcpy(INTEGER(i), A->i, (size_t) nnz * sizeof(int)); SET_SLOT(to, Matrix_pSym, p); SET_SLOT(to, Matrix_iSym, i); if (A->xtype != CHOLMOD_PATTERN) { SEXP x; if (A->xtype == CHOLMOD_COMPLEX) { PROTECT(x = allocVector(CPLXSXP, nnz)); memcpy(COMPLEX(x), A->x, (size_t) nnz * sizeof(Rcomplex)); } else if (!doLogic) { PROTECT(x = allocVector(REALSXP, nnz)); memcpy(REAL(x), A->x, (size_t) nnz * sizeof(double)); } else { PROTECT(x = allocVector(LGLSXP, nnz)); int *px = LOGICAL(x); double *py = (double *) A->x; for (int k = 0; k < nnz; ++k) px[k] = (ISNAN(py[k])) ? NA_LOGICAL : (py[k] != 0.0); } SET_SLOT(to, Matrix_xSym, x); UNPROTECT(1); } if (ttype < 0 || A->stype < 0) { SEXP uplo = PROTECT(mkString("L")); SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); } if (ttype != 0 && diagString && diagString[0] != 'N') { SEXP diag = PROTECT(mkString("U")); SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); } if (TYPEOF(dimnames) == VECSXP && LENGTH(dimnames) == 2) SET_SLOT(to, Matrix_DimNamesSym, dimnames); if (A != A_) cholmod_free_sparse(&A, &c); FREE_THEN(); #undef FREE_THEN UNPROTECT(4); return to; } /** * Coerce from (cholmod_triplet *) to TsparseMatrix * * Allocates an S4 object inheriting from virtual class TsparseMatrix * and copies into the slots from members of a pointed-to cholmod_triplet * struct. The specific class of the result is determined by struct * members xtype and stype and by arguments ttype and doLogic. * * @param A a pointer to a cholmod_triplet struct. * @param doFree a flag indicating if and how to free A before returning. * (0) don't free, (>0) free with cholmod_free_triplet, (<0) free with * R_Free. * @param ttype a flag indicating if the result should be a .tTMatrix. * (0) not .tTMatrix, (>0) .tTMatrix with uplo="U", (<0) .tTMatrix * with uplo="L". If ttype=0, then the result is a .gTMatrix or * .sTMatrix depending on stype. (0) .gTMatrix, (>0) .sTMatrix with * uplo="U", (<0) .sTMatrix with uplo="L". * @param doLogic a flag indicating if the result should be an l.TMatrix * if xtype=CHOLMOD_REAL. * @param diagString a null-terminated string or NULL. The diag slot * of a .tTMatrix result is "N" if and only if diagString is NULL * or diagString[0] is 'N'. * @param dimnames an R object specifying the Dimnames slot of the result, * unused if not a list of length 2. * * @return A TsparseMatrix. */ SEXP cholmod_triplet_as_sexp(cholmod_triplet *A, int doFree, int ttype, int doLogic, const char *diagString, SEXP dimnames) { #define FREE_THEN(_EXPR_) \ do { \ if (doFree != 0) { \ if (doFree < 0) \ R_Free(A); \ else if (A->itype == CHOLMOD_INT) \ cholmod_free_triplet(&A, &c); \ else \ cholmod_l_free_triplet(&A, &cl); \ _EXPR_; \ } \ } while (0) if (A->itype != CHOLMOD_INT) FREE_THEN(error(_("wrong '%s'"), "itype")); if (A->xtype != CHOLMOD_PATTERN && A->xtype != CHOLMOD_REAL && A->xtype != CHOLMOD_COMPLEX) FREE_THEN(error(_("wrong '%s'"), "xtype")); if (A->dtype != CHOLMOD_DOUBLE) FREE_THEN(error(_("wrong '%s'"), "dtype")); if (A->nrow > INT_MAX || A->ncol > INT_MAX) FREE_THEN(error(_("dimensions cannot exceed %s"), "2^31-1")); int m = (int) A->nrow, n = (int) A->ncol; R_xlen_t nnz = (R_xlen_t) A->nnz; char class[] = "..TMatrix"; class[0] = (A->xtype == CHOLMOD_PATTERN) ? 'n' : ((A->xtype == CHOLMOD_COMPLEX) ? 'z' : ((doLogic) ? 'l' : 'd')); class[1] = (ttype != 0) ? 't' : ((A->stype != 0) ? 's' : 'g'); SEXP to = PROTECT(newObject(class)), dim = PROTECT(GET_SLOT(to, Matrix_DimSym)), i = PROTECT(allocVector(INTSXP, nnz)), j = PROTECT(allocVector(INTSXP, nnz)); INTEGER(dim)[0] = m; INTEGER(dim)[1] = n; memcpy(INTEGER(i), A->i, (size_t) nnz * sizeof(int)); memcpy(INTEGER(j), A->j, (size_t) nnz * sizeof(int)); if (A->stype != 0) { int tmp, *pi = INTEGER(i), *pj = INTEGER(j); for (R_xlen_t k = 0; k < nnz; ++k) { tmp = pi[k]; pi[k] = pj[k]; pj[k] = tmp; } } SET_SLOT(to, Matrix_iSym, i); SET_SLOT(to, Matrix_jSym, j); if (A->xtype != CHOLMOD_PATTERN) { SEXP x; if (A->xtype == CHOLMOD_COMPLEX) { PROTECT(x = allocVector(CPLXSXP, nnz)); memcpy(COMPLEX(x), A->x, (size_t) nnz * sizeof(Rcomplex)); } else if (!doLogic) { PROTECT(x = allocVector(REALSXP, nnz)); memcpy(REAL(x), A->x, (size_t) nnz * sizeof(double)); } else { PROTECT(x = allocVector(LGLSXP, nnz)); int *px = LOGICAL(x); double *py = (double *) A->x; for (R_xlen_t k = 0; k < nnz; ++k) px[k] = (ISNAN(py[k])) ? NA_LOGICAL : (py[k] != 0.0); } SET_SLOT(to, Matrix_xSym, x); UNPROTECT(1); } if (ttype < 0 || A->stype < 0) { SEXP uplo = PROTECT(mkString("L")); SET_SLOT(to, Matrix_uploSym, uplo); UNPROTECT(1); } if (ttype != 0 && diagString && diagString[0] != 'N') { SEXP diag = PROTECT(mkString("U")); SET_SLOT(to, Matrix_diagSym, diag); UNPROTECT(1); } if (TYPEOF(dimnames) == VECSXP && LENGTH(dimnames) == 2) SET_SLOT(to, Matrix_DimNamesSym, dimnames); FREE_THEN(); #undef FREE_THEN UNPROTECT(4); return to; } /** * Coerce from (cholmod_dense *) to [dz]geMatrix * * Allocates an S4 object of class [dz]geMatrix * and copies into the slots from members of a pointed-to cholmod_dense * struct. The specific class of the result is determined by struct * member xtype. * * @param A a pointer to a cholmod_dense struct. * @param doFree a flag indicating if and how to free A before returning. * (0) don't free, (>0) free with cholmod_free_dense, (<0) free with * R_Free. * * @return A [dz]geMatrix. */ /* NB: mostly parallel to CHD2M in ./cholmod-etc.c */ SEXP cholmod_dense_as_sexp(cholmod_dense *A, int doFree) { #define FREE_THEN(_EXPR_) \ do { \ if (doFree != 0) { \ if (doFree < 0) \ R_Free(A); \ else \ cholmod_free_dense(&A, &c); \ _EXPR_; \ } \ } while (0) if (A->xtype != CHOLMOD_REAL && A->xtype != CHOLMOD_COMPLEX) FREE_THEN(error(_("wrong '%s'"), "xtype")); if (A->dtype != CHOLMOD_DOUBLE) FREE_THEN(error(_("wrong '%s'"), "dtype")); if (A->d != A->nrow) /* MJ: currently no need to support this case */ FREE_THEN(error(_("leading dimension not equal to number of rows"))); if (A->nrow > INT_MAX || A->ncol > INT_MAX) FREE_THEN(error(_("dimensions cannot exceed %s"), "2^31-1")); int m = (int) A->nrow, n = (int) A->ncol; if ((Matrix_int_fast64_t) m * n > R_XLEN_T_MAX) FREE_THEN(error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX")); char class[] = ".geMatrix"; class[0] = (A->xtype == CHOLMOD_COMPLEX) ? 'z' : 'd'; SEXP to = PROTECT(newObject(class)), dim = PROTECT(GET_SLOT(to, Matrix_DimSym)); INTEGER(dim)[0] = m; INTEGER(dim)[1] = n; SEXP x; if (A->xtype == CHOLMOD_COMPLEX) { PROTECT(x = allocVector(CPLXSXP, (R_xlen_t) m * n)); memcpy(COMPLEX(x), A->x, (size_t) m * n * sizeof(Rcomplex)); } else { PROTECT(x = allocVector(REALSXP, (R_xlen_t) m * n)); memcpy(REAL(x), A->x, (size_t) m * n * sizeof(double)); } SET_SLOT(to, Matrix_xSym, x); FREE_THEN(); #undef FREE_THEN UNPROTECT(3); return to; } /** * Log determinant from Cholesky factorization * * Computes log(det(A)) given the Cholesky factorization of A as * P1 * A * P1' = L1 * D * L1' = L * L', L = L1 * sqrt(D). The * result is computed as sum(log(diag(D))) or 2*sum(log(diag(L))), * depending on members is_super and is_ll of the supplied struct. * Note that CHOLMOD does not require diag(D) to be positive and * that this routine does not check (FIXME). * * @param L a pointer to a cholmod_factor struct. It is assumed that * L->xtype=CHOLMOD_REAL. */ double cholmod_factor_ldetA(cholmod_factor *L) { int i, j, p; double ans = 0; if (L->is_super) { int *lpi = (int *) L->pi, *lsup = (int *) L->super; for (i = 0; i < L->nsuper; i++) { int nrp1 = 1 + lpi[i + 1] - lpi[i], nc = lsup[i + 1] - lsup[i]; double *x = (double *) L->x + ((int *) L->px)[i]; for (R_xlen_t jn = 0, j = 0; j < nc; j++, jn += nrp1) ans += 2.0 * log(fabs(x[jn])); } } else { int *li = (int *) L->i, *lp = (int *) L->p; double *lx = (double *) L->x; for (j = 0; j < L->n; j++) { for (p = lp[j]; li[p] != j && p < lp[j + 1]; p++) ; if (li[p] != j) { error(_("invalid simplicial Cholesky factorization: structural zero on main diagonal in column %d"), j); break; } ans += log(lx[p] * ((L->is_ll) ? lx[p] : 1.0)); } } return ans; } /** * Update a Cholesky factorization * * Updates in-place the Cholesky factorization of a symmetric matrix * X+alpha*I with the Cholesky factorization of * (1) A+beta*I, where A is a symmetric matrix sharing the nonzero pattern * of X, or * (2) A*A'+beta*I, where A is a general matrix sharing the nonzero pattern * of Y, assuming that X = Y*Y'. * * @param L a pointer to a cholmod_factor struct, to be modified in-place. * @param A a pointer to a cholmod_sparse struct. * @param beta a multiplier, typically positive, to guarantee strict * diagonal dominance. * * @return L. */ cholmod_factor *cholmod_factor_update(cholmod_factor *L, cholmod_sparse *A, double beta) { int ll = L->is_ll; double z[2]; z[0] = beta; z[1] = 0.0; if (!cholmod_factorize_p(A, z, NULL, 0, L, &c)) error(_("'%s' failed in '%s'"), "cholmod_factorize_p", __func__); if (L->is_ll != ll && !cholmod_change_factor(L->xtype, ll, L->is_super, 1, 1, L, &c)) error(_("'%s' failed in '%s'"), "cholmod_change_factor", __func__); return L; } #if 0 static int R_cholmod_print_function(const char *fmt, ...) { va_list(ap); va_start(ap, fmt); Rprintf((char *) fmt, ap); va_end(ap); return 0; } #endif static void R_cholmod_error_handler(int status, const char *file, int line, const char *message) { R_cholmod_common_envget(); if (status < 0) error(_("CHOLMOD error '%s' at file '%s', line %d"), message, file, line); else warning(_("CHOLMOD warning '%s' at file '%s', line %d"), message, file, line); } int R_cholmod_start(cholmod_common *Common) { int ans = cholmod_start(Common); if (!ans) error(_("'%s' failed in '%s'"), "cholmod_start", __func__); #if 0 /* No longer, with SuiteSparse 5.7.1 : */ Common->print_function = # if 0 R_cholmod_print_function; # else NULL; # endif #endif Common->error_handler = R_cholmod_error_handler; return ans; } int R_cholmod_finish(cholmod_common *Common) { int ans = cholmod_finish(Common); if (!ans) error(_("'%s' failed in '%s'"), "cholmod_finish", __func__); return ans; } SEXP cholmod_common_env; static SEXP dboundSym, grow0Sym, grow1Sym, grow2Sym, maxrankSym, supernodal_switchSym, supernodalSym, final_asisSym, final_superSym, final_llSym, final_packSym, final_monotonicSym, final_resymbolSym, prefer_zomplexSym, prefer_upperSym, quick_return_if_not_posdefSym, nmethodsSym, postorderSym, m0_ordSym; SEXP R_cholmod_common_envini(SEXP rho) { if (!isEnvironment(rho)) ERROR_INVALID_TYPE(rho, __func__); cholmod_common_env = rho; dboundSym = install("dbound"); grow0Sym = install("grow0"); grow1Sym = install("grow1"); grow2Sym = install("grow2"); maxrankSym = install("maxrank"); supernodal_switchSym = install("supernodal_switch"); supernodalSym = install("supernodal"); final_asisSym = install("final_asis"); final_superSym = install("final_super"); final_llSym = install("final_ll"); final_packSym = install("final_pack"); final_monotonicSym = install("final_monotonic"); final_resymbolSym = install("final_resymbol"); prefer_zomplexSym = install("final_zomplex"); prefer_upperSym = install("final_upper"); quick_return_if_not_posdefSym = install("quick_return_if_not_posdef"); nmethodsSym = install("nmethods"); postorderSym = install("postorder"); m0_ordSym = install("m0.ord"); R_cholmod_common_envset(); return R_NilValue; } void R_cholmod_common_envset(void) { SEXP rho = cholmod_common_env, tmp; #define SET_FRAME_FROM_MEMBER(_MEMBER_, _KIND_) \ do { \ PROTECT(tmp = Scalar ## _KIND_(c. _MEMBER_)); \ defineVar(_MEMBER_ ## Sym, tmp, rho); \ UNPROTECT(1); \ } while (0) SET_FRAME_FROM_MEMBER(dbound, Real); SET_FRAME_FROM_MEMBER(grow0, Real); SET_FRAME_FROM_MEMBER(grow1, Real); SET_FRAME_FROM_MEMBER(grow2, Integer); SET_FRAME_FROM_MEMBER(maxrank, Integer); SET_FRAME_FROM_MEMBER(supernodal_switch, Real); SET_FRAME_FROM_MEMBER(supernodal, Logical); SET_FRAME_FROM_MEMBER(final_asis, Logical); SET_FRAME_FROM_MEMBER(final_super, Logical); SET_FRAME_FROM_MEMBER(final_ll, Logical); SET_FRAME_FROM_MEMBER(final_pack, Logical); SET_FRAME_FROM_MEMBER(final_monotonic, Logical); SET_FRAME_FROM_MEMBER(final_resymbol, Logical); SET_FRAME_FROM_MEMBER(prefer_zomplex, Logical); SET_FRAME_FROM_MEMBER(prefer_upper, Logical); SET_FRAME_FROM_MEMBER(quick_return_if_not_posdef, Logical); SET_FRAME_FROM_MEMBER(nmethods, Integer); SET_FRAME_FROM_MEMBER(postorder, Logical); PROTECT(tmp = ScalarInteger(c.method[0].ordering)); defineVar(m0_ordSym, tmp, rho); UNPROTECT(1); return; } void R_cholmod_common_envget(void) { SEXP rho = cholmod_common_env, tmp; #define GET_MEMBER_FROM_FRAME(_MEMBER_, _KIND_) \ do { \ PROTECT(tmp = findVarInFrame(rho, _MEMBER_ ## Sym)); \ c. _MEMBER_ = as ## _KIND_(tmp); \ UNPROTECT(1); \ } while (0) GET_MEMBER_FROM_FRAME(dbound, Real); GET_MEMBER_FROM_FRAME(grow0, Real); GET_MEMBER_FROM_FRAME(grow1, Real); GET_MEMBER_FROM_FRAME(grow2, Integer); GET_MEMBER_FROM_FRAME(maxrank, Integer); GET_MEMBER_FROM_FRAME(supernodal_switch, Real); GET_MEMBER_FROM_FRAME(supernodal, Logical); GET_MEMBER_FROM_FRAME(final_asis, Logical); GET_MEMBER_FROM_FRAME(final_super, Logical); GET_MEMBER_FROM_FRAME(final_ll, Logical); GET_MEMBER_FROM_FRAME(final_pack, Logical); GET_MEMBER_FROM_FRAME(final_monotonic, Logical); GET_MEMBER_FROM_FRAME(final_resymbol, Logical); GET_MEMBER_FROM_FRAME(prefer_zomplex, Logical); GET_MEMBER_FROM_FRAME(prefer_upper, Logical); GET_MEMBER_FROM_FRAME(quick_return_if_not_posdef, Logical); GET_MEMBER_FROM_FRAME(nmethods, Integer); GET_MEMBER_FROM_FRAME(postorder, Logical); PROTECT(tmp = findVarInFrame(rho, m0_ordSym)); c.method[0].ordering = asInteger(tmp); UNPROTECT(1); return; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/determinant.c����������������������������������������������������������������������������0000644�0001751�0000144�00000023257�14511304746�015017� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include /* math.h, logspace_add, logspace_sub */ #include "Mdefines.h" #include "cholmod-etc.h" #include "determinant.h" static SEXP mkDet(double modulus, int logarithm, int sign) { SEXP nms = PROTECT(allocVector(STRSXP, 2)), cl = PROTECT(mkString("det")), det = PROTECT(allocVector(VECSXP, 2)), det0 = PROTECT(ScalarReal((logarithm) ? modulus : exp(modulus))), det1 = PROTECT(ScalarInteger(sign)), det0a = PROTECT(ScalarLogical(logarithm)); SET_STRING_ELT(nms, 0, mkChar("modulus")); SET_STRING_ELT(nms, 1, mkChar("sign")); setAttrib(det, R_NamesSymbol, nms); setAttrib(det, R_ClassSymbol, cl); setAttrib(det0, install("logarithm"), det0a); SET_VECTOR_ELT(det, 0, det0); SET_VECTOR_ELT(det, 1, det1); UNPROTECT(6); return det; } SEXP denseLU_determinant(SEXP obj, SEXP logarithm) { #define DETERMINANT_START \ SEXP dim = GET_SLOT(obj, Matrix_DimSym); \ int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; \ if (m != n) \ error(_("determinant of non-square matrix is undefined")); \ int givelog = asLogical(logarithm) != 0; \ double modulus = 0.0; /* result for n == 0 */ DETERMINANT_START; SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)); int sign = (TYPEOF(x) == CPLXSXP) ? NA_INTEGER : 1; if (n > 0) { int j; R_xlen_t n1a = (R_xlen_t) n + 1; if (TYPEOF(x) == CPLXSXP) { Rcomplex *px = COMPLEX(x); for (j = 0; j < n; ++j) { modulus += log(hypot((*px).r, (*px).i)); px += n1a; } } else { SEXP pivot = GET_SLOT(obj, Matrix_permSym); int *ppivot = INTEGER(pivot); double *px = REAL(x); for (j = 0; j < n; ++j) { if (ISNAN(*px) || *px >= 0.0) { modulus += log(*px); if (*ppivot != j + 1) sign = -sign; } else { modulus += log(-(*px)); if (*ppivot == j + 1) sign = -sign; } px += n1a; ppivot += 1; } } } UNPROTECT(1); /* x */ return mkDet(modulus, givelog, sign); } SEXP BunchKaufman_determinant(SEXP obj, SEXP logarithm) { DETERMINANT_START; SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)); int sign = (TYPEOF(x) == CPLXSXP) ? NA_INTEGER : 1; if (n > 0) { SEXP pivot = GET_SLOT(obj, Matrix_permSym); int *ppivot = INTEGER(pivot); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); int j = 0, unpacked = (Matrix_int_fast64_t) n * n <= R_XLEN_T_MAX && XLENGTH(x) == (R_xlen_t) m * m; R_xlen_t n1a = (R_xlen_t) n + 1; if (TYPEOF(x) == CPLXSXP) { Rcomplex *px = COMPLEX(x), a, b, c; while (j < n) { if (ppivot[j] > 0) { modulus += log(hypot((*px).r, (*px).i)); px += (unpacked) ? n1a : ((ul == 'U') ? j + 2 : n - j); j += 1; } else { a = *px; if (ul == 'U') { px += (unpacked) ? n1a : j + 2; b = *px; c = *(px - 1); px += (unpacked) ? n1a : j + 3; } else { c = *(px + 1); px += (unpacked) ? n1a : n - j; b = *px; px += (unpacked) ? n1a : n - j - 1; } modulus += log(hypot(a.r * b.r - a.i * b.i - c.r * c.r + c.i * c.i, a.r * b.i + a.i * b.r - 2.0 * c.r * c.i)); j += 2; } } } else { double *px = REAL(x), a, b, c, logab, logcc; while (j < n) { if (ppivot[j] > 0) { if (*px >= 0.0) modulus += log(*px); else { modulus += log(-(*px)); sign = -sign; } px += (unpacked) ? n1a : ((ul == 'U') ? j + 2 : n - j); j += 1; } else { a = *px; if (ul == 'U') { px += (unpacked) ? n1a : j + 2; b = *px; c = *(px - 1); px += (unpacked) ? n1a : j + 3; } else { c = *(px + 1); px += (unpacked) ? n1a : n - j; b = *px; px += (unpacked) ? n1a : n - j - 1; } logab = log(fabs(a)) + log(fabs(b)); logcc = 2.0 * log(fabs(c)); if ((a < 0.0) != (b < 0.0)) { /* det = ab - cc = -(abs(ab) + cc) < 0 */ modulus += logspace_add(logab, logcc); sign = -sign; } else if (logab < logcc) { /* det = ab - cc = -(cc - ab) < 0 */ modulus += logspace_sub(logcc, logab); sign = -sign; } else { /* det = ab - cc > 0 */ modulus += logspace_sub(logab, logcc); } j += 2; } } } } UNPROTECT(1); /* x */ return mkDet(modulus, givelog, sign); } SEXP Cholesky_determinant(SEXP obj, SEXP logarithm) { DETERMINANT_START; SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)); int sign = (TYPEOF(x) == CPLXSXP) ? NA_INTEGER : 1; if (n > 0) { SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); int j, unpacked = (Matrix_int_fast64_t) n * n <= R_XLEN_T_MAX && XLENGTH(x) == (R_xlen_t) m * m; R_xlen_t n1a = (R_xlen_t) n + 1; if (TYPEOF(x) == CPLXSXP) { Rcomplex *px = COMPLEX(x); for (j = 0; j < n; ++j) { modulus += log(hypot((*px).r, (*px).i)); px += (unpacked) ? n1a : ((ul == 'U') ? j + 2 : n - j); } } else { double *px = REAL(x); for (j = 0; j < n; ++j) { if (ISNAN(*px) || *px >= 0.0) modulus += log(*px); else { modulus += log(-(*px)); sign = -sign; } px += (unpacked) ? n1a : ((ul == 'U') ? j + 2 : n - j); } } modulus *= 2.0; } UNPROTECT(1); /* x */ return mkDet(modulus, givelog, sign); } SEXP sparseLU_determinant(SEXP obj, SEXP logarithm) { DETERMINANT_START; SEXP U = PROTECT(GET_SLOT(obj, Matrix_USym)), x = PROTECT(GET_SLOT(U, Matrix_xSym)); int sign = (TYPEOF(x) == CPLXSXP) ? NA_INTEGER : 1; if (n > 0) { SEXP p = PROTECT(GET_SLOT(U, Matrix_pSym)), i = PROTECT(GET_SLOT(U, Matrix_iSym)); int *pp = INTEGER(p) + 1, *pi = INTEGER(i), j, k = 0, kend; if (TYPEOF(x) == CPLXSXP) { Rcomplex *px = COMPLEX(x); for (j = 0; j < n; ++j) { kend = pp[j]; if (k < kend && pi[kend - 1] == j) modulus += log(hypot(px[kend - 1].r, px[kend - 1].i)); else { UNPROTECT(4); /* i, p, x, U */ return mkDet(R_NegInf, givelog, 1); } k = kend; } } else { double *px = REAL(x); for (j = 0; j < n; ++j) { kend = pp[j]; if (k < kend && pi[kend - 1] == j) { if (ISNAN(px[kend - 1]) || px[kend - 1] >= 0.0) modulus += log(px[kend - 1]); else { modulus += log(-px[kend - 1]); sign = -sign; } } else { UNPROTECT(4); /* i, p, x, U */ return mkDet(R_NegInf, givelog, 1); } k = kend; } /* defined in ./perm.c : */ int signPerm(const int *, int, int); p = GET_SLOT(obj, Matrix_pSym); if (signPerm(INTEGER(p), LENGTH(p), 0) < 0) sign = -sign; p = GET_SLOT(obj, Matrix_qSym); if (signPerm(INTEGER(p), LENGTH(p), 0) < 0) sign = -sign; } UNPROTECT(2); /* i, p */ } UNPROTECT(2); /* x, U */ return mkDet(modulus, givelog, sign); } SEXP sparseQR_determinant(SEXP obj, SEXP logarithm) { DETERMINANT_START; SEXP R = PROTECT(GET_SLOT(obj, Matrix_RSym)), x = PROTECT(GET_SLOT(R, Matrix_xSym)); int sign = (TYPEOF(x) == CPLXSXP) ? NA_INTEGER : 1; dim = GET_SLOT(R, Matrix_DimSym); if (INTEGER(dim)[0] > n) error(_("%s(<%s>) does not support structurally rank deficient case"), "determinant", "sparseQR"); if (n > 0) { SEXP p = PROTECT(GET_SLOT(R, Matrix_pSym)), i = PROTECT(GET_SLOT(R, Matrix_iSym)); int *pp = INTEGER(p) + 1, *pi = INTEGER(i), j, k = 0, kend; if (TYPEOF(x) == CPLXSXP) { Rcomplex *px = COMPLEX(x); for (j = 0; j < n; ++j) { kend = pp[j]; if (k < kend && pi[kend - 1] == j) modulus += log(hypot(px[kend - 1].r, px[kend - 1].i)); else { UNPROTECT(4); /* i, p, x, U */ return mkDet(R_NegInf, givelog, 1); } k = kend; } } else { double *px = REAL(x); for (j = 0; j < n; ++j) { kend = pp[j]; if (k < kend && pi[kend - 1] == j) { if (ISNAN(px[kend - 1]) || px[kend - 1] >= 0.0) modulus += log(px[kend - 1]); else { modulus += log(-px[kend - 1]); sign = -sign; } } else { UNPROTECT(4); /* i, p, x, R */ return mkDet(R_NegInf, givelog, 1); } k = kend; } /* defined in ./perm.c : */ int signPerm(const int *, int, int); p = GET_SLOT(obj, Matrix_pSym); if (signPerm(INTEGER(p), LENGTH(p), 0) < 0) sign = -sign; p = GET_SLOT(obj, Matrix_qSym); if (signPerm(INTEGER(p), LENGTH(p), 0) < 0) sign = -sign; if (n % 2) sign = -sign; } UNPROTECT(2); /* i, p */ } UNPROTECT(2); /* x, R */ return mkDet(modulus, givelog, sign); } SEXP CHMfactor_determinant(SEXP obj, SEXP logarithm, SEXP sqrt) { DETERMINANT_START; cholmod_factor *L = M2CHF(obj, 1); int sign = (L->xtype == CHOLMOD_COMPLEX) ? NA_INTEGER : 1; if (n > 0) { int j, sqrt_ = asLogical(sqrt); if (L->is_super) { int k, nc, nsuper = (int) L->nsuper, *psuper = (int *) L->super, *ppi = (int *) L->pi, *ppx = (int *) L->px; R_xlen_t nr1a; if (L->xtype == CHOLMOD_COMPLEX) { Rcomplex *px = (Rcomplex *) L->x, *px_; for (k = 0; k < nsuper; ++k) { nc = psuper[k + 1] - psuper[k]; nr1a = (R_xlen_t) (ppi[k + 1] - ppi[k]) + 1; px_ = px + ppx[k]; for (j = 0; j < nc; ++j) { modulus += log(hypot((*px_).r, (*px_).i)); px_ += nr1a; } } } else { double *px = (double *) L->x, *px_; for (k = 0; k < nsuper; ++k) { nc = psuper[k + 1] - psuper[k]; nr1a = (R_xlen_t) (ppi[k + 1] - ppi[k]) + 1; px_ = px + ppx[k]; for (j = 0; j < nc; ++j) { modulus += log(*px_); px_ += nr1a; } } } modulus *= 2.0; } else { int *pp = (int *) L->p; if (L->xtype == CHOLMOD_COMPLEX) { Rcomplex *px = (Rcomplex *) L->x; for (j = 0; j < n; ++j) modulus += log(hypot(px[pp[j]].r, px[pp[j]].i)); if (L->is_ll) modulus *= 2.0; } else { double *px = (double *) L->x; if (L->is_ll) { for (j = 0; j < n; ++j) modulus += log(px[pp[j]]); modulus *= 2.0; } else { for (j = 0; j < n; ++j) { if (ISNAN(px[pp[j]]) || px[pp[j]] >= 0.0) modulus += log(px[pp[j]]); else { if (sqrt_) return mkDet(R_NaN, givelog, 1); modulus += log(-px[pp[j]]); sign = -sign; } } } } } if (sqrt_) modulus *= 0.5; } return mkDet(modulus, givelog, sign); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/expm.c�����������������������������������������������������������������������������������0000644�0001751�0000144�00000011364�14574651213�013455� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Lapack-etc.h" #include "Mdefines.h" #include "expm.h" /* For matrix exponential calculation : */ const static double padec [] = { 5.0000000000000000e-1, 1.1666666666666667e-1, 1.6666666666666667e-2, 1.6025641025641026e-3, 1.0683760683760684e-4, 4.8562548562548563e-6, 1.3875013875013875e-7, 1.9270852604185938e-9, }; /* Based on _corrected_ code for Octave function 'expm' : */ SEXP dgeMatrix_expm(SEXP x) { const double one = 1.0, zero = 0.0; const int i1 = 1; int *Dims = INTEGER(GET_SLOT(x, Matrix_DimSym)); const int n = Dims[1]; const R_xlen_t n_ = n, np1 = n + 1, nsqr = n_ * n_; // nsqr = n^2 SEXP val = PROTECT(duplicate(x)); int i, ilo, ilos, ihi, ihis, j, sqpow; int *pivot = R_Calloc(n, int); double *dpp = R_Calloc(nsqr, double), /* denominator power Pade' */ *npp = R_Calloc(nsqr, double), /* numerator power Pade' */ *perm = R_Calloc(n, double), *scale = R_Calloc(n, double), *v = REAL(GET_SLOT(val, Matrix_xSym)), *work = R_Calloc(nsqr, double), inf_norm, m1_j/*= (-1)^j */, trshift; R_CheckStack(); if (n < 1 || Dims[0] != n) error(_("Matrix exponential requires square, non-null matrix")); if(n == 1) { v[0] = exp(v[0]); UNPROTECT(1); return val; } /* Preconditioning 1. Shift diagonal by average diagonal if positive. */ trshift = 0; /* determine average diagonal element */ for (i = 0; i < n; i++) trshift += v[i * np1]; trshift /= n; if (trshift > 0.) { /* shift diagonal by -trshift */ for (i = 0; i < n; i++) v[i * np1] -= trshift; } /* Preconditioning 2. Balancing with dgebal. */ F77_CALL(dgebal)("P", &n, v, &n, &ilo, &ihi, perm, &j FCONE); if (j) error(_("dgeMatrix_exp: LAPACK routine dgebal returned %d"), j); F77_CALL(dgebal)("S", &n, v, &n, &ilos, &ihis, scale, &j FCONE); if (j) error(_("dgeMatrix_exp: LAPACK routine dgebal returned %d"), j); /* Preconditioning 3. Scaling according to infinity norm */ inf_norm = F77_CALL(dlange)("I", &n, &n, v, &n, work FCONE); sqpow = (inf_norm > 0) ? (int) (1 + log(inf_norm)/log(2.)) : 0; if (sqpow < 0) sqpow = 0; if (sqpow > 0) { double scale_factor = 1.0; for (i = 0; i < sqpow; i++) scale_factor *= 2.; for (R_xlen_t i = 0; i < nsqr; i++) v[i] /= scale_factor; } /* Pade' approximation. Powers v^8, v^7, ..., v^1 */ Matrix_memset(npp, 0, nsqr, sizeof(double)); Matrix_memset(dpp, 0, nsqr, sizeof(double)); m1_j = -1; for (j = 7; j >=0; j--) { double mult = padec[j]; /* npp = m * npp + padec[j] *m */ F77_CALL(dgemm)("N", "N", &n, &n, &n, &one, v, &n, npp, &n, &zero, work, &n FCONE FCONE); for (R_xlen_t i = 0; i < nsqr; i++) npp[i] = work[i] + mult * v[i]; /* dpp = m * dpp + (m1_j * padec[j]) * m */ mult *= m1_j; F77_CALL(dgemm)("N", "N", &n, &n, &n, &one, v, &n, dpp, &n, &zero, work, &n FCONE FCONE); for (R_xlen_t i = 0; i < nsqr; i++) dpp[i] = work[i] + mult * v[i]; m1_j *= -1; } /* Zero power */ for (R_xlen_t i = 0; i < nsqr; i++) dpp[i] *= -1.; for (j = 0; j < n; j++) { npp[j * np1] += 1.; dpp[j * np1] += 1.; } /* Pade' approximation is solve(dpp, npp) */ F77_CALL(dgetrf)(&n, &n, dpp, &n, pivot, &j); if (j) error(_("dgeMatrix_exp: dgetrf returned error code %d"), j); F77_CALL(dgetrs)("N", &n, &n, dpp, &n, pivot, npp, &n, &j FCONE); if (j) error(_("dgeMatrix_exp: dgetrs returned error code %d"), j); Memcpy(v, npp, nsqr); /* Now undo all of the preconditioning */ /* Preconditioning 3: square the result for every power of 2 */ while (sqpow--) { F77_CALL(dgemm)("N", "N", &n, &n, &n, &one, v, &n, v, &n, &zero, work, &n FCONE FCONE); Memcpy(v, work, nsqr); } /* Preconditioning 2: apply inverse scaling */ for (j = 0; j < n; j++) { R_xlen_t jn = j * n_; for (i = 0; i < n; i++) v[i + jn] *= scale[i]/scale[j]; } /* 2 b) Inverse permutation (if not the identity permutation) */ if (ilo != 1 || ihi != n) { /* Martin Maechler's code */ #define SWAP_ROW(I,J) F77_CALL(dswap)(&n, &v[(I)], &n, &v[(J)], &n) #define SWAP_COL(I,J) F77_CALL(dswap)(&n, &v[(I)*n_], &i1, &v[(J)*n_], &i1) #define RE_PERMUTE(I) \ int p_I = (int) (perm[I]) - 1; \ SWAP_COL(I, p_I); \ SWAP_ROW(I, p_I) /* reversion of "leading permutations" : in reverse order */ for (i = (ilo - 1) - 1; i >= 0; i--) { RE_PERMUTE(i); } /* reversion of "trailing permutations" : applied in forward order */ for (i = (ihi + 1) - 1; i < n; i++) { RE_PERMUTE(i); } } /* Preconditioning 1: Trace normalization */ if (trshift > 0.) { double mult = exp(trshift); for (R_xlen_t i = 0; i < nsqr; i++) v[i] *= mult; } /* Clean up */ R_Free(work); R_Free(scale); R_Free(perm); R_Free(npp); R_Free(dpp); R_Free(pivot); UNPROTECT(1); return val; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/factor.c���������������������������������������������������������������������������������0000644�0001751�0000144�00000061220�14575137654�013767� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Lapack-etc.h" #include "cs-etc.h" #include "cholmod-etc.h" #include "Mdefines.h" #include "factor.h" /* defined in ./attrib.c : */ SEXP get_factor(SEXP, const char *); void set_factor(SEXP, const char *, SEXP); static SEXP dgeMatrix_trf_(SEXP obj, int warn) { SEXP val = PROTECT(newObject("denseLU")), dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)), dimnames = PROTECT(GET_SLOT(obj, Matrix_DimNamesSym)); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1], r = (m < n) ? m : n; SET_SLOT(val, Matrix_DimSym, dim); SET_SLOT(val, Matrix_DimNamesSym, dimnames); if (r > 0) { SEXP perm = PROTECT(allocVector(INTSXP, r)), x = PROTECT(GET_SLOT(obj, Matrix_xSym)), y = PROTECT(allocVector(TYPEOF(x), XLENGTH(x))); int *pperm = INTEGER(perm), info; #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) { Rcomplex *px = COMPLEX(x), *py = COMPLEX(y); Matrix_memcpy(py, px, XLENGTH(y), sizeof(Rcomplex)); F77_CALL(zgetrf)(&m, &n, py, &m, pperm, &info); ERROR_LAPACK_2(zgetrf, info, warn, U); } else { #endif double *px = REAL(x), *py = REAL(y); Matrix_memcpy(py, px, XLENGTH(y), sizeof(double)); F77_CALL(dgetrf)(&m, &n, py, &m, pperm, &info); ERROR_LAPACK_2(dgetrf, info, warn, U); #ifdef MATRIX_ENABLE_ZMATRIX } #endif SET_SLOT(val, Matrix_permSym, perm); SET_SLOT(val, Matrix_xSym, y); UNPROTECT(3); /* y, x, perm */ } UNPROTECT(3); /* dimnames, dim, val */ return val; } static SEXP dsyMatrix_trf_(SEXP obj, int warn) { SEXP val = PROTECT(newObject("BunchKaufman")), dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)), dimnames = PROTECT(GET_SLOT(obj, Matrix_DimNamesSym)), uplo = PROTECT(GET_SLOT(obj, Matrix_uploSym)); int n = INTEGER(dim)[1]; char ul = *CHAR(STRING_ELT(uplo, 0)); SET_SLOT(val, Matrix_DimSym, dim); set_symmetrized_DimNames(val, dimnames, -1); SET_SLOT(val, Matrix_uploSym, uplo); if (n > 0) { SEXP perm = PROTECT(allocVector(INTSXP, n)), x = PROTECT(GET_SLOT(obj, Matrix_xSym)), y = PROTECT(allocVector(TYPEOF(x), XLENGTH(x))); int *pperm = INTEGER(perm), info, lwork = -1; #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) { Rcomplex *px = COMPLEX(x), *py = COMPLEX(y), tmp, *work; Matrix_memset(py, 0, XLENGTH(y), sizeof(Rcomplex)); F77_CALL(zlacpy)(&ul, &n, &n, px, &n, py, &n FCONE); F77_CALL(zsytrf)(&ul, &n, py, &n, pperm, &tmp, &lwork, &info FCONE); lwork = (int) tmp.r; Matrix_Calloc(work, lwork, Rcomplex); F77_CALL(zsytrf)(&ul, &n, py, &n, pperm, work, &lwork, &info FCONE); Matrix_Free(work, lwork); ERROR_LAPACK_2(zsytrf, info, warn, D); } else { #endif double *px = REAL(x), *py = REAL(y), tmp, *work; Matrix_memset(py, 0, XLENGTH(y), sizeof(double)); F77_CALL(dlacpy)(&ul, &n, &n, px, &n, py, &n FCONE); F77_CALL(dsytrf)(&ul, &n, py, &n, pperm, &tmp, &lwork, &info FCONE); lwork = (int) tmp; Matrix_Calloc(work, lwork, double); F77_CALL(dsytrf)(&ul, &n, py, &n, pperm, work, &lwork, &info FCONE); Matrix_Free(work, lwork); ERROR_LAPACK_2(dsytrf, info, warn, D); #ifdef MATRIX_ENABLE_ZMATRIX } #endif SET_SLOT(val, Matrix_permSym, perm); SET_SLOT(val, Matrix_xSym, y); UNPROTECT(3); /* y, x, perm */ } UNPROTECT(4); /* uplo, dimnames, dim, val */ return val; } static SEXP dspMatrix_trf_(SEXP obj, int warn) { SEXP val = PROTECT(newObject("pBunchKaufman")), dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)), dimnames = PROTECT(GET_SLOT(obj, Matrix_DimNamesSym)), uplo = PROTECT(GET_SLOT(obj, Matrix_uploSym)); int n = INTEGER(dim)[1]; char ul = *CHAR(STRING_ELT(uplo, 0)); SET_SLOT(val, Matrix_DimSym, dim); set_symmetrized_DimNames(val, dimnames, -1); SET_SLOT(val, Matrix_uploSym, uplo); if (n > 0) { SEXP perm = PROTECT(allocVector(INTSXP, n)), x = PROTECT(GET_SLOT(obj, Matrix_xSym)), y = PROTECT(allocVector(TYPEOF(x), XLENGTH(x))); int *pperm = INTEGER(perm), info; #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) { Rcomplex *px = COMPLEX(x), *py = COMPLEX(y); Matrix_memcpy(py, px, XLENGTH(y), sizeof(Rcomplex)); F77_CALL(zsptrf)(&ul, &n, py, pperm, &info FCONE); ERROR_LAPACK_2(zsptrf, info, warn, D); } else { #endif double *px = REAL(x), *py = REAL(y); Matrix_memcpy(py, px, XLENGTH(y), sizeof(double)); F77_CALL(dsptrf)(&ul, &n, py, pperm, &info FCONE); ERROR_LAPACK_2(dsptrf, info, warn, D); #ifdef MATRIX_ENABLE_ZMATRIX } #endif SET_SLOT(val, Matrix_permSym, perm); SET_SLOT(val, Matrix_xSym, y); UNPROTECT(3); /* y, x, perm */ } UNPROTECT(4); /* uplo, dimnames, dim, val */ return val; } static SEXP dpoMatrix_trf_(SEXP obj, int warn, int pivot, double tol) { SEXP val = PROTECT(newObject("Cholesky")), dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)), dimnames = PROTECT(GET_SLOT(obj, Matrix_DimNamesSym)), uplo = PROTECT(GET_SLOT(obj, Matrix_uploSym)); int n = INTEGER(dim)[1]; char ul = *CHAR(STRING_ELT(uplo, 0)); SET_SLOT(val, Matrix_DimSym, dim); set_symmetrized_DimNames(val, dimnames, -1); SET_SLOT(val, Matrix_uploSym, uplo); if (n > 0) { SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), y = PROTECT(allocVector(TYPEOF(x), XLENGTH(x))); int info; #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) { Rcomplex *px = COMPLEX(x), *py = COMPLEX(y); Matrix_memset(py, 0, XLENGTH(y), sizeof(Rcomplex)); F77_CALL(zlacpy)(&ul, &n, &n, px, &n, py, &n FCONE); if (!pivot) { F77_CALL(zpotrf)(&ul, &n, py, &n, &info FCONE); ERROR_LAPACK_3(zpotrf, info, warn, 6); } else { SEXP perm = PROTECT(allocVector(INTSXP, n)); int *pperm = INTEGER(perm), rank; Rcomplex *work = (Rcomplex *) R_alloc((size_t) 2 * n, sizeof(Rcomplex)); F77_CALL(zpstrf)(&ul, &n, py, &n, pperm, &rank, &tol, work, &info FCONE); ERROR_LAPACK_4(zpstrf, info, rank, warn); if (info > 0) { int j, d = n - rank; py += (R_xlen_t) rank * n + rank; for (j = rank; j < n; ++j) { Matrix_memset(py, 0, d, sizeof(Rcomplex)); py += n; } } SET_SLOT(val, Matrix_permSym, perm); UNPROTECT(1); /* perm */ } } else { #endif double *px = REAL(x), *py = REAL(y); Matrix_memset(py, 0, XLENGTH(y), sizeof(double)); F77_CALL(dlacpy)(&ul, &n, &n, px, &n, py, &n FCONE); if (!pivot) { F77_CALL(dpotrf)(&ul, &n, py, &n, &info FCONE); ERROR_LAPACK_3(dpotrf, info, warn, 6); } else { SEXP perm = PROTECT(allocVector(INTSXP, n)); int *pperm = INTEGER(perm), rank; double *work = (double *) R_alloc((size_t) 2 * n, sizeof(double)); F77_CALL(dpstrf)(&ul, &n, py, &n, pperm, &rank, &tol, work, &info FCONE); ERROR_LAPACK_4(dpstrf, info, rank, warn); if (info > 0) { int j, d = n - rank; py += (R_xlen_t) rank * n + rank; for (j = rank; j < n; ++j) { Matrix_memset(py, 0, d, sizeof(double)); py += n; } } SET_SLOT(val, Matrix_permSym, perm); UNPROTECT(1); /* perm */ } #ifdef MATRIX_ENABLE_ZMATRIX } #endif SET_SLOT(val, Matrix_xSym, y); UNPROTECT(2); /* y, x */ } UNPROTECT(4); /* uplo, dimnames, dim, val */ return val; } static SEXP dppMatrix_trf_(SEXP obj, int warn) { SEXP val = PROTECT(newObject("pCholesky")), dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)), dimnames = PROTECT(GET_SLOT(obj, Matrix_DimNamesSym)), uplo = PROTECT(GET_SLOT(obj, Matrix_uploSym)); int n = INTEGER(dim)[1]; char ul = *CHAR(STRING_ELT(uplo, 0)); SET_SLOT(val, Matrix_DimSym, dim); set_symmetrized_DimNames(val, dimnames, -1); SET_SLOT(val, Matrix_uploSym, uplo); if (n > 0) { SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), y = PROTECT(allocVector(TYPEOF(x), XLENGTH(x))); int info; #ifdef MATRIX_ENABLE_ZMATRIX if (TYPEOF(x) == CPLXSXP) { Rcomplex *px = COMPLEX(x), *py = COMPLEX(y); Matrix_memcpy(py, px, XLENGTH(y), sizeof(Rcomplex)); F77_CALL(zpptrf)(&ul, &n, py, &info FCONE); ERROR_LAPACK_3(zpptrf, info, warn, 6); } else { #endif double *px = REAL(x), *py = REAL(y); Matrix_memcpy(py, px, XLENGTH(y), sizeof(double)); F77_CALL(dpptrf)(&ul, &n, py, &info FCONE); ERROR_LAPACK_3(dpptrf, info, warn, 6); #ifdef MATRIX_ENABLE_ZMATRIX } #endif SET_SLOT(val, Matrix_xSym, y); UNPROTECT(2); /* y, x */ } UNPROTECT(4); /* uplo, dimnames, dim, val */ return val; } SEXP dgeMatrix_trf(SEXP obj, SEXP warn) { SEXP val = get_factor(obj, "denseLU"); if (isNull(val)) { PROTECT(val = dgeMatrix_trf_(obj, asInteger(warn))); set_factor(obj, "denseLU", val); UNPROTECT(1); } return val; } SEXP dsyMatrix_trf(SEXP obj, SEXP warn) { SEXP val = get_factor(obj, "BunchKaufman"); if (isNull(val)) { PROTECT(val = dsyMatrix_trf_(obj, asInteger(warn))); set_factor(obj, "BunchKaufman", val); UNPROTECT(1); } return val; } SEXP dspMatrix_trf(SEXP obj, SEXP warn) { SEXP val = get_factor(obj, "pBunchKaufman"); if (isNull(val)) { PROTECT(val = dspMatrix_trf_(obj, asInteger(warn))); set_factor(obj, "pBunchKaufman", val); UNPROTECT(1); } return val; } SEXP dpoMatrix_trf(SEXP obj, SEXP warn, SEXP pivot, SEXP tol) { int pivot_ = asLogical(pivot); SEXP val = get_factor(obj, (pivot_) ? "Cholesky~" : "Cholesky"); if (isNull(val)) { double tol_ = asReal(tol); PROTECT(val = dpoMatrix_trf_(obj, asInteger(warn), pivot_, tol_)); set_factor(obj, (pivot_) ? "Cholesky~" : "Cholesky", val); UNPROTECT(1); } return val; } SEXP dppMatrix_trf(SEXP obj, SEXP warn) { SEXP val = get_factor(obj, "pCholesky"); if (isNull(val)) { PROTECT(val = dppMatrix_trf_(obj, asInteger(warn))); set_factor(obj, "pCholesky", val); UNPROTECT(1); } return val; } SEXP dgeMatrix_sch(SEXP x, SEXP vectors, SEXP isDGE) { // 'x' is either a traditional matrix or a dgeMatrix, as indicated by isDGE. int *dims, n, vecs = asLogical(vectors), is_dge = asLogical(isDGE), info, izero = 0, lwork = -1, nprot = 1; if(is_dge) { dims = INTEGER(GET_SLOT(x, Matrix_DimSym)); } else { // traditional matrix dims = INTEGER(getAttrib(x, R_DimSymbol)); if(!isReal(x)) { // may not be "numeric" .. x = PROTECT(coerceVector(x, REALSXP)); // -> maybe error nprot++; } } double *work, tmp; const char *nms[] = {"WR", "WI", "T", "Z", ""}; SEXP val = PROTECT(Rf_mkNamed(VECSXP, nms)); n = dims[0]; if (n != dims[1] || n < 1) error(_("dgeMatrix_Schur: argument x must be a non-null square matrix")); const R_xlen_t n2 = ((R_xlen_t)n) * n; // = n^2 SET_VECTOR_ELT(val, 0, allocVector(REALSXP, n)); SET_VECTOR_ELT(val, 1, allocVector(REALSXP, n)); SET_VECTOR_ELT(val, 2, allocMatrix(REALSXP, n, n)); Memcpy(REAL(VECTOR_ELT(val, 2)), REAL(is_dge ? GET_SLOT(x, Matrix_xSym) : x), n2); SET_VECTOR_ELT(val, 3, allocMatrix(REALSXP, vecs ? n : 0, vecs ? n : 0)); F77_CALL(dgees)(vecs ? "V" : "N", "N", NULL, dims, (double *) NULL, dims, &izero, (double *) NULL, (double *) NULL, (double *) NULL, dims, &tmp, &lwork, (int *) NULL, &info FCONE FCONE); if (info) error(_("dgeMatrix_Schur: first call to dgees failed")); lwork = (int) tmp; Matrix_Calloc(work, lwork, double); F77_CALL(dgees)(vecs ? "V" : "N", "N", NULL, dims, REAL(VECTOR_ELT(val, 2)), dims, &izero, REAL(VECTOR_ELT(val, 0)), REAL(VECTOR_ELT(val, 1)), REAL(VECTOR_ELT(val, 3)), dims, work, &lwork, (int *) NULL, &info FCONE FCONE); Matrix_Free(work, lwork); if (info) error(_("dgeMatrix_Schur: dgees returned code %d"), info); UNPROTECT(nprot); return val; } #define DO_FREE(_A_, _S_, _N_) \ do { \ if (!(_A_)) \ _A_ = Matrix_cs_spfree(_A_); \ if (!(_S_)) \ _S_ = Matrix_cs_sfree (_S_); \ if (!(_N_)) \ _N_ = Matrix_cs_nfree (_N_); \ } while (0) #define DO_SORT(_A_) \ do { \ Matrix_cs_dropzeros(_A_); \ T = Matrix_cs_transpose(_A_, 1); \ if (!T) { \ DO_FREE(T, *S, *N); \ return 0; \ } \ _A_ = Matrix_cs_spfree(_A_); \ _A_ = Matrix_cs_transpose(T, 1); \ if (!(_A_)) { \ DO_FREE(T, *S, *N); \ return 0; \ } \ T = Matrix_cs_spfree(T); \ } while (0) static int dgCMatrix_trf_(const Matrix_cs *A, Matrix_css **S, Matrix_csn **N, int order, double tol) { Matrix_cs *T = NULL; if (!(*S = Matrix_cs_sqr(order, A, 0)) || !(*N = Matrix_cs_lu(A, *S, tol))) { DO_FREE(T, *S, *N); return 0; } DO_SORT((*N)->L); DO_SORT((*N)->U); return 1; } SEXP dgCMatrix_trf(SEXP obj, SEXP order, SEXP tol, SEXP doError) { double tol_ = asReal(tol); if (ISNAN(tol_)) error(_("'%s' is not a number"), "tol"); int order_ = asInteger(order); if (order_ == NA_INTEGER) order_ = (tol_ == 1.0) ? 2 : 1; else if (order_ < 0 || order_ > 3) order_ = 0; SEXP val = get_factor(obj, (order_) ? "sparseLU~" : "sparseLU"); if (!isNull(val)) return val; PROTECT(val = newObject("sparseLU")); Matrix_cs *A = M2CXS(obj, 1); MCS_XTYPE_SET(A->xtype); Matrix_css *S = NULL; Matrix_csn *N = NULL; int *P = NULL; if (A->m != A->n) error(_("LU factorization of m-by-n %s requires m == n"), ".gCMatrix"); if (!dgCMatrix_trf_(A, &S, &N, order_, tol_) || !(P = Matrix_cs_pinv(N->pinv, A->m))) { if (!P) { S = Matrix_cs_sfree(S); N = Matrix_cs_nfree(N); } if (asLogical(doError)) error(_("LU factorization of %s failed: out of memory or near-singular"), ".gCMatrix"); /* Defensive code will check with is(., "sparseLU") : */ UNPROTECT(1); /* val */ return ScalarLogical(NA_LOGICAL); } SEXP dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)); SET_SLOT(val, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(obj, Matrix_DimNamesSym)); SET_SLOT(val, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ SEXP L = PROTECT(CXS2M(N->L, 1, 't')), U = PROTECT(CXS2M(N->U, 1, 't')), uplo = PROTECT(mkString("L")); SET_SLOT(L, Matrix_uploSym, uplo); SET_SLOT(val, Matrix_LSym, L); SET_SLOT(val, Matrix_USym, U); UNPROTECT(3); /* uplo, U, L */ SEXP p = PROTECT(allocVector(INTSXP, A->m)); Matrix_memcpy(INTEGER(p), P, A->m, sizeof(int)); SET_SLOT(val, Matrix_pSym, p); UNPROTECT(1); /* p */ if (order_ > 0) { SEXP q = PROTECT(allocVector(INTSXP, A->n)); Matrix_memcpy(INTEGER(q), S->q, A->n, sizeof(int)); SET_SLOT(val, Matrix_qSym, q); UNPROTECT(1); /* q */ } S = Matrix_cs_sfree(S); N = Matrix_cs_nfree(N); P = Matrix_cs_free(P); set_factor(obj, (order_) ? "sparseLU~" : "sparseLU", val); UNPROTECT(1); /* val */ return val; } static int dgCMatrix_orf_(const Matrix_cs *A, Matrix_css **S, Matrix_csn **N, int order) { Matrix_cs *T = NULL; if (!(*S = Matrix_cs_sqr(order, A, 1)) || !(*N = Matrix_cs_qr(A, *S))) { DO_FREE(T, *S, *N); return 0; } DO_SORT((*N)->L); DO_SORT((*N)->U); return 1; } SEXP dgCMatrix_orf(SEXP obj, SEXP order, SEXP doError) { int order_ = asInteger(order); if (order_ < 0 || order_ > 3) order_ = 0; SEXP val = get_factor(obj, (order_) ? "sparseQR~" : "sparseQR"); if (!isNull(val)) return val; PROTECT(val = newObject("sparseQR")); Matrix_cs *A = M2CXS(obj, 1); MCS_XTYPE_SET(A->xtype); Matrix_css *S = NULL; Matrix_csn *N = NULL; int *P = NULL; if (A->m < A->n) error(_("QR factorization of m-by-n %s requires m >= n"), ".gCMatrix"); if (!dgCMatrix_orf_(A, &S, &N, order_) || !(P = Matrix_cs_pinv(S->pinv, S->m2))) { if (!P) { S = Matrix_cs_sfree(S); N = Matrix_cs_nfree(N); } if (asLogical(doError)) error(_("QR factorization of %s failed: out of memory"), ".gCMatrix"); /* Defensive code will check with is(., "sparseQR") : */ UNPROTECT(1); /* val */ return ScalarLogical(NA_LOGICAL); } SEXP dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)); SET_SLOT(val, Matrix_DimSym, dim); UNPROTECT(1); /* dim */ SEXP dimnames = PROTECT(GET_SLOT(obj, Matrix_DimNamesSym)); SET_SLOT(val, Matrix_DimNamesSym, dimnames); UNPROTECT(1); /* dimnames */ SEXP V = PROTECT(CXS2M(N->L, 1, 'g')), R = PROTECT(CXS2M(N->U, 1, 'g')); SET_SLOT(val, Matrix_VSym, V); SET_SLOT(val, Matrix_RSym, R); UNPROTECT(2); /* R, V */ SEXP beta = PROTECT(allocVector(REALSXP, A->n)); Matrix_memcpy(REAL(beta), N->B, A->n, sizeof(double)); SET_SLOT(val, Matrix_betaSym, beta); UNPROTECT(1); /* beta */ SEXP p = PROTECT(allocVector(INTSXP, S->m2)); Matrix_memcpy(INTEGER(p), P, S->m2, sizeof(int)); SET_SLOT(val, Matrix_pSym, p); UNPROTECT(1); /* p */ if (order_ > 0) { SEXP q = PROTECT(allocVector(INTSXP, A->n)); Matrix_memcpy(INTEGER(q), S->q, A->n, sizeof(int)); SET_SLOT(val, Matrix_qSym, q); UNPROTECT(1); /* q */ } S = Matrix_cs_sfree(S); N = Matrix_cs_nfree(N); P = Matrix_cs_free(P); set_factor(obj, (order_) ? "sparseQR~" : "sparseQR", val); UNPROTECT(1); /* val */ return val; } #undef DO_FREE #undef DO_SORT static int dpCMatrix_trf_(cholmod_sparse *A, cholmod_factor **L, int perm, int ldl, int super, double mult) { /* defined in ./cholmod-common.c : */ void R_cholmod_common_envget(void); void R_cholmod_common_envset(void); R_cholmod_common_envset(); if (*L == NULL) { if (perm == 0) { c.nmethods = 1; c.method[0].ordering = CHOLMOD_NATURAL; c.postorder = 0; } c.supernodal = (super == NA_LOGICAL) ? CHOLMOD_AUTO : ((super != 0) ? CHOLMOD_SUPERNODAL : CHOLMOD_SIMPLICIAL); *L = cholmod_analyze(A, &c); } if (super == NA_LOGICAL) super = (*L)->is_super; if (super != 0) ldl = 0; c.final_asis = 0; c.final_super = super != 0; c.final_ll = ldl == 0; c.final_pack = 1; c.final_monotonic = 1; double beta[2]; beta[0] = mult; beta[1] = 0.0; int res = cholmod_factorize_p(A, beta, NULL, 0, *L, &c); R_cholmod_common_envget(); return res; } SEXP dpCMatrix_trf(SEXP obj, SEXP perm, SEXP ldl, SEXP super, SEXP mult) { int perm_ = asLogical(perm), ldl_ = asLogical(ldl), super_ = asLogical(super); double mult_ = asReal(mult); if (!R_FINITE(mult_)) error(_("'%s' is not a number or not finite"), "mult"); SEXP trf = R_NilValue; char nm[] = "spdCholesky"; if (perm_) nm[1] = 'P'; if (super_ != NA_LOGICAL && super_ != 0) ldl_ = 0; if (super_ == NA_LOGICAL || super_ == 0) { if (ldl_) nm[2] = 'D'; trf = get_factor(obj, nm); } if (isNull(trf) && (super_ == NA_LOGICAL || super_ != 0)) { nm[0] = 'S'; nm[2] = 'd'; trf = get_factor(obj, nm); } int cached = !isNull(trf); if (cached && mult_ == 0.0) return trf; PROTECT_INDEX pid; PROTECT_WITH_INDEX(trf, &pid); cholmod_sparse *A = M2CHS(obj, 1); cholmod_factor *L = NULL; SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); A->stype = (ul == 'U') ? 1 : -1; if (cached) { L = M2CHF(trf, 1); L = cholmod_copy_factor(L, &c); dpCMatrix_trf_(A, &L, perm_, ldl_, super_, mult_); } else { dpCMatrix_trf_(A, &L, perm_, ldl_, super_, mult_); if (super_ == NA_LOGICAL) { nm[0] = (L->is_super) ? 'S' : 's'; nm[2] = (L->is_ll ) ? 'd' : 'D'; } } REPROTECT(trf = CHF2M(L, 1), pid); cholmod_free_factor(&L, &c); SEXP dimnames = PROTECT(GET_SLOT(obj, Matrix_DimNamesSym)); set_symmetrized_DimNames(trf, dimnames, -1); UNPROTECT(1); /* dimnames */ if (!cached && mult_ == 0.0) set_factor(obj, nm, trf); UNPROTECT(1); /* trf */ return trf; } SEXP BunchKaufman_expand(SEXP obj, SEXP packed) { SEXP P_ = PROTECT(newObject("pMatrix")), T_ = PROTECT(newObject("dtCMatrix")), D_ = PROTECT(newObject("dsCMatrix")), dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)); int i, j, s, n = INTEGER(dim)[0]; R_xlen_t n1a = (R_xlen_t) n + 1; if (n > 0) { SET_SLOT(P_, Matrix_DimSym, dim); SET_SLOT(T_, Matrix_DimSym, dim); SET_SLOT(D_, Matrix_DimSym, dim); } UNPROTECT(1); /* dim */ SEXP uplo = PROTECT(GET_SLOT(obj, Matrix_uploSym)); int upper = *CHAR(STRING_ELT(uplo, 0)) == 'U'; if (!upper) { SET_SLOT(T_, Matrix_uploSym, uplo); SET_SLOT(D_, Matrix_uploSym, uplo); } UNPROTECT(1); /* uplo */ SEXP diag = PROTECT(mkString("U")); SET_SLOT(T_, Matrix_diagSym, diag); UNPROTECT(1); /* diag */ SEXP pivot = PROTECT(GET_SLOT(obj, Matrix_permSym)), D_p = PROTECT(allocVector(INTSXP, n1a)); int *ppivot = INTEGER(pivot), *D_pp = INTEGER(D_p), b = n, dp = (upper) ? 1 : 2; D_pp[0] = 0; j = 0; while (j < n) { if (ppivot[j] > 0) { D_pp[j+1] = D_pp[j] + 1; j += 1; } else { D_pp[j+1] = D_pp[j] + dp; D_pp[j+2] = D_pp[j] + 3; j += 2; --b; } } SET_SLOT(D_, Matrix_pSym, D_p); UNPROTECT(1); /* D_p */ SEXP P, P_perm, T, T_p, T_i, T_x, D_i = PROTECT(allocVector(INTSXP, D_pp[n])), D_x = PROTECT(allocVector(REALSXP, D_pp[n])), x = PROTECT(GET_SLOT(obj, Matrix_xSym)); int *P_pperm, *T_pp, *T_pi, *D_pi = INTEGER(D_i); double *T_px, *D_px = REAL(D_x), *px = REAL(x); int unpacked = !asLogical(packed); R_xlen_t len = (R_xlen_t) 2 * b + 1, k = (upper) ? len - 2 : 0; SEXP res = PROTECT(allocVector(VECSXP, len)); j = 0; while (b--) { s = (ppivot[j] > 0) ? 1 : 2; dp = (upper) ? j : n - j - s; PROTECT(P = duplicate(P_)); PROTECT(P_perm = allocVector(INTSXP, n)); PROTECT(T = duplicate(T_)); PROTECT(T_p = allocVector(INTSXP, n1a)); PROTECT(T_i = allocVector(INTSXP, (R_xlen_t) s * dp)); PROTECT(T_x = allocVector(REALSXP, (R_xlen_t) s * dp)); P_pperm = INTEGER(P_perm); T_pp = INTEGER(T_p); T_pi = INTEGER(T_i); T_px = REAL(T_x); T_pp[0] = 0; for (i = 0; i < j; ++i) { T_pp[i+1] = 0; P_pperm[i] = i + 1; } for (i = j; i < j+s; ++i) { T_pp[i+1] = T_pp[i] + dp; P_pperm[i] = i + 1; } for (i = j+s; i < n; ++i) { T_pp[i+1] = T_pp[i]; P_pperm[i] = i + 1; } if (s == 1) { P_pperm[j] = ppivot[j]; P_pperm[ppivot[j]-1] = j + 1; } else if (upper) { P_pperm[j] = -ppivot[j]; P_pperm[-ppivot[j]-1] = j + 1; } else { P_pperm[j+1] = -ppivot[j]; P_pperm[-ppivot[j]-1] = j + 2; } if (upper) { for (i = 0; i < j; ++i) { *(T_pi++) = i; *(T_px++) = *(px++); } *(D_pi++) = j; *(D_px++) = *(px++); ++j; if (unpacked) px += n - j; if (s == 2) { for (i = 0; i < j-1; ++i) { *(T_pi++) = i; *(T_px++) = *(px++); } *(D_pi++) = j - 1; *(D_pi++) = j; *(D_px++) = *(px++); *(D_px++) = *(px++); ++j; if (unpacked) px += n - j; } } else { if (s == 2) { *(D_pi++) = j; *(D_pi++) = j + 1; *(D_px++) = *(px++); *(D_px++) = *(px++); for (i = j+2; i < n; ++i) { *(T_pi++) = i; *(T_px++) = *(px++); } ++j; if (unpacked) px += j; } *(D_pi++) = j; *(D_px++) = *(px++); for (i = j+1; i < n; ++i) { *(T_pi++) = i; *(T_px++) = *(px++); } ++j; if (unpacked) px += j; } SET_SLOT(P, Matrix_permSym, P_perm); SET_SLOT(T, Matrix_pSym, T_p); SET_SLOT(T, Matrix_iSym, T_i); SET_SLOT(T, Matrix_xSym, T_x); if (upper) { SET_VECTOR_ELT(res, k-1, P); SET_VECTOR_ELT(res, k , T); k -= 2; } else { SET_VECTOR_ELT(res, k , P); SET_VECTOR_ELT(res, k+1, T); k += 2; } UNPROTECT(6); /* T_x, T_i, T_p, T, P_perm, P */ } SET_SLOT(D_, Matrix_iSym, D_i); SET_SLOT(D_, Matrix_xSym, D_x); SET_VECTOR_ELT(res, len-1, D_); UNPROTECT(8); /* res, x, D_x, D_i, pivot, D_, T_, P_ */ return res; } SEXP CHMfactor_diag_get(SEXP obj, SEXP square) { cholmod_factor *L = M2CHF(obj, 1); int n = (int) L->n, square_ = asLogical(square); SEXP y = PROTECT(allocVector(REALSXP, n)); double *py = REAL(y); if (L->is_super) { int k, j, nc, nsuper = (int) L->nsuper, *psuper = (int *) L->super, *ppi = (int *) L->pi, *ppx = (int *) L->px; double *px = (double *) L->x, *px_; R_xlen_t nr1a; for (k = 0; k < nsuper; ++k) { nc = psuper[k+1] - psuper[k]; nr1a = (R_xlen_t) (ppi[k+1] - ppi[k]) + 1; px_ = px + ppx[k]; for (j = 0; j < nc; ++j) { *py = *px_; if (square_) *py *= *py; ++py; px_ += nr1a; } } } else { square_ = square_ && L->is_ll; int j, *pp = (int *) L->p; double *px = (double *) L->x; for (j = 0; j < n; ++j) { *py = px[pp[j]]; if (square_) *py *= *py; ++py; } } UNPROTECT(1); return y; } SEXP CHMfactor_update(SEXP obj, SEXP parent, SEXP mult) { /* defined in ./objects.c : */ char Matrix_shape(SEXP); double mult_ = asReal(mult); if (!R_FINITE(mult_)) error(_("'%s' is not a number or not finite"), "mult"); cholmod_factor *L = cholmod_copy_factor(M2CHF(obj, 1), &c); cholmod_sparse *A = M2CHS(parent, 1); if (Matrix_shape(parent) == 's') { SEXP uplo = GET_SLOT(parent, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); A->stype = (ul == 'U') ? 1 : -1; } dpCMatrix_trf_(A, &L, 0, !L->is_ll, L->is_super, mult_); SEXP res = PROTECT(CHF2M(L, 1)); cholmod_free_factor(&L, &c); SEXP dimnames = PROTECT(GET_SLOT(obj, Matrix_DimNamesSym)); SET_SLOT(res, Matrix_DimNamesSym, dimnames); UNPROTECT(1); UNPROTECT(1); return res; } SEXP CHMfactor_updown(SEXP obj, SEXP parent, SEXP update) { /* defined in ./objects.c : */ char Matrix_shape(SEXP); cholmod_factor *L = cholmod_copy_factor(M2CHF(obj, 1), &c); cholmod_sparse *A = M2CHS(parent, 1); if (Matrix_shape(parent) == 's') { SEXP uplo = GET_SLOT(parent, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); A->stype = (ul == 'U') ? 1 : -1; } cholmod_updown(asLogical(update) != 0, A, L, &c); SEXP res = PROTECT(CHF2M(L, 1)); cholmod_free_factor(&L, &c); SEXP dimnames = PROTECT(GET_SLOT(obj, Matrix_DimNamesSym)); SET_SLOT(res, Matrix_DimNamesSym, dimnames); UNPROTECT(1); UNPROTECT(1); return res; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/vector.h���������������������������������������������������������������������������������0000644�0001751�0000144�00000000215�14575137654�014015� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_VECTOR_H #define MATRIX_VECTOR_H #include SEXP v2spV(SEXP); SEXP CR2spV(SEXP); #endif /* MATRIX_VECTOR_H */ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/utils-R.h��������������������������������������������������������������������������������0000644�0001751�0000144�00000001041�14574651213�014037� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MATRIX_UTILS_R_H #define MATRIX_UTILS_R_H #include SEXP R_Matrix_version(void); SEXP R_index_triangle(SEXP, SEXP, SEXP, SEXP); SEXP R_index_diagonal(SEXP, SEXP, SEXP); SEXP R_nnz(SEXP, SEXP, SEXP); SEXP R_all0(SEXP); SEXP R_any0(SEXP); SEXP Mmatrix(SEXP); SEXP compressed_non_0_ij(SEXP, SEXP); SEXP Matrix_expand_pointers(SEXP); SEXP m_encodeInd (SEXP, SEXP, SEXP, SEXP); SEXP m_encodeInd2(SEXP, SEXP, SEXP, SEXP, SEXP); SEXP Matrix_rle_i(SEXP, SEXP); SEXP Matrix_rle_d(SEXP, SEXP); #endif /* MATRIX_UTILS_R_H */ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/utils-R.c��������������������������������������������������������������������������������0000644�0001751�0000144�00000037273�14575137654�014063� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "Mdefines.h" #include "utils-R.h" SEXP R_Matrix_version(void) { SEXP ans, nms; PROTECT(ans = allocVector(INTSXP, 3)); INTEGER(ans)[0] = MATRIX_PACKAGE_VERSION; INTEGER(ans)[1] = MATRIX_ABI_VERSION; INTEGER(ans)[2] = MATRIX_SUITESPARSE_VERSION; PROTECT(nms = allocVector(STRSXP, 3)); SET_STRING_ELT(nms, 0, mkChar("package")); SET_STRING_ELT(nms, 1, mkChar("abi")); SET_STRING_ELT(nms, 2, mkChar("suitesparse")); setAttrib(ans, R_NamesSymbol, nms); UNPROTECT(2); return ans; } SEXP R_index_triangle(SEXP n, SEXP packed, SEXP upper, SEXP diag) { SEXP r; int i, j, n_ = asInteger(n), packed_ = asLogical(packed), upper_ = asLogical(upper), diag_ = asLogical(diag); Matrix_int_fast64_t nn = (Matrix_int_fast64_t) n_ * n_, nx = (packed_) ? n_ + (nn - n_) / 2 : nn, nr = (diag_) ? n_ + (nn - n_) / 2 : (nn - n_) / 2; if (nx > 0x1.0p+53) error(_("indices would exceed %s"), "2^53"); if (nr > R_XLEN_T_MAX) error(_("attempt to allocate vector of length exceeding %s"), "R_XLEN_T_MAX"); #define DO_INDEX \ do { \ if (packed_) { \ if (diag_) { \ while (k <= nr_) \ *(pr++) = k++; \ } else if (upper_) { \ for (j = 0; j < n_; ++j) { \ for (i = 0; i < j; ++i) \ *(pr++) = k++; \ k++; \ } \ } else { \ for (j = 0; j < n_; ++j) { \ k++; \ for (i = j+1; i < n_; ++i) \ *(pr++) = k++; \ } \ } \ } else if (diag_) { \ if (upper_) { \ for (j = 0; j < n_; ++j) { \ for (i = 0; i <= j; ++i) \ *(pr++) = k++; \ k += n_-j-1; \ } \ } else { \ for (j = 0; j < n_; ++j) { \ k += j; \ for (i = j; i < n_; ++i) \ *(pr++) = k++; \ } \ } \ } else { \ if (upper_) { \ for (j = 0; j < n_; ++j) { \ for (i = 0; i < j; ++i) \ *(pr++) = k++; \ k += n_-j; \ } \ } else { \ for (j = 0; j < n_; ++j) { \ k += j+1; \ for (i = j+1; i < n_; ++i) \ *(pr++) = k++; \ } \ } \ } \ } while (0) if (nx > INT_MAX) { PROTECT(r = allocVector(REALSXP, (R_xlen_t) nr)); double k = 1.0, nr_ = (double) nr, *pr = REAL(r); DO_INDEX; } else { PROTECT(r = allocVector(INTSXP, (R_xlen_t) nr)); int k = 1, nr_ = (int) nr, *pr = INTEGER(r); DO_INDEX; } #undef DO_INDEX UNPROTECT(1); return r; } SEXP R_index_diagonal(SEXP n, SEXP packed, SEXP upper) { SEXP r; int j, n_ = asInteger(n), packed_ = asLogical(packed), upper_ = asLogical(upper); Matrix_int_fast64_t nn = (Matrix_int_fast64_t) n_ * n_, nx = (packed_) ? n_ + (nn - n_) / 2 : nn; if (nx > 0x1.0p+53) error(_("indices would exceed %s"), "2^53"); #define DO_INDEX \ do { \ if (!packed_) { \ for (j = 0; j < n_; ++j) { \ *(pr++) = k++; \ k += n_; \ } \ } else if (upper_) { \ for (j = 0; j < n_; ++j) { \ *(pr++) = k; \ k += j+2; \ } \ } else { \ for (j = 0; j < n_; ++j) { \ *(pr++) = k; \ k += n_-j; \ } \ } \ } while (0) if (nx > INT_MAX) { PROTECT(r = allocVector(REALSXP, n_)); double k = 1.0, *pr = REAL(r); DO_INDEX; } else { PROTECT(r = allocVector(INTSXP, n_)); int k = 1, *pr = INTEGER(r); DO_INDEX; } #undef DO_INDEX UNPROTECT(1); return r; } SEXP R_nnz(SEXP x, SEXP countNA, SEXP nnzmax) { int do_countNA = asLogical(countNA); R_xlen_t n = XLENGTH(x), nnz = 0; double n_ = asReal(nnzmax); if (!ISNAN(n_) && n_ >= 0.0 && n_ < (double) n) n = (R_xlen_t) n_; #define DO_NNZ(_CTYPE_, _PTR_, _ISNA_, _ISNZ_, _STRICTLY_ISNZ_) \ do { \ _CTYPE_ *px = _PTR_(x); \ if (do_countNA == NA_LOGICAL) { \ while (n-- > 0) { \ if (_ISNA_(*px)) \ return ScalarInteger(NA_INTEGER); \ if (_ISNZ_(*px)) \ ++nnz; \ ++px; \ } \ } else if (do_countNA != 0) { \ while (n-- > 0) { \ if (_ISNZ_(*px)) \ ++nnz; \ ++px; \ } \ } else { \ while (n-- > 0) { \ if (_STRICTLY_ISNZ_(*px)) \ ++nnz; \ ++px; \ } \ } \ } while (0) switch (TYPEOF(x)) { case LGLSXP: DO_NNZ(int, LOGICAL, ISNA_LOGICAL, ISNZ_LOGICAL, STRICTLY_ISNZ_LOGICAL); break; case INTSXP: DO_NNZ(int, INTEGER, ISNA_INTEGER, ISNZ_INTEGER, STRICTLY_ISNZ_INTEGER); break; case REALSXP: DO_NNZ(double, REAL, ISNA_REAL, ISNZ_REAL, STRICTLY_ISNZ_REAL); break; case CPLXSXP: DO_NNZ(Rcomplex, COMPLEX, ISNA_COMPLEX, ISNZ_COMPLEX, STRICTLY_ISNZ_COMPLEX); break; default: ERROR_INVALID_TYPE(x, __func__); } #undef DO_NNZ return (nnz <= INT_MAX) ? ScalarInteger((int) nnz) : ScalarReal((double) nnz); } /* ================================================================== */ /* ================================================================== */ #define TRUE_ ScalarLogical(1) #define FALSE_ ScalarLogical(0) // Fast implementation of [ originally in ../R/Auxiliaries.R ] // all0 <- function(x) !any(is.na(x)) && all(!x) ## ~= allFalse // allFalse <- function(x) !any(x) && !any(is.na(x)) ## ~= all0 SEXP R_all0(SEXP x) { if (!isVectorAtomic(x)) { if (length(x) == 0) return TRUE_; // Typically S4. TODO: Call the R code above, instead! error(_("Argument must be numeric-like atomic vector")); } R_xlen_t i, n = XLENGTH(x); if (n == 0) return TRUE_; switch (TYPEOF(x)) { case LGLSXP: { int *xx = LOGICAL(x); for (i = 0; i < n; i++) if (xx[i] == NA_LOGICAL || xx[i] != 0) return FALSE_; return TRUE_; } case INTSXP: { int *xx = INTEGER(x); for (i = 0; i < n; i++) if (xx[i] == NA_INTEGER || xx[i] != 0) return FALSE_; return TRUE_; } case REALSXP: { double *xx = REAL(x); for (i = 0; i < n; i++) if (ISNAN(xx[i]) || xx[i] != 0.) return FALSE_; return TRUE_; } case RAWSXP: { unsigned char *xx = RAW(x); for (i = 0; i < n; i++) if (xx[i] != 0) return FALSE_; return TRUE_; } } error(_("Argument must be numeric-like atomic vector")); return R_NilValue; // -Wall } // Fast implementation of [ originally in ../R/Auxiliaries.R ] // any0 <- function(x) isTRUE(any(x == 0)) ## ~= anyFalse // anyFalse <- function(x) isTRUE(any(!x)) ## ~= any0 SEXP R_any0(SEXP x) { if (!isVectorAtomic(x)) { if (length(x) == 0) return FALSE_; // Typically S4. TODO: Call the R code above, instead! error(_("Argument must be numeric-like atomic vector")); } R_xlen_t i, n = XLENGTH(x); if (n == 0) return FALSE_; switch (TYPEOF(x)) { case LGLSXP: { int *xx = LOGICAL(x); for (i = 0; i < n; i++) if (xx[i] == 0) return TRUE_; return FALSE_; } case INTSXP: { int *xx = INTEGER(x); for (i = 0; i < n; i++) if (xx[i] == 0) return TRUE_; return FALSE_; } case REALSXP: { double *xx = REAL(x); for (i = 0; i < n; i++) if (xx[i] == 0.) return TRUE_; return FALSE_; } case RAWSXP: { unsigned char *xx = RAW(x); for (i = 0; i < n; i++) if (xx[i] == 0) return TRUE_; return FALSE_; } } error(_("Argument must be numeric-like atomic vector")); return R_NilValue; // -Wall } #undef TRUE_ #undef FALSE_ // Almost "Cut n Paste" from ...R../src/main/array.c do_matrix() : // used in ../R/Matrix.R as // // .External(Mmatrix, // data, nrow, ncol, byrow, dimnames, // missing(nrow), missing(ncol)) SEXP Mmatrix(SEXP args) { SEXP vals, ans, snr, snc, dimnames; int nr = 1, nc = 1, byrow, miss_nr, miss_nc; R_xlen_t lendat; args = CDR(args); /* skip 'name' */ vals = CAR(args); args = CDR(args); /* Supposedly as.vector() gave a vector type, but we check */ switch (TYPEOF(vals)) { case LGLSXP: case INTSXP: case REALSXP: case CPLXSXP: case STRSXP: case RAWSXP: case EXPRSXP: case VECSXP: break; default: error(_("'data' must be of a vector type")); } lendat = XLENGTH(vals); snr = CAR(args); args = CDR(args); snc = CAR(args); args = CDR(args); byrow = asLogical(CAR(args)); args = CDR(args); if (byrow == NA_INTEGER) error(_("invalid '%s' argument"), "byrow"); dimnames = CAR(args); args = CDR(args); miss_nr = asLogical(CAR(args)); args = CDR(args); miss_nc = asLogical(CAR(args)); if (!miss_nr) { if (!isNumeric(snr)) error(_("non-numeric matrix extent")); nr = asInteger(snr); if (nr == NA_INTEGER) error(_("invalid 'nrow' value (too large or NA)")); if (nr < 0) error(_("invalid 'nrow' value (< 0)")); } if (!miss_nc) { if (!isNumeric(snc)) error(_("non-numeric matrix extent")); nc = asInteger(snc); if (nc == NA_INTEGER) error(_("invalid 'ncol' value (too large or NA)")); if (nc < 0) error(_("invalid 'ncol' value (< 0)")); } if (miss_nr && miss_nc) { if (lendat > INT_MAX) error("data is too long"); nr = (int) lendat; } else if (miss_nr) { if (lendat > (double) nc * INT_MAX) error("data is too long"); nr = (int) ceil((double) lendat / (double) nc); } else if (miss_nc) { if (lendat > (double) nr * INT_MAX) error("data is too long"); nc = (int) ceil((double) lendat / (double) nr); } if (lendat > 0) { R_xlen_t nrc = (R_xlen_t) nr * nc; if (lendat > 1 && nrc % lendat != 0) { if ((lendat > nr && (lendat / nr) * nr != lendat) || (lendat < nr && (nr / lendat) * lendat != nr)) warning(_("data length [%lld] is not a sub-multiple " "or multiple of the number of rows [%d]"), (long long)lendat, nr); else if ((lendat > nc && (lendat / nc) * nc != lendat) || (lendat < nc && (nc / lendat) * lendat != nc)) warning(_("data length [%lld] is not a sub-multiple " "or multiple of the number of columns [%d]"), (long long)lendat, nc); } else if (lendat > 1 && nrc == 0) warning(_("data length exceeds size of matrix")); } #ifndef LONG_VECTOR_SUPPORT if ((double) nr * (double) nc > INT_MAX) error(_("too many elements specified")); #endif PROTECT(ans = allocMatrix(TYPEOF(vals), nr, nc)); if (lendat) { if (isVector(vals)) copyMatrix(ans, vals, byrow); else copyListMatrix(ans, vals, byrow); } else if (isVector(vals)) { /* fill with NAs */ R_xlen_t N = (R_xlen_t) nr * nc, i; switch (TYPEOF(vals)) { case STRSXP: for (i = 0; i < N; i++) SET_STRING_ELT(ans, i, NA_STRING); break; case LGLSXP: for (i = 0; i < N; i++) LOGICAL(ans)[i] = NA_LOGICAL; break; case INTSXP: for (i = 0; i < N; i++) INTEGER(ans)[i] = NA_INTEGER; break; case REALSXP: for (i = 0; i < N; i++) REAL(ans)[i] = NA_REAL; break; case CPLXSXP: { /* Initialization must work whether Rcomplex is typedef-ed to a struct { R < 4.3.0 } or to a union { R >= 4.3.0 } */ Rcomplex zna = { .r = NA_REAL, .i = 0.0 }; for (i = 0; i < N; i++) COMPLEX(ans)[i] = zna; break; } case RAWSXP: // FIXME: N may overflow size_t !! memset(RAW(ans), 0, N); break; default: /* don't fill with anything */ ; } } if (!isNull(dimnames)&& length(dimnames) > 0) ans = dimnamesgets(ans, dimnames); UNPROTECT(1); return ans; } /** * Expand compressed pointers in the array mp into a full set of indices * in the array mj. * * @param ncol number of columns (or rows) * @param mp column pointer vector of length ncol + 1 * @param mj vector of length mp[ncol] to hold the result * * @return mj */ static int *expand_cmprPt(int ncol, const int mp[], int mj[]) { int j; for (j = 0; j < ncol; j++) { int j2 = mp[j+1], jj; for (jj = mp[j]; jj < j2; jj++) mj[jj] = j; } return mj; } /** Return a 2 column matrix '' cbind(i, j) '' of 0-origin index vectors (i,j) * which entirely correspond to the (i,j) slots of * as(x, "TsparseMatrix") : */ SEXP compressed_non_0_ij(SEXP x, SEXP colP) { int col = asLogical(colP); /* 1 if "C"olumn compressed; 0 if "R"ow */ SEXP ans, indSym = col ? Matrix_iSym : Matrix_jSym; SEXP indP = PROTECT(GET_SLOT(x, indSym)), pP = PROTECT(GET_SLOT(x, Matrix_pSym)); int i, *ij; int nouter = INTEGER(GET_SLOT(x, Matrix_DimSym))[col ? 1 : 0], n_el = INTEGER(pP)[nouter]; /* is only == length(indP), if the inner slot is not over-allocated */ ij = INTEGER(ans = PROTECT(allocMatrix(INTSXP, n_el, 2))); /* expand the compressed margin to 'i' or 'j' : */ expand_cmprPt(nouter, INTEGER(pP), &ij[col ? n_el : 0]); /* and copy the other one: */ if (col) for(i = 0; i < n_el; i++) ij[i] = INTEGER(indP)[i]; else /* row compressed */ for(i = 0; i < n_el; i++) ij[i + n_el] = INTEGER(indP)[i]; UNPROTECT(3); return ans; } SEXP Matrix_expand_pointers(SEXP pP) { int n = length(pP) - 1; int *p = INTEGER(pP); SEXP ans = PROTECT(allocVector(INTSXP, p[n])); expand_cmprPt(n, p, INTEGER(ans)); UNPROTECT(1); return ans; } /** * Encode Matrix index (i,j) |--> i + j * nrow {i,j : 0-origin} * * @param ij: 2-column integer matrix * @param di: dim(.), i.e. length 2 integer vector * @param chk_bnds: logical indicating 0 <= ij[,k] < di[k] need to be checked. * * @return encoded index; integer if prod(dim) is small; double otherwise */ SEXP m_encodeInd(SEXP ij, SEXP di, SEXP orig_1, SEXP chk_bnds) { SEXP ans; int *ij_di = NULL, n, nprot=1; Rboolean check_bounds = asLogical(chk_bnds), one_ind = asLogical(orig_1); if (TYPEOF(di) != INTSXP) { di = PROTECT(coerceVector(di, INTSXP)); nprot++; } if (TYPEOF(ij) != INTSXP) { ij = PROTECT(coerceVector(ij, INTSXP)); nprot++; } if (!isMatrix(ij) || (ij_di = INTEGER(getAttrib(ij, R_DimSymbol)))[1] != 2) error(_("Argument ij must be 2-column integer matrix")); n = ij_di[0]; int *Di = INTEGER(di), *IJ = INTEGER(ij), *j_ = IJ+n;/* pointer offset! */ if ((Di[0] * (double) Di[1]) >= 1 + (double)INT_MAX) { /* need double */ ans = PROTECT(allocVector(REALSXP, n)); double *ii = REAL(ans), nr = (double) Di[0]; #define do_ii_FILL(_i_, _j_) \ int i; \ if (check_bounds) { \ for (i = 0; i < n; i++) { \ if (_i_[i] == NA_INTEGER || _j_[i] == NA_INTEGER) \ ii[i] = NA_INTEGER; \ else { \ register int i_i, j_i; \ if (one_ind) { \ i_i = _i_[i]-1; \ j_i = _j_[i]-1; \ } else { \ i_i = _i_[i]; \ j_i = _j_[i]; \ } \ if (i_i < 0 || i_i >= Di[0]) \ error(_("subscript 'i' out of bounds in M[ij]")); \ if (j_i < 0 || j_i >= Di[1]) \ error(_("subscript 'j' out of bounds in M[ij]")); \ ii[i] = i_i + j_i * nr; \ } \ } \ } else { \ for (i = 0; i < n; i++) \ ii[i] = (_i_[i] == NA_INTEGER || _j_[i] == NA_INTEGER) \ ? NA_INTEGER \ : ((one_ind) \ ? ((_i_[i]-1) + (_j_[i]-1) * nr) \ : _i_[i] + _j_[i] * nr); \ } do_ii_FILL(IJ, j_); } else { ans = PROTECT(allocVector(INTSXP, n)); int *ii = INTEGER(ans), nr = Di[0]; do_ii_FILL(IJ, j_); } UNPROTECT(nprot); return ans; } /** * Encode Matrix index (i,j) |--> i + j * nrow {i,j : 0-origin} * * @param i: integer vector * @param j: integer vector of same length as 'i' * @param orig_1: logical: if TRUE, "1-origin" otherwise "0-origin" * @param di: dim(.), i.e. length 2 integer vector * @param chk_bnds: logical indicating 0 <= ij[,k] < di[k] need to be checked. * * @return encoded index; integer if prod(dim) is small; double otherwise */ SEXP m_encodeInd2(SEXP i, SEXP j, SEXP di, SEXP orig_1, SEXP chk_bnds) { SEXP ans; int n = LENGTH(i), nprot = 1; Rboolean check_bounds = asLogical(chk_bnds), one_ind = asLogical(orig_1); if (TYPEOF(di)!= INTSXP) { di = PROTECT(coerceVector(di,INTSXP)); nprot++; } if (TYPEOF(i) != INTSXP) { i = PROTECT(coerceVector(i, INTSXP)); nprot++; } if (TYPEOF(j) != INTSXP) { j = PROTECT(coerceVector(j, INTSXP)); nprot++; } if (LENGTH(j) != n) error(_("i and j must be integer vectors of the same length")); int *Di = INTEGER(di), *i_ = INTEGER(i), *j_ = INTEGER(j); if ((Di[0] * (double) Di[1]) >= 1 + (double) INT_MAX) { /* need double */ ans = PROTECT(allocVector(REALSXP, n)); double *ii = REAL(ans), nr = (double) Di[0]; do_ii_FILL(i_, j_); } else { ans = PROTECT(allocVector(INTSXP, n)); int *ii = INTEGER(ans), nr = Di[0]; do_ii_FILL(i_, j_); } UNPROTECT(nprot); return ans; } #undef do_ii_FILL #define _rle_d_ #include "t_rle.c" #undef _rle_d_ #define _rle_i_ #include "t_rle.c" #undef _rle_i_ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/�����������������������������������������������������������������������������0000755�0001751�0000144�00000000000�14576343415�014606� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/������������������������������������������������������������������������0000755�0001751�0000144�00000000000�14576344041�015306� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Include/����������������������������������������������������������������0000755�0001751�0000144�00000000000�14576343415�016675� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Include/camd_internal.h�������������������������������������������������0000644�0001751�0000144�00000015502�14552026002�021631� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_internal.h: internal definitions for CAMD //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2023, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* This file is for internal use in CAMD itself, and does not normally need to * be included in user code (it is included in UMFPACK, however). All others * should use camd.h instead. */ /* ========================================================================= */ /* === NDEBUG ============================================================== */ /* ========================================================================= */ /* * Turning on debugging takes some work (see below). If you do not edit this * file, then debugging is always turned off, regardless of whether or not * -DNDEBUG is specified in your compiler options. * * If CAMD is being compiled as a mexFunction, then MATLAB_MEX_FILE is defined, * and mxAssert is used instead of assert. If debugging is not enabled, no * MATLAB include files or functions are used. Thus, the CAMD library libcamd.a * can be safely used in either a stand-alone C program or in another * mexFunction, without any change. */ /* CAMD 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 */ /* ------------------------------------------------------------------------- */ /* basic definitions */ /* ------------------------------------------------------------------------- */ #ifdef FLIP #undef FLIP #endif #ifdef MAX #undef MAX #endif #ifdef MIN #undef MIN #endif #ifdef EMPTY #undef EMPTY #endif #define PRIVATE static /* 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 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 /* largest value of size_t */ #ifndef SIZE_T_MAX #ifdef SIZE_MAX /* C99 only */ #define SIZE_T_MAX SIZE_MAX #else #define SIZE_T_MAX ((size_t) (-1)) #endif #endif /* ------------------------------------------------------------------------- */ /* integer type for CAMD: int32_t or int64_t */ /* ------------------------------------------------------------------------- */ #include "camd.h" #if defined (DLONG) || defined (ZLONG) #define Int int64_t #define UInt uint64_t #define ID "%" PRId64 #define Int_MAX INT64_MAX #define CAMD_order camd_l_order #define CAMD_defaults camd_l_defaults #define CAMD_control camd_l_control #define CAMD_info camd_l_info #define CAMD_1 camd_l1 #define CAMD_2 camd_l2 #define CAMD_valid camd_l_valid #define CAMD_cvalid camd_l_cvalid #define CAMD_aat camd_l_aat #define CAMD_postorder camd_l_postorder #define CAMD_dump camd_l_dump #define CAMD_debug camd_l_debug #define CAMD_debug_init camd_l_debug_init #define CAMD_preprocess camd_l_preprocess #else #define Int int32_t #define UInt uint32_t #define ID "%d" #define Int_MAX INT_MAX #define CAMD_order camd_order #define CAMD_defaults camd_defaults #define CAMD_control camd_control #define CAMD_info camd_info #define CAMD_1 camd_1 #define CAMD_2 camd_2 #define CAMD_valid camd_valid #define CAMD_cvalid camd_cvalid #define CAMD_aat camd_aat #define CAMD_postorder camd_postorder #define CAMD_dump camd_dump #define CAMD_debug camd_debug #define CAMD_debug_init camd_debug_init #define CAMD_preprocess camd_preprocess #endif /* ------------------------------------------------------------------------- */ /* CAMD routine definitions (not user-callable) */ /* ------------------------------------------------------------------------- */ size_t CAMD_aat ( Int n, const Int Ap [ ], const Int Ai [ ], Int Len [ ], Int Tp [ ], double Info [ ] ) ; void CAMD_1 ( Int n, const Int Ap [ ], const Int Ai [ ], Int P [ ], Int Pinv [ ], Int Len [ ], Int slen, Int S [ ], double Control [ ], double Info [ ], const Int C [ ] ) ; Int CAMD_postorder ( Int j, Int k, Int n, Int head [], Int next [], Int post [], Int stack [] ) ; void CAMD_preprocess ( Int n, const Int Ap [ ], const Int Ai [ ], Int Rp [ ], Int Ri [ ], Int W [ ], Int Flag [ ] ) ; /* ------------------------------------------------------------------------- */ /* debugging definitions */ /* ------------------------------------------------------------------------- */ #ifndef NDEBUG /* from assert.h: assert macro */ #include extern Int CAMD_debug ; void CAMD_debug_init ( char *s ) ; void CAMD_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, Int BucketSet [], const Int C [], Int Curc ) ; #ifdef ASSERT #undef ASSERT #endif /* Use mxAssert if CAMD is compiled into a mexFunction */ #ifdef MATLAB_MEX_FILE #define ASSERT(expression) (mxAssert ((expression), "")) #else #define ASSERT(expression) (assert (expression)) #endif #define CAMD_DEBUG0(params) { SUITESPARSE_PRINTF (params) ; } #define CAMD_DEBUG1(params) \ { if (CAMD_debug >= 1) SUITESPARSE_PRINTF (params) ; } #define CAMD_DEBUG2(params) \ { if (CAMD_debug >= 2) SUITESPARSE_PRINTF (params) ; } #define CAMD_DEBUG3(params) \ { if (CAMD_debug >= 3) SUITESPARSE_PRINTF (params) ; } #define CAMD_DEBUG4(params) \ { if (CAMD_debug >= 4) SUITESPARSE_PRINTF (params) ; } #else /* no debugging */ #define ASSERT(expression) #define CAMD_DEBUG0(params) #define CAMD_DEBUG1(params) #define CAMD_DEBUG2(params) #define CAMD_DEBUG3(params) #define CAMD_DEBUG4(params) #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Include/camd.h����������������������������������������������������������0000644�0001751�0000144�00000041250�14552026002�017734� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Include/camd.h: constrained approximate minimum degree ordering //------------------------------------------------------------------------------ // CAMD, Copyright (c) 1996-2024, Timothy A. Davis, Yanqing Chen, // Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* CAMD 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 int32_t integers and the other for int64_t 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. */ #ifndef CAMD_H #define CAMD_H #include "SuiteSparse_config.h" /* make it easy for C++ programs to include CAMD */ #ifdef __cplusplus extern "C" { #endif int camd_order /* returns CAMD_OK, CAMD_OK_BUT_JUMBLED, * CAMD_INVALID, or CAMD_OUT_OF_MEMORY */ ( int32_t n, /* A is n-by-n. n must be >= 0. */ const int32_t Ap [ ], /* column pointers for A, of size n+1 */ const int32_t Ai [ ], /* row indices of A, of size nz = Ap [n] */ int32_t P [ ], /* output permutation, of size n */ double Control [ ], /* input Control settings, of size CAMD_CONTROL */ double Info [ ], /* output Info statistics, of size CAMD_INFO */ const int32_t C [ ] /* Constraint set of A, of size n; can be NULL */ ) ; int camd_l_order /* see above for description */ ( int64_t n, const int64_t Ap [ ], const int64_t Ai [ ], int64_t P [ ], double Control [ ], double Info [ ], const int64_t C [ ] ) ; /* Input arguments (not modified): * * n: the matrix A is n-by-n. * Ap: an int32_t/int64_t array of size n+1, containing column * pointers of A. * Ai: an int32_t/int64_t array of size nz, containing the row * indices of A, where nz = Ap [n]. * Control: a double array of size CAMD_CONTROL, containing control * parameters. Defaults are used if Control is NULL. * * Output arguments (not defined on input): * * P: an int32_t/int64_t 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 CAMD_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]. * * If the row indices appear in ascending order in each column, and there * are no duplicate entries, then camd_order is slightly more efficient in * terms of time and memory usage. If this condition does not hold, a copy * of the matrix is created (where these conditions do hold), and the copy is * ordered. * * 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 [CAMD_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.suitesparse.com. * * 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. Ai [0..nz-1] must be in the range 0 * to n-1. Finally, Ai, Ap, and P must not be NULL. If any of these * restrictions are not met, CAMD returns CAMD_INVALID. * * CAMD returns: * * CAMD_OK if the matrix is valid and sufficient memory can be allocated to * perform the ordering. * * CAMD_OUT_OF_MEMORY if not enough memory can be allocated. * * CAMD_INVALID if the input arguments n, Ap, Ai are invalid, or if P is * NULL. * * CAMD_OK_BUT_JUMBLED if the matrix had unsorted columns, and/or duplicate * entries, but was otherwise valid. * * The CAMD 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 CAMD. If a NULL * pointer is passed, default values are used. The Control array is not * modified. * * Control [CAMD_DENSE]: controls the threshold for "dense" rows/columns. * A dense row/column in A+A' can cause CAMD to spend a lot of time in * ordering the matrix. If Control [CAMD_DENSE] >= 0, rows/columns * with more than Control [CAMD_DENSE] * sqrt (n) entries are ignored * during the ordering, and placed last in the output order. The * default value of Control [CAMD_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 [CAMD_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 [CAMD_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 [CAMD_STATUS]: the return value of CAMD, either CAMD_OK, * CAMD_OK_BUT_JUMBLED, CAMD_OUT_OF_MEMORY, or CAMD_INVALID. * * Info [CAMD_N]: n, the size of the input matrix * * Info [CAMD_NZ]: the number of nonzeros in A, nz = Ap [n] * * Info [CAMD_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 [CAMD_NZDIAG]: the number of entries on the diagonal of A. * * Info [CAMD_NZ_A_PLUS_AT]: the number of nonzeros in A+A', excluding the * diagonal. If A is perfectly symmetric (Info [CAMD_SYMMETRY] = 1) * with a fully nonzero diagonal, then Info [CAMD_NZ_A_PLUS_AT] = nz-n * (the smallest possible value). If A is perfectly unsymmetric * (Info [CAMD_SYMMETRY] = 0, for an upper triangular matrix, for * example) with no diagonal, then Info [CAMD_NZ_A_PLUS_AT] = 2*nz * (the largest possible value). * * Info [CAMD_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 [CAMD_MEMORY]: the amount of memory used by CAMD, in bytes. In the * current version, this is 1.2 * Info [CAMD_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 [CAMD_NCMPA]: the number of garbage collections performed. * * Info [CAMD_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 [CAMD_NDIV]: the number of divide operations for a subsequent LDL' * or LU factorization of the permuted matrix A (P,P). * * Info [CAMD_NMULTSUBS_LDL]: the number of multiply-subtract pairs for a * subsequent LDL' factorization of A (P,P). * * Info [CAMD_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 [CAMD_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. */ /* ------------------------------------------------------------------------- */ /* direct interface to CAMD */ /* ------------------------------------------------------------------------- */ /* camd_2 is the primary CAMD ordering routine. It is not meant to be * user-callable because of its restrictive inputs and because it destroys * the user's input matrix. It does not check its inputs for errors, either. * However, if you can work with these restrictions it can be faster than * camd_order and use less memory (assuming that you can create your own copy * of the matrix for CAMD to destroy). Refer to CAMD/Source/camd_2.c for a * description of each parameter. */ void camd_2 ( int32_t n, int32_t Pe [ ], int32_t Iw [ ], int32_t Len [ ], int32_t iwlen, int32_t pfree, int32_t Nv [ ], int32_t Next [ ], int32_t Last [ ], int32_t Head [ ], int32_t Elen [ ], int32_t Degree [ ], int32_t W [ ], double Control [ ], double Info [ ], const int32_t C [ ], int32_t BucketSet [ ] ) ; void camd_l2 ( int64_t n, int64_t Pe [ ], int64_t Iw [ ], int64_t Len [ ], int64_t iwlen, int64_t pfree, int64_t Nv [ ], int64_t Next [ ], int64_t Last [ ], int64_t Head [ ], int64_t Elen [ ], int64_t Degree [ ], int64_t W [ ], double Control [ ], double Info [ ], const int64_t C [ ], int64_t BucketSet [ ] ) ; /* ------------------------------------------------------------------------- */ /* camd_valid */ /* ------------------------------------------------------------------------- */ /* Returns CAMD_OK or CAMD_OK_BUT_JUMBLED if the matrix is valid as input to * camd_order; the latter is returned if the matrix has unsorted and/or * duplicate row indices in one or more columns. Returns CAMD_INVALID if the * matrix cannot be passed to camd_order. For camd_order, the matrix must also * be square. The first two arguments are the number of rows and the number * of columns of the matrix. For its use in CAMD, these must both equal n. */ int camd_valid ( int32_t n_row, /* # of rows */ int32_t n_col, /* # of columns */ const int32_t Ap [ ], /* column pointers, of size n_col+1 */ const int32_t Ai [ ] /* row indices, of size Ap [n_col] */ ) ; int camd_l_valid ( int64_t n_row, int64_t n_col, const int64_t Ap [ ], const int64_t Ai [ ] ) ; /* ------------------------------------------------------------------------- */ /* camd_cvalid */ /* ------------------------------------------------------------------------- */ /* Returns TRUE if the constraint set is valid as input to camd_order, * FALSE otherwise. */ int camd_cvalid ( int32_t n, const int32_t C [ ] ) ; int camd_l_cvalid ( int64_t n, const int64_t C [ ] ) ; /* ------------------------------------------------------------------------- */ /* CAMD Control and Info arrays */ /* ------------------------------------------------------------------------- */ /* camd_defaults: sets the default control settings */ void camd_defaults (double Control [ ]) ; void camd_l_defaults (double Control [ ]) ; /* camd_control: prints the control settings */ void camd_control (double Control [ ]) ; void camd_l_control (double Control [ ]) ; /* camd_info: prints the statistics */ void camd_info (double Info [ ]) ; void camd_l_info (double Info [ ]) ; // camd_version: return CAMD version. The version array is returned with // version [0..2] = {CAMD_MAIN_VERSION, CAMD_SUB_VERSION, CAMD_SUBSUB_VERSION} void camd_version (int version [3]) ; #ifdef __cplusplus } #endif #define CAMD_CONTROL 5 /* size of Control array */ #define CAMD_INFO 20 /* size of Info array */ /* contents of Control */ #define CAMD_DENSE 0 /* "dense" if degree > Control [0] * sqrt (n) */ #define CAMD_AGGRESSIVE 1 /* do aggressive absorption if Control [1] != 0 */ /* default Control settings */ #define CAMD_DEFAULT_DENSE 10.0 /* default "dense" degree 10*sqrt(n) */ #define CAMD_DEFAULT_AGGRESSIVE 1 /* do aggressive absorption by default */ /* contents of Info */ #define CAMD_STATUS 0 /* return value of camd_order and camd_l_order */ #define CAMD_N 1 /* A is n-by-n */ #define CAMD_NZ 2 /* number of nonzeros in A */ #define CAMD_SYMMETRY 3 /* symmetry of pattern (1 is sym., 0 is unsym.) */ #define CAMD_NZDIAG 4 /* # of entries on diagonal */ #define CAMD_NZ_A_PLUS_AT 5 /* nz in A+A' */ #define CAMD_NDENSE 6 /* number of "dense" rows/columns in A */ #define CAMD_MEMORY 7 /* amount of memory used by CAMD */ #define CAMD_NCMPA 8 /* number of garbage collections in CAMD */ #define CAMD_LNZ 9 /* approx. nz in L, excluding the diagonal */ #define CAMD_NDIV 10 /* number of fl. point divides for LU and LDL' */ #define CAMD_NMULTSUBS_LDL 11 /* number of fl. point (*,-) pairs for LDL' */ #define CAMD_NMULTSUBS_LU 12 /* number of fl. point (*,-) pairs for LU */ #define CAMD_DMAX 13 /* max nz. in any column of L, incl. diagonal */ /* ------------------------------------------------------------------------- */ /* return values of CAMD */ /* ------------------------------------------------------------------------- */ #define CAMD_OK 0 /* success */ #define CAMD_OUT_OF_MEMORY -1 /* malloc failed, or problem too large */ #define CAMD_INVALID -2 /* input arguments are not valid */ #define CAMD_OK_BUT_JUMBLED 1 /* input matrix is OK for camd_order, but * columns were not sorted, and/or duplicate entries were present. CAMD had * to do extra work before ordering the matrix. This is a warning, not an * error. */ /* ========================================================================== */ /* === CAMD version ========================================================= */ /* ========================================================================== */ /* * As an example, to test if the version you are using is 1.2 or later: * * if (CAMD_VERSION >= CAMD_VERSION_CODE (1,2)) ... * * This also works during compile-time: * * #if (CAMD_VERSION >= CAMD_VERSION_CODE (1,2)) * printf ("This is version 1.2 or later\n") ; * #else * printf ("This is an early version\n") ; * #endif */ #define CAMD_DATE "Jan 10, 2024" #define CAMD_MAIN_VERSION 3 #define CAMD_SUB_VERSION 3 #define CAMD_SUBSUB_VERSION 1 #define CAMD_VERSION_CODE(main,sub) SUITESPARSE_VER_CODE(main,sub) #define CAMD_VERSION CAMD_VERSION_CODE(3,3) #define CAMD__VERSION SUITESPARSE__VERCODE(3,3,1) #if !defined (SUITESPARSE__VERSION) || \ (SUITESPARSE__VERSION < SUITESPARSE__VERCODE(7,5,0)) #error "CAMD 3.3.1 requires SuiteSparse_config 7.5.0 or later" #endif #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Makefile����������������������������������������������������������������0000644�0001751�0000144�00000001557�14576344042�016757� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sources = \ Source/camd_1.c Source/camd_l1.c \ Source/camd_2.c Source/camd_l2.c \ Source/camd_aat.c Source/camd_l_aat.c \ Source/camd_control.c Source/camd_l_control.c \ Source/camd_defaults.c Source/camd_l_defaults.c \ Source/camd_dump.c Source/camd_l_dump.c \ Source/camd_info.c Source/camd_l_info.c \ Source/camd_order.c Source/camd_l_order.c \ Source/camd_postorder.c Source/camd_l_postorder.c \ Source/camd_preprocess.c Source/camd_l_preprocess.c \ Source/camd_valid.c Source/camd_l_valid.c \ Source/camd_version.c objects = $(sources:.c=.o) archive = CAMD.a PKG_CPPFLAGS = -I./Include -I../SuiteSparse_config all : $(archive) $(archive) : $(objects) rm -f $@ $(AR) -cr $@ $(objects) $(RANLIB) $@ .c.o : $(CC) $(PKG_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) -c $< -o $*.o clean : @rm -f $(objects) $(archive) �������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/�����������������������������������������������������������������0000755�0001751�0000144�00000000000�14576344041�016546� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_l_control.c�������������������������������������������������0000644�0001751�0000144�00000001012�14552026002�021647� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_l_control.c: int64_t version of camd_control //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "camd_control.c" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_postorder.c�������������������������������������������������0000644�0001751�0000144�00000003341�14552026002�021704� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_postorder: post-order the assembly tree from CAMD //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* Perform a postordering (via depth-first search) of an assembly tree. */ #include "camd_internal.h" Int CAMD_postorder ( Int j, /* start at node j, a root of the assembly tree */ Int k, /* on input, next node is the kth node */ Int n, /* normal nodes 0 to n-1, place-holder node n */ Int head [], /* head of link list of children of each node */ Int next [], /* next[i] is the next child after i in link list */ Int post [], /* postordering, post [k] = p if p is the kth node */ Int stack [] /* recursion stack */ ) { int i, p, top = 0 ; stack [0] = j ; /* place j on the stack, maybe place-holder node n */ while (top >= 0) /* while (stack is not empty) */ { p = stack [top] ; /* p = top of stack */ i = head [p] ; /* i = youngest child of p */ if (i == -1) { top-- ; /* p has no unordered children left */ if (p != n) { /* node p is the kth postordered node. Do not postorder the * place-holder node n, which is the root of a subtree * containing all dense and empty nodes. */ post [k++] = p ; } } else { head [p] = next [i] ; /* remove i from children of p */ stack [++top] = i ; /* start dfs on child node i */ } } return (k) ; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_dump.c������������������������������������������������������0000644�0001751�0000144�00000012147�14552026002�020634� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_dump: debug routines for CAMD //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* Debugging routines for CAMD. Not used if NDEBUG is not defined at compile- * time (the default). See comments in camd_internal.h on how to enable * debugging. Not user-callable. */ #include "camd_internal.h" #ifndef NDEBUG /* This global variable is present only when debugging */ Int CAMD_debug = -999 ; /* default is no debug printing */ /* ========================================================================= */ /* === CAMD_debug_init ===================================================== */ /* ========================================================================= */ /* Sets the debug print level, by reading the file debug.camd (if it exists) */ void CAMD_debug_init ( char *s ) { FILE *f ; f = fopen ("debug.camd", "r") ; if (f == (FILE *) NULL) { CAMD_debug = -999 ; } else { fscanf (f, ID, &CAMD_debug) ; fclose (f) ; } if (CAMD_debug >= 0) { printf ("%s: CAMD_debug_init, D= "ID"\n", s, CAMD_debug) ; } } /* ========================================================================= */ /* === CAMD_dump =========================================================== */ /* ========================================================================= */ /* Dump CAMD's data structure, except for the hash buckets. This routine * cannot be called when the hash buckets are non-empty. */ void CAMD_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 BucketSet [ ], const Int C [ ], Int CurC ) { Int i, pe, elen, nv, len, e, p, k, j, deg, w, cnt, ilast ; if (CAMD_debug < 0) return ; ASSERT (pfree <= iwlen) ; CAMD_DEBUG3 (("\nCAMD dump, pfree: "ID"\n", pfree)) ; 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) { CAMD_DEBUG4 (("\nI "ID": nonprincipal: ", i)) ; ASSERT (elen == EMPTY) ; if (pe == FLIP(n)) { CAMD_DEBUG4 ((" dense node\n")) ; ASSERT (w == 1) ; } else { ASSERT (pe < EMPTY) ; CAMD_DEBUG4 ((" i "ID" -> parent "ID"\n", i, FLIP (Pe[i]))); } } else { CAMD_DEBUG4 (("\nI "ID": active principal supervariable:\n",i)); CAMD_DEBUG4 ((" nv(i): "ID" Flag: %d\n", nv, (nv < 0))) ; ASSERT (elen >= 0) ; ASSERT (nv > 0 && pe >= 0) ; p = pe ; CAMD_DEBUG4 ((" e/s: ")) ; if (elen == 0) CAMD_DEBUG4 ((" : ")) ; ASSERT (pe + len <= pfree) ; for (k = 0 ; k < len ; k++) { j = Iw [p] ; CAMD_DEBUG4 ((" "ID"", j)) ; ASSERT (j >= 0 && j < n) ; if (k == elen-1) CAMD_DEBUG4 ((" : ")) ; p++ ; } CAMD_DEBUG4 (("\n")) ; } } else { e = i ; if (w == 0) { CAMD_DEBUG4 (("\nE "ID": absorbed element: w "ID"\n", e, w)) ; ASSERT (nv > 0 && pe < 0) ; CAMD_DEBUG4 ((" e "ID" -> parent "ID"\n", e, FLIP (Pe [e]))) ; } else { CAMD_DEBUG4 (("\nE "ID": unabsorbed element: w "ID"\n", e, w)) ; ASSERT (nv > 0 && pe >= 0) ; p = pe ; CAMD_DEBUG4 ((" : ")) ; ASSERT (pe + len <= pfree) ; for (k = 0 ; k < len ; k++) { j = Iw [p] ; CAMD_DEBUG4 ((" "ID"", j)) ; ASSERT (j >= 0 && j < n) ; p++ ; } CAMD_DEBUG4 (("\n")) ; } } CAMD_DEBUG4 (("C[i] is :"ID"\n", (C == NULL) ? 0 : C [i])); } /* this routine cannot be called when the hash buckets are non-empty */ CAMD_DEBUG4 (("\nDegree lists:\n")) ; if (nel >= 0) { cnt = 0 ; for (deg = 0 ; deg < n ; deg++) { if (Head [deg] == EMPTY) continue ; ilast = EMPTY ; CAMD_DEBUG4 ((ID": \n", deg)) ; for (i = Head [deg] ; i != EMPTY ; i = Next [i]) { CAMD_DEBUG4 ((" "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 ; } CAMD_DEBUG4 (("\n")) ; } } CAMD_DEBUG4(("\nCurrent C[i] is "ID". current Buckets are:\n", CurC)) ; for (i = 0 ; i < n ; i++) { if ((C == NULL) ? 1 : (C [BucketSet [i]] <= CurC)) CAMD_DEBUG4((ID",",BucketSet [i])); } CAMD_DEBUG4 (("\n")) ; } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_defaults.c��������������������������������������������������0000644�0001751�0000144�00000002124�14552026002�021470� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_defaults: set defaults for CAMD //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* User-callable. Sets default control parameters for CAMD. See camd.h * for details. */ #include "camd_internal.h" /* ========================================================================= */ /* === CAMD defaults ======================================================= */ /* ========================================================================= */ void CAMD_defaults ( double Control [ ] ) { Int i ; if (Control != (double *) NULL) { for (i = 0 ; i < CAMD_CONTROL ; i++) { Control [i] = 0 ; } Control [CAMD_DENSE] = CAMD_DEFAULT_DENSE ; Control [CAMD_AGGRESSIVE] = CAMD_DEFAULT_AGGRESSIVE ; } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_l_dump.c����������������������������������������������������0000644�0001751�0000144�00000001001�14552026002�021132� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_l_dump.c: int64_t version of camd_dump //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "camd_dump.c" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_aat.c�������������������������������������������������������0000644�0001751�0000144�00000011211�14552026002�020423� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_aat: compute symmetry of A and nnz in each column of A+A' //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* CAMD_aat: compute the symmetry of the pattern of A, and count the number of * nonzeros each column of A+A' (excluding the diagonal). Assumes the input * matrix has no errors, with sorted columns and no duplicates * (CAMD_valid (n, n, Ap, Ai) must be CAMD_OK, but this condition is not * checked). */ #include "camd_internal.h" size_t CAMD_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 ; double sym ; size_t nzaat ; #ifndef NDEBUG CAMD_debug_init ("CAMD AAT") ; for (k = 0 ; k < n ; k++) Tp [k] = EMPTY ; ASSERT (CAMD_valid (n, n, Ap, Ai) == CAMD_OK) ; #endif if (Info != (double *) NULL) { /* clear the Info array, if it exists */ for (i = 0 ; i < CAMD_INFO ; i++) { Info [i] = EMPTY ; } Info [CAMD_STATUS] = CAMD_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] ; CAMD_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]++ ; CAMD_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]++ ; CAMD_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]++ ; CAMD_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 = (2 * (double) nzboth) / ((double) (nz - nzdiag)) ; } nzaat = 0 ; for (k = 0 ; k < n ; k++) { nzaat += Len [k] ; } CAMD_DEBUG1 (("CAMD nz in A+A', excluding diagonal (nzaat) = %g\n", (double) nzaat)) ; CAMD_DEBUG1 ((" nzboth: "ID" nz: "ID" nzdiag: "ID" symmetry: %g\n", nzboth, nz, nzdiag, sym)) ; if (Info != (double *) NULL) { Info [CAMD_STATUS] = CAMD_OK ; Info [CAMD_N] = n ; Info [CAMD_NZ] = nz ; Info [CAMD_SYMMETRY] = sym ; /* symmetry of pattern of A */ Info [CAMD_NZDIAG] = nzdiag ; /* nonzeros on diagonal of A */ Info [CAMD_NZ_A_PLUS_AT] = nzaat ; /* nonzeros in A+A' */ } return (nzaat) ; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_1.c���������������������������������������������������������0000644�0001751�0000144�00000013371�14552026002�020027� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_1: construct input matrix and then order with camd_2 //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* CAMD_1: Construct A+A' for a sparse matrix A and perform the CAMD ordering. * * The n-by-n sparse matrix A can be unsymmetric. It is stored in MATLAB-style * compressed-column form, with sorted row indices in each column, and no * duplicate entries. Diagonal entries may be present, but they are ignored. * Row indices of column j of A are stored in Ai [Ap [j] ... Ap [j+1]-1]. * Ap [0] must be zero, and nz = Ap [n] is the number of entries in A. The * size of the matrix, n, must be greater than or equal to zero. * * This routine must be preceded by a call to CAMD_aat, which computes the * number of entries in each row/column in A+A', excluding the diagonal. * Len [j], on input, is the number of entries in row/column j of A+A'. This * routine constructs the matrix A+A' and then calls CAMD_2. No error checking * is performed (this was done in CAMD_valid). */ #include "camd_internal.h" void CAMD_1 ( Int n, /* n > 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+2, * ideally slen = 1.2 * sum (Len) + 8n+2 */ Int S [ ], /* size slen workspace */ double Control [ ], /* input array of size CAMD_CONTROL */ double Info [ ], /* output array of size CAMD_INFO */ const Int C [ ] /* Constraint set of size n */ ) { Int i, j, k, p, pfree, iwlen, pj, p1, p2, pj2, *Iw, *Pe, *Nv, *Head, *Elen, *Degree, *s, *W, *Sp, *Tp, *BucketSet ; /* --------------------------------------------------------------------- */ /* construct the matrix for CAMD_2 */ /* --------------------------------------------------------------------- */ ASSERT (n > 0) ; iwlen = slen - (7*n+2) ; /* allocate 7*n+2 workspace from S */ s = S ; Pe = s ; s += n ; Nv = s ; s += n ; Head = s ; s += n+1 ; /* NOTE: was size n in AMD; size n+1 in CAMD */ Elen = s ; s += n ; Degree = s ; s += n ; W = s ; s += n+1 ; /* NOTE: was size n in AMD; size n+1 in CAMD */ BucketSet = s ; s += n ; Iw = s ; s += iwlen ; ASSERT (CAMD_valid (n, n, Ap, Ai) == CAMD_OK) ; ASSERT (CAMD_cvalid (n, C)) ; /* 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 CAMD_2. CAMD_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++) { CAMD_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 */ /* --------------------------------------------------------------------- */ CAMD_2 (n, Pe, Iw, Len, iwlen, pfree, Nv, Pinv, P, Head, Elen, Degree, W, Control, Info, C, BucketSet) ; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_l_info.c����������������������������������������������������0000644�0001751�0000144�00000001001�14552026002�021120� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_l_info.c: int64_t version of camd_info //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "camd_info.c" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_valid.c�����������������������������������������������������0000644�0001751�0000144�00000006104�14552026002�020762� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_valid: check if a matrix is valid for CAMD //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* 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. * Ai [0 ... nz-1] must be in the range 0 to n_row-1. * * If any of the above conditions hold, CAMD_INVALID is returned. If the * following condition holds, CAMD_OK_BUT_JUMBLED is returned (a warning, * not an error): * * row indices in Ai [Ap [j] ... Ap [j+1]-1] are not sorted in ascending * order, and/or duplicate entries exist. * * Otherwise, CAMD_OK is returned. */ #include "camd_internal.h" int CAMD_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 ; int result = CAMD_OK ; if (n_row < 0 || n_col < 0 || Ap == NULL || Ai == NULL) { return (CAMD_INVALID) ; } nz = Ap [n_col] ; if (Ap [0] != 0 || nz < 0) { /* column pointers must start at Ap [0] = 0, and Ap [n] must be >= 0 */ CAMD_DEBUG0 (("column 0 pointer bad or nz < 0\n")) ; return (CAMD_INVALID) ; } for (j = 0 ; j < n_col ; j++) { p1 = Ap [j] ; p2 = Ap [j+1] ; CAMD_DEBUG2 (("\nColumn: "ID" p1: "ID" p2: "ID"\n", j, p1, p2)) ; if (p1 > p2) { /* column pointers must be ascending */ CAMD_DEBUG0 (("column "ID" pointer bad\n", j)) ; return (CAMD_INVALID) ; } ilast = EMPTY ; for (p = p1 ; p < p2 ; p++) { i = Ai [p] ; CAMD_DEBUG3 (("row: "ID"\n", i)) ; if (i < 0 || i >= n_row) { /* row index out of range */ CAMD_DEBUG0 (("index out of range, col "ID" row "ID"\n", j, i)); return (CAMD_INVALID) ; } if (i <= ilast) { /* row index unsorted, or duplicate entry present */ CAMD_DEBUG1 (("index unsorted/dupl col "ID" row "ID"\n", j, i)); result = CAMD_OK_BUT_JUMBLED ; } ilast = i ; } } return (result) ; } int CAMD_cvalid /* return TRUE if the Constraint set is valid, * FALSE otherwise */ ( /* inputs, not modified on output: */ Int n, /* the length of constraint set */ const Int C [ ] /* constraint set */ ) { Int i ; if (C != NULL) { for (i = 0 ; i < n ; i++) { if (C [i] < 0 || C [i] > n - 1) { CAMD_DEBUG0 (("C["ID"] = "ID" invalid\n", i, C [i])) ; return (FALSE) ; } } } return (TRUE) ; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_order.c�����������������������������������������������������0000644�0001751�0000144�00000013416�14552026002�021002� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_order: user-callable CAMD ordering method //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* User-callable CAMD minimum degree ordering routine. See camd.h for * documentation. */ #include "camd_internal.h" /* ========================================================================= */ /* === CAMD_order ========================================================== */ /* ========================================================================= */ int CAMD_order ( Int n, const Int Ap [ ], const Int Ai [ ], Int P [ ], double Control [ ], double Info [ ], const Int C [ ] ) { Int *Len, *S, nz, i, *Pinv, info, status, *Rp, *Ri, *Cp, *Ci, ok ; size_t nzaat, slen ; double mem = 0 ; #ifndef NDEBUG CAMD_debug_init ("camd") ; #endif /* clear the Info array, if it exists */ info = Info != (double *) NULL ; if (info) { for (i = 0 ; i < CAMD_INFO ; i++) { Info [i] = EMPTY ; } Info [CAMD_N] = n ; Info [CAMD_STATUS] = CAMD_OK ; } /* make sure inputs exist and n is >= 0 */ if (Ai == (Int *) NULL || Ap == (Int *) NULL || P == (Int *) NULL || n < 0) { if (info) Info [CAMD_STATUS] = CAMD_INVALID ; return (CAMD_INVALID) ; /* arguments are invalid */ } if (n == 0) { return (CAMD_OK) ; /* n is 0 so there's nothing to do */ } nz = Ap [n] ; if (info) { Info [CAMD_NZ] = nz ; } if (nz < 0) { if (info) Info [CAMD_STATUS] = CAMD_INVALID ; return (CAMD_INVALID) ; } /* check if n or nz will cause integer overflow */ if (((size_t) n) >= Int_MAX / sizeof (Int) || ((size_t) nz) >= Int_MAX / sizeof (Int)) { if (info) Info [CAMD_STATUS] = CAMD_OUT_OF_MEMORY ; return (CAMD_OUT_OF_MEMORY) ; /* problem too large */ } /* check the input matrix: CAMD_OK, CAMD_INVALID, or CAMD_OK_BUT_JUMBLED */ status = CAMD_valid (n, n, Ap, Ai) ; if (status == CAMD_INVALID) { if (info) Info [CAMD_STATUS] = CAMD_INVALID ; return (CAMD_INVALID) ; /* matrix is invalid */ } /* allocate two size-n integer workspaces */ Len = SuiteSparse_malloc (n, sizeof (Int)) ; Pinv = SuiteSparse_malloc (n, sizeof (Int)) ; mem += n ; mem += n ; if (!Len || !Pinv) { /* :: out of memory :: */ SuiteSparse_free (Len) ; SuiteSparse_free (Pinv) ; if (info) Info [CAMD_STATUS] = CAMD_OUT_OF_MEMORY ; return (CAMD_OUT_OF_MEMORY) ; } if (status == CAMD_OK_BUT_JUMBLED) { /* sort the input matrix and remove duplicate entries */ CAMD_DEBUG1 (("Matrix is jumbled\n")) ; Rp = SuiteSparse_malloc (n+1, sizeof (Int)) ; Ri = SuiteSparse_malloc (nz, sizeof (Int)) ; mem += (n+1) ; mem += MAX (nz,1) ; if (!Rp || !Ri) { /* :: out of memory :: */ SuiteSparse_free (Rp) ; SuiteSparse_free (Ri) ; SuiteSparse_free (Len) ; SuiteSparse_free (Pinv) ; if (info) Info [CAMD_STATUS] = CAMD_OUT_OF_MEMORY ; return (CAMD_OUT_OF_MEMORY) ; } /* use Len and Pinv as workspace to create R = A' */ CAMD_preprocess (n, Ap, Ai, Rp, Ri, Len, Pinv) ; Cp = Rp ; Ci = Ri ; } else { /* order the input matrix as-is. No need to compute R = A' first */ Rp = NULL ; Ri = NULL ; Cp = (Int *) Ap ; Ci = (Int *) Ai ; } /* --------------------------------------------------------------------- */ /* determine the symmetry and count off-diagonal nonzeros in A+A' */ /* --------------------------------------------------------------------- */ nzaat = CAMD_aat (n, Cp, Ci, Len, P, Info) ; CAMD_DEBUG1 (("nzaat: %g\n", (double) nzaat)) ; ASSERT ((MAX (nz-n, 0) <= nzaat) && (nzaat <= 2 * (size_t) nz)) ; /* --------------------------------------------------------------------- */ /* allocate workspace for matrix, elbow room, and 7 size-n vectors */ /* --------------------------------------------------------------------- */ S = NULL ; slen = nzaat ; /* space for matrix */ ok = ((slen + nzaat/5) >= slen) ; /* check for size_t overflow */ slen += nzaat/5 ; /* add elbow room */ for (i = 0 ; ok && i < 8 ; i++) { ok = ((slen + n+1) > slen) ; /* check for size_t overflow */ slen += (n+1) ; /* size-n elbow room, 7 size-(n+1) workspace */ } mem += slen ; ok = ok && (slen < SIZE_T_MAX / sizeof (Int)) ; /* check for overflow */ if (ok) { S = SuiteSparse_malloc (slen, sizeof (Int)) ; } CAMD_DEBUG1 (("slen %g\n", (double) slen)) ; if (!S) { /* :: out of memory :: (or problem too large) */ SuiteSparse_free (Rp) ; SuiteSparse_free (Ri) ; SuiteSparse_free (Len) ; SuiteSparse_free (Pinv) ; if (info) Info [CAMD_STATUS] = CAMD_OUT_OF_MEMORY ; return (CAMD_OUT_OF_MEMORY) ; } if (info) { /* memory usage, in bytes. */ Info [CAMD_MEMORY] = mem * sizeof (Int) ; } /* --------------------------------------------------------------------- */ /* order the matrix */ /* --------------------------------------------------------------------- */ CAMD_1 (n, Cp, Ci, P, Pinv, Len, slen, S, Control, Info, C) ; /* --------------------------------------------------------------------- */ /* free the workspace */ /* --------------------------------------------------------------------- */ SuiteSparse_free (Rp) ; SuiteSparse_free (Ri) ; SuiteSparse_free (Len) ; SuiteSparse_free (Pinv) ; SuiteSparse_free (S) ; if (info) Info [CAMD_STATUS] = status ; return (status) ; /* successful ordering */ } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_l_valid.c���������������������������������������������������0000644�0001751�0000144�00000001004�14552026002�021267� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_l_valid.c: int64_t version of camd_valid //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "camd_valid.c" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_l_preprocess.c����������������������������������������������0000644�0001751�0000144�00000001023�14552026002�022356� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_l_preprocess.c: int64_t version of camd_preprocess //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "camd_preprocess.c" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_l_aat.c�����������������������������������������������������0000644�0001751�0000144�00000000776�14552026002�020754� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_l_aat.c: int64_t version of camd_aat //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "camd_aat.c" ��Matrix/src/SuiteSparse/CAMD/Source/camd_l_defaults.c������������������������������������������������0000644�0001751�0000144�00000001015�14552026002�022001� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_l_defaults.c: int64_t version of camd_defaults //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "camd_defaults.c" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_l_order.c���������������������������������������������������0000644�0001751�0000144�00000001004�14552026002�021303� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_l_order.c: int64_t version of camd_order //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "camd_order.c" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_l2.c��������������������������������������������������������0000644�0001751�0000144�00000000767�14552026002�020211� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_l2.c: int64_t version of camd_2 //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "camd_2.c" ���������Matrix/src/SuiteSparse/CAMD/Source/camd_l1.c��������������������������������������������������������0000644�0001751�0000144�00000000767�14552026002�020210� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_l1.c: int64_t version of camd_1 //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "camd_1.c" ���������Matrix/src/SuiteSparse/CAMD/Source/camd_control.c���������������������������������������������������0000644�0001751�0000144�00000003324�14552026002�021344� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_control: print control parameters for CAMD //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* User-callable. Prints the control parameters for CAMD. See camd.h * for details. If the Control array is not present, the defaults are * printed instead. */ #include "camd_internal.h" void CAMD_control ( double Control [ ] ) { double alpha ; Int aggressive ; if (Control != (double *) NULL) { alpha = Control [CAMD_DENSE] ; aggressive = Control [CAMD_AGGRESSIVE] != 0 ; } else { alpha = CAMD_DEFAULT_DENSE ; aggressive = CAMD_DEFAULT_AGGRESSIVE ; } SUITESPARSE_PRINTF (( "\ncamd version %d.%d.%d, %s: approximate minimum degree ordering:\n" " dense row parameter: %g\n", CAMD_MAIN_VERSION, CAMD_SUB_VERSION, CAMD_SUBSUB_VERSION, CAMD_DATE, alpha)) ; if (alpha < 0) { SUITESPARSE_PRINTF ((" no rows treated as dense\n")) ; } else { SUITESPARSE_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) { SUITESPARSE_PRINTF ((" aggressive absorption: yes\n")) ; } else { SUITESPARSE_PRINTF ((" aggressive absorption: no\n")) ; } SUITESPARSE_PRINTF ((" size of CAMD integer: %d\n\n", sizeof (Int))) ; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_info.c������������������������������������������������������0000644�0001751�0000144�00000010123�14552026002�020612� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_info: print output statistics for CAMD //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* User-callable. Prints the output statistics for CAMD. See camd.h * for details. If the Info array is not present, nothing is printed. */ #include "camd_internal.h" #define PRI(format,x) { if (x >= 0) { SUITESPARSE_PRINTF ((format, x)) ; }} void CAMD_info ( double Info [ ] ) { double n, ndiv, nmultsubs_ldl, nmultsubs_lu, lnz, lnzd ; SUITESPARSE_PRINTF (("\nCAMD version %d.%d.%d, %s, results:\n", CAMD_MAIN_VERSION, CAMD_SUB_VERSION, CAMD_SUBSUB_VERSION, CAMD_DATE)) ; if (!Info) { return ; } n = Info [CAMD_N] ; ndiv = Info [CAMD_NDIV] ; nmultsubs_ldl = Info [CAMD_NMULTSUBS_LDL] ; nmultsubs_lu = Info [CAMD_NMULTSUBS_LU] ; lnz = Info [CAMD_LNZ] ; lnzd = (n >= 0 && lnz >= 0) ? (n + lnz) : (-1) ; /* CAMD return status */ SUITESPARSE_PRINTF ((" status: ")) ; if (Info [CAMD_STATUS] == CAMD_OK) { SUITESPARSE_PRINTF (("OK\n")) ; } else if (Info [CAMD_STATUS] == CAMD_OUT_OF_MEMORY) { SUITESPARSE_PRINTF (("out of memory\n")) ; } else if (Info [CAMD_STATUS] == CAMD_INVALID) { SUITESPARSE_PRINTF (("invalid matrix\n")) ; } else if (Info [CAMD_STATUS] == CAMD_OK_BUT_JUMBLED) { SUITESPARSE_PRINTF (("OK, but jumbled\n")) ; } else { SUITESPARSE_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 [CAMD_NZ]) ; PRI (" symmetry of A: %.4f\n", Info [CAMD_SYMMETRY]) ; PRI (" number of nonzeros on diagonal: %.20g\n", Info [CAMD_NZDIAG]) ; PRI (" nonzeros in pattern of A+A' (excl. diagonal): %.20g\n", Info [CAMD_NZ_A_PLUS_AT]) ; PRI (" # dense rows/columns of A+A': %.20g\n", Info [CAMD_NDENSE]) ; /* statistics about CAMD's behavior */ PRI (" memory used, in bytes: %.20g\n", Info [CAMD_MEMORY]) ; PRI (" # of memory compactions: %.20g\n", Info [CAMD_NCMPA]) ; /* statistics about the ordering quality */ SUITESPARSE_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 [CAMD_DMAX]) ; /* total flop counts for various factorizations */ if (n >= 0 && ndiv >= 0 && nmultsubs_ldl >= 0 && nmultsubs_lu >= 0) { SUITESPARSE_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)) ; } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_version.c���������������������������������������������������0000644�0001751�0000144�00000001211�14552026002�021342� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_version: return CAMD version //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2023, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #include "camd_internal.h" void camd_version (int version [3]) { version [0] = CAMD_MAIN_VERSION ; version [1] = CAMD_SUB_VERSION ; version [2] = CAMD_SUBSUB_VERSION ; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_2.c���������������������������������������������������������0000644�0001751�0000144�00000211432�14552026002�020026� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_2: CAMD ordering //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* CAMD_2: performs the CAMD ordering on a symmetric sparse matrix A, followed * by a postordering (via depth-first search) of the assembly tree using the * CAMD_postorder routine. */ /* ========================================================================= */ /* === Macros and definitions ============================================== */ /* ========================================================================= */ /* True if node i is in the current Constraint Set */ #define IsInCurrentSet(C,i,curC) ((C == NULL) ? 1 : (C [i] == curC)) /* True if i and j are in the same Constraint Set */ #define InSameConstraintSet(C,i,j) ((C == NULL) ? 1 : (C [i] == C [j])) #include "camd_internal.h" /* ========================================================================= */ /* === clear_flag ========================================================== */ /* ========================================================================= */ static Int clear_flag (Int wflg, Int wbig, Int W [ ], Int n) { Int x ; if (wflg < 2 || 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 */ return (wflg) ; } /* ========================================================================= */ /* === CAMD_2 ============================================================== */ /* ========================================================================= */ void CAMD_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 or size-n+1 workspaces, not defined on input: */ Int Nv [ ], /* size n, the size of each supernode on output */ Int Next [ ], /* size n, the output inverse permutation */ Int Last [ ], /* size n, the output permutation */ Int Head [ ], /* size n+1 (Note: it was size n in AMD) */ Int Elen [ ], /* size n, the size columns of L for each supernode */ Int Degree [ ], /* size n */ Int W [ ], /* size n+1 (Note: it was size n in AMD) */ /* control parameters and output statistics */ double Control [ ], /* array of size CAMD_CONTROL */ double Info [ ], /* array of size CAMD_INFO */ /* input, not modified: */ const Int C [ ], /* size n, C [i] is the constraint set of node i */ /* size-n workspace, not defined on input or output: */ Int BucketSet [ ] /* size n */ ) { /* * 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 camd_order or camd_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. * * AMD Authors, and Copyright (C) 2004 by: * Timothy A. Davis, Patrick Amestoy, Iain S. Duff, John K. Reid. * Modifications for CAMD authored by Davis and Yanqing "Morris" Chen. * * 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 CAMD, 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. * Ordering constraints were added with support from Sandia National Labs (DOE). * ---------------------------------------------------------------------------- * 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 (camd_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 CAMD_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 CAMD_CONTROL containing input parameters * that affect how the ordering is computed. If NULL, then default * settings are used. * * Control [CAMD_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 [CAMD_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 [CAMD_DENSE] to a negative number, or to a * number larger than sqrt (n). The default value of Control [CAMD_DENSE] * is CAMD_DEFAULT_DENSE, which is defined in camd.h as 10. * * Control [CAMD_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). * * C: defines the ordering constraints. s = C [j] gives the constraint set s * that contains the row/column j (Restriction: 0 <= s < n). * In the output row permutation, all rows in set 0 appear first, followed * by all rows in set 1, and so on. If NULL, all rows are treated as if * they were in a single constraint set, and you will obtain a similar * ordering as AMD (slightly different because of the different * postordering used). * ---------------------------------------------------------------------------- * 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 camd_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 or empty variable i: if i is "dense" or empty (with zero degree), * then Pe [i] = FLIP (n). * * 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 CAMD_INFO. If present, (that is, not NULL), * then statistics about the ordering are returned in the Info array. * See camd.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. Len also works as a temporary * workspace in post ordering with dense nodes detected. * * 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. * * Nv also works as a temporary workspace in initializing the BucketSet * array. * * 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. * * Head also workes as a temporary workspace in post ordering with dense * nodes detected. * * 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). * * BucketSet: An integer array of size n. * During execution it stores the rows that sorted in the ascending order * based on C []. For instance: if C[]={0,2,1,0,1,0,2,1}, the * Bucketset will be {0,3,5,2,4,7,1,6}. * The elements in Bucketset are then modified, to maintain the order of * roots (Pe[i]=-1) in each Constraint Set. * ---------------------------------------------------------------------------- * LOCAL INTEGERS: * ---------------------------------------------------------------------------- */ Int deg, degme, dext, lemax, e, elenme, eln, i, ilast, inext, j, jlast, k, knt1, knt2, knt3, lenj, ln, me, mindeg, nel, nleft, nvi, nvj, nvpiv, slenme, wbig, we, wflg, wnvi, ok, ndense, ncmpa, nnull, dense, aggressive ; UInt 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 * 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 * nnull: number of empty 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 */ Int curC, pBucket, pBucket2, degreeListCounter, c, cmax = 0, ndense_or_null ; Int *Bucket, *Perm ; /* * curC: the current Constraint Set being ordered * pBucket: pointer into Bucketset[] when building the degreelist for each * Constraint Set * pBucket2: pointer into Bucketset[] to tell the post ordering where to stop * degreeListCounter: number of elements remaining in the * degreelist of current Constraint Set * Bucket: used to construct BucketSet * Perm: permutation */ /* ========================================================================= */ /* INITIALIZATIONS */ /* ========================================================================= */ /* Note that this restriction on iwlen is slightly more restrictive than * what is actually required in CAMD_2. CAMD_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 ; mindeg = 0 ; ncmpa = 0 ; nel = 0 ; lemax = 0 ; curC = 0 ; /* camd work initBucketSet using CountingSort * BucketSort the index Array BucketSet According to Contrains Array C, Using * Nv[] as a temporary workspace * Input: Index Array from 0 to n.(index of rows) * Output: Index Array sorted according to C. worked as a bucket set. * * All the value in C must be 0 <= C[i] <= n-1 * For instance: if C[]={0,2,1,0,1,0,2,1}, the output Bucketset should be * {0,3,5,2,4,7,1,6} */ /* CountingSort BucketSet[] based on C[], It is O(n) linear time */ if (C == NULL) { /* store everything in bucket without changing order */ for (j = 0 ; j < n ; j++) { BucketSet [j] = j ; } } else { Bucket = Nv ; for (i = 0 ; i < n ; i++) { Bucket [i] = 0 ; } cmax = C [0] ; for (j = 0 ; j < n ; j++) { c = C [j] ; CAMD_DEBUG1 (("C [%d] = "ID"\n", j, c)) ; Bucket [c]++ ; cmax = MAX (cmax, c) ; ASSERT (c >= 0 && c < n) ; } CAMD_DEBUG1 (("Max constraint set: "ID"\n", cmax)) ; for (i = 1 ; i < n ; i++) { Bucket [i] += Bucket [i-1] ; } for (j = n-1 ; j >= 0 ; j--) { BucketSet [--Bucket [C [j]]] = j ; } #ifndef NDEBUG CAMD_DEBUG3 (("\nConstraint Set "ID" :", C [BucketSet [0]])); for (i = 0 ; i < n ; i++) { CAMD_DEBUG3 ((ID" ", BucketSet [i])) ; if (i == n-1) { CAMD_DEBUG3 (("\n")) ; break ; } if (C [BucketSet [i+1]] != C [BucketSet [i]]) { CAMD_DEBUG3 (("\nConstraint Set "ID" :", C [BucketSet [i+1]])) ; } } #endif } /* get control parameters */ if (Control != (double *) NULL) { alpha = Control [CAMD_DENSE] ; aggressive = (Control [CAMD_AGGRESSIVE] != 0) ; } else { alpha = CAMD_DEFAULT_DENSE ; aggressive = CAMD_DEFAULT_AGGRESSIVE ; } /* Note: if alpha is NaN, this is undefined: */ if (alpha < 0) { /* only remove completely dense rows/columns */ dense = n-2 ; } else { dense = alpha * sqrt ((double) n) ; } dense = MAX (16, dense) ; dense = MIN (n, dense) ; CAMD_DEBUG1 (("\n\nCAMD (debug), alpha %g, aggr. "ID"\n", alpha, aggressive)) ; for (i = 0 ; i < n ; i++) { Last [i] = EMPTY ; Head [i] = EMPTY ; Next [i] = EMPTY ; /* if separate Hhead array is used for hash buckets: * Hhead [i] = EMPTY ; */ Nv [i] = 1 ; W [i] = 1 ; Elen [i] = 0 ; Degree [i] = Len [i] ; } Head [n] = EMPTY ; /* initialize wflg */ wbig = Int_MAX - n ; wflg = clear_flag (0, wbig, W, n) ; /* --------------------------------------------------------------------- */ /* eliminate dense and empty rows */ /* --------------------------------------------------------------------- */ ndense = 0 ; nnull = 0 ; for (j = 0 ; j < n ; j++) { i = BucketSet [j] ; deg = Degree [i] ; ASSERT (deg >= 0 && deg < n) ; if (deg > dense || deg == 0) { /* ------------------------------------------------------------- * Dense or empty variables are treated as non-principal variables * represented by node n. That is, i is absorbed into n, just like * j is absorbed into i in supervariable detection (see "found it!" * comment, below). * ------------------------------------------------------------- */ if (deg > dense) { CAMD_DEBUG1 (("Dense node "ID" degree "ID" bucket "ID"\n", i, deg, j)) ; ndense++ ; } else { CAMD_DEBUG1 (("Empty node "ID" degree "ID" bucket "ID"\n", i, deg, j)) ; nnull++ ; } Pe [i] = FLIP (n) ; Nv [i] = 0 ; /* do not postorder this node */ Elen [i] = EMPTY ; nel++ ; } } ndense_or_null = ndense + nnull ; pBucket = 0 ; degreeListCounter = 0 ; pBucket2 = 0 ; /* ========================================================================= */ /* WHILE (selecting pivots) DO */ /* ========================================================================= */ while (nel < n) { /* ------------------------------------------------------------------ */ /* if empty, fill the degree list with next non-empty constraint set */ /* ------------------------------------------------------------------ */ while (degreeListCounter == 0) { mindeg = n ; /* determine the new constraint set */ curC = (C == NULL) ? 0 : C [BucketSet [pBucket]] ; for ( ; pBucket < n ; pBucket++) { /* add i to the degree list, unless it's dead or not in curC */ i = BucketSet [pBucket] ; if (!IsInCurrentSet (C, i, curC)) break ; deg = Degree [i] ; ASSERT (deg >= 0 && deg < n) ; if (Pe [i] >= 0) { /* ------------------------------------------------------ * 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 ; degreeListCounter++ ; Last [i] = EMPTY ; mindeg = MIN (mindeg, deg) ; } } } #ifndef NDEBUG CAMD_DEBUG1 (("\n======Nel "ID"\n", nel)) ; if (CAMD_debug >= 2) { CAMD_dump (n, Pe, Iw, Len, iwlen, pfree, Nv, Next, Last, Head, Elen, Degree, W, nel, BucketSet, C, curC) ; } #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) ; CAMD_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 ; degreeListCounter-- ; /* ----------------------------------------------------------------- */ /* 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 ; CAMD_DEBUG1 (("nvpiv is initially "ID"\n", 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. */ /* ----------------------------------------------------- */ if (IsInCurrentSet (C, i, curC)) { 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 ; } degreeListCounter-- ; } } } } 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 ; CAMD_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] ; CAMD_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] ; CAMD_DEBUG2 ((": "ID" "ID" "ID" "ID"\n", i, Elen [i], Nv [i], wflg)) ; if (nvi > 0) { /* ------------------------------------------------- */ /* compress Iw, if necessary */ /* ------------------------------------------------- */ if (pfree >= iwlen) { CAMD_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) { CAMD_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 ; CAMD_DEBUG2 ((" s: "ID" nv "ID"\n", i, Nv [i])); /* ------------------------------------------------- */ /* remove variable i from degree link list */ /* ------------------------------------------------- */ if (IsInCurrentSet (C, i, curC)) { 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 ; } degreeListCounter-- ; } } } if (e != me) { if (IsInCurrentSet (C, e, curC)) { /* absorb element here if in same bucket */ /* set tree pointer and flag to indicate element e is * absorbed into new element me (the parent of e is me) */ CAMD_DEBUG1 ((" Element "ID" => "ID"\n", e, me)) ; Pe [e] = FLIP (me) ; W [e] = 0 ; } else { /* make element a root; kill it if not in same bucket */ CAMD_DEBUG1 (("2 Element "ID" => "ID"\n", e, me)) ; Pe [e] = EMPTY ; 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 CAMD_DEBUG2 (("New element structure: length= "ID"\n", pme2-pme1+1)) ; for (pme = pme1 ; pme <= pme2 ; pme++) CAMD_DEBUG3 ((" "ID"", Iw[pme])); CAMD_DEBUG3 (("\n")) ; #endif /* ----------------------------------------------------------------- */ /* make sure that wflg is not too large. */ /* ----------------------------------------------------------------- */ /* With the current value of wflg, wflg+n must not cause integer * overflow */ wflg = clear_flag (wflg, wbig, W, n) ; /* ========================================================================= */ /* 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] + Len [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. * ----------------------------------------------------------------- */ CAMD_DEBUG2 (("me: ")) ; for (pme = pme1 ; pme <= pme2 ; pme++) { i = Iw [pme] ; ASSERT (i >= 0 && i < n) ; eln = Elen [i] ; CAMD_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] ; CAMD_DEBUG4 ((" e "ID" we "ID" ", e, we)) ; if (we >= wflg) { /* unabsorbed element e has been seen in this loop */ CAMD_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 */ CAMD_DEBUG4 ((" unabsorbed")) ; we = Degree [e] + wnvi ; } CAMD_DEBUG4 (("\n")) ; W [e] = we ; } } } CAMD_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) ; CAMD_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 ; CAMD_DEBUG4 ((" e: "ID" hash = "ID"\n",e,hash)) ; } else { if (IsInCurrentSet (C, e, curC)) { /* external degree of e is zero and if * C[e] = curC; absorb e into me */ CAMD_DEBUG1 ((" Element "ID" =>"ID" (aggr)\n", e, me)) ; ASSERT (dext == 0) ; Pe [e] = FLIP (me) ; W [e] = 0 ; } else { /* make element a root; kill it if not in same * bucket */ CAMD_DEBUG1 (("2 Element "ID" =>"ID" (aggr)\n", e, me)) ; ASSERT (dext == 0) ; Pe [e] = EMPTY ; 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 ; CAMD_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 CAMD 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 ; CAMD_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 && IsInCurrentSet (C, i, curC)) { /* --------------------------------------------------------- */ /* 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 CAMD'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. */ CAMD_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 separate Hhead array is used: * Next [i] = Hhead [hash] ; Hhead [hash] = i ; */ CAMD_DEBUG4 ((" s: "ID" hash "ID" \n", i, hash)) ; 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 ; wflg = clear_flag (wflg, wbig, W, n) ; /* at this point, W [0..n-1] < wflg holds */ /* ========================================================================= */ /* SUPERVARIABLE DETECTION */ /* ========================================================================= */ CAMD_DEBUG1 (("Detecting supervariables:\n")) ; for (pme = pme1 ; pme <= pme2 ; pme++) { i = Iw [pme] ; ASSERT (i >= 0 && i < n) ; CAMD_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 * --------------------------------------------------------- */ CAMD_DEBUG2 (("Last: "ID"\n", Last [i])) ; /* 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 separate Hhead array is used: * i = Hhead [hash] ; Hhead [hash] = EMPTY ; */ ASSERT (i >= EMPTY && i < n) ; CAMD_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 */ /* ------------------------------------------------- */ CAMD_DEBUG3 (("compare i "ID" and j "ID"\n", i,j)) ; /* check if i and j have the same Len and Elen */ /* and are in the same bucket */ ASSERT (Len [j] >= 0 && Elen [j] >= 0) ; ASSERT (Pe [j] >= 0 && Pe [j] < iwlen) ; ok = (Len [j] == ln) && (Elen [j] == eln) ; ok = ok && InSameConstraintSet (C,i,j) ; /* skip 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 */ /* --------------------------------------------- */ CAMD_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) ; } } } CAMD_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] ; CAMD_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 (deg >= 0 && deg < n) ; /* --------------------------------------------------------- */ /* place the supervariable at the head of the degree list */ /* --------------------------------------------------------- */ if (IsInCurrentSet (C, i, curC)) { inext = Head [deg] ; ASSERT (inext >= EMPTY && inext < n) ; if (inext != EMPTY) Last [inext] = i ; Next [i] = inext ; Last [i] = EMPTY ; Head [deg] = i ; degreeListCounter++ ; } /* --------------------------------------------------------- */ /* 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 ; } } CAMD_DEBUG2 (("restore done\n")) ; /* ========================================================================= */ /* FINALIZE THE NEW ELEMENT */ /* ========================================================================= */ CAMD_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 ; } /* Store the element back into BucketSet. This is the way to maintain * the order of roots (Pe[i]=-1) in each Constraint Set. */ BucketSet [pBucket2++] = me ; /* 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 CAMD_DEBUG2 (("finalize done nel "ID" n "ID"\n ::::\n", nel, n)) ; for (pme = Pe [me] ; pme <= Pe [me] + Len [me] - 1 ; pme++) { CAMD_DEBUG3 ((" "ID"", Iw [pme])) ; } CAMD_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 [CAMD_LNZ] = lnz ; /* number of divide ops for LU and LDL' */ Info [CAMD_NDIV] = ndiv ; /* number of multiply-subtract pairs for LDL' */ Info [CAMD_NMULTSUBS_LDL] = nms_ldl ; /* number of multiply-subtract pairs for LU */ Info [CAMD_NMULTSUBS_LU] = nms_lu ; /* number of "dense" rows/columns */ Info [CAMD_NDENSE] = ndense ; /* largest front is dmax-by-dmax */ Info [CAMD_DMAX] = dmax ; /* number of garbage collections in CAMD */ Info [CAMD_NCMPA] = ncmpa ; /* successful ordering */ Info [CAMD_STATUS] = CAMD_OK ; } /* ========================================================================= */ /* POST-ORDERING */ /* ========================================================================= */ /* ------------------------------------------------------------------------- * 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 and empty variables are non-principal and unordered. They are * all represented by the fictitious node n (that is, Pe [i] = FLIP (n) * and Elen [i] = EMPTY if i is a dense or empty node). * * 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. * * BucketSet: BucketSet [0.....pBucket2] holds all * the elements that removed during the elimination, in eliminated order. * * * Contents no longer needed: * W, Iw, Len, Degree, Head, Next, Last. * * The matrix itself has been destroyed. * * n: the size of the matrix. * ndense: the number of "dense" nodes. * nnull: the number of empty nodes (zero degree) * No other scalars needed (pfree, iwlen, etc.) * ------------------------------------------------------------------------- */ /* restore Pe */ for (i = 0 ; i < n ; i++) { Pe [i] = FLIP (Pe [i]) ; } /* restore Elen, for output information only */ for (i = 0 ; i < n ; i++) { Elen [i] = FLIP (Elen [i]) ; } /* Now, Pe [j] is the parent of j, or EMPTY if j is a root. * Pe [j] = n if j is a dense/empty node */ /* place all variables in the list of children of their parents */ for (j = n-1 ; j >= 0 ; j--) { if (Nv [j] > 0) continue ; /* skip if j is an element */ ASSERT (Pe [j] >= 0 && Pe [j] <= n) ; Next [j] = Head [Pe [j]] ; /* place j in list of its parent */ Head [Pe [j]] = j ; } /* place all elements in the list of children of their parents */ for (e = n-1 ; e >= 0 ; e--) { if (Nv [e] <= 0) continue ; /* skip if e is a variable */ if (Pe [e] == EMPTY) continue ; /* skip if e is a root */ Next [e] = Head [Pe [e]] ; /* place e in list of its parent */ Head [Pe [e]] = e ; } /* determine where to put the postordering permutation */ if (C != NULL && ndense_or_null > 0) { /* Perm needs to be computed in a temporary workspace, and then * transformed and copied into the output permutation, in Last */ Perm = Degree ; } else { /* the postorder computes the permutation directly, in Last */ Perm = Last ; } /* postorder the elements and their descendants (both elements and * variables), but not (yet) the dense/empty nodes */ for (k = 0 , i = 0 ; i < pBucket2 ; i++) { j = BucketSet [i] ; ASSERT (j >= 0 && j < n) ; if (Pe [j] == EMPTY) { k = CAMD_postorder (j, k, n, Head, Next, Perm, W) ; } } /* Perm [0..k-1] now contains a list of the nonempty/nondense nodes, * ordered via minimum degree and following the constraints. */ CAMD_DEBUG1 (("before dense/empty, k = "ID"\n", k)) ; fflush (stdout) ; ASSERT (k + ndense_or_null == n) ; if (ndense_or_null > 0) { if (C == NULL) { /* postorder the dense/empty nodes (the parent of all these is n) */ CAMD_postorder (n, k, n, Head, Next, Perm, W) ; } else { /* dense (or empty) nodes exist, AND C also exists. The dense/empty * nodes are a link list whose head is Head[n], and Next[i] gives the * next node after i in the list. They need to be sorted by their * constraints, and then merged with Perm [0..k-1].*/ /* count how many dense/empty nodes are in each constraint set */ Bucket = W ; /* use W as workspace (it has size n+1) */ /* count the number of dense/empty nodes in each constraint set */ for (c = 0 ; c <= cmax ; c++) { Bucket [c] = 0 ; } i = 0 ; for (j = Head [n] ; j != EMPTY ; j = Next [j]) { CAMD_DEBUG1 (("Dense/empty node: "ID" : "ID" "ID"\n", j, Pe [j], Elen [j])) ; fflush (stdout) ; ASSERT (Pe [j] == n && Elen [j] == EMPTY) ; i++ ; Bucket [C [j]]++ ; } ASSERT (i == ndense_or_null) ; /* find the cumulative sum of Bucket */ knt1 = 0 ; for (c = 0 ; c <= cmax ; c++) { i = Bucket [c] ; Bucket [c] = knt1 ; knt1 += i ; } CAMD_DEBUG1 (("knt1 "ID" dense/empty "ID"\n", knt1, ndense_or_null)); ASSERT (knt1 == ndense_or_null) ; /* place dense/empty nodes in BucketSet, in constraint order, * ties in natural order */ for (j = Head [n] ; j != EMPTY ; j = Next [j]) { BucketSet [Bucket [C [j]]++] = j ; } #ifndef NDEBUG /* each set is in monotonically increasing order of constraints */ for (i = 1 ; i < k ; i++) { ASSERT (C [Perm [i]] >= C [Perm [i-1]]) ; } for (i = 1 ; i < ndense_or_null ; i++) { /* in order of constraints, with ties in natural order */ ASSERT ( (C [BucketSet [i]] > C [BucketSet [i-1]]) || (C [BucketSet [i]] == C [BucketSet [i-1]] && (BucketSet [i] > BucketSet [i-1]))) ; } #endif /* merge Perm [0..k-1] and BucketSet [0..ndense+nnull] */ p1 = 0 ; p2 = 0 ; p3 = 0 ; while (p1 < k && p2 < ndense_or_null) { /* place the dense/empty nodes at the end of each constraint * set, after the non-dense/non-empty nodes in the same set */ if (C [Perm [p1]] <= C [BucketSet [p2]]) { /* non-dense/non-empty node */ Last [p3++] = Perm [p1++] ; } else { /* dense/empty node */ Last [p3++] = BucketSet [p2++] ; } } /* wrap up; either Perm[0..k-1] or BucketSet[ ] is used up */ while (p1 < k) { Last [p3++] = Perm [p1++] ; } while (p2 < ndense_or_null) { Last [p3++] = BucketSet [p2++] ; } } } #ifndef NDEBUG CAMD_DEBUG1 (("\nFinal constrained ordering:\n")) ; i = 0 ; CAMD_DEBUG1 (("Last ["ID"] = "ID", C["ID"] = "ID"\n", i, Last [i], Last [i], C [Last [i]])) ; for (i = 1 ; i < n ; i++) { CAMD_DEBUG1 (("Last ["ID"] = "ID", C["ID"] = "ID"\n", i, Last [i], Last [i], C [Last [i]])) ; /* This is the critical assertion. It states that the permutation * satisfies the constraints. */ ASSERT (C [Last [i]] >= C [Last [i-1]]) ; } #endif } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_l_postorder.c�����������������������������������������������0000644�0001751�0000144�00000001020�14552026002�022207� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_l_postorder.c: int64_t version of camd_postorder //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "camd_postorder.c" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CAMD/Source/camd_preprocess.c������������������������������������������������0000644�0001751�0000144�00000007152�14552026002�022054� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CAMD/Source/camd_preprocess: sort, remove duplicates, transpose a matrix //------------------------------------------------------------------------------ // CAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. // Amestoy, and Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* Sorts, removes duplicate entries, and transposes from the nonzero pattern of * a column-form matrix A, to obtain the matrix R. The input matrix can have * duplicate entries and/or unsorted columns (CAMD_valid (n,Ap,Ai) must not be * CAMD_INVALID). * * This input condition is NOT checked. This routine is not user-callable. */ #include "camd_internal.h" /* ========================================================================= */ /* === CAMD_preprocess ===================================================== */ /* ========================================================================= */ /* CAMD_preprocess does not check its input for errors or allocate workspace. * On input, the condition (CAMD_valid (n,n,Ap,Ai) != CAMD_INVALID) must hold. */ void CAMD_preprocess ( 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 ; ASSERT (CAMD_valid (n, n, Ap, Ai) != CAMD_INVALID) ; /* --------------------------------------------------------------------- */ /* 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 ASSERT (CAMD_valid (n, n, Rp, Ri) == CAMD_OK) ; for (j = 0 ; j < n ; j++) { ASSERT (W [j] == Rp [j+1]) ; } #endif } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/��������������������������������������������������������������������0000755�0001751�0000144�00000000000�14576344041�016272� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Include/������������������������������������������������������������0000755�0001751�0000144�00000000000�14576343415�017661� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Include/cs.h��������������������������������������������������������0000644�0001751�0000144�00000101626�14552026002�020425� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Include/cs.h: include file for CXSparse //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ /* This is the CXSparse/Include/cs.h file. It has the same name (cs.h) as the CSparse/Include/cs.h file. The 'make install' for SuiteSparse installs CXSparse, and this file, instead of CSparse. The two packages have the same cs.h include filename, because CXSparse is a superset of CSparse. Any user program that uses CSparse can rely on CXSparse instead, with no change to the user code. The #include "cs.h" line will work for both versions, in user code, and the function names and user-visible typedefs from CSparse all appear in CXSparse. For experimenting and changing the package itself, I recommend using CSparse since it's simpler and easier to modify. For using the package in production codes, I recommend CXSparse since it has more features (support for complex matrices, and both int32_t and int64_t versions). */ //------------------------------------------------------------------------------ #ifndef _CXS_H #define _CXS_H #if 1 # ifdef __cplusplus # include # else # include # endif # define cs_complex_t double _Complex #endif #define CS_VER 4 /* CXSparse Version */ #define CS_SUBVER 3 #define CS_SUBSUB 1 #define CS_DATE "Jan 10, 2024" /* CXSparse release date */ #define CS_COPYRIGHT "Copyright (c) Timothy A. Davis, 2006-2024" #define CXSPARSE #include "SuiteSparse_config.h" #define CXSPARSE__VERSION SUITESPARSE__VERCODE(4,3,1) #if !defined (SUITESPARSE__VERSION) || \ (SUITESPARSE__VERSION < SUITESPARSE__VERCODE(7,5,0)) #error "CXSparse 4.3.1 requires SuiteSparse_config 7.5.0 or later" #endif #define cs_long_t int64_t #define cs_long_t_id "%" PRId64 #define cs_long_t_max INT64_MAX #ifdef __cplusplus extern "C" { #endif void cxsparse_version (int version [3]) ; // return version /* -------------------------------------------------------------------------- */ /* double/int32_t version of CXSparse */ /* -------------------------------------------------------------------------- */ /* --- primary CSparse routines and data structures ------------------------- */ typedef struct cs_di_sparse /* matrix in compressed-column or triplet form */ { int32_t nzmax ; /* maximum number of entries */ int32_t m ; /* number of rows */ int32_t n ; /* number of columns */ int32_t *p ; /* column pointers (size n+1) or col indices (size nzmax) */ int32_t *i ; /* row indices, size nzmax */ double *x ; /* numerical values, size nzmax */ int32_t nz ; /* # of entries in triplet matrix, -1 for compressed-col */ } cs_di ; cs_di *cs_di_add (const cs_di *A, const cs_di *B, double alpha, double beta) ; int32_t cs_di_cholsol (int32_t order, const cs_di *A, double *b) ; int32_t cs_di_dupl (cs_di *A) ; int32_t cs_di_entry (cs_di *T, int32_t i, int32_t j, double x) ; int32_t cs_di_lusol (int32_t order, const cs_di *A, double *b, double tol) ; int32_t cs_di_gaxpy (const cs_di *A, const double *x, double *y) ; cs_di *cs_di_multiply (const cs_di *A, const cs_di *B) ; int32_t cs_di_qrsol (int32_t order, const cs_di *A, double *b) ; cs_di *cs_di_transpose (const cs_di *A, int32_t values) ; cs_di *cs_di_compress (const cs_di *T) ; double cs_di_norm (const cs_di *A) ; int32_t cs_di_print (const cs_di *A, int32_t brief) ; cs_di *cs_di_load (FILE *f) ; /* utilities */ void *cs_di_calloc (int32_t n, size_t size) ; void *cs_di_free (void *p) ; void *cs_di_realloc (void *p, int32_t n, size_t size, int32_t *ok) ; cs_di *cs_di_spalloc (int32_t m, int32_t n, int32_t nzmax, int32_t values, int32_t t) ; cs_di *cs_di_spfree (cs_di *A) ; int32_t cs_di_sprealloc (cs_di *A, int32_t nzmax) ; void *cs_di_malloc (int32_t n, size_t size) ; /* --- secondary CSparse routines and data structures ----------------------- */ typedef struct cs_di_symbolic /* symbolic Cholesky, LU, or QR analysis */ { int32_t *pinv ; /* inverse row perm. for QR, fill red. perm for Chol */ int32_t *q ; /* fill-reducing column permutation for LU and QR */ int32_t *parent ; /* elimination tree for Cholesky and QR */ int32_t *cp ; /* column pointers for Cholesky, row counts for QR */ int32_t *leftmost ; /* leftmost[i] = min(find(A(i,:))), for QR */ int32_t m2 ; /* # of rows for QR, after adding fictitious rows */ double lnz ; /* # entries in L for LU or Cholesky; in V for QR */ double unz ; /* # entries in U for LU; in R for QR */ } cs_dis ; typedef struct cs_di_numeric /* numeric Cholesky, LU, or QR factorization */ { cs_di *L ; /* L for LU and Cholesky, V for QR */ cs_di *U ; /* U for LU, r for QR, not used for Cholesky */ int32_t *pinv ; /* partial pivoting for LU */ double *B ; /* beta [0..n-1] for QR */ } cs_din ; typedef struct cs_di_dmperm_results /* cs_di_dmperm or cs_di_scc output */ { int32_t *p ; /* size m, row permutation */ int32_t *q ; /* size n, column permutation */ int32_t *r ; /* size nb+1, block k is rows r[k] to r[k+1]-1 in A(p,q) */ int32_t *s ; /* size nb+1, block k is cols s[k] to s[k+1]-1 in A(p,q) */ int32_t nb ; /* # of blocks in fine dmperm decomposition */ int32_t rr [5] ; /* coarse row decomposition */ int32_t cc [5] ; /* coarse column decomposition */ } cs_did ; int32_t *cs_di_amd (int32_t order, const cs_di *A) ; cs_din *cs_di_chol (const cs_di *A, const cs_dis *S) ; cs_did *cs_di_dmperm (const cs_di *A, int32_t seed) ; int32_t cs_di_droptol (cs_di *A, double tol) ; int32_t cs_di_dropzeros (cs_di *A) ; int32_t cs_di_happly (const cs_di *V, int32_t i, double beta, double *x) ; int32_t cs_di_ipvec (const int32_t *p, const double *b, double *x, int32_t n) ; int32_t cs_di_lsolve (const cs_di *L, double *x) ; int32_t cs_di_ltsolve (const cs_di *L, double *x) ; cs_din *cs_di_lu (const cs_di *A, const cs_dis *S, double tol) ; cs_di *cs_di_permute (const cs_di *A, const int32_t *pinv, const int32_t *q, int32_t values) ; int32_t *cs_di_pinv (const int32_t *p, int32_t n) ; int32_t cs_di_pvec (const int32_t *p, const double *b, double *x, int32_t n) ; cs_din *cs_di_qr (const cs_di *A, const cs_dis *S) ; cs_dis *cs_di_schol (int32_t order, const cs_di *A) ; cs_dis *cs_di_sqr (int32_t order, const cs_di *A, int32_t qr) ; cs_di *cs_di_symperm (const cs_di *A, const int32_t *pinv, int32_t values) ; int32_t cs_di_usolve (const cs_di *U, double *x) ; int32_t cs_di_utsolve (const cs_di *U, double *x) ; int32_t cs_di_updown (cs_di *L, int32_t sigma, const cs_di *C, const int32_t *parent) ; /* utilities */ cs_dis *cs_di_sfree (cs_dis *S) ; cs_din *cs_di_nfree (cs_din *N) ; cs_did *cs_di_dfree (cs_did *D) ; /* --- tertiary CSparse routines -------------------------------------------- */ int32_t *cs_di_counts (const cs_di *A, const int32_t *parent, const int32_t *post, int32_t ata) ; double cs_di_cumsum (int32_t *p, int32_t *c, int32_t n) ; int32_t cs_di_dfs (int32_t j, cs_di *G, int32_t top, int32_t *xi, int32_t *pstack, const int32_t *pinv) ; int32_t *cs_di_etree (const cs_di *A, int32_t ata) ; int32_t cs_di_fkeep (cs_di *A, int32_t (*fkeep) (int32_t, int32_t, double, void *), void *other) ; double cs_di_house (double *x, double *beta, int32_t n) ; int32_t *cs_di_maxtrans (const cs_di *A, int32_t seed) ; int32_t *cs_di_post (const int32_t *parent, int32_t n) ; cs_did *cs_di_scc (cs_di *A) ; int32_t cs_di_scatter (const cs_di *A, int32_t j, double beta, int32_t *w, double *x, int32_t mark, cs_di *C, int32_t nz) ; int32_t cs_di_tdfs (int32_t j, int32_t k, int32_t *head, const int32_t *next, int32_t *post, int32_t *stack) ; int32_t cs_di_leaf (int32_t i, int32_t j, const int32_t *first, int32_t *maxfirst, int32_t *prevleaf, int32_t *ancestor, int32_t *jleaf) ; int32_t cs_di_reach (cs_di *G, const cs_di *B, int32_t k, int32_t *xi, const int32_t *pinv) ; int32_t cs_di_spsolve (cs_di *L, const cs_di *B, int32_t k, int32_t *xi, double *x, const int32_t *pinv, int32_t lo) ; int32_t cs_di_ereach (const cs_di *A, int32_t k, const int32_t *parent, int32_t *s, int32_t *w) ; int32_t *cs_di_randperm (int32_t n, int32_t seed) ; /* utilities */ cs_did *cs_di_dalloc (int32_t m, int32_t n) ; cs_di *cs_di_done (cs_di *C, void *w, void *x, int32_t ok) ; int32_t *cs_di_idone (int32_t *p, cs_di *C, void *w, int32_t ok) ; cs_din *cs_di_ndone (cs_din *N, cs_di *C, void *w, void *x, int32_t ok) ; cs_did *cs_di_ddone (cs_did *D, cs_di *C, void *w, int32_t ok) ; /* -------------------------------------------------------------------------- */ /* double/int64_t version of CXSparse */ /* -------------------------------------------------------------------------- */ /* --- primary CSparse routines and data structures ------------------------- */ typedef struct cs_dl_sparse /* matrix in compressed-column or triplet form */ { int64_t nzmax ; /* maximum number of entries */ int64_t m ; /* number of rows */ int64_t n ; /* number of columns */ int64_t *p ; /* column pointers (size n+1) or col indlces (size nzmax) */ int64_t *i ; /* row indices, size nzmax */ double *x ; /* numerical values, size nzmax */ int64_t nz ; /* # of entries in triplet matrix, -1 for compressed-col */ } cs_dl ; cs_dl *cs_dl_add (const cs_dl *A, const cs_dl *B, double alpha, double beta) ; int64_t cs_dl_cholsol (int64_t order, const cs_dl *A, double *b) ; int64_t cs_dl_dupl (cs_dl *A) ; int64_t cs_dl_entry (cs_dl *T, int64_t i, int64_t j, double x) ; int64_t cs_dl_lusol (int64_t order, const cs_dl *A, double *b, double tol) ; int64_t cs_dl_gaxpy (const cs_dl *A, const double *x, double *y) ; cs_dl *cs_dl_multiply (const cs_dl *A, const cs_dl *B) ; int64_t cs_dl_qrsol (int64_t order, const cs_dl *A, double *b) ; cs_dl *cs_dl_transpose (const cs_dl *A, int64_t values) ; cs_dl *cs_dl_compress (const cs_dl *T) ; double cs_dl_norm (const cs_dl *A) ; int64_t cs_dl_print (const cs_dl *A, int64_t brief) ; cs_dl *cs_dl_load (FILE *f) ; /* utilities */ void *cs_dl_calloc (int64_t n, size_t size) ; void *cs_dl_free (void *p) ; void *cs_dl_realloc (void *p, int64_t n, size_t size, int64_t *ok) ; cs_dl *cs_dl_spalloc (int64_t m, int64_t n, int64_t nzmax, int64_t values, int64_t t) ; cs_dl *cs_dl_spfree (cs_dl *A) ; int64_t cs_dl_sprealloc (cs_dl *A, int64_t nzmax) ; void *cs_dl_malloc (int64_t n, size_t size) ; /* --- secondary CSparse routines and data structures ----------------------- */ typedef struct cs_dl_symbolic /* symbolic Cholesky, LU, or QR analysis */ { int64_t *pinv ; /* inverse row perm. for QR, fill red. perm for Chol */ int64_t *q ; /* fill-reducing column permutation for LU and QR */ int64_t *parent ; /* elimination tree for Cholesky and QR */ int64_t *cp ; /* column pointers for Cholesky, row counts for QR */ int64_t *leftmost ; /* leftmost[i] = min(find(A(i,:))), for QR */ int64_t m2 ; /* # of rows for QR, after adding fictitious rows */ double lnz ; /* # entries in L for LU or Cholesky; in V for QR */ double unz ; /* # entries in U for LU; in R for QR */ } cs_dls ; typedef struct cs_dl_numeric /* numeric Cholesky, LU, or QR factorization */ { cs_dl *L ; /* L for LU and Cholesky, V for QR */ cs_dl *U ; /* U for LU, r for QR, not used for Cholesky */ int64_t *pinv ; /* partial pivoting for LU */ double *B ; /* beta [0..n-1] for QR */ } cs_dln ; typedef struct cs_dl_dmperm_results /* cs_dl_dmperm or cs_dl_scc output */ { int64_t *p ; /* size m, row permutation */ int64_t *q ; /* size n, column permutation */ int64_t *r ; /* size nb+1, block k is rows r[k] to r[k+1]-1 in A(p,q) */ int64_t *s ; /* size nb+1, block k is cols s[k] to s[k+1]-1 in A(p,q) */ int64_t nb ; /* # of blocks in fine dmperm decomposition */ int64_t rr [5] ; /* coarse row decomposition */ int64_t cc [5] ; /* coarse column decomposition */ } cs_dld ; int64_t *cs_dl_amd (int64_t order, const cs_dl *A) ; cs_dln *cs_dl_chol (const cs_dl *A, const cs_dls *S) ; cs_dld *cs_dl_dmperm (const cs_dl *A, int64_t seed) ; int64_t cs_dl_droptol (cs_dl *A, double tol) ; int64_t cs_dl_dropzeros (cs_dl *A) ; int64_t cs_dl_happly (const cs_dl *V, int64_t i, double beta, double *x) ; int64_t cs_dl_ipvec (const int64_t *p, const double *b, double *x, int64_t n) ; int64_t cs_dl_lsolve (const cs_dl *L, double *x) ; int64_t cs_dl_ltsolve (const cs_dl *L, double *x) ; cs_dln *cs_dl_lu (const cs_dl *A, const cs_dls *S, double tol) ; cs_dl *cs_dl_permute (const cs_dl *A, const int64_t *pinv, const int64_t *q, int64_t values) ; int64_t *cs_dl_pinv (const int64_t *p, int64_t n) ; int64_t cs_dl_pvec (const int64_t *p, const double *b, double *x, int64_t n) ; cs_dln *cs_dl_qr (const cs_dl *A, const cs_dls *S) ; cs_dls *cs_dl_schol (int64_t order, const cs_dl *A) ; cs_dls *cs_dl_sqr (int64_t order, const cs_dl *A, int64_t qr) ; cs_dl *cs_dl_symperm (const cs_dl *A, const int64_t *pinv, int64_t values) ; int64_t cs_dl_usolve (const cs_dl *U, double *x) ; int64_t cs_dl_utsolve (const cs_dl *U, double *x) ; int64_t cs_dl_updown (cs_dl *L, int64_t sigma, const cs_dl *C, const int64_t *parent) ; /* utilities */ cs_dls *cs_dl_sfree (cs_dls *S) ; cs_dln *cs_dl_nfree (cs_dln *N) ; cs_dld *cs_dl_dfree (cs_dld *D) ; /* --- tertiary CSparse routines -------------------------------------------- */ int64_t *cs_dl_counts (const cs_dl *A, const int64_t *parent, const int64_t *post, int64_t ata) ; double cs_dl_cumsum (int64_t *p, int64_t *c, int64_t n) ; int64_t cs_dl_dfs (int64_t j, cs_dl *G, int64_t top, int64_t *xi, int64_t *pstack, const int64_t *pinv) ; int64_t *cs_dl_etree (const cs_dl *A, int64_t ata) ; int64_t cs_dl_fkeep (cs_dl *A, int64_t (*fkeep) (int64_t, int64_t, double, void *), void *other) ; double cs_dl_house (double *x, double *beta, int64_t n) ; int64_t *cs_dl_maxtrans (const cs_dl *A, int64_t seed) ; int64_t *cs_dl_post (const int64_t *parent, int64_t n) ; cs_dld *cs_dl_scc (cs_dl *A) ; int64_t cs_dl_scatter (const cs_dl *A, int64_t j, double beta, int64_t *w, double *x, int64_t mark,cs_dl *C, int64_t nz) ; int64_t cs_dl_tdfs (int64_t j, int64_t k, int64_t *head, const int64_t *next, int64_t *post, int64_t *stack) ; int64_t cs_dl_leaf (int64_t i, int64_t j, const int64_t *first, int64_t *maxfirst, int64_t *prevleaf, int64_t *ancestor, int64_t *jleaf) ; int64_t cs_dl_reach (cs_dl *G, const cs_dl *B, int64_t k, int64_t *xi, const int64_t *pinv) ; int64_t cs_dl_spsolve (cs_dl *L, const cs_dl *B, int64_t k, int64_t *xi, double *x, const int64_t *pinv, int64_t lo) ; int64_t cs_dl_ereach (const cs_dl *A, int64_t k, const int64_t *parent, int64_t *s, int64_t *w) ; int64_t *cs_dl_randperm (int64_t n, int64_t seed) ; /* utilities */ cs_dld *cs_dl_dalloc (int64_t m, int64_t n) ; cs_dl *cs_dl_done (cs_dl *C, void *w, void *x, int64_t ok) ; int64_t *cs_dl_idone (int64_t *p, cs_dl *C, void *w, int64_t ok) ; cs_dln *cs_dl_ndone (cs_dln *N, cs_dl *C, void *w, void *x, int64_t ok) ; cs_dld *cs_dl_ddone (cs_dld *D, cs_dl *C, void *w, int64_t ok) ; /* -------------------------------------------------------------------------- */ /* complex/int32_t version of CXSparse */ /* -------------------------------------------------------------------------- */ #if 1 /* --- primary CSparse routines and data structures ------------------------- */ typedef struct cs_ci_sparse /* matrix in compressed-column or triplet form */ { int32_t nzmax ; /* maximum number of entries */ int32_t m ; /* number of rows */ int32_t n ; /* number of columns */ int32_t *p ; /* column pointers (size n+1) or col indices (size nzmax) */ int32_t *i ; /* row indices, size nzmax */ cs_complex_t *x ; /* numerical values, size nzmax */ int32_t nz ; /* # of entries in triplet matrix, -1 for compressed-col */ } cs_ci ; cs_ci *cs_ci_add (const cs_ci *A, const cs_ci *B, cs_complex_t alpha, cs_complex_t beta) ; int32_t cs_ci_cholsol (int32_t order, const cs_ci *A, cs_complex_t *b) ; int32_t cs_ci_dupl (cs_ci *A) ; int32_t cs_ci_entry (cs_ci *T, int32_t i, int32_t j, cs_complex_t x) ; int32_t cs_ci_lusol (int32_t order, const cs_ci *A, cs_complex_t *b, double tol) ; int32_t cs_ci_gaxpy (const cs_ci *A, const cs_complex_t *x, cs_complex_t *y) ; cs_ci *cs_ci_multiply (const cs_ci *A, const cs_ci *B) ; int32_t cs_ci_qrsol (int32_t order, const cs_ci *A, cs_complex_t *b) ; cs_ci *cs_ci_transpose (const cs_ci *A, int32_t values) ; cs_ci *cs_ci_compress (const cs_ci *T) ; double cs_ci_norm (const cs_ci *A) ; int32_t cs_ci_print (const cs_ci *A, int32_t brief) ; cs_ci *cs_ci_load (FILE *f) ; /* utilities */ void *cs_ci_calloc (int32_t n, size_t size) ; void *cs_ci_free (void *p) ; void *cs_ci_realloc (void *p, int32_t n, size_t size, int32_t *ok) ; cs_ci *cs_ci_spalloc (int32_t m, int32_t n, int32_t nzmax, int32_t values, int32_t t) ; cs_ci *cs_ci_spfree (cs_ci *A) ; int32_t cs_ci_sprealloc (cs_ci *A, int32_t nzmax) ; void *cs_ci_malloc (int32_t n, size_t size) ; /* --- secondary CSparse routines and data structures ----------------------- */ typedef struct cs_ci_symbolic /* symbolic Cholesky, LU, or QR analysis */ { int32_t *pinv ; /* inverse row perm. for QR, fill red. perm for Chol */ int32_t *q ; /* fill-reducing column permutation for LU and QR */ int32_t *parent ; /* elimination tree for Cholesky and QR */ int32_t *cp ; /* column pointers for Cholesky, row counts for QR */ int32_t *leftmost ; /* leftmost[i] = min(find(A(i,:))), for QR */ int32_t m2 ; /* # of rows for QR, after adding fictitious rows */ double lnz ; /* # entries in L for LU or Cholesky; in V for QR */ double unz ; /* # entries in U for LU; in R for QR */ } cs_cis ; typedef struct cs_ci_numeric /* numeric Cholesky, LU, or QR factorization */ { cs_ci *L ; /* L for LU and Cholesky, V for QR */ cs_ci *U ; /* U for LU, r for QR, not used for Cholesky */ int32_t *pinv ; /* partial pivoting for LU */ double *B ; /* beta [0..n-1] for QR */ } cs_cin ; typedef struct cs_ci_dmperm_results /* cs_ci_dmperm or cs_ci_scc output */ { int32_t *p ; /* size m, row permutation */ int32_t *q ; /* size n, column permutation */ int32_t *r ; /* size nb+1, block k is rows r[k] to r[k+1]-1 in A(p,q) */ int32_t *s ; /* size nb+1, block k is cols s[k] to s[k+1]-1 in A(p,q) */ int32_t nb ; /* # of blocks in fine dmperm decomposition */ int32_t rr [5] ; /* coarse row decomposition */ int32_t cc [5] ; /* coarse column decomposition */ } cs_cid ; int32_t *cs_ci_amd (int32_t order, const cs_ci *A) ; cs_cin *cs_ci_chol (const cs_ci *A, const cs_cis *S) ; cs_cid *cs_ci_dmperm (const cs_ci *A, int32_t seed) ; int32_t cs_ci_droptol (cs_ci *A, double tol) ; int32_t cs_ci_dropzeros (cs_ci *A) ; int32_t cs_ci_happly (const cs_ci *V, int32_t i, double beta, cs_complex_t *x) ; int32_t cs_ci_ipvec (const int32_t *p, const cs_complex_t *b, cs_complex_t *x, int32_t n) ; int32_t cs_ci_lsolve (const cs_ci *L, cs_complex_t *x) ; int32_t cs_ci_ltsolve (const cs_ci *L, cs_complex_t *x) ; cs_cin *cs_ci_lu (const cs_ci *A, const cs_cis *S, double tol) ; cs_ci *cs_ci_permute (const cs_ci *A, const int32_t *pinv, const int32_t *q, int32_t values) ; int32_t *cs_ci_pinv (const int32_t *p, int32_t n) ; int32_t cs_ci_pvec (const int32_t *p, const cs_complex_t *b, cs_complex_t *x, int32_t n) ; cs_cin *cs_ci_qr (const cs_ci *A, const cs_cis *S) ; cs_cis *cs_ci_schol (int32_t order, const cs_ci *A) ; cs_cis *cs_ci_sqr (int32_t order, const cs_ci *A, int32_t qr) ; cs_ci *cs_ci_symperm (const cs_ci *A, const int32_t *pinv, int32_t values) ; int32_t cs_ci_usolve (const cs_ci *U, cs_complex_t *x) ; int32_t cs_ci_utsolve (const cs_ci *U, cs_complex_t *x) ; int32_t cs_ci_updown (cs_ci *L, int32_t sigma, const cs_ci *C, const int32_t *parent) ; /* utilities */ cs_cis *cs_ci_sfree (cs_cis *S) ; cs_cin *cs_ci_nfree (cs_cin *N) ; cs_cid *cs_ci_dfree (cs_cid *D) ; /* --- tertiary CSparse routines -------------------------------------------- */ int32_t *cs_ci_counts (const cs_ci *A, const int32_t *parent, const int32_t *post, int32_t ata) ; double cs_ci_cumsum (int32_t *p, int32_t *c, int32_t n) ; int32_t cs_ci_dfs (int32_t j, cs_ci *G, int32_t top, int32_t *xi, int32_t *pstack, const int32_t *pinv) ; int32_t *cs_ci_etree (const cs_ci *A, int32_t ata) ; int32_t cs_ci_fkeep (cs_ci *A, int32_t (*fkeep) (int32_t, int32_t, cs_complex_t, void *), void *other) ; cs_complex_t cs_ci_house (cs_complex_t *x, double *beta, int32_t n) ; int32_t *cs_ci_maxtrans (const cs_ci *A, int32_t seed) ; int32_t *cs_ci_post (const int32_t *parent, int32_t n) ; cs_cid *cs_ci_scc (cs_ci *A) ; int32_t cs_ci_scatter (const cs_ci *A, int32_t j, cs_complex_t beta, int32_t *w, cs_complex_t *x, int32_t mark,cs_ci *C, int32_t nz) ; int32_t cs_ci_tdfs (int32_t j, int32_t k, int32_t *head, const int32_t *next, int32_t *post, int32_t *stack) ; int32_t cs_ci_leaf (int32_t i, int32_t j, const int32_t *first, int32_t *maxfirst, int32_t *prevleaf, int32_t *ancestor, int32_t *jleaf) ; int32_t cs_ci_reach (cs_ci *G, const cs_ci *B, int32_t k, int32_t *xi, const int32_t *pinv) ; int32_t cs_ci_spsolve (cs_ci *L, const cs_ci *B, int32_t k, int32_t *xi, cs_complex_t *x, const int32_t *pinv, int32_t lo) ; int32_t cs_ci_ereach (const cs_ci *A, int32_t k, const int32_t *parent, int32_t *s, int32_t *w) ; int32_t *cs_ci_randperm (int32_t n, int32_t seed) ; /* utilities */ cs_cid *cs_ci_dalloc (int32_t m, int32_t n) ; cs_ci *cs_ci_done (cs_ci *C, void *w, void *x, int32_t ok) ; int32_t *cs_ci_idone (int32_t *p, cs_ci *C, void *w, int32_t ok) ; cs_cin *cs_ci_ndone (cs_cin *N, cs_ci *C, void *w, void *x, int32_t ok) ; cs_cid *cs_ci_ddone (cs_cid *D, cs_ci *C, void *w, int32_t ok) ; /* -------------------------------------------------------------------------- */ /* complex/int64_t version of CXSparse */ /* -------------------------------------------------------------------------- */ /* --- primary CSparse routines and data structures ------------------------- */ typedef struct cs_cl_sparse /* matrix in compressed-column or triplet form */ { int64_t nzmax ; /* maximum number of entries */ int64_t m ; /* number of rows */ int64_t n ; /* number of columns */ int64_t *p ; /* column pointers (size n+1) or col indlces (size nzmax) */ int64_t *i ; /* row indices, size nzmax */ cs_complex_t *x ; /* numerical values, size nzmax */ int64_t nz ; /* # of entries in triplet matrix, -1 for compressed-col */ } cs_cl ; cs_cl *cs_cl_add (const cs_cl *A, const cs_cl *B, cs_complex_t alpha, cs_complex_t beta) ; int64_t cs_cl_cholsol (int64_t order, const cs_cl *A, cs_complex_t *b) ; int64_t cs_cl_dupl (cs_cl *A) ; int64_t cs_cl_entry (cs_cl *T, int64_t i, int64_t j, cs_complex_t x) ; int64_t cs_cl_lusol (int64_t order, const cs_cl *A, cs_complex_t *b, double tol) ; int64_t cs_cl_gaxpy (const cs_cl *A, const cs_complex_t *x, cs_complex_t *y) ; cs_cl *cs_cl_multiply (const cs_cl *A, const cs_cl *B) ; int64_t cs_cl_qrsol (int64_t order, const cs_cl *A, cs_complex_t *b) ; cs_cl *cs_cl_transpose (const cs_cl *A, int64_t values) ; cs_cl *cs_cl_compress (const cs_cl *T) ; double cs_cl_norm (const cs_cl *A) ; int64_t cs_cl_print (const cs_cl *A, int64_t brief) ; cs_cl *cs_cl_load (FILE *f) ; /* utilities */ void *cs_cl_calloc (int64_t n, size_t size) ; void *cs_cl_free (void *p) ; void *cs_cl_realloc (void *p, int64_t n, size_t size, int64_t *ok) ; cs_cl *cs_cl_spalloc (int64_t m, int64_t n, int64_t nzmax, int64_t values, int64_t t) ; cs_cl *cs_cl_spfree (cs_cl *A) ; int64_t cs_cl_sprealloc (cs_cl *A, int64_t nzmax) ; void *cs_cl_malloc (int64_t n, size_t size) ; /* --- secondary CSparse routines and data structures ----------------------- */ typedef struct cs_cl_symbolic /* symbolic Cholesky, LU, or QR analysis */ { int64_t *pinv ; /* inverse row perm. for QR, fill red. perm for Chol */ int64_t *q ; /* fill-reducing column permutation for LU and QR */ int64_t *parent ; /* elimination tree for Cholesky and QR */ int64_t *cp ; /* column pointers for Cholesky, row counts for QR */ int64_t *leftmost ; /* leftmost[i] = min(find(A(i,:))), for QR */ int64_t m2 ; /* # of rows for QR, after adding fictitious rows */ double lnz ; /* # entries in L for LU or Cholesky; in V for QR */ double unz ; /* # entries in U for LU; in R for QR */ } cs_cls ; typedef struct cs_cl_numeric /* numeric Cholesky, LU, or QR factorization */ { cs_cl *L ; /* L for LU and Cholesky, V for QR */ cs_cl *U ; /* U for LU, r for QR, not used for Cholesky */ int64_t *pinv ; /* partial pivoting for LU */ double *B ; /* beta [0..n-1] for QR */ } cs_cln ; typedef struct cs_cl_dmperm_results /* cs_cl_dmperm or cs_cl_scc output */ { int64_t *p ; /* size m, row permutation */ int64_t *q ; /* size n, column permutation */ int64_t *r ; /* size nb+1, block k is rows r[k] to r[k+1]-1 in A(p,q) */ int64_t *s ; /* size nb+1, block k is cols s[k] to s[k+1]-1 in A(p,q) */ int64_t nb ; /* # of blocks in fine dmperm decomposition */ int64_t rr [5] ; /* coarse row decomposition */ int64_t cc [5] ; /* coarse column decomposition */ } cs_cld ; int64_t *cs_cl_amd (int64_t order, const cs_cl *A) ; cs_cln *cs_cl_chol (const cs_cl *A, const cs_cls *S) ; cs_cld *cs_cl_dmperm (const cs_cl *A, int64_t seed) ; int64_t cs_cl_droptol (cs_cl *A, double tol) ; int64_t cs_cl_dropzeros (cs_cl *A) ; int64_t cs_cl_happly (const cs_cl *V, int64_t i, double beta, cs_complex_t *x) ; int64_t cs_cl_ipvec (const int64_t *p, const cs_complex_t *b, cs_complex_t *x, int64_t n) ; int64_t cs_cl_lsolve (const cs_cl *L, cs_complex_t *x) ; int64_t cs_cl_ltsolve (const cs_cl *L, cs_complex_t *x) ; cs_cln *cs_cl_lu (const cs_cl *A, const cs_cls *S, double tol) ; cs_cl *cs_cl_permute (const cs_cl *A, const int64_t *pinv, const int64_t *q, int64_t values) ; int64_t *cs_cl_pinv (const int64_t *p, int64_t n) ; int64_t cs_cl_pvec (const int64_t *p, const cs_complex_t *b, cs_complex_t *x, int64_t n) ; cs_cln *cs_cl_qr (const cs_cl *A, const cs_cls *S) ; cs_cls *cs_cl_schol (int64_t order, const cs_cl *A) ; cs_cls *cs_cl_sqr (int64_t order, const cs_cl *A, int64_t qr) ; cs_cl *cs_cl_symperm (const cs_cl *A, const int64_t *pinv, int64_t values) ; int64_t cs_cl_usolve (const cs_cl *U, cs_complex_t *x) ; int64_t cs_cl_utsolve (const cs_cl *U, cs_complex_t *x) ; int64_t cs_cl_updown (cs_cl *L, int64_t sigma, const cs_cl *C, const int64_t *parent) ; /* utilities */ cs_cls *cs_cl_sfree (cs_cls *S) ; cs_cln *cs_cl_nfree (cs_cln *N) ; cs_cld *cs_cl_dfree (cs_cld *D) ; /* --- tertiary CSparse routines -------------------------------------------- */ int64_t *cs_cl_counts (const cs_cl *A, const int64_t *parent, const int64_t *post, int64_t ata) ; double cs_cl_cumsum (int64_t *p, int64_t *c, int64_t n) ; int64_t cs_cl_dfs (int64_t j, cs_cl *G, int64_t top, int64_t *xi, int64_t *pstack, const int64_t *pinv) ; int64_t *cs_cl_etree (const cs_cl *A, int64_t ata) ; int64_t cs_cl_fkeep (cs_cl *A, int64_t (*fkeep) (int64_t, int64_t, cs_complex_t, void *), void *other) ; cs_complex_t cs_cl_house (cs_complex_t *x, double *beta, int64_t n) ; int64_t *cs_cl_maxtrans (const cs_cl *A, int64_t seed) ; int64_t *cs_cl_post (const int64_t *parent, int64_t n) ; cs_cld *cs_cl_scc (cs_cl *A) ; int64_t cs_cl_scatter (const cs_cl *A, int64_t j, cs_complex_t beta, int64_t *w, cs_complex_t *x, int64_t mark,cs_cl *C, int64_t nz) ; int64_t cs_cl_tdfs (int64_t j, int64_t k, int64_t *head, const int64_t *next, int64_t *post, int64_t *stack) ; int64_t cs_cl_leaf (int64_t i, int64_t j, const int64_t *first, int64_t *maxfirst, int64_t *prevleaf, int64_t *ancestor, int64_t *jleaf) ; int64_t cs_cl_reach (cs_cl *G, const cs_cl *B, int64_t k, int64_t *xi, const int64_t *pinv) ; int64_t cs_cl_spsolve (cs_cl *L, const cs_cl *B, int64_t k, int64_t *xi, cs_complex_t *x, const int64_t *pinv, int64_t lo) ; int64_t cs_cl_ereach (const cs_cl *A, int64_t k, const int64_t *parent, int64_t *s, int64_t *w) ; int64_t *cs_cl_randperm (int64_t n, int64_t seed) ; /* utilities */ cs_cld *cs_cl_dalloc (int64_t m, int64_t n) ; cs_cl *cs_cl_done (cs_cl *C, void *w, void *x, int64_t ok) ; int64_t *cs_cl_idone (int64_t *p, cs_cl *C, void *w, int64_t ok) ; cs_cln *cs_cl_ndone (cs_cln *N, cs_cl *C, void *w, void *x, int64_t ok) ; cs_cld *cs_cl_ddone (cs_cld *D, cs_cl *C, void *w, int64_t ok) ; #endif /* -------------------------------------------------------------------------- */ /* Macros for constructing each version of CSparse */ /* -------------------------------------------------------------------------- */ #ifdef CS_LONG #define CS_INT int64_t #define CS_INT_MAX cs_long_t_max #define CS_ID cs_long_t_id #ifdef CS_COMPLEX #define CS_ENTRY cs_complex_t #define CS_NAME(nm) cs_cl ## nm #define cs cs_cl #else #define CS_ENTRY double #define CS_NAME(nm) cs_dl ## nm #define cs cs_dl #endif #else #define CS_INT int32_t #define CS_INT_MAX INT_MAX #define CS_ID "%d" #ifdef CS_COMPLEX #define CS_ENTRY cs_complex_t #define CS_NAME(nm) cs_ci ## nm #define cs cs_ci #else #define CS_ENTRY double #define CS_NAME(nm) cs_di ## nm #define cs cs_di #endif #endif #ifdef CS_COMPLEX #define CS_REAL(x) creal(x) #define CS_IMAG(x) cimag(x) #define CS_CONJ(x) conj(x) #define CS_ABS(x) cabs(x) #else #define CS_REAL(x) (x) #define CS_IMAG(x) (0.) #define CS_CONJ(x) (x) #define CS_ABS(x) fabs(x) #endif #define CS_MAX(a,b) (((a) > (b)) ? (a) : (b)) #define CS_MIN(a,b) (((a) < (b)) ? (a) : (b)) #define CS_FLIP(i) (-(i)-2) #define CS_UNFLIP(i) (((i) < 0) ? CS_FLIP(i) : (i)) #define CS_MARKED(w,j) (w [j] < 0) #define CS_MARK(w,j) { w [j] = CS_FLIP (w [j]) ; } #define CS_CSC(A) (A && (A->nz == -1)) #define CS_TRIPLET(A) (A && (A->nz >= 0)) /* --- primary CSparse routines and data structures ------------------------- */ #define cs_add CS_NAME (_add) #define cs_cholsol CS_NAME (_cholsol) #define cs_dupl CS_NAME (_dupl) #define cs_entry CS_NAME (_entry) #define cs_lusol CS_NAME (_lusol) #define cs_gaxpy CS_NAME (_gaxpy) #define cs_multiply CS_NAME (_multiply) #define cs_qrsol CS_NAME (_qrsol) #define cs_transpose CS_NAME (_transpose) #define cs_compress CS_NAME (_compress) #define cs_norm CS_NAME (_norm) #define cs_print CS_NAME (_print) #define cs_load CS_NAME (_load) /* utilities */ #define cs_calloc CS_NAME (_calloc) #define cs_free CS_NAME (_free) #define cs_realloc CS_NAME (_realloc) #define cs_spalloc CS_NAME (_spalloc) #define cs_spfree CS_NAME (_spfree) #define cs_sprealloc CS_NAME (_sprealloc) #define cs_malloc CS_NAME (_malloc) /* --- secondary CSparse routines and data structures ----------------------- */ #define css CS_NAME (s) #define csn CS_NAME (n) #define csd CS_NAME (d) #define cs_amd CS_NAME (_amd) #define cs_chol CS_NAME (_chol) #define cs_dmperm CS_NAME (_dmperm) #define cs_droptol CS_NAME (_droptol) #define cs_dropzeros CS_NAME (_dropzeros) #define cs_happly CS_NAME (_happly) #define cs_ipvec CS_NAME (_ipvec) #define cs_lsolve CS_NAME (_lsolve) #define cs_ltsolve CS_NAME (_ltsolve) #define cs_lu CS_NAME (_lu) #define cs_permute CS_NAME (_permute) #define cs_pinv CS_NAME (_pinv) #define cs_pvec CS_NAME (_pvec) #define cs_qr CS_NAME (_qr) #define cs_schol CS_NAME (_schol) #define cs_sqr CS_NAME (_sqr) #define cs_symperm CS_NAME (_symperm) #define cs_usolve CS_NAME (_usolve) #define cs_utsolve CS_NAME (_utsolve) #define cs_updown CS_NAME (_updown) /* utilities */ #define cs_sfree CS_NAME (_sfree) #define cs_nfree CS_NAME (_nfree) #define cs_dfree CS_NAME (_dfree) /* --- tertiary CSparse routines -------------------------------------------- */ #define cs_counts CS_NAME (_counts) #define cs_cumsum CS_NAME (_cumsum) #define cs_dfs CS_NAME (_dfs) #define cs_etree CS_NAME (_etree) #define cs_fkeep CS_NAME (_fkeep) #define cs_house CS_NAME (_house) #define cs_invmatch CS_NAME (_invmatch) #define cs_maxtrans CS_NAME (_maxtrans) #define cs_post CS_NAME (_post) #define cs_scc CS_NAME (_scc) #define cs_scatter CS_NAME (_scatter) #define cs_tdfs CS_NAME (_tdfs) #define cs_reach CS_NAME (_reach) #define cs_spsolve CS_NAME (_spsolve) #define cs_ereach CS_NAME (_ereach) #define cs_randperm CS_NAME (_randperm) #define cs_leaf CS_NAME (_leaf) /* utilities */ #define cs_dalloc CS_NAME (_dalloc) #define cs_done CS_NAME (_done) #define cs_idone CS_NAME (_idone) #define cs_ndone CS_NAME (_ndone) #define cs_ddone CS_NAME (_ddone) /* -------------------------------------------------------------------------- */ /* Conversion routines */ /* -------------------------------------------------------------------------- */ #if 1 cs_di *cs_i_real (cs_ci *A, int32_t real) ; cs_ci *cs_i_complex (cs_di *A, int32_t real) ; cs_dl *cs_l_real (cs_cl *A, int64_t real) ; cs_cl *cs_l_complex (cs_dl *A, int64_t real) ; #endif #ifdef __cplusplus } #endif #endif ����������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Makefile������������������������������������������������������������0000644�0001751�0000144�00000012233�14576344042�017734� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sources = \ Source/cs_add.c Source/cs_dl_add.c Source/cs_ci_add.c Source/cs_cl_add.c \ Source/cs_amd.c Source/cs_dl_amd.c Source/cs_ci_amd.c Source/cs_cl_amd.c \ Source/cs_chol.c Source/cs_dl_chol.c Source/cs_ci_chol.c Source/cs_cl_chol.c \ Source/cs_cholsol.c Source/cs_dl_cholsol.c Source/cs_ci_cholsol.c Source/cs_cl_cholsol.c \ Source/cs_compress.c Source/cs_dl_compress.c Source/cs_ci_compress.c Source/cs_cl_compress.c \ Source/cs_convert.c \ Source/cs_counts.c Source/cs_dl_counts.c Source/cs_ci_counts.c Source/cs_cl_counts.c \ Source/cs_cumsum.c Source/cs_dl_cumsum.c Source/cs_ci_cumsum.c Source/cs_cl_cumsum.c \ Source/cs_dfs.c Source/cs_dl_dfs.c Source/cs_ci_dfs.c Source/cs_cl_dfs.c \ Source/cs_dmperm.c Source/cs_dl_dmperm.c Source/cs_ci_dmperm.c Source/cs_cl_dmperm.c \ Source/cs_droptol.c Source/cs_dl_droptol.c Source/cs_ci_droptol.c Source/cs_cl_droptol.c \ Source/cs_dropzeros.c Source/cs_dl_dropzeros.c Source/cs_ci_dropzeros.c Source/cs_cl_dropzeros.c \ Source/cs_dupl.c Source/cs_dl_dupl.c Source/cs_ci_dupl.c Source/cs_cl_dupl.c \ Source/cs_entry.c Source/cs_dl_entry.c Source/cs_ci_entry.c Source/cs_cl_entry.c \ Source/cs_ereach.c Source/cs_dl_ereach.c Source/cs_ci_ereach.c Source/cs_cl_ereach.c \ Source/cs_etree.c Source/cs_dl_etree.c Source/cs_ci_etree.c Source/cs_cl_etree.c \ Source/cs_fkeep.c Source/cs_dl_fkeep.c Source/cs_ci_fkeep.c Source/cs_cl_fkeep.c \ Source/cs_gaxpy.c Source/cs_dl_gaxpy.c Source/cs_ci_gaxpy.c Source/cs_cl_gaxpy.c \ Source/cs_happly.c Source/cs_dl_happly.c Source/cs_ci_happly.c Source/cs_cl_happly.c \ Source/cs_house.c Source/cs_dl_house.c Source/cs_ci_house.c Source/cs_cl_house.c \ Source/cs_ipvec.c Source/cs_dl_ipvec.c Source/cs_ci_ipvec.c Source/cs_cl_ipvec.c \ Source/cs_leaf.c Source/cs_dl_leaf.c Source/cs_ci_leaf.c Source/cs_cl_leaf.c \ Source/cs_load.c Source/cs_dl_load.c Source/cs_ci_load.c Source/cs_cl_load.c \ Source/cs_lsolve.c Source/cs_dl_lsolve.c Source/cs_ci_lsolve.c Source/cs_cl_lsolve.c \ Source/cs_ltsolve.c Source/cs_dl_ltsolve.c Source/cs_ci_ltsolve.c Source/cs_cl_ltsolve.c \ Source/cs_lu.c Source/cs_dl_lu.c Source/cs_ci_lu.c Source/cs_cl_lu.c \ Source/cs_lusol.c Source/cs_dl_lusol.c Source/cs_ci_lusol.c Source/cs_cl_lusol.c \ Source/cs_malloc.c Source/cs_dl_malloc.c Source/cs_ci_malloc.c Source/cs_cl_malloc.c \ Source/cs_maxtrans.c Source/cs_dl_maxtrans.c Source/cs_ci_maxtrans.c Source/cs_cl_maxtrans.c \ Source/cs_multiply.c Source/cs_dl_multiply.c Source/cs_ci_multiply.c Source/cs_cl_multiply.c \ Source/cs_norm.c Source/cs_dl_norm.c Source/cs_ci_norm.c Source/cs_cl_norm.c \ Source/cs_permute.c Source/cs_dl_permute.c Source/cs_ci_permute.c Source/cs_cl_permute.c \ Source/cs_pinv.c Source/cs_dl_pinv.c Source/cs_ci_pinv.c Source/cs_cl_pinv.c \ Source/cs_post.c Source/cs_dl_post.c Source/cs_ci_post.c Source/cs_cl_post.c \ Source/cs_print.c Source/cs_dl_print.c Source/cs_ci_print.c Source/cs_cl_print.c \ Source/cs_pvec.c Source/cs_dl_pvec.c Source/cs_ci_pvec.c Source/cs_cl_pvec.c \ Source/cs_qr.c Source/cs_dl_qr.c Source/cs_ci_qr.c Source/cs_cl_qr.c \ Source/cs_qrsol.c Source/cs_dl_qrsol.c Source/cs_ci_qrsol.c Source/cs_cl_qrsol.c \ Source/cs_randperm.c Source/cs_dl_randperm.c Source/cs_ci_randperm.c Source/cs_cl_randperm.c \ Source/cs_reach.c Source/cs_dl_reach.c Source/cs_ci_reach.c Source/cs_cl_reach.c \ Source/cs_scatter.c Source/cs_dl_scatter.c Source/cs_ci_scatter.c Source/cs_cl_scatter.c \ Source/cs_scc.c Source/cs_dl_scc.c Source/cs_ci_scc.c Source/cs_cl_scc.c \ Source/cs_schol.c Source/cs_dl_schol.c Source/cs_ci_schol.c Source/cs_cl_schol.c \ Source/cs_spsolve.c Source/cs_dl_spsolve.c Source/cs_ci_spsolve.c Source/cs_cl_spsolve.c \ Source/cs_sqr.c Source/cs_dl_sqr.c Source/cs_ci_sqr.c Source/cs_cl_sqr.c \ Source/cs_symperm.c Source/cs_dl_symperm.c Source/cs_ci_symperm.c Source/cs_cl_symperm.c \ Source/cs_tdfs.c Source/cs_dl_tdfs.c Source/cs_ci_tdfs.c Source/cs_cl_tdfs.c \ Source/cs_transpose.c Source/cs_dl_transpose.c Source/cs_ci_transpose.c Source/cs_cl_transpose.c \ Source/cs_updown.c Source/cs_dl_updown.c Source/cs_ci_updown.c Source/cs_cl_updown.c \ Source/cs_usolve.c Source/cs_dl_usolve.c Source/cs_ci_usolve.c Source/cs_cl_usolve.c \ Source/cs_util.c Source/cs_dl_util.c Source/cs_ci_util.c Source/cs_cl_util.c \ Source/cs_utsolve.c Source/cs_dl_utsolve.c Source/cs_ci_utsolve.c Source/cs_cl_utsolve.c \ Source/cxsparse_version.c objects = $(sources:.c=.o) archive = CXSparse.a PKG_CPPFLAGS = -I./Include -I../SuiteSparse_config all : $(archive) $(archive) : $(objects) rm -f $@ $(AR) -cr $@ $(objects) $(RANLIB) $@ .c.o : $(CC) $(PKG_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) -c $< -o $*.o clean : @rm -f $(objects) $(archive) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/�������������������������������������������������������������0000755�0001751�0000144�00000000000�14576344041�017532� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_updown.c�����������������������������������������������0000644�0001751�0000144�00000000606�14552026002�022344� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_updown.c: double, int64_t version of cs_updown //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_updown.c" ��������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_usolve.c��������������������������������������������������0000644�0001751�0000144�00000001300�14552026002�021656� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_usolve: x=U\b where x and b are dense // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* solve Ux=b where x and b are dense. x=b on input, solution on output. */ CS_INT cs_usolve (const cs *U, CS_ENTRY *x) { CS_INT p, j, n, *Up, *Ui ; CS_ENTRY *Ux ; if (!CS_CSC (U) || !x) return (0) ; /* check inputs */ n = U->n ; Up = U->p ; Ui = U->i ; Ux = U->x ; for (j = n-1 ; j >= 0 ; j--) { x [j] /= Ux [Up [j+1]-1] ; for (p = Up [j] ; p < Up [j+1]-1 ; p++) { x [Ui [p]] -= Ux [p] * x [j] ; } } return (1) ; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_lusol.c������������������������������������������������0000644�0001751�0000144�00000000627�14552026002�022170� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_lusol.c: complex, int64_t version of cs_lusol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_lusol.c" ���������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_reach.c������������������������������������������������0000644�0001751�0000144�00000000627�14552026002�022114� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_reach.c: complex, int64_t version of cs_reach //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_reach.c" ���������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_schol.c���������������������������������������������������0000644�0001751�0000144�00000002522�14552026002�021460� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_schol: ordering and symbolic analysis for sparse Cholesky // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* ordering and symbolic analysis for a Cholesky factorization */ css *cs_schol (CS_INT order, const cs *A) { CS_INT n, *c, *post, *P ; cs *C ; css *S ; if (!CS_CSC (A)) return (NULL) ; /* check inputs */ n = A->n ; S = cs_calloc (1, sizeof (css)) ; /* allocate result S */ if (!S) return (NULL) ; /* out of memory */ P = cs_amd (order, A) ; /* P = amd(A+A'), or natural */ S->pinv = cs_pinv (P, n) ; /* find inverse permutation */ cs_free (P) ; if (order && !S->pinv) return (cs_sfree (S)) ; C = cs_symperm (A, S->pinv, 0) ; /* C = spones(triu(A(P,P))) */ S->parent = cs_etree (C, 0) ; /* find etree of C */ post = cs_post (S->parent, n) ; /* postorder the etree */ c = cs_counts (C, S->parent, post, 0) ; /* find column counts of chol(C) */ cs_free (post) ; cs_spfree (C) ; S->cp = cs_malloc (n+1, sizeof (CS_INT)) ; /* allocate result S->cp */ S->unz = S->lnz = cs_cumsum (S->cp, c, n) ; /* find column pointers for L */ cs_free (c) ; return ((S->lnz >= 0) ? S : cs_sfree (S)) ; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_reach.c������������������������������������������������0000644�0001751�0000144�00000000603�14552026002�022107� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_reach.c: double, int64_t version of cs_reach //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_reach.c" �����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_utsolve.c����������������������������������������������0000644�0001751�0000144�00000000615�14552026002�022525� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_utsolve.c: complex, int32_t version of cs_utsolve //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_utsolve.c" �������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dmperm.c��������������������������������������������������0000644�0001751�0000144�00000014706�14552026002�021643� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_dmperm: Dulmage-Mendelsohn permutation // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* breadth-first search for coarse decomposition (C0,C1,R1 or R0,R3,C3) */ static CS_INT cs_bfs (const cs *A, CS_INT n, CS_INT *wi, CS_INT *wj, CS_INT *queue, const CS_INT *imatch, const CS_INT *jmatch, CS_INT mark) { CS_INT *Ap, *Ai, head = 0, tail = 0, j, i, p, j2 ; cs *C ; for (j = 0 ; j < n ; j++) /* place all unmatched nodes in queue */ { if (imatch [j] >= 0) continue ; /* skip j if matched */ wj [j] = 0 ; /* j in set C0 (R0 if transpose) */ queue [tail++] = j ; /* place unmatched col j in queue */ } if (tail == 0) return (1) ; /* quick return if no unmatched nodes */ C = (mark == 1) ? ((cs *) A) : cs_transpose (A, 0) ; if (!C) return (0) ; /* bfs of C=A' to find R3,C3 from R0 */ Ap = C->p ; Ai = C->i ; while (head < tail) /* while queue is not empty */ { j = queue [head++] ; /* get the head of the queue */ for (p = Ap [j] ; p < Ap [j+1] ; p++) { i = Ai [p] ; if (wi [i] >= 0) continue ; /* skip if i is marked */ wi [i] = mark ; /* i in set R1 (C3 if transpose) */ j2 = jmatch [i] ; /* traverse alternating path to j2 */ if (wj [j2] >= 0) continue ;/* skip j2 if it is marked */ wj [j2] = mark ; /* j2 in set C1 (R3 if transpose) */ queue [tail++] = j2 ; /* add j2 to queue */ } } if (mark != 1) cs_spfree (C) ; /* free A' if it was created */ return (1) ; } /* collect matched rows and columns into p and q */ static void cs_matched (CS_INT n, const CS_INT *wj, const CS_INT *imatch, CS_INT *p, CS_INT *q, CS_INT *cc, CS_INT *rr, CS_INT set, CS_INT mark) { CS_INT kc = cc [set], j ; CS_INT kr = rr [set-1] ; for (j = 0 ; j < n ; j++) { if (wj [j] != mark) continue ; /* skip if j is not in C set */ p [kr++] = imatch [j] ; q [kc++] = j ; } cc [set+1] = kc ; rr [set] = kr ; } /* collect unmatched rows into the permutation vector p */ static void cs_unmatched (CS_INT m, const CS_INT *wi, CS_INT *p, CS_INT *rr, CS_INT set) { CS_INT i, kr = rr [set] ; for (i = 0 ; i < m ; i++) if (wi [i] == 0) p [kr++] = i ; rr [set+1] = kr ; } /* return 1 if row i is in R2 */ static CS_INT cs_rprune (CS_INT i, CS_INT j, CS_ENTRY aij, void *other) { CS_INT *rr = (CS_INT *) other ; return (i >= rr [1] && i < rr [2]) ; } /* Given A, compute coarse and then fine dmperm */ csd *cs_dmperm (const cs *A, CS_INT seed) { CS_INT m, n, i, j, k, cnz, nc, *jmatch, *imatch, *wi, *wj, *pinv, *Cp, *Ci, *ps, *rs, nb1, nb2, *p, *q, *cc, *rr, *r, *s, ok ; cs *C ; csd *D, *scc ; /* --- Maximum matching ------------------------------------------------- */ if (!CS_CSC (A)) return (NULL) ; /* check inputs */ m = A->m ; n = A->n ; D = cs_dalloc (m, n) ; /* allocate result */ if (!D) return (NULL) ; p = D->p ; q = D->q ; r = D->r ; s = D->s ; cc = D->cc ; rr = D->rr ; jmatch = cs_maxtrans (A, seed) ; /* max transversal */ imatch = jmatch + m ; /* imatch = inverse of jmatch */ if (!jmatch) return (cs_ddone (D, NULL, jmatch, 0)) ; /* --- Coarse decomposition --------------------------------------------- */ wi = r ; wj = s ; /* use r and s as workspace */ for (j = 0 ; j < n ; j++) wj [j] = -1 ; /* unmark all cols for bfs */ for (i = 0 ; i < m ; i++) wi [i] = -1 ; /* unmark all rows for bfs */ cs_bfs (A, n, wi, wj, q, imatch, jmatch, 1) ; /* find C1, R1 from C0*/ ok = cs_bfs (A, m, wj, wi, p, jmatch, imatch, 3) ; /* find R3, C3 from R0*/ if (!ok) return (cs_ddone (D, NULL, jmatch, 0)) ; cs_unmatched (n, wj, q, cc, 0) ; /* unmatched set C0 */ cs_matched (n, wj, imatch, p, q, cc, rr, 1, 1) ; /* set R1 and C1 */ cs_matched (n, wj, imatch, p, q, cc, rr, 2, -1) ; /* set R2 and C2 */ cs_matched (n, wj, imatch, p, q, cc, rr, 3, 3) ; /* set R3 and C3 */ cs_unmatched (m, wi, p, rr, 3) ; /* unmatched set R0 */ cs_free (jmatch) ; /* --- Fine decomposition ----------------------------------------------- */ pinv = cs_pinv (p, m) ; /* pinv=p' */ if (!pinv) return (cs_ddone (D, NULL, NULL, 0)) ; C = cs_permute (A, pinv, q, 0) ;/* C=A(p,q) (it will hold A(R2,C2)) */ cs_free (pinv) ; if (!C) return (cs_ddone (D, NULL, NULL, 0)) ; Cp = C->p ; nc = cc [3] - cc [2] ; /* delete cols C0, C1, and C3 from C */ if (cc [2] > 0) for (j = cc [2] ; j <= cc [3] ; j++) Cp [j-cc[2]] = Cp [j] ; C->n = nc ; if (rr [2] - rr [1] < m) /* delete rows R0, R1, and R3 from C */ { cs_fkeep (C, cs_rprune, rr) ; cnz = Cp [nc] ; Ci = C->i ; if (rr [1] > 0) for (k = 0 ; k < cnz ; k++) Ci [k] -= rr [1] ; } C->m = nc ; scc = cs_scc (C) ; /* find strongly connected components of C*/ if (!scc) return (cs_ddone (D, C, NULL, 0)) ; /* --- Combine coarse and fine decompositions --------------------------- */ ps = scc->p ; /* C(ps,ps) is the permuted matrix */ rs = scc->r ; /* kth block is rs[k]..rs[k+1]-1 */ nb1 = scc->nb ; /* # of blocks of A(R2,C2) */ for (k = 0 ; k < nc ; k++) wj [k] = q [ps [k] + cc [2]] ; for (k = 0 ; k < nc ; k++) q [k + cc [2]] = wj [k] ; for (k = 0 ; k < nc ; k++) wi [k] = p [ps [k] + rr [1]] ; for (k = 0 ; k < nc ; k++) p [k + rr [1]] = wi [k] ; nb2 = 0 ; /* create the fine block partitions */ r [0] = s [0] = 0 ; if (cc [2] > 0) nb2++ ; /* leading coarse block A (R1, [C0 C1]) */ for (k = 0 ; k < nb1 ; k++) /* coarse block A (R2,C2) */ { r [nb2] = rs [k] + rr [1] ; /* A (R2,C2) splits into nb1 fine blocks */ s [nb2] = rs [k] + cc [2] ; nb2++ ; } if (rr [2] < m) { r [nb2] = rr [2] ; /* trailing coarse block A ([R3 R0], C3) */ s [nb2] = cc [3] ; nb2++ ; } r [nb2] = m ; s [nb2] = n ; D->nb = nb2 ; cs_dfree (scc) ; return (cs_ddone (D, C, NULL, 1)) ; } ����������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_lusol.c���������������������������������������������������0000644�0001751�0000144�00000002037�14552026002�021507� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_lusol: x=A\b using a sparse LU factorization // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* x=A\b where A is unsymmetric; b overwritten with solution */ CS_INT cs_lusol (CS_INT order, const cs *A, CS_ENTRY *b, double tol) { CS_ENTRY *x ; css *S ; csn *N ; CS_INT n, ok ; if (!CS_CSC (A) || !b) return (0) ; /* check inputs */ n = A->n ; S = cs_sqr (order, A, 0) ; /* ordering and symbolic analysis */ N = cs_lu (A, S, tol) ; /* numeric LU factorization */ x = cs_malloc (n, sizeof (CS_ENTRY)) ; /* get workspace */ ok = (S && N && x) ; if (ok) { cs_ipvec (N->pinv, b, x, n) ; /* x = b(p) */ cs_lsolve (N->L, x) ; /* x = L\x */ cs_usolve (N->U, x) ; /* x = U\x */ cs_ipvec (S->q, x, b, n) ; /* b(q) = x */ } cs_free (x) ; cs_sfree (S) ; cs_nfree (N) ; return (ok) ; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_load.c�������������������������������������������������0000644�0001751�0000144�00000000624�14552026002�021746� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_load.c: complex, int64_t version of cs_load //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_load.c" ������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_cholsol.c����������������������������������������������0000644�0001751�0000144�00000000611�14552026002�022467� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_cholsol.c: double, int64_t version of cs_cholsol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_cholsol.c" �����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_add.c��������������������������������������������������0000644�0001751�0000144�00000000621�14552026002�021554� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_add.c: complex, int64_t version of cs_add //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_add.c" ���������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_amd.c��������������������������������������������������0000644�0001751�0000144�00000000601�14552026002�021560� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_amd.c: complex, int32_t version of cs_amd //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_amd.c" �������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_entry.c���������������������������������������������������0000644�0001751�0000144�00000001213�14552026002�021505� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_entry: add an entry to a sparse matrix in triplet-form // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* add an entry to a triplet matrix; return 1 if ok, 0 otherwise */ CS_INT cs_entry (cs *T, CS_INT i, CS_INT j, CS_ENTRY x) { if (!CS_TRIPLET (T) || i < 0 || j < 0) return (0) ; /* check inputs */ if (T->nz >= T->nzmax && !cs_sprealloc (T,2*(T->nzmax))) return (0) ; if (T->x) T->x [T->nz] = x ; T->i [T->nz] = i ; T->p [T->nz++] = j ; T->m = CS_MAX (T->m, i+1) ; T->n = CS_MAX (T->n, j+1) ; return (1) ; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_util.c�������������������������������������������������0000644�0001751�0000144�00000000604�14552026002�021777� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_util.c: complex, int32_t version of cs_util //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_util.c" ����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cholsol.c�������������������������������������������������0000644�0001751�0000144�00000002043�14552026002�022011� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_cholsol: x=A\b using a sparse Cholesky factorization // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* x=A\b where A is symmetric positive definite; b overwritten with solution */ CS_INT cs_cholsol (CS_INT order, const cs *A, CS_ENTRY *b) { CS_ENTRY *x ; css *S ; csn *N ; CS_INT n, ok ; if (!CS_CSC (A) || !b) return (0) ; /* check inputs */ n = A->n ; S = cs_schol (order, A) ; /* ordering and symbolic analysis */ N = cs_chol (A, S) ; /* numeric Cholesky factorization */ x = cs_malloc (n, sizeof (CS_ENTRY)) ; /* get workspace */ ok = (S && N && x) ; if (ok) { cs_ipvec (S->pinv, b, x, n) ; /* x = P*b */ cs_lsolve (N->L, x) ; /* x = L\x */ cs_ltsolve (N->L, x) ; /* x = L'\x */ cs_pvec (S->pinv, x, b, n) ; /* b = P'*x */ } cs_free (x) ; cs_sfree (S) ; cs_nfree (N) ; return (ok) ; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_add.c��������������������������������������������������0000644�0001751�0000144�00000000575�14552026002�021565� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_add.c: double, int64_t version of cs_add //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_add.c" �����������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_counts.c�����������������������������������������������0000644�0001751�0000144�00000000632�14552026002�022341� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_counts.c: complex, int64_t version of cs_counts //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_counts.c" ������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_counts.c��������������������������������������������������0000644�0001751�0000144�00000005766�14552026002�021700� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_counts: column counts for sparse Cholesky // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* column counts of LL'=A or LL'=A'A, given parent & post ordering */ #define HEAD(k,j) (ata ? head [k] : j) #define NEXT(J) (ata ? next [J] : -1) static void init_ata (cs *AT, const CS_INT *post, CS_INT *w, CS_INT **head, CS_INT **next) { CS_INT i, k, p, m = AT->n, n = AT->m, *ATp = AT->p, *ATi = AT->i ; *head = w+4*n, *next = w+5*n+1 ; for (k = 0 ; k < n ; k++) w [post [k]] = k ; /* invert post */ for (i = 0 ; i < m ; i++) { for (k = n, p = ATp[i] ; p < ATp[i+1] ; p++) k = CS_MIN (k, w [ATi[p]]); (*next) [i] = (*head) [k] ; /* place row i in linked list k */ (*head) [k] = i ; } } CS_INT *cs_counts (const cs *A, const CS_INT *parent, const CS_INT *post, CS_INT ata) { CS_INT i, j, k, n, m, J, s, p, q, jleaf, *ATp, *ATi, *maxfirst, *prevleaf, *ancestor, *head = NULL, *next = NULL, *colcount, *w, *first, *delta ; cs *AT ; if (!CS_CSC (A) || !parent || !post) return (NULL) ; /* check inputs */ m = A->m ; n = A->n ; s = 4*n + (ata ? (n+m+1) : 0) ; delta = colcount = cs_malloc (n, sizeof (CS_INT)) ; /* allocate result */ w = cs_malloc (s, sizeof (CS_INT)) ; /* get workspace */ AT = cs_transpose (A, 0) ; /* AT = A' */ if (!AT || !colcount || !w) return (cs_idone (colcount, AT, w, 0)) ; ancestor = w ; maxfirst = w+n ; prevleaf = w+2*n ; first = w+3*n ; for (k = 0 ; k < s ; k++) w [k] = -1 ; /* clear workspace w [0..s-1] */ for (k = 0 ; k < n ; k++) /* find first [j] */ { j = post [k] ; delta [j] = (first [j] == -1) ? 1 : 0 ; /* delta[j]=1 if j is a leaf */ for ( ; j != -1 && first [j] == -1 ; j = parent [j]) first [j] = k ; } ATp = AT->p ; ATi = AT->i ; if (ata) init_ata (AT, post, w, &head, &next) ; for (i = 0 ; i < n ; i++) ancestor [i] = i ; /* each node in its own set */ for (k = 0 ; k < n ; k++) { j = post [k] ; /* j is the kth node in postordered etree */ if (parent [j] != -1) delta [parent [j]]-- ; /* j is not a root */ for (J = HEAD (k,j) ; J != -1 ; J = NEXT (J)) /* J=j for LL'=A case */ { for (p = ATp [J] ; p < ATp [J+1] ; p++) { i = ATi [p] ; q = cs_leaf (i, j, first, maxfirst, prevleaf, ancestor, &jleaf); if (jleaf >= 1) delta [j]++ ; /* A(i,j) is in skeleton */ if (jleaf == 2) delta [q]-- ; /* account for overlap in q */ } } if (parent [j] != -1) ancestor [j] = parent [j] ; } for (j = 0 ; j < n ; j++) /* sum up delta's of each child */ { if (parent [j] != -1) colcount [parent [j]] += colcount [j] ; } return (cs_idone (colcount, AT, w, 1)) ; /* success: free workspace */ } ����������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_randperm.c���������������������������������������������0000644�0001751�0000144�00000000614�14552026002�022637� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_randperm.c: double, int64_t version of cs_randperm //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_randperm.c" ��������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_qrsol.c������������������������������������������������0000644�0001751�0000144�00000000603�14552026002�022165� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_qrsol.c: double, int64_t version of cs_qrsol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_qrsol.c" �����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_transpose.c�����������������������������������������������0000644�0001751�0000144�00000002313�14552026002�022364� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_transpose: transpose a sparse matrix // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* C = A' */ cs *cs_transpose (const cs *A, CS_INT values) { CS_INT p, q, j, *Cp, *Ci, n, m, *Ap, *Ai, *w ; CS_ENTRY *Cx, *Ax ; cs *C ; if (!CS_CSC (A)) return (NULL) ; /* check inputs */ m = A->m ; n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; C = cs_spalloc (n, m, Ap [n], values && Ax, 0) ; /* allocate result */ w = cs_calloc (m, sizeof (CS_INT)) ; /* get workspace */ if (!C || !w) return (cs_done (C, w, NULL, 0)) ; /* out of memory */ Cp = C->p ; Ci = C->i ; Cx = C->x ; for (p = 0 ; p < Ap [n] ; p++) w [Ai [p]]++ ; /* row counts */ cs_cumsum (Cp, w, m) ; /* row pointers */ for (j = 0 ; j < n ; j++) { for (p = Ap [j] ; p < Ap [j+1] ; p++) { Ci [q = w [Ai [p]]++] = j ; /* place A(i,j) as entry C(j,i) */ if (Cx) Cx [q] = (values > 0) ? CS_CONJ (Ax [p]) : Ax [p] ; } } return (cs_done (C, w, NULL, 1)) ; /* success; free w and return C */ } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_multiply.c������������������������������������������������0000644�0001751�0000144�00000003460�14552026002�022231� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_multiply: sparse-times-sparse matrix multiply // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* C = A*B */ cs *cs_multiply (const cs *A, const cs *B) { CS_INT p, j, nz = 0, anz, *Cp, *Ci, *Bp, m, n, bnz, *w, values, *Bi ; CS_ENTRY *x, *Bx, *Cx ; cs *C ; if (!CS_CSC (A) || !CS_CSC (B)) return (NULL) ; /* check inputs */ if (A->n != B->m) return (NULL) ; m = A->m ; anz = A->p [A->n] ; n = B->n ; Bp = B->p ; Bi = B->i ; Bx = B->x ; bnz = Bp [n] ; w = cs_calloc (m, sizeof (CS_INT)) ; /* get workspace */ values = (A->x != NULL) && (Bx != NULL) ; x = values ? cs_malloc (m, sizeof (CS_ENTRY)) : NULL ; /* get workspace */ C = cs_spalloc (m, n, anz + bnz, values, 0) ; /* allocate result */ if (!C || !w || (values && !x)) return (cs_done (C, w, x, 0)) ; Cp = C->p ; for (j = 0 ; j < n ; j++) { if (C->nzmax > (CS_INT_MAX - m) / 2 || /* 2*(C->nzmax)+m overflows */ (nz + m > C->nzmax && !cs_sprealloc (C, 2*(C->nzmax)+m))) { return (cs_done (C, w, x, 0)) ; /* out of memory */ } Ci = C->i ; Cx = C->x ; /* C->i and C->x may be reallocated */ Cp [j] = nz ; /* column j of C starts here */ for (p = Bp [j] ; p < Bp [j+1] ; p++) { nz = cs_scatter (A, Bi [p], Bx ? Bx [p] : 1, w, x, j+1, C, nz) ; } if (values) for (p = Cp [j] ; p < nz ; p++) Cx [p] = x [Ci [p]] ; } Cp [n] = nz ; /* finalize the last column of C */ cs_sprealloc (C, 0) ; /* remove extra space from C */ return (cs_done (C, w, x, 1)) ; /* success; free workspace, return C */ } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_post.c�������������������������������������������������0000644�0001751�0000144�00000000604�14552026002�022007� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_post.c: complex, int32_t version of cs_post //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_post.c" ����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_sqr.c��������������������������������������������������0000644�0001751�0000144�00000000601�14552026002�021624� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_sqr.c: complex, int32_t version of cs_sqr //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_sqr.c" �������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_pvec.c�������������������������������������������������0000644�0001751�0000144�00000000624�14552026002�021764� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_pvec.c: complex, int64_t version of cs_pvec //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_pvec.c" ������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_post.c����������������������������������������������������0000644�0001751�0000144�00000002345�14552026002�021340� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_post: postorder a forest // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* post order a forest */ CS_INT *cs_post (const CS_INT *parent, CS_INT n) { CS_INT j, k = 0, *post, *w, *head, *next, *stack ; if (!parent) return (NULL) ; /* check inputs */ post = cs_malloc (n, sizeof (CS_INT)) ; /* allocate result */ w = cs_malloc (3*n, sizeof (CS_INT)) ; /* get workspace */ if (!w || !post) return (cs_idone (post, NULL, w, 0)) ; head = w ; next = w + n ; stack = w + 2*n ; for (j = 0 ; j < n ; j++) head [j] = -1 ; /* empty linked lists */ for (j = n-1 ; j >= 0 ; j--) /* traverse nodes in reverse order*/ { if (parent [j] == -1) continue ; /* j is a root */ next [j] = head [parent [j]] ; /* add j to list of its parent */ head [parent [j]] = j ; } for (j = 0 ; j < n ; j++) { if (parent [j] != -1) continue ; /* skip j if it is not a root */ k = cs_tdfs (j, k, head, next, post, stack) ; } return (cs_idone (post, NULL, w, 1)) ; /* success; free w, return post */ } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_randperm.c���������������������������������������������0000644�0001751�0000144�00000000620�14552026002�022630� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_randperm.c: complex, int32_t version of cs_randperm //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_randperm.c" ����������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_usolve.c�����������������������������������������������0000644�0001751�0000144�00000000606�14552026002�022345� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_usolve.c: double, int64_t version of cs_usolve //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_usolve.c" ��������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_usolve.c�����������������������������������������������0000644�0001751�0000144�00000000612�14552026002�022336� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_usolve.c: complex, int32_t version of cs_usolve //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_usolve.c" ����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_dfs.c��������������������������������������������������0000644�0001751�0000144�00000000601�14552026002�021573� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_dfs.c: complex, int32_t version of cs_dfs //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_dfs.c" �������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_norm.c�������������������������������������������������0000644�0001751�0000144�00000000600�14552026002�021775� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_norm.c: double, int64_t version of cs_norm //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_norm.c" ��������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_dmperm.c�����������������������������������������������0000644�0001751�0000144�00000000606�14552026002�022314� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_dmperm.c: double, int64_t version of cs_dmperm //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_dmperm.c" ��������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_dfs.c��������������������������������������������������0000644�0001751�0000144�00000000621�14552026002�021600� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_dfs.c: complex, int64_t version of cs_dfs //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_dfs.c" ���������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_lsolve.c�����������������������������������������������0000644�0001751�0000144�00000000612�14552026002�022325� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_lsolve.c: complex, int32_t version of cs_lsolve //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_lsolve.c" ����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_tdfs.c�������������������������������������������������0000644�0001751�0000144�00000000604�14552026002�021762� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_tdfs.c: complex, int32_t version of cs_tdfs //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_tdfs.c" ����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_happly.c�����������������������������������������������0000644�0001751�0000144�00000000606�14552026002�022325� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_happly.c: double, int64_t version of cs_happly //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_happly.c" ��������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_maxtrans.c���������������������������������������������0000644�0001751�0000144�00000000614�14552026002�022664� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_maxtrans.c: double, int64_t version of cs_maxtrans //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_maxtrans.c" ��������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_print.c������������������������������������������������0000644�0001751�0000144�00000000607�14552026002�022161� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_print.c: complex, int32_t version of cs_print //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_print.c" �������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_scc.c��������������������������������������������������0000644�0001751�0000144�00000000601�14552026002�021567� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_scc.c: complex, int32_t version of cs_scc //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_scc.c" �������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_fkeep.c���������������������������������������������������0000644�0001751�0000144�00000002173�14552026002�021444� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_fkeep: keep or drop entries from a sparse matrix // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* drop entries for which fkeep(A(i,j)) is false; return nz if OK, else -1 */ CS_INT cs_fkeep (cs *A, CS_INT (*fkeep) (CS_INT, CS_INT, CS_ENTRY, void *), void *other) { CS_INT j, p, nz = 0, n, *Ap, *Ai ; CS_ENTRY *Ax ; if (!CS_CSC (A) || !fkeep) return (-1) ; /* check inputs */ n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; for (j = 0 ; j < n ; j++) { p = Ap [j] ; /* get current location of col j */ Ap [j] = nz ; /* record new location of col j */ for ( ; p < Ap [j+1] ; p++) { if (fkeep (Ai [p], j, Ax ? Ax [p] : 1, other)) { if (Ax) Ax [nz] = Ax [p] ; /* keep A(i,j) */ Ai [nz++] = Ai [p] ; } } } Ap [n] = nz ; /* finalize A */ cs_sprealloc (A, 0) ; /* remove extra space from A */ return (nz) ; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_ltsolve.c����������������������������������������������0000644�0001751�0000144�00000000635�14552026002�022521� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_ltsolve.c: complex, int64_t version of cs_ltsolve //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_ltsolve.c" ���������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_leaf.c�������������������������������������������������0000644�0001751�0000144�00000000600�14552026002�021731� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_leaf.c: double, int64_t version of cs_leaf //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_leaf.c" ��������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_lu.c���������������������������������������������������0000644�0001751�0000144�00000000572�14552026002�021452� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_lu.c: double, int64_t version of cs_lu //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_lu.c" ��������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_chol.c�������������������������������������������������0000644�0001751�0000144�00000000604�14552026002�021747� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_chol.c: complex, int32_t version of cs_chol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_chol.c" ����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_etree.c������������������������������������������������0000644�0001751�0000144�00000000607�14552026002�022131� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_etree.c: complex, int32_t version of cs_etree //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_etree.c" �������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_print.c���������������������������������������������������0000644�0001751�0000144�00000003715�14552026002�021511� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_print: print a sparse matrix // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" #include /* print a sparse matrix; use %g for integers to avoid differences with CS_INT */ CS_INT cs_print (const cs *A, CS_INT brief) { CS_INT p, j, m, n, nzmax, nz, *Ap, *Ai ; CS_ENTRY *Ax ; if (!A) { Rprintf ("(null)\n") ; return (0) ; } m = A->m ; n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; nzmax = A->nzmax ; nz = A->nz ; Rprintf ("CXSparse Version %d.%d.%d, %s. %s\n", CS_VER, CS_SUBVER, CS_SUBSUB, CS_DATE, CS_COPYRIGHT) ; if (nz < 0) { Rprintf ("%g-by-%g, nzmax: %g nnz: %g, 1-norm: %g\n", (double) m, (double) n, (double) nzmax, (double) (Ap [n]), cs_norm (A)) ; for (j = 0 ; j < n ; j++) { Rprintf (" col %g : locations %g to %g\n", (double) j, (double) (Ap [j]), (double) (Ap [j+1]-1)) ; for (p = Ap [j] ; p < Ap [j+1] ; p++) { Rprintf (" %g : ", (double) (Ai [p])) ; #ifdef CS_COMPLEX Rprintf ("(%g, %g)\n", Ax ? CS_REAL (Ax [p]) : 1, Ax ? CS_IMAG (Ax [p]) : 0) ; #else Rprintf ("%g\n", Ax ? Ax [p] : 1) ; #endif if (brief && p > 20) { Rprintf (" ...\n") ; return (1) ; } } } } else { Rprintf ("triplet: %g-by-%g, nzmax: %g nnz: %g\n", (double) m, (double) n, (double) nzmax, (double) nz) ; for (p = 0 ; p < nz ; p++) { Rprintf (" %g %g : ", (double) (Ai [p]), (double) (Ap [p])) ; #ifdef CS_COMPLEX Rprintf ("(%g, %g)\n", Ax ? CS_REAL (Ax [p]) : 1, Ax ? CS_IMAG (Ax [p]) : 0) ; #else Rprintf ("%g\n", Ax ? Ax [p] : 1) ; #endif if (brief && p > 20) { Rprintf (" ...\n") ; return (1) ; } } } return (1) ; } ���������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_pvec.c�������������������������������������������������0000644�0001751�0000144�00000000600�14552026002�021757� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_pvec.c: double, int64_t version of cs_pvec //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_pvec.c" ��������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_lusol.c������������������������������������������������0000644�0001751�0000144�00000000603�14552026002�022163� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_lusol.c: double, int64_t version of cs_lusol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_lusol.c" �����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_chol.c�������������������������������������������������0000644�0001751�0000144�00000000624�14552026002�021754� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_chol.c: complex, int64_t version of cs_chol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_chol.c" ������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_pinv.c�������������������������������������������������0000644�0001751�0000144�00000000604�14552026002�021776� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_pinv.c: complex, int32_t version of cs_pinv //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_pinv.c" ����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_lsolve.c�����������������������������������������������0000644�0001751�0000144�00000000632�14552026002�022332� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_lsolve.c: complex, int64_t version of cs_lsolve //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_lsolve.c" ������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_norm.c�������������������������������������������������0000644�0001751�0000144�00000000624�14552026002�022002� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_norm.c: complex, int64_t version of cs_norm //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_norm.c" ������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_dfs.c��������������������������������������������������0000644�0001751�0000144�00000000575�14552026002�021611� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_dfs.c: double, int64_t version of cs_dfs //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_dfs.c" �����������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_qrsol.c������������������������������������������������0000644�0001751�0000144�00000000607�14552026002�022165� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_qrsol.c: complex, int32_t version of cs_qrsol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_qrsol.c" �������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_ipvec.c������������������������������������������������0000644�0001751�0000144�00000000603�14552026002�022133� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_ipvec.c: double, int64_t version of cs_ipvec //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_ipvec.c" �����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_symperm.c����������������������������������������������0000644�0001751�0000144�00000000635�14552026002�022525� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_symperm.c: complex, int64_t version of cs_symperm //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_symperm.c" ���������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_counts.c�����������������������������������������������0000644�0001751�0000144�00000000606�14552026002�022343� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_counts.c: double, int64_t version of cs_counts //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_counts.c" ��������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_entry.c������������������������������������������������0000644�0001751�0000144�00000000603�14552026002�022166� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_entry.c: double, int64_t version of cs_entry //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_entry.c" �����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_dmperm.c�����������������������������������������������0000644�0001751�0000144�00000000632�14552026002�022312� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_dmperm.c: complex, int64_t version of cs_dmperm //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_dmperm.c" ������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_pvec.c����������������������������������������������������0000644�0001751�0000144�00000000761�14552026002�021310� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_pvec: permute a dense vector // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* x = b(p), for dense vectors x and b; p=NULL denotes identity */ CS_INT cs_pvec (const CS_INT *p, const CS_ENTRY *b, CS_ENTRY *x, CS_INT n) { CS_INT k ; if (!x || !b) return (0) ; /* check inputs */ for (k = 0 ; k < n ; k++) x [k] = b [p ? p [k] : k] ; return (1) ; } ���������������Matrix/src/SuiteSparse/CXSparse/Source/cs_load.c����������������������������������������������������0000644�0001751�0000144�00000001644�14552026002�021273� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_load: load a triplet matrix from a file // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* load a triplet matrix from a file */ cs *cs_load (FILE *f) { double i, j ; /* use double for integers to avoid csi conflicts */ double x ; #ifdef CS_COMPLEX double xi ; #endif cs *T ; if (!f) return (NULL) ; /* check inputs */ T = cs_spalloc (0, 0, 1, 1, 1) ; /* allocate result */ #ifdef CS_COMPLEX while (fscanf (f, "%lg %lg %lg %lg\n", &i, &j, &x, &xi) == 4) #else while (fscanf (f, "%lg %lg %lg\n", &i, &j, &x) == 3) #endif { #ifdef CS_COMPLEX if (!cs_entry (T, (CS_INT) i, (CS_INT) j, x + xi*I)) return (cs_spfree (T)) ; #else if (!cs_entry (T, (CS_INT) i, (CS_INT) j, x)) return (cs_spfree (T)) ; #endif } return (T) ; } ��������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_malloc.c�����������������������������������������������0000644�0001751�0000144�00000000632�14552026002�022275� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_malloc.c: complex, int64_t version of cs_malloc //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_malloc.c" ������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_etree.c������������������������������������������������0000644�0001751�0000144�00000000627�14552026002�022136� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_etree.c: complex, int64_t version of cs_etree //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_etree.c" ���������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_ipvec.c������������������������������������������������0000644�0001751�0000144�00000000607�14552026002�022133� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_ipvec.c: complex, int32_t version of cs_ipvec //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_ipvec.c" �������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_add.c��������������������������������������������������0000644�0001751�0000144�00000000601�14552026002�021547� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_add.c: complex, int32_t version of cs_add //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_add.c" �������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_droptol.c����������������������������������������������0000644�0001751�0000144�00000000611�14552026002�022507� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_droptol.c: double, int64_t version of cs_droptol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_droptol.c" �����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_lu.c���������������������������������������������������0000644�0001751�0000144�00000000576�14552026002�021452� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_lu.c: complex, int32_t version of cs_lu //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_lu.c" ����������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_dropzeros.c��������������������������������������������0000644�0001751�0000144�00000000643�14552026002�023057� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_dropzeros.c: complex, int64_t version of cs_dropzeros //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_dropzeros.c" ���������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_scatter.c����������������������������������������������0000644�0001751�0000144�00000000635�14552026002�022476� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_scatter.c: complex, int64_t version of cs_scatter //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_scatter.c" ���������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_utsolve.c����������������������������������������������0000644�0001751�0000144�00000000611�14552026002�022525� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_utsolve.c: double, int64_t version of cs_utsolve //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_utsolve.c" �����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_transpose.c��������������������������������������������0000644�0001751�0000144�00000000643�14552026002�023046� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_transpose.c: complex, int64_t version of cs_transpose //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_transpose.c" ���������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_etree.c���������������������������������������������������0000644�0001751�0000144�00000003014�14552026002�021451� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_etree: compute the elimination tree // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* compute the etree of A (using triu(A), or A'A without forming A'A */ CS_INT *cs_etree (const cs *A, CS_INT ata) { CS_INT i, k, p, m, n, inext, *Ap, *Ai, *w, *parent, *ancestor, *prev ; if (!CS_CSC (A)) return (NULL) ; /* check inputs */ m = A->m ; n = A->n ; Ap = A->p ; Ai = A->i ; parent = cs_malloc (n, sizeof (CS_INT)) ; /* allocate result */ w = cs_malloc (n + (ata ? m : 0), sizeof (CS_INT)) ; /* get workspace */ if (!w || !parent) return (cs_idone (parent, NULL, w, 0)) ; ancestor = w ; prev = w + n ; if (ata) for (i = 0 ; i < m ; i++) prev [i] = -1 ; for (k = 0 ; k < n ; k++) { parent [k] = -1 ; /* node k has no parent yet */ ancestor [k] = -1 ; /* nor does k have an ancestor */ for (p = Ap [k] ; p < Ap [k+1] ; p++) { i = ata ? (prev [Ai [p]]) : (Ai [p]) ; for ( ; i != -1 && i < k ; i = inext) /* traverse from i to k */ { inext = ancestor [i] ; /* inext = ancestor of i */ ancestor [i] = k ; /* path compression */ if (inext == -1) parent [i] = k ; /* no anc., parent is k */ } if (ata) prev [Ai [p]] = k ; } } return (cs_idone (parent, NULL, w, 1)) ; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_transpose.c��������������������������������������������0000644�0001751�0000144�00000000623�14552026002�023041� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_transpose.c: complex, int32_t version of cs_transpose //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_transpose.c" �������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_qrsol.c������������������������������������������������0000644�0001751�0000144�00000000627�14552026002�022172� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_qrsol.c: complex, int64_t version of cs_qrsol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_qrsol.c" ���������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_load.c�������������������������������������������������0000644�0001751�0000144�00000000600�14552026002�021741� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_load.c: double, int64_t version of cs_load //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_load.c" ��������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_multiply.c���������������������������������������������0000644�0001751�0000144�00000000614�14552026002�022706� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_multiply.c: double, int64_t version of cs_multiply //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_multiply.c" ��������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_norm.c����������������������������������������������������0000644�0001751�0000144�00000001210�14552026002�021314� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_norm: 1-norm of a sparse matrix // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* 1-norm of a sparse matrix = max (sum (abs (A))), largest column sum */ double cs_norm (const cs *A) { CS_INT p, j, n, *Ap ; CS_ENTRY *Ax ; double norm = 0, s ; if (!CS_CSC (A) || !A->x) return (-1) ; /* check inputs */ n = A->n ; Ap = A->p ; Ax = A->x ; for (j = 0 ; j < n ; j++) { for (s = 0, p = Ap [j] ; p < Ap [j+1] ; p++) s += CS_ABS (Ax [p]) ; norm = CS_MAX (norm, s) ; } return (norm) ; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_compress.c���������������������������������������������0000644�0001751�0000144�00000000614�14552026002�022662� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_compress.c: double, int64_t version of cs_compress //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_compress.c" ��������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dropzeros.c�����������������������������������������������0000644�0001751�0000144�00000000631�14552026002�022376� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_dropzeros: drop zeros from a sparse matrix // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" static CS_INT cs_nonzero (CS_INT i, CS_INT j, CS_ENTRY aij, void *other) { return (aij != 0) ; } CS_INT cs_dropzeros (cs *A) { return (cs_fkeep (A, &cs_nonzero, NULL)) ; /* keep all nonzero entries */ } �������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_sqr.c��������������������������������������������������0000644�0001751�0000144�00000000575�14552026002�021642� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_sqr.c: double, int64_t version of cs_sqr //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_sqr.c" �����������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_print.c������������������������������������������������0000644�0001751�0000144�00000000603�14552026002�022161� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_print.c: double, int64_t version of cs_print //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_print.c" �����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ltsolve.c�������������������������������������������������0000644�0001751�0000144�00000001347�14552026002�022044� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_ltsolve: x=L'\b, back substitution where x and b are dense // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* solve L'x=b where x and b are dense. x=b on input, solution on output. */ CS_INT cs_ltsolve (const cs *L, CS_ENTRY *x) { CS_INT p, j, n, *Lp, *Li ; CS_ENTRY *Lx ; if (!CS_CSC (L) || !x) return (0) ; /* check inputs */ n = L->n ; Lp = L->p ; Li = L->i ; Lx = L->x ; for (j = n-1 ; j >= 0 ; j--) { for (p = Lp [j]+1 ; p < Lp [j+1] ; p++) { x [j] -= CS_CONJ (Lx [p]) * x [Li [p]] ; } x [j] /= CS_CONJ (Lx [Lp [j]]) ; } return (1) ; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_lsolve.c��������������������������������������������������0000644�0001751�0000144�00000001310�14552026002�021646� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_lsolve: x=L\b, forward solve where x and b are dense // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* solve Lx=b where x and b are dense. x=b on input, solution on output. */ CS_INT cs_lsolve (const cs *L, CS_ENTRY *x) { CS_INT p, j, n, *Lp, *Li ; CS_ENTRY *Lx ; if (!CS_CSC (L) || !x) return (0) ; /* check inputs */ n = L->n ; Lp = L->p ; Li = L->i ; Lx = L->x ; for (j = 0 ; j < n ; j++) { x [j] /= Lx [Lp [j]] ; for (p = Lp [j]+1 ; p < Lp [j+1] ; p++) { x [Li [p]] -= Lx [p] * x [j] ; } } return (1) ; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_ltsolve.c����������������������������������������������0000644�0001751�0000144�00000000615�14552026002�022514� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_ltsolve.c: complex, int32_t version of cs_ltsolve //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_ltsolve.c" �������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_compress.c������������������������������������������������0000644�0001751�0000144�00000002254�14552026002�022205� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_compress: convert triplet to sparse compressed-column // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* C = compressed-column form of a triplet matrix T */ cs *cs_compress (const cs *T) { CS_INT m, n, nz, p, k, *Cp, *Ci, *w, *Ti, *Tj ; CS_ENTRY *Cx, *Tx ; cs *C ; if (!CS_TRIPLET (T)) return (NULL) ; /* check inputs */ m = T->m ; n = T->n ; Ti = T->i ; Tj = T->p ; Tx = T->x ; nz = T->nz ; C = cs_spalloc (m, n, nz, Tx != NULL, 0) ; /* allocate result */ w = cs_calloc (n, sizeof (CS_INT)) ; /* get workspace */ if (!C || !w) return (cs_done (C, w, NULL, 0)) ; /* out of memory */ Cp = C->p ; Ci = C->i ; Cx = C->x ; for (k = 0 ; k < nz ; k++) w [Tj [k]]++ ; /* column counts */ cs_cumsum (Cp, w, n) ; /* column pointers */ for (k = 0 ; k < nz ; k++) { Ci [p = w [Tj [k]]++] = Ti [k] ; /* A(i,j) is the pth entry in C */ if (Cx) Cx [p] = Tx [k] ; } return (cs_done (C, w, NULL, 1)) ; /* success; free w and return C */ } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_amd.c�����������������������������������������������������0000644�0001751�0000144�00000040453�14552026002�021116� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_amd: approximate minimum degree // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* clear w */ static CS_INT cs_wclear (CS_INT mark, CS_INT lemax, CS_INT *w, CS_INT n) { CS_INT k ; if (mark < 2 || (mark + lemax < 0)) { for (k = 0 ; k < n ; k++) if (w [k] != 0) w [k] = 1 ; mark = 2 ; } return (mark) ; /* at this point, w [0..n-1] < mark holds */ } /* keep off-diagonal entries; drop diagonal entries */ static CS_INT cs_diag (CS_INT i, CS_INT j, CS_ENTRY aij, void *other) { return (i != j) ; } /* p = amd(A+A') if symmetric is true, or amd(A'A) otherwise */ CS_INT *cs_amd (CS_INT order, const cs *A) /* order 0:natural, 1:Chol, 2:LU, 3:QR */ { cs *C, *A2, *AT ; CS_INT *Cp, *Ci, *last, *W, *len, *nv, *next, *P, *head, *elen, *degree, *w, *hhead, *ATp, *ATi, d, dk, dext, lemax = 0, e, elenk, eln, i, j, k, k1, k2, k3, jlast, ln, dense, nzmax, mindeg = 0, nvi, nvj, nvk, mark, wnvi, ok, cnz, nel = 0, p, p1, p2, p3, p4, pj, pk, pk1, pk2, pn, q, n, m, t ; CS_INT h ; /* --- Construct matrix C ----------------------------------------------- */ if (!CS_CSC (A) || order <= 0 || order > 3) return (NULL) ; /* check */ AT = cs_transpose (A, 0) ; /* compute A' */ if (!AT) return (NULL) ; m = A->m ; n = A->n ; dense = CS_MAX (16, 10 * sqrt ((double) n)) ; /* find dense threshold */ dense = CS_MIN (n-2, dense) ; if (order == 1 && n == m) { C = cs_add (A, AT, 0, 0) ; /* C = A+A' */ } else if (order == 2) { ATp = AT->p ; /* drop dense columns from AT */ ATi = AT->i ; for (p2 = 0, j = 0 ; j < m ; j++) { p = ATp [j] ; /* column j of AT starts here */ ATp [j] = p2 ; /* new column j starts here */ if (ATp [j+1] - p > dense) continue ; /* skip dense col j */ for ( ; p < ATp [j+1] ; p++) ATi [p2++] = ATi [p] ; } ATp [m] = p2 ; /* finalize AT */ A2 = cs_transpose (AT, 0) ; /* A2 = AT' */ C = A2 ? cs_multiply (AT, A2) : NULL ; /* C=A'*A with no dense rows */ cs_spfree (A2) ; } else { C = cs_multiply (AT, A) ; /* C=A'*A */ } cs_spfree (AT) ; if (!C) return (NULL) ; cs_fkeep (C, &cs_diag, NULL) ; /* drop diagonal entries */ Cp = C->p ; cnz = Cp [n] ; P = cs_malloc (n+1, sizeof (CS_INT)) ; /* allocate result */ W = cs_malloc (8*(n+1), sizeof (CS_INT)) ; /* get workspace */ t = cnz + cnz/5 + 2*n ; /* add elbow room to C */ if (!P || !W || !cs_sprealloc (C, t)) return (cs_idone (P, C, W, 0)) ; len = W ; nv = W + (n+1) ; next = W + 2*(n+1) ; head = W + 3*(n+1) ; elen = W + 4*(n+1) ; degree = W + 5*(n+1) ; w = W + 6*(n+1) ; hhead = W + 7*(n+1) ; last = P ; /* use P as workspace for last */ /* --- Initialize quotient graph ---------------------------------------- */ for (k = 0 ; k < n ; k++) len [k] = Cp [k+1] - Cp [k] ; len [n] = 0 ; nzmax = C->nzmax ; Ci = C->i ; for (i = 0 ; i <= n ; i++) { head [i] = -1 ; /* degree list i is empty */ last [i] = -1 ; next [i] = -1 ; hhead [i] = -1 ; /* hash list i is empty */ nv [i] = 1 ; /* node i is just one node */ w [i] = 1 ; /* node i is alive */ elen [i] = 0 ; /* Ek of node i is empty */ degree [i] = len [i] ; /* degree of node i */ } mark = cs_wclear (0, 0, w, n) ; /* clear w */ elen [n] = -2 ; /* n is a dead element */ Cp [n] = -1 ; /* n is a root of assembly tree */ w [n] = 0 ; /* n is a dead element */ /* --- Initialize degree lists ------------------------------------------ */ for (i = 0 ; i < n ; i++) { d = degree [i] ; if (d == 0) /* node i is empty */ { elen [i] = -2 ; /* element i is dead */ nel++ ; Cp [i] = -1 ; /* i is a root of assembly tree */ w [i] = 0 ; } else if (d > dense) /* node i is dense */ { nv [i] = 0 ; /* absorb i into element n */ elen [i] = -1 ; /* node i is dead */ nel++ ; Cp [i] = CS_FLIP (n) ; nv [n]++ ; } else { if (head [d] != -1) last [head [d]] = i ; next [i] = head [d] ; /* put node i in degree list d */ head [d] = i ; } } while (nel < n) /* while (selecting pivots) do */ { /* --- Select node of minimum approximate degree -------------------- */ for (k = -1 ; mindeg < n && (k = head [mindeg]) == -1 ; mindeg++) ; if (next [k] != -1) last [next [k]] = -1 ; head [mindeg] = next [k] ; /* remove k from degree list */ elenk = elen [k] ; /* elenk = |Ek| */ nvk = nv [k] ; /* # of nodes k represents */ nel += nvk ; /* nv[k] nodes of A eliminated */ /* --- Garbage collection ------------------------------------------- */ if (elenk > 0 && cnz + mindeg >= nzmax) { for (j = 0 ; j < n ; j++) { if ((p = Cp [j]) >= 0) /* j is a live node or element */ { Cp [j] = Ci [p] ; /* save first entry of object */ Ci [p] = CS_FLIP (j) ; /* first entry is now CS_FLIP(j) */ } } for (q = 0, p = 0 ; p < cnz ; ) /* scan all of memory */ { if ((j = CS_FLIP (Ci [p++])) >= 0) /* found object j */ { Ci [q] = Cp [j] ; /* restore first entry of object */ Cp [j] = q++ ; /* new pointer to object j */ for (k3 = 0 ; k3 < len [j]-1 ; k3++) Ci [q++] = Ci [p++] ; } } cnz = q ; /* Ci [cnz...nzmax-1] now free */ } /* --- Construct new element ---------------------------------------- */ dk = 0 ; nv [k] = -nvk ; /* flag k as in Lk */ p = Cp [k] ; pk1 = (elenk == 0) ? p : cnz ; /* do in place if elen[k] == 0 */ pk2 = pk1 ; for (k1 = 1 ; k1 <= elenk + 1 ; k1++) { if (k1 > elenk) { e = k ; /* search the nodes in k */ pj = p ; /* list of nodes starts at Ci[pj]*/ ln = len [k] - elenk ; /* length of list of nodes in k */ } else { e = Ci [p++] ; /* search the nodes in e */ pj = Cp [e] ; ln = len [e] ; /* length of list of nodes in e */ } for (k2 = 1 ; k2 <= ln ; k2++) { i = Ci [pj++] ; if ((nvi = nv [i]) <= 0) continue ; /* node i dead, or seen */ dk += nvi ; /* degree[Lk] += size of node i */ nv [i] = -nvi ; /* negate nv[i] to denote i in Lk*/ Ci [pk2++] = i ; /* place i in Lk */ if (next [i] != -1) last [next [i]] = last [i] ; if (last [i] != -1) /* remove i from degree list */ { next [last [i]] = next [i] ; } else { head [degree [i]] = next [i] ; } } if (e != k) { Cp [e] = CS_FLIP (k) ; /* absorb e into k */ w [e] = 0 ; /* e is now a dead element */ } } if (elenk != 0) cnz = pk2 ; /* Ci [cnz...nzmax] is free */ degree [k] = dk ; /* external degree of k - |Lk\i| */ Cp [k] = pk1 ; /* element k is in Ci[pk1..pk2-1] */ len [k] = pk2 - pk1 ; elen [k] = -2 ; /* k is now an element */ /* --- Find set differences ----------------------------------------- */ mark = cs_wclear (mark, lemax, w, n) ; /* clear w if necessary */ for (pk = pk1 ; pk < pk2 ; pk++) /* scan 1: find |Le\Lk| */ { i = Ci [pk] ; if ((eln = elen [i]) <= 0) continue ;/* skip if elen[i] empty */ nvi = -nv [i] ; /* nv [i] was negated */ wnvi = mark - nvi ; for (p = Cp [i] ; p <= Cp [i] + eln - 1 ; p++) /* scan Ei */ { e = Ci [p] ; if (w [e] >= mark) { w [e] -= nvi ; /* decrement |Le\Lk| */ } else if (w [e] != 0) /* ensure e is a live element */ { w [e] = degree [e] + wnvi ; /* 1st time e seen in scan 1 */ } } } /* --- Degree update ------------------------------------------------ */ for (pk = pk1 ; pk < pk2 ; pk++) /* scan2: degree update */ { i = Ci [pk] ; /* consider node i in Lk */ p1 = Cp [i] ; p2 = p1 + elen [i] - 1 ; pn = p1 ; for (h = 0, d = 0, p = p1 ; p <= p2 ; p++) /* scan Ei */ { e = Ci [p] ; if (w [e] != 0) /* e is an unabsorbed element */ { dext = w [e] - mark ; /* dext = |Le\Lk| */ if (dext > 0) { d += dext ; /* sum up the set differences */ Ci [pn++] = e ; /* keep e in Ei */ h += e ; /* compute the hash of node i */ } else { Cp [e] = CS_FLIP (k) ; /* aggressive absorb. e->k */ w [e] = 0 ; /* e is a dead element */ } } } elen [i] = pn - p1 + 1 ; /* elen[i] = |Ei| */ p3 = pn ; p4 = p1 + len [i] ; for (p = p2 + 1 ; p < p4 ; p++) /* prune edges in Ai */ { j = Ci [p] ; if ((nvj = nv [j]) <= 0) continue ; /* node j dead or in Lk */ d += nvj ; /* degree(i) += |j| */ Ci [pn++] = j ; /* place j in node list of i */ h += j ; /* compute hash for node i */ } if (d == 0) /* check for mass elimination */ { Cp [i] = CS_FLIP (k) ; /* absorb i into k */ nvi = -nv [i] ; dk -= nvi ; /* |Lk| -= |i| */ nvk += nvi ; /* |k| += nv[i] */ nel += nvi ; nv [i] = 0 ; elen [i] = -1 ; /* node i is dead */ } else { degree [i] = CS_MIN (degree [i], d) ; /* update degree(i) */ Ci [pn] = Ci [p3] ; /* move first node to end */ Ci [p3] = Ci [p1] ; /* move 1st el. to end of Ei */ Ci [p1] = k ; /* add k as 1st element in of Ei */ len [i] = pn - p1 + 1 ; /* new len of adj. list of node i */ h = ((h<0) ? (-h):h) % n ; /* finalize hash of i */ next [i] = hhead [h] ; /* place i in hash bucket */ hhead [h] = i ; last [i] = h ; /* save hash of i in last[i] */ } } /* scan2 is done */ degree [k] = dk ; /* finalize |Lk| */ lemax = CS_MAX (lemax, dk) ; mark = cs_wclear (mark+lemax, lemax, w, n) ; /* clear w */ /* --- Supernode detection ------------------------------------------ */ for (pk = pk1 ; pk < pk2 ; pk++) { i = Ci [pk] ; if (nv [i] >= 0) continue ; /* skip if i is dead */ h = last [i] ; /* scan hash bucket of node i */ i = hhead [h] ; hhead [h] = -1 ; /* hash bucket will be empty */ for ( ; i != -1 && next [i] != -1 ; i = next [i], mark++) { ln = len [i] ; eln = elen [i] ; for (p = Cp [i]+1 ; p <= Cp [i] + ln-1 ; p++) w [Ci [p]] = mark; jlast = i ; for (j = next [i] ; j != -1 ; ) /* compare i with all j */ { ok = (len [j] == ln) && (elen [j] == eln) ; for (p = Cp [j] + 1 ; ok && p <= Cp [j] + ln - 1 ; p++) { if (w [Ci [p]] != mark) ok = 0 ; /* compare i and j*/ } if (ok) /* i and j are identical */ { Cp [j] = CS_FLIP (i) ; /* absorb j into i */ nv [i] += nv [j] ; nv [j] = 0 ; elen [j] = -1 ; /* node j is dead */ j = next [j] ; /* delete j from hash bucket */ next [jlast] = j ; } else { jlast = j ; /* j and i are different */ j = next [j] ; } } } } /* --- Finalize new element------------------------------------------ */ for (p = pk1, pk = pk1 ; pk < pk2 ; pk++) /* finalize Lk */ { i = Ci [pk] ; if ((nvi = -nv [i]) <= 0) continue ;/* skip if i is dead */ nv [i] = nvi ; /* restore nv[i] */ d = degree [i] + dk - nvi ; /* compute external degree(i) */ d = CS_MIN (d, n - nel - nvi) ; if (head [d] != -1) last [head [d]] = i ; next [i] = head [d] ; /* put i back in degree list */ last [i] = -1 ; head [d] = i ; mindeg = CS_MIN (mindeg, d) ; /* find new minimum degree */ degree [i] = d ; Ci [p++] = i ; /* place i in Lk */ } nv [k] = nvk ; /* # nodes absorbed into k */ if ((len [k] = p-pk1) == 0) /* length of adj list of element k*/ { Cp [k] = -1 ; /* k is a root of the tree */ w [k] = 0 ; /* k is now a dead element */ } if (elenk != 0) cnz = p ; /* free unused space in Lk */ } /* --- Postordering ----------------------------------------------------- */ for (i = 0 ; i < n ; i++) Cp [i] = CS_FLIP (Cp [i]) ;/* fix assembly tree */ for (j = 0 ; j <= n ; j++) head [j] = -1 ; for (j = n ; j >= 0 ; j--) /* place unordered nodes in lists */ { if (nv [j] > 0) continue ; /* skip if j is an element */ next [j] = head [Cp [j]] ; /* place j in list of its parent */ head [Cp [j]] = j ; } for (e = n ; e >= 0 ; e--) /* place elements in lists */ { if (nv [e] <= 0) continue ; /* skip unless e is an element */ if (Cp [e] != -1) { next [e] = head [Cp [e]] ; /* place e in list of its parent */ head [Cp [e]] = e ; } } for (k = 0, i = 0 ; i <= n ; i++) /* postorder the assembly tree */ { if (Cp [i] == -1) k = cs_tdfs (i, k, head, next, P, w) ; } return (cs_idone (P, C, W, 1)) ; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_randperm.c������������������������������������������������0000644�0001751�0000144�00000002176�14552026002�022165� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_randperm: generate a random permutation // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" #include /* return a random permutation vector, the identity perm, or p = n-1:-1:0. * seed = -1 means p = n-1:-1:0. seed = 0 means p = identity. otherwise * p = random permutation. */ CS_INT *cs_randperm (CS_INT n, CS_INT seed) { CS_INT *p, k, j, t ; if (seed == 0) return (NULL) ; /* return p = NULL (identity) */ p = cs_malloc (n, sizeof (CS_INT)) ; /* allocate result */ if (!p) return (NULL) ; /* out of memory */ for (k = 0 ; k < n ; k++) p [k] = n-k-1 ; if (seed == -1) return (p) ; /* return reverse permutation */ GetRNGstate(); srand (seed) ; /* get new random number seed */ for (k = 0 ; k < n ; k++) { j = k + (rand ( ) % (n-k)) ; /* j = rand integer in range k to n-1 */ t = p [j] ; /* swap p[k] and p[j] */ p [j] = p [k] ; p [k] = t ; } PutRNGstate(); return (p) ; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_permute.c����������������������������������������������0000644�0001751�0000144�00000000615�14552026002�022505� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_permute.c: complex, int32_t version of cs_permute //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_permute.c" �������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_scc.c��������������������������������������������������0000644�0001751�0000144�00000000575�14552026002�021605� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_scc.c: double, int64_t version of cs_scc //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_scc.c" �����������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_ereach.c�����������������������������������������������0000644�0001751�0000144�00000000632�14552026002�022255� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_ereach.c: complex, int64_t version of cs_ereach //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_ereach.c" ������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_tdfs.c�������������������������������������������������0000644�0001751�0000144�00000000624�14552026002�021767� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_tdfs.c: complex, int64_t version of cs_tdfs //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_tdfs.c" ������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_leaf.c�������������������������������������������������0000644�0001751�0000144�00000000604�14552026002�021731� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_leaf.c: complex, int32_t version of cs_leaf //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_leaf.c" ����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cumsum.c��������������������������������������������������0000644�0001751�0000144�00000001343�14552026002�021661� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_cumsum: cumulative sum // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* p [0..n] = cumulative sum of c [0..n-1], and then copy p [0..n-1] into c */ double cs_cumsum (CS_INT *p, CS_INT *c, CS_INT n) { CS_INT i, nz = 0 ; double nz2 = 0 ; if (!p || !c) return (-1) ; /* check inputs */ for (i = 0 ; i < n ; i++) { p [i] = nz ; nz += c [i] ; nz2 += c [i] ; /* also in double to avoid CS_INT overflow */ c [i] = p [i] ; /* also copy p[0..n-1] back into c[0..n-1]*/ } p [n] = nz ; return (nz2) ; /* return sum (c [0..n-1]) */ } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_ereach.c�����������������������������������������������0000644�0001751�0000144�00000000606�14552026002�022257� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_ereach.c: double, int64_t version of cs_ereach //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_ereach.c" ��������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_dropzeros.c��������������������������������������������0000644�0001751�0000144�00000000623�14552026002�023052� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_dropzeros.c: complex, int32_t version of cs_dropzeros //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_dropzeros.c" �������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_entry.c������������������������������������������������0000644�0001751�0000144�00000000607�14552026002�022166� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_entry.c: complex, int32_t version of cs_entry //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_entry.c" �������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_droptol.c����������������������������������������������0000644�0001751�0000144�00000000615�14552026002�022507� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_droptol.c: complex, int32_t version of cs_droptol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_droptol.c" �������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_dmperm.c�����������������������������������������������0000644�0001751�0000144�00000000612�14552026002�022305� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_dmperm.c: complex, int32_t version of cs_dmperm //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_dmperm.c" ����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_tdfs.c����������������������������������������������������0000644�0001751�0000144�00000002131�14552026002�021304� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_tdfs: depth-first search of a tree // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* depth-first search and postorder of a tree rooted at node j */ CS_INT cs_tdfs (CS_INT j, CS_INT k, CS_INT *head, const CS_INT *next, CS_INT *post, CS_INT *stack) { CS_INT i, p, top = 0 ; if (!head || !next || !post || !stack) return (-1) ; /* check inputs */ stack [0] = j ; /* place j on the stack */ while (top >= 0) /* while (stack is not empty) */ { p = stack [top] ; /* p = top of stack */ i = head [p] ; /* i = youngest child of p */ if (i == -1) { top-- ; /* p has no unordered children left */ post [k++] = p ; /* node p is the kth postordered node */ } else { head [p] = next [i] ; /* remove i from children of p */ stack [++top] = i ; /* start dfs on child node i */ } } return (k) ; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_counts.c�����������������������������������������������0000644�0001751�0000144�00000000612�14552026002�022334� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_counts.c: complex, int32_t version of cs_counts //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_counts.c" ����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_util.c�������������������������������������������������0000644�0001751�0000144�00000000624�14552026002�022004� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_util.c: complex, int64_t version of cs_util //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_util.c" ������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_multiply.c���������������������������������������������0000644�0001751�0000144�00000000620�14552026002�022677� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_multiply.c: complex, int32_t version of cs_multiply //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_multiply.c" ����������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_sqr.c��������������������������������������������������0000644�0001751�0000144�00000000621�14552026002�021631� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_sqr.c: complex, int64_t version of cs_sqr //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_sqr.c" ���������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_qr.c���������������������������������������������������0000644�0001751�0000144�00000000576�14552026002�021454� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_qr.c: complex, int32_t version of cs_qr //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_qr.c" ����������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_cumsum.c�����������������������������������������������0000644�0001751�0000144�00000000606�14552026002�022341� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_cumsum.c: double, int64_t version of cs_cumsum //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_cumsum.c" ��������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_util.c����������������������������������������������������0000644�0001751�0000144�00000010413�14552026002�021323� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_util: sparse matrix utilities // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* allocate a sparse matrix (triplet form or compressed-column form) */ cs *cs_spalloc (CS_INT m, CS_INT n, CS_INT nzmax, CS_INT values, CS_INT triplet) { cs *A = cs_calloc (1, sizeof (cs)) ; /* allocate the cs struct */ if (!A) return (NULL) ; /* out of memory */ A->m = m ; /* define dimensions and nzmax */ A->n = n ; A->nzmax = nzmax = CS_MAX (nzmax, 1) ; A->nz = triplet ? 0 : -1 ; /* allocate triplet or comp.col */ A->p = cs_malloc (triplet ? nzmax : n+1, sizeof (CS_INT)) ; A->i = cs_malloc (nzmax, sizeof (CS_INT)) ; A->x = values ? cs_malloc (nzmax, sizeof (CS_ENTRY)) : NULL ; return ((!A->p || !A->i || (values && !A->x)) ? cs_spfree (A) : A) ; } /* change the max # of entries sparse matrix */ CS_INT cs_sprealloc (cs *A, CS_INT nzmax) { CS_INT ok, oki, okj = 1, okx = 1 ; if (!A) return (0) ; if (nzmax <= 0) nzmax = (CS_CSC (A)) ? (A->p [A->n]) : A->nz ; nzmax = CS_MAX (nzmax, 1) ; A->i = cs_realloc (A->i, nzmax, sizeof (CS_INT), &oki) ; if (CS_TRIPLET (A)) A->p = cs_realloc (A->p, nzmax, sizeof (CS_INT), &okj) ; if (A->x) A->x = cs_realloc (A->x, nzmax, sizeof (CS_ENTRY), &okx) ; ok = (oki && okj && okx) ; if (ok) A->nzmax = nzmax ; return (ok) ; } /* free a sparse matrix */ cs *cs_spfree (cs *A) { if (!A) return (NULL) ; /* do nothing if A already NULL */ cs_free (A->p) ; cs_free (A->i) ; cs_free (A->x) ; return ((cs *) cs_free (A)) ; /* free the cs struct and return NULL */ } /* free a numeric factorization */ csn *cs_nfree (csn *N) { if (!N) return (NULL) ; /* do nothing if N already NULL */ cs_spfree (N->L) ; cs_spfree (N->U) ; cs_free (N->pinv) ; cs_free (N->B) ; return ((csn *) cs_free (N)) ; /* free the csn struct and return NULL */ } /* free a symbolic factorization */ css *cs_sfree (css *S) { if (!S) return (NULL) ; /* do nothing if S already NULL */ cs_free (S->pinv) ; cs_free (S->q) ; cs_free (S->parent) ; cs_free (S->cp) ; cs_free (S->leftmost) ; return ((css *) cs_free (S)) ; /* free the css struct and return NULL */ } /* allocate a cs_dmperm or cs_scc result */ csd *cs_dalloc (CS_INT m, CS_INT n) { csd *D ; D = cs_calloc (1, sizeof (csd)) ; if (!D) return (NULL) ; D->p = cs_malloc (m, sizeof (CS_INT)) ; D->r = cs_malloc (m+6, sizeof (CS_INT)) ; D->q = cs_malloc (n, sizeof (CS_INT)) ; D->s = cs_malloc (n+6, sizeof (CS_INT)) ; return ((!D->p || !D->r || !D->q || !D->s) ? cs_dfree (D) : D) ; } /* free a cs_dmperm or cs_scc result */ csd *cs_dfree (csd *D) { if (!D) return (NULL) ; /* do nothing if D already NULL */ cs_free (D->p) ; cs_free (D->q) ; cs_free (D->r) ; cs_free (D->s) ; return ((csd *) cs_free (D)) ; /* free the csd struct and return NULL */ } /* free workspace and return a sparse matrix result */ cs *cs_done (cs *C, void *w, void *x, CS_INT ok) { cs_free (w) ; /* free workspace */ cs_free (x) ; return (ok ? C : cs_spfree (C)) ; /* return result if OK, else free it */ } /* free workspace and return CS_INT array result */ CS_INT *cs_idone (CS_INT *p, cs *C, void *w, CS_INT ok) { cs_spfree (C) ; /* free temporary matrix */ cs_free (w) ; /* free workspace */ return (ok ? p : (CS_INT *) cs_free (p)) ; /* return result, or free it */ } /* free workspace and return a numeric factorization (Cholesky, LU, or QR) */ csn *cs_ndone (csn *N, cs *C, void *w, void *x, CS_INT ok) { cs_spfree (C) ; /* free temporary matrix */ cs_free (w) ; /* free workspace */ cs_free (x) ; return (ok ? N : cs_nfree (N)) ; /* return result if OK, else free it */ } /* free workspace and return a csd result */ csd *cs_ddone (csd *D, cs *C, void *w, CS_INT ok) { cs_spfree (C) ; /* free temporary matrix */ cs_free (w) ; /* free workspace */ return (ok ? D : cs_dfree (D)) ; /* return result if OK, else free it */ } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_post.c�������������������������������������������������0000644�0001751�0000144�00000000624�14552026002�022014� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_post.c: complex, int64_t version of cs_post //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_post.c" ������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_cumsum.c�����������������������������������������������0000644�0001751�0000144�00000000632�14552026002�022337� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_cumsum.c: complex, int64_t version of cs_cumsum //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_cumsum.c" ������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dfs.c�����������������������������������������������������0000644�0001751�0000144�00000003416�14552026002�021127� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_dfs: depth-first search // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* depth-first-search of the graph of a matrix, starting at node j */ CS_INT cs_dfs (CS_INT j, cs *G, CS_INT top, CS_INT *xi, CS_INT *pstack, const CS_INT *pinv) { CS_INT i, p, p2, done, jnew, head = 0, *Gp, *Gi ; if (!CS_CSC (G) || !xi || !pstack) return (-1) ; /* check inputs */ Gp = G->p ; Gi = G->i ; xi [0] = j ; /* initialize the recursion stack */ while (head >= 0) { j = xi [head] ; /* get j from the top of the recursion stack */ jnew = pinv ? (pinv [j]) : j ; if (!CS_MARKED (Gp, j)) { CS_MARK (Gp, j) ; /* mark node j as visited */ pstack [head] = (jnew < 0) ? 0 : CS_UNFLIP (Gp [jnew]) ; } done = 1 ; /* node j done if no unvisited neighbors */ p2 = (jnew < 0) ? 0 : CS_UNFLIP (Gp [jnew+1]) ; for (p = pstack [head] ; p < p2 ; p++) /* examine all neighbors of j */ { i = Gi [p] ; /* consider neighbor node i */ if (CS_MARKED (Gp, i)) continue ; /* skip visited node i */ pstack [head] = p ; /* pause depth-first search of node j */ xi [++head] = i ; /* start dfs at node i */ done = 0 ; /* node j is not done */ break ; /* break, to start dfs (i) */ } if (done) /* depth-first search at node j is done */ { head-- ; /* remove j from the recursion stack */ xi [--top] = j ; /* and place in the output stack */ } } return (top) ; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ipvec.c���������������������������������������������������0000644�0001751�0000144�00000000755�14552026002�021464� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_ipvec: permute a vector // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* x(p) = b, for dense vectors x and b; p=NULL denotes identity */ CS_INT cs_ipvec (const CS_INT *p, const CS_ENTRY *b, CS_ENTRY *x, CS_INT n) { CS_INT k ; if (!x || !b) return (0) ; /* check inputs */ for (k = 0 ; k < n ; k++) x [p ? p [k] : k] = b [k] ; return (1) ; } �������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_lsolve.c�����������������������������������������������0000644�0001751�0000144�00000000606�14552026002�022334� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_lsolve.c: double, int64_t version of cs_lsolve //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_lsolve.c" ��������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_reach.c������������������������������������������������0000644�0001751�0000144�00000000607�14552026002�022107� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_reach.c: complex, int32_t version of cs_reach //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_reach.c" �������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_chol.c����������������������������������������������������0000644�0001751�0000144�00000005752�14552026002�021305� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_chol: sparse Cholesky factorization // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* L = chol (A, [pinv parent cp]), pinv is optional */ csn *cs_chol (const cs *A, const css *S) { CS_ENTRY d, lki, *Lx, *x, *Cx ; CS_INT top, i, p, k, n, *Li, *Lp, *cp, *pinv, *s, *c, *parent, *Cp, *Ci ; cs *L, *C, *E ; csn *N ; if (!CS_CSC (A) || !S || !S->cp || !S->parent) return (NULL) ; n = A->n ; N = cs_calloc (1, sizeof (csn)) ; /* allocate result */ c = cs_malloc (2*n, sizeof (CS_INT)) ; /* get CS_INT workspace */ x = cs_malloc (n, sizeof (CS_ENTRY)) ; /* get CS_ENTRY workspace */ cp = S->cp ; pinv = S->pinv ; parent = S->parent ; C = pinv ? cs_symperm (A, pinv, 1) : ((cs *) A) ; E = pinv ? C : NULL ; /* E is alias for A, or a copy E=A(p,p) */ if (!N || !c || !x || !C) return (cs_ndone (N, E, c, x, 0)) ; s = c + n ; Cp = C->p ; Ci = C->i ; Cx = C->x ; N->L = L = cs_spalloc (n, n, cp [n], 1, 0) ; /* allocate result */ if (!L) return (cs_ndone (N, E, c, x, 0)) ; Lp = L->p ; Li = L->i ; Lx = L->x ; for (k = 0 ; k < n ; k++) Lp [k] = c [k] = cp [k] ; for (k = 0 ; k < n ; k++) /* compute L(k,:) for L*L' = C */ { /* --- Nonzero pattern of L(k,:) ------------------------------------ */ top = cs_ereach (C, k, parent, s, c) ; /* find pattern of L(k,:) */ x [k] = 0 ; /* x (0:k) is now zero */ for (p = Cp [k] ; p < Cp [k+1] ; p++) /* x = full(triu(C(:,k))) */ { if (Ci [p] <= k) x [Ci [p]] = Cx [p] ; } d = x [k] ; /* d = C(k,k) */ x [k] = 0 ; /* clear x for k+1st iteration */ /* --- Triangular solve --------------------------------------------- */ for ( ; top < n ; top++) /* solve L(0:k-1,0:k-1) * x = C(:,k) */ { i = s [top] ; /* s [top..n-1] is pattern of L(k,:) */ lki = x [i] / Lx [Lp [i]] ; /* L(k,i) = x (i) / L(i,i) */ x [i] = 0 ; /* clear x for k+1st iteration */ for (p = Lp [i] + 1 ; p < c [i] ; p++) { x [Li [p]] -= Lx [p] * lki ; } d -= lki * CS_CONJ (lki) ; /* d = d - L(k,i)*L(k,i) */ p = c [i]++ ; Li [p] = k ; /* store L(k,i) in column i */ Lx [p] = CS_CONJ (lki) ; } /* --- Compute L(k,k) ----------------------------------------------- */ if (CS_REAL (d) <= 0 || CS_IMAG (d) != 0) return (cs_ndone (N, E, c, x, 0)) ; /* not pos def */ p = c [k]++ ; Li [p] = k ; /* store L(k,k) = sqrt (d) in column k */ Lx [p] = sqrt (d) ; } Lp [n] = cp [n] ; /* finalize L */ return (cs_ndone (N, E, c, x, 1)) ; /* success: free E,s,x; return N */ } ����������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_norm.c�������������������������������������������������0000644�0001751�0000144�00000000604�14552026002�021775� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_norm.c: complex, int32_t version of cs_norm //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_norm.c" ����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_qr.c������������������������������������������������������0000644�0001751�0000144�00000007154�14552026002�021000� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_qr: sparse QR factorization // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* sparse QR factorization [V,beta,pinv,R] = qr (A) */ csn *cs_qr (const cs *A, const css *S) { CS_ENTRY *Rx, *Vx, *Ax, *x ; double *Beta ; CS_INT i, k, p, n, vnz, p1, top, m2, len, col, rnz, *s, *leftmost, *Ap, *Ai, *parent, *Rp, *Ri, *Vp, *Vi, *w, *pinv, *q ; cs *R, *V ; csn *N ; if (!CS_CSC (A) || !S) return (NULL) ; n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; q = S->q ; parent = S->parent ; pinv = S->pinv ; m2 = S->m2 ; vnz = S->lnz ; rnz = S->unz ; leftmost = S->leftmost ; w = cs_malloc (m2+n, sizeof (CS_INT)) ; /* get CS_INT workspace */ x = cs_malloc (m2, sizeof (CS_ENTRY)) ; /* get CS_ENTRY workspace */ N = cs_calloc (1, sizeof (csn)) ; /* allocate result */ if (!w || !x || !N) return (cs_ndone (N, NULL, w, x, 0)) ; s = w + m2 ; /* s is size n */ for (k = 0 ; k < m2 ; k++) x [k] = 0 ; /* clear workspace x */ N->L = V = cs_spalloc (m2, n, vnz, 1, 0) ; /* allocate result V */ N->U = R = cs_spalloc (m2, n, rnz, 1, 0) ; /* allocate result R */ N->B = Beta = cs_malloc (n, sizeof (double)) ; /* allocate result Beta */ if (!R || !V || !Beta) return (cs_ndone (N, NULL, w, x, 0)) ; Rp = R->p ; Ri = R->i ; Rx = R->x ; Vp = V->p ; Vi = V->i ; Vx = V->x ; for (i = 0 ; i < m2 ; i++) w [i] = -1 ; /* clear w, to mark nodes */ rnz = 0 ; vnz = 0 ; for (k = 0 ; k < n ; k++) /* compute V and R */ { Rp [k] = rnz ; /* R(:,k) starts here */ Vp [k] = p1 = vnz ; /* V(:,k) starts here */ w [k] = k ; /* add V(k,k) to pattern of V */ Vi [vnz++] = k ; top = n ; col = q ? q [k] : k ; for (p = Ap [col] ; p < Ap [col+1] ; p++) /* find R(:,k) pattern */ { i = leftmost [Ai [p]] ; /* i = min(find(A(i,q))) */ for (len = 0 ; w [i] != k ; i = parent [i]) /* traverse up to k */ { s [len++] = i ; w [i] = k ; } while (len > 0) s [--top] = s [--len] ; /* push path on stack */ i = pinv [Ai [p]] ; /* i = permuted row of A(:,col) */ x [i] = Ax [p] ; /* x (i) = A(:,col) */ if (i > k && w [i] < k) /* pattern of V(:,k) = x (k+1:m) */ { Vi [vnz++] = i ; /* add i to pattern of V(:,k) */ w [i] = k ; } } for (p = top ; p < n ; p++) /* for each i in pattern of R(:,k) */ { i = s [p] ; /* R(i,k) is nonzero */ cs_happly (V, i, Beta [i], x) ; /* apply (V(i),Beta(i)) to x */ Ri [rnz] = i ; /* R(i,k) = x(i) */ Rx [rnz++] = x [i] ; x [i] = 0 ; if (parent [i] == k) vnz = cs_scatter (V, i, 0, w, NULL, k, V, vnz); } for (p = p1 ; p < vnz ; p++) /* gather V(:,k) = x */ { Vx [p] = x [Vi [p]] ; x [Vi [p]] = 0 ; } Ri [rnz] = k ; /* R(k,k) = norm (x) */ Rx [rnz++] = cs_house (Vx+p1, Beta+k, vnz-p1) ; /* [v,beta]=house(x) */ } Rp [n] = rnz ; /* finalize R */ Vp [n] = vnz ; /* finalize V */ return (cs_ndone (N, NULL, w, x, 1)) ; /* success */ } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_house.c������������������������������������������������0000644�0001751�0000144�00000000607�14552026002�022150� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_house.c: complex, int32_t version of cs_house //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_house.c" �������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_cumsum.c�����������������������������������������������0000644�0001751�0000144�00000000612�14552026002�022332� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_cumsum.c: complex, int32_t version of cs_cumsum //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_cumsum.c" ����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_happly.c��������������������������������������������������0000644�0001751�0000144�00000001435�14552026002�021647� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_happly: apply a Householder transformation to a vector // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* apply the ith Householder vector to x */ CS_INT cs_happly (const cs *V, CS_INT i, double beta, CS_ENTRY *x) { CS_INT p, *Vp, *Vi ; CS_ENTRY *Vx, tau = 0 ; if (!CS_CSC (V) || !x) return (0) ; /* check inputs */ Vp = V->p ; Vi = V->i ; Vx = V->x ; for (p = Vp [i] ; p < Vp [i+1] ; p++) /* tau = v'*x */ { tau += CS_CONJ (Vx [p]) * x [Vi [p]] ; } tau *= beta ; /* tau = beta*(v'*x) */ for (p = Vp [i] ; p < Vp [i+1] ; p++) /* x = x - v*tau */ { x [Vi [p]] -= Vx [p] * tau ; } return (1) ; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_permute.c����������������������������������������������0000644�0001751�0000144�00000000635�14552026002�022512� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_permute.c: complex, int64_t version of cs_permute //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_permute.c" ���������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_scc.c��������������������������������������������������0000644�0001751�0000144�00000000621�14552026002�021574� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_scc.c: complex, int64_t version of cs_scc //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_scc.c" ���������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_pinv.c�������������������������������������������������0000644�0001751�0000144�00000000624�14552026002�022003� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_pinv.c: complex, int64_t version of cs_pinv //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_pinv.c" ������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_pinv.c�������������������������������������������������0000644�0001751�0000144�00000000600�14552026002�021776� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_pinv.c: double, int64_t version of cs_pinv //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_pinv.c" ��������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_lu.c������������������������������������������������������0000644�0001751�0000144�00000010323�14552026002�020766� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_lu: sparse left-looking LU factorization // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* [L,U,pinv]=lu(A, [q lnz unz]). lnz and unz can be guess */ csn *cs_lu (const cs *A, const css *S, double tol) { cs *L, *U ; csn *N ; CS_ENTRY pivot, *Lx, *Ux, *x ; double a, t ; CS_INT *Lp, *Li, *Up, *Ui, *pinv, *xi, *q, n, ipiv, k, top, p, i, col, lnz,unz; if (!CS_CSC (A) || !S) return (NULL) ; /* check inputs */ n = A->n ; q = S->q ; lnz = S->lnz ; unz = S->unz ; x = cs_malloc (n, sizeof (CS_ENTRY)) ; /* get CS_ENTRY workspace */ xi = cs_malloc (2*n, sizeof (CS_INT)) ; /* get CS_INT workspace */ N = cs_calloc (1, sizeof (csn)) ; /* allocate result */ if (!x || !xi || !N) return (cs_ndone (N, NULL, xi, x, 0)) ; N->L = L = cs_spalloc (n, n, lnz, 1, 0) ; /* allocate result L */ N->U = U = cs_spalloc (n, n, unz, 1, 0) ; /* allocate result U */ N->pinv = pinv = cs_malloc (n, sizeof (CS_INT)) ; /* allocate result pinv */ if (!L || !U || !pinv) return (cs_ndone (N, NULL, xi, x, 0)) ; Lp = L->p ; Up = U->p ; for (i = 0 ; i < n ; i++) x [i] = 0 ; /* clear workspace */ for (i = 0 ; i < n ; i++) pinv [i] = -1 ; /* no rows pivotal yet */ for (k = 0 ; k <= n ; k++) Lp [k] = 0 ; /* no cols of L yet */ lnz = unz = 0 ; for (k = 0 ; k < n ; k++) /* compute L(:,k) and U(:,k) */ { /* --- Triangular solve --------------------------------------------- */ Lp [k] = lnz ; /* L(:,k) starts here */ Up [k] = unz ; /* U(:,k) starts here */ if ((lnz + n > L->nzmax && !cs_sprealloc (L, 2*L->nzmax + n)) || (unz + n > U->nzmax && !cs_sprealloc (U, 2*U->nzmax + n))) { return (cs_ndone (N, NULL, xi, x, 0)) ; } Li = L->i ; Lx = L->x ; Ui = U->i ; Ux = U->x ; col = q ? (q [k]) : k ; top = cs_spsolve (L, A, col, xi, x, pinv, 1) ; /* x = L\A(:,col) */ /* --- Find pivot --------------------------------------------------- */ ipiv = -1 ; a = -1 ; for (p = top ; p < n ; p++) { i = xi [p] ; /* x(i) is nonzero */ if (pinv [i] < 0) /* row i is not yet pivotal */ { if ((t = CS_ABS (x [i])) > a) { a = t ; /* largest pivot candidate so far */ ipiv = i ; } } else /* x(i) is the entry U(pinv[i],k) */ { Ui [unz] = pinv [i] ; Ux [unz++] = x [i] ; } } if (ipiv == -1 || a <= 0) return (cs_ndone (N, NULL, xi, x, 0)) ; /* tol=1 for partial pivoting; tol<1 gives preference to diagonal */ if (pinv [col] < 0 && CS_ABS (x [col]) >= a*tol) ipiv = col ; /* --- Divide by pivot ---------------------------------------------- */ pivot = x [ipiv] ; /* the chosen pivot */ Ui [unz] = k ; /* last entry in U(:,k) is U(k,k) */ Ux [unz++] = pivot ; pinv [ipiv] = k ; /* ipiv is the kth pivot row */ Li [lnz] = ipiv ; /* first entry in L(:,k) is L(k,k) = 1 */ Lx [lnz++] = 1 ; for (p = top ; p < n ; p++) /* L(k+1:n,k) = x / pivot */ { i = xi [p] ; if (pinv [i] < 0) /* x(i) is an entry in L(:,k) */ { Li [lnz] = i ; /* save unpermuted row in L */ Lx [lnz++] = x [i] / pivot ; /* scale pivot column */ } x [i] = 0 ; /* x [0..n-1] = 0 for next k */ } } /* --- Finalize L and U ------------------------------------------------- */ Lp [n] = lnz ; Up [n] = unz ; Li = L->i ; /* fix row indices of L for final pinv */ for (p = 0 ; p < lnz ; p++) Li [p] = pinv [Li [p]] ; cs_sprealloc (L, 0) ; /* remove extra space from L and U */ cs_sprealloc (U, 0) ; return (cs_ndone (N, NULL, xi, x, 1)) ; /* success */ } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_house.c������������������������������������������������0000644�0001751�0000144�00000000603�14552026002�022150� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_house.c: double, int64_t version of cs_house //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_house.c" �����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_happly.c�����������������������������������������������0000644�0001751�0000144�00000000632�14552026002�022323� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_happly.c: complex, int64_t version of cs_happly //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_happly.c" ������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_spsolve.c�������������������������������������������������0000644�0001751�0000144�00000003055�14552026002�022045� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_spsolve: solve x=L\b or U\b where x and b are both sparse // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* solve Gx=b(:,k), where G is either upper (lo=0) or lower (lo=1) triangular */ CS_INT cs_spsolve (cs *G, const cs *B, CS_INT k, CS_INT *xi, CS_ENTRY *x, const CS_INT *pinv, CS_INT lo) { CS_INT j, J, p, q, px, top, n, *Gp, *Gi, *Bp, *Bi ; CS_ENTRY *Gx, *Bx ; if (!CS_CSC (G) || !CS_CSC (B) || !xi || !x) return (-1) ; Gp = G->p ; Gi = G->i ; Gx = G->x ; n = G->n ; Bp = B->p ; Bi = B->i ; Bx = B->x ; top = cs_reach (G, B, k, xi, pinv) ; /* xi[top..n-1]=Reach(B(:,k)) */ for (p = top ; p < n ; p++) x [xi [p]] = 0 ; /* clear x */ for (p = Bp [k] ; p < Bp [k+1] ; p++) x [Bi [p]] = Bx [p] ; /* scatter B */ for (px = top ; px < n ; px++) { j = xi [px] ; /* x(j) is nonzero */ J = pinv ? (pinv [j]) : j ; /* j maps to col J of G */ if (J < 0) continue ; /* column J is empty */ x [j] /= Gx [lo ? (Gp [J]) : (Gp [J+1]-1)] ;/* x(j) /= G(j,j) */ p = lo ? (Gp [J]+1) : (Gp [J]) ; /* lo: L(j,j) 1st entry */ q = lo ? (Gp [J+1]) : (Gp [J+1]-1) ; /* up: U(j,j) last entry */ for ( ; p < q ; p++) { x [Gi [p]] -= Gx [p] * x [j] ; /* x(i) -= G(i,j) * x(j) */ } } return (top) ; /* return top of stack */ } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_add.c�����������������������������������������������������0000644�0001751�0000144�00000003060�14552026002�021076� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_add: sparse matrix addition // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* C = alpha*A + beta*B */ cs *cs_add (const cs *A, const cs *B, CS_ENTRY alpha, CS_ENTRY beta) { CS_INT p, j, nz = 0, anz, *Cp, *Ci, *Bp, m, n, bnz, *w, values ; CS_ENTRY *x, *Bx, *Cx ; cs *C ; if (!CS_CSC (A) || !CS_CSC (B)) return (NULL) ; /* check inputs */ if (A->m != B->m || A->n != B->n) return (NULL) ; m = A->m ; anz = A->p [A->n] ; n = B->n ; Bp = B->p ; Bx = B->x ; bnz = Bp [n] ; w = cs_calloc (m, sizeof (CS_INT)) ; /* get workspace */ values = (A->x != NULL) && (Bx != NULL) ; x = values ? cs_malloc (m, sizeof (CS_ENTRY)) : NULL ; /* get workspace */ C = cs_spalloc (m, n, anz + bnz, values, 0) ; /* allocate result*/ if (!C || !w || (values && !x)) return (cs_done (C, w, x, 0)) ; Cp = C->p ; Ci = C->i ; Cx = C->x ; for (j = 0 ; j < n ; j++) { Cp [j] = nz ; /* column j of C starts here */ nz = cs_scatter (A, j, alpha, w, x, j+1, C, nz) ; /* alpha*A(:,j)*/ nz = cs_scatter (B, j, beta, w, x, j+1, C, nz) ; /* beta*B(:,j) */ if (values) for (p = Cp [j] ; p < nz ; p++) Cx [p] = x [Ci [p]] ; } Cp [n] = nz ; /* finalize the last column of C */ cs_sprealloc (C, 0) ; /* remove extra space from C */ return (cs_done (C, w, x, 1)) ; /* success; free workspace, return C */ } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_convert.c�������������������������������������������������0000644�0001751�0000144�00000007170�14552026002�022034� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_convert: convert between real and complex // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* convert from complex to real (int version) */ /* C = real(A) if real is true, imag(A) otherwise */ cs_di *cs_i_real (cs_ci *A, int real) { cs_di *C ; int n, triplet, nn, p, nz, *Ap, *Ai, *Cp, *Ci ; cs_complex_t *Ax ; double *Cx ; if (!A || !A->x) return (NULL) ; /* return if A NULL or pattern-only */ n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; triplet = (A->nz >= 0) ; /* true if A is a triplet matrix */ nz = triplet ? A->nz : Ap [n] ; C = cs_di_spalloc (A->m, n, A->nzmax, 1, triplet) ; if (!C) return (NULL) ; Cp = C->p ; Ci = C->i ; Cx = C->x ; nn = triplet ? nz : (n+1) ; for (p = 0 ; p < nz ; p++) Ci [p] = Ai [p] ; for (p = 0 ; p < nn ; p++) Cp [p] = Ap [p] ; for (p = 0 ; p < nz ; p++) Cx [p] = real ? creal (Ax [p]) : cimag (Ax [p]) ; if (triplet) C->nz = nz ; return (C) ; } /* convert from real to complex (int version) */ /* C = A if real is true, or C = i*A otherwise */ cs_ci *cs_i_complex (cs_di *A, int real) { cs_ci *C ; int n, triplet, nn, p, nz, *Ap, *Ai, *Cp, *Ci ; double *Ax ; cs_complex_t *Cx ; if (!A || !A->x) return (NULL) ; /* return if A NULL or pattern-only */ n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; triplet = (A->nz >= 0) ; /* true if A is a triplet matrix */ nz = triplet ? A->nz : Ap [n] ; C = cs_ci_spalloc (A->m, n, A->nzmax, 1, triplet) ; if (!C) return (NULL) ; Cp = C->p ; Ci = C->i ; Cx = C->x ; nn = triplet ? nz : (n+1) ; for (p = 0 ; p < nz ; p++) Ci [p] = Ai [p] ; for (p = 0 ; p < nn ; p++) Cp [p] = Ap [p] ; for (p = 0 ; p < nz ; p++) Cx [p] = real ? Ax [p] : (I * Ax [p]) ; if (triplet) C->nz = nz ; return (C) ; } /* convert from complex to real (int64_t version) */ /* C = real(A) if real is true, imag(A) otherwise */ cs_dl *cs_l_real (cs_cl *A, int64_t real) { cs_dl *C ; int64_t n, triplet, nn, p, nz, *Ap, *Ai, *Cp, *Ci ; cs_complex_t *Ax ; double *Cx ; if (!A || !A->x) return (NULL) ; /* return if A NULL or pattern-only */ n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; triplet = (A->nz >= 0) ; /* true if A is a triplet matrix */ nz = triplet ? A->nz : Ap [n] ; C = cs_dl_spalloc (A->m, n, A->nzmax, 1, triplet) ; if (!C) return (NULL) ; Cp = C->p ; Ci = C->i ; Cx = C->x ; nn = triplet ? nz : (n+1) ; for (p = 0 ; p < nz ; p++) Ci [p] = Ai [p] ; for (p = 0 ; p < nn ; p++) Cp [p] = Ap [p] ; for (p = 0 ; p < nz ; p++) Cx [p] = real ? creal (Ax [p]) : cimag (Ax [p]) ; if (triplet) C->nz = nz ; return (C) ; } /* convert from real to complex (int64_t version) */ /* C = A if real is true, or C = i*A otherwise */ cs_cl *cs_l_complex (cs_dl *A, int64_t real) { cs_cl *C ; int64_t n, triplet, nn, p, nz, *Ap, *Ai, *Cp, *Ci ; double *Ax ; cs_complex_t *Cx ; if (!A || !A->x) return (NULL) ; /* return if A NULL or pattern-only */ n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; triplet = (A->nz >= 0) ; /* true if A is a triplet matrix */ nz = triplet ? A->nz : Ap [n] ; C = cs_cl_spalloc (A->m, n, A->nzmax, 1, triplet) ; if (!C) return (NULL) ; Cp = C->p ; Ci = C->i ; Cx = C->x ; nn = triplet ? nz : (n+1) ; for (p = 0 ; p < nz ; p++) Ci [p] = Ai [p] ; for (p = 0 ; p < nn ; p++) Cp [p] = Ap [p] ; for (p = 0 ; p < nz ; p++) Cx [p] = real ? Ax [p] : (I * Ax [p]) ; if (triplet) C->nz = nz ; return (C) ; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_chol.c�������������������������������������������������0000644�0001751�0000144�00000000600�14552026002�021747� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_chol.c: double, int64_t version of cs_chol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_chol.c" ��������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_dupl.c�������������������������������������������������0000644�0001751�0000144�00000000624�14552026002�021773� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_dupl.c: complex, int64_t version of cs_dupl //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_dupl.c" ������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_cholsol.c����������������������������������������������0000644�0001751�0000144�00000000635�14552026002�022474� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_cholsol.c: complex, int64_t version of cs_cholsol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_cholsol.c" ���������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_leaf.c�������������������������������������������������0000644�0001751�0000144�00000000624�14552026002�021736� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_leaf.c: complex, int64_t version of cs_leaf //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_leaf.c" ������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_multiply.c���������������������������������������������0000644�0001751�0000144�00000000640�14552026002�022704� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_multiply.c: complex, int64_t version of cs_multiply //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_multiply.c" ������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_lu.c���������������������������������������������������0000644�0001751�0000144�00000000616�14552026002�021450� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_lu.c: complex, int64_t version of cs_lu //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_lu.c" ������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_scc.c�����������������������������������������������������0000644�0001751�0000144�00000004020�14552026002�021113� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_scc: strongly connected components // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* find the strongly connected components of a square matrix */ csd *cs_scc (cs *A) /* matrix A temporarily modified, then restored */ { CS_INT n, i, k, b, nb = 0, top, *xi, *pstack, *p, *r, *Ap, *ATp, *rcopy, *Blk ; cs *AT ; csd *D ; if (!CS_CSC (A)) return (NULL) ; /* check inputs */ n = A->n ; Ap = A->p ; D = cs_dalloc (n, 0) ; /* allocate result */ AT = cs_transpose (A, 0) ; /* AT = A' */ xi = cs_malloc (2*n+1, sizeof (CS_INT)) ; /* get workspace */ if (!D || !AT || !xi) return (cs_ddone (D, AT, xi, 0)) ; Blk = xi ; rcopy = pstack = xi + n ; p = D->p ; r = D->r ; ATp = AT->p ; top = n ; for (i = 0 ; i < n ; i++) /* first dfs(A) to find finish times (xi) */ { if (!CS_MARKED (Ap, i)) top = cs_dfs (i, A, top, xi, pstack, NULL) ; } for (i = 0 ; i < n ; i++) CS_MARK (Ap, i) ; /* restore A; unmark all nodes*/ top = n ; nb = n ; for (k = 0 ; k < n ; k++) /* dfs(A') to find strongly connnected comp */ { i = xi [k] ; /* get i in reverse order of finish times */ if (CS_MARKED (ATp, i)) continue ; /* skip node i if already ordered */ r [nb--] = top ; /* node i is the start of a component in p */ top = cs_dfs (i, AT, top, p, pstack, NULL) ; } r [nb] = 0 ; /* first block starts at zero; shift r up */ for (k = nb ; k <= n ; k++) r [k-nb] = r [k] ; D->nb = nb = n-nb ; /* nb = # of strongly connected components */ for (b = 0 ; b < nb ; b++) /* sort each block in natural order */ { for (k = r [b] ; k < r [b+1] ; k++) Blk [p [k]] = b ; } for (b = 0 ; b <= nb ; b++) rcopy [b] = r [b] ; for (i = 0 ; i < n ; i++) p [rcopy [Blk [i]]++] = i ; return (cs_ddone (D, AT, xi, 1)) ; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_randperm.c���������������������������������������������0000644�0001751�0000144�00000000640�14552026002�022635� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_randperm.c: complex, int64_t version of cs_randperm //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_randperm.c" ������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_ereach.c�����������������������������������������������0000644�0001751�0000144�00000000612�14552026002�022250� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_ereach.c: complex, int32_t version of cs_ereach //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_ereach.c" ����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_ltsolve.c����������������������������������������������0000644�0001751�0000144�00000000611�14552026002�022514� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_ltsolve.c: double, int64_t version of cs_ltsolve //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_ltsolve.c" �����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_malloc.c�����������������������������������������������0000644�0001751�0000144�00000000612�14552026002�022270� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_malloc.c: complex, int32_t version of cs_malloc //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_malloc.c" ����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_updown.c�����������������������������������������������0000644�0001751�0000144�00000000612�14552026002�022335� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_updown.c: complex, int32_t version of cs_updown //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_updown.c" ����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_post.c�������������������������������������������������0000644�0001751�0000144�00000000600�14552026002�022007� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_post.c: double, int64_t version of cs_post //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_post.c" ��������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ereach.c��������������������������������������������������0000644�0001751�0000144�00000002432�14552026002�021577� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_ereach: find reach of a set of nodes in graph of L // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* find nonzero pattern of Cholesky L(k,1:k-1) using etree and triu(A(:,k)) */ CS_INT cs_ereach (const cs *A, CS_INT k, const CS_INT *parent, CS_INT *s, CS_INT *w) { CS_INT i, p, n, len, top, *Ap, *Ai ; if (!CS_CSC (A) || !parent || !s || !w) return (-1) ; /* check inputs */ top = n = A->n ; Ap = A->p ; Ai = A->i ; CS_MARK (w, k) ; /* mark node k as visited */ for (p = Ap [k] ; p < Ap [k+1] ; p++) { i = Ai [p] ; /* A(i,k) is nonzero */ if (i > k) continue ; /* only use upper triangular part of A */ for (len = 0 ; !CS_MARKED (w,i) ; i = parent [i]) /* traverse up etree*/ { s [len++] = i ; /* L(k,i) is nonzero */ CS_MARK (w, i) ; /* mark i as visited */ } while (len > 0) s [--top] = s [--len] ; /* push path onto stack */ } for (p = top ; p < n ; p++) CS_MARK (w, s [p]) ; /* unmark all nodes */ CS_MARK (w, k) ; /* unmark node k */ return (top) ; /* s [top..n-1] contains pattern of L(k,:)*/ } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_droptol.c����������������������������������������������0000644�0001751�0000144�00000000635�14552026002�022514� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_droptol.c: complex, int64_t version of cs_droptol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_droptol.c" ���������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_fkeep.c������������������������������������������������0000644�0001751�0000144�00000000603�14552026002�022117� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_fkeep.c: double, int64_t version of cs_fkeep //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_fkeep.c" �����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_maxtrans.c���������������������������������������������0000644�0001751�0000144�00000000620�14552026002�022655� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_maxtrans.c: complex, int32_t version of cs_maxtrans //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_maxtrans.c" ����������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_sqr.c�����������������������������������������������������0000644�0001751�0000144�00000007665�14552026002�021172� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_sqr: ordering and symbolic analysis for sparse QR // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* compute nnz(V) = S->lnz, S->pinv, S->leftmost, S->m2 from A and S->parent */ static CS_INT cs_vcount (const cs *A, css *S) { CS_INT i, k, p, pa, n = A->n, m = A->m, *Ap = A->p, *Ai = A->i, *next, *head, *tail, *nque, *pinv, *leftmost, *w, *parent = S->parent ; S->pinv = pinv = cs_malloc (m+n, sizeof (CS_INT)) ; /* allocate pinv, */ S->leftmost = leftmost = cs_malloc (m, sizeof (CS_INT)) ; /* and leftmost */ w = cs_malloc (m+3*n, sizeof (CS_INT)) ; /* get workspace */ if (!pinv || !w || !leftmost) { cs_free (w) ; /* pinv and leftmost freed later */ return (0) ; /* out of memory */ } next = w ; head = w + m ; tail = w + m + n ; nque = w + m + 2*n ; for (k = 0 ; k < n ; k++) head [k] = -1 ; /* queue k is empty */ for (k = 0 ; k < n ; k++) tail [k] = -1 ; for (k = 0 ; k < n ; k++) nque [k] = 0 ; for (i = 0 ; i < m ; i++) leftmost [i] = -1 ; for (k = n-1 ; k >= 0 ; k--) { for (p = Ap [k] ; p < Ap [k+1] ; p++) { leftmost [Ai [p]] = k ; /* leftmost[i] = min(find(A(i,:)))*/ } } for (i = m-1 ; i >= 0 ; i--) /* scan rows in reverse order */ { pinv [i] = -1 ; /* row i is not yet ordered */ k = leftmost [i] ; if (k == -1) continue ; /* row i is empty */ if (nque [k]++ == 0) tail [k] = i ; /* first row in queue k */ next [i] = head [k] ; /* put i at head of queue k */ head [k] = i ; } S->lnz = 0 ; S->m2 = m ; for (k = 0 ; k < n ; k++) /* find row permutation and nnz(V)*/ { i = head [k] ; /* remove row i from queue k */ S->lnz++ ; /* count V(k,k) as nonzero */ if (i < 0) i = S->m2++ ; /* add a fictitious row */ pinv [i] = k ; /* associate row i with V(:,k) */ if (--nque [k] <= 0) continue ; /* skip if V(k+1:m,k) is empty */ S->lnz += nque [k] ; /* nque [k] is nnz (V(k+1:m,k)) */ if ((pa = parent [k]) != -1) /* move all rows to parent of k */ { if (nque [pa] == 0) tail [pa] = tail [k] ; next [tail [k]] = head [pa] ; head [pa] = next [i] ; nque [pa] += nque [k] ; } } for (i = 0 ; i < m ; i++) if (pinv [i] < 0) pinv [i] = k++ ; cs_free (w) ; return (1) ; } /* symbolic ordering and analysis for QR or LU */ css *cs_sqr (CS_INT order, const cs *A, CS_INT qr) { CS_INT n, k, ok = 1, *post ; css *S ; if (!CS_CSC (A)) return (NULL) ; /* check inputs */ n = A->n ; S = cs_calloc (1, sizeof (css)) ; /* allocate result S */ if (!S) return (NULL) ; /* out of memory */ S->q = cs_amd (order, A) ; /* fill-reducing ordering */ if (order && !S->q) return (cs_sfree (S)) ; if (qr) /* QR symbolic analysis */ { cs *C = order ? cs_permute (A, NULL, S->q, 0) : ((cs *) A) ; S->parent = cs_etree (C, 1) ; /* etree of C'*C, where C=A(:,q) */ post = cs_post (S->parent, n) ; S->cp = cs_counts (C, S->parent, post, 1) ; /* col counts chol(C'*C) */ cs_free (post) ; ok = C && S->parent && S->cp && cs_vcount (C, S) ; if (ok) for (S->unz = 0, k = 0 ; k < n ; k++) S->unz += S->cp [k] ; if (order) cs_spfree (C) ; } else { S->unz = 4*(A->p [n]) + n ; /* for LU factorization only, */ S->lnz = S->unz ; /* guess nnz(L) and nnz(U) */ } return (ok ? S : cs_sfree (S)) ; /* return result S */ } ���������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_schol.c������������������������������������������������0000644�0001751�0000144�00000000627�14552026002�022142� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_schol.c: complex, int64_t version of cs_schol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_schol.c" ���������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_permute.c�������������������������������������������������0000644�0001751�0000144�00000002301�14552026002�022024� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_permute: permute a sparse matrix // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* C = A(p,q) where p and q are permutations of 0..m-1 and 0..n-1. */ cs *cs_permute (const cs *A, const CS_INT *pinv, const CS_INT *q, CS_INT values) { CS_INT t, j, k, nz = 0, m, n, *Ap, *Ai, *Cp, *Ci ; CS_ENTRY *Cx, *Ax ; cs *C ; if (!CS_CSC (A)) return (NULL) ; /* check inputs */ m = A->m ; n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; C = cs_spalloc (m, n, Ap [n], values && Ax != NULL, 0) ; /* alloc result */ if (!C) return (cs_done (C, NULL, NULL, 0)) ; /* out of memory */ Cp = C->p ; Ci = C->i ; Cx = C->x ; for (k = 0 ; k < n ; k++) { Cp [k] = nz ; /* column k of C is column q[k] of A */ j = q ? (q [k]) : k ; for (t = Ap [j] ; t < Ap [j+1] ; t++) { if (Cx) Cx [nz] = Ax [t] ; /* row i of A is row pinv[i] of C */ Ci [nz++] = pinv ? (pinv [Ai [t]]) : Ai [t] ; } } Cp [n] = nz ; /* finalize the last column of C */ return (cs_done (C, NULL, NULL, 1)) ; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_spsolve.c����������������������������������������������0000644�0001751�0000144�00000000611�14552026002�022517� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_spsolve.c: double, int64_t version of cs_spsolve //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_spsolve.c" �����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_utsolve.c�������������������������������������������������0000644�0001751�0000144�00000001325�14552026002�022051� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_utsolve: x=U'\b where x and b are dense // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* solve U'x=b where x and b are dense. x=b on input, solution on output. */ CS_INT cs_utsolve (const cs *U, CS_ENTRY *x) { CS_INT p, j, n, *Up, *Ui ; CS_ENTRY *Ux ; if (!CS_CSC (U) || !x) return (0) ; /* check inputs */ n = U->n ; Up = U->p ; Ui = U->i ; Ux = U->x ; for (j = 0 ; j < n ; j++) { for (p = Up [j] ; p < Up [j+1]-1 ; p++) { x [j] -= CS_CONJ (Ux [p]) * x [Ui [p]] ; } x [j] /= CS_CONJ (Ux [Up [j+1]-1]) ; } return (1) ; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_compress.c���������������������������������������������0000644�0001751�0000144�00000000620�14552026002�022653� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_compress.c: complex, int32_t version of cs_compress //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_compress.c" ����������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_qr.c���������������������������������������������������0000644�0001751�0000144�00000000572�14552026002�021454� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_qr.c: double, int64_t version of cs_qr //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_qr.c" ��������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_amd.c��������������������������������������������������0000644�0001751�0000144�00000000621�14552026002�021565� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_amd.c: complex, int64_t version of cs_amd //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_amd.c" ���������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_dupl.c�������������������������������������������������0000644�0001751�0000144�00000000604�14552026002�021766� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_dupl.c: complex, int32_t version of cs_dupl //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_dupl.c" ����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_maxtrans.c������������������������������������������������0000644�0001751�0000144�00000011115�14552026002�022203� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_maxtrans: maximum transversal of a graph // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* find an augmenting path starting at column k and extend the match if found */ static void cs_augment (CS_INT k, const cs *A, CS_INT *jmatch, CS_INT *cheap, CS_INT *w, CS_INT *js, CS_INT *is, CS_INT *ps) { CS_INT found = 0, p, i = -1, *Ap = A->p, *Ai = A->i, head = 0, j ; js [0] = k ; /* start with just node k in jstack */ while (head >= 0) { /* --- Start (or continue) depth-first-search at node j ------------- */ j = js [head] ; /* get j from top of jstack */ if (w [j] != k) /* 1st time j visited for kth path */ { w [j] = k ; /* mark j as visited for kth path */ for (p = cheap [j] ; p < Ap [j+1] && !found ; p++) { i = Ai [p] ; /* try a cheap assignment (i,j) */ found = (jmatch [i] == -1) ; } cheap [j] = p ; /* start here next time j is traversed*/ if (found) { is [head] = i ; /* column j matched with row i */ break ; /* end of augmenting path */ } ps [head] = Ap [j] ; /* no cheap match: start dfs for j */ } /* --- Depth-first-search of neighbors of j ------------------------- */ for (p = ps [head] ; p < Ap [j+1] ; p++) { i = Ai [p] ; /* consider row i */ if (w [jmatch [i]] == k) continue ; /* skip jmatch [i] if marked */ ps [head] = p + 1 ; /* pause dfs of node j */ is [head] = i ; /* i will be matched with j if found */ js [++head] = jmatch [i] ; /* start dfs at column jmatch [i] */ break ; } if (p == Ap [j+1]) head-- ; /* node j is done; pop from stack */ } /* augment the match if path found: */ if (found) for (p = head ; p >= 0 ; p--) jmatch [is [p]] = js [p] ; } /* find a maximum transveral */ CS_INT *cs_maxtrans (const cs *A, CS_INT seed) /*[jmatch [0..m-1]; imatch [0..n-1]]*/ { CS_INT i, j, k, n, m, p, n2 = 0, m2 = 0, *Ap, *jimatch, *w, *cheap, *js, *is, *ps, *Ai, *Cp, *jmatch, *imatch, *q ; cs *C ; if (!CS_CSC (A)) return (NULL) ; /* check inputs */ n = A->n ; m = A->m ; Ap = A->p ; Ai = A->i ; w = jimatch = cs_calloc (m+n, sizeof (CS_INT)) ; /* allocate result */ if (!jimatch) return (NULL) ; for (k = 0, j = 0 ; j < n ; j++) /* count nonempty rows and columns */ { n2 += (Ap [j] < Ap [j+1]) ; for (p = Ap [j] ; p < Ap [j+1] ; p++) { w [Ai [p]] = 1 ; k += (j == Ai [p]) ; /* count entries already on diagonal */ } } if (k == CS_MIN (m,n)) /* quick return if diagonal zero-free */ { jmatch = jimatch ; imatch = jimatch + m ; for (i = 0 ; i < k ; i++) jmatch [i] = i ; for ( ; i < m ; i++) jmatch [i] = -1 ; for (j = 0 ; j < k ; j++) imatch [j] = j ; for ( ; j < n ; j++) imatch [j] = -1 ; return (cs_idone (jimatch, NULL, NULL, 1)) ; } for (i = 0 ; i < m ; i++) m2 += w [i] ; C = (m2 < n2) ? cs_transpose (A,0) : ((cs *) A) ; /* transpose if needed */ if (!C) return (cs_idone (jimatch, (m2 < n2) ? C : NULL, NULL, 0)) ; n = C->n ; m = C->m ; Cp = C->p ; jmatch = (m2 < n2) ? jimatch + n : jimatch ; imatch = (m2 < n2) ? jimatch : jimatch + m ; w = cs_malloc (5*n, sizeof (CS_INT)) ; /* get workspace */ if (!w) return (cs_idone (jimatch, (m2 < n2) ? C : NULL, w, 0)) ; cheap = w + n ; js = w + 2*n ; is = w + 3*n ; ps = w + 4*n ; for (j = 0 ; j < n ; j++) cheap [j] = Cp [j] ; /* for cheap assignment */ for (j = 0 ; j < n ; j++) w [j] = -1 ; /* all columns unflagged */ for (i = 0 ; i < m ; i++) jmatch [i] = -1 ; /* nothing matched yet */ q = cs_randperm (n, seed) ; /* q = random permutation */ for (k = 0 ; k < n ; k++) /* augment, starting at column q[k] */ { cs_augment (q ? q [k]: k, C, jmatch, cheap, w, js, is, ps) ; } cs_free (q) ; for (j = 0 ; j < n ; j++) imatch [j] = -1 ; /* find row match */ for (i = 0 ; i < m ; i++) if (jmatch [i] >= 0) imatch [jmatch [i]] = i ; return (cs_idone (jimatch, (m2 < n2) ? C : NULL, w, 1)) ; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_lusol.c������������������������������������������������0000644�0001751�0000144�00000000607�14552026002�022163� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_lusol.c: complex, int32_t version of cs_lusol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_lusol.c" �������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_malloc.c��������������������������������������������������0000644�0001751�0000144�00000002077�14552026002�021624� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_malloc: wrappers for malloc/calloc/realloc/free // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" #ifdef MATLAB_MEX_FILE #define malloc mxMalloc #define free mxFree #define realloc mxRealloc #define calloc mxCalloc #endif /* wrapper for malloc */ void *cs_malloc (CS_INT n, size_t size) { return (malloc (CS_MAX (n,1) * size)) ; } /* wrapper for calloc */ void *cs_calloc (CS_INT n, size_t size) { return (calloc (CS_MAX (n,1), size)) ; } /* wrapper for free */ void *cs_free (void *p) { if (p) free (p) ; /* free p if it is not already NULL */ return (NULL) ; /* return NULL to simplify the use of cs_free */ } /* wrapper for realloc */ void *cs_realloc (void *p, CS_INT n, size_t size, CS_INT *ok) { void *pnew ; pnew = realloc (p, CS_MAX (n,1) * size) ; /* realloc the block */ *ok = (pnew != NULL) ; /* realloc fails if pnew is NULL */ return ((*ok) ? pnew : p) ; /* return original p if failure */ } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_permute.c����������������������������������������������0000644�0001751�0000144�00000000611�14552026002�022505� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_permute.c: double, int64_t version of cs_permute //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_permute.c" �����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_gaxpy.c������������������������������������������������0000644�0001751�0000144�00000000607�14552026002�022155� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_gaxpy.c: complex, int32_t version of cs_gaxpy //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_gaxpy.c" �������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_cholsol.c����������������������������������������������0000644�0001751�0000144�00000000615�14552026002�022467� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_cholsol.c: complex, int32_t version of cs_cholsol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_cholsol.c" �������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_util.c�������������������������������������������������0000644�0001751�0000144�00000000600�14552026002�021777� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_util.c: double, int64_t version of cs_util //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_util.c" ��������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_spsolve.c����������������������������������������������0000644�0001751�0000144�00000000615�14552026002�022517� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_spsolve.c: complex, int32_t version of cs_spsolve //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_spsolve.c" �������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_house.c���������������������������������������������������0000644�0001751�0000144�00000002026�14552026002�021472� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_house: create a Householder transformation // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* create a Householder reflection [v,beta,s]=house(x), overwrite x with v, * where (I-beta*v*v')*x = s*e1 and e1 = [1 0 ... 0]'. * Note that this CXSparse version is different than CSparse. See Higham, * Accuracy & Stability of Num Algorithms, 2nd ed, 2002, page 357. */ CS_ENTRY cs_house (CS_ENTRY *x, double *beta, CS_INT n) { CS_ENTRY s = 0 ; CS_INT i ; if (!x || !beta) return (-1) ; /* check inputs */ /* s = norm(x) */ for (i = 0 ; i < n ; i++) s += x [i] * CS_CONJ (x [i]) ; s = sqrt (s) ; if (s == 0) { (*beta) = 0 ; x [0] = 1 ; } else { /* s = sign(x[0]) * norm (x) ; */ if (x [0] != 0) { s *= x [0] / CS_ABS (x [0]) ; } x [0] += s ; (*beta) = 1. / CS_REAL (CS_CONJ (s) * x [0]) ; } return (-s) ; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_gaxpy.c������������������������������������������������0000644�0001751�0000144�00000000627�14552026002�022162� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_gaxpy.c: complex, int64_t version of cs_gaxpy //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_gaxpy.c" ���������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_print.c������������������������������������������������0000644�0001751�0000144�00000000627�14552026002�022166� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_print.c: complex, int64_t version of cs_print //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_print.c" ���������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_leaf.c����������������������������������������������������0000644�0001751�0000144�00000002312�14552026002�021254� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_leaf: find least common ancestor of a row subtree // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* consider A(i,j), node j in ith row subtree and return lca(jprev,j) */ CS_INT cs_leaf (CS_INT i, CS_INT j, const CS_INT *first, CS_INT *maxfirst, CS_INT *prevleaf, CS_INT *ancestor, CS_INT *jleaf) { CS_INT q, s, sparent, jprev ; if (!first || !maxfirst || !prevleaf || !ancestor || !jleaf) return (-1) ; *jleaf = 0 ; if (i <= j || first [j] <= maxfirst [i]) return (-1) ; /* j not a leaf */ maxfirst [i] = first [j] ; /* update max first[j] seen so far */ jprev = prevleaf [i] ; /* jprev = previous leaf of ith subtree */ prevleaf [i] = j ; *jleaf = (jprev == -1) ? 1: 2 ; /* j is first or subsequent leaf */ if (*jleaf == 1) return (i) ; /* if 1st leaf, q = root of ith subtree */ for (q = jprev ; q != ancestor [q] ; q = ancestor [q]) ; for (s = jprev ; s != q ; s = sparent) { sparent = ancestor [s] ; /* path compression */ ancestor [s] = q ; } return (q) ; /* q = least common ancester (jprev,j) */ } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_schol.c������������������������������������������������0000644�0001751�0000144�00000000603�14552026002�022135� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_schol.c: double, int64_t version of cs_schol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_schol.c" �����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_fkeep.c������������������������������������������������0000644�0001751�0000144�00000000607�14552026002�022117� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_fkeep.c: complex, int32_t version of cs_fkeep //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_fkeep.c" �������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_amd.c��������������������������������������������������0000644�0001751�0000144�00000000575�14552026002�021576� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_amd.c: double, int64_t version of cs_amd //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_amd.c" �����������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_dupl.c�������������������������������������������������0000644�0001751�0000144�00000000600�14552026002�021766� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_dupl.c: double, int64_t version of cs_dupl //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_dupl.c" ��������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_dropzeros.c��������������������������������������������0000644�0001751�0000144�00000000617�14552026002�023061� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_dropzeros.c: double, int64_t version of cs_dropzeros //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_dropzeros.c" �����������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dupl.c����������������������������������������������������0000644�0001751�0000144�00000003063�14552026002�021315� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_dupl: remove duplicates from a sparse matrix // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* remove duplicate entries from A */ CS_INT cs_dupl (cs *A) { CS_INT i, j, p, q, nz = 0, n, m, *Ap, *Ai, *w ; CS_ENTRY *Ax ; if (!CS_CSC (A)) return (0) ; /* check inputs */ m = A->m ; n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; w = cs_malloc (m, sizeof (CS_INT)) ; /* get workspace */ if (!w) return (0) ; /* out of memory */ for (i = 0 ; i < m ; i++) w [i] = -1 ; /* row i not yet seen */ for (j = 0 ; j < n ; j++) { q = nz ; /* column j will start at q */ for (p = Ap [j] ; p < Ap [j+1] ; p++) { i = Ai [p] ; /* A(i,j) is nonzero */ if (w [i] >= q) { Ax [w [i]] += Ax [p] ; /* A(i,j) is a duplicate */ } else { w [i] = nz ; /* record where row i occurs */ Ai [nz] = i ; /* keep A(i,j) */ Ax [nz++] = Ax [p] ; } } Ap [j] = q ; /* record start of column j */ } Ap [n] = nz ; /* finalize A */ cs_free (w) ; /* free workspace */ return (cs_sprealloc (A, 0)) ; /* remove extra space from A */ } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_gaxpy.c���������������������������������������������������0000644�0001751�0000144�00000001147�14552026002�021502� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_gaxpy: sparse matrix times dense vector // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* y = A*x+y */ CS_INT cs_gaxpy (const cs *A, const CS_ENTRY *x, CS_ENTRY *y) { CS_INT p, j, n, *Ap, *Ai ; CS_ENTRY *Ax ; if (!CS_CSC (A) || !x || !y) return (0) ; /* check inputs */ n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; for (j = 0 ; j < n ; j++) { for (p = Ap [j] ; p < Ap [j+1] ; p++) { y [Ai [p]] += Ax [p] * x [j] ; } } return (1) ; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_droptol.c�������������������������������������������������0000644�0001751�0000144�00000000666�14552026002�022042� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_droptol: drop small entries from a sparse matrix // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" static CS_INT cs_tol (CS_INT i, CS_INT j, CS_ENTRY aij, void *tol) { return (CS_ABS (aij) > *((double *) tol)) ; } CS_INT cs_droptol (cs *A, double tol) { return (cs_fkeep (A, &cs_tol, &tol)) ; /* keep all large entries */ } ��������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_spsolve.c����������������������������������������������0000644�0001751�0000144�00000000635�14552026002�022524� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_spsolve.c: complex, int64_t version of cs_spsolve //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_spsolve.c" ���������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_scatter.c����������������������������������������������0000644�0001751�0000144�00000000611�14552026002�022471� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_scatter.c: double, int64_t version of cs_scatter //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_scatter.c" �����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_transpose.c��������������������������������������������0000644�0001751�0000144�00000000617�14552026002�023050� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_transpose.c: double, int64_t version of cs_transpose //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_transpose.c" �����������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_updown.c�����������������������������������������������0000644�0001751�0000144�00000000632�14552026002�022342� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_updown.c: complex, int64_t version of cs_updown //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_updown.c" ������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_maxtrans.c���������������������������������������������0000644�0001751�0000144�00000000640�14552026002�022662� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_maxtrans.c: complex, int64_t version of cs_maxtrans //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_maxtrans.c" ������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_entry.c������������������������������������������������0000644�0001751�0000144�00000000627�14552026002�022173� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_entry.c: complex, int64_t version of cs_entry //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_entry.c" ���������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_malloc.c�����������������������������������������������0000644�0001751�0000144�00000000606�14552026002�022277� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_malloc.c: double, int64_t version of cs_malloc //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_malloc.c" ��������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_house.c������������������������������������������������0000644�0001751�0000144�00000000627�14552026002�022155� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_house.c: complex, int64_t version of cs_house //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_house.c" ���������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_happly.c�����������������������������������������������0000644�0001751�0000144�00000000612�14552026002�022316� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_happly.c: complex, int32_t version of cs_happly //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_happly.c" ����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_tdfs.c�������������������������������������������������0000644�0001751�0000144�00000000600�14552026002�021762� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_tdfs.c: double, int64_t version of cs_tdfs //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_tdfs.c" ��������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_usolve.c�����������������������������������������������0000644�0001751�0000144�00000000632�14552026002�022343� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_usolve.c: complex, int64_t version of cs_usolve //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_usolve.c" ������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_compress.c���������������������������������������������0000644�0001751�0000144�00000000640�14552026002�022660� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_compress.c: complex, int64_t version of cs_compress //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_compress.c" ������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_pvec.c�������������������������������������������������0000644�0001751�0000144�00000000604�14552026002�021757� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_pvec.c: complex, int32_t version of cs_pvec //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_pvec.c" ����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cxsparse_version.c�������������������������������������������0000644�0001751�0000144�00000000503�14552026002�023255� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cxsparse_version: return CXSparse version // CXSparse, Copyright (c) 2006-2023, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" void cxsparse_version (int version [3]) { version [0] = CS_VER ; version [1] = CS_SUBVER ; version [2] = CS_SUBSUB ; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_symperm.c����������������������������������������������0000644�0001751�0000144�00000000615�14552026002�022520� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_symperm.c: complex, int32_t version of cs_symperm //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_symperm.c" �������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_pinv.c����������������������������������������������������0000644�0001751�0000144�00000001222�14552026002�021320� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_pinv: construct an inverse permutation // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* pinv = p', or p = pinv' */ CS_INT *cs_pinv (CS_INT const *p, CS_INT n) { CS_INT k, *pinv ; if (!p) return (NULL) ; /* p = NULL denotes identity */ pinv = cs_malloc (n, sizeof (CS_INT)) ; /* allocate result */ if (!pinv) return (NULL) ; /* out of memory */ for (k = 0 ; k < n ; k++) pinv [p [k]] = k ;/* invert the permutation */ return (pinv) ; /* return result */ } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_scatter.c����������������������������������������������0000644�0001751�0000144�00000000615�14552026002�022471� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_scatter.c: complex, int32_t version of cs_scatter //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_scatter.c" �������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_etree.c������������������������������������������������0000644�0001751�0000144�00000000603�14552026002�022131� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_etree.c: double, int64_t version of cs_etree //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_etree.c" �����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_fkeep.c������������������������������������������������0000644�0001751�0000144�00000000627�14552026002�022124� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_fkeep.c: complex, int64_t version of cs_fkeep //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_fkeep.c" ���������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_qr.c���������������������������������������������������0000644�0001751�0000144�00000000616�14552026002�021452� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_qr.c: complex, int64_t version of cs_qr //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_qr.c" ������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_load.c�������������������������������������������������0000644�0001751�0000144�00000000604�14552026002�021741� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_load.c: complex, int32_t version of cs_load //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_load.c" ����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_symperm.c����������������������������������������������0000644�0001751�0000144�00000000611�14552026002�022520� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_symperm.c: double, int64_t version of cs_symperm //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_symperm.c" �����������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_qrsol.c���������������������������������������������������0000644�0001751�0000144�00000004021�14552026002�021504� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_qrsol: x=A\b using a sparse QR factorization // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* x=A\b where A can be rectangular; b overwritten with solution */ CS_INT cs_qrsol (CS_INT order, const cs *A, CS_ENTRY *b) { CS_ENTRY *x ; css *S ; csn *N ; cs *AT = NULL ; CS_INT k, m, n, ok ; if (!CS_CSC (A) || !b) return (0) ; /* check inputs */ n = A->n ; m = A->m ; if (m >= n) { S = cs_sqr (order, A, 1) ; /* ordering and symbolic analysis */ N = cs_qr (A, S) ; /* numeric QR factorization */ x = cs_calloc (S ? S->m2 : 1, sizeof (CS_ENTRY)) ; /* get workspace */ ok = (S && N && x) ; if (ok) { cs_ipvec (S->pinv, b, x, m) ; /* x(0:m-1) = b(p(0:m-1) */ for (k = 0 ; k < n ; k++) /* apply Householder refl. to x */ { cs_happly (N->L, k, N->B [k], x) ; } cs_usolve (N->U, x) ; /* x = R\x */ cs_ipvec (S->q, x, b, n) ; /* b(q(0:n-1)) = x(0:n-1) */ } } else { AT = cs_transpose (A, 1) ; /* Ax=b is underdetermined */ S = cs_sqr (order, AT, 1) ; /* ordering and symbolic analysis */ N = cs_qr (AT, S) ; /* numeric QR factorization of A' */ x = cs_calloc (S ? S->m2 : 1, sizeof (CS_ENTRY)) ; /* get workspace */ ok = (AT && S && N && x) ; if (ok) { cs_pvec (S->q, b, x, m) ; /* x(q(0:m-1)) = b(0:m-1) */ cs_utsolve (N->U, x) ; /* x = R'\x */ for (k = m-1 ; k >= 0 ; k--) /* apply Householder refl. to x */ { cs_happly (N->L, k, N->B [k], x) ; } cs_pvec (S->pinv, x, b, n) ; /* b(0:n-1) = x(p(0:n-1)) */ } } cs_free (x) ; cs_sfree (S) ; cs_nfree (N) ; cs_spfree (AT) ; return (ok) ; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_scatter.c�������������������������������������������������0000644�0001751�0000144�00000002112�14552026002�022010� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_scatter: scatter a scaled sparse vector into a dense vector // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* x = x + beta * A(:,j), where x is a dense vector and A(:,j) is sparse */ CS_INT cs_scatter (const cs *A, CS_INT j, CS_ENTRY beta, CS_INT *w, CS_ENTRY *x, CS_INT mark, cs *C, CS_INT nz) { CS_INT i, p, *Ap, *Ai, *Ci ; CS_ENTRY *Ax ; if (!CS_CSC (A) || !w || !CS_CSC (C)) return (-1) ; /* check inputs */ Ap = A->p ; Ai = A->i ; Ax = A->x ; Ci = C->i ; for (p = Ap [j] ; p < Ap [j+1] ; p++) { i = Ai [p] ; /* A(i,j) is nonzero */ if (w [i] < mark) { w [i] = mark ; /* i is new entry in column j */ Ci [nz++] = i ; /* add i to pattern of C(:,j) */ if (x) x [i] = beta * Ax [p] ; /* x(i) = beta*A(i,j) */ } else if (x) x [i] += beta * Ax [p] ; /* i exists in C(:,j) already */ } return (nz) ; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_utsolve.c����������������������������������������������0000644�0001751�0000144�00000000635�14552026002�022532� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_utsolve.c: complex, int64_t version of cs_utsolve //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_utsolve.c" ���������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_symperm.c�������������������������������������������������0000644�0001751�0000144�00000003662�14552026002�022052� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_symperm: symmetric permutation of a sparse matrix // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* C = A(p,p) where A and C are symmetric the upper part stored; pinv not p */ cs *cs_symperm (const cs *A, const CS_INT *pinv, CS_INT values) { CS_INT i, j, p, q, i2, j2, n, *Ap, *Ai, *Cp, *Ci, *w ; CS_ENTRY *Cx, *Ax ; cs *C ; if (!CS_CSC (A)) return (NULL) ; /* check inputs */ n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; C = cs_spalloc (n, n, Ap [n], values && (Ax != NULL), 0) ; /* alloc result*/ w = cs_calloc (n, sizeof (CS_INT)) ; /* get workspace */ if (!C || !w) return (cs_done (C, w, NULL, 0)) ; /* out of memory */ Cp = C->p ; Ci = C->i ; Cx = C->x ; for (j = 0 ; j < n ; j++) /* count entries in each column of C */ { j2 = pinv ? pinv [j] : j ; /* column j of A is column j2 of C */ for (p = Ap [j] ; p < Ap [j+1] ; p++) { i = Ai [p] ; if (i > j) continue ; /* skip lower triangular part of A */ i2 = pinv ? pinv [i] : i ; /* row i of A is row i2 of C */ w [CS_MAX (i2, j2)]++ ; /* column count of C */ } } cs_cumsum (Cp, w, n) ; /* compute column pointers of C */ for (j = 0 ; j < n ; j++) { j2 = pinv ? pinv [j] : j ; /* column j of A is column j2 of C */ for (p = Ap [j] ; p < Ap [j+1] ; p++) { i = Ai [p] ; if (i > j) continue ; /* skip lower triangular part of A*/ i2 = pinv ? pinv [i] : i ; /* row i of A is row i2 of C */ Ci [q = w [CS_MAX (i2, j2)]++] = CS_MIN (i2, j2) ; if (Cx) Cx [q] = (i2 <= j2) ? Ax [p] : CS_CONJ (Ax [p]) ; } } return (cs_done (C, w, NULL, 1)) ; /* success; free workspace, return C */ } ������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_cl_ipvec.c������������������������������������������������0000644�0001751�0000144�00000000627�14552026002�022140� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_cl_ipvec.c: complex, int64_t version of cs_ipvec //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #define CS_LONG #include "cs_ipvec.c" ���������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_dl_gaxpy.c������������������������������������������������0000644�0001751�0000144�00000000603�14552026002�022155� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_dl_gaxpy.c: double, int64_t version of cs_gaxpy //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_LONG #include "cs_gaxpy.c" �����������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_ci_schol.c������������������������������������������������0000644�0001751�0000144�00000000607�14552026002�022135� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CXSparse/Source/cs_ci_schol.c: complex, int32_t version of cs_schol //------------------------------------------------------------------------------ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis, All Rights Reserved // SPDX-License-Identifier: LGPL-2.1+ #define CS_COMPLEX #include "cs_schol.c" �������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_reach.c���������������������������������������������������0000644�0001751�0000144�00000001567�14552026002�021442� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_reach: find the reach of a set in an arbitrary graph // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* xi [top...n-1] = nodes reachable from graph of G*P' via nodes in B(:,k). * xi [n...2n-1] used as workspace */ CS_INT cs_reach (cs *G, const cs *B, CS_INT k, CS_INT *xi, const CS_INT *pinv) { CS_INT p, n, top, *Bp, *Bi, *Gp ; if (!CS_CSC (G) || !CS_CSC (B) || !xi) return (-1) ; /* check inputs */ n = G->n ; Bp = B->p ; Bi = B->i ; Gp = G->p ; top = n ; for (p = Bp [k] ; p < Bp [k+1] ; p++) { if (!CS_MARKED (Gp, Bi [p])) /* start a dfs at unmarked node i */ { top = cs_dfs (Bi [p], G, top, xi, xi+n, pinv) ; } } for (p = top ; p < n ; p++) CS_MARK (Gp, xi [p]) ; /* restore G */ return (top) ; } �����������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CXSparse/Source/cs_updown.c��������������������������������������������������0000644�0001751�0000144�00000004533�14552026002�021670� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// CXSparse/Source/cs_updown: sparse Cholesky update/downdate // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" /* sparse Cholesky update/downdate, L*L' + sigma*w*w' (sigma = +1 or -1) */ CS_INT cs_updown (cs *L, CS_INT sigma, const cs *C, const CS_INT *parent) { CS_INT n, p, f, j, *Lp, *Li, *Cp, *Ci ; CS_ENTRY *Lx, *Cx, alpha, gamma, w1, w2, *w ; double beta = 1, beta2 = 1, delta ; #ifdef CS_COMPLEX cs_complex_t phase ; #endif if (!CS_CSC (L) || !CS_CSC (C) || !parent) return (0) ; /* check inputs */ Lp = L->p ; Li = L->i ; Lx = L->x ; n = L->n ; Cp = C->p ; Ci = C->i ; Cx = C->x ; if ((p = Cp [0]) >= Cp [1]) return (1) ; /* return if C empty */ w = cs_malloc (n, sizeof (CS_ENTRY)) ; /* get workspace */ if (!w) return (0) ; /* out of memory */ f = Ci [p] ; for ( ; p < Cp [1] ; p++) f = CS_MIN (f, Ci [p]) ; /* f = min (find (C)) */ for (j = f ; j != -1 ; j = parent [j]) w [j] = 0 ; /* clear workspace w */ for (p = Cp [0] ; p < Cp [1] ; p++) w [Ci [p]] = Cx [p] ; /* w = C */ for (j = f ; j != -1 ; j = parent [j]) /* walk path f up to root */ { p = Lp [j] ; alpha = w [j] / Lx [p] ; /* alpha = w(j) / L(j,j) */ #ifdef CS_COMPLEX beta2 = beta*beta + sigma*creal(alpha*CS_CONJ(alpha)) ; #else beta2 = beta*beta + sigma*(alpha*alpha) ; #endif if (beta2 <= 0) break ; /* not positive definite */ beta2 = sqrt (beta2) ; delta = (sigma > 0) ? (beta / beta2) : (beta2 / beta) ; gamma = sigma * CS_CONJ(alpha) / (beta2 * beta) ; Lx [p] = delta * Lx [p] + ((sigma > 0) ? (gamma * w [j]) : 0) ; beta = beta2 ; #ifdef CS_COMPLEX phase = CS_ABS (Lx [p]) / Lx [p] ; /* phase = abs(L(j,j))/L(j,j)*/ Lx [p] *= phase ; /* L(j,j) = L(j,j) * phase */ #endif for (p++ ; p < Lp [j+1] ; p++) { w1 = w [Li [p]] ; w [Li [p]] = w2 = w1 - alpha * Lx [p] ; Lx [p] = delta * Lx [p] + gamma * ((sigma > 0) ? w1 : w2) ; #ifdef CS_COMPLEX Lx [p] *= phase ; /* L(i,j) = L(i,j) * phase */ #endif } } cs_free (w) ; return (beta2 > 0) ; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CCOLAMD/���������������������������������������������������������������������0000755�0001751�0000144�00000000000�14576344041�015644� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CCOLAMD/Include/�������������������������������������������������������������0000755�0001751�0000144�00000000000�14576343415�017233� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CCOLAMD/Include/ccolamd.h����������������������������������������������������0000644�0001751�0000144�00000024546�14561103552�021007� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CCOLAMD/Include/ccolamd.h: constrained column approx. min. degree ordering //------------------------------------------------------------------------------ // CCOLAMD, Copyright (c) 1996-2024, Timothy A. Davis, Sivasankaran // Rajamanickam, and Stefan Larimore. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* * You must include this file (ccolamd.h) in any routine that uses ccolamd, * csymamd, or the related macros and definitions. */ #ifndef CCOLAMD_H #define CCOLAMD_H #include "SuiteSparse_config.h" /* ========================================================================== */ /* === CCOLAMD version ====================================================== */ /* ========================================================================== */ /* All versions of CCOLAMD will include the following definitions. * As an example, to test if the version you are using is 1.3 or later: * * if (CCOLAMD_VERSION >= CCOLAMD_VERSION_CODE (1,3)) ... * * This also works during compile-time: * * #if CCOLAMD_VERSION >= CCOLAMD_VERSION_CODE (1,3) * printf ("This is version 1.3 or later\n") ; * #else * printf ("This is an early version\n") ; * #endif */ #define CCOLAMD_DATE "Jan 20, 2024" #define CCOLAMD_MAIN_VERSION 3 #define CCOLAMD_SUB_VERSION 3 #define CCOLAMD_SUBSUB_VERSION 2 #define CCOLAMD_VERSION_CODE(main,sub) SUITESPARSE_VER_CODE(main,sub) #define CCOLAMD_VERSION CCOLAMD_VERSION_CODE(3,3) #define CCOLAMD__VERSION SUITESPARSE__VERCODE(3,3,2) #if !defined (SUITESPARSE__VERSION) || \ (SUITESPARSE__VERSION < SUITESPARSE__VERCODE(7,6,0)) #error "CCOLAMD 3.3.2 requires SuiteSparse_config 7.6.0 or later" #endif /* ========================================================================== */ /* === Knob and statistics definitions ====================================== */ /* ========================================================================== */ /* size of the knobs [ ] array. Only knobs [0..3] are currently used. */ #define CCOLAMD_KNOBS 20 /* number of output statistics. Only stats [0..10] are currently used. */ #define CCOLAMD_STATS 20 /* knobs [0] and stats [0]: dense row knob and output statistic. */ #define CCOLAMD_DENSE_ROW 0 /* knobs [1] and stats [1]: dense column knob and output statistic. */ #define CCOLAMD_DENSE_COL 1 /* knobs [2]: aggressive absorption option */ #define CCOLAMD_AGGRESSIVE 2 /* knobs [3]: LU or Cholesky factorization option */ #define CCOLAMD_LU 3 /* stats [2]: memory defragmentation count output statistic */ #define CCOLAMD_DEFRAG_COUNT 2 /* stats [3]: ccolamd status: zero OK, > 0 warning or notice, < 0 error */ #define CCOLAMD_STATUS 3 /* stats [4..6]: error info, or info on jumbled columns */ #define CCOLAMD_INFO1 4 #define CCOLAMD_INFO2 5 #define CCOLAMD_INFO3 6 /* stats [7]: number of originally empty rows */ #define CCOLAMD_EMPTY_ROW 7 /* stats [8]: number of originally empty cols */ #define CCOLAMD_EMPTY_COL 8 /* stats [9]: number of rows with entries only in dense cols */ #define CCOLAMD_NEWLY_EMPTY_ROW 9 /* stats [10]: number of cols with entries only in dense rows */ #define CCOLAMD_NEWLY_EMPTY_COL 10 /* error codes returned in stats [3]: */ #define CCOLAMD_OK (0) #define CCOLAMD_OK_BUT_JUMBLED (1) #define CCOLAMD_ERROR_A_not_present (-1) #define CCOLAMD_ERROR_p_not_present (-2) #define CCOLAMD_ERROR_nrow_negative (-3) #define CCOLAMD_ERROR_ncol_negative (-4) #define CCOLAMD_ERROR_nnz_negative (-5) #define CCOLAMD_ERROR_p0_nonzero (-6) #define CCOLAMD_ERROR_A_too_small (-7) #define CCOLAMD_ERROR_col_length_negative (-8) #define CCOLAMD_ERROR_row_index_out_of_bounds (-9) #define CCOLAMD_ERROR_out_of_memory (-10) #define CCOLAMD_ERROR_invalid_cmember (-11) #define CCOLAMD_ERROR_internal_error (-999) /* ========================================================================== */ /* === Prototypes of user-callable routines ================================= */ /* ========================================================================== */ /* make it easy for C++ programs to include CCOLAMD */ #ifdef __cplusplus extern "C" { #endif size_t ccolamd_recommended /* returns recommended value of Alen, */ /* or 0 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 */ ) ; size_t ccolamd_l_recommended /* returns recommended value of Alen, */ /* or 0 if input arguments are erroneous */ ( int64_t nnz, /* nonzeros in A */ int64_t n_row, /* number of rows in A */ int64_t n_col /* number of columns in A */ ) ; void ccolamd_set_defaults /* sets default parameters */ ( /* knobs argument is modified on output */ double knobs [CCOLAMD_KNOBS] /* parameter settings for ccolamd */ ) ; void ccolamd_l_set_defaults /* sets default parameters */ ( /* knobs argument is modified on output */ double knobs [CCOLAMD_KNOBS] /* parameter settings for ccolamd */ ) ; int ccolamd /* 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 [CCOLAMD_KNOBS],/* parameter settings for ccolamd */ int stats [CCOLAMD_STATS], /* ccolamd output statistics and error codes */ int cmember [ ] /* Constraint set of A, of size n_col */ ) ; int ccolamd_l /* as ccolamd w/ int64_t integers */ ( int64_t n_row, int64_t n_col, int64_t Alen, int64_t A [ ], int64_t p [ ], double knobs [CCOLAMD_KNOBS], int64_t stats [CCOLAMD_STATS], int64_t cmember [ ] ) ; int csymamd /* 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 [CCOLAMD_KNOBS],/* parameters (uses defaults if NULL) */ int stats [CCOLAMD_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) */ int cmember [ ], /* Constraint set of A */ int stype /* 0: use both parts, >0: upper, <0: lower */ ) ; int csymamd_l /* as csymamd, w/ int64_t integers */ ( int64_t n, int64_t A [ ], int64_t p [ ], int64_t perm [ ], double knobs [CCOLAMD_KNOBS], int64_t stats [CCOLAMD_STATS], void * (*allocate) (size_t, size_t), void (*release) (void *), int64_t cmember [ ], int64_t stype ) ; void ccolamd_report ( int stats [CCOLAMD_STATS] ) ; void ccolamd_l_report ( int64_t stats [CCOLAMD_STATS] ) ; void csymamd_report ( int stats [CCOLAMD_STATS] ) ; void csymamd_l_report ( int64_t stats [CCOLAMD_STATS] ) ; void ccolamd_version (int version [3]) ; /* ========================================================================== */ /* === Prototypes of "expert" routines ====================================== */ /* ========================================================================== */ /* These routines are meant to be used internally, or in a future version of * UMFPACK. They appear here so that UMFPACK can use them, but they should not * be called directly by the user. */ int ccolamd2 ( /* 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 [CCOLAMD_KNOBS],/* parameter settings for ccolamd */ int stats [CCOLAMD_STATS], /* ccolamd output statistics and error codes */ /* 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 row in front f */ int cmember [ ] /* Constraint set of A */ ) ; int ccolamd2_l /* as ccolamd2, w/ int64_t integers */ ( int64_t n_row, int64_t n_col, int64_t Alen, int64_t A [ ], int64_t p [ ], double knobs [CCOLAMD_KNOBS], int64_t stats [CCOLAMD_STATS], int64_t Front_npivcol [ ], int64_t Front_nrows [ ], int64_t Front_ncols [ ], int64_t Front_parent [ ], int64_t Front_cols [ ], int64_t *p_nfr, int64_t InFront [ ], int64_t cmember [ ] ) ; void ccolamd_apply_order ( int Front [ ], const int Order [ ], int Temp [ ], int nn, int nfr ) ; void ccolamd_l_apply_order ( int64_t Front [ ], const int64_t Order [ ], int64_t Temp [ ], int64_t nn, int64_t nfr ) ; void ccolamd_fsize ( int nn, int MaxFsize [ ], int Fnrows [ ], int Fncols [ ], int Parent [ ], int Npiv [ ] ) ; void ccolamd_l_fsize ( int64_t nn, int64_t MaxFsize [ ], int64_t Fnrows [ ], int64_t Fncols [ ], int64_t Parent [ ], int64_t Npiv [ ] ) ; void ccolamd_postorder ( int nn, int Parent [ ], int Npiv [ ], int Fsize [ ], int Order [ ], int Child [ ], int Sibling [ ], int Stack [ ], int Front_cols [ ], int cmember [ ] ) ; void ccolamd_l_postorder ( int64_t nn, int64_t Parent [ ], int64_t Npiv [ ], int64_t Fsize [ ], int64_t Order [ ], int64_t Child [ ], int64_t Sibling [ ], int64_t Stack [ ], int64_t Front_cols [ ], int64_t cmember [ ] ) ; int ccolamd_post_tree ( int root, int k, int Child [ ], const int Sibling [ ], int Order [ ], int Stack [ ] ) ; int64_t ccolamd_l_post_tree ( int64_t root, int64_t k, int64_t Child [ ], const int64_t Sibling [ ], int64_t Order [ ], int64_t Stack [ ] ) ; #ifdef __cplusplus } #endif #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CCOLAMD/Makefile�������������������������������������������������������������0000644�0001751�0000144�00000000560�14576344042�017306� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sources = Source/ccolamd.c Source/ccolamd_l.c Source/ccolamd_version.c objects = $(sources:.c=.o) archive = CCOLAMD.a PKG_CPPFLAGS = -I./Include -I../SuiteSparse_config all : $(archive) $(archive) : $(objects) rm -f $@ $(AR) -cr $@ $(objects) $(RANLIB) $@ .c.o : $(CC) $(PKG_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) -c $< -o $*.o clean : @rm -f $(objects) $(archive) ������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CCOLAMD/Source/��������������������������������������������������������������0000755�0001751�0000144�00000000000�14576344041�017104� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CCOLAMD/Source/ccolamd.c�����������������������������������������������������0000644�0001751�0000144�00000420030�14552026002�020635� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CCOLAMD/Source/ccolamd.c: constrained column ordering //------------------------------------------------------------------------------ // CCOLAMD, Copyright (c) 2005-2022, Univ. of Florida, All Rights Reserved. // Authors: Timothy A. Davis, Sivasankaran Rajamanickam, and Stefan Larimore. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* * ccolamd: a constrained approximate minimum degree column ordering * algorithm, LU factorization of symmetric or unsymmetric matrices, * QR factorization, least squares, interior point methods for * linear programming problems, and other related problems. * * csymamd: a constrained approximate minimum degree ordering algorithm for * Cholesky factorization of symmetric matrices. * * Purpose: * * CCOLAMD 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. CCOLAMD is an * extension of COLAMD, 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 COLAMD in MATLAB. * * CSYMAMD 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. CSYMAMD 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. CSYMAMD is an extension of SYMAMD. * * Authors: * * Timothy A. Davis and S. Rajamanickam wrote CCOLAMD, based directly on * COLAMD by Stefan I. Larimore and Timothy A. Davis, University of * Florida. The algorithm was developed in collaboration with John * Gilbert, (UCSB, then at Xerox PARC), and Esmond Ng, (Lawrence Berkeley * National Lab, then at Oak Ridge National Laboratory). * * Acknowledgements: * * This work was supported by the National Science Foundation, under * grants DMS-9504974 and DMS-9803599, CCR-0203270, and a grant from the * Sandia National Laboratory (Dept. of Energy). * * Copyright and License: * * Copyright (c) 1998-2022 by the University of Florida. * All Rights Reserved. * CCOLAMD is also available under alternate licenses, contact T. Davis * for details. * * See CCOLAMD/Doc/License.txt for the license. * * Availability: * * The CCOLAMD/CSYMAMD library is available at * * http://www.suitesparse.com * * See the ChangeLog file for changes since Version 1.0. */ /* ========================================================================== */ /* === Description of user-callable routines ================================ */ /* ========================================================================== */ /* CCOLAMD includes both int32_t and int64_t versions of all its routines. * The description below is for the int32_t version. For int64_t, all * int32_t arguments become int64_t integers. */ /* ---------------------------------------------------------------------------- * ccolamd_recommended: * ---------------------------------------------------------------------------- * * C syntax: * * #include "ccolamd.h" * size_t ccolamd_recommended (int32_t nnz, int32_t n_row, int32_t n_col) ; * size_t ccolamd_l_recommended (int64_t nnz, * int64_t n_row, int64_t n_col) ; * * Purpose: * * Returns recommended value of Alen for use by ccolamd. Returns 0 * if any input argument is negative. The use of this routine * is optional. Not needed for csymamd, which dynamically allocates * its own memory. * * Arguments (all input arguments): * * int32_t nnz ; Number of nonzeros in the matrix A. This must * be the same value as p [n_col] in the call to * ccolamd - otherwise you will get a wrong value * of the recommended memory to use. * * int32_t n_row ; Number of rows in the matrix A. * * int32_t n_col ; Number of columns in the matrix A. * * ---------------------------------------------------------------------------- * ccolamd_set_defaults: * ---------------------------------------------------------------------------- * * C syntax: * * #include "ccolamd.h" * ccolamd_set_defaults (double knobs [CCOLAMD_KNOBS]) ; * ccolamd_l_set_defaults (double knobs [CCOLAMD_KNOBS]) ; * * Purpose: * * Sets the default parameters. The use of this routine is optional. * Passing a (double *) NULL pointer for the knobs results in the * default parameter settings. * * Arguments: * * double knobs [CCOLAMD_KNOBS] ; Output only. * * knobs [0] and knobs [1] behave differently than they did in COLAMD. * The other knobs are new to CCOLAMD. * * knobs [0]: dense row control * * For CCOLAMD, rows with more than * max (16, knobs [CCOLAMD_DENSE_ROW] * sqrt (n_col)) * entries are removed prior to ordering. * * For CSYMAMD, rows and columns with more than * max (16, knobs [CCOLAMD_DENSE_ROW] * sqrt (n)) * entries are removed prior to ordering, and placed last in the * output ordering (subject to the constraints). * * If negative, only completely dense rows are removed. If you * intend to use CCOLAMD for a Cholesky factorization of A*A', set * knobs [CCOLAMD_DENSE_ROW] to -1, which is more appropriate for * that case. * * Default: 10. * * knobs [1]: dense column control * * For CCOLAMD, columns with more than * max (16, knobs [CCOLAMD_DENSE_COL] * sqrt (MIN (n_row,n_col))) * entries are removed prior to ordering, and placed last in the * output column ordering (subject to the constraints). * Not used by CSYMAMD. If negative, only completely dense * columns are removed. Default: 10. * * knobs [2]: aggressive absorption * * knobs [CCOLAMD_AGGRESSIVE] controls whether or not to do * aggressive absorption during the ordering. Default is TRUE * (nonzero). If zero, no aggressive absorption is performed. * * knobs [3]: optimize ordering for LU or Cholesky * * knobs [CCOLAMD_LU] controls an option that optimizes the * ordering for the LU of A or the Cholesky factorization of A'A. * If TRUE (nonzero), an ordering optimized for LU is performed. * If FALSE (zero), an ordering for Cholesky is performed. * Default is FALSE. CSYMAMD ignores this parameter; it always * orders for Cholesky. * * ---------------------------------------------------------------------------- * ccolamd: * ---------------------------------------------------------------------------- * * C syntax: * * #include "ccolamd.h" * int ccolamd (int32_t n_row, int32_t n_col, int32_t Alen, int32_t *A, * int32_t *p, double knobs [CCOLAMD_KNOBS], * int32_t stats [CCOLAMD_STATS], int32_t *cmember) ; * * int64_t ccolamd_l (int64_t n_row, * int64_t n_col, int64_t Alen, * int64_t *A, int64_t *p, * double knobs [CCOLAMD_KNOBS], * int64_t stats [CCOLAMD_STATS], * int64_t *cmember) ; * * 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 (for int32_t version): * * int32_t n_row ; Input argument. * * Number of rows in the matrix A. * Restriction: n_row >= 0. * ccolamd returns FALSE if n_row is negative. * * int32_t n_col ; Input argument. * * Number of columns in the matrix A. * Restriction: n_col >= 0. * ccolamd returns FALSE if n_col is negative. * * int32_t Alen ; Input argument. * * Restriction (see note): * Alen >= MAX (2*nnz, 4*n_col) + 17*n_col + 7*n_row + 7, where * nnz = p [n_col]. ccolamd returns FALSE if this condition is * not met. We recommend about nnz/5 more space for better * efficiency. This restriction makes an modest assumption * regarding the size of two typedef'd structures in ccolamd.h. * We do, however, guarantee that * * Alen >= ccolamd_recommended (nnz, n_row, n_col) * * will work efficiently. * * int32_t 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 * ccolamd_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, ccolamd will * work a little faster if both of these conditions are met * (ccolamd 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. ccolamd * returns FALSE if any row index is out of range. * * The contents of A are modified during ordering, and are * undefined on output. * * int32_t 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 nnz = p [n_col] * is thus the total number of entries in the pattern of the * matrix A. ccolamd returns FALSE if these conditions are not * met. * * On output, if ccolamd 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 ccolamd returns FALSE, then no permutation is returned, and * p is undefined on output. * * double knobs [CCOLAMD_KNOBS] ; Input argument. * * See ccolamd_set_defaults for a description. * * int32_t stats [CCOLAMD_STATS] ; Output argument. * * Statistics on the ordering, and error status. * See ccolamd.h for related definitions. * ccolamd 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, subject to the * constraints). 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). CCOLAMD 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 ccolamd was TRUE). * * stats [4]: highest column index of jumbled columns * 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 csymamd) * * int32_t cmember [n_col] ; Input argument. * * cmember is new to CCOLAMD. It did not appear in COLAMD. * It places contraints on the output ordering. s = cmember [j] * gives the constraint set s that contains the column j * (Restriction: 0 <= s < n_col). In the output column * permutation, all columns in set 0 appear first, followed by * all columns in set 1, and so on. If NULL, all columns are * treated as if they were in a single constraint set, and you * will obtain the same ordering as COLAMD (with one exception: * the dense row/column threshold and other default knobs in * CCOLAMD and COLAMD are different). * * Example: * * See ccolamd_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, no output statistics, and no ordering * constraints, do the following: * * #include "ccolamd.h" * #define ALEN 144 * int32_t A [ALEN] = {0, 1, 4, 2, 4, 0, 1, 2, 3, 1, 3} ; * int32_t p [ ] = {0, 3, 5, 9, 11} ; * int32_t stats [CCOLAMD_STATS] ; * ccolamd (5, 4, ALEN, A, p, (double *) NULL, stats, NULL) ; * * The permutation is returned in the array p, and A is destroyed. * * ---------------------------------------------------------------------------- * csymamd: * ---------------------------------------------------------------------------- * * C syntax: * * #include "ccolamd.h" * * int csymamd (int32_t n, int32_t *A, int32_t *p, int32_t *perm, * double knobs [CCOLAMD_KNOBS], int32_t stats [CCOLAMD_STATS], * void (*allocate) (size_t, size_t), void (*release) (void *), * int32_t *cmember, int32_t stype) ; * * int64_t csymamd_l (int64_t n, * int64_t *A, int64_t *p, * int64_t *perm, double knobs [CCOLAMD_KNOBS], * int64_t stats [CCOLAMD_STATS], void (*allocate) * (size_t, size_t), void (*release) (void *), * int64_t *cmember, int64_t stype) ; * * Purpose: * * The csymamd 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. Either the * lower or upper triangular part of A can be used, or the pattern * A+A' can be used. You must pass your selected memory allocator * (usually calloc/free or mxCalloc/mxFree) to csymamd, for it to * allocate memory for the temporary matrix M. * * Returns: * * TRUE (1) if successful, FALSE (0) otherwise. * * Arguments: * * int32_t n ; Input argument. * * Number of rows and columns in the symmetrix matrix A. * Restriction: n >= 0. * csymamd returns FALSE if n is negative. * * int32_t 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, csymamd 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. csymamd * returns FALSE if any row index is out of range. * * The contents of A are not modified. * * int32_t 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. * csymamd returns FALSE if these conditions are not met. * * The contents of p are not modified. * * int32_t perm [n+1] ; Output argument. * * On output, if csymamd 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 [CCOLAMD_KNOBS] ; Input argument. * * See colamd_set_defaults for a description. * * int32_t stats [CCOLAMD_STATS] ; Output argument. * * Statistics on the ordering, and error status. * See ccolamd.h for related definitions. * csymand 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, subject * to the constraints). 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 to -9: same as ccolamd, with n replacing n_col and n_row, * and -3 and -7 are unused. * * -10 out of memory (unable to allocate temporary workspace * for M or count arrays using the "allocate" routine * passed into csymamd). * * 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. * * int32_t cmember [n] ; Input argument. * * Same as ccolamd, except that cmember is of size n, and it places * contraints symmetrically, on both the row and column ordering. * Entries in cmember must be in the range 0 to n-1. * * int32_t stype ; Input argument. * * If stype < 0, then only the strictly lower triangular part of * A is accessed. The upper triangular part is assumed to be the * transpose of the lower triangular part. This is the same as * SYMAMD, which did not have an stype parameter. * * If stype > 0, only the strictly upper triangular part of A is * accessed. The lower triangular part is assumed to be the * transpose of the upper triangular part. * * If stype == 0, then the nonzero pattern of A+A' is ordered. * * ---------------------------------------------------------------------------- * ccolamd_report: * ---------------------------------------------------------------------------- * * C syntax: * * #include "ccolamd.h" * ccolamd_report (int32_t stats [CCOLAMD_STATS]) ; * ccolamd_l_report (int64_t stats [CCOLAMD_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: * * int32_t stats [CCOLAMD_STATS] ; Input only. Statistics from ccolamd. * * * ---------------------------------------------------------------------------- * csymamd_report: * ---------------------------------------------------------------------------- * * C syntax: * * #include "ccolamd.h" * csymamd_report (int32_t stats [CCOLAMD_STATS]) ; * csymamd_l_report (int64_t stats [CCOLAMD_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: * * int32_t stats [CCOLAMD_STATS] ; Input only. Statistics from csymamd. * */ /* ========================================================================== */ /* === Scaffolding code definitions ======================================== */ /* ========================================================================== */ /* Ensure that debugging is turned off: */ #ifndef NDEBUG #define NDEBUG #endif /* turn on debugging by uncommenting the following line #undef NDEBUG */ /* ========================================================================== */ /* === Include files ======================================================== */ /* ========================================================================== */ #include "ccolamd.h" #ifndef NULL #define NULL ((void *) 0) #endif /* ========================================================================== */ /* === int32_t or int64_t ============================================== */ /* ========================================================================== */ #ifdef DLONG #define Int int64_t #define UInt uint64_t #define ID "%" PRId64 #define Int_MAX INT64_MAX #define CCOLAMD_recommended ccolamd_l_recommended #define CCOLAMD_set_defaults ccolamd_l_set_defaults #define CCOLAMD_2 ccolamd2_l #define CCOLAMD_MAIN ccolamd_l #define CCOLAMD_apply_order ccolamd_l_apply_order #define CCOLAMD_postorder ccolamd_l_postorder #define CCOLAMD_post_tree ccolamd_l_post_tree #define CCOLAMD_fsize ccolamd_l_fsize #define CSYMAMD_MAIN csymamd_l #define CCOLAMD_report ccolamd_l_report #define CSYMAMD_report csymamd_l_report #else #define Int int32_t #define UInt uint32_t #define ID "%d" #define Int_MAX INT32_MAX #define CCOLAMD_recommended ccolamd_recommended #define CCOLAMD_set_defaults ccolamd_set_defaults #define CCOLAMD_2 ccolamd2 #define CCOLAMD_MAIN ccolamd #define CCOLAMD_apply_order ccolamd_apply_order #define CCOLAMD_postorder ccolamd_postorder #define CCOLAMD_post_tree ccolamd_post_tree #define CCOLAMD_fsize ccolamd_fsize #define CSYMAMD_MAIN csymamd #define CCOLAMD_report ccolamd_report #define CSYMAMD_report csymamd_report #endif /* ========================================================================== */ /* === Row and Column structures ============================================ */ /* ========================================================================== */ typedef struct CColamd_Col_struct { /* size of this struct is 8 integers if no padding occurs */ 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 ; Int order ; } 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 ; Int nextcol ; /* next column in this supercolumn */ Int lastcol ; /* last column in this supercolumn */ } CColamd_Col ; typedef struct CColamd_Row_struct { /* size of this struct is 6 integers if no padding occurs */ 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 ; 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 */ } CColamd_Row ; /* ========================================================================== */ /* === basic definitions ==================================================== */ /* ========================================================================== */ #define EMPTY (-1) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) /* Routines are either public (user-callable) or PRIVATE (not user-callable) */ #define PRIVATE static #define DENSE_DEGREE(alpha,n) \ ((Int) MAX (16.0, (alpha) * sqrt ((double) (n)))) #define CMEMBER(c) ((cmember == (Int *) NULL) ? (0) : (cmember [c])) /* True if x is NaN */ #define SCALAR_IS_NAN(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)) #define ONES_COMPLEMENT(r) (-(r)-1) #undef TRUE #undef FALSE #define TRUE (1) #define FALSE (0) /* 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 ; } /* ========================================================================== */ /* === ccolamd reporting mechanism ========================================== */ /* ========================================================================== */ #if defined (MATLAB_MEX_FILE) || defined (MATHWORKS) /* In MATLAB, matrices are 1-based to the user, but 0-based internally */ #define INDEX(i) ((i)+1) #else /* In C, matrices are 0-based and indices are reported as such in *_report */ #define INDEX(i) (i) #endif /* ========================================================================== */ /* === Debugging prototypes and definitions ================================= */ /* ========================================================================== */ #ifndef NDEBUG #include /* debug print level, present only when debugging */ PRIVATE Int ccolamd_debug ; /* debug print statements */ #define DEBUG0(params) { SUITESPARSE_PRINTF (params) ; } #define DEBUG1(params) { if (ccolamd_debug >= 1) SUITESPARSE_PRINTF (params) ; } #define DEBUG2(params) { if (ccolamd_debug >= 2) SUITESPARSE_PRINTF (params) ; } #define DEBUG3(params) { if (ccolamd_debug >= 3) SUITESPARSE_PRINTF (params) ; } #define DEBUG4(params) { if (ccolamd_debug >= 4) SUITESPARSE_PRINTF (params) ; } #ifdef MATLAB_MEX_FILE #define ASSERT(expression) (mxAssert ((expression), "")) #else #define ASSERT(expression) (assert (expression)) #endif PRIVATE void ccolamd_get_debug ( char *method ) ; PRIVATE void debug_mark ( Int n_row, CColamd_Row Row [], Int tag_mark, Int max_mark ) ; PRIVATE void debug_matrix ( Int n_row, Int n_col, CColamd_Row Row [], CColamd_Col Col [], Int A [] ) ; PRIVATE void debug_structures ( Int n_row, Int n_col, CColamd_Row Row [], CColamd_Col Col [], Int A [], Int in_cset [], Int cset_start [] ) ; PRIVATE void dump_super ( Int super_c, CColamd_Col Col [], Int n_col ) ; PRIVATE void debug_deg_lists ( Int n_row, Int n_col, CColamd_Row Row [ ], CColamd_Col Col [ ], Int head [ ], Int min_score, Int should, Int max_deg ) ; #else /* === No debugging ========================================================= */ #define DEBUG0(params) ; #define DEBUG1(params) ; #define DEBUG2(params) ; #define DEBUG3(params) ; #define DEBUG4(params) ; #define ASSERT(expression) #endif /* ========================================================================== */ /* === Prototypes of PRIVATE routines ======================================= */ /* ========================================================================== */ PRIVATE Int init_rows_cols ( Int n_row, Int n_col, CColamd_Row Row [ ], CColamd_Col Col [ ], Int A [ ], Int p [ ], Int stats [CCOLAMD_STATS] ) ; PRIVATE void init_scoring ( Int n_row, Int n_col, CColamd_Row Row [ ], CColamd_Col Col [ ], Int A [ ], Int head [ ], double knobs [CCOLAMD_KNOBS], Int *p_n_row2, Int *p_n_col2, Int *p_max_deg, Int cmember [ ], Int n_cset, Int cset_start [ ], Int dead_cols [ ], 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, CColamd_Row Row [ ], CColamd_Col Col [ ], Int A [ ], Int head [ ], #ifndef NDEBUG Int n_col2, #endif Int max_deg, Int pfree, Int cset [ ], Int cset_start [ ], #ifndef NDEBUG Int n_cset, #endif Int cmember [ ], Int Front_npivcol [ ], Int Front_nrows [ ], Int Front_ncols [ ], Int Front_parent [ ], Int Front_cols [ ], Int *p_nfr, Int aggressive, Int InFront [ ], Int order_for_lu ) ; PRIVATE void detect_super_cols ( #ifndef NDEBUG Int n_col, CColamd_Row Row [ ], #endif CColamd_Col Col [ ], Int A [ ], Int head [ ], Int row_start, Int row_length, Int in_set [ ] ) ; PRIVATE Int garbage_collection ( Int n_row, Int n_col, CColamd_Row Row [ ], CColamd_Col Col [ ], Int A [ ], Int *pfree ) ; PRIVATE Int clear_mark ( Int tag_mark, Int max_mark, Int n_row, CColamd_Row Row [ ] ) ; PRIVATE void print_report ( char *method, Int stats [CCOLAMD_STATS] ) ; /* ========================================================================== */ /* === USER-CALLABLE ROUTINES: ============================================== */ /* ========================================================================== */ /* ========================================================================== */ /* === ccolamd_recommended ================================================== */ /* ========================================================================== */ /* * The ccolamd_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 ccolamd. If any * argument is negative, or if integer overflow occurs, a 0 is returned as * an error condition. * * 2*nnz space is required for the row and column indices of the matrix * (or 4*n_col, which ever is larger). * * CCOLAMD_C (n_col) + CCOLAMD_R (n_row) space is required for the Col and Row * arrays, respectively, which are internal to ccolamd. This is equal to * 8*n_col + 6*n_row if the structures are not padded. * * An additional n_col space is the minimal amount of "elbow room", * and nnz/5 more space is recommended for run time efficiency. * * The remaining (((3 * n_col) + 1) + 5 * (n_col + 1) + n_row) space is * for other workspace used in ccolamd which did not appear in colamd. */ /* add two values of type size_t, and check for integer overflow */ static size_t t_add (size_t a, size_t b, int *ok) { (*ok) = (*ok) && ((a + b) >= MAX (a,b)) ; return ((*ok) ? (a + b) : 0) ; } /* compute a*k where k is a small integer, and check for integer overflow */ static size_t t_mult (size_t a, size_t k, int *ok) { size_t i, s = 0 ; for (i = 0 ; i < k ; i++) { s = t_add (s, a, ok) ; } return (s) ; } /* size of the Col and Row structures */ #define CCOLAMD_C(n_col,ok) \ ((t_mult (t_add (n_col, 1, ok), sizeof (CColamd_Col), ok) / sizeof (Int))) #define CCOLAMD_R(n_row,ok) \ ((t_mult (t_add (n_row, 1, ok), sizeof (CColamd_Row), ok) / sizeof (Int))) /* #define CCOLAMD_RECOMMENDED(nnz, n_row, n_col) \ MAX (2 * nnz, 4 * n_col) + \ CCOLAMD_C (n_col) + CCOLAMD_R (n_row) + n_col + (nnz / 5) \ + ((3 * n_col) + 1) + 5 * (n_col + 1) + n_row */ static size_t ccolamd_need (Int nnz, Int n_row, Int n_col, int *ok) { /* ccolamd_need, compute the following, and check for integer overflow: need = MAX (2*nnz, 4*n_col) + n_col + Col_size + Row_size + (3*n_col+1) + (5*(n_col+1)) + n_row ; */ size_t s, c, r, t ; /* MAX (2*nnz, 4*n_col) */ s = t_mult (nnz, 2, ok) ; /* 2*nnz */ t = t_mult (n_col, 4, ok) ; /* 4*n_col */ s = MAX (s,t) ; s = t_add (s, n_col, ok) ; /* bare minimum elbow room */ /* Col and Row arrays */ c = CCOLAMD_C (n_col, ok) ; /* size of column structures */ r = CCOLAMD_R (n_row, ok) ; /* size of row structures */ s = t_add (s, c, ok) ; s = t_add (s, r, ok) ; c = t_mult (n_col, 3, ok) ; /* 3*n_col + 1 */ c = t_add (c, 1, ok) ; s = t_add (s, c, ok) ; c = t_add (n_col, 1, ok) ; /* 5 * (n_col + 1) */ c = t_mult (c, 5, ok) ; s = t_add (s, c, ok) ; s = t_add (s, n_row, ok) ; /* n_row */ return (ok ? s : 0) ; } size_t CCOLAMD_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 */ ) { size_t s ; int ok = TRUE ; if (nnz < 0 || n_row < 0 || n_col < 0) { return (0) ; } s = ccolamd_need (nnz, n_row, n_col, &ok) ; /* bare minimum needed */ s = t_add (s, nnz/5, &ok) ; /* extra elbow room */ return (ok ? s : 0) ; } /* ========================================================================== */ /* === ccolamd_set_defaults ================================================= */ /* ========================================================================== */ /* * The ccolamd_set_defaults routine sets the default values of the user- * controllable parameters for ccolamd. */ void CCOLAMD_set_defaults ( /* === Parameters ======================================================= */ double knobs [CCOLAMD_KNOBS] /* knob array */ ) { /* === Local variables ================================================== */ Int i ; if (!knobs) { return ; /* no knobs to initialize */ } for (i = 0 ; i < CCOLAMD_KNOBS ; i++) { knobs [i] = 0 ; } knobs [CCOLAMD_DENSE_ROW] = 10 ; knobs [CCOLAMD_DENSE_COL] = 10 ; knobs [CCOLAMD_AGGRESSIVE] = TRUE ; /* default: do aggressive absorption*/ knobs [CCOLAMD_LU] = FALSE ; /* default: order for Cholesky */ } /* ========================================================================== */ /* === symamd =============================================================== */ /* ========================================================================== */ int CSYMAMD_MAIN /* 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 [CCOLAMD_KNOBS], /* parameters (uses defaults if NULL) */ Int stats [CCOLAMD_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) */ Int cmember [ ], /* constraint set */ Int stype /* stype of A */ ) { /* === Local variables ================================================== */ double cknobs [CCOLAMD_KNOBS] ; double default_knobs [CCOLAMD_KNOBS] ; 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 */ size_t 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 */ Int both ; /* TRUE if ordering A+A' */ Int upper ; /* TRUE if ordering triu(A)+triu(A)' */ Int lower ; /* TRUE if ordering tril(A)+tril(A)' */ #ifndef NDEBUG ccolamd_get_debug ("csymamd") ; #endif both = (stype == 0) ; upper = (stype > 0) ; lower = (stype < 0) ; /* === Check the input arguments ======================================== */ if (!stats) { DEBUG1 (("csymamd: stats not present\n")) ; return (FALSE) ; } for (i = 0 ; i < CCOLAMD_STATS ; i++) { stats [i] = 0 ; } stats [CCOLAMD_STATUS] = CCOLAMD_OK ; stats [CCOLAMD_INFO1] = -1 ; stats [CCOLAMD_INFO2] = -1 ; if (!A) { stats [CCOLAMD_STATUS] = CCOLAMD_ERROR_A_not_present ; DEBUG1 (("csymamd: A not present\n")) ; return (FALSE) ; } if (!p) /* p is not present */ { stats [CCOLAMD_STATUS] = CCOLAMD_ERROR_p_not_present ; DEBUG1 (("csymamd: p not present\n")) ; return (FALSE) ; } if (n < 0) /* n must be >= 0 */ { stats [CCOLAMD_STATUS] = CCOLAMD_ERROR_ncol_negative ; stats [CCOLAMD_INFO1] = n ; DEBUG1 (("csymamd: n negative "ID" \n", n)) ; return (FALSE) ; } nnz = p [n] ; if (nnz < 0) /* nnz must be >= 0 */ { stats [CCOLAMD_STATUS] = CCOLAMD_ERROR_nnz_negative ; stats [CCOLAMD_INFO1] = nnz ; DEBUG1 (("csymamd: number of entries negative "ID" \n", nnz)) ; return (FALSE) ; } if (p [0] != 0) { stats [CCOLAMD_STATUS] = CCOLAMD_ERROR_p0_nonzero ; stats [CCOLAMD_INFO1] = p [0] ; DEBUG1 (("csymamd: p[0] not zero "ID"\n", p [0])) ; return (FALSE) ; } /* === If no knobs, set default knobs =================================== */ if (!knobs) { CCOLAMD_set_defaults (default_knobs) ; knobs = default_knobs ; } /* === Allocate count and mark ========================================== */ count = (Int *) ((*allocate) (n+1, sizeof (Int))) ; if (!count) { stats [CCOLAMD_STATUS] = CCOLAMD_ERROR_out_of_memory ; DEBUG1 (("csymamd: allocate count (size "ID") failed\n", n+1)) ; return (FALSE) ; } mark = (Int *) ((*allocate) (n+1, sizeof (Int))) ; if (!mark) { stats [CCOLAMD_STATUS] = CCOLAMD_ERROR_out_of_memory ; (*release) ((void *) count) ; DEBUG1 (("csymamd: allocate mark (size "ID") failed\n", n+1)) ; return (FALSE) ; } /* === Compute column counts of M, check if A is valid ================== */ stats [CCOLAMD_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 [CCOLAMD_STATUS] = CCOLAMD_ERROR_col_length_negative ; stats [CCOLAMD_INFO1] = j ; stats [CCOLAMD_INFO2] = length ; (*release) ((void *) count) ; (*release) ((void *) mark) ; DEBUG1 (("csymamd: col "ID" negative length "ID"\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 [CCOLAMD_STATUS] = CCOLAMD_ERROR_row_index_out_of_bounds ; stats [CCOLAMD_INFO1] = j ; stats [CCOLAMD_INFO2] = i ; stats [CCOLAMD_INFO3] = n ; (*release) ((void *) count) ; (*release) ((void *) mark) ; DEBUG1 (("csymamd: row "ID" col "ID" 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 [CCOLAMD_STATUS] = CCOLAMD_OK_BUT_JUMBLED ; stats [CCOLAMD_INFO1] = j ; stats [CCOLAMD_INFO2] = i ; (stats [CCOLAMD_INFO3]) ++ ; DEBUG1 (("csymamd: row "ID" col "ID" unsorted/dupl.\n", i, j)) ; } if (mark [i] != j) { if ((both && i != j) || (lower && i > j) || (upper && 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 ; } } /* === 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 = CCOLAMD_recommended (mnz, n_row, n) ; M = (Int *) ((*allocate) (Mlen, sizeof (Int))) ; DEBUG1 (("csymamd: M is "ID"-by-"ID" with "ID" entries, Mlen = %g\n", n_row, n, mnz, (double) Mlen)) ; if (!M) { stats [CCOLAMD_STATUS] = CCOLAMD_ERROR_out_of_memory ; (*release) ((void *) count) ; (*release) ((void *) mark) ; DEBUG1 (("csymamd: allocate M (size %g) failed\n", (double) Mlen)) ; return (FALSE) ; } k = 0 ; if (stats [CCOLAMD_STATUS] == CCOLAMD_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 ((both && i != j) || (lower && i > j) || (upper && 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. */ DEBUG1 (("csymamd: 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 (mark [i] != j) { if ((both && i != j) || (lower && i > j) || (upper && i= 0 */ { stats [CCOLAMD_STATUS] = CCOLAMD_ERROR_nrow_negative ; stats [CCOLAMD_INFO1] = n_row ; DEBUG1 (("ccolamd: nrow negative "ID"\n", n_row)) ; return (FALSE) ; } if (n_col < 0) /* n_col must be >= 0 */ { stats [CCOLAMD_STATUS] = CCOLAMD_ERROR_ncol_negative ; stats [CCOLAMD_INFO1] = n_col ; DEBUG1 (("ccolamd: ncol negative "ID"\n", n_col)) ; return (FALSE) ; } nnz = p [n_col] ; if (nnz < 0) /* nnz must be >= 0 */ { stats [CCOLAMD_STATUS] = CCOLAMD_ERROR_nnz_negative ; stats [CCOLAMD_INFO1] = nnz ; DEBUG1 (("ccolamd: number of entries negative "ID"\n", nnz)) ; return (FALSE) ; } if (p [0] != 0) { stats [CCOLAMD_STATUS] = CCOLAMD_ERROR_p0_nonzero ; stats [CCOLAMD_INFO1] = p [0] ; DEBUG1 (("ccolamd: p[0] not zero "ID"\n", p [0])) ; return (FALSE) ; } /* === If no knobs, set default knobs =================================== */ if (!knobs) { CCOLAMD_set_defaults (default_knobs) ; knobs = default_knobs ; } aggressive = (knobs [CCOLAMD_AGGRESSIVE] != FALSE) ; order_for_lu = (knobs [CCOLAMD_LU] != FALSE) ; /* === Allocate workspace from array A ================================== */ ok = TRUE ; Col_size = CCOLAMD_C (n_col, &ok) ; Row_size = CCOLAMD_R (n_row, &ok) ; /* min size of A is 2nnz+ncol. cset and cset_start are of size 2ncol+1 */ /* Each of the 5 fronts is of size n_col + 1. InFront is of size nrow. */ /* need = MAX (2*nnz, 4*n_col) + n_col + Col_size + Row_size + (3*n_col+1) + (5*(n_col+1)) + n_row ; */ need = ccolamd_need (nnz, n_row, n_col, &ok) ; if (!ok || need > (size_t) Alen) { /* not enough space in array A to perform the ordering */ stats [CCOLAMD_STATUS] = CCOLAMD_ERROR_A_too_small ; stats [CCOLAMD_INFO1] = need ; stats [CCOLAMD_INFO2] = Alen ; DEBUG1 (("ccolamd: Need Alen >= "ID", given "ID"\n", need, Alen)) ; return (FALSE) ; } /* since integer overflow has been check, the following cannot overflow: */ Alen -= Col_size + Row_size + (3*n_col + 1) + 5*(n_col+1) + n_row ; /* 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. */ ap = Alen ; /* Front array workspace: 5*(n_col+1) + n_row */ if (!Front_npivcol || !Front_nrows || !Front_ncols || !Front_parent || !Front_cols || !Front_cols || !InFront) { Front_npivcol = &A [ap] ; ap += (n_col + 1) ; Front_nrows = &A [ap] ; ap += (n_col + 1) ; Front_ncols = &A [ap] ; ap += (n_col + 1) ; Front_parent = &A [ap] ; ap += (n_col + 1) ; Front_cols = &A [ap] ; ap += (n_col + 1) ; InFront = &A [ap] ; ap += (n_row) ; } else { /* Fronts are present. Leave the additional space as elbow room. */ ap += 5*(n_col+1) + n_row ; ap = Alen ; } /* Workspace for cset management: 3*n_col+1 */ /* cset_start is of size n_col + 1 */ cset_start = &A [ap] ; ap += n_col + 1 ; /* dead_col is of size n_col */ dead_cols = &A [ap] ; ap += n_col ; /* cset is of size n_col */ cset = &A [ap] ; ap += n_col ; /* Col is of size Col_size. The space is shared by temp_cstart and csize */ Col = (CColamd_Col *) &A [ap] ; temp_cstart = (Int *) Col ; /* [ temp_cstart is of size n_col+1 */ csize = temp_cstart + (n_col+1) ; /* csize is of size n_col+1 */ ap += Col_size ; ASSERT (Col_size >= 2*n_col+1) ; /* Row is of size Row_size */ Row = (CColamd_Row *) &A [ap] ; ap += Row_size ; /* Initialize csize & dead_cols to zero */ for (i = 0 ; i < n_col ; i++) { csize [i] = 0 ; dead_cols [i] = 0 ; } /* === Construct the constraint set ===================================== */ if (n_col == 0) { n_cset = 0 ; } else if (cmember == (Int *) NULL) { /* no constraint set; all columns belong to set zero */ n_cset = 1 ; csize [0] = n_col ; DEBUG1 (("no cmember present\n")) ; } else { n_cset = 0 ; for (i = 0 ; i < n_col ; i++) { if (cmember [i] < 0 || cmember [i] > n_col) { stats [CCOLAMD_STATUS] = CCOLAMD_ERROR_invalid_cmember ; DEBUG1 (("ccolamd: malformed cmember \n")) ; return (FALSE) ; } n_cset = MAX (n_cset, cmember [i]) ; csize [cmember [i]]++ ; } /* cset is zero based */ n_cset++ ; } ASSERT ((n_cset >= 0) && (n_cset <= n_col)) ; cset_start [0] = temp_cstart [0] = 0 ; for (i = 1 ; i <= n_cset ; i++) { cset_start [i] = cset_start [i-1] + csize [i-1] ; DEBUG4 ((" cset_start ["ID"] = "ID" \n", i , cset_start [i])) ; temp_cstart [i] = cset_start [i] ; } /* do in reverse order to encourage natural tie-breaking */ if (cmember == (Int *) NULL) { for (i = n_col-1 ; i >= 0 ; i--) { cset [temp_cstart [0]++] = i ; } } else { for (i = n_col-1 ; i >= 0 ; i--) { cset [temp_cstart [cmember [i]]++] = i ; } } /* ] temp_cstart and csize are no longer used */ /* === Construct the row and column data structures ===================== */ if (!init_rows_cols (n_row, n_col, Row, Col, A, p, stats)) { /* input matrix is invalid */ DEBUG1 (("ccolamd: Matrix invalid\n")) ; return (FALSE) ; } /* === 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, cmember, n_cset, cset_start, dead_cols, &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) ; DEBUG1 (("# dense rows "ID" cols "ID"\n", ndense_row, ndense_col)) ; /* === Order the supercolumns =========================================== */ ngarbage = find_ordering (n_row, n_col, Alen, Row, Col, A, p, #ifndef NDEBUG n_col2, #endif max_deg, 2*nnz, cset, cset_start, #ifndef NDEBUG n_cset, #endif cmember, Front_npivcol, Front_nrows, Front_ncols, Front_parent, Front_cols, &nfr, aggressive, InFront, order_for_lu) ; ASSERT (Alen >= 5*n_col) ; /* === Postorder ======================================================== */ /* 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 ; CCOLAMD_fsize (nfr, Front_size, Front_nrows, Front_ncols, Front_parent, Front_npivcol) ; CCOLAMD_postorder (nfr, Front_parent, Front_npivcol, Front_size, Front_order, Front_child, Front_sibling, Front_stack, Front_cols, cmember) ; /* Front_size, Front_stack, Front_child, Front_sibling no longer needed ] */ /* use A [0..nfr-1] as workspace */ CCOLAMD_apply_order (Front_npivcol, Front_order, A, nfr, nfr) ; CCOLAMD_apply_order (Front_nrows, Front_order, A, nfr, nfr) ; CCOLAMD_apply_order (Front_ncols, Front_order, A, nfr, nfr) ; CCOLAMD_apply_order (Front_parent, Front_order, A, nfr, nfr) ; CCOLAMD_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 ; set1 = 0 ; for (i = 0 ; i < nfr ; i++) { ASSERT (Front_npivcol [i] > 0) ; set2 = CMEMBER (Front_cols [i]) ; while (set1 < set2) { k += dead_cols [set1] ; DEBUG3 (("Skip null/dense columns of set "ID"\n",set1)) ; set1++ ; } set1 = set2 ; for (col = Front_cols [i] ; col != EMPTY ; col = Col [col].nextcol) { ASSERT (col >= 0 && col < n_col) ; DEBUG1 (("ccolamd output ordering: k "ID" col "ID"\n", k, col)) ; p [k] = col ; ASSERT (A [col] == EMPTY) ; #ifndef NDEBUG cs = CMEMBER (col) ; #endif ASSERT (k >= cset_start [cs] && k < cset_start [cs+1]) ; A [col] = k ; k++ ; } } /* === Order the "dense" and null columns =============================== */ if (n_col2 < n_col) { for (col = 0 ; col < n_col ; col++) { if (A [col] == EMPTY) { k = Col [col].shared2.order ; #ifndef NDEBUG cs = CMEMBER (col) ; dead_cols [cs]-- ; #endif ASSERT (k >= cset_start [cs] && k < cset_start [cs+1]) ; DEBUG1 (("ccolamd output ordering: k "ID" col "ID " (dense or null col)\n", k, col)) ; p [k] = col ; A [col] = k ; } } } #ifndef NDEBUG for (i = 0 ; i < n_cset ; i++) { ASSERT (dead_cols [i] == 0) ; } #endif /* === Return statistics in stats ======================================= */ stats [CCOLAMD_DENSE_ROW] = ndense_row ; stats [CCOLAMD_EMPTY_ROW] = nempty_row ; /* fixed in 2.7.3 */ stats [CCOLAMD_NEWLY_EMPTY_ROW] = nnewlyempty_row ; stats [CCOLAMD_DENSE_COL] = ndense_col ; stats [CCOLAMD_EMPTY_COL] = nempty_col ; stats [CCOLAMD_NEWLY_EMPTY_COL] = nnewlyempty_col ; ASSERT (ndense_col + nempty_col + nnewlyempty_col == n_col - n_col2) ; if (p_nfr) { *p_nfr = nfr ; } stats [CCOLAMD_DEFRAG_COUNT] = ngarbage ; DEBUG1 (("ccolamd: done.\n")) ; return (TRUE) ; } /* ========================================================================== */ /* === colamd_report ======================================================== */ /* ========================================================================== */ void CCOLAMD_report ( Int stats [CCOLAMD_STATS] ) { print_report ("ccolamd", stats) ; } /* ========================================================================== */ /* === symamd_report ======================================================== */ /* ========================================================================== */ void CSYMAMD_report ( Int stats [CCOLAMD_STATS] ) { print_report ("csymamd", 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 */ CColamd_Row Row [ ], /* of size n_row+1 */ CColamd_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 [CCOLAMD_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 [CCOLAMD_STATUS] = CCOLAMD_ERROR_col_length_negative ; stats [CCOLAMD_INFO1] = col ; stats [CCOLAMD_INFO2] = Col [col].length ; DEBUG1 (("ccolamd: col "ID" length "ID" < 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 ; 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 [CCOLAMD_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 ; Row [row].thickness = 1 ; Row [row].front = EMPTY ; } for (col = 0 ; col < n_col ; col++) { DEBUG1 (("\nCcolamd input column "ID":\n", col)) ; last_row = -1 ; cp = &A [p [col]] ; cp_end = &A [p [col+1]] ; while (cp < cp_end) { row = *cp++ ; DEBUG1 (("row: "ID"\n", row)) ; /* make sure row indices within range */ if (row < 0 || row >= n_row) { stats [CCOLAMD_STATUS] = CCOLAMD_ERROR_row_index_out_of_bounds ; stats [CCOLAMD_INFO1] = col ; stats [CCOLAMD_INFO2] = row ; stats [CCOLAMD_INFO3] = n_row ; DEBUG1 (("row "ID" col "ID" 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 [CCOLAMD_STATUS] = CCOLAMD_OK_BUT_JUMBLED ; stats [CCOLAMD_INFO1] = col ; stats [CCOLAMD_INFO2] = row ; (stats [CCOLAMD_INFO3]) ++ ; DEBUG1 (("row "ID" col "ID" 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 [CCOLAMD_STATUS] == CCOLAMD_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 [CCOLAMD_STATUS] == CCOLAMD_OK_BUT_JUMBLED) { DEBUG1 (("ccolamd: 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 /* === 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 */ CColamd_Row Row [ ], /* of size n_row+1 */ CColamd_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 [CCOLAMD_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 */ Int cmember [ ], Int n_cset, Int cset_start [ ], Int dead_cols [ ], 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 max_deg ; /* maximum row degree */ Int s ; /* a cset index */ 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 /* === Extract knobs ==================================================== */ /* Note: if knobs contains a NaN, this is undefined: */ if (knobs [CCOLAMD_DENSE_ROW] < 0) { /* only remove completely dense rows */ dense_row_count = n_col-1 ; } else { dense_row_count = DENSE_DEGREE (knobs [CCOLAMD_DENSE_ROW], n_col) ; } if (knobs [CCOLAMD_DENSE_COL] < 0) { /* only remove completely dense columns */ dense_col_count = n_row-1 ; } else { dense_col_count = DENSE_DEGREE (knobs [CCOLAMD_DENSE_COL], MIN (n_row, n_col)) ; } DEBUG1 (("densecount: "ID" "ID"\n", dense_row_count, dense_col_count)) ; max_deg = 0 ; n_col2 = n_col ; n_row2 = n_row ; /* Set the head array for bookkeeping of dense and empty columns. */ /* This will be used as hash buckets later. */ for (s = 0 ; s < n_cset ; s++) { head [s] = cset_start [s+1] ; } ndense_col = 0 ; nempty_col = 0 ; nnewlyempty_col = 0 ; ndense_row = 0 ; nempty_row = 0 ; nnewlyempty_row = 0 ; /* === 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 of its cset */ Col [c].shared2.order = --head [CMEMBER (c)] ; --n_col2 ; dead_cols [CMEMBER (c)] ++ ; nempty_col++ ; KILL_PRINCIPAL_COL (c) ; } } DEBUG1 (("ccolamd: null columns killed: "ID"\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 of its cset */ Col [c].shared2.order = --head [CMEMBER (c)] ; --n_col2 ; dead_cols [CMEMBER (c)] ++ ; 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 (("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) ; if (deg > dense_row_count) { /* There is at least one dense row. Continue ordering, but */ /* symbolic factorization will be redone after ccolamd 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) ; 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 (("ccolamd: 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 COLMMD 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) */ DEBUG1 (("Newly null killed: "ID"\n", c)) ; Col [c].shared2.order = -- head [CMEMBER (c)] ; --n_col2 ; dead_cols [CMEMBER (c)] ++ ; nnewlyempty_col++ ; 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 (("ccolamd: 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_count = 0 ; #endif /* clear the hash buckets */ for (c = 0 ; c <= n_col ; c++) { head [c] = EMPTY ; } #ifndef NDEBUG debug_structures (n_row, n_col, Row, Col, A, cmember, cset_start) ; #endif /* === Return number of remaining columns, and max row degree =========== */ *p_n_col2 = n_col2 ; *p_n_row2 = n_row2 ; *p_max_deg = max_deg ; *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 */ CColamd_Row Row [ ], /* of size n_row+1 */ CColamd_Col Col [ ], /* of size n_col+1 */ Int A [ ], /* column form and row form of A */ Int head [ ], /* of size n_col+1 */ #ifndef NDEBUG Int n_col2, /* Remaining columns to order */ #endif Int max_deg, /* Maximum row degree */ Int pfree, /* index of first free slot (2*nnz on entry) */ Int cset [ ], /* constraint set of A */ Int cset_start [ ], /* pointer to the start of every cset */ #ifndef NDEBUG Int n_cset, /* number of csets */ #endif Int cmember [ ], /* col -> cset mapping */ 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 [ ], Int order_for_lu ) { /* === 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 */ UInt 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 */ Int current_set ; /* consraint set that is being ordered */ Int score ; /* score of a column */ Int colstart ; /* pointer to first column in current cset */ Int colend ; /* pointer to last column in current cset */ Int deadcol ; /* number of dense & null columns in a cset */ #ifndef NDEBUG Int debug_d ; /* debug loop counter */ Int debug_step = 0 ; /* debug loop counter */ Int cols_thickness = 0 ; /* the thickness of the columns in current */ /* cset degreelist and in pivot row pattern. */ #endif 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 = Int_MAX - n_col ; /* Int_MAX defined in */ tag_mark = clear_mark (0, max_mark, n_row, Row) ; min_score = 0 ; ngarbage = 0 ; current_set = -1 ; deadcol = 0 ; DEBUG1 (("ccolamd: 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_col ; /* 'k' is incremented below */) { /* 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 /* Initialize the degree list with columns from next non-empty cset */ while ((k+deadcol) == cset_start [current_set+1]) { current_set++ ; DEBUG1 (("\n\n\n============ CSET: "ID"\n", current_set)) ; k += deadcol ; /* jump to start of next cset */ deadcol = 0 ; /* reset dead column count */ ASSERT ((current_set == n_cset) == (k == n_col)) ; /* return if all columns are ordered. */ if (k == n_col) { *p_nfr = nfr ; return (ngarbage) ; } #ifndef NDEBUG for (col = 0 ; col <= n_col ; col++) { ASSERT (head [col] == EMPTY) ; } #endif min_score = n_col ; colstart = cset_start [current_set] ; colend = cset_start [current_set+1] ; while (colstart < colend) { col = cset [colstart++] ; if (COL_IS_DEAD(col)) { DEBUG1 (("Column "ID" is dead\n", col)) ; /* count dense and null columns */ if (Col [col].shared2.order != EMPTY) { deadcol++ ; } continue ; } /* only add principal columns in current set to degree lists */ ASSERT (CMEMBER (col) == current_set) ; score = Col [col].shared2.score ; DEBUG1 (("Column "ID" is alive, score "ID"\n", col, 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 [col].shared3.prev = EMPTY ; Col [col].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 = col ; } head [score] = col ; /* see if this score is less than current min */ min_score = MIN (min_score, score) ; } #ifndef NDEBUG DEBUG1 (("degree lists initialized \n")) ; debug_deg_lists (n_row, n_col, Row, Col, head, min_score, ((cset_start [current_set+1]-cset_start [current_set])-deadcol), max_deg) ; #endif } #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++ ; DEBUG1 (("start of step k="ID": ", k)) ; debug_deg_lists (n_row, n_col, Row, Col, head, min_score, cset_start [current_set+1]-(k+deadcol), max_deg) ; debug_matrix (n_row, n_col, Row, Col, A) ; #endif /* === Select pivot column, and order it ============================ */ 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)) ; /* 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) ; DEBUG3 (("Pivot col: "ID" thick "ID"\n", pivot_col, pivot_col_thickness)) ; /* === 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 Row [ ].shared2.mark array */ tag_mark = clear_mark (0, max_mark, n_row, Row) ; #ifndef NDEBUG debug_matrix (n_row, n_col, Row, Col, A) ; #endif } /* === 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 ; 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++ ; ASSERT (row >= 0 && row < n_row) ; DEBUG4 (("Pivcol pattern "ID" "ID"\n", ROW_IS_ALIVE (row), row)) ; /* skip if row is dead */ if (ROW_IS_ALIVE (row)) { /* sum the thicknesses of all the rows */ 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 ; DEBUG4 (("\t\t\tNew live col in pivrow: "ID"\n",col)) ; } #ifndef NDEBUG if (col_thickness < 0 && COL_IS_ALIVE (col)) { DEBUG4 (("\t\t\tOld live col in pivrow: "ID"\n",col)) ; } #endif } } } /* pivot_row_thickness is the number of rows in frontal matrix */ /* including 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 /* === 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: "ID"\n", row)) ; ASSERT (row >= 0 && row < n_row) ; 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) ; 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: ")) ; /* 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 =========================== */ /* only columns in current_set will be in degree list */ if (CMEMBER (col) == current_set) { #ifndef NDEBUG cols_thickness += col_thickness ; #endif cur_score = Col [col].shared2.score ; prev_col = Col [col].shared3.prev ; next_col = Col [col].shared4.degree_next ; DEBUG3 ((" cur_score "ID" prev_col "ID" next_col "ID"\n", cur_score, prev_col, next_col)) ; 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 && aggressive) { 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 */ 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, cset_start [current_set+1]-(k+deadcol)-(cols_thickness), max_deg) ; cols_thickness = 0 ; #endif /* === 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)) { DEBUG4 ((" Row "ID", dead\n", row)) ; continue ; } 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 && CMEMBER (col) == current_set) { 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 ; 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 */ hash %= n_col + 1 ; DEBUG4 ((" Hash = "ID", n_col = "ID".\n", 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 Col, A, head, pivot_row_start, pivot_row_length, cmember) ; /* === Kill the pivotal column ====================================== */ DEBUG1 ((" KILLING column detect supercols "ID" \n", pivot_col)) ; KILL_PRINCIPAL_COL (pivot_col) ; /* 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 = clear_mark (tag_mark+max_deg+1, max_mark, n_row, Row) ; #ifndef NDEBUG DEBUG3 (("check3\n")) ; debug_mark (n_row, Row, tag_mark, max_mark) ; #endif /* === 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 ========================= */ if (CMEMBER (col) == current_set) { 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) ; } else { Col [col].shared4.degree_next = EMPTY ; Col [col].shared3.prev = EMPTY ; } } #ifndef NDEBUG debug_deg_lists (n_row, n_col, Row, Col, head, min_score, cset_start [current_set+1]-(k+deadcol), max_deg) ; #endif /* 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 && pivot_row_thickness > 0 && (order_for_lu)) || (pivot_row_degree > 0 && (!order_for_lu))) { /* 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 ; Row [pivot_row].thickness = pivot_row_thickness ; Row [pivot_row].front = nfr ; /* pivot row is no longer dead */ DEBUG1 (("Resurrect Pivot_row "ID" deg: "ID"\n", pivot_row, pivot_row_degree)) ; } #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 ====================== */ *p_nfr = nfr ; return (ngarbage) ; } /* ========================================================================== */ /* === 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 */ CColamd_Row Row [ ], /* of size n_row+1 */ #endif CColamd_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 */ Int cmember [ ] /* col -> cset mapping */ ) { /* === 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, */ /* or if in different constraint sets */ if (Col [c].length != length || Col [c].shared2.score != Col [super_c].shared2.score || CMEMBER (c) != CMEMBER (super_c)) { 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" */ /* super columns should belong to the same constraint set */ 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 ; /* 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 */ CColamd_Row Row [ ], /* row info */ CColamd_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 /* === 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_DEAD (r) || (Row [r].length == 0)) { /* This row is already dead, or is of zero length. Cannot compact * a row of zero length, so kill it. NOTE: in the current version, * there are no zero-length live rows. Kill the row (for the first * time, or again) just to be safe. */ 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 } } /* === 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 } } /* 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 tag_mark, /* new value of tag_mark */ Int max_mark, /* max allowed value of tag_mark */ Int n_row, /* number of rows in A */ CColamd_Row Row [ ] /* Row [0 ... n_row-1].shared2.mark is set to zero */ ) { /* === Local variables ================================================== */ Int r ; if (tag_mark <= 0 || tag_mark >= max_mark) { for (r = 0 ; r < n_row ; r++) { if (ROW_IS_ALIVE (r)) { Row [r].shared2.mark = 0 ; } } tag_mark = 1 ; } return (tag_mark) ; } /* ========================================================================== */ /* === print_report ========================================================= */ /* ========================================================================== */ /* No printing occurs if NPRINT is defined at compile time. */ PRIVATE void print_report ( char *method, Int stats [CCOLAMD_STATS] ) { Int i1, i2, i3 ; SUITESPARSE_PRINTF (("\n%s version %d.%d.%d, %s: ", method, CCOLAMD_MAIN_VERSION, CCOLAMD_SUB_VERSION, CCOLAMD_SUBSUB_VERSION, CCOLAMD_DATE)) ; if (!stats) { SUITESPARSE_PRINTF (("No statistics available.\n")) ; return ; } i1 = stats [CCOLAMD_INFO1] ; i2 = stats [CCOLAMD_INFO2] ; i3 = stats [CCOLAMD_INFO3] ; if (stats [CCOLAMD_STATUS] >= 0) { SUITESPARSE_PRINTF(("OK. ")) ; } else { SUITESPARSE_PRINTF(("ERROR. ")) ; } switch (stats [CCOLAMD_STATUS]) { case CCOLAMD_OK_BUT_JUMBLED: SUITESPARSE_PRINTF(( "Matrix has unsorted or duplicate row indices.\n")) ; SUITESPARSE_PRINTF(( "%s: duplicate or out-of-order row indices: "ID"\n", method, i3)) ; SUITESPARSE_PRINTF(( "%s: last seen duplicate or out-of-order row: "ID"\n", method, INDEX (i2))) ; SUITESPARSE_PRINTF(( "%s: last seen in column: "ID"", method, INDEX (i1))) ; /* no break - fall through to next case instead */ case CCOLAMD_OK: SUITESPARSE_PRINTF(("\n")) ; SUITESPARSE_PRINTF(( "%s: number of dense or empty rows ignored: "ID"\n", method, stats [CCOLAMD_DENSE_ROW])) ; SUITESPARSE_PRINTF(( "%s: number of dense or empty columns ignored: "ID"\n", method, stats [CCOLAMD_DENSE_COL])) ; SUITESPARSE_PRINTF(( "%s: number of garbage collections performed: "ID"\n", method, stats [CCOLAMD_DEFRAG_COUNT])) ; break ; case CCOLAMD_ERROR_A_not_present: SUITESPARSE_PRINTF(( "Array A (row indices of matrix) not present.\n")) ; break ; case CCOLAMD_ERROR_p_not_present: SUITESPARSE_PRINTF(( "Array p (column pointers for matrix) not present.\n")) ; break ; case CCOLAMD_ERROR_nrow_negative: SUITESPARSE_PRINTF(("Invalid number of rows ("ID").\n", i1)) ; break ; case CCOLAMD_ERROR_ncol_negative: SUITESPARSE_PRINTF(("Invalid number of columns ("ID").\n", i1)) ; break ; case CCOLAMD_ERROR_nnz_negative: SUITESPARSE_PRINTF(( "Invalid number of nonzero entries ("ID").\n", i1)) ; break ; case CCOLAMD_ERROR_p0_nonzero: SUITESPARSE_PRINTF(( "Invalid column pointer, p [0] = "ID", must be 0.\n", i1)) ; break ; case CCOLAMD_ERROR_A_too_small: SUITESPARSE_PRINTF(("Array A too small.\n")) ; SUITESPARSE_PRINTF(( " Need Alen >= "ID", but given only Alen = "ID".\n", i1, i2)) ; break ; case CCOLAMD_ERROR_col_length_negative: SUITESPARSE_PRINTF(( "Column "ID" has a negative number of entries ("ID").\n", INDEX (i1), i2)) ; break ; case CCOLAMD_ERROR_row_index_out_of_bounds: SUITESPARSE_PRINTF(( "Row index (row "ID") out of bounds ("ID" to "ID") in" "column "ID".\n", INDEX (i2), INDEX (0), INDEX (i3-1), INDEX (i1))) ; break ; case CCOLAMD_ERROR_out_of_memory: SUITESPARSE_PRINTF(("Out of memory.\n")) ; break ; case CCOLAMD_ERROR_invalid_cmember: SUITESPARSE_PRINTF(("cmember invalid\n")) ; break ; } } /* ========================================================================= */ /* === "Expert" routines =================================================== */ /* ========================================================================= */ /* The following routines are visible outside this routine, but are not meant * to be called by the user. They are meant for a future version of UMFPACK, * to replace UMFPACK internal routines with a similar name. */ /* ========================================================================== */ /* === CCOLAMD_apply_order ================================================== */ /* ========================================================================== */ /* * Apply post-ordering of supernodal elimination tree. */ void CCOLAMD_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] ; } } /* ========================================================================== */ /* === CCOLAMD_fsize ======================================================== */ /* ========================================================================== */ /* Determine the largest frontal matrix size for each subtree. * Only required to sort the children of each * node prior to postordering the column elimination tree. */ void CCOLAMD_fsize ( Int nn, Int Fsize [ ], Int Fnrows [ ], Int Fncols [ ], Int Parent [ ], Int Npiv [ ] ) { double dr, dc ; 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] ; /* avoid integer overflow */ dr = (double) r ; dc = (double) c ; frsize = (INT_OVERFLOW (dr * dc)) ? Int_MAX : (r * c) ; 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])); } } } DEBUG1 (("fsize done\n")) ; } /* ========================================================================= */ /* === CCOLAMD_postorder =================================================== */ /* ========================================================================= */ /* Perform a postordering (via depth-first search) of an assembly tree. */ void CCOLAMD_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 Front_cols [ ], /* input, not modified on output: */ Int cmember [ ] ) { 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] ; if (CMEMBER (Front_cols[parent]) == CMEMBER (Front_cols[j])) { Child [parent] = j ; } } } } #ifndef NDEBUG { Int nels, ff, nchild ; DEBUG1 (("\n\n================================ ccolamd_postorder:\n")); nels = 0 ; for (j = 0 ; j < nn ; j++) { if (Nv [j] > 0) { 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 ; DEBUG1 ((" Children: ")) ; for (ff = Child [j] ; ff != EMPTY ; ff = Sibling [ff]) { DEBUG1 ((ID" ", ff)) ; nchild++ ; ASSERT (nchild < nn) ; } DEBUG1 (("\n")) ; parent = Parent [j] ; nels++ ; } } } #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 ; DEBUG1 (("Before partial sort, element "ID"\n", i)) ; nchild = 0 ; for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) { DEBUG1 ((" f: "ID" size: "ID"\n", f, Fsize [f])) ; nchild++ ; } #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]) { frsize = Fsize [f] ; if (frsize >= maxfrsize) { /* this is the biggest seen so far */ maxfrsize = frsize ; bigfprev = fprev ; bigf = f ; } fprev = f ; } fnext = Sibling [bigf] ; 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 ; Sibling [fprev] = bigf ; } #ifndef NDEBUG DEBUG1 (("After partial sort, element "ID"\n", i)) ; for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) { DEBUG1 ((" "ID" "ID"\n", f, Fsize [f])) ; nchild-- ; } #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 || (CMEMBER (Front_cols [Parent [i]]) != CMEMBER (Front_cols [i]))) && Nv [i] > 0) { DEBUG1 (("Root of assembly tree "ID"\n", i)) ; k = CCOLAMD_post_tree (i, k, Child, Sibling, Order, Stack) ; } } } /* ========================================================================= */ /* === CCOLAMD_post_tree =================================================== */ /* ========================================================================= */ /* Post-ordering of a supernodal column elimination tree. */ Int CCOLAMD_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 */ ) { Int f, head, h, i ; #if 0 /* --------------------------------------------------------------------- */ /* recursive version (Stack [ ] is not used): */ /* --------------------------------------------------------------------- */ /* this is simple, but can cause stack overflow if nn is large */ i = root ; for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) { k = CCOLAMD_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 */ i = Stack [head] ; DEBUG1 (("head of stack "ID" \n", i)) ; 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++ ; } h = head ; for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) { ASSERT (h > 0) ; Stack [h--] = f ; DEBUG1 (("push "ID" on stack\n", f)) ; } 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-- ; DEBUG1 (("pop "ID" order "ID"\n", i, k)) ; Order [i] = k++ ; } #ifndef NDEBUG DEBUG1 (("\nStack:")) ; for (h = head ; h >= 0 ; h--) { Int j = Stack [h] ; DEBUG1 ((" "ID, j)) ; } DEBUG1 (("\n\n")) ; #endif } return (k) ; } /* ========================================================================== */ /* === CCOLAMD 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, CColamd_Row Row [ ], CColamd_Col Col [ ], Int A [ ], Int cmember [ ], Int cset_start [ ] ) { /* === Local variables ================================================== */ Int i ; Int c ; Int *cp ; Int *cp_end ; Int len ; Int score ; Int r ; Int *rp ; Int *rp_end ; Int deg ; Int cs ; /* === 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 ; cs = CMEMBER (c) ; ASSERT (i >= cset_start [cs] && i < cset_start [cs+1]) ; } } 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, CColamd_Row Row [ ], CColamd_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 && ccolamd_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 (("%d:", deg)) ; ASSERT (Col [col].shared3.prev == EMPTY) ; 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 && ccolamd_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, CColamd_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 && ccolamd_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, CColamd_Row Row [ ], CColamd_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 (ccolamd_debug < 3) { return ; } DEBUG3 (("DUMP MATRIX:\n")) ; for (r = 0 ; r < n_row ; r++) { DEBUG3 (("Row "ID" alive? "ID"\n", r, ROW_IS_ALIVE (r))) ; if (ROW_IS_DEAD (r)) { continue ; } DEBUG3 (("start "ID" length "ID" degree "ID"\nthickness "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 ((" "ID" col "ID"\n", COL_IS_ALIVE (c), c)) ; } } for (c = 0 ; c < n_col ; c++) { DEBUG3 (("Col "ID" alive? "ID"\n", c, COL_IS_ALIVE (c))) ; if (COL_IS_DEAD (c)) { continue ; } DEBUG3 (("start "ID" length "ID" shared1 "ID" shared2 "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 ((" "ID" row "ID"\n", ROW_IS_ALIVE (r), r)) ; } } } /* ========================================================================== */ /* === dump_super =========================================================== */ /* ========================================================================== */ PRIVATE void dump_super ( Int super_c, CColamd_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")) ; } /* ========================================================================== */ /* === ccolamd_get_debug ==================================================== */ /* ========================================================================== */ PRIVATE void ccolamd_get_debug ( char *method ) { FILE *debug_file ; ccolamd_debug = 0 ; /* no debug printing */ /* Read debug info from the debug file. */ debug_file = fopen ("debug", "r") ; if (debug_file) { (void) fscanf (debug_file, ""ID"", &ccolamd_debug) ; (void) fclose (debug_file) ; } DEBUG0 ((":")) ; DEBUG1 (("%s: debug version, D = "ID" (THIS WILL BE SLOW!)\n", method, ccolamd_debug)) ; DEBUG1 ((" Debug printing level: "ID"\n", ccolamd_debug)) ; } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CCOLAMD/Source/ccolamd_version.c���������������������������������������������0000644�0001751�0000144�00000001263�14552026002�022405� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CCOLAMD/Source/ccolamd_version.c: return CCOLAMD version //------------------------------------------------------------------------------ // CCOLAMD, Copyright (c) 2005-2022, Univ. of Florida, All Rights Reserved. // Authors: Timothy A. Davis, Sivasankaran Rajamanickam, and Stefan Larimore. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #include "ccolamd.h" void ccolamd_version (int version [3]) { version [0] = CCOLAMD_MAIN_VERSION ; version [1] = CCOLAMD_SUB_VERSION ; version [2] = CCOLAMD_SUBSUB_VERSION ; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CCOLAMD/Source/ccolamd_l.c���������������������������������������������������0000644�0001751�0000144�00000001027�14552026002�021151� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CCOLAMD/Source/ccolamd_l.c: int64_t version of ccolamd //------------------------------------------------------------------------------ // CCOLAMD, Copyright (c) 2005-2022, Univ. of Florida, All Rights Reserved. // Authors: Timothy A. Davis, Sivasankaran Rajamanickam, and Stefan Larimore. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "ccolamd.c" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/�������������������������������������������������������������������������0000755�0001751�0000144�00000000000�14576344041�015203� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Include/�����������������������������������������������������������������0000755�0001751�0000144�00000000000�14576343415�016572� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Include/amd.h������������������������������������������������������������0000644�0001751�0000144�00000041567�14552026002�017501� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Include/amd.h: approximate minimum degree ordering //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2024, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* 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 int32_t integers and the other for int64_t 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 #include "SuiteSparse_config.h" /* make it easy for C++ programs to include AMD */ #ifdef __cplusplus extern "C" { #endif int amd_order /* returns AMD_OK, AMD_OK_BUT_JUMBLED, * AMD_INVALID, or AMD_OUT_OF_MEMORY */ ( int32_t n, /* A is n-by-n. n must be >= 0. */ const int32_t Ap [ ], /* column pointers for A, of size n+1 */ const int32_t Ai [ ], /* row indices of A, of size nz = Ap [n] */ int32_t P [ ], /* output permutation, of size n */ double Control [ ], /* input Control settings, of size AMD_CONTROL */ double Info [ ] /* output Info statistics, of size AMD_INFO */ ) ; int amd_l_order /* see above for description */ ( int64_t n, const int64_t Ap [ ], const int64_t Ai [ ], int64_t P [ ], double Control [ ], double Info [ ] ) ; /* Input arguments (not modified): * * n: the matrix A is n-by-n. * Ap: an int32_t/int64_t array of size n+1, containing column * pointers of A. * Ai: an int32_t/int64_t 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 int32_t/int64_t 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]. * * If the row indices appear in ascending order in each column, and there * are no duplicate entries, then amd_order is slightly more efficient in * terms of time and memory usage. If this condition does not hold, a copy * of the matrix is created (where these conditions do hold), and the copy is * ordered. * * 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.suitesparse.com. * * 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. Ai [0..nz-1] must be in the range 0 * to n-1. 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. * * AMD_OK_BUT_JUMBLED if the matrix had unsorted columns, and/or duplicate * entries, but was otherwise valid. * * 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_OK_BUT_JUMBLED, 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. */ /* ------------------------------------------------------------------------- */ /* direct interface to AMD */ /* ------------------------------------------------------------------------- */ /* amd_2 is the primary AMD ordering routine. It is not meant to be * user-callable because of its restrictive inputs and because it destroys * the user's input matrix. It does not check its inputs for errors, either. * However, if you can work with these restrictions it can be faster than * amd_order and use less memory (assuming that you can create your own copy * of the matrix for AMD to destroy). Refer to AMD/Source/amd_2.c for a * description of each parameter. */ void amd_2 ( int32_t n, int32_t Pe [ ], int32_t Iw [ ], int32_t Len [ ], int32_t iwlen, int32_t pfree, int32_t Nv [ ], int32_t Next [ ], int32_t Last [ ], int32_t Head [ ], int32_t Elen [ ], int32_t Degree [ ], int32_t W [ ], double Control [ ], double Info [ ] ) ; void amd_l2 ( int64_t n, int64_t Pe [ ], int64_t Iw [ ], int64_t Len [ ], int64_t iwlen, int64_t pfree, int64_t Nv [ ], int64_t Next [ ], int64_t Last [ ], int64_t Head [ ], int64_t Elen [ ], int64_t Degree [ ], int64_t W [ ], double Control [ ], double Info [ ] ) ; /* ------------------------------------------------------------------------- */ /* amd_valid */ /* ------------------------------------------------------------------------- */ /* Returns AMD_OK or AMD_OK_BUT_JUMBLED if the matrix is valid as input to * amd_order; the latter is returned if the matrix has unsorted and/or * duplicate row indices in one or more columns. Returns AMD_INVALID if the * matrix cannot be passed to amd_order. For amd_order, the matrix must also * be square. The first two arguments are the number of rows and the number * of columns of the matrix. For its use in AMD, these must both equal n. */ int amd_valid ( int32_t n_row, /* # of rows */ int32_t n_col, /* # of columns */ const int32_t Ap [ ], /* column pointers, of size n_col+1 */ const int32_t Ai [ ] /* row indices, of size Ap [n_col] */ ) ; int amd_l_valid ( int64_t n_row, int64_t n_col, const int64_t Ap [ ], const int64_t Ai [ ] ) ; /* ------------------------------------------------------------------------- */ /* 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 [ ]) ; // amd_version: return AMD version. The version array is returned with // version [0..2] = {AMD_MAIN_VERSION, AMD_SUB_VERSION, AMD_SUBSUB_VERSION} void amd_version (int version [3]) ; #ifdef __cplusplus } #endif #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, or problem too large */ #define AMD_INVALID -2 /* input arguments are not valid */ #define AMD_OK_BUT_JUMBLED 1 /* input matrix is OK for amd_order, but * columns were not sorted, and/or duplicate entries were present. AMD had * to do extra work before ordering the matrix. This is a warning, not an * error. */ /* ========================================================================== */ /* === AMD version ========================================================== */ /* ========================================================================== */ /* AMD Version 1.2 and later include the following definitions. * As an example, to test if the version you are using is 1.2 or later: * * #ifdef AMD_VERSION * if (AMD_VERSION >= AMD_VERSION_CODE (1,2)) ... * #endif * * This also works during compile-time: * * #if defined(AMD_VERSION) && (AMD_VERSION >= AMD_VERSION_CODE (1,2)) * printf ("This is version 1.2 or later\n") ; * #else * printf ("This is an early version\n") ; * #endif * * Versions 1.1 and earlier of AMD do not include a #define'd version number. */ #define AMD_DATE "Jan 10, 2024" #define AMD_MAIN_VERSION 3 #define AMD_SUB_VERSION 3 #define AMD_SUBSUB_VERSION 1 #define AMD_VERSION_CODE(main,sub) SUITESPARSE_VER_CODE(main,sub) #define AMD_VERSION AMD_VERSION_CODE(3,3) #define AMD__VERSION SUITESPARSE__VERCODE(3,3,1) #if !defined (SUITESPARSE__VERSION) || \ (SUITESPARSE__VERSION < SUITESPARSE__VERCODE(7,5,0)) #error "AMD 3.3.1 requires SuiteSparse_config 7.5.0 or later" #endif #endif �����������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Include/amd_internal.h���������������������������������������������������0000644�0001751�0000144�00000015172�14552026002�021366� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Include/amd_internal.h: internal definitions for AMD //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2023, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* This file is for internal use in AMD itself, and does not normally need to * be included in user code (it is included in UMFPACK, however). All others * should use amd.h instead. */ /* ========================================================================= */ /* === NDEBUG ============================================================== */ /* ========================================================================= */ /* * Turning on debugging takes some work (see below). If you do not edit this * file, then debugging is always turned off, regardless of whether or not * -DNDEBUG is specified in your compiler options. * * If AMD is being compiled as a mexFunction, then MATLAB_MEX_FILE is defined, * and mxAssert is used instead of assert. If debugging is not enabled, no * MATLAB include files or functions are used. Thus, the AMD library libamd.a * can be safely used in either a stand-alone C program or in another * mexFunction, without any change. */ /* 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 #include "amd.h" /* ------------------------------------------------------------------------- */ /* basic definitions */ /* ------------------------------------------------------------------------- */ #ifdef FLIP #undef FLIP #endif #ifdef MAX #undef MAX #endif #ifdef MIN #undef MIN #endif #ifdef EMPTY #undef EMPTY #endif #define PRIVATE static /* 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 EMPTY (-1) /* largest value of size_t */ #ifndef SIZE_T_MAX #ifdef SIZE_MAX /* C99 only */ #define SIZE_T_MAX SIZE_MAX #else #define SIZE_T_MAX ((size_t) (-1)) #endif #endif /* ------------------------------------------------------------------------- */ /* integer type for AMD: int32_t or int64_t */ /* ------------------------------------------------------------------------- */ #if defined (DLONG) || defined (ZLONG) #define Int int64_t #define UInt uint64_t #define ID "%" PRId64 #define Int_MAX INT64_MAX #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_preprocess amd_l_preprocess #else #define Int int32_t #define UInt uint32_t #define ID "%d" #define Int_MAX INT32_MAX #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_preprocess amd_preprocess #endif /* ------------------------------------------------------------------------- */ /* AMD routine definitions (not user-callable) */ /* ------------------------------------------------------------------------- */ size_t AMD_aat ( Int n, const Int Ap [ ], const Int Ai [ ], Int Len [ ], Int Tp [ ], double Info [ ] ) ; 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 [ ] ) ; void AMD_postorder ( Int nn, Int Parent [ ], Int Npiv [ ], Int Fsize [ ], Int Order [ ], Int Child [ ], Int Sibling [ ], Int Stack [ ] ) ; Int AMD_post_tree ( Int root, Int k, Int Child [ ], const Int Sibling [ ], Int Order [ ], Int Stack [ ] #ifndef NDEBUG , Int nn #endif ) ; void AMD_preprocess ( Int n, const Int Ap [ ], const Int Ai [ ], Int Rp [ ], Int Ri [ ], Int W [ ], Int Flag [ ] ) ; /* ------------------------------------------------------------------------- */ /* debugging definitions */ /* ------------------------------------------------------------------------- */ #ifndef NDEBUG /* from assert.h: assert macro */ #include extern Int AMD_debug ; void AMD_debug_init ( char *s ) ; 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 /* Use mxAssert if AMD is compiled into a mexFunction */ #ifdef MATLAB_MEX_FILE #define ASSERT(expression) (mxAssert ((expression), "")) #else #define ASSERT(expression) (assert (expression)) #endif #define AMD_DEBUG0(params) { SUITESPARSE_PRINTF (params) ; } #define AMD_DEBUG1(params) { if (AMD_debug >= 1) SUITESPARSE_PRINTF (params) ; } #define AMD_DEBUG2(params) { if (AMD_debug >= 2) SUITESPARSE_PRINTF (params) ; } #define AMD_DEBUG3(params) { if (AMD_debug >= 3) SUITESPARSE_PRINTF (params) ; } #define AMD_DEBUG4(params) { if (AMD_debug >= 4) SUITESPARSE_PRINTF (params) ; } #else /* no debugging */ #define ASSERT(expression) #define AMD_DEBUG0(params) #define AMD_DEBUG1(params) #define AMD_DEBUG2(params) #define AMD_DEBUG3(params) #define AMD_DEBUG4(params) #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Makefile�����������������������������������������������������������������0000644�0001751�0000144�00000001613�14576344042�016645� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sources = \ Source/amd_1.c Source/amd_l1.c \ Source/amd_2.c Source/amd_l2.c \ Source/amd_aat.c Source/amd_l_aat.c \ Source/amd_control.c Source/amd_l_control.c \ Source/amd_defaults.c Source/amd_l_defaults.c \ Source/amd_dump.c Source/amd_l_dump.c \ Source/amd_info.c Source/amd_l_info.c \ Source/amd_order.c Source/amd_l_order.c \ Source/amd_post_tree.c Source/amd_l_post_tree.c \ Source/amd_postorder.c Source/amd_l_postorder.c \ Source/amd_preprocess.c Source/amd_l_preprocess.c \ Source/amd_valid.c Source/amd_l_valid.c \ Source/amd_version.c objects = $(sources:.c=.o) archive = AMD.a PKG_CPPFLAGS = -I./Include -I../SuiteSparse_config all : $(archive) $(archive) : $(objects) rm -f $@ $(AR) -cr $@ $(objects) $(RANLIB) $@ .c.o : $(CC) $(PKG_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) -c $< -o $*.o clean : @rm -f $(objects) $(archive) ���������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Source/������������������������������������������������������������������0000755�0001751�0000144�00000000000�14576344041�016443� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Source/amd_l_order.c�����������������������������������������������������0000644�0001751�0000144�00000000762�14552026002�021047� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_l_order.c: int64_t version of amd_order //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "amd_order.c" ��������������Matrix/src/SuiteSparse/AMD/Source/amd_l2.c����������������������������������������������������������0000644�0001751�0000144�00000000744�14552026002�017736� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_l2.c: int64_t version of amd_2 //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "amd_2.c" ����������������������������Matrix/src/SuiteSparse/AMD/Source/amd_postorder.c���������������������������������������������������0000644�0001751�0000144�00000012354�14552026002�021442� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_postorder: post-order the assembly tree from AMD //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* Perform a postordering (via depth-first search) of an assembly tree. */ #include "amd_internal.h" 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 ) ; } } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Source/amd_valid.c�������������������������������������������������������0000644�0001751�0000144�00000005415�14552026002�020520� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_valid: check if a matrix is valid for AMD //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* 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. * Ai [0 ... nz-1] must be in the range 0 to n_row-1. * * If any of the above conditions hold, AMD_INVALID is returned. If the * following condition holds, AMD_OK_BUT_JUMBLED is returned (a warning, * not an error): * * row indices in Ai [Ap [j] ... Ap [j+1]-1] are not sorted in ascending * order, and/or duplicate entries exist. * * Otherwise, AMD_OK is returned. * * In v1.2 and earlier, this function returned TRUE if the matrix was valid * (now returns AMD_OK), or FALSE otherwise (now returns AMD_INVALID or * AMD_OK_BUT_JUMBLED). */ #include "amd_internal.h" 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 ; int result = AMD_OK ; if (n_row < 0 || n_col < 0 || Ap == NULL || Ai == NULL) { return (AMD_INVALID) ; } 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 (AMD_INVALID) ; } 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 (AMD_INVALID) ; } ilast = EMPTY ; for (p = p1 ; p < p2 ; p++) { i = Ai [p] ; AMD_DEBUG3 (("row: "ID"\n", i)) ; if (i < 0 || i >= n_row) { /* row index out of range */ AMD_DEBUG0 (("index out of range, col "ID" row "ID"\n", j, i)); return (AMD_INVALID) ; } if (i <= ilast) { /* row index unsorted, or duplicate entry present */ AMD_DEBUG1 (("index unsorted/dupl col "ID" row "ID"\n", j, i)); result = AMD_OK_BUT_JUMBLED ; } ilast = i ; } } return (result) ; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Source/amd_2.c�����������������������������������������������������������0000644�0001751�0000144�00000176132�14552026002�017567� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_2: AMD ordering //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* 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" /* ========================================================================= */ /* === clear_flag ========================================================== */ /* ========================================================================= */ static Int clear_flag (Int wflg, Int wbig, Int W [ ], Int n) { Int x ; if (wflg < 2 || 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 */ return (wflg) ; } /* ========================================================================= */ /* === AMD_2 =============================================================== */ /* ========================================================================= */ 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 int32_t and int64_t versions are provided. In the * descriptions below an integer is int32_t or int64_t 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, ok, ndense, ncmpa, dense, aggressive ; UInt 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: = (INT32_MAX - n) for the int32_t version, (INT64_MAX - n) * for the int64_t 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 ; mindeg = 0 ; ncmpa = 0 ; nel = 0 ; lemax = 0 ; /* 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 ; } /* Note: if alpha is NaN, this is undefined: */ if (alpha < 0) { /* only remove completely dense rows/columns */ dense = n-2 ; } else { dense = alpha * sqrt ((double) n) ; } dense = MAX (16, dense) ; dense = MIN (n, dense) ; AMD_DEBUG1 (("\n\nAMD (debug), alpha %g, aggr. "ID"\n", alpha, aggressive)) ; for (i = 0 ; i < n ; i++) { Last [i] = EMPTY ; Head [i] = EMPTY ; Next [i] = EMPTY ; /* if separate 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" initial\n", nel)) ; AMD_dump (n, Pe, Iw, Len, iwlen, pfree, Nv, Next, Last, Head, Elen, Degree, W, -1) ; #endif /* initialize wflg */ wbig = Int_MAX - n ; wflg = clear_flag (0, wbig, W, n) ; /* --------------------------------------------------------------------- */ /* initialize degree lists and eliminate dense and empty rows */ /* --------------------------------------------------------------------- */ ndense = 0 ; 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 */ wflg = clear_flag (wflg, wbig, W, n) ; /* ========================================================================= */ /* 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] + Len [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 separate 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 ; wflg = clear_flag (wflg, wbig, W, n) ; /* 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 separate 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) ; /* skip 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 ; } /* ========================================================================= */ /* POST-ORDERING */ /* ========================================================================= */ /* ------------------------------------------------------------------------- * 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.) * ------------------------------------------------------------------------- */ /* restore Pe */ for (i = 0 ; i < n ; i++) { Pe [i] = FLIP (Pe [i]) ; } /* restore Elen, for output information, and for postordering */ for (i = 0 ; i < n ; 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)) ; } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Source/amd_info.c��������������������������������������������������������0000644�0001751�0000144�00000010041�14552026002�020343� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_info: print output statistics for AMD //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* 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) { SUITESPARSE_PRINTF ((format, x)) ; }} void AMD_info ( double Info [ ] ) { double n, ndiv, nmultsubs_ldl, nmultsubs_lu, lnz, lnzd ; SUITESPARSE_PRINTF (("\nAMD version %d.%d.%d, %s, results:\n", AMD_MAIN_VERSION, AMD_SUB_VERSION, AMD_SUBSUB_VERSION, AMD_DATE)) ; 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 */ SUITESPARSE_PRINTF ((" status: ")) ; if (Info [AMD_STATUS] == AMD_OK) { SUITESPARSE_PRINTF (("OK\n")) ; } else if (Info [AMD_STATUS] == AMD_OUT_OF_MEMORY) { SUITESPARSE_PRINTF (("out of memory\n")) ; } else if (Info [AMD_STATUS] == AMD_INVALID) { SUITESPARSE_PRINTF (("invalid matrix\n")) ; } else if (Info [AMD_STATUS] == AMD_OK_BUT_JUMBLED) { SUITESPARSE_PRINTF (("OK, but jumbled\n")) ; } else { SUITESPARSE_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 */ SUITESPARSE_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) { SUITESPARSE_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)) ; } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Source/amd_l_valid.c�����������������������������������������������������0000644�0001751�0000144�00000000761�14552026002�021032� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_l_valid.c: int64_t version of amd_valid //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "amd_valid.c" ���������������Matrix/src/SuiteSparse/AMD/Source/amd_aat.c���������������������������������������������������������0000644�0001751�0000144�00000011137�14552026002�020164� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_aat: compute symmetry of A and nnz in each column of A+A' //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* AMD_aat: compute the symmetry of the pattern of A, and count the number of * nonzeros each column of A+A' (excluding the diagonal). Assumes the input * matrix has no errors, with sorted columns and no duplicates * (AMD_valid (n, n, Ap, Ai) must be AMD_OK, but this condition is not * checked). */ #include "amd_internal.h" size_t 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 ; double sym ; size_t nzaat ; #ifndef NDEBUG AMD_debug_init ("AMD AAT") ; for (k = 0 ; k < n ; k++) Tp [k] = EMPTY ; ASSERT (AMD_valid (n, n, Ap, Ai) == AMD_OK) ; #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 = (2 * (double) 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) = %g\n", (double) 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) ; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Source/amd_control.c�����������������������������������������������������0000644�0001751�0000144�00000003253�14552026002�021077� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_control: print control parameters for AMD //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* 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" 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 ; } SUITESPARSE_PRINTF (( "\nAMD version %d.%d.%d, %s: approximate minimum degree ordering\n" " dense row parameter: %g\n", AMD_MAIN_VERSION, AMD_SUB_VERSION, AMD_SUBSUB_VERSION, AMD_DATE, alpha)) ; if (alpha < 0) { SUITESPARSE_PRINTF ((" no rows treated as dense\n")) ; } else { SUITESPARSE_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) { SUITESPARSE_PRINTF ((" aggressive absorption: yes\n")) ; } else { SUITESPARSE_PRINTF ((" aggressive absorption: no\n")) ; } SUITESPARSE_PRINTF ((" size of AMD integer: %d\n\n", sizeof (Int))) ; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Source/amd_l_postorder.c�������������������������������������������������0000644�0001751�0000144�00000000775�14552026002�021761� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_l_postorder.c: int64_t version of amd_postorder //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "amd_postorder.c" ���Matrix/src/SuiteSparse/AMD/Source/amd_l_info.c������������������������������������������������������0000644�0001751�0000144�00000000757�14552026002�020673� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_l_info.c: int64_t version of amd_info //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "amd_info.c" �����������������Matrix/src/SuiteSparse/AMD/Source/amd_order.c�������������������������������������������������������0000644�0001751�0000144�00000013311�14552026002�020526� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_order: user-callable AMD ordering method //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* User-callable AMD minimum degree ordering routine. See amd.h for * documentation. */ #include "amd_internal.h" /* ========================================================================= */ /* === AMD_order =========================================================== */ /* ========================================================================= */ int AMD_order ( Int n, const Int Ap [ ], const Int Ai [ ], Int P [ ], double Control [ ], double Info [ ] ) { Int *Len, *S, nz, i, *Pinv, info, status, *Rp, *Ri, *Cp, *Ci, ok ; size_t nzaat, slen ; double mem = 0 ; #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) ; } /* check if n or nz will cause integer overflow */ if (((size_t) n) >= Int_MAX / sizeof (Int) || ((size_t) nz) >= Int_MAX / sizeof (Int)) { if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; return (AMD_OUT_OF_MEMORY) ; /* problem too large */ } /* check the input matrix: AMD_OK, AMD_INVALID, or AMD_OK_BUT_JUMBLED */ status = AMD_valid (n, n, Ap, Ai) ; if (status == AMD_INVALID) { if (info) Info [AMD_STATUS] = AMD_INVALID ; return (AMD_INVALID) ; /* matrix is invalid */ } /* allocate two size-n integer workspaces */ size_t nn = (size_t) n ; Len = SuiteSparse_malloc (nn, sizeof (Int)) ; Pinv = SuiteSparse_malloc (nn, sizeof (Int)) ; mem += n ; mem += n ; if (!Len || !Pinv) { /* :: out of memory :: */ SuiteSparse_free (Len) ; SuiteSparse_free (Pinv) ; if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; return (AMD_OUT_OF_MEMORY) ; } if (status == AMD_OK_BUT_JUMBLED) { /* sort the input matrix and remove duplicate entries */ AMD_DEBUG1 (("Matrix is jumbled\n")) ; Rp = SuiteSparse_malloc (nn+1, sizeof (Int)) ; Ri = SuiteSparse_malloc (nz, sizeof (Int)) ; mem += (n+1) ; mem += MAX (nz,1) ; if (!Rp || !Ri) { /* :: out of memory :: */ SuiteSparse_free (Rp) ; SuiteSparse_free (Ri) ; SuiteSparse_free (Len) ; SuiteSparse_free (Pinv) ; if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; return (AMD_OUT_OF_MEMORY) ; } /* use Len and Pinv as workspace to create R = A' */ AMD_preprocess (n, Ap, Ai, Rp, Ri, Len, Pinv) ; Cp = Rp ; Ci = Ri ; } else { /* order the input matrix as-is. No need to compute R = A' first */ Rp = NULL ; Ri = NULL ; Cp = (Int *) Ap ; Ci = (Int *) Ai ; } /* --------------------------------------------------------------------- */ /* determine the symmetry and count off-diagonal nonzeros in A+A' */ /* --------------------------------------------------------------------- */ nzaat = AMD_aat (n, Cp, Ci, Len, P, Info) ; AMD_DEBUG1 (("nzaat: %g\n", (double) nzaat)) ; ASSERT ((MAX (nz-n, 0) <= nzaat) && (nzaat <= 2 * (size_t) nz)) ; /* --------------------------------------------------------------------- */ /* allocate workspace for matrix, elbow room, and 6 size-n vectors */ /* --------------------------------------------------------------------- */ S = NULL ; slen = nzaat ; /* space for matrix */ ok = ((slen + nzaat/5) >= slen) ; /* check for size_t overflow */ slen += nzaat/5 ; /* add elbow room */ for (i = 0 ; ok && i < 7 ; i++) { ok = ((slen + nn) > slen) ; /* check for size_t overflow */ slen += nn ; /* size-n elbow room, 6 size-n work */ } mem += slen ; ok = ok && (slen < SIZE_T_MAX / sizeof (Int)) ; /* check for overflow */ if (ok) { S = SuiteSparse_malloc (slen, sizeof (Int)) ; } AMD_DEBUG1 (("slen %g\n", (double) slen)) ; if (!S) { /* :: out of memory :: (or problem too large) */ SuiteSparse_free (Rp) ; SuiteSparse_free (Ri) ; SuiteSparse_free (Len) ; SuiteSparse_free (Pinv) ; if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; return (AMD_OUT_OF_MEMORY) ; } if (info) { /* memory usage, in bytes. */ Info [AMD_MEMORY] = mem * sizeof (Int) ; } /* --------------------------------------------------------------------- */ /* order the matrix */ /* --------------------------------------------------------------------- */ AMD_1 (n, Cp, Ci, P, Pinv, Len, slen, S, Control, Info) ; /* --------------------------------------------------------------------- */ /* free the workspace */ /* --------------------------------------------------------------------- */ SuiteSparse_free (Rp) ; SuiteSparse_free (Ri) ; SuiteSparse_free (Len) ; SuiteSparse_free (Pinv) ; SuiteSparse_free (S) ; if (info) Info [AMD_STATUS] = status ; return (status) ; /* successful ordering */ } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Source/amd_l_defaults.c��������������������������������������������������0000644�0001751�0000144�00000000773�14552026002�021545� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_l_defaults.c: int64_t version of amd_defaults //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "amd_defaults.c" �����Matrix/src/SuiteSparse/AMD/Source/amd_l_dump.c������������������������������������������������������0000644�0001751�0000144�00000000757�14552026002�020705� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_l_dump.c: int64_t version of amd_dump //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "amd_dump.c" �����������������Matrix/src/SuiteSparse/AMD/Source/amd_1.c�����������������������������������������������������������0000644�0001751�0000144�00000012670�14552026002�017562� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_1: construct input matrix and then order with amd_2 //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* AMD_1: Construct A+A' for a sparse matrix A and perform the AMD ordering. * * The n-by-n sparse matrix A can be unsymmetric. It is stored in MATLAB-style * compressed-column form, with sorted row indices in each column, and no * duplicate entries. Diagonal entries may be present, but they are ignored. * Row indices of column j of A are stored in Ai [Ap [j] ... Ap [j+1]-1]. * Ap [0] must be zero, and nz = Ap [n] is the number of entries in A. The * size of the matrix, n, must be greater than or equal to zero. * * This routine must be preceded by a call to AMD_aat, which computes the * number of entries in each row/column in A+A', excluding the diagonal. * Len [j], on input, is the number of entries in row/column j of A+A'. This * routine constructs the matrix A+A' and then calls AMD_2. No error checking * is performed (this was done in AMD_valid). */ #include "amd_internal.h" void AMD_1 ( Int n, /* n > 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) == AMD_OK) ; /* 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) ; } ������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Source/amd_l_post_tree.c�������������������������������������������������0000644�0001751�0000144�00000000775�14552026002�021744� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_l_post_tree.c: int64_t version of amd_post_tree //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "amd_post_tree.c" ���Matrix/src/SuiteSparse/AMD/Source/amd_l1.c����������������������������������������������������������0000644�0001751�0000144�00000000742�14552026002�017733� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_l1: int64_t version of amd_1 //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "amd_1.c" ������������������������������Matrix/src/SuiteSparse/AMD/Source/amd_dump.c��������������������������������������������������������0000644�0001751�0000144�00000011331�14552026002�020360� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_dump: debug routines for AMD //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* 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 */ 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) */ 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. */ 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) ; AMD_DEBUG3 (("\nAMD dump, pfree: "ID"\n", pfree)) ; 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 + len <= 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 + len <= 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": \n", 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 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Source/amd_defaults.c����������������������������������������������������0000644�0001751�0000144�00000002072�14552026002�021224� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_defaults: set defaults for AMD //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* User-callable. Sets default control parameters for AMD. See amd.h * for details. */ #include "amd_internal.h" /* ========================================================================= */ /* === AMD defaults ======================================================== */ /* ========================================================================= */ 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 ; } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Source/amd_post_tree.c���������������������������������������������������0000644�0001751�0000144�00000006727�14552026002�021434� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_post_tree: post-ordering of a single etree //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* Post-ordering of a supernodal elimination tree. */ #include "amd_internal.h" 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 cause 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) ; } �����������������������������������������Matrix/src/SuiteSparse/AMD/Source/amd_l_control.c���������������������������������������������������0000644�0001751�0000144�00000000770�14552026002�021413� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_l_control.c: int64_t version of amd_control //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "amd_control.c" ��������Matrix/src/SuiteSparse/AMD/Source/amd_version.c�����������������������������������������������������0000644�0001751�0000144�00000001162�14552026002�021101� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_version: return AMD version //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2023, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #include "amd_internal.h" void amd_version (int version [3]) { version [0] = AMD_MAIN_VERSION ; version [1] = AMD_SUB_VERSION ; version [2] = AMD_SUBSUB_VERSION ; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/AMD/Source/amd_l_aat.c�������������������������������������������������������0000644�0001751�0000144�00000000754�14552026002�020502� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_l_aat.c: int64_t version of amd_aat //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "amd_aat.c" ��������������������Matrix/src/SuiteSparse/AMD/Source/amd_l_preprocess.c������������������������������������������������0000644�0001751�0000144�00000001000�14552026002�022103� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_l_preprocess.c: int64_t version of amd_preprocess //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "amd_preprocess.c" Matrix/src/SuiteSparse/AMD/Source/amd_preprocess.c��������������������������������������������������0000644�0001751�0000144�00000006535�14552026002�021612� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // AMD/Source/amd_preprocess: sort, remove duplicates, transpose a matrix //------------------------------------------------------------------------------ // AMD, Copyright (c) 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and // Iain S. Duff. All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* Sorts, removes duplicate entries, and transposes from the nonzero pattern of * a column-form matrix A, to obtain the matrix R. The input matrix can have * duplicate entries and/or unsorted columns (AMD_valid (n,Ap,Ai) must not be * AMD_INVALID). * * This input condition is NOT checked. This routine is not user-callable. */ #include "amd_internal.h" /* AMD_preprocess does not check its input for errors or allocate workspace. * On input, the condition (AMD_valid (n,n,Ap,Ai) != AMD_INVALID) must hold. */ void AMD_preprocess ( 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 ; ASSERT (AMD_valid (n, n, Ap, Ai) != AMD_INVALID) ; /* --------------------------------------------------------------------- */ /* 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 ASSERT (AMD_valid (n, n, Rp, Ri) == AMD_OK) ; for (j = 0 ; j < n ; j++) { ASSERT (W [j] == Rp [j+1]) ; } #endif } �������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/COLAMD/����������������������������������������������������������������������0000755�0001751�0000144�00000000000�14576344041�015541� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/COLAMD/Include/��������������������������������������������������������������0000755�0001751�0000144�00000000000�14576343415�017130� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/COLAMD/Include/colamd.h������������������������������������������������������0000644�0001751�0000144�00000022505�14561103552�020532� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // COLAMD/Include/colamd.h: include file for COLAMD //------------------------------------------------------------------------------ // COLAMD, Copyright (c) 1998-2024, Timothy A. Davis and Stefan Larimore, // All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* COLAMD / SYMAMD include file 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 (DrTimothyAldenDavis@gmail.com). The algorithm was developed in collaboration with John Gilbert, Xerox PARC, and Esmond Ng, Oak Ridge National Laboratory. Acknowledgements: This work was supported by the National Science Foundation, under grants DMS-9504974 and DMS-9803599. Availability: The colamd/symamd library is available at http://www.suitesparse.com This file 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 "SuiteSparse_config.h" /* ========================================================================== */ /* === COLAMD version ======================================================= */ /* ========================================================================== */ /* COLAMD Version 2.4 and later will include the following definitions. * As an example, to test if the version you are using is 2.4 or later: * * #ifdef COLAMD_VERSION * if (COLAMD_VERSION >= COLAMD_VERSION_CODE (2,4)) ... * #endif * * This also works during compile-time: * * #if defined(COLAMD_VERSION) && (COLAMD_VERSION >= COLAMD_VERSION_CODE (2,4)) * printf ("This is version 2.4 or later\n") ; * #else * printf ("This is an early version\n") ; * #endif * * Versions 2.3 and earlier of COLAMD do not include a #define'd version number. */ #define COLAMD_DATE "Jan 20, 2024" #define COLAMD_MAIN_VERSION 3 #define COLAMD_SUB_VERSION 3 #define COLAMD_SUBSUB_VERSION 2 #define COLAMD_VERSION_CODE(main,sub) SUITESPARSE_VER_CODE(main,sub) #define COLAMD_VERSION COLAMD_VERSION_CODE(3,3) #define COLAMD__VERSION SUITESPARSE__VERCODE(3,3,2) #if !defined (SUITESPARSE__VERSION) || \ (SUITESPARSE__VERSION < SUITESPARSE__VERCODE(7,6,0)) #error "COLAMD 3.3.2 requires SuiteSparse_config 7.6.0 or later" #endif /* ========================================================================== */ /* === 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 /* knobs [2]: aggressive absorption */ #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 /* 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) /* ========================================================================== */ /* === Prototypes of user-callable routines ================================= */ /* ========================================================================== */ /* make it easy for C++ programs to include COLAMD */ #ifdef __cplusplus extern "C" { #endif size_t colamd_recommended /* returns recommended value of Alen, */ /* or 0 if input arguments are erroneous */ ( int32_t nnz, /* nonzeros in A */ int32_t n_row, /* number of rows in A */ int32_t n_col /* number of columns in A */ ) ; size_t colamd_l_recommended /* returns recommended value of Alen, */ /* or 0 if input arguments are erroneous */ ( int64_t nnz, /* nonzeros in A */ int64_t n_row, /* number of rows in A */ int64_t 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 */ ) ; void colamd_l_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 */ int32_t n_row, /* number of rows in A */ int32_t n_col, /* number of columns in A */ int32_t Alen, /* size of the array A */ int32_t A [], /* row indices of A, of size Alen */ int32_t p [], /* column pointers of A, of size n_col+1 */ double knobs [COLAMD_KNOBS], /* parameter settings for colamd */ int32_t stats [COLAMD_STATS] /* colamd output stats and error codes */ ) ; int colamd_l /* returns (1) if successful, (0) otherwise*/ ( /* A and p arguments are modified on output */ int64_t n_row, /* number of rows in A */ int64_t n_col, /* number of columns in A */ int64_t Alen, /* size of the array A */ int64_t A [], /* row indices of A, of size Alen */ int64_t p [], /* column pointers of A, of size n_col+1 */ double knobs [COLAMD_KNOBS], /* parameter settings for colamd */ int64_t stats [COLAMD_STATS] /* colamd output stats and error codes */ ) ; int symamd /* return (1) if OK, (0) otherwise */ ( int32_t n, /* number of rows and columns of A */ int32_t A [], /* row indices of A */ int32_t p [], /* column pointers of A */ int32_t perm [], /* output permutation, size n_col+1 */ double knobs [COLAMD_KNOBS], /* parameters (uses defaults if NULL) */ int32_t stats [COLAMD_STATS], /* output stats 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) */ ) ; int symamd_l /* return (1) if OK, (0) otherwise */ ( int64_t n, /* number of rows and columns of A */ int64_t A [], /* row indices of A */ int64_t p [], /* column pointers of A */ int64_t perm [], /* output permutation, size n_col+1 */ double knobs [COLAMD_KNOBS], /* parameters (uses defaults if NULL) */ int64_t stats [COLAMD_STATS], /* output stats 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 ( int32_t stats [COLAMD_STATS] ) ; void colamd_l_report ( int64_t stats [COLAMD_STATS] ) ; void symamd_report ( int32_t stats [COLAMD_STATS] ) ; void symamd_l_report ( int64_t stats [COLAMD_STATS] ) ; void colamd_version (int version [3]) ; #ifdef __cplusplus } #endif #endif /* COLAMD_H */ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/COLAMD/Makefile��������������������������������������������������������������0000644�0001751�0000144�00000000554�14576344042�017206� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sources = Source/colamd.c Source/colamd_l.c Source/colamd_version.c objects = $(sources:.c=.o) archive = COLAMD.a PKG_CPPFLAGS = -I./Include -I../SuiteSparse_config all : $(archive) $(archive) : $(objects) rm -f $@ $(AR) -cr $@ $(objects) $(RANLIB) $@ .c.o : $(CC) $(PKG_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) -c $< -o $*.o clean : @rm -f $(objects) $(archive) ����������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/COLAMD/Source/���������������������������������������������������������������0000755�0001751�0000144�00000000000�14576344041�017001� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/COLAMD/Source/colamd_version.c�����������������������������������������������0000644�0001751�0000144�00000001163�14552026002�022136� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // COLAMD/Source/colamd_version.c: return COLAMD version //------------------------------------------------------------------------------ // COLAMD, Copyright (c) 1998-2022, Timothy A. Davis and Stefan Larimore, // All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #include "colamd.h" void colamd_version (int version [3]) { version [0] = COLAMD_MAIN_VERSION ; version [1] = COLAMD_SUB_VERSION ; version [2] = COLAMD_SUBSUB_VERSION ; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/COLAMD/Source/colamd_l.c�����������������������������������������������������0000644�0001751�0000144�00000000733�14552026002�020706� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // COLAMD/Source/colamd_l.c: int64_t version of colamd //------------------------------------------------------------------------------ // COLAMD, Copyright (c) 1998-2022, Timothy A. Davis and Stefan Larimore, // All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ #define DLONG #include "colamd.c" �������������������������������������Matrix/src/SuiteSparse/COLAMD/Source/colamd.c�������������������������������������������������������0000644�0001751�0000144�00000321342�14552026002�020375� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // COLAMD/Source/colamd.c: column approximate minimum degree ordering //------------------------------------------------------------------------------ // COLAMD, Copyright (c) 1998-2022, Timothy A. Davis and Stefan Larimore, // All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* COLAMD / SYMAMD 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 (DrTimothyAldenDavis@gmail.com). The algorithm was developed in collaboration with John Gilbert, Xerox PARC, and Esmond Ng, Oak Ridge National Laboratory. Acknowledgements: This work was supported by the National Science Foundation, under grants DMS-9504974 and DMS-9803599. Copyright and License: Copyright (c) 1998-2022, Timothy A. Davis, All Rights Reserved. COLAMD is also available under alternate licenses, contact T. Davis for details. See COLAMD/Doc/License.txt for the license. Availability: The colamd/symamd library is available at http://www.suitesparse.com Appears as ACM Algorithm 836. See the ChangeLog file for changes since Version 1.0. References: T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, An approximate column minimum degree ordering algorithm, ACM Transactions on Mathematical Software, vol. 30, no. 3., pp. 353-376, 2004. T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, Algorithm 836: COLAMD, an approximate column minimum degree ordering algorithm, ACM Transactions on Mathematical Software, vol. 30, no. 3., pp. 377-380, 2004. */ /* ========================================================================== */ /* === Description of user-callable routines ================================ */ /* ========================================================================== */ /* COLAMD includes both int32_t and int64_t versions of all its routines. The description below is for the int32_t version. For int64_t, all int32_t arguments become int64_t. ---------------------------------------------------------------------------- colamd_recommended: ---------------------------------------------------------------------------- C syntax: #include "colamd.h" size_t colamd_recommended (int32_t nnz, int32_t n_row, int32_t n_col) ; size_t colamd_l_recommended (int64_t nnz, int64_t n_row, int64_t n_col) ; Purpose: Returns recommended value of Alen for use by colamd. Returns 0 if any input argument is negative. The use of this routine is optional. Not needed for symamd, which dynamically allocates its own memory. Arguments (all input arguments): int32_t 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. int32_t n_row ; Number of rows in the matrix A. int32_t n_col ; Number of columns in the matrix A. ---------------------------------------------------------------------------- colamd_set_defaults: ---------------------------------------------------------------------------- C syntax: #include "colamd.h" colamd_set_defaults (double knobs [COLAMD_KNOBS]) ; colamd_l_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. NOTE: the meaning of the dense row/col knobs has changed in v2.4 knobs [0] and knobs [1] control dense row and col detection: Colamd: rows with more than max (16, knobs [COLAMD_DENSE_ROW] * sqrt (n_col)) entries are removed prior to ordering. Columns with more than max (16, knobs [COLAMD_DENSE_COL] * sqrt (MIN (n_row,n_col))) 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 max (16, knobs [COLAMD_DENSE_ROW] * sqrt (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 10. 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 [2]: aggressive absorption knobs [COLAMD_AGGRESSIVE] controls whether or not to do aggressive absorption during the ordering. Default is TRUE. ---------------------------------------------------------------------------- colamd: ---------------------------------------------------------------------------- C syntax: #include "colamd.h" int colamd (int32_t n_row, int32_t n_col, int32_t Alen, int32_t *A, int32_t *p, double knobs [COLAMD_KNOBS], int32_t stats [COLAMD_STATS]) ; int colamd_l (int64_t n_row, int64_t n_col, int64_t Alen, int64_t *A, int64_t *p, double knobs [COLAMD_KNOBS], int64_t 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: int32_t n_row ; Input argument. Number of rows in the matrix A. Restriction: n_row >= 0. Colamd returns FALSE if n_row is negative. int32_t n_col ; Input argument. Number of columns in the matrix A. Restriction: n_col >= 0. Colamd returns FALSE if n_col is negative. int32_t 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) will be sufficient. Note: the macro version does not check for integer overflow, and thus is not recommended. Use the colamd_recommended routine instead. int32_t 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. int32_t 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. int32_t 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 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 100 int32_t A [ALEN] = {0, 1, 4, 2, 4, 0, 1, 2, 3, 1, 3} ; int32_t p [ ] = {0, 3, 5, 9, 11} ; int32_t 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 (int32_t n, int32_t *A, int32_t *p, int32_t *perm, double knobs [COLAMD_KNOBS], int32_t stats [COLAMD_STATS], void (*allocate) (size_t, size_t), void (*release) (void *)) ; int symamd_l (int64_t n, int64_t *A, int64_t *p, int64_t *perm, double knobs [COLAMD_KNOBS], int64_t 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: int32_t n ; Input argument. Number of rows and columns in the symmetrix matrix A. Restriction: n >= 0. Symamd returns FALSE if n is negative. int32_t 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. int32_t 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. int32_t 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. int32_t 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). 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 (int32_t stats [COLAMD_STATS]) ; colamd_l_report (int64_t 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: int32_t stats [COLAMD_STATS] ; Input only. Statistics from colamd. ---------------------------------------------------------------------------- symamd_report: ---------------------------------------------------------------------------- C syntax: #include "colamd.h" symamd_report (int32_t stats [COLAMD_STATS]) ; symamd_l_report (int64_t 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: int32_t stats [COLAMD_STATS] ; Input only. Statistics from symamd. */ /* ========================================================================== */ /* === Scaffolding code definitions ======================================== */ /* ========================================================================== */ /* Ensure that debugging is turned off: */ #ifndef NDEBUG #define NDEBUG #endif /* turn on debugging by uncommenting the following line #undef 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... 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" #ifndef NULL #define NULL ((void *) 0) #endif /* ========================================================================== */ /* === int32_t or int64_t ============================================== */ /* ========================================================================== */ #ifdef DLONG #define Int int64_t #define UInt uint64_t #define ID "%" PRId64 #define Int_MAX INT64_MAX #define COLAMD_recommended colamd_l_recommended #define COLAMD_set_defaults colamd_l_set_defaults #define COLAMD_MAIN colamd_l #define SYMAMD_MAIN symamd_l #define COLAMD_report colamd_l_report #define SYMAMD_report symamd_l_report #else #define Int int32_t #define UInt uint32_t #define ID "%d" #define Int_MAX INT32_MAX #define COLAMD_recommended colamd_recommended #define COLAMD_set_defaults colamd_set_defaults #define COLAMD_MAIN colamd #define SYMAMD_MAIN symamd #define COLAMD_report colamd_report #define SYMAMD_report symamd_report #endif /* ========================================================================== */ /* === 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 colamd_recommended. */ 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 ; /* ========================================================================== */ /* === Definitions ========================================================== */ /* ========================================================================== */ /* Routines are either user-callable or PRIVATE (not user-callable) */ #define PRIVATE static #define DENSE_DEGREE(alpha,n) \ ((Int) MAX (16.0, (alpha) * sqrt ((double) (n)))) #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 =========================================== */ /* ========================================================================== */ #if defined (MATLAB_MEX_FILE) || defined (MATHWORKS) /* In MATLAB, matrices are 1-based to the user, but 0-based internally */ #define INDEX(i) ((i)+1) #else /* In C, matrices are 0-based and indices are reported as such in *_report */ #define INDEX(i) (i) #endif /* ========================================================================== */ /* === 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, Int aggressive ) ; 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 tag_mark, Int max_mark, Int n_row, Colamd_Row Row [] ) ; PRIVATE void print_report ( char *method, Int stats [COLAMD_STATS] ) ; /* ========================================================================== */ /* === Debugging prototypes and definitions ================================= */ /* ========================================================================== */ #ifndef NDEBUG #include /* colamd_debug is the *ONLY* global variable, and is only */ /* present when debugging */ PRIVATE Int colamd_debug = 0 ; /* debug print level */ #define DEBUG0(params) { SUITESPARSE_PRINTF (params) ; } #define DEBUG1(params) { if (colamd_debug >= 1) SUITESPARSE_PRINTF (params) ; } #define DEBUG2(params) { if (colamd_debug >= 2) SUITESPARSE_PRINTF (params) ; } #define DEBUG3(params) { if (colamd_debug >= 3) SUITESPARSE_PRINTF (params) ; } #define DEBUG4(params) { if (colamd_debug >= 4) SUITESPARSE_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) #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, or if integer overflow occurs, a 0 is returned as an error condition. 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 (roughly 6*n_col + 4*n_row). An additional n_col space is the minimal amount of "elbow room", and nnz/5 more space is recommended for run time efficiency. Alen is approximately 2.2*nnz + 7*n_col + 4*n_row + 10. This function is not needed when using symamd. */ /* add two values of type size_t, and check for integer overflow */ static size_t t_add (size_t a, size_t b, int *ok) { (*ok) = (*ok) && ((a + b) >= MAX (a,b)) ; return ((*ok) ? (a + b) : 0) ; } /* compute a*k where k is a small integer, and check for integer overflow */ static size_t t_mult (size_t a, size_t k, int *ok) { size_t i, s = 0 ; for (i = 0 ; i < k ; i++) { s = t_add (s, a, ok) ; } return (s) ; } /* size of the Col and Row structures */ #define COLAMD_C(n_col,ok) \ ((t_mult (t_add (n_col, 1, ok), sizeof (Colamd_Col), ok) / sizeof (Int))) #define COLAMD_R(n_row,ok) \ ((t_mult (t_add (n_row, 1, ok), sizeof (Colamd_Row), ok) / sizeof (Int))) size_t 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 */ ) { size_t s, c, r ; int ok = TRUE ; if (nnz < 0 || n_row < 0 || n_col < 0) { return (0) ; } s = t_mult (nnz, 2, &ok) ; /* 2*nnz */ c = COLAMD_C (n_col, &ok) ; /* size of column structures */ r = COLAMD_R (n_row, &ok) ; /* size of row structures */ s = t_add (s, c, &ok) ; s = t_add (s, r, &ok) ; s = t_add (s, n_col, &ok) ; /* elbow room */ s = t_add (s, nnz/5, &ok) ; /* elbow room */ return (ok ? s : 0) ; } /* ========================================================================== */ /* === colamd_set_defaults ================================================== */ /* ========================================================================== */ /* The colamd_set_defaults routine sets the default values of the user- controllable parameters for colamd and symamd: Colamd: rows with more than max (16, knobs [0] * sqrt (n_col)) entries are removed prior to ordering. Columns with more than max (16, knobs [1] * sqrt (MIN (n_row,n_col))) entries are removed prior to ordering, and placed last in the output column ordering. Symamd: Rows and columns with more than max (16, knobs [0] * sqrt (n)) entries are removed prior to ordering, and placed last in the output ordering. knobs [0] dense row control knobs [1] dense column control knobs [2] if nonzero, do aggresive absorption knobs [3..19] unused, but future versions might use this */ 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] = 10 ; knobs [COLAMD_DENSE_COL] = 10 ; knobs [COLAMD_AGGRESSIVE] = TRUE ; /* default: do aggressive absorption*/ } /* ========================================================================== */ /* === symamd =============================================================== */ /* ========================================================================== */ int SYMAMD_MAIN /* 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 */ size_t 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 */ #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 ; } } /* v2.4: removed free(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 = %g\n", n_row, n, mnz, (double) Mlen)) ; if (!M) { stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ; (*release) ((void *) count) ; (*release) ((void *) mark) ; DEBUG0 (("symamd: allocate M (size %g) failed\n", (double) 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 ; } } } /* v2.4: free(mark) moved below */ } /* count and mark no longer needed */ (*release) ((void *) count) ; (*release) ((void *) mark) ; /* v2.4: free (mark) moved here */ 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 ; cknobs [COLAMD_DENSE_COL] = knobs [COLAMD_DENSE_ROW] ; /* === Order the columns of M =========================================== */ /* v2.4: colamd cannot fail here, so the error check is removed */ (void) COLAMD_MAIN (n_row, n, (Int) Mlen, M, perm, cknobs, stats) ; /* Note that the output permutation is now in perm */ /* === get the statistics for symamd from colamd ======================== */ /* a dense column in colamd means a dense row and col in symamd */ stats [COLAMD_DENSE_ROW] = stats [COLAMD_DENSE_COL] ; /* === 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. */ int COLAMD_MAIN /* 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 */ size_t Row_size ; /* size of Row [], in integers */ size_t Col_size ; /* size of Col [], in integers */ size_t 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 */ Int aggressive ; /* do aggressive absorption */ int ok ; #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 ; } aggressive = (knobs [COLAMD_AGGRESSIVE] != FALSE) ; /* === Allocate the Row and Col arrays from array A ===================== */ ok = TRUE ; Col_size = COLAMD_C (n_col, &ok) ; /* size of Col array of structs */ Row_size = COLAMD_R (n_row, &ok) ; /* size of Row array of structs */ /* need = 2*nnz + n_col + Col_size + Row_size ; */ need = t_mult (nnz, 2, &ok) ; need = t_add (need, n_col, &ok) ; need = t_add (need, Col_size, &ok) ; need = t_add (need, Row_size, &ok) ; if (!ok || need > (size_t) 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, aggressive) ; /* === 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 ======================================================== */ /* ========================================================================== */ void COLAMD_report ( Int stats [COLAMD_STATS] ) { print_report ("colamd", stats) ; } /* ========================================================================== */ /* === symamd_report ======================================================== */ /* ========================================================================== */ 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 ==================================================== */ /* Note: if knobs contains a NaN, this is undefined: */ if (knobs [COLAMD_DENSE_ROW] < 0) { /* only remove completely dense rows */ dense_row_count = n_col-1 ; } else { dense_row_count = DENSE_DEGREE (knobs [COLAMD_DENSE_ROW], n_col) ; } if (knobs [COLAMD_DENSE_COL] < 0) { /* only remove completely dense columns */ dense_col_count = n_row-1 ; } else { dense_col_count = DENSE_DEGREE (knobs [COLAMD_DENSE_COL], MIN (n_row, n_col)) ; } 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) */ Int aggressive ) { /* === 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 */ UInt 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 (0, max_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)) ; /* 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) ; DEBUG3 (("Pivot col: %d thick %d\n", pivot_col, pivot_col_thickness)) ; /* === 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 (0, max_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_ALIVE (row)) { 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 && aggressive) { 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)) { DEBUG4 ((" Row %d, dead\n", row)) ; continue ; } DEBUG4 ((" Row %d, set diff %d\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: %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 (((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) ; /* === Clear mark =================================================== */ tag_mark = clear_mark (tag_mark+max_deg+1, max_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]) ; ASSERT (Row [pivot_row].length > 0) ; Row [pivot_row].shared1.degree = pivot_row_degree ; Row [pivot_row].shared2.mark = 0 ; /* pivot row is no longer dead */ DEBUG1 (("Resurrect Pivot_row %d deg: %d\n", pivot_row, pivot_row_degree)) ; } } /* === 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_DEAD (r) || (Row [r].length == 0)) { /* This row is already dead, or is of zero length. Cannot compact * a row of zero length, so kill it. NOTE: in the current version, * there are no zero-length live rows. Kill the row (for the first * time, or again) just to be safe. */ 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)) ; ASSERT (Row [r].length > 0) ; /* 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]) ; ASSERT (Row [r].length > 0) ; #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 tag_mark, /* new value of tag_mark */ Int max_mark, /* max allowed value of tag_mark */ 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 ; if (tag_mark <= 0 || tag_mark >= max_mark) { for (r = 0 ; r < n_row ; r++) { if (ROW_IS_ALIVE (r)) { Row [r].shared2.mark = 0 ; } } tag_mark = 1 ; } return (tag_mark) ; } /* ========================================================================== */ /* === print_report ========================================================= */ /* ========================================================================== */ PRIVATE void print_report ( char *method, Int stats [COLAMD_STATS] ) { Int i1, i2, i3 ; SUITESPARSE_PRINTF (("\n%s version %d.%d.%d, %s: ", method, COLAMD_MAIN_VERSION, COLAMD_SUB_VERSION, COLAMD_SUBSUB_VERSION, COLAMD_DATE)) ; if (!stats) { SUITESPARSE_PRINTF (("No statistics available.\n")) ; return ; } i1 = stats [COLAMD_INFO1] ; i2 = stats [COLAMD_INFO2] ; i3 = stats [COLAMD_INFO3] ; if (stats [COLAMD_STATUS] >= 0) { SUITESPARSE_PRINTF (("OK. ")) ; } else { SUITESPARSE_PRINTF (("ERROR. ")) ; } switch (stats [COLAMD_STATUS]) { case COLAMD_OK_BUT_JUMBLED: SUITESPARSE_PRINTF(( "Matrix has unsorted or duplicate row indices.\n")) ; SUITESPARSE_PRINTF(( "%s: number of duplicate or out-of-order row indices: %d\n", method, i3)) ; SUITESPARSE_PRINTF(( "%s: last seen duplicate or out-of-order row index: %d\n", method, INDEX (i2))) ; SUITESPARSE_PRINTF(( "%s: last seen in column: %d", method, INDEX (i1))) ; /* no break - fall through to next case instead */ case COLAMD_OK: SUITESPARSE_PRINTF(("\n")) ; SUITESPARSE_PRINTF(( "%s: number of dense or empty rows ignored: %d\n", method, stats [COLAMD_DENSE_ROW])) ; SUITESPARSE_PRINTF(( "%s: number of dense or empty columns ignored: %d\n", method, stats [COLAMD_DENSE_COL])) ; SUITESPARSE_PRINTF(( "%s: number of garbage collections performed: %d\n", method, stats [COLAMD_DEFRAG_COUNT])) ; break ; case COLAMD_ERROR_A_not_present: SUITESPARSE_PRINTF(( "Array A (row indices of matrix) not present.\n")) ; break ; case COLAMD_ERROR_p_not_present: SUITESPARSE_PRINTF(( "Array p (column pointers for matrix) not present.\n")) ; break ; case COLAMD_ERROR_nrow_negative: SUITESPARSE_PRINTF(("Invalid number of rows (%d).\n", i1)) ; break ; case COLAMD_ERROR_ncol_negative: SUITESPARSE_PRINTF(("Invalid number of columns (%d).\n", i1)) ; break ; case COLAMD_ERROR_nnz_negative: SUITESPARSE_PRINTF(( "Invalid number of nonzero entries (%d).\n", i1)) ; break ; case COLAMD_ERROR_p0_nonzero: SUITESPARSE_PRINTF(( "Invalid column pointer, p [0] = %d, must be zero.\n", i1)); break ; case COLAMD_ERROR_A_too_small: SUITESPARSE_PRINTF(("Array A too small.\n")) ; SUITESPARSE_PRINTF(( " Need Alen >= %d, but given only Alen = %d.\n", i1, i2)) ; break ; case COLAMD_ERROR_col_length_negative: SUITESPARSE_PRINTF (("Column %d has a negative number of nonzero entries (%d).\n", INDEX (i1), i2)) ; break ; case COLAMD_ERROR_row_index_out_of_bounds: SUITESPARSE_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: SUITESPARSE_PRINTF(("Out of memory.\n")) ; break ; /* v2.4: internal-error case deleted */ } } /* ========================================================================== */ /* === 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 ) { FILE *f ; colamd_debug = 0 ; /* no debug printing */ f = fopen ("debug", "r") ; if (f == (FILE *) NULL) { colamd_debug = 0 ; } else { fscanf (f, "%d", &colamd_debug) ; fclose (f) ; } DEBUG0 (("%s: debug version, D = %d (THIS WILL BE SLOW!)\n", method, colamd_debug)) ; } #endif /* NDEBUG */ ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/���������������������������������������������������������������������0000755�0001751�0000144�00000000000�14576344041�015667� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Include/�������������������������������������������������������������0000755�0001751�0000144�00000000000�14576343415�017256� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Include/cholmod_types.h����������������������������������������������0000644�0001751�0000144�00000010375�14552026002�022266� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Include/cholmod_types.h //------------------------------------------------------------------------------ // CHOLMOD/Include/cholmod_types.h. Copyright (C) 2005-2023, // Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 //------------------------------------------------------------------------------ // CHOLMOD internal include file for defining integer types. This file is // suitable for inclusion in C and C++ codes. It can be #include'd more than // once. The #include'ing file defines one of two macros (CHOLMOD_INT32 or // CHOLMOD_INT64). CHOLMOD is designed for 2 types of integer variables: // int32_t or int64_t. // // The complex types (ANSI-compatible complex, and MATLAB-compatible zomplex) // are based on the double or float type, and are not selected here. They are // typically selected via template routines. //------------------------------------------------------------------------------ #undef Int #undef UInt #undef Int_max #undef CHOLMOD #undef ITYPE #undef ID #undef CLEAR_FLAG // #undef I_GOTCHA // #undef L_GOTCHA #if defined ( CHOLMOD_INT64 ) //-------------------------------------------------------------------------- // CHOLMOD_INT64: int64_t //-------------------------------------------------------------------------- #define Int int64_t #define UInt uint64_t #define Int_max INT64_MAX #define CHOLMOD(name) cholmod_l_ ## name #define ITYPE CHOLMOD_LONG #define ID "%" PRId64 // #define L_GOTCHA GOTCHA // #define I_GOTCHA ; #define CLEAR_FLAG(Common) \ { \ Common->mark++ ; \ if (Common->mark <= 0) \ { \ Common->mark = EMPTY ; \ cholmod_l_clear_flag (Common) ; \ } \ } #else //-------------------------------------------------------------------------- // CHOLMOD_INT32: int32 //-------------------------------------------------------------------------- #ifndef CHOLMOD_INT32 #define CHOLMOD_INT32 #endif #define Int int32_t #define UInt uint32_t #define Int_max INT32_MAX #define CHOLMOD(name) cholmod_ ## name #define ITYPE CHOLMOD_INT #define ID "%d" // #define L_GOTCHA ; // #define I_GOTCHA GOTCHA #define CLEAR_FLAG(Common) \ { \ Common->mark++ ; \ if (Common->mark <= 0 || Common->mark > INT32_MAX) \ { \ Common->mark = EMPTY ; \ cholmod_clear_flag (Common) ; \ } \ } #endif //------------------------------------------------------------------------------ // check for BLAS integer overflow //------------------------------------------------------------------------------ // The conversion of a CHOLMOD integer (Int) to a BLAS/LAPACK integer (the // SUITESPARSE_BLAS_INT can result in an integer overflow. This is detected by // the SUITESPARSE_TO_BLAS_INT macro in SuiteSparse_config.h. If the error // condition occurs, that macro sets Common->blas_ok to false, and that call // and any subsequent calls to the BLAS/LAPACK will be skipped. From that // point on, Common->blas_ok will remain false for that call to CHOLMOD. The // following macro sets CHOLMOD status to CHOLMOD_TOO_LARGE if the BLAS // conversion has failed. This is done only once for a particular call to any // given CHOLMOD method. #define CHECK_FOR_BLAS_INTEGER_OVERFLOW \ { \ if ((sizeof (SUITESPARSE_BLAS_INT) < sizeof (Int)) && \ (Common->status == CHOLMOD_OK) && !(Common->blas_ok)) \ { \ ERROR (CHOLMOD_TOO_LARGE, "BLAS integer overflow") ; \ } \ } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Include/cholmod_internal.h�������������������������������������������0000644�0001751�0000144�00000073150�14552026002�022736� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Include/cholmod_internal.h //------------------------------------------------------------------------------ // CHOLMOD/Include/cholmod_internal.h. Copyright (C) 2005-2023, // Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 //------------------------------------------------------------------------------ // CHOLMOD internal include file. // // This file contains internal definitions for CHOLMOD, not meant to be // included in user code. They define macros that are not prefixed with // CHOLMOD_. This file can safely #include'd in user code if you want to make // use of the macros defined here, and don't mind the possible name conflicts // with your code, however. // // Required by all CHOLMOD routines. Not required by any user routine that // uses CHOLMOMD. Unless debugging is enabled, this file does not require any // CHOLMOD module (not even the Utility module). // // If debugging is enabled, all CHOLMOD modules require the Check module. // Enabling debugging requires that this file be editted. Debugging cannot be // enabled with a compiler flag. This is because CHOLMOD is exceedingly slow // when debugging is enabled. Debugging is meant for development of CHOLMOD // itself, not by users of CHOLMOD. #ifndef CHOLMOD_INTERNAL_H #define CHOLMOD_INTERNAL_H #define SUITESPARSE_BLAS_DEFINITIONS #include "cholmod.h" //------------------------------------------------------------------------------ // debugging and basic includes //------------------------------------------------------------------------------ // turn off debugging #ifndef NDEBUG #define NDEBUG #endif // Uncomment this line to enable debugging. CHOLMOD will be very slow. // #undef NDEBUG // Uncomment this line to get a summary of the time spent in the BLAS, // for development diagnostics only: // #define BLAS_TIMER // Uncomment this line to get a long dump as a text file (blas_dump.txt), that // records each call to the BLAS, for development diagnostics only: // #define BLAS_DUMP // if BLAS_DUMP is enabled, the BLAS_TIMER must also be enabled. #if defined ( BLAS_DUMP ) && ! defined ( BLAS_TIMER ) #define BLAS_TIMER #endif //------------------------------------------------------------------------------ // basic definitions //------------------------------------------------------------------------------ // Some non-conforming compilers insist on defining TRUE and FALSE. #undef TRUE #undef FALSE #define TRUE 1 #define FALSE 0 // NULL should already be defined, but ensure it is here. #ifndef NULL #define NULL ((void *) 0) #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)) // MAX and MIN are not safe to use for NaN's #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #define MAX3(a,b,c) (((a) > (b)) ? (MAX (a,c)) : (MAX (b,c))) #define MAX4(a,b,c,d) (((a) > (b)) ? (MAX3 (a,c,d)) : (MAX3 (b,c,d))) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define IMPLIES(p,q) (!(p) || (q)) // RANGE (k, lo, hi): ensures k is in range lo:hi #define RANGE(k,lo,hi) \ (((k) < (lo)) ? (lo) : \ (((k) > (hi)) ? (hi) : (k))) // find the sign: -1 if x < 0, 1 if x > 0, zero otherwise. // Not safe for NaN's #define SIGN(x) (((x) < 0) ? (-1) : (((x) > 0) ? 1 : 0)) // round up an integer x to a multiple of s #define ROUNDUP(x,s) ((s) * (((x) + ((s) - 1)) / (s))) #define ERROR(status,msg) \ CHOLMOD(error) (status, __FILE__, __LINE__, msg, Common) // Check a pointer and return if null. Set status to invalid, unless the // status is already "out of memory" #define RETURN_IF_NULL(A,result) \ { \ if ((A) == NULL) \ { \ if (Common->status != CHOLMOD_OUT_OF_MEMORY) \ { \ ERROR (CHOLMOD_INVALID, "argument missing") ; \ } \ return (result) ; \ } \ } // Return if Common is NULL or invalid #define RETURN_IF_NULL_COMMON(result) \ { \ if (Common == NULL) \ { \ return (result) ; \ } \ if (Common->itype != ITYPE) \ { \ Common->status = CHOLMOD_INVALID ; \ return (result) ; \ } \ } // 1e308 is a huge number that doesn't take many characters to print in a // file, in CHOLMOD/Check/cholmod_read and _write. Numbers larger than this // are interpretted as Inf, since sscanf doesn't read in Inf's properly. // This assumes IEEE double precision arithmetic. DBL_MAX would be a little // better, except that it takes too many digits to print in a file. #define HUGE_DOUBLE 1e308 //============================================================================== // int32/int64 and double/single definitions //============================================================================== #include "cholmod_types.h" #ifndef CHOLMOD_INT64 // GPU acceleration only available for the CHOLMOD_INT64 case (int64) #undef CHOLMOD_HAS_CUDA #endif //------------------------------------------------------------------------------ // internal routines //------------------------------------------------------------------------------ bool cholmod_mult_uint64_t // c = a*b, return true if ok ( uint64_t *c, const uint64_t a, const uint64_t b ) ; size_t cholmod_add_size_t (size_t a, size_t b, int *ok) ; size_t cholmod_mult_size_t (size_t a, size_t b, int *ok) ; size_t cholmod_l_add_size_t (size_t a, size_t b, int *ok) ; size_t cholmod_l_mult_size_t (size_t a, size_t b, int *ok) ; int64_t cholmod_cumsum // return sum (Cnz), or -1 if int32_t overflow ( int32_t *Cp, // size n+1, output array, the cumsum of Cnz int32_t *Cnz, // size n, input array size_t n // size of Cp and Cnz ) ; int64_t cholmod_l_cumsum // return sum (Cnz), or -1 if int64_t overflow ( int64_t *Cp, // size n+1, output array, the cumsum of Cnz int64_t *Cnz, // size n, input array size_t n // size of Cp and Cnz ) ; void cholmod_set_empty ( int32_t *S, // int32 array of size n size_t n ) ; void cholmod_l_set_empty ( int64_t *S, // int64 array of size n size_t n ) ; void cholmod_to_simplicial_sym ( cholmod_factor *L, // sparse factorization to modify int to_ll, // change L to hold a LL' or LDL' factorization cholmod_common *Common ) ; void cholmod_l_to_simplicial_sym ( cholmod_factor *L, // sparse factorization to modify int to_ll, // change L to hold a LL' or LDL' factorization cholmod_common *Common ) ; //------------------------------------------------------------------------------ // operations for pattern/real/complex/zomplex //------------------------------------------------------------------------------ // Define operations on pattern, real, complex, and zomplex objects. // // The xtype of an object defines it numerical type. A qttern object has no // numerical values (A->x and A->z are NULL). A real object has no imaginary // qrt (A->x is used, A->z is NULL). A complex object has an imaginary qrt // that is stored interleaved with its real qrt (A->x is of size 2*nz, A->z // is NULL). A zomplex object has both real and imaginary qrts, which are // stored seqrately, as in MATLAB (A->x and A->z are both used). // // XTYPE is CHOLMOD_PATTERN, _REAL, _COMPLEX or _ZOMPLEX, and is the xtype of // the template routine under construction. XTYPE2 is equal to XTYPE, except // if XTYPE is CHOLMOD_PATTERN, in which case XTYPE is CHOLMOD_REAL. // XTYPE and XTYPE2 are defined in cholmod_template.h. //------------------------------------------------------------------------------ // pattern: single or double //------------------------------------------------------------------------------ #define P_TEMPLATE(name) p_ ## name #define PS_TEMPLATE(name) ps_ ## name #define P_ASSIGN2(x,z,p,ax,az,q) x [p] = 1 #define P_PRINT(k,x,z,p) PRK(k, ("1")) //------------------------------------------------------------------------------ // real: single or double //------------------------------------------------------------------------------ #define RD_TEMPLATE(name) rd_ ## name #define RS_TEMPLATE(name) rs_ ## name #define R_ABS(x,z,p) fabs ((double) (x [p])) #define R_ASSEMBLE(x,z,p,ax,az,q) x [p] += ax [q] #define R_ASSIGN(x,z,p,ax,az,q) x [p] = ax [q] #define R_ASSIGN_CONJ(x,z,p,ax,az,q) x [p] = ax [q] #define R_ASSIGN_REAL(x,p,ax,q) x [p] = ax [q] #define R_XTYPE_OK(type) ((type) == CHOLMOD_REAL) #define R_IS_NONZERO(ax,az,q) (ax [q] != 0) #define R_IS_ZERO(ax,az,q) (ax [q] == 0) #define R_IS_ONE(ax,az,q) (ax [q] == 1) #define R_MULT(x,z,p, ax,az,q, bx,bz,r) x [p] = ax [q] * bx [r] #define R_MULTADD(x,z,p, ax,az,q, bx,bz,r) x [p] += ax [q] * bx [r] #define R_MULTSUB(x,z,p, ax,az,q, bx,bz,r) x [p] -= ax [q] * bx [r] #define R_MULTADDCONJ(x,z,p, ax,az,q, bx,bz,r) x [p] += ax [q] * bx [r] #define R_MULTSUBCONJ(x,z,p, ax,az,q, bx,bz,r) x [p] -= ax [q] * bx [r] #define R_ADD(x,z,p, ax,az,q, bx,bz,r) x [p] = ax [q] + bx [r] #define R_ADD_REAL(x,p, ax,q, bx,r) x [p] = ax [q] + bx [r] #define R_CLEAR(x,z,p) x [p] = 0 #define R_CLEAR_IMAG(x,z,p) #define R_DIV(x,z,p,ax,az,q) x [p] /= ax [q] #define R_LLDOT(x,p, ax,az,q) x [p] -= ax [q] * ax [q] #define R_PRINT(k,x,z,p) PRK(k, ("%24.16e", x [p])) #define R_DIV_REAL(x,z,p, ax,az,q, bx,r) x [p] = ax [q] / bx [r] #define R_MULT_REAL(x,z,p, ax,az,q, bx,r) x [p] = ax [q] * bx [r] #define R_LDLDOT(x,p, ax,az,q, bx,r) x [p] -=(ax[q] * ax[q])/ bx[r] //------------------------------------------------------------------------------ // complex: single or double //------------------------------------------------------------------------------ #define CD_TEMPLATE(name) cd_ ## name #define CD_T_TEMPLATE(name) cd_t_ ## name #define CS_TEMPLATE(name) cs_ ## name #define CS_T_TEMPLATE(name) cs_t_ ## name #define C_ABS(x,z,p) SuiteSparse_config_hypot ((double) (x [2*(p)]), \ (double) (x [2*(p)+1])) #define C_ASSEMBLE(x,z,p,ax,az,q) \ x [2*(p) ] += ax [2*(q) ] ; \ x [2*(p)+1] += ax [2*(q)+1] #define C_ASSIGN(x,z,p,ax,az,q) \ x [2*(p) ] = ax [2*(q) ] ; \ x [2*(p)+1] = ax [2*(q)+1] #define C_ASSIGN_REAL(x,p,ax,q) x [2*(p)] = ax [2*(q)] #define C_ASSIGN_CONJ(x,z,p,ax,az,q) \ x [2*(p) ] = ax [2*(q) ] ; \ x [2*(p)+1] = -ax [2*(q)+1] #define C_XTYPE_OK(type) ((type) == CHOLMOD_COMPLEX) #define C_IS_NONZERO(ax,az,q) ((ax [2*(q)] != 0) || (ax [2*(q)+1] != 0)) #define C_IS_ZERO(ax,az,q) ((ax [2*(q)] == 0) && (ax [2*(q)+1] == 0)) #define C_IS_ONE(ax,az,q) \ ((ax [2*(q)] == 1) && (ax [2*(q)+1]) == 0) #define C_IMAG_IS_NONZERO(ax,az,q) (ax [2*(q)+1] != 0) #define C_MULT(x,z,p, ax,az,q, bx,bz,r) \ x [2*(p) ] = ax [2*(q) ] * bx [2*(r)] - ax [2*(q)+1] * bx [2*(r)+1] ; \ x [2*(p)+1] = ax [2*(q)+1] * bx [2*(r)] + ax [2*(q) ] * bx [2*(r)+1] #define C_MULTADD(x,z,p, ax,az,q, bx,bz,r) \ x [2*(p) ] += ax [2*(q) ] * bx [2*(r)] - ax [2*(q)+1] * bx [2*(r)+1] ; \ x [2*(p)+1] += ax [2*(q)+1] * bx [2*(r)] + ax [2*(q) ] * bx [2*(r)+1] #define C_MULTSUB(x,z,p, ax,az,q, bx,bz,r) \ x [2*(p) ] -= ax [2*(q) ] * bx [2*(r)] - ax [2*(q)+1] * bx [2*(r)+1] ; \ x [2*(p)+1] -= ax [2*(q)+1] * bx [2*(r)] + ax [2*(q) ] * bx [2*(r)+1] // s += conj(a)*b #define C_MULTADDCONJ(x,z,p, ax,az,q, bx,bz,r) \ x [2*(p) ] += ax [2*(q) ] * bx [2*(r)] + ax [2*(q)+1] * bx [2*(r)+1] ;\ x [2*(p)+1] += (-ax [2*(q)+1]) * bx [2*(r)] + ax [2*(q) ] * bx [2*(r)+1] // s -= conj(a)*b #define C_MULTSUBCONJ(x,z,p, ax,az,q, bx,bz,r) \ x [2*(p) ] -= ax [2*(q) ] * bx [2*(r)] + ax [2*(q)+1] * bx [2*(r)+1] ;\ x [2*(p)+1] -= (-ax [2*(q)+1]) * bx [2*(r)] + ax [2*(q) ] * bx [2*(r)+1] #define C_ADD(x,z,p, ax,az,q, bx,bz,r) \ x [2*(p) ] = ax [2*(q) ] + bx [2*(r) ] ; \ x [2*(p)+1] = ax [2*(q)+1] + bx [2*(r)+1] #define C_ADD_REAL(x,p, ax,q, bx,r) \ x [2*(p)] = ax [2*(q)] + bx [2*(r)] #define C_CLEAR(x,z,p) \ x [2*(p) ] = 0 ; \ x [2*(p)+1] = 0 #define C_CLEAR_IMAG(x,z,p) \ x [2*(p)+1] = 0 // s = s / a (complex double case) #define C_DIV(x,z,p,ax,az,q) \ SuiteSparse_config_divcomplex ( \ x [2*(p)], x [2*(p)+1], \ ax [2*(q)], ax [2*(q)+1], \ &x [2*(p)], &x [2*(p)+1]) // s = s / a (complex single case) #define C_S_DIV(x,z,p,ax,az,q) \ { \ double cr, ci ; \ SuiteSparse_config_divcomplex ( \ (double) x [2*(p)], (double) x [2*(p)+1], \ (double) ax [2*(q)], (double) ax [2*(q)+1], \ &cr, &ci) ; \ x [2*(p) ] = (float) cr ; \ x [2*(p)+1] = (float) ci ; \ } // s -= conj(a)*a ; note that the result of conj(a)*a is real #define C_LLDOT(x,p, ax,az,q) \ x [2*(p)] -= ax [2*(q)] * ax [2*(q)] + ax [2*(q)+1] * ax [2*(q)+1] #define C_PRINT(k,x,z,p) PRK(k, ("(%24.16e,%24.16e)", x [2*(p)], x [2*(p)+1])) #define C_DIV_REAL(x,z,p, ax,az,q, bx,r) \ x [2*(p) ] = ax [2*(q) ] / bx [2*(r)] ; \ x [2*(p)+1] = ax [2*(q)+1] / bx [2*(r)] #define C_MULT_REAL(x,z,p, ax,az,q, bx,r) \ x [2*(p) ] = ax [2*(q) ] * bx [2*(r)] ; \ x [2*(p)+1] = ax [2*(q)+1] * bx [2*(r)] // s -= conj(a)*a/t #define C_LDLDOT(x,p, ax,az,q, bx,r) \ x [2*(p)] -= (ax [2*(q)] * ax [2*(q)] + ax [2*(q)+1] * ax [2*(q)+1]) / bx[r] //------------------------------------------------------------------------------ // zomplex: single or double //------------------------------------------------------------------------------ #define ZD_TEMPLATE(name) zd_ ## name #define ZD_T_TEMPLATE(name) zd_t_ ## name #define ZS_TEMPLATE(name) zs_ ## name #define ZS_T_TEMPLATE(name) zs_t_ ## name #define Z_ABS(x,z,p) SuiteSparse_config_hypot ((double) (x [p]), \ (double) (z [p])) #define Z_ASSEMBLE(x,z,p,ax,az,q) \ x [p] += ax [q] ; \ z [p] += az [q] #define Z_ASSIGN(x,z,p,ax,az,q) \ x [p] = ax [q] ; \ z [p] = az [q] #define Z_ASSIGN_REAL(x,p,ax,q) x [p] = ax [q] #define Z_ASSIGN_CONJ(x,z,p,ax,az,q) \ x [p] = ax [q] ; \ z [p] = -az [q] #define Z_XTYPE_OK(type) ((type) == CHOLMOD_ZOMPLEX) #define Z_IS_NONZERO(ax,az,q) ((ax [q] != 0) || (az [q] != 0)) #define Z_IS_ZERO(ax,az,q) ((ax [q] == 0) && (az [q] == 0)) #define Z_IS_ONE(ax,az,q) ((ax [q] == 1) && (az [q] == 0)) #define Z_IMAG_IS_NONZERO(ax,az,q) (az [q] != 0) #define Z_MULT(x,z,p, ax,az,q, bx,bz,r) \ x [p] = ax [q] * bx [r] - az [q] * bz [r] ; \ z [p] = az [q] * bx [r] + ax [q] * bz [r] #define Z_MULTADD(x,z,p, ax,az,q, bx,bz,r) \ x [p] += ax [q] * bx [r] - az [q] * bz [r] ; \ z [p] += az [q] * bx [r] + ax [q] * bz [r] #define Z_MULTSUB(x,z,p, ax,az,q, bx,bz,r) \ x [p] -= ax [q] * bx [r] - az [q] * bz [r] ; \ z [p] -= az [q] * bx [r] + ax [q] * bz [r] #define Z_MULTADDCONJ(x,z,p, ax,az,q, bx,bz,r) \ x [p] += ax [q] * bx [r] + az [q] * bz [r] ; \ z [p] += (-az [q]) * bx [r] + ax [q] * bz [r] #define Z_MULTSUBCONJ(x,z,p, ax,az,q, bx,bz,r) \ x [p] -= ax [q] * bx [r] + az [q] * bz [r] ; \ z [p] -= (-az [q]) * bx [r] + ax [q] * bz [r] #define Z_ADD(x,z,p, ax,az,q, bx,bz,r) \ x [p] = ax [q] + bx [r] ; \ z [p] = az [q] + bz [r] #define Z_ADD_REAL(x,p, ax,q, bx,r) \ x [p] = ax [q] + bx [r] #define Z_CLEAR(x,z,p) \ x [p] = 0 ; \ z [p] = 0 #define Z_CLEAR_IMAG(x,z,p) \ z [p] = 0 // s = s / a (zomplex double case) #define Z_DIV(x,z,p,ax,az,q) \ SuiteSparse_config_divcomplex \ (x [p], z [p], ax [q], az [q], &x [p], &z [p]) // s = s / a (zomplex single case) #define Z_S_DIV(x,z,p,ax,az,q) \ { \ double cr, ci ; \ SuiteSparse_config_divcomplex ( \ (double) x [p], (double) z [p], \ (double) ax [q], (double) az [q], \ &cr, &ci) ; \ x [p] = (float) cr ; \ z [p] = (float) ci ; \ } // s -= conj(a)*a ; note that the result of conj(a)*a is real #define Z_LLDOT(x,p, ax,az,q) \ x [p] -= ax [q] * ax [q] + az [q] * az [q] #define Z_PRINT(k,x,z,p) PRK(k, ("(%24.16e,%24.16e)", x [p], z [p])) #define Z_DIV_REAL(x,z,p, ax,az,q, bx,r) \ x [p] = ax [q] / bx [r] ; \ z [p] = az [q] / bx [r] #define Z_MULT_REAL(x,z,p, ax,az,q, bx,r) \ x [p] = ax [q] * bx [r] ; \ z [p] = az [q] * bx [r] // s -= conj(a)*a/t #define Z_LDLDOT(x,p, ax,az,q, bx,r) \ x [p] -= (ax [q] * ax [q] + az [q] * az [q]) / bx[r] //------------------------------------------------------------------------------ // all classes //------------------------------------------------------------------------------ // Check if A->xtype and the two arrays A->x and A->z are valid. Set status to // invalid, unless status is already "out of memory". A can be a sparse matrix, // dense matrix, factor, or triplet. #define RETURN_IF_XTYPE_IS_INVALID(xtype,xtype1,xtype2,result) \ if (xtype < (xtype1) || xtype > (xtype2)) \ { \ if (Common->status != CHOLMOD_OUT_OF_MEMORY) \ { \ ERROR (CHOLMOD_INVALID, "invalid xtype") ; \ } \ return (result) ; \ } \ #define RETURN_IF_XTYPE_INVALID(A,xtype1,xtype2,result) \ { \ if ((A)->xtype < (xtype1) || (A)->xtype > (xtype2) || \ ((A)->xtype != CHOLMOD_PATTERN && ((A)->x) == NULL) || \ ((A)->xtype == CHOLMOD_ZOMPLEX && ((A)->z) == NULL) || \ !(((A)->dtype == CHOLMOD_DOUBLE) || ((A)->dtype == CHOLMOD_SINGLE))) \ { \ if (Common->status != CHOLMOD_OUT_OF_MEMORY) \ { \ ERROR (CHOLMOD_INVALID, "invalid xtype or dtype") ; \ } \ return (result) ; \ } \ } #define RETURN_IF_DENSE_MATRIX_INVALID(X,result) \ RETURN_IF_NULL (X, result) ; \ RETURN_IF_XTYPE_INVALID (X, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, result) ; \ if ((X)->d < (X)->nrow) \ { \ if (Common->status != CHOLMOD_OUT_OF_MEMORY) \ { \ ERROR (CHOLMOD_INVALID, "dense matrix invalid") ; \ } \ return (result) ; \ } #define RETURN_IF_SPARSE_MATRIX_INVALID(A,result) \ RETURN_IF_NULL (A, result) ; \ RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, result) ; \ if ((A)->p == NULL || (!(A)->packed && ((A)->nz == NULL)) || \ (A->stype != 0 && A->nrow != A->ncol)) \ { \ if (Common->status != CHOLMOD_OUT_OF_MEMORY) \ { \ ERROR (CHOLMOD_INVALID, "sparse matrix invalid") ; \ } \ return (result) ; \ } #define RETURN_IF_TRIPLET_MATRIX_INVALID(T,result) \ RETURN_IF_NULL (T, result) ; \ RETURN_IF_XTYPE_INVALID (T, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, result) ; \ if ((T)->nnz > 0 && ((T)->i == NULL || (T)->j == NULL || \ ((T)->xtype != CHOLMOD_PATTERN && (T)->x == NULL) || \ ((T)->xtype == CHOLMOD_ZOMPLEX && (T)->z == NULL))) \ { \ if (Common->status != CHOLMOD_OUT_OF_MEMORY) \ { \ ERROR (CHOLMOD_INVALID, "triplet matrix invalid") ; \ } \ return (result) ; \ } #define RETURN_IF_FACTOR_INVALID(L,result) \ RETURN_IF_NULL (L, result) ; \ RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, result) ; //============================================================================== //=== openmp support =========================================================== //============================================================================== static inline int cholmod_nthreads // returns # of OpenMP threads to use ( double work, // total work to do cholmod_common *Common ) { #ifdef _OPENMP double chunk = Common->chunk ; // give each thread at least this much work int nthreads_max = Common->nthreads_max ; // max # of threads to use if (nthreads_max <= 0) { nthreads_max = SUITESPARSE_OPENMP_MAX_THREADS ; } work = MAX (work, 1) ; chunk = MAX (chunk, 1) ; int64_t nthreads = (int64_t) floor (work / chunk) ; nthreads = MIN (nthreads, nthreads_max) ; nthreads = MAX (nthreads, 1) ; return ((int) nthreads) ; #else return (1) ; #endif } //============================================================================== //==== debugging definitions =================================================== //============================================================================== #if 0 #if 0 #define GOTCHA ; #else #define GOTCHA \ { \ printf ("Gotcha! %d:%s\n", __LINE__, __FILE__) ; \ fflush (stdout) ; \ abort ( ) ; \ } #endif #endif #ifndef NDEBUG #include // The cholmod_dump routines are in the Check module. No CHOLMOD routine // calls the cholmod_check_* or cholmod_print_* routines in the Check module, // since they use Common workspace that may already be in use. Instead, they // use the cholmod_dump_* routines defined there, which allocate their own // workspace if they need it. #ifndef EXTERN #define EXTERN extern #endif // int32_t EXTERN int cholmod_dump ; EXTERN int cholmod_dump_malloc ; int64_t cholmod_dump_sparse (cholmod_sparse *, const char *, cholmod_common *) ; int cholmod_dump_factor (cholmod_factor *, const char *, cholmod_common *) ; int cholmod_dump_triplet (cholmod_triplet *, const char *, cholmod_common *) ; int cholmod_dump_dense (cholmod_dense *, const char *, cholmod_common *) ; int cholmod_dump_subset (int *, size_t, size_t, const char *, cholmod_common *) ; int cholmod_dump_perm (int *, size_t, size_t, const char *, cholmod_common *) ; int cholmod_dump_parent (int *, size_t, const char *, cholmod_common *) ; void cholmod_dump_init (const char *, cholmod_common *) ; int cholmod_dump_mem (const char *, int64_t, cholmod_common *) ; void cholmod_dump_real (const char *, void *, int, int64_t, int64_t, int, int, cholmod_common *) ; void cholmod_dump_super (int64_t, int *, int *, int *, int *, void *, int, int, cholmod_common *) ; int cholmod_dump_partition (int64_t, int *, int *, int *, int *, int64_t, cholmod_common *) ; int cholmod_dump_work(int, int, int64_t, int, cholmod_common *) ; // int64_t EXTERN int cholmod_l_dump ; EXTERN int cholmod_l_dump_malloc ; int64_t cholmod_l_dump_sparse (cholmod_sparse *, const char *, cholmod_common *) ; int cholmod_l_dump_factor (cholmod_factor *, const char *, cholmod_common *) ; int cholmod_l_dump_triplet (cholmod_triplet *, const char *, cholmod_common *); int cholmod_l_dump_dense (cholmod_dense *, const char *, cholmod_common *) ; int cholmod_l_dump_subset (int64_t *, size_t, size_t, const char *, cholmod_common *) ; int cholmod_l_dump_perm (int64_t *, size_t, size_t, const char *, cholmod_common *) ; int cholmod_l_dump_parent (int64_t *, size_t, const char *, cholmod_common *) ; void cholmod_l_dump_init (const char *, cholmod_common *) ; int cholmod_l_dump_mem (const char *, int64_t, cholmod_common *) ; void cholmod_l_dump_real (const char *, void *, int, int64_t, int64_t, int, int, cholmod_common *) ; void cholmod_l_dump_super (int64_t, int64_t *, int64_t *, int64_t *, int64_t *, void *, int, int, cholmod_common *) ; int cholmod_l_dump_partition (int64_t, int64_t *, int64_t *, int64_t *, int64_t *, int64_t, cholmod_common *) ; int cholmod_l_dump_work(int, int, int64_t, int, cholmod_common *) ; #define DEBUG_INIT(s,Common) { CHOLMOD(dump_init)(s, Common) ; } #ifdef MATLAB_MEX_FILE #define ASSERT(expression) (mxAssert ((expression), "")) #else #define ASSERT(expression) (assert (expression)) #endif #define PRK(k,params) \ { \ if (CHOLMOD(dump) >= (k)) \ { \ int (*printf_func) (const char *, ...) ; \ printf_func = SuiteSparse_config_printf_func_get ( ) ; \ if (printf_func != NULL) \ { \ (void) (printf_func) params ; \ } \ } \ } #define PRINT0(params) PRK (0, params) #define PRINT1(params) PRK (1, params) #define PRINT2(params) PRK (2, params) #define PRINT3(params) PRK (3, params) void CM_memtable_dump (void) ; int CM_memtable_n (void) ; void CM_memtable_clear (void) ; void CM_memtable_add (void *p, size_t size) ; size_t CM_memtable_size (void *p) ; bool CM_memtable_find (void *p) ; void CM_memtable_remove (void *p) ; #define PRINTM(params) \ { \ if (CHOLMOD(dump_malloc) > 0) \ { \ printf params ; \ } \ } #define DEBUG(statement) statement static bool check_flag (cholmod_common *Common) { int64_t mark = Common->mark ; size_t n = Common->nrow ; if (Common->itype == CHOLMOD_LONG) { int64_t *Flag = Common->Flag ; for (int64_t i = 0 ; i < n ; i++) { if (Flag [i] >= mark) return (false) ; } } else { ASSERT (mark <= INT32_MAX) ; int32_t *Flag = Common->Flag ; for (int32_t i = 0 ; i < n ; i++) { if (Flag [i] >= mark) return (false) ; } } return (true) ; } #else // Debugging disabled (the normal case) #define PRK(k,params) #define DEBUG_INIT(s,Common) #define PRINT0(params) #define PRINT1(params) #define PRINT2(params) #define PRINT3(params) #define PRINTM(params) #define ASSERT(expression) #define DEBUG(statement) #endif #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Include/cholmod.h����������������������������������������������������0000644�0001751�0000144�00000520357�14561103552�021056� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Include/cholmod.h: include file for CHOLMOD //------------------------------------------------------------------------------ // CHOLMOD/Include/cholmod.h. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // Each Module of CHOLMOD has its own license, and a shared cholmod.h file. // CHOLMOD/Check: SPDX-License-Identifier: LGPL-2.1+ // CHOLMOD/Cholesky: SPDX-License-Identifier: LGPL-2.1+ // CHOLMOD/Utility: SPDX-License-Identifier: LGPL-2.1+ // CHOLMOD/Partition: SPDX-License-Identifier: LGPL-2.1+ // CHOLMOD/Demo: SPDX-License-Identifier: GPL-2.0+ // CHOLMOD/GPU: SPDX-License-Identifier: GPL-2.0+ // CHOLMOD/MATLAB: SPDX-License-Identifier: GPL-2.0+ // CHOLMOD/MatrixOps: SPDX-License-Identifier: GPL-2.0+ // CHOLMOD/Modify: SPDX-License-Identifier: GPL-2.0+ // CHOLMOD/Supernodal: SPDX-License-Identifier: GPL-2.0+ // CHOLMOD/Tcov: SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // CHOLMOD consists of a set of Modules, each with their own Copyright and // license: either LGPL-2.1+ or GPL-2.0+. This cholmod.h file includes // definitions of the CHOLMOD API for all Modules, and this cholmod.h file // itself is provided to you with a permissive license (Apache-2.0). You are // permitted to provide the hooks for an optional interface to CHOLMOD in a // non-GPL/non-LGPL code, without requiring you to agree to the GPL/LGPL // license of the Modules, as long as you don't use the *.c files in the // relevant Modules. The Modules themselves can only be functional if their // GPL or LGPL licenses are used, or if you obtain a different license from the // respective copyright holders. // // For the files in CHOLMOD/Include: // CHOLMOD/Include/cholmod.h SPDX-License-Identifier: Apache-2.0 // CHOLMOD/Include/cholmod_internal.h SPDX-License-Identifier: Apache-2.0 // CHOLMOD/Include/cholmod_template.h SPDX-License-Identifier: Apache-2.0 // CHOLMOD/Include/cholmod_types.h SPDX-License-Identifier: Apache-2.0 // // The Modify Module is co-authored by William W. Hager. // // Acknowledgements: this work was supported in part by the National Science // Foundation (NFS CCR-0203270 and DMS-9803599), and a grant from Sandia // National Laboratories (Dept. of Energy) which supported the development of // CHOLMOD's Partition Module. // ----------------------------------------------------------------------------- #ifndef CHOLMOD_H #define CHOLMOD_H //------------------------------------------------------------------------------ // CHOLMOD conventions //------------------------------------------------------------------------------ // Each routine in CHOLMOD follows the following conventions: // // Naming convention: // ------------------ // // All routine names, data types, and CHOLMOD library files use the cholmod_ // prefix. All macros and other #define's use the CHOLMOD prefix. // // Return value: // ------------- // // Most CHOLMOD routines return an int (TRUE (1) if successful, or FALSE // (0) otherwise. An int32_t, int64_t, double, or float return value // is >= 0 if successful, or -1 otherwise. A size_t return value // is > 0 if successful, or 0 otherwise. // // If a routine returns a pointer, it is a pointer to a newly allocated // object or NULL if a failure occured, with one exception. cholmod_free // always returns NULL. // // "Common" parameter: // ------------------ // // The last parameter in all CHOLMOD routines is a pointer to the CHOLMOD // "Common" object. This contains control parameters, statistics, and // workspace used between calls to CHOLMOD. It is always an input/output // parameter. // // Input, Output, and Input/Output parameters: // ------------------------------------------- // // Input parameters are listed first. They are not modified by CHOLMOD. // // Input/output are listed next. They must be defined on input, and // are modified on output. // // Output parameters are listed next. If they are pointers, they must // point to allocated space on input, but their contents are not defined // on input. // // Workspace parameters appear next. They are used in only two routines // in the Supernodal module. // // The cholmod_common *Common parameter always appears as the last // parameter. It is always an input/output parameter. //------------------------------------------------------------------------------ // CHOLMOD matrix formats //------------------------------------------------------------------------------ // A CHOLMOD sparse, dense, or triplet matrix A, or a sparse factorization L // can hold numeric values of 8 different types, according to its A->xtype and // A->dtype parameters (or L->xtype and L->dtype for a sparse factor object). // These values are held in the A->x array, and also A->z for "zomplex" // matrices. // // A->xtype: the matrix is real, complex, "zomplex", or pattern-only. // // (0): CHOLMOD_PATTERN: A->x and A->z are NULL. The matrix has no // numerical values. Only the pattern is stored. // // (1): CHOLMOD_REAL: The matrix is real, and the values are held in // A->x, whose size (in terms of double or float // values) is given by A->nzmax. The kth value in // the matrix is held in A->x [k]. // // (2): CHOLMOD_COMPLEX: The matrix is complex, with interleaved real and // imaginary parts. The kth value in the matrix // is held in A->x [2*k] and A->x [2*k+1], where // A->x can hold up to 2*A->nzmax values. // // (3): CHOLMOD_ZOMPLEX: The matrix is complex, with separate array for // the real and imaginary parts. The kth value in // the matrix is held in A->x [k] and A->z [k], // where A->x and A->z can hold up to A->nzmax // values each. // A->xtype values: #define CHOLMOD_PATTERN 0 #define CHOLMOD_REAL 1 #define CHOLMOD_COMPLEX 2 #define CHOLMOD_ZOMPLEX 3 // A->dtype: this parameter determines the type of values in A->x (and A->z // if zomplex). // // (0) CHOLMOD_DOUBLE: A->x (and A->z for zomplex matrices) is double. // If A is real, A->x has a size of A->nzmax * // sizeof (double). If A is complex, A->x has // size A->nzmax * 2 * sizeof (double). If // zomplex, both A->x and A->z have size A->nzmax // * sizeof (double). // // (4) CHOLMOD_SINGLE: A->x (and A->z for zomplex matrices) is float. // If A is real, A->x has a size of A->nzmax * // sizeof (float). If A is complex, A->x has size // A->nzmax * 2 * sizeof (float). If zomplex, // both A->x and A->z have size A->nzmax * sizeof // (float). This feature is new to CHOLMOD v5. // // A->dtype values: #define CHOLMOD_DOUBLE 0 #define CHOLMOD_SINGLE 4 // Unless stated otherwise, the xtype and dtypes of all inputs to a method must // be the same. // // Many methods accept an xdtype parameter, which is simply xtype + dtype, // combining the two parameters into a single number handling all 8 cases: // // (0) CHOLMOD_DOUBLE + CHOLMOD_PATTERN a pattern-only matrix // (1) CHOLMOD_DOUBLE + CHOLMOD_REAL a double real matrix // (2) CHOLMOD_DOUBLE + CHOLMOD_COMPLEX a double complex matrix // (3) CHOLMOD_DOUBLE + CHOLMOD_ZOMPLEX a double zomplex matrix // (4) CHOLMOD_SINGLE + CHOLMOD_PATTERN a pattern-only matrix // (5) CHOLMOD_SINGLE + CHOLMOD_REAL a float real matrix // (6) CHOLMOD_SINGLE + CHOLMOD_COMPLEX a float complex matrix // (7) CHOLMOD_SINGLE + CHOLMOD_ZOMPLEX a float zomplex matrix // // This approach was selected for backward compatibility with CHOLMOD v4 and // earlier, where only the first four values were supported, and where the // parameter was called "xtype" instead of "xdtype". Several function names // reflect the older parameter name (cholmod_*_xtype), but they have not been // renamed "_xdtype", for backward compatibility. // // A CHOLMOD sparse or triplet matrix A can held in three symmetry formats // according to its A->stype parameter. Dense matrices do not have this // parameter and are always treated as unsymmetric. A sparse factor object L // is always held in lower triangular form, with no entries ever held in the // strictly upper triangular part. // // 0: the matrix is unsymmetric with both lower and upper parts stored. // // <0: the matrix is symmetric, with just the lower triangular part and // diagonal stored. Any entries in the upper part are ignored. // // >0: the matrix is symmetric, with just the upper triangular part stored // and diagonal. Any entries in the upper part are ignored. // // If a sparse or triplet matrix A is complex or zomplex, most methods treat // the matrix as Hermitian, where A(i,j) is the complex conjugate of A(j,i), // when i is not equal to j. Some methods can also interpret the matrix as // complex symmetric, where A(i,j) == A(j,i) when i != j. This is not // determined by the matrix itself, but by a "mode" parameter of the function. // This mode parameter also determines if the values of any matrix are to be // ignored entirely, in which case only the pattern is operated on. Any output // matrix will have an xtype of CHOLMOD_PATTERN. // // The valid mode values are given below, except that many methods do not // handle the negative cases. Values below the range accepted by the method // are treated as its lowest accepted value, and values above the range // accepted by the method are treated as its highest accepted value. // // mode = 2: the numerical values of a real, complex, or zomplex matrix are // handled. If the matrix is complex or zomplex, an entry A(i,j) // that not stored (or in the ignored part) is treated as the // complex conjugate of A (j,i). Use this mode to treat a // complex or zomplex matrix as Hermitian. // // mode = 1: the numerical values of a real, complex, or zomplex matrix are // handled. If the matrix is complex or zomplex, an entry A(i,j) // that not stored (or in the ignored part) is treated as equal A // (j,i). Use this mode to treat a complex or zomplex matrix as // complex symmetric. // // mode = 0: the numerical values are ignored. Any output matrix will have // an xtype of CHOLMOD_PATTERN. This mode allows inputs to have // different dtypes. // // mode = -1: the same as mode = 0, except that the diagonal entries are // ignored, and do not appear in any output matrix. // // mode = -2: the same as mode = -1, except that the output matrix is given an // additional slack space so that it can hold about 50% more // entries. This mode is documented here but it is primarily // meant for internal use, for CHOLMOD's interface to the AMD, // CAMD, COLAMD, and CCOLAMD ordering methods. // // The integer arrays in all objects are either int32 or int64, as determined // by A->type. This integer type must be identical for all inputs, and must // also match both the function name (cholmod_method for int32, or // cholmod_l_method for int64) and the Common->itype as defined when CHOLMOD // was initialized (via cholmod_start for int32, or cholmod_l_start for int64). // itype values: #define CHOLMOD_INT 0 /* int32, for cholmod_* methods (no _l_) */ #define CHOLMOD_LONG 2 /* int64, for cholmod_l_* methods */ //------------------------------------------------------------------------------ // version control //------------------------------------------------------------------------------ #define CHOLMOD_DATE "Jan 20, 2024" #define CHOLMOD_MAIN_VERSION 5 #define CHOLMOD_SUB_VERSION 2 #define CHOLMOD_SUBSUB_VERSION 0 #define CHOLMOD_VER_CODE(main,sub) SUITESPARSE_VER_CODE(main,sub) #define CHOLMOD_VERSION CHOLMOD_VER_CODE(5,2) #define CHOLMOD_HAS_VERSION_FUNCTION #ifdef __cplusplus extern "C" { #endif int cholmod_version // returns CHOLMOD_VERSION, defined above ( // if version is not NULL, then cholmod_version returns its contents as: // version [0] = CHOLMOD_MAIN_VERSION // version [1] = CHOLMOD_SUB_VERSION // version [2] = CHOLMOD_SUBSUB_VERSION int version [3] ) ; int cholmod_l_version (int version [3]) ; #ifdef __cplusplus } #endif //------------------------------------------------------------------------------ // Large file support //------------------------------------------------------------------------------ // CHOLMOD assumes large file support. If problems occur, compile with // -DNLARGEFILE // Definitions required for large file I/O, which must come before any other // #includes. These are not used if -DNLARGEFILE is defined at compile time. // Large file support may not be portable across all platforms and compilers; // if you encounter an error here, compile your code with -DNLARGEFILE. In // particular, you must use -DNLARGEFILE for MATLAB 6.5 or earlier (which does // not have the io64.h include file). // skip all of this if NLARGEFILE is defined at the compiler command line #ifndef NLARGEFILE #if defined(MATLAB_MEX_FILE) || defined(MATHWORKS) // CHOLMOD compiled as a MATLAB mexFunction, or for use in MATLAB #include "io64.h" #else // CHOLMOD is being compiled in a stand-alone library #undef _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE #undef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 #endif #endif //------------------------------------------------------------------------------ // SuiteSparse_config: definitions for all SuiteSparse packages //------------------------------------------------------------------------------ #include "SuiteSparse_config.h" #define CHOLMOD__VERSION SUITESPARSE__VERCODE(5,2,0) #if !defined (SUITESPARSE__VERSION) || \ (SUITESPARSE__VERSION < SUITESPARSE__VERCODE(7,6,0)) #error "CHOLMOD 5.2.0 requires SuiteSparse_config 7.6.0 or later" #endif //------------------------------------------------------------------------------ // CHOLMOD configuration //------------------------------------------------------------------------------ // You do not have to edit any CHOLMOD files to compile and install CHOLMOD. // However, if you do not use all of CHOLMOD's modules, you need to compile // with the appropriate flag, or edit this file to add the appropriate #define. // // Compiler flags for CHOLMOD // // -DNCHECK do not include the Check module. // -DNCHOLESKY do not include the Cholesky module. // -DNPARTITION do not include the Partition module. // -DNCAMD do not include the interfaces to CAMD, // CCOLAMD, CSYMAND in Partition module. // -DNMATRIXOPS do not include the MatrixOps module. // -DNMODIFY do not include the Modify module. // -DNSUPERNODAL do not include the Supernodal module. // // -DNPRINT do not print anything // // The Utility Module is always included in the CHOLMOD library. // Use the compiler flag, or uncomment the definition(s), if you want to use // one or more non-default installation options: // #define NCHECK // #define NCHOLESKY // #define NCAMD // #define NPARTITION // #define NMATRIXOPS // #define NMODIFY // #define NSUPERNODAL // #define NPRINT // #define NGPL // The NGPL option disables the MatrixOps, Modify, and Supernodal modules. The // existence of this #define here, and its use in these 3 modules, does not // affect the license itself; see CHOLMOD/Doc/License.txt for your actual // license. #ifdef NGPL #undef NMATRIXOPS #define NMATRIXOPS #undef NMODIFY #define NMODIFY #undef NSUPERNODAL #define NSUPERNODAL #endif //============================================================================== // CHOLMOD:Utility Module //============================================================================== // the CHOLMOD:Utility Module is always required #if 1 //------------------------------------------------------------------------------ // CUDA BLAS //------------------------------------------------------------------------------ // Define buffering parameters for GPU processing #ifndef SUITESPARSE_GPU_EXTERN_ON #ifdef CHOLMOD_HAS_CUDA #include #endif #endif #define CHOLMOD_DEVICE_SUPERNODE_BUFFERS 6 #define CHOLMOD_HOST_SUPERNODE_BUFFERS 8 #define CHOLMOD_DEVICE_STREAMS 2 //------------------------------------------------------------------------------ // CHOLMOD objects //------------------------------------------------------------------------------ // CHOLMOD object enums #define CHOLMOD_COMMON 0 /* parameters, statistics, and workspace */ #define CHOLMOD_SPARSE 1 /* a sparse matrix in CSC form (and variants) */ #define CHOLMOD_FACTOR 2 /* a sparse factorization */ #define CHOLMOD_DENSE 3 /* a dense matrix in column-oriented form */ #define CHOLMOD_TRIPLET 4 /* a sparse matrix in triplet form */ //------------------------------------------------------------------------------ // CHOLMOD Common object //------------------------------------------------------------------------------ #ifdef __cplusplus extern "C" { #endif typedef struct cholmod_common_struct { //-------------------------------------------------------------------------- // primary parameters for factorization and update/downdate //-------------------------------------------------------------------------- double dbound ; // Bounds the diagonal entries of D for LDL' // factorization and update/downdate/rowadd. Entries outside this // bound are replaced with dbound. Default: 0. dbound is used for // double precision factorization only. See sbound for single // precision factorization. double grow0 ; // default: 1.2 double grow1 ; // default: 1.2 size_t grow2 ; // default: 5 // Initial space for simplicial factorization is max(grow0,1) times the // required space. If space is exhausted, L is grown by max(grow0,1.2) // times the required space. grow1 and grow2 control how each column // of L can grow in an update/downdate; if space runs out, then // grow1*(required space) + grow2 is allocated. size_t maxrank ; // maximum rank for update/downdate. Valid values are // 2, 4, and 8. Default is 8. If a larger update/downdate is done, it // is done in steps of maxrank. double supernodal_switch ; // default: 40 int supernodal ; // default: CHOLMOD_AUTO. // Controls supernodal vs simplicial factorization. If // Common->supernodal is CHOLMOD_SIMPLICIAL, a simplicial factorization // is always done; if CHOLMOD_SUPERNODAL, a supernodal factorization is // always done. If CHOLMOD_AUTO, then a simplicial factorization is // down if flops/nnz(L) < Common->supernodal_switch. #define CHOLMOD_SIMPLICIAL 0 /* always use simplicial method */ #define CHOLMOD_AUTO 1 /* auto select simplicial vs supernodal */ #define CHOLMOD_SUPERNODAL 2 /* always use supernoda method */ int final_asis ; // if true, other final_* parameters are ignored, // except for final_pack and the factors are left as-is when done. // Default: true. int final_super ; // if true, leave factor in supernodal form. // if false, convert to simplicial. Default: true. int final_ll ; // if true, simplicial factors are converted to LL', // otherwise left as LDL. Default: false. int final_pack ; // if true, the factorize are allocated with exactly // the space required. Set this to false if you expect future // updates/downdates (giving a little extra space for future growth), // Default: true. int final_monotonic ; // if true, columns are sorted when done, by // ascending row index. Default: true. int final_resymbol ; // if true, a supernodal factorization converted // to simplicial is reanalyzed, to remove zeros added for relaxed // amalgamation. Default: false. double zrelax [3] ; size_t nrelax [3] ; // The zrelax and nrelax parameters control relaxed supernodal // amalgamation, If ns is the # of columns in two adjacent supernodes, // and z is the fraction of zeros in the two supernodes if merged, then // the two supernodes are merged if any of the 5 following condition // are true: // // no new zero entries added if the two supernodes are merged // (ns <= nrelax [0]) // (ns <= nrelax [1] && z < zrelax [0]) // (ns <= nrelax [2] && z < zrelax [1]) // (z < zrelax [2]) // // With the defaults, the rules become: // // no new zero entries added if the two supernodes are merged // (ns <= 4) // (ns <= 16 && z < 0.8) // (ns <= 48 && z < 0.1) // (z < 0.05) int prefer_zomplex ; // if true, and a complex system is solved, // X is returned as zomplex (with two arrays, one for the real part // and one for the imaginary part). If false, then X is returned as // a single array with interleaved real and imaginary parts. // Default: false. int prefer_upper ; // if true, then a preference is given for holding // a symmetric matrix by just its upper triangular form. This gives // the best performance by the CHOLMOD analysis and factorization // methods. Only used by cholmod_read. Default: true. int quick_return_if_not_posdef ; // if true, a supernodal factorization // returns immediately if it finds the matrix is not positive definite. // If false, the failed supernode is refactorized, up to but not // including the failed column (required by MATLAB). int prefer_binary ; // if true, cholmod_read_triplet converts a symmetric // pattern-only matrix to a real matrix with all values set to 1. // if false, diagonal entries A(k,k) are set to one plus the # of // entries in row/column k, and off-diagonals are set to -1. // Default: false. //-------------------------------------------------------------------------- // printing and error handling options //-------------------------------------------------------------------------- int print ; // print level. Default is 3. int precise ; // if true, print 16 digits, otherwise 5. Default: false. int try_catch ; // if true, ignore errors (CHOLMOD is assumed to be inside // a try/catch block. No error messages are printed and the // error_handler function is not called. Default: false. void (*error_handler) (int status, const char *file, int line, const char *message) ; // User error handling routine; default is NULL. // This function is called if an error occurs, with parameters: // status: the Common->status result. // file: filename where the error occurred. // line: line number where the error occurred. // message: a string that describes the error. //-------------------------------------------------------------------------- // ordering options //-------------------------------------------------------------------------- // CHOLMOD can try many ordering options and then pick the best result it // finds. The default is to use one or two orderings: the user's // permutation (if given), and AMD. // Common->nmethods is the number of methods to try. If the // Common->method array is left unmodified, the methods are: // (0) given (skipped if no user permutation) // (1) amd // (2) metis // (3) nesdis with defaults (CHOLMOD's nested dissection, based on METIS) // (4) natural // (5) nesdis: stop at subgraphs of 20000 nodes // (6) nesdis: stop at subgraphs of 4 nodes, do not use CAMD // (7) nesdis: no pruning on of dense rows/cols // (8) colamd // To use all 9 of the above methods, set Common->nmethods to 9. The // analysis will take a long time, but that might be worth it if the // ordering will be reused many many times. // Common->nmethods and Common->methods can be revised to use a different // set of orderings. For example, to use just a single method // (AMD with a weighted postordering): // // Common->nmethods = 1 ; // Common->method [0].ordering = CHOLMOD_AMD ; // Common->postorder = TRUE ; // // int nmethods ; // Number of methods to try, default is 0. // The value of 0 is a special case, and tells CHOLMOD to use the user // permutation (if not NULL) and then AMD. Next, if fl is lnz are the // flop counts and number of nonzeros in L as found by AMD, then the // this ordering is used if fl/lnz < 500 or lnz/anz < 5, where anz is // the number of entries in A. If this condition fails, METIS is tried // as well. // // Otherwise, if Common->nmethods > 0, then the methods defined by // Common->method [0 ... Common->nmethods-1] are used. int current ; // The current method being tried in the analysis. int selected ; // The selected method: Common->method [Common->selected] // The Common->method parameter is an array of structs that defines up // to 9 methods: struct cholmod_method_struct { //---------------------------------------------------------------------- // statistics from the ordering //---------------------------------------------------------------------- double lnz ; // number of nonzeros in L double fl ; // Cholesky flop count for this ordering (each // multiply and each add counted once (doesn't count complex // flops). //---------------------------------------------------------------------- // ordering parameters: //---------------------------------------------------------------------- double prune_dense ; // dense row/col control. Default: 10. // Rows/cols with more than max (prune_dense*sqrt(n),16) are // removed prior to orderingm and placed last. If negative, // only completely dense rows/cols are removed. Removing these // rows/cols with many entries can speed up the ordering, but // removing too many can reduce the ordering quality. // // For AMD, SYMAMD, and CSYMAMD, this is the only dense row/col // parameter. For COLAMD and CCOLAMD, this parameter controls // how dense columns are handled. double prune_dense2 ; // dense row control for COLAMD and CCOLAMD. // Default -1. When computing the Cholesky factorization of AA' // rows with more than max(prune_dense2*sqrt(n),16) entries // are removed prior to ordering. If negative, only completely // dense rows are removed. double nd_oksep ; // for CHOLMOD's nesdis method. Default 1. // A node separator with nsep nodes is discarded if // nsep >= nd_oksep*n. double other_1 [4] ; // unused, for future expansion size_t nd_small ; // for CHOLMOD's nesdis method. Default 200. // Subgraphs with fewer than nd_small nodes are not partitioned. double other_2 [4] ; // unused, for future expansion int aggressive ; // if true, AMD, COLAMD, SYMAMD, CCOLAMD, and // CSYMAMD perform aggresive absorption. Default: true int order_for_lu ; // Default: false. If the CHOLMOD analysis/ // ordering methods are used as an ordering method for an LU // factorization, then set this to true. For use in a Cholesky // factorization by CHOLMOD itself, never set this to true. int nd_compress ; // if true, then the graph and subgraphs are // compressed before partitioning them in CHOLMOD's nesdis // method. Default: true. int nd_camd ; // if 1, then CHOLMOD's nesdis is followed by // CAMD. If 2: followed by CSYMAMD. If nd_small is very small, // then use 0, which skips CAMD or CSYMAMD. Default: 1. int nd_components ; // CHOLMOD's nesdis can partition a graph and then // find that the subgraphs are unconnected. If true, each of these // components is partitioned separately. If false, the whole // subgraph is partitioned. Default: false. int ordering ; // ordering method to use: #define CHOLMOD_NATURAL 0 /* no preordering */ #define CHOLMOD_GIVEN 1 /* user-provided permutation */ #define CHOLMOD_AMD 2 /* AMD: approximate minimum degree */ #define CHOLMOD_METIS 3 /* METIS: mested dissection */ #define CHOLMOD_NESDIS 4 /* CHOLMOD's nested dissection */ #define CHOLMOD_COLAMD 5 /* AMD for A, COLAMD for AA' or A'A */ #define CHOLMOD_POSTORDERED 6 /* natural then postordered */ size_t other_3 [4] ; // unused, for future expansion } #define CHOLMOD_MAXMETHODS 9 /* max # of methods in Common->method */ method [CHOLMOD_MAXMETHODS + 1] ; int postorder ; // if true, CHOLMOD performs a weighted postordering // after its fill-reducing ordering, which improves supernodal // amalgamation. Has no effect on flop count or nnz(L). // Default: true. int default_nesdis ; // If false, then the default ordering strategy // when Common->nmethods is zero is to try the user's permutation // if given, then AMD, and then METIS if the AMD ordering results in // a lot of fill-in. If true, then nesdis is used instead of METIS. // Default: false. //-------------------------------------------------------------------------- // METIS workarounds //-------------------------------------------------------------------------- // These workarounds were put into place for METIS 4.0.1. They are safe // to use with METIS 5.1.0, but they might not longer be necessary. double metis_memory ; // default: 0. If METIS terminates your // program when it runs out of memory, try 2, or higher. double metis_dswitch ; // default: 0.66 size_t metis_nswitch ; // default: 3000 // If a matrix has n > metis_nswitch and a density (nnz(A)/n^2) > // metis_dswitch, then METIS is not used. //-------------------------------------------------------------------------- // workspace //-------------------------------------------------------------------------- // This workspace is kept in the CHOLMOD Common object. cholmod_start // sets these arrays to NULL, and cholmod_finish frees them. size_t nrow ; // Flag has size nrow, Head has size nrow+1 int64_t mark ; // Flag is cleared if Flag [0..nrow-1] < mark. size_t iworksize ; // size of Iwork, in Ints (int32 or int64). // This is at most 6*nrow + ncol. size_t xworkbytes ; // size of Xwork, in bytes. // NOTE: in CHOLMOD v4 and earlier, this variable was called xworksize, // and was in terms of # of doubles, not # of bytes. void *Flag ; // size nrow. If this is "cleared" then // Flag [i] < mark for all i = 0:nrow-1. Flag is kept cleared between // calls to CHOLMOD. void *Head ; // size nrow+1. If Head [i] = EMPTY (-1) then that // entry is "cleared". Head is kept cleared between calls to CHOLMOD. void *Xwork ; // a double or float array. It has size nrow for most // routines, or 2*nrow if complex matrices are being handled. // It has size 2*nrow for cholmod_rowadd/rowdel, and maxrank*nrow for // cholmod_updown, where maxrank is 2, 4, or 8. Xwork is kept all // zero between calls to CHOLMOD. void *Iwork ; // size iworksize integers (int32's or int64's). // Uninitialized integer workspace, of size at most 6*nrow+ncol. int itype ; // cholmod_start (for int32's) sets this to CHOLMOD_INT, // and cholmod_l_start sets this to CHOLMOD_LONG. It defines the // integer sizes for th Flag, Head, and Iwork arrays, and also // defines the integers for all objects created by CHOLMOD. // The itype of the Common object must match the function name // and all objects passed to it. int other_5 ; // unused: for future expansion int no_workspace_reallocate ; // an internal flag, usually false. // This is set true to disable any reallocation of the workspace // in the Common object. //-------------------------------------------------------------------------- // statistics //-------------------------------------------------------------------------- int status ; // status code (0: ok, negative: error, pos: warning) // Common->status for error handling: 0 is ok, negative is a fatal // error, and positive is a warning #define CHOLMOD_OK (0) #define CHOLMOD_NOT_INSTALLED (-1) /* module not installed */ #define CHOLMOD_OUT_OF_MEMORY (-2) /* malloc/calloc/realloc failed */ #define CHOLMOD_TOO_LARGE (-3) /* integer overflow */ #define CHOLMOD_INVALID (-4) /* input invalid */ #define CHOLMOD_GPU_PROBLEM (-5) /* CUDA error */ #define CHOLMOD_NOT_POSDEF (1) /* matrix not positive definite */ #define CHOLMOD_DSMALL (2) /* diagonal entry very small */ double fl ; // flop count from last analysis double lnz ; // nnz(L) from last analysis double anz ; // in last analysis: nnz(tril(A)) or nnz(triu(A)) if A // symmetric, or tril(A*A') if A is unsymmetric. double modfl ; // flop count from last update/downdate/rowadd/rowdel, // not included the flops to revise the solution to Lx=b, // if that was performed. size_t malloc_count ; // # of malloc'd objects not yet freed size_t memory_usage ; // peak memory usage in bytes size_t memory_inuse ; // current memory usage in bytes double nrealloc_col ; // # of column reallocations double nrealloc_factor ;// # of factor reallocations due to col. reallocs double ndbounds_hit ; // # of times diagonal modified by dbound double rowfacfl ; // flop count of cholmod_rowfac double aatfl ; // flop count to compute A(:,f)*A(:,f)' int called_nd ; // true if last analysis used nesdis or METIS. int blas_ok ; // true if no integer overflow has occured when trying to // call the BLAS. The typical BLAS library uses 32-bit integers for // its input parameters, even on a 64-bit platform. CHOLMOD uses int64 // in its cholmod_l_* methods, and these must be typecast to the BLAS // integer. If integer overflow occurs, this is set false. //-------------------------------------------------------------------------- // SuiteSparseQR control parameters and statistics //-------------------------------------------------------------------------- // SPQR uses the CHOLMOD Common object for its control and statistics. // These parameters are not used by CHOLMOD itself. // control parameters: double SPQR_grain ; // task size is >= max (total flops / grain) double SPQR_small ; // task size is >= small int SPQR_shrink ; // controls stack realloc method int SPQR_nthreads ; // number of TBB threads, 0 = auto // statistics: double SPQR_flopcount ; // flop count for SPQR double SPQR_analyze_time ; // analysis time in seconds for SPQR double SPQR_factorize_time ; // factorize time in seconds for SPQR double SPQR_solve_time ; // backsolve time in seconds double SPQR_flopcount_bound ; // upper bound on flop count double SPQR_tol_used ; // tolerance used double SPQR_norm_E_fro ; // Frobenius norm of dropped entries //-------------------------------------------------------------------------- // Revised for CHOLMOD v5.0 //-------------------------------------------------------------------------- // was size 10 in CHOLMOD v4.2; reduced to 8 in CHOLMOD v5: int64_t SPQR_istat [8] ; // other statistics //-------------------------------------------------------------------------- // Added for CHOLMOD v5.0 //-------------------------------------------------------------------------- // These terms have been added to the CHOLMOD Common struct for v5.0, and // on most systems they will total 16 bytes. The preceding term, // SPQR_istat, was reduced by 16 bytes, since those last 2 entries were // unused in CHOLMOD v4.2. As a result, the Common struct in v5.0 has the // same size as v4.0, and all entries would normally be in the same offset, // as well. This mitigates any changes between v4.0 and v5.0, and may make // it easier to upgrade from v4 to v5. double nsbounds_hit ; // # of times diagonal modified by sbound. // This ought to be int64_t, but ndbounds_hit was double in // v4 (see above), so nsbounds_hit is made the same type // for consistency. float sbound ; // Same as dbound, // but for single precision factorization. float other_6 ; // for future expansion //-------------------------------------------------------------------------- // GPU configuration and statistics //-------------------------------------------------------------------------- int useGPU ; // 1 if GPU is requested for CHOLMOD // 0 if GPU is not requested for CHOLMOD // -1 if the use of the GPU is in CHOLMOD controled by the // CHOLMOD_USE_GPU environment variable. size_t maxGpuMemBytes ; // GPU control for CHOLMOD double maxGpuMemFraction ; // GPU control for CHOLMOD // for SPQR: size_t gpuMemorySize ; // Amount of memory in bytes on the GPU double gpuKernelTime ; // Time taken by GPU kernels int64_t gpuFlops ; // Number of flops performed by the GPU int gpuNumKernelLaunches ; // Number of GPU kernel launches #ifdef CHOLMOD_HAS_CUDA // these three types are pointers defined by CUDA: #define CHOLMOD_CUBLAS_HANDLE cublasHandle_t #define CHOLMOD_CUDASTREAM cudaStream_t #define CHOLMOD_CUDAEVENT cudaEvent_t #else // they are (void *) if CUDA is not in use: #define CHOLMOD_CUBLAS_HANDLE void * #define CHOLMOD_CUDASTREAM void * #define CHOLMOD_CUDAEVENT void * #endif CHOLMOD_CUBLAS_HANDLE cublasHandle ; // a set of streams for general use CHOLMOD_CUDASTREAM gpuStream [CHOLMOD_HOST_SUPERNODE_BUFFERS] ; CHOLMOD_CUDAEVENT cublasEventPotrf [3] ; CHOLMOD_CUDAEVENT updateCKernelsComplete ; CHOLMOD_CUDAEVENT updateCBuffersFree [CHOLMOD_HOST_SUPERNODE_BUFFERS] ; void *dev_mempool ; // pointer to single allocation of device memory size_t dev_mempool_size ; void *host_pinned_mempool ; // pointer to single alloc of pinned mem size_t host_pinned_mempool_size ; size_t devBuffSize ; int ibuffer ; double syrkStart ; // time syrk started // run times of the different parts of CHOLMOD (GPU and CPU): double cholmod_cpu_gemm_time ; double cholmod_cpu_syrk_time ; double cholmod_cpu_trsm_time ; double cholmod_cpu_potrf_time ; double cholmod_gpu_gemm_time ; double cholmod_gpu_syrk_time ; double cholmod_gpu_trsm_time ; double cholmod_gpu_potrf_time ; double cholmod_assemble_time ; double cholmod_assemble_time2 ; // number of times the BLAS are called on the CPU and the GPU: size_t cholmod_cpu_gemm_calls ; size_t cholmod_cpu_syrk_calls ; size_t cholmod_cpu_trsm_calls ; size_t cholmod_cpu_potrf_calls ; size_t cholmod_gpu_gemm_calls ; size_t cholmod_gpu_syrk_calls ; size_t cholmod_gpu_trsm_calls ; size_t cholmod_gpu_potrf_calls ; double chunk ; // chunksize for computing # of OpenMP threads to use. // Given nwork work to do, # of threads is // max (1, min (floor (work / chunk), nthreads_max)) int nthreads_max ; // max # of OpenMP threads to use in CHOLMOD. // Defaults to SUITESPARSE_OPENMP_MAX_THREADS. #ifdef BLAS_DUMP FILE *blas_dump ; // only used if CHOLMOD is compiled with -DBLAS_DUMP #endif } cholmod_common ; // size_t BLAS statistcs in Common: #define CHOLMOD_CPU_GEMM_CALLS cholmod_cpu_gemm_calls #define CHOLMOD_CPU_SYRK_CALLS cholmod_cpu_syrk_calls #define CHOLMOD_CPU_TRSM_CALLS cholmod_cpu_trsm_calls #define CHOLMOD_CPU_POTRF_CALLS cholmod_cpu_potrf_calls #define CHOLMOD_GPU_GEMM_CALLS cholmod_gpu_gemm_calls #define CHOLMOD_GPU_SYRK_CALLS cholmod_gpu_syrk_calls #define CHOLMOD_GPU_TRSM_CALLS cholmod_gpu_trsm_calls #define CHOLMOD_GPU_POTRF_CALLS cholmod_gpu_potrf_calls // double BLAS statistics in Common: #define CHOLMOD_CPU_GEMM_TIME cholmod_cpu_gemm_time #define CHOLMOD_CPU_SYRK_TIME cholmod_cpu_syrk_time #define CHOLMOD_CPU_TRSM_TIME cholmod_cpu_trsm_time #define CHOLMOD_CPU_POTRF_TIME cholmod_cpu_potrf_time #define CHOLMOD_GPU_GEMM_TIME cholmod_gpu_gemm_time #define CHOLMOD_GPU_SYRK_TIME cholmod_gpu_syrk_time #define CHOLMOD_GPU_TRSM_TIME cholmod_gpu_trsm_time #define CHOLMOD_GPU_POTRF_TIME cholmod_gpu_potrf_time #define CHOLMOD_ASSEMBLE_TIME cholmod_assemble_time #define CHOLMOD_ASSEMBLE_TIME2 cholmod_assemble_time2 //------------------------------------------------------------------------------ // cholmod_start: first call to CHOLMOD //------------------------------------------------------------------------------ int cholmod_start (cholmod_common *Common) ; int cholmod_l_start (cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_finish: last call to CHOLMOD //------------------------------------------------------------------------------ int cholmod_finish (cholmod_common *Common) ; int cholmod_l_finish (cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_defaults: set default parameters //------------------------------------------------------------------------------ int cholmod_defaults (cholmod_common *Common) ; int cholmod_l_defaults (cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_maxrank: return valid maximum rank for update/downdate //------------------------------------------------------------------------------ size_t cholmod_maxrank // return validated Common->maxrank ( // input: size_t n, // # of rows of L and A cholmod_common *Common ) ; size_t cholmod_l_maxrank (size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_allocate_work: allocate workspace in Common //------------------------------------------------------------------------------ // This method always allocates Xwork as double, for backward compatibility // with CHOLMOD v4 and earlier. See cholmod_alloc_work for CHOLMOD v5. int cholmod_allocate_work ( // input: size_t nrow, // size of Common->Flag (nrow int32's) // and Common->Head (nrow+1 int32's) size_t iworksize, // size of Common->Iwork (# of int32's) size_t xworksize, // size of Common->Xwork (# of double's) cholmod_common *Common ) ; int cholmod_l_allocate_work (size_t, size_t, size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_alloc_work: allocate workspace in Common //------------------------------------------------------------------------------ // Added for CHOLMOD v5: allocates Xwork as either double or single. int cholmod_alloc_work ( // input: size_t nrow, // size of Common->Flag (nrow int32's) // and Common->Head (nrow+1 int32's) size_t iworksize, // size of Common->Iwork (# of int32's) size_t xworksize, // size of Common->Xwork (# of entries) int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE cholmod_common *Common ) ; int cholmod_l_alloc_work (size_t, size_t, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_free_work: free workspace in Common //------------------------------------------------------------------------------ int cholmod_free_work (cholmod_common *Common) ; int cholmod_l_free_work (cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_clear_flag: clear Flag workspace in Common //------------------------------------------------------------------------------ // This macro is deprecated; do not use it: #define CHOLMOD_CLEAR_FLAG(Common) \ { \ Common->mark++ ; \ if (Common->mark <= 0 || Common->mark >= INT32_MAX) \ { \ Common->mark = EMPTY ; \ CHOLMOD (clear_flag) (Common) ; \ } \ } int64_t cholmod_clear_flag (cholmod_common *Common) ; int64_t cholmod_l_clear_flag (cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_error: called when CHOLMOD encounters an error //------------------------------------------------------------------------------ int cholmod_error ( // input: int status, // Common->status const char *file, // source file where error occurred int line, // line number where error occurred const char *message, // error message to print cholmod_common *Common ) ; int cholmod_l_error (int, const char *, int, const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_dbound and cholmod_sbound: for internal use in CHOLMOD only //------------------------------------------------------------------------------ // These were once documented functions but no are no longer meant to be used // by the user application. They remain here for backward compatibility. double cholmod_dbound (double, cholmod_common *) ; double cholmod_l_dbound (double, cholmod_common *) ; float cholmod_sbound (float, cholmod_common *) ; float cholmod_l_sbound (float, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_hypot: compute sqrt (x*x + y*y) accurately //------------------------------------------------------------------------------ double cholmod_hypot (double x, double y) ; double cholmod_l_hypot (double, double) ; //------------------------------------------------------------------------------ // cholmod_divcomplex: complex division, c = a/b //------------------------------------------------------------------------------ int cholmod_divcomplex // return 1 if divide-by-zero, 0 if OK ( // input: double ar, double ai, // a (real, imaginary) double br, double bi, // b (real, imaginary) double *cr, double *ci // c (real, imaginary) ) ; int cholmod_l_divcomplex (double, double, double, double, double *, double *) ; //============================================================================== // cholmod_sparse: a sparse matrix in compressed-column (CSC) form //============================================================================== typedef struct cholmod_sparse_struct { size_t nrow ; // # of rows of the matrix size_t ncol ; // # of colums of the matrix size_t nzmax ; // max # of entries that can be held in the matrix // int32_t or int64_t arrays: void *p ; // A->p [0..ncol], column "pointers" of the CSC matrix void *i ; // A->i [0..nzmax-1], the row indices // for unpacked matrices only: void *nz ; // A->nz [0..ncol-1], is the # of nonzeros in each col. // This is NULL for a "packed" matrix (conventional CSC). // For a packed matrix, the jth column is held in A->i and A->x in // postions A->p [j] to A->p [j+1]-1, with no gaps between columns. // For an "unpacked" matrix, there can be gaps between columns, so // the jth columns appears in positions A-p [j] to // A->p [j] + A->nz [j] - 1. // double or float arrays: void *x ; // size nzmax or 2*nzmax, or NULL void *z ; // size nzmax, or NULL int stype ; // A->stype defines what parts of the matrix is held: // 0: the matrix is unsymmetric with both lower and upper parts stored. // >0: the matrix is square and symmetric, with just the upper // triangular part stored. // <0: the matrix is square and symmetric, with just the lower // triangular part stored. int itype ; // A->itype defines the integers used for A->p, A->i, and A->nz. // if CHOLMOD_INT, these arrays are all of type int32_t. // if CHOLMOD_LONG, these arrays are all of type int64_t. int xtype ; // pattern, real, complex, or zomplex int dtype ; // x and z are double or single int sorted ; // true if columns are sorted, false otherwise int packed ; // true if packed (A->nz ignored), false if unpacked } cholmod_sparse ; //------------------------------------------------------------------------------ // cholmod_allocate_sparse: allocate a sparse matrix //------------------------------------------------------------------------------ cholmod_sparse *cholmod_allocate_sparse ( // input: size_t nrow, // # of rows size_t ncol, // # of columns size_t nzmax, // max # of entries the matrix can hold int sorted, // true if columns are sorted int packed, // true if A is be packed (A->nz NULL), false if unpacked int stype, // the stype of the matrix (unsym, tril, or triu) int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_sparse *cholmod_l_allocate_sparse (size_t, size_t, size_t, int, int, int, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_free_sparse: free a sparse matrix //------------------------------------------------------------------------------ int cholmod_free_sparse ( // input/output: cholmod_sparse **A, // handle of sparse matrix to free cholmod_common *Common ) ; int cholmod_l_free_sparse (cholmod_sparse **, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_reallocate_sparse: change max # of entries in a sparse matrix //------------------------------------------------------------------------------ int cholmod_reallocate_sparse ( // input: size_t nznew, // new max # of nonzeros the sparse matrix can hold // input/output: cholmod_sparse *A, // sparse matrix to reallocate cholmod_common *Common ) ; int cholmod_l_reallocate_sparse (size_t, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_nnz: # of entries in a sparse matrix //------------------------------------------------------------------------------ int64_t cholmod_nnz // return # of entries in the sparse matrix ( // input: cholmod_sparse *A, // sparse matrix to query cholmod_common *Common ) ; int64_t cholmod_l_nnz (cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_speye: sparse identity matrix (possibly rectangular) //------------------------------------------------------------------------------ cholmod_sparse *cholmod_speye ( // input: size_t nrow, // # of rows size_t ncol, // # of columns int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_sparse *cholmod_l_speye (size_t, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_spzeros: sparse matrix with no entries //------------------------------------------------------------------------------ // Identical to cholmod_allocate_sparse, with packed = true, sorted = true, // and stype = 0. cholmod_sparse *cholmod_spzeros // return a sparse matrix with no entries ( // input: size_t nrow, // # of rows size_t ncol, // # of columns size_t nzmax, // max # of entries the matrix can hold int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_sparse *cholmod_l_spzeros (size_t, size_t, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_transpose: transpose a sparse matrix //------------------------------------------------------------------------------ cholmod_sparse *cholmod_transpose // return new sparse matrix C ( // input: cholmod_sparse *A, // input matrix int mode, // 2: numerical (conj) // 1: numerical (non-conj.) // 0: pattern (with diag) cholmod_common *Common ) ; cholmod_sparse *cholmod_l_transpose (cholmod_sparse *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_transpose_unsym: transpose an unsymmetric sparse matrix //------------------------------------------------------------------------------ // Compute C = A', A (:,f)', or A (p,f)', where A is unsymmetric and C is // already allocated. See cholmod_transpose for a routine with a simpler // interface. int cholmod_transpose_unsym ( // input: cholmod_sparse *A, // input matrix int mode, // 2: numerical (conj) // 1: numerical (non-conj.), // 0: pattern (with diag) int32_t *Perm, // permutation for C=A(p,f)', or NULL int32_t *fset, // a list of column indices in range 0:A->ncol-1 size_t fsize, // # of entries in fset // input/output: cholmod_sparse *C, // output matrix, must be allocated on input cholmod_common *Common ) ; int cholmod_l_transpose_unsym (cholmod_sparse *, int, int64_t *, int64_t *, size_t, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_transpose_sym: symmetric permuted transpose //------------------------------------------------------------------------------ // C = A' or C = A(p,p)' where A and C are both symmetric and C is already // allocated. See cholmod_transpose or cholmod_ptranspose for a routine with // a simpler interface. int cholmod_transpose_sym ( // input: cholmod_sparse *A, // input matrix int mode, // 2: numerical (conj) // 1: numerical (non-conj.), // 0: pattern (with diag) int32_t *Perm, // permutation for C=A(p,p)', or NULL // input/output: cholmod_sparse *C, // output matrix, must be allocated on input cholmod_common *Common ) ; int cholmod_l_transpose_sym (cholmod_sparse *, int, int64_t *, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_ptranspose: C = A', A(:,f)', A(p,p)', or A(p,f)' //------------------------------------------------------------------------------ cholmod_sparse *cholmod_ptranspose // return new sparse matrix C ( // input: cholmod_sparse *A, // input matrix int mode, // 2: numerical (conj) // 1: numerical (non-conj.) // 0: pattern (with diag) int32_t *Perm, // permutation for C=A(p,f)', or NULL int32_t *fset, // a list of column indices in range 0:A->ncol-1 size_t fsize, // # of entries in fset cholmod_common *Common ) ; cholmod_sparse *cholmod_l_ptranspose (cholmod_sparse *, int, int64_t *, int64_t *, size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_sort: sort the indices of a sparse matrix //------------------------------------------------------------------------------ int cholmod_sort ( // input/output: cholmod_sparse *A, // input/output matrix to sort cholmod_common *Common ) ; int cholmod_l_sort (cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_band_nnz: # of entries within a band of a sparse matrix //------------------------------------------------------------------------------ int64_t cholmod_band_nnz // return # of entries in a band (-1 if error) ( // input: cholmod_sparse *A, // matrix to examine int64_t k1, // count entries in k1:k2 diagonals int64_t k2, bool ignore_diag, // if true, exclude any diagonal entries cholmod_common *Common ) ; int64_t cholmod_l_band_nnz (cholmod_sparse *, int64_t, int64_t, bool, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_band: C = tril (triu (A,k1), k2) //------------------------------------------------------------------------------ cholmod_sparse *cholmod_band // return a new matrix C ( // input: cholmod_sparse *A, // input matrix int64_t k1, // count entries in k1:k2 diagonals int64_t k2, int mode, // >0: numerical, 0: pattern, <0: pattern (no diag) cholmod_common *Common ) ; cholmod_sparse *cholmod_l_band (cholmod_sparse *, int64_t, int64_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_band_inplace: A = tril (triu (A,k1), k2) //------------------------------------------------------------------------------ int cholmod_band_inplace ( // input: int64_t k1, // count entries in k1:k2 diagonals int64_t k2, int mode, // >0: numerical, 0: pattern, <0: pattern (no diag) // input/output: cholmod_sparse *A, // input/output matrix cholmod_common *Common ) ; int cholmod_l_band_inplace (int64_t, int64_t, int, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_aat: C = A*A' or A(:,f)*A(:,f)' //------------------------------------------------------------------------------ cholmod_sparse *cholmod_aat // return sparse matrix C ( // input: cholmod_sparse *A, // input matrix int32_t *fset, // a list of column indices in range 0:A->ncol-1 size_t fsize, // # of entries in fset int mode, // 2: numerical (conj) // 1: numerical (non-conj.), // 0: pattern (with diag) // -1: pattern (remove diag), // -2: pattern (remove diag; add ~50% extra space in C) cholmod_common *Common ) ; cholmod_sparse *cholmod_l_aat (cholmod_sparse *, int64_t *, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_copy_sparse: C = A, create an exact copy of a sparse matrix //------------------------------------------------------------------------------ // Creates an exact copy of a sparse matrix. For making a copy with a change // of stype and/or copying the pattern of a numerical matrix, see cholmod_copy. // For changing the xtype and/or dtype, see cholmod_sparse_xtype. cholmod_sparse *cholmod_copy_sparse // return new sparse matrix ( // input: cholmod_sparse *A, // sparse matrix to copy cholmod_common *Common ) ; cholmod_sparse *cholmod_l_copy_sparse (cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_copy: C = A, with possible change of stype //------------------------------------------------------------------------------ cholmod_sparse *cholmod_copy // return new sparse matrix ( // input: cholmod_sparse *A, // input matrix, not modified int stype, // stype of C int mode, // 2: numerical (conj) // 1: numerical (non-conj.) // 0: pattern (with diag) // -1: pattern (remove diag) // -2: pattern (remove diag; add ~50% extra space in C) cholmod_common *Common ) ; cholmod_sparse *cholmod_l_copy (cholmod_sparse *, int, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_add: C = alpha*A + beta*B //------------------------------------------------------------------------------ cholmod_sparse *cholmod_add // return C = alpha*A + beta*B ( // input: cholmod_sparse *A, // input matrix cholmod_sparse *B, // input matrix double alpha [2], // scale factor for A (two entires used if complex) double beta [2], // scale factor for A (two entires used if complex) int mode, // 2: numerical (conj) if A and/or B are symmetric, // 1: numerical (non-conj.) if A and/or B are symmetric. // 0: pattern int sorted, // ignored; C is now always returned as sorted cholmod_common *Common ) ; cholmod_sparse *cholmod_l_add (cholmod_sparse *, cholmod_sparse *, double [2], double [2], int, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_sparse_xtype: change the xtype and/or dtype of a sparse matrix //------------------------------------------------------------------------------ int cholmod_sparse_xtype ( // input: int to_xdtype, // requested xtype and dtype // input/output: cholmod_sparse *A, // sparse matrix to change cholmod_common *Common ) ; int cholmod_l_sparse_xtype (int, cholmod_sparse *, cholmod_common *) ; //============================================================================== // cholmod_factor: symbolic or numeric factorization (simplicial or supernodal) //============================================================================== typedef struct cholmod_factor_struct { size_t n ; // L is n-by-n size_t minor ; // If the factorization failed because of numerical issues // (the matrix being factorized is found to be singular or not positive // definte), then L->minor is the column at which it failed. L->minor // = n means the factorization was successful. //-------------------------------------------------------------------------- // symbolic ordering and analysis //-------------------------------------------------------------------------- void *Perm ; // int32/int64, size n, fill-reducing ordering void *ColCount ;// int32/int64, size n, # entries in each column of L void *IPerm ; // int32/int64, size n, created by cholmod_solve2; // containing the inverse of L->Perm //-------------------------------------------------------------------------- // simplicial factorization (not supernodal) //-------------------------------------------------------------------------- // The row indices of L(:,j) are held in L->i [L->p [j] ... L->p [j] + // L->nz [j] - 1]. The numeical values of L(:,j) are held in the same // positions in L->x (and L->z if L is zomplex). L->next and L->prev hold // a link list of columns of L, that tracks the order they appear in the // arrays L->i, L->x, and L->z. The head and tail of the list is n+1 and // n, respectively. size_t nzmax ; // # of entries that L->i, L->x, and L->z can hold void *p ; // int32/int64, size n+1, column pointers void *i ; // int32/int64, size nzmax, row indices void *x ; // float/double, size nzmax or 2*nzmax, numerical values void *z ; // float/double, size nzmax or empty, imaginary values void *nz ; // int32/int64, size ncol, # of entries in each column void *next ; // int32/int64, size n+2 void *prev ; // int32/int64, size n+2 //-------------------------------------------------------------------------- // supernodal factorization (not simplicial) //-------------------------------------------------------------------------- // L->x is shared with the simplicial structure above. L->z is not used // for the supernodal case since a supernodal factor cannot be zomplex. size_t nsuper ; // # of supernodes size_t ssize ; // # of integers in L->s size_t xsize ; // # of entries in L->x size_t maxcsize ; // size of largest update matrix size_t maxesize ; // max # of rows in supernodes, excl. triangular part // the following are int32/int64 and are size nsuper+1: void *super ; // first column in each supernode void *pi ; // index into L->s for integer part of a supernode void *px ; // index into L->x for numeric part of a supernode // int32/int64, of size ssize: void *s ; // integer part of supernodes //-------------------------------------------------------------------------- // type of the factorization //-------------------------------------------------------------------------- int ordering ; // the fill-reducing method used (CHOLMOD_NATURAL, // CHOLMOD_GIVEN, CHOLMOD_AMD, CHOLMOD_METIS, CHOLMOD_NESDIS, // CHOLMOD_COLAMD, or CHOLMOD_POSTORDERED). int is_ll ; // true: an LL' factorization; false: LDL' instead int is_super ; // true: supernodal; false: simplicial int is_monotonic ; // true: columns appear in order 0 to n-1 in L, for a // simplicial factorization only // Two boolean values above (is_ll, is_super) and L->xtype (pattern or // otherwise, define eight types of factorizations, but only 6 are used: // If L->xtype is CHOLMOD_PATTERN, then L is a symbolic factor: // // simplicial LDL': (is_ll false, is_super false). Nothing is present // except Perm and ColCount. // // simplicial LL': (is_ll true, is_super false). Identical to the // simplicial LDL', except for the is_ll flag. // // supernodal LL': (is_ll true, is_super true). A supernodal symbolic // factorization. The simplicial symbolic information is present // (Perm and ColCount), as is all of the supernodal factorization // except for the numerical values (x and z). // // If L->xtype is CHOLMOD_REAL, CHOLMOD_COMPLEX, or CHOLMOD_ZOMPLEX, // then L is a numeric factor: // // simplicial LDL': (is_ll false, is_super false). Stored in compressed // column form, using the simplicial components above (nzmax, p, i, // x, z, nz, next, and prev). The unit diagonal of L is not stored, // and D is stored in its place. There are no supernodes. // // simplicial LL': (is_ll true, is_super false). Uses the same storage // scheme as the simplicial LDL', except that D does not appear. // The first entry of each column of L is the diagonal entry of // that column of L. // // supernodal LL': (is_ll true, is_super true). A supernodal factor, // using the supernodal components described above (nsuper, ssize, // xsize, maxcsize, maxesize, super, pi, px, s, x, and z). // A supernodal factorization is never zomplex. int itype ; // integer type for L->Perm, L->ColCount, L->p, L->i, L->nz, // L->next, L->prev, L->super, L->pi, L->px, and L->s. // These are all int32 if L->itype is CHOLMOD_INT, or all int64 // if L->itype is CHOLMOD_LONG. int xtype ; // pattern, real, complex, or zomplex int dtype ; // x and z are double or single int useGPU; // if true, symbolic factorization allows for use of the GPU } cholmod_factor ; //------------------------------------------------------------------------------ // cholmod_allocate_factor: allocate a numerical factor //------------------------------------------------------------------------------ // L is returned as double precision cholmod_factor *cholmod_allocate_factor // return the new factor L ( // input: size_t n, // L is factorization of an n-by-n matrix cholmod_common *Common ) ; cholmod_factor *cholmod_l_allocate_factor (size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_alloc_factor: allocate a numerical factor (double or single) //------------------------------------------------------------------------------ cholmod_factor *cholmod_alloc_factor // return the new factor L ( // input: size_t n, // L is factorization of an n-by-n matrix int dtype, // CHOLMOD_SINGLE or CHOLMOD_DOUBLE cholmod_common *Common ) ; cholmod_factor *cholmod_l_alloc_factor (size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_free_factor: free a factor //------------------------------------------------------------------------------ int cholmod_free_factor ( // input/output: cholmod_factor **L, // handle of sparse factorization to free cholmod_common *Common ) ; int cholmod_l_free_factor (cholmod_factor **, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_reallocate_factor: change the # entries in a factor //------------------------------------------------------------------------------ int cholmod_reallocate_factor ( // input: size_t nznew, // new max # of nonzeros the factor matrix can hold // input/output: cholmod_factor *L, // factor to reallocate cholmod_common *Common ) ; int cholmod_l_reallocate_factor (size_t, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_change_factor: change the type of factor (e.g., LDL' to LL') //------------------------------------------------------------------------------ int cholmod_change_factor ( // input: int to_xtype, // CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX; // L->dtype remains unchanged. int to_ll, // if true: convert to LL'; else to LDL' int to_super, // if true: convert to supernodal; else to simplicial int to_packed, // if true: pack simplicial columns; else: do not pack int to_monotonic, // if true, put simplicial columns in order // input/output: cholmod_factor *L, // factor to change. cholmod_common *Common ) ; int cholmod_l_change_factor (int, int, int, int, int, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_pack_factor: pack a factor //------------------------------------------------------------------------------ // Removes all slack space from all columns in a factor. int cholmod_pack_factor ( // input/output: cholmod_factor *L, // factor to pack cholmod_common *Common ) ; int cholmod_l_pack_factor (cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_reallocate_column: reallocate a single column L(:,j) //------------------------------------------------------------------------------ int cholmod_reallocate_column ( // input: size_t j, // reallocate L(:,j) size_t need, // space in L(:,j) for this # of entries // input/output: cholmod_factor *L, // L factor modified, L(:,j) resized cholmod_common *Common ) ; int cholmod_l_reallocate_column (size_t, size_t, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_factor_to_sparse: create a sparse matrix copy of a factor //------------------------------------------------------------------------------ cholmod_sparse *cholmod_factor_to_sparse // return a new sparse matrix ( // input/output: cholmod_factor *L, // input: factor to convert; output: L is converted // to a simplicial symbolic factor cholmod_common *Common ) ; cholmod_sparse *cholmod_l_factor_to_sparse (cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_copy_factor: create a copy of a factor //------------------------------------------------------------------------------ cholmod_factor *cholmod_copy_factor // return a copy of the factor ( // input: cholmod_factor *L, // factor to copy (not modified) cholmod_common *Common ) ; cholmod_factor *cholmod_l_copy_factor (cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_factor_xtype: change the xtype and/or dtype of a factor //------------------------------------------------------------------------------ int cholmod_factor_xtype ( // input: int to_xdtype, // requested xtype and dtype // input/output: cholmod_factor *L, // factor to change cholmod_common *Common ) ; int cholmod_l_factor_xtype (int, cholmod_factor *, cholmod_common *) ; //============================================================================== // cholmod_dense: a dense matrix, held by column //============================================================================== typedef struct cholmod_dense_struct { size_t nrow ; // the matrix is nrow-by-ncol size_t ncol ; size_t nzmax ; // maximum number of entries in the matrix size_t d ; // leading dimension (d >= nrow must hold) void *x ; // size nzmax or 2*nzmax, if present void *z ; // size nzmax, if present int xtype ; // pattern, real, complex, or zomplex int dtype ; // x and z double or single } cholmod_dense ; //------------------------------------------------------------------------------ // cholmod_allocate_dense: allocate a dense matrix (contents not initialized) //------------------------------------------------------------------------------ cholmod_dense *cholmod_allocate_dense ( // input: size_t nrow, // # of rows size_t ncol, // # of columns size_t d, // leading dimension int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_dense *cholmod_l_allocate_dense (size_t, size_t, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_zeros: allocate a dense matrix and set it to zero //------------------------------------------------------------------------------ cholmod_dense *cholmod_zeros ( // input: size_t nrow, // # of rows size_t ncol, // # of columns int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_dense *cholmod_l_zeros (size_t, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_ones: allocate a dense matrix of all 1's //------------------------------------------------------------------------------ cholmod_dense *cholmod_ones ( // input: size_t nrow, // # of rows size_t ncol, // # of columns int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (_REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_dense *cholmod_l_ones (size_t, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_eye: allocate a dense identity matrix //------------------------------------------------------------------------------ cholmod_dense *cholmod_eye // return a dense identity matrix ( // input: size_t nrow, // # of rows size_t ncol, // # of columns int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (_REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_dense *cholmod_l_eye (size_t, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_free_dense: free a dense matrix //------------------------------------------------------------------------------ int cholmod_free_dense ( // input/output: cholmod_dense **X, // handle of dense matrix to free cholmod_common *Common ) ; int cholmod_l_free_dense (cholmod_dense **, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_ensure_dense: ensure a dense matrix has a given size and type //------------------------------------------------------------------------------ cholmod_dense *cholmod_ensure_dense ( // input/output: cholmod_dense **X, // matrix to resize as needed (*X may be NULL) // input: size_t nrow, // # of rows size_t ncol, // # of columns size_t d, // leading dimension int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_dense *cholmod_l_ensure_dense (cholmod_dense **, size_t, size_t, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_sparse_to_dense: create a dense matrix copy of a sparse matrix //------------------------------------------------------------------------------ cholmod_dense *cholmod_sparse_to_dense // return a dense matrix ( // input: cholmod_sparse *A, // input matrix cholmod_common *Common ) ; cholmod_dense *cholmod_l_sparse_to_dense (cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_dense_nnz: count # of nonzeros in a dense matrix //------------------------------------------------------------------------------ int64_t cholmod_dense_nnz // return # of entries in the dense matrix ( // input: cholmod_dense *X, // input matrix cholmod_common *Common ) ; int64_t cholmod_l_dense_nnz (cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_dense_to_sparse: create a sparse matrix copy of a dense matrix //------------------------------------------------------------------------------ cholmod_sparse *cholmod_dense_to_sparse // return a sparse matrix C ( // input: cholmod_dense *X, // input matrix int mode, // 1: copy the values // 0: C is pattern cholmod_common *Common ) ; cholmod_sparse *cholmod_l_dense_to_sparse (cholmod_dense *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_copy_dense: create a copy of a dense matrix //------------------------------------------------------------------------------ cholmod_dense *cholmod_copy_dense // returns new dense matrix ( // input: cholmod_dense *X, // input dense matrix cholmod_common *Common ) ; cholmod_dense *cholmod_l_copy_dense (cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_copy_dense2: copy a dense matrix (pre-allocated) //------------------------------------------------------------------------------ int cholmod_copy_dense2 ( // input: cholmod_dense *X, // input dense matrix // input/output: cholmod_dense *Y, // output dense matrix (already allocated on input) cholmod_common *Common ) ; int cholmod_l_copy_dense2 (cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_dense_xtype: change the xtype and/or dtype of a dense matrix //------------------------------------------------------------------------------ int cholmod_dense_xtype ( // input: int to_xdtype, // requested xtype and dtype // input/output: cholmod_dense *X, // dense matrix to change cholmod_common *Common ) ; int cholmod_l_dense_xtype (int, cholmod_dense *, cholmod_common *) ; //============================================================================= // cholmod_triplet: a sparse matrix in triplet form //============================================================================= typedef struct cholmod_triplet_struct { size_t nrow ; // # of rows of the matrix size_t ncol ; // # of colums of the matrix size_t nzmax ; // max # of entries that can be held in the matrix size_t nnz ; // current # of entries can be held in the matrix // int32 or int64 arrays (depending on T->itype) void *i ; // i [0..nzmax-1], the row indices void *j ; // j [0..nzmax-1], the column indices // double or float arrays: void *x ; // size nzmax or 2*nzmax, or NULL void *z ; // size nzmax, or NULL int stype ; // T->stype defines what parts of the matrix is held: // 0: the matrix is unsymmetric with both lower and upper parts stored. // >0: the matrix is square and symmetric, where entries in the lower // triangular part are transposed and placed in the upper // triangular part of A if T is converted into a sparse matrix A. // <0: the matrix is square and symmetric, where entries in the upper // triangular part are transposed and placed in the lower // triangular part of A if T is converted into a sparse matrix A. // // Note that A->stype (for a sparse matrix) and T->stype (for a // triplet matrix) are handled differently. In a triplet matrix T, // no entry is ever ignored. For a sparse matrix A, if A->stype < 0 // or A->stype > 0, then entries not in the correct triangular part // are ignored. int itype ; // T->itype defines the integers used for T->i and T->j. // if CHOLMOD_INT, these arrays are all of type int32_t. // if CHOLMOD_LONG, these arrays are all of type int64_t. int xtype ; // pattern, real, complex, or zomplex int dtype ; // x and z are double or single } cholmod_triplet ; //------------------------------------------------------------------------------ // cholmod_allocate_triplet: allocate a triplet matrix //------------------------------------------------------------------------------ cholmod_triplet *cholmod_allocate_triplet // return triplet matrix T ( // input: size_t nrow, // # of rows size_t ncol, // # of columns size_t nzmax, // max # of entries the matrix can hold int stype, // the stype of the matrix (unsym, tril, or triu) int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_triplet *cholmod_l_allocate_triplet (size_t, size_t, size_t, int, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_free_triplet: free a triplet matrix //------------------------------------------------------------------------------ int cholmod_free_triplet ( // input/output: cholmod_triplet **T, // handle of triplet matrix to free cholmod_common *Common ) ; int cholmod_l_free_triplet (cholmod_triplet **, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_reallocate_triplet: change max # of entries in a triplet matrix //------------------------------------------------------------------------------ int cholmod_reallocate_triplet ( // input: size_t nznew, // new max # of nonzeros the triplet matrix can hold // input/output: cholmod_triplet *T, // triplet matrix to reallocate cholmod_common *Common ) ; int cholmod_l_reallocate_triplet (size_t, cholmod_triplet *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_sparse_to_triplet: create a triplet matrix copy of a sparse matrix //------------------------------------------------------------------------------ cholmod_triplet *cholmod_sparse_to_triplet ( // input: cholmod_sparse *A, // matrix to copy into triplet form T cholmod_common *Common ) ; cholmod_triplet *cholmod_l_sparse_to_triplet (cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_triplet_to_sparse: create a sparse matrix from of triplet matrix //------------------------------------------------------------------------------ cholmod_sparse *cholmod_triplet_to_sparse // return sparse matrix A ( // input: cholmod_triplet *T, // input triplet matrix size_t nzmax, // allocate space for max(nzmax,nnz(A)) entries cholmod_common *Common ) ; cholmod_sparse *cholmod_l_triplet_to_sparse (cholmod_triplet *, size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_copy_triplet: copy a triplet matrix //------------------------------------------------------------------------------ cholmod_triplet *cholmod_copy_triplet // return new triplet matrix ( // input: cholmod_triplet *T, // triplet matrix to copy cholmod_common *Common ) ; cholmod_triplet *cholmod_l_copy_triplet (cholmod_triplet *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_triplet_xtype: change the xtype and/or dtype of a triplet matrix //------------------------------------------------------------------------------ int cholmod_triplet_xtype ( // input: int to_xdtype, // requested xtype and dtype // input/output: cholmod_triplet *T, // triplet matrix to change cholmod_common *Common ) ; int cholmod_l_triplet_xtype (int, cholmod_triplet *, cholmod_common *) ; //------------------------------------------------------------------------------ // memory allocation: malloc/calloc/realloc/free //------------------------------------------------------------------------------ // These methods act like malloc/calloc/realloc/free, with some differences. // They are simple wrappers around the memory management functions in // SuiteSparse_config. cholmod_malloc and cholmod_calloc have the same // signature, unlike malloc and calloc. If cholmod_free is given a NULL // pointer, it safely does nothing. cholmod_free must be passed the size of // the object being freed, but that is just to keep track of memory usage // statistics. cholmod_realloc does not return NULL if it fails; instead, it // returns the pointer to the unmodified block of memory. void *cholmod_malloc // return pointer to newly allocated memory ( // input: size_t n, // number of items size_t size, // size of each item cholmod_common *Common ) ; void *cholmod_l_malloc (size_t, size_t, cholmod_common *) ; void *cholmod_calloc // return pointer to newly allocated memory ( // input: size_t n, // number of items size_t size, // size of each item cholmod_common *Common ) ; void *cholmod_l_calloc (size_t, size_t, cholmod_common *) ; void *cholmod_free // returns NULL to simplify its usage ( // input: size_t n, // number of items size_t size, // size of each item // input/output: void *p, // memory to free cholmod_common *Common ) ; void *cholmod_l_free (size_t, size_t, void *, cholmod_common *) ; void *cholmod_realloc // return newly reallocated block of memory ( // input: size_t nnew, // # of items in newly reallocate memory size_t size, // size of each item // input/output: void *p, // pointer to memory to reallocate (may be NULL) size_t *n, // # of items in p on input; nnew on output if success cholmod_common *Common ) ; void *cholmod_l_realloc (size_t, size_t, void *, size_t *, cholmod_common *) ; int cholmod_realloc_multiple // returns true if successful, false otherwise ( // input: size_t nnew, // # of items in newly reallocate memory int nint, // 0: do not allocate I_block or J_block, 1: just I_block, // 2: both I_block and J_block int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX) // input/output: void **I_block, // integer block of memory (int32_t or int64_t) void **J_block, // integer block of memory (int32_t or int64_t) void **X_block, // real or complex, double or single, block void **Z_block, // zomplex only: double or single block size_t *n, // current size of I_block, J_block, X_block, and/or Z_block // on input, changed to nnew on output, if successful cholmod_common *Common ) ; int cholmod_l_realloc_multiple (size_t, int, int, void **, void **, void **, void **, size_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // numerical comparisons //------------------------------------------------------------------------------ // These macros were different on Windows for older versions of CHOLMOD. // They are no longer needed but are kept for backward compatibility. #define CHOLMOD_IS_NAN(x) isnan (x) #define CHOLMOD_IS_ZERO(x) ((x) == 0.) #define CHOLMOD_IS_NONZERO(x) ((x) != 0.) #define CHOLMOD_IS_LT_ZERO(x) ((x) < 0.) #define CHOLMOD_IS_GT_ZERO(x) ((x) > 0.) #define CHOLMOD_IS_LE_ZERO(x) ((x) <= 0.) #endif //============================================================================== // CHOLMOD:Check Module //============================================================================== #ifndef NCHECK // Routines that check and print the 5 basic data types in CHOLMOD, and 3 kinds // of integer vectors (subset, perm, and parent), and read in matrices from a // file: // // cholmod_check_common check/print the Common object // cholmod_print_common // // cholmod_check_sparse check/print a sparse matrix in column-oriented form // cholmod_print_sparse // // cholmod_check_dense check/print a dense matrix // cholmod_print_dense // // cholmod_check_factor check/print a Cholesky factorization // cholmod_print_factor // // cholmod_check_triplet check/print a sparse matrix in triplet form // cholmod_print_triplet // // cholmod_check_subset check/print a subset (integer vector in given range) // cholmod_print_subset // // cholmod_check_perm check/print a permutation (an integer vector) // cholmod_print_perm // // cholmod_check_parent check/print an elimination tree (an integer vector) // cholmod_print_parent // // cholmod_read_triplet read a matrix in triplet form (any Matrix Market // "coordinate" format, or a generic triplet format). // // cholmod_read_sparse read a matrix in sparse form (same file format as // cholmod_read_triplet). // // cholmod_read_dense read a dense matrix (any Matrix Market "array" // format, or a generic dense format). // // cholmod_write_sparse write a sparse matrix to a Matrix Market file. // // cholmod_write_dense write a dense matrix to a Matrix Market file. // // cholmod_print_common and cholmod_check_common are the only two routines that // you may call after calling cholmod_finish. // // Requires the Utility module. Not required by any CHOLMOD module, except when // debugging is enabled (in which case all modules require the Check module). // // See cholmod_read.c for a description of the file formats supported by the // cholmod_read_* routines. //------------------------------------------------------------------------------ // cholmod_check_common: check the Common object //------------------------------------------------------------------------------ int cholmod_check_common ( cholmod_common *Common ) ; int cholmod_l_check_common (cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_print_common: print the Common object //------------------------------------------------------------------------------ int cholmod_print_common ( // input: const char *name, // printed name of Common object cholmod_common *Common ) ; int cholmod_l_print_common (const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_gpu_stats: print the GPU / CPU statistics //------------------------------------------------------------------------------ int cholmod_gpu_stats (cholmod_common *) ; int cholmod_l_gpu_stats (cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_check_sparse: check a sparse matrix //------------------------------------------------------------------------------ int cholmod_check_sparse ( // input: cholmod_sparse *A, // sparse matrix to check cholmod_common *Common ) ; int cholmod_l_check_sparse (cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_print_sparse //------------------------------------------------------------------------------ int cholmod_print_sparse ( // input: cholmod_sparse *A, // sparse matrix to print const char *name, // printed name of sparse matrix cholmod_common *Common ) ; int cholmod_l_print_sparse (cholmod_sparse *, const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_check_dense: check a dense matrix //------------------------------------------------------------------------------ int cholmod_check_dense ( // input: cholmod_dense *X, // dense matrix to check cholmod_common *Common ) ; int cholmod_l_check_dense (cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_print_dense: print a dense matrix //------------------------------------------------------------------------------ int cholmod_print_dense ( // input: cholmod_dense *X, // dense matrix to print const char *name, // printed name of dense matrix cholmod_common *Common ) ; int cholmod_l_print_dense (cholmod_dense *, const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_check_factor: check a factor //------------------------------------------------------------------------------ int cholmod_check_factor ( // input: cholmod_factor *L, // factor to check cholmod_common *Common ) ; int cholmod_l_check_factor (cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_print_factor: print a factor //------------------------------------------------------------------------------ int cholmod_print_factor ( // input: cholmod_factor *L, // factor to print const char *name, // printed name of factor cholmod_common *Common ) ; int cholmod_l_print_factor (cholmod_factor *, const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_check_triplet: check a sparse matrix in triplet form //------------------------------------------------------------------------------ int cholmod_check_triplet ( // input: cholmod_triplet *T, // triplet matrix to check cholmod_common *Common ) ; int cholmod_l_check_triplet (cholmod_triplet *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_print_triplet: print a triplet matrix //------------------------------------------------------------------------------ int cholmod_print_triplet ( // input: cholmod_triplet *T, // triplet matrix to print const char *name, // printed name of triplet matrix cholmod_common *Common ) ; int cholmod_l_print_triplet (cholmod_triplet *, const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_check_subset: check a subset //------------------------------------------------------------------------------ int cholmod_check_subset ( // input: int32_t *Set, // Set [0:len-1] is a subset of 0:n-1. Duplicates OK int64_t len, // size of Set (an integer array) size_t n, // 0:n-1 is valid range cholmod_common *Common ) ; int cholmod_l_check_subset (int64_t *, int64_t, size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_print_subset: print a subset //------------------------------------------------------------------------------ int cholmod_print_subset ( // input: int32_t *Set, // Set [0:len-1] is a subset of 0:n-1. Duplicates OK int64_t len, // size of Set (an integer array) size_t n, // 0:n-1 is valid range const char *name, // printed name of Set cholmod_common *Common ) ; int cholmod_l_print_subset (int64_t *, int64_t, size_t, const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_check_perm: check a permutation //------------------------------------------------------------------------------ int cholmod_check_perm ( // input: int32_t *Perm, // Perm [0:len-1] is a permutation of subset of 0:n-1 size_t len, // size of Perm (an integer array) size_t n, // 0:n-1 is valid range cholmod_common *Common ) ; int cholmod_l_check_perm (int64_t *, size_t, size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_print_perm: print a permutation vector //------------------------------------------------------------------------------ int cholmod_print_perm ( // input: int32_t *Perm, // Perm [0:len-1] is a permutation of subset of 0:n-1 size_t len, // size of Perm (an integer array) size_t n, // 0:n-1 is valid range const char *name, // printed name of Perm cholmod_common *Common ) ; int cholmod_l_print_perm (int64_t *, size_t, size_t, const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_check_parent: check an elimination tree //------------------------------------------------------------------------------ int cholmod_check_parent ( // input: int32_t *Parent, // Parent [0:n-1] is an elimination tree size_t n, // size of Parent cholmod_common *Common ) ; int cholmod_l_check_parent (int64_t *, size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_print_parent //------------------------------------------------------------------------------ int cholmod_print_parent ( // input: int32_t *Parent, // Parent [0:n-1] is an elimination tree size_t n, // size of Parent const char *name, // printed name of Parent cholmod_common *Common ) ; int cholmod_l_print_parent (int64_t *, size_t, const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_read_sparse: read a sparse matrix from a file (double only) //------------------------------------------------------------------------------ cholmod_sparse *cholmod_read_sparse // return sparse matrix (double) ( // input: FILE *f, // file to read from, must already be open cholmod_common *Common ) ; cholmod_sparse *cholmod_l_read_sparse (FILE *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_read_sparse2: read a sparse matrix from a file (float or double) //------------------------------------------------------------------------------ cholmod_sparse *cholmod_read_sparse2 // return sparse matrix (double/single) ( // input: FILE *f, // file to read from, must already be open int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE cholmod_common *Common ) ; cholmod_sparse *cholmod_l_read_sparse2 (FILE *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_read_triplet: read a triplet matrix from a file (double only) //------------------------------------------------------------------------------ cholmod_triplet *cholmod_read_triplet // return triplet matrix (double) ( // input: FILE *f, // file to read from, must already be open cholmod_common *Common ) ; cholmod_triplet *cholmod_l_read_triplet (FILE *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_read_triplet: read a triplet matrix from a file (float or double) //------------------------------------------------------------------------------ cholmod_triplet *cholmod_read_triplet2 // return triplet matrix (double/single) ( // input: FILE *f, // file to read from, must already be open int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE cholmod_common *Common ) ; cholmod_triplet *cholmod_l_read_triplet2 (FILE *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_read_dense: read a dense matrix from a file (double only) //------------------------------------------------------------------------------ cholmod_dense *cholmod_read_dense // return dense matrix (double) ( // input: FILE *f, // file to read from, must already be open cholmod_common *Common ) ; cholmod_dense *cholmod_l_read_dense (FILE *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_read_dense2: read a dense matrix from a file (float or double) //------------------------------------------------------------------------------ cholmod_dense *cholmod_read_dense2 // return dense matrix (double/single) ( // input: FILE *f, // file to read from, must already be open int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE cholmod_common *Common ) ; cholmod_dense *cholmod_l_read_dense2 (FILE *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_read_matrix: read a sparse or dense matrix from a file (double only) //------------------------------------------------------------------------------ void *cholmod_read_matrix // return sparse/triplet/double matrix (double) ( // input: FILE *f, // file to read from, must already be open int prefer, // If 0, a sparse matrix is always return as a // cholmod_triplet form. It can have any stype // (symmetric-lower, unsymmetric, or symmetric-upper). // If 1, a sparse matrix is returned as an unsymmetric // cholmod_sparse form (A->stype == 0), with both upper and // lower triangular parts present. This is what the MATLAB // mread mexFunction does, since MATLAB does not have an // stype. // If 2, a sparse matrix is returned with an stype of 0 or // 1 (unsymmetric, or symmetric with upper part stored). // This argument has no effect for dense matrices. // output: int *mtype, // CHOLMOD_TRIPLET, CHOLMOD_SPARSE or CHOLMOD_DENSE cholmod_common *Common ) ; void *cholmod_l_read_matrix (FILE *, int, int *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_read_matrix2: read a sparse or dense matrix (float or double) //------------------------------------------------------------------------------ void *cholmod_read_matrix2 // sparse/triplet/double matrix (double/single) ( // input: FILE *f, // file to read from, must already be open int prefer, // see cholmod_read_matrix int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE // output: int *mtype, // CHOLMOD_TRIPLET, CHOLMOD_SPARSE or CHOLMOD_DENSE cholmod_common *Common ) ; void *cholmod_l_read_matrix2 (FILE *, int, int, int *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_write_sparse: write a sparse matrix to a file //------------------------------------------------------------------------------ // return values of cholmod_symmetry and cholmod_write: #define CHOLMOD_MM_RECTANGULAR 1 #define CHOLMOD_MM_UNSYMMETRIC 2 #define CHOLMOD_MM_SYMMETRIC 3 #define CHOLMOD_MM_HERMITIAN 4 #define CHOLMOD_MM_SKEW_SYMMETRIC 5 #define CHOLMOD_MM_SYMMETRIC_POSDIAG 6 #define CHOLMOD_MM_HERMITIAN_POSDIAG 7 int cholmod_write_sparse // see above, or -1 on error ( // input: FILE *f, // file to write to, must already be open cholmod_sparse *A, // matrix to print cholmod_sparse *Z, // optional matrix with pattern of explicit zeros const char *comments, // optional filename of comments to include cholmod_common *Common ) ; int cholmod_l_write_sparse (FILE *, cholmod_sparse *, cholmod_sparse *, const char *c, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_write_dense: write a dense matrix to a file //------------------------------------------------------------------------------ int cholmod_write_dense // CHOLMOD_MM_UNSYMMETRIC or _RECTANGULAR, or ( // -1 on error // input: FILE *f, // file to write to, must already be open cholmod_dense *X, // matrix to print const char *comments, // optional filename of comments to include cholmod_common *Common ) ; int cholmod_l_write_dense (FILE *, cholmod_dense *, const char *, cholmod_common *) ; #endif //============================================================================== // CHOLMOD:Cholesky Module //============================================================================== #ifndef NCHOLESKY // Sparse Cholesky routines: analysis, factorization, and solve. // // The primary routines are all that a user requires to order, analyze, and // factorize a sparse symmetric positive definite matrix A (or A*A'), and // to solve Ax=b (or A*A'x=b). The primary routines rely on the secondary // routines, the CHOLMOD Utility module, and the AMD and COLAMD packages. They // make optional use of the CHOLMOD Supernodal and Partition modules, the // METIS package, and the CCOLAMD package. // // Primary routines: // ----------------- // // cholmod_analyze order and analyze (simplicial or supernodal) // cholmod_factorize simplicial or supernodal Cholesky factorization // cholmod_solve solve a linear system (simplicial or supernodal) // cholmod_solve2 like cholmod_solve, but reuse workspace // cholmod_spsolve solve a linear system (sparse x and b) // // Secondary routines: // ------------------ // // cholmod_analyze_p analyze, with user-provided permutation or f set // cholmod_factorize_p factorize, with user-provided permutation or f // cholmod_analyze_ordering analyze a fill-reducing ordering // cholmod_etree find the elimination tree // cholmod_rowcolcounts compute the row/column counts of L // cholmod_amd order using AMD // cholmod_colamd order using COLAMD // cholmod_rowfac incremental simplicial factorization // cholmod_rowfac_mask rowfac, specific to LPDASA // cholmod_rowfac_mask2 rowfac, specific to LPDASA // cholmod_row_subtree find the nonzero pattern of a row of L // cholmod_resymbol recompute the symbolic pattern of L // cholmod_resymbol_noperm recompute the symbolic pattern of L, no L->Perm // cholmod_postorder postorder a tree // // Requires the Utility module, and two packages: AMD and COLAMD. // Optionally uses the Supernodal and Partition modules. // Required by the Partition module. //------------------------------------------------------------------------------ // cholmod_analyze: order and analyze (simplicial or supernodal) //------------------------------------------------------------------------------ // Orders and analyzes A, AA', PAP', or PAA'P' and returns a symbolic factor // that can later be passed to cholmod_factorize. cholmod_factor *cholmod_analyze // returns symbolic factor L ( // input: cholmod_sparse *A, // matrix to order and analyze cholmod_common *Common ) ; cholmod_factor *cholmod_l_analyze (cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_analyze_p: analyze, with user-provided permutation or f set //------------------------------------------------------------------------------ // Orders and analyzes A, AA', PAP', PAA'P', FF', or PFF'P and returns a // symbolic factor that can later be passed to cholmod_factorize, where // F = A(:,fset) if fset is not NULL and A->stype is zero. // UserPerm is tried if non-NULL. cholmod_factor *cholmod_analyze_p // returns symbolic factor L ( // input: cholmod_sparse *A, // matrix to order and analyze int32_t *UserPerm, // user-provided permutation, size A->nrow int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset cholmod_common *Common ) ; cholmod_factor *cholmod_l_analyze_p (cholmod_sparse *, int64_t *, int64_t *, size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_analyze_p2: analyze for sparse Cholesky or sparse QR //------------------------------------------------------------------------------ // This is normally not need by the user application. cholmod_factor *cholmod_analyze_p2 ( // input: int for_whom, // FOR_SPQR (0): for SPQR but not GPU-accelerated // FOR_CHOLESKY (1): for Cholesky (GPU or not) // FOR_SPQRGPU (2): for SPQR with GPU acceleration cholmod_sparse *A, // matrix to order and analyze int32_t *UserPerm, // user-provided permutation, size A->nrow int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset cholmod_common *Common ) ; cholmod_factor *cholmod_l_analyze_p2 (int, cholmod_sparse *, int64_t *, int64_t *, size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_factorize: simplicial or supernodal Cholesky factorization //------------------------------------------------------------------------------ // Factorizes PAP' (or PAA'P' if A->stype is 0), using a factor obtained // from cholmod_analyze. The analysis can be re-used simply by calling this // routine a second time with another matrix. A must have the same nonzero // pattern as that passed to cholmod_analyze. int cholmod_factorize // simplicial or superodal Cholesky factorization ( // input: cholmod_sparse *A, // matrix to factorize // input/output: cholmod_factor *L, // resulting factorization cholmod_common *Common ) ; int cholmod_l_factorize (cholmod_sparse *, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_factorize_p: factorize, with user-provided permutation or fset //------------------------------------------------------------------------------ // Same as cholmod_factorize, but with more options. int cholmod_factorize_p ( // input: cholmod_sparse *A, // matrix to factorize double beta [2], // factorize beta*I+A or beta*I+A'*A int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset // input/output: cholmod_factor *L, // resulting factorization cholmod_common *Common ) ; int cholmod_l_factorize_p (cholmod_sparse *, double [2], int64_t *, size_t, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_solve: solve a linear system (simplicial or supernodal) //------------------------------------------------------------------------------ // Solves one of many linear systems with a dense right-hand-side, using the // factorization from cholmod_factorize (or as modified by any other CHOLMOD // routine). D is identity for LL' factorizations. #define CHOLMOD_A 0 /* solve Ax=b */ #define CHOLMOD_LDLt 1 /* solve LDL'x=b */ #define CHOLMOD_LD 2 /* solve LDx=b */ #define CHOLMOD_DLt 3 /* solve DL'x=b */ #define CHOLMOD_L 4 /* solve Lx=b */ #define CHOLMOD_Lt 5 /* solve L'x=b */ #define CHOLMOD_D 6 /* solve Dx=b */ #define CHOLMOD_P 7 /* permute x=Px */ #define CHOLMOD_Pt 8 /* permute x=P'x */ cholmod_dense *cholmod_solve // returns the solution X ( // input: int sys, // system to solve cholmod_factor *L, // factorization to use cholmod_dense *B, // right-hand-side cholmod_common *Common ) ; cholmod_dense *cholmod_l_solve (int, cholmod_factor *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_solve2: like cholmod_solve, but with reusable workspace //------------------------------------------------------------------------------ int cholmod_solve2 // returns TRUE on success, FALSE on failure ( // input: int sys, // system to solve cholmod_factor *L, // factorization to use cholmod_dense *B, // right-hand-side cholmod_sparse *Bset, // output: cholmod_dense **X_Handle, // solution, allocated if need be cholmod_sparse **Xset_Handle, // workspace: cholmod_dense **Y_Handle, // workspace, or NULL cholmod_dense **E_Handle, // workspace, or NULL cholmod_common *Common ) ; int cholmod_l_solve2 (int, cholmod_factor *, cholmod_dense *, cholmod_sparse *, cholmod_dense **, cholmod_sparse **, cholmod_dense **, cholmod_dense **, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_spsolve: solve a linear system with a sparse right-hand-side //------------------------------------------------------------------------------ cholmod_sparse *cholmod_spsolve // returns the sparse solution X ( // input: int sys, // system to solve cholmod_factor *L, // factorization to use cholmod_sparse *B, // right-hand-side cholmod_common *Common ) ; cholmod_sparse *cholmod_l_spsolve (int, cholmod_factor *, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_etree: find the elimination tree of A or A'*A //------------------------------------------------------------------------------ int cholmod_etree ( // input: cholmod_sparse *A, // output: int32_t *Parent, // size ncol. Parent [j] = p if p is the parent of j cholmod_common *Common ) ; int cholmod_l_etree (cholmod_sparse *, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowcolcounts: compute the row/column counts of L //------------------------------------------------------------------------------ int cholmod_rowcolcounts ( // input: cholmod_sparse *A, // matrix to analyze int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int32_t *Parent, // size nrow. Parent [i] = p if p is the parent of i int32_t *Post, // size nrow. Post [k] = i if i is the kth node in // the postordered etree. // output: int32_t *RowCount, // size nrow. RowCount [i] = # entries in the ith // row of L, including the diagonal. int32_t *ColCount, // size nrow. ColCount [i] = # entries in the ith // column of L, including the diagonal. int32_t *First, // size nrow. First [i] = k is the least // postordering of any descendant of i. int32_t *Level, // size nrow. Level [i] is the length of the path // from i to the root, with Level [root] = 0. cholmod_common *Common ) ; int cholmod_l_rowcolcounts (cholmod_sparse *, int64_t *, size_t, int64_t *, int64_t *, int64_t *, int64_t *, int64_t *, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_analyze_ordering: analyze a fill-reducing ordering //------------------------------------------------------------------------------ int cholmod_analyze_ordering ( // input: cholmod_sparse *A, // matrix to analyze int ordering, // ordering method used int32_t *Perm, // size n, fill-reducing permutation to analyze int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset // output: int32_t *Parent, // size n, elimination tree int32_t *Post, // size n, postordering of elimination tree int32_t *ColCount, // size n, nnz in each column of L // workspace: int32_t *First, // size n workspace for cholmod_postorder int32_t *Level, // size n workspace for cholmod_postorder cholmod_common *Common ) ; int cholmod_l_analyze_ordering (cholmod_sparse *, int, int64_t *, int64_t *, size_t, int64_t *, int64_t *, int64_t *, int64_t *, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_amd: order using AMD //------------------------------------------------------------------------------ // Finds a permutation P to reduce fill-in in the factorization of P*A*P' // or P*A*A'P' int cholmod_amd ( // input: cholmod_sparse *A, // matrix to order int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset // output: int32_t *Perm, // size A->nrow, output permutation cholmod_common *Common ) ; int cholmod_l_amd (cholmod_sparse *, int64_t *, size_t, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_colamd: order using COLAMD //------------------------------------------------------------------------------ // Finds a permutation P to reduce fill-in in the factorization of P*A*A'*P'. // Orders F*F' where F = A (:,fset) if fset is not NULL int cholmod_colamd ( // input: cholmod_sparse *A, // matrix to order int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int postorder, // if TRUE, follow with a coletree postorder // output: int32_t *Perm, // size A->nrow, output permutation cholmod_common *Common ) ; int cholmod_l_colamd (cholmod_sparse *, int64_t *, size_t, int, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowfac: incremental simplicial factorization //------------------------------------------------------------------------------ // Partial or complete simplicial factorization. Rows and columns kstart:kend-1 // of L and D must be initially equal to rows/columns kstart:kend-1 of the // identity matrix. Row k can only be factorized if all descendants of node // k in the elimination tree have been factorized. int cholmod_rowfac ( // input: cholmod_sparse *A, // matrix to factorize cholmod_sparse *F, // used for A*A' case only. F=A' or A(:,f)' double beta [2], // factorize beta*I+A or beta*I+AA' size_t kstart, // first row to factorize size_t kend, // last row to factorize is kend-1 // input/output: cholmod_factor *L, cholmod_common *Common ) ; int cholmod_l_rowfac (cholmod_sparse *, cholmod_sparse *, double [2], size_t, size_t, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowfac_mask: incremental simplicial factorization //------------------------------------------------------------------------------ // cholmod_rowfac_mask and cholmod_rowfac_mask2 are version of cholmod_rowfac // that are specific to LPDASA. It is unlikely to be needed by any other // application, and is not documented in the CHOLMOD User Guide. int cholmod_rowfac_mask ( // input: cholmod_sparse *A, // matrix to factorize cholmod_sparse *F, // used for A*A' case only. F=A' or A(:,f)' double beta [2], // factorize beta*I+A or beta*I+AA' size_t kstart, // first row to factorize size_t kend, // last row to factorize is kend-1 int32_t *mask, // size A->nrow. if mask[i] >= 0 row i is set to zero int32_t *RLinkUp, // size A->nrow. link list of rows to compute // input/output: cholmod_factor *L, cholmod_common *Common ) ; int cholmod_l_rowfac_mask (cholmod_sparse *, cholmod_sparse *, double [2], size_t, size_t, int64_t *, int64_t *, cholmod_factor *, cholmod_common *) ; int cholmod_rowfac_mask2 ( // input: cholmod_sparse *A, // matrix to factorize cholmod_sparse *F, // used for A*A' case only. F=A' or A(:,f)' double beta [2], // factorize beta*I+A or beta*I+AA' size_t kstart, // first row to factorize size_t kend, // last row to factorize is kend-1 int32_t *mask, // size A->nrow. if mask[i] >= maskmark row i is set // to zero int32_t maskmark, // for mask [i] test int32_t *RLinkUp, // size A->nrow. link list of rows to compute // input/output: cholmod_factor *L, cholmod_common *Common ) ; int cholmod_l_rowfac_mask2 (cholmod_sparse *, cholmod_sparse *, double [2], size_t, size_t, int64_t *, int64_t, int64_t *, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_row_subtree: find the nonzero pattern of a row of L //------------------------------------------------------------------------------ // Find the nonzero pattern of x for the system Lx=b where L = (0:k-1,0:k-1) // and b = kth column of A or A*A' (rows 0 to k-1 only) int cholmod_row_subtree ( // input: cholmod_sparse *A, // matrix to analyze cholmod_sparse *F, // used for A*A' case only. F=A' or A(:,f)' size_t krow, // row k of L int32_t *Parent, // elimination tree // output: cholmod_sparse *R, // pattern of L(k,:), 1-by-n with R->nzmax >= n cholmod_common *Common ) ; int cholmod_l_row_subtree (cholmod_sparse *, cholmod_sparse *, size_t, int64_t *, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_lsolve_pattern: find the nonzero pattern of y=L\b //------------------------------------------------------------------------------ int cholmod_lsolve_pattern ( // input: cholmod_sparse *B, // sparse right-hand-side (a single sparse column) cholmod_factor *L, // the factor L from which parent(i) is derived // output: cholmod_sparse *Yset, // pattern of Y=L\B, n-by-1 with Y->nzmax >= n cholmod_common *Common ) ; int cholmod_l_lsolve_pattern (cholmod_sparse *, cholmod_factor *, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_row_lsubtree: find the nonzero pattern of a row of L //------------------------------------------------------------------------------ // Identical to cholmod_row_subtree, except that it finds the elimination tree // from L itself. int cholmod_row_lsubtree ( // input: cholmod_sparse *A, // matrix to analyze int32_t *Fi, // nonzero pattern of kth row of A', not required // for the symmetric case. Need not be sorted. size_t fnz, // size of Fi size_t krow, // row k of L cholmod_factor *L, // the factor L from which parent(i) is derived // output: cholmod_sparse *R, // pattern of L(k,:), n-by-1 with R->nzmax >= n cholmod_common *Common ) ; int cholmod_l_row_lsubtree (cholmod_sparse *, int64_t *, size_t, size_t, cholmod_factor *, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_resymbol: recompute the symbolic pattern of L //------------------------------------------------------------------------------ // Remove entries from L that are not in the factorization of P*A*P', P*A*A'*P', // or P*F*F'*P' (depending on A->stype and whether fset is NULL or not). // // cholmod_resymbol is the same as cholmod_resymbol_noperm, except that it // first permutes A according to L->Perm. A can be upper/lower/unsymmetric, // in contrast to cholmod_resymbol_noperm (which can be lower or unsym). int cholmod_resymbol // recompute symbolic pattern of L ( // input: cholmod_sparse *A, // matrix to analyze int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int pack, // if TRUE, pack the columns of L // input/output: cholmod_factor *L, // factorization, entries pruned on output cholmod_common *Common ) ; int cholmod_l_resymbol (cholmod_sparse *, int64_t *, size_t, int, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_resymbol_noperm: recompute the symbolic pattern of L, no L->Perm //------------------------------------------------------------------------------ // Remove entries from L that are not in the factorization of A, A*A', // or F*F' (depending on A->stype and whether fset is NULL or not). int cholmod_resymbol_noperm ( // input: cholmod_sparse *A, // matrix to analyze int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int pack, // if TRUE, pack the columns of L // input/output: cholmod_factor *L, // factorization, entries pruned on output cholmod_common *Common ) ; int cholmod_l_resymbol_noperm (cholmod_sparse *, int64_t *, size_t, int, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rcond: compute rough estimate of reciprocal of condition number //------------------------------------------------------------------------------ double cholmod_rcond // return rcond estimate ( // input: cholmod_factor *L, // factorization to query; not modified cholmod_common *Common ) ; double cholmod_l_rcond (cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_postorder: Compute the postorder of a tree //------------------------------------------------------------------------------ int32_t cholmod_postorder // return # of nodes postordered ( // input: int32_t *Parent, // size n. Parent [j] = p if p is the parent of j size_t n, int32_t *Weight, // size n, optional. Weight [j] is weight of node j // output: int32_t *Post, // size n. Post [k] = j is kth in postordered tree cholmod_common *Common ) ; int64_t cholmod_l_postorder (int64_t *, size_t, int64_t *, int64_t *, cholmod_common *) ; #endif //============================================================================== // CHOLMOD:MatrixOps Module //============================================================================== #ifndef NMATRIXOPS // Basic operations on sparse and dense matrices. // // cholmod_drop A = entries in A with abs. value >= tol // cholmod_norm_dense s = norm (X), 1-norm, inf-norm, or 2-norm // cholmod_norm_sparse s = norm (A), 1-norm or inf-norm // cholmod_horzcat C = [A,B] // cholmod_scale A = diag(s)*A, A*diag(s), s*A or diag(s)*A*diag(s) // cholmod_sdmult Y = alpha*(A*X) + beta*Y or alpha*(A'*X) + beta*Y // cholmod_ssmult C = A*B // cholmod_submatrix C = A (i,j), where i and j are arbitrary vectors // cholmod_vertcat C = [A ; B] // // A, B, C: sparse matrices (cholmod_sparse) // X, Y: dense matrices (cholmod_dense) // s: scalar or vector // // Requires the Utility module. Not required by any other CHOLMOD module. //------------------------------------------------------------------------------ // cholmod_drop: drop entries with small absolute value //------------------------------------------------------------------------------ int cholmod_drop ( // input: double tol, // keep entries with absolute value > tol // input/output: cholmod_sparse *A, // matrix to drop entries from cholmod_common *Common ) ; int cholmod_l_drop (double, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_norm_dense: s = norm (X), 1-norm, inf-norm, or 2-norm //------------------------------------------------------------------------------ double cholmod_norm_dense // returns norm (X) ( // input: cholmod_dense *X, // matrix to compute the norm of int norm, // type of norm: 0: inf. norm, 1: 1-norm, 2: 2-norm cholmod_common *Common ) ; double cholmod_l_norm_dense (cholmod_dense *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_norm_sparse: s = norm (A), 1-norm or inf-norm //------------------------------------------------------------------------------ double cholmod_norm_sparse // returns norm (A) ( // input: cholmod_sparse *A, // matrix to compute the norm of int norm, // type of norm: 0: inf. norm, 1: 1-norm cholmod_common *Common ) ; double cholmod_l_norm_sparse (cholmod_sparse *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_horzcat: C = [A,B] //------------------------------------------------------------------------------ // C is returned as an unsymmetric matrix with C->stype of zero. If A and/or // B are symmetric, they are converted first to unsymmetric, and the conversion // is governed by the mode input parameter. cholmod_sparse *cholmod_horzcat // returns C = [A B] ( // input: cholmod_sparse *A, // left matrix to concatenate cholmod_sparse *B, // right matrix to concatenate int mode, // 2: numerical (conj) if A and/or B are symmetric, // 1: numerical (non-conj.) if A and/or B are symmetric. // 0: pattern cholmod_common *Common ) ; cholmod_sparse *cholmod_l_horzcat (cholmod_sparse *, cholmod_sparse *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_scale: A = diag(s)*A, A*diag(s), s*A or diag(s)*A*diag(s) //------------------------------------------------------------------------------ // scaling modes, selected by the scale input parameter: #define CHOLMOD_SCALAR 0 /* A = s*A */ #define CHOLMOD_ROW 1 /* A = diag(s)*A */ #define CHOLMOD_COL 2 /* A = A*diag(s) */ #define CHOLMOD_SYM 3 /* A = diag(s)*A*diag(s) */ int cholmod_scale ( // input: cholmod_dense *S, // scale factors (scalar or vector) int scale, // type of scaling to compute // input/output: cholmod_sparse *A, // matrix to scale cholmod_common *Common ) ; int cholmod_l_scale (cholmod_dense *, int, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_sdmult: Y = alpha*(A*X) + beta*Y or alpha*(A'*X) + beta*Y //------------------------------------------------------------------------------ // Sparse matrix times dense matrix int cholmod_sdmult ( // input: cholmod_sparse *A, // sparse matrix to multiply int transpose, // use A if 0, otherwise use A' double alpha [2], // scale factor for A double beta [2], // scale factor for Y cholmod_dense *X, // dense matrix to multiply // input/output: cholmod_dense *Y, // resulting dense matrix cholmod_common *Common ) ; int cholmod_l_sdmult (cholmod_sparse *, int, double [2], double [2], cholmod_dense *, cholmod_dense *Y, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_ssmult: C = A*B //------------------------------------------------------------------------------ // Sparse matrix times sparse matrix. // If A and/or B are symmetric, they are converted first to unsymmetric, and // the conversion is governed by the mode input parameter. cholmod_sparse *cholmod_ssmult // return C=A*B ( // input: cholmod_sparse *A, // left matrix to multiply cholmod_sparse *B, // right matrix to multiply int stype, // requested stype of C int mode, // 2: numerical (conj) if A and/or B are symmetric, // 1: numerical (non-conj.) if A and/or B are symmetric. // 0: pattern int sorted, // if TRUE then return C with sorted columns cholmod_common *Common ) ; cholmod_sparse *cholmod_l_ssmult (cholmod_sparse *, cholmod_sparse *, int, int, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_submatrix: C = A (r,c), where i and j are arbitrary vectors //------------------------------------------------------------------------------ // rsize < 0 denotes ":" in MATLAB notation, or more precisely 0:(A->nrow)-1. // In this case, r can be NULL. An rsize of zero, or r = NULL and rsize >= 0, // denotes "[ ]" in MATLAB notation (the empty set). // Similar rules hold for csize. // C is returned as an unsymmetric matrix with C->stype of zero. If A and/or // B are symmetric, they are converted first to unsymmetric, and the conversion // is governed by the mode input parameter. cholmod_sparse *cholmod_submatrix // return C = A (rset,cset) ( // input: cholmod_sparse *A, // matrix to subreference int32_t *rset, // set of row indices, duplicates OK int64_t rsize, // size of rset, or -1 for ":" int32_t *cset, // set of column indices, duplicates OK int64_t csize, // size of cset, or -1 for ":" int mode, // 2: numerical (conj) if A and/or B are symmetric, // 1: numerical (non-conj.) if A and/or B are symmetric. // 0: pattern int sorted, // if TRUE then return C with sorted columns cholmod_common *Common ) ; cholmod_sparse *cholmod_l_submatrix (cholmod_sparse *, int64_t *, int64_t, int64_t *, int64_t, int, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_vertcat: C = [A ; B] //------------------------------------------------------------------------------ // C is returned as an unsymmetric matrix with C->stype of zero. If A and/or // B are symmetric, they are converted first to unsymmetric, and the conversion // is governed by the mode input parameter. cholmod_sparse *cholmod_vertcat // returns C = [A ; B] ( // input: cholmod_sparse *A, // top matrix to concatenate cholmod_sparse *B, // bottom matrix to concatenate int mode, // 2: numerical (conj) if A and/or B are symmetric, // 1: numerical (non-conj.) if A and/or B are symmetric // 0: pattern cholmod_common *Common ) ; cholmod_sparse *cholmod_l_vertcat (cholmod_sparse *, cholmod_sparse *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_symmetry: determine if a sparse matrix is symmetric //------------------------------------------------------------------------------ // return values of cholmod_symmetry and cholmod_write: // #define CHOLMOD_MM_RECTANGULAR 1 // #define CHOLMOD_MM_UNSYMMETRIC 2 // #define CHOLMOD_MM_SYMMETRIC 3 // #define CHOLMOD_MM_HERMITIAN 4 // #define CHOLMOD_MM_SKEW_SYMMETRIC 5 // #define CHOLMOD_MM_SYMMETRIC_POSDIAG 6 // #define CHOLMOD_MM_HERMITIAN_POSDIAG 7 int cholmod_symmetry // returns the matrix symmetry (see above) ( // input: cholmod_sparse *A, int option, // option 0, 1, or 2 // output: int32_t *xmatched, // # of matched numerical entries int32_t *pmatched, // # of matched entries in pattern int32_t *nzoffdiag, // # of off diagonal entries int32_t *nzdiag, // # of diagonal entries cholmod_common *Common ) ; int cholmod_l_symmetry (cholmod_sparse *, int, int64_t *, int64_t *, int64_t *, int64_t *, cholmod_common *) ; #endif //============================================================================== // CHOLMOD:Modify Module //============================================================================== #ifndef NMODIFY //------------------------------------------------------------------------------ // CHOLMOD:Modify Module. Copyright (C) 2005-2023, Timothy A. Davis and William // W. Hager. http://www.suitesparse.com //------------------------------------------------------------------------------ // Sparse Cholesky modification routines: update / downdate / rowadd / rowdel. // Can also modify a corresponding solution to Lx=b when L is modified. This // module is most useful when applied on a Cholesky factorization computed by // the Cholesky module, but it does not actually require the Cholesky module. // The Utility module can create an identity Cholesky factorization (LDL' where // L=D=I) that can then by modified by these routines. // // Primary routines: // ----------------- // // cholmod_updown multiple rank update/downdate // cholmod_rowadd add a row to an LDL' factorization // cholmod_rowdel delete a row from an LDL' factorization // // Secondary routines: // ------------------- // // cholmod_updown_solve update/downdate, and modify solution to Lx=b // cholmod_updown_mark update/downdate, and modify solution to partial Lx=b // cholmod_updown_mask update/downdate for LPDASA // cholmod_updown_mask2 update/downdate for LPDASA // cholmod_rowadd_solve add a row, and update solution to Lx=b // cholmod_rowadd_mark add a row, and update solution to partial Lx=b // cholmod_rowdel_solve delete a row, and downdate Lx=b // cholmod_rowdel_mark delete a row, and downdate solution to partial Lx=b // // Requires the Utility module. Not required by any other CHOLMOD module. //------------------------------------------------------------------------------ // cholmod_updown: multiple rank update/downdate //------------------------------------------------------------------------------ // Compute the new LDL' factorization of LDL'+CC' (an update) or LDL'-CC' // (a downdate). The factor object L need not be an LDL' factorization; it // is converted to one if it isn't. int cholmod_updown // update/downdate ( // input: int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // the incoming sparse update // input/output: cholmod_factor *L, // factor to modify cholmod_common *Common ) ; int cholmod_l_updown (int, cholmod_sparse *, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_updown_solve: update/downdate, and modify solution to Lx=b //------------------------------------------------------------------------------ // Does the same as cholmod_updown, except that it also updates/downdates the // solution to Lx=b+DeltaB. x and b must be n-by-1 dense matrices. b is not // need as input to this routine, but a sparse change to b is (DeltaB). Only // entries in DeltaB corresponding to columns modified in L are accessed; the // rest must be zero. int cholmod_updown_solve ( // input: int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // the incoming sparse update // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; int cholmod_l_updown_solve (int, cholmod_sparse *, cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_updown_mark: update/downdate, and modify solution to partial Lx=b //------------------------------------------------------------------------------ // Does the same as cholmod_updown_solve, except only part of L is used in // the update/downdate of the solution to Lx=b. This routine is an "expert" // routine. It is meant for use in LPDASA only. See cholmod_updown.c for // a description of colmark. int cholmod_updown_mark ( // input: int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // the incoming sparse update int32_t *colmark, // array of size n. See cholmod_updown.c for details // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; int cholmod_l_updown_mark (int, cholmod_sparse *, int64_t *, cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_updown_mask: update/downdate, for LPDASA //------------------------------------------------------------------------------ // Does the same as cholmod_updown_mark, except has an additional "mask" // argument. This routine is an "expert" routine. It is meant for use in // LPDASA only. See cholmod_updown.c for a description of mask. int cholmod_updown_mask ( // input: int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // the incoming sparse update int32_t *colmark, // array of size n. See cholmod_updown.c for details int32_t *mask, // size n // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; int cholmod_l_updown_mask (int, cholmod_sparse *, int64_t *, int64_t *, cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; int cholmod_updown_mask2 ( // input: int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // the incoming sparse update int32_t *colmark, // array of size n. See cholmod_updown.c for details int32_t *mask, // size n int32_t maskmark, // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; int cholmod_l_updown_mask2 (int, cholmod_sparse *, int64_t *, int64_t *, int64_t, cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowadd: add a row to an LDL' factorization (a rank-2 update) //------------------------------------------------------------------------------ // cholmod_rowadd adds a row to the LDL' factorization. It computes the kth // row and kth column of L, and then updates the submatrix L (k+1:n,k+1:n) // accordingly. The kth row and column of L must originally be equal to the // kth row and column of the identity matrix. The kth row/column of L is // computed as the factorization of the kth row/column of the matrix to // factorize, which is provided as a single n-by-1 sparse matrix R. int cholmod_rowadd // add a row to an LDL' factorization ( // input: size_t k, // row/column index to add cholmod_sparse *R, // row/column of matrix to factorize (n-by-1) // input/output: cholmod_factor *L, // factor to modify cholmod_common *Common ) ; int cholmod_l_rowadd (size_t, cholmod_sparse *, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowadd_solve: add a row, and update solution to Lx=b //------------------------------------------------------------------------------ // Does the same as cholmod_rowadd, and also updates the solution to Lx=b // See cholmod_updown for a description of how Lx=b is updated. There is on // additional parameter: bk specifies the new kth entry of b. int cholmod_rowadd_solve ( // input: size_t k, // row/column index to add cholmod_sparse *R, // row/column of matrix to factorize (n-by-1) double bk [2], // kth entry of the right-hand-side b // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; int cholmod_l_rowadd_solve (size_t, cholmod_sparse *, double [2], cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowadd_mark: add a row, and update solution to partial Lx=b //------------------------------------------------------------------------------ // Does the same as cholmod_rowadd_solve, except only part of L is used in // the update/downdate of the solution to Lx=b. This routine is an "expert" // routine. It is meant for use in LPDASA only. int cholmod_rowadd_mark ( // input: size_t k, // row/column index to add cholmod_sparse *R, // row/column of matrix to factorize (n-by-1) double bk [2], // kth entry of the right hand side, b int32_t *colmark, // int32_t array of size 1. See cholmod_updown.c // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; int cholmod_l_rowadd_mark (size_t, cholmod_sparse *, double [2], int64_t *, cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowdel: delete a row from an LDL' factorization (a rank-2 update) //------------------------------------------------------------------------------ // Sets the kth row and column of L to be the kth row and column of the identity // matrix, and updates L(k+1:n,k+1:n) accordingly. To reduce the running time, // the caller can optionally provide the nonzero pattern (or an upper bound) of // kth row of L, as the sparse n-by-1 vector R. Provide R as NULL if you want // CHOLMOD to determine this itself, which is easier for the caller, but takes // a little more time. int cholmod_rowdel // delete a rw from an LDL' factorization ( // input: size_t k, // row/column index to delete cholmod_sparse *R, // NULL, or the nonzero pattern of kth row of L // input/output: cholmod_factor *L, // factor to modify cholmod_common *Common ) ; int cholmod_l_rowdel (size_t, cholmod_sparse *, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowdel_solve: delete a row, and downdate Lx=b //------------------------------------------------------------------------------ // Does the same as cholmod_rowdel, but also downdates the solution to Lx=b. // When row/column k of A is "deleted" from the system A*y=b, this can induce // a change to x, in addition to changes arising when L and b are modified. // If this is the case, the kth entry of y is required as input (yk). int cholmod_rowdel_solve ( // input: size_t k, // row/column index to delete cholmod_sparse *R, // NULL, or the nonzero pattern of kth row of L double yk [2], // kth entry in the solution to A*y=b // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; int cholmod_l_rowdel_solve (size_t, cholmod_sparse *, double [2], cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowdel_mark: delete a row, and downdate solution to partial Lx=b //------------------------------------------------------------------------------ // Does the same as cholmod_rowdel_solve, except only part of L is used in // the update/downdate of the solution to Lx=b. This routine is an "expert" // routine. It is meant for use in LPDASA only. int cholmod_rowdel_mark ( // input: size_t k, // row/column index to delete cholmod_sparse *R, // NULL, or the nonzero pattern of kth row of L double yk [2], // kth entry in the solution to A*y=b int32_t *colmark, // int32_t array of size 1. See cholmod_updown.c // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; int cholmod_l_rowdel_mark (size_t, cholmod_sparse *, double [2], int64_t *, cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; #endif //============================================================================== // CHOLMOD:Partition Module (CAMD, CCOLAMD, and CSYMAMD) //============================================================================== //------------------------------------------------------------------------------ // CHOLMOD/Partition: // Copyright (C) 2005-2023, Univ. of Florida. Author: Timothy A. Davis //------------------------------------------------------------------------------ // CHOLMOD Partition module, interface to CAMD, CCOLAMD, CSYMAMD, and METIS, // and graph partitioning and graph-partition-based orderings. Includes an // interface to CCOLAMD and CSYMAMD, constrained minimum degree ordering // methods which order a matrix following constraints determined via nested // dissection. // // These functions do not require METIS. They are installed unless NCAMD // is defined: // cholmod_ccolamd interface to CCOLAMD ordering // cholmod_csymamd interface to CSYMAMD ordering // cholmod_camd interface to CAMD ordering // // These functions require METIS: // cholmod_nested_dissection CHOLMOD nested dissection ordering // cholmod_metis METIS nested dissection ordering (METIS_NodeND) // cholmod_bisect graph partitioner (currently based on METIS) // cholmod_metis_bisector direct interface to METIS_ComputeVertexSeparator // // Requires the Utility and Cholesky modules, and three packages: METIS, CAMD, // and CCOLAMD. Optionally used by the Cholesky module. #ifndef NCAMD //------------------------------------------------------------------------------ // cholmod_ccolamd //------------------------------------------------------------------------------ // Order AA' or A(:,f)*A(:,f)' using CCOLAMD. int cholmod_ccolamd ( // input: cholmod_sparse *A, // matrix to order int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int32_t *Cmember, // size A->nrow. Cmember [i] = c if row i is in the // constraint set c. c must be >= 0. The # of // constraint sets is max (Cmember) + 1. If Cmember is // NULL, then it is interpretted as Cmember [i] = 0 for // all i. // output: int32_t *Perm, // size A->nrow, output permutation cholmod_common *Common ) ; int cholmod_l_ccolamd (cholmod_sparse *, int64_t *, size_t, int64_t *, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_csymamd //------------------------------------------------------------------------------ // Order A using CSYMAMD. int cholmod_csymamd ( // input: cholmod_sparse *A, // matrix to order // output: int32_t *Cmember, // size nrow. see cholmod_ccolamd.c for description int32_t *Perm, // size A->nrow, output permutation cholmod_common *Common ) ; int cholmod_l_csymamd (cholmod_sparse *, int64_t *, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_camd: order A using CAMD //------------------------------------------------------------------------------ int cholmod_camd ( // input: cholmod_sparse *A, // matrix to order int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int32_t *Cmember, // size nrow. see cholmod_ccolamd.c for description. // output: int32_t *Perm, // size A->nrow, output permutation cholmod_common *Common ) ; int cholmod_l_camd (cholmod_sparse *, int64_t *, size_t, int64_t *, int64_t *, cholmod_common *) ; #endif //------------------------------------------------------------------------------ // CHOLMOD:Partition Module (graph partition methods) //------------------------------------------------------------------------------ // These routines still exist if CHOLMOD is compiled with -DNPARTITION, // but they return Common->status = CHOLMOD_NOT_INSTALLED in that case. #if 1 //------------------------------------------------------------------------------ // cholmod_nested_dissection //------------------------------------------------------------------------------ // Order A, AA', or A(:,f)*A(:,f)' using CHOLMOD's nested dissection method // (METIS's node bisector applied recursively to compute the separator tree // and constraint sets, followed by CCOLAMD using the constraints). Usually // finds better orderings than METIS_NodeND, but takes longer. int64_t cholmod_nested_dissection // returns # of components, or -1 if error ( // input: cholmod_sparse *A, // matrix to order int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset // output: int32_t *Perm, // size A->nrow, output permutation int32_t *CParent, // size A->nrow. On output, CParent [c] is the parent // of component c, or EMPTY if c is a root, and where // c is in the range 0 to # of components minus 1 int32_t *Cmember, // size A->nrow. Cmember [j] = c if node j of A is // in component c cholmod_common *Common ) ; int64_t cholmod_l_nested_dissection (cholmod_sparse *, int64_t *, size_t, int64_t *, int64_t *, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_metis //------------------------------------------------------------------------------ // Order A, AA', or A(:,f)*A(:,f)' using METIS_NodeND. int cholmod_metis ( // input: cholmod_sparse *A, // matrix to order int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int postorder, // if TRUE, follow with etree or coletree postorder // output: int32_t *Perm, // size A->nrow, output permutation cholmod_common *Common ) ; int cholmod_l_metis (cholmod_sparse *, int64_t *, size_t, int, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_bisect //------------------------------------------------------------------------------ // Finds a node bisector of A, A*A', A(:,f)*A(:,f)'. int64_t cholmod_bisect // returns # of nodes in separator ( // input: cholmod_sparse *A, // matrix to bisect int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int compress, // if TRUE, compress the graph first // output: int32_t *Partition, // size A->nrow. Node i is in the left graph if // Partition [i] = 0, the right graph if 1, and in the // separator if 2. cholmod_common *Common ) ; int64_t cholmod_l_bisect (cholmod_sparse *, int64_t *, size_t, int, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_metis_bisector //------------------------------------------------------------------------------ // Find a set of nodes that bisects the graph of A or AA' (direct interface // to METIS_ComputeVertexSeperator). int64_t cholmod_metis_bisector // returns separator size ( // input: cholmod_sparse *A, // matrix to bisect int32_t *Anw, // size A->nrow, node weights, can be NULL, // which means the graph is unweighted. int32_t *Aew, // size nz, edge weights (silently ignored). // This option was available with METIS 4, but not // in METIS 5. This argument is now unused, but // it remains for backward compatibilty, so as not // to change the API for cholmod_metis_bisector. // output: int32_t *Partition, // size A->nrow cholmod_common *Common ) ; int64_t cholmod_l_metis_bisector (cholmod_sparse *, int64_t *, int64_t *, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_collapse_septree //------------------------------------------------------------------------------ // Collapse nodes in a separator tree. int64_t cholmod_collapse_septree ( // input: size_t n, // # of nodes in the graph size_t ncomponents, // # of nodes in the separator tree (must be <= n) double nd_oksep, // collapse if #sep >= nd_oksep * #nodes in subtree size_t nd_small, // collapse if #nodes in subtree < nd_small // output: int32_t *CParent, // size ncomponents; from cholmod_nested_dissection int32_t *Cmember, // size n; from cholmod_nested_dissection cholmod_common *Common ) ; int64_t cholmod_l_collapse_septree (size_t, size_t, double, size_t, int64_t *, int64_t *, cholmod_common *) ; #endif //============================================================================== // CHOLMOD:Supernodal Module //============================================================================== #ifndef NSUPERNODAL // Supernodal analysis, factorization, and solve. The simplest way to use // these routines is via the Cholesky module. It does not provide any // fill-reducing orderings, but does accept the orderings computed by the // Cholesky module. It does not require the Cholesky module itself, however. // // Primary routines: // ----------------- // cholmod_super_symbolic supernodal symbolic analysis // cholmod_super_numeric supernodal numeric factorization // cholmod_super_lsolve supernodal Lx=b solve // cholmod_super_ltsolve supernodal L'x=b solve // // Prototypes for the BLAS and LAPACK routines that CHOLMOD uses are listed // below, including how they are used in CHOLMOD. Only the double methods are // listed, but CHOLMOD also uses the corresponding single, single complex, and // double complex routines. // // BLAS routines: // -------------- // dtrsv solve Lx=b or L'x=b, L non-unit diagonal, x and b stride-1 // dtrsm solve LX=B or L'X=b, L non-unit diagonal // dgemv y=y-A*x or y=y-A'*x (x and y stride-1) // dgemm C=A*B', C=C-A*B, or C=C-A'*B // dsyrk C=tril(A*A'), zherk for the double complex case // // LAPACK routines: // ---------------- // dpotrf LAPACK: A=chol(tril(A)) // // Requires the Utility module, and two external packages: LAPACK and the BLAS. // Optionally used by the Cholesky module. //------------------------------------------------------------------------------ // cholmod_super_symbolic //------------------------------------------------------------------------------ // Analyzes A, AA', or A(:,f)*A(:,f)' in preparation for a supernodal numeric // factorization. The user need not call this directly; cholmod_analyze is // a "simple" wrapper for this routine. int cholmod_super_symbolic ( // input: cholmod_sparse *A, // matrix to analyze cholmod_sparse *F, // F = A' or A(:,f)' int32_t *Parent, // elimination tree // input/output: cholmod_factor *L, // simplicial symbolic on input, // supernodal symbolic on output cholmod_common *Common ) ; int cholmod_l_super_symbolic (cholmod_sparse *, cholmod_sparse *, int64_t *, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_super_symbolic2 //------------------------------------------------------------------------------ // Analyze for supernodal Cholesky or multifrontal QR #define CHOLMOD_ANALYZE_FOR_SPQR 0 #define CHOLMOD_ANALYZE_FOR_CHOLESKY 1 #define CHOLMOD_ANALYZE_FOR_SPQRGPU 2 int cholmod_super_symbolic2 ( // input: int for_whom, // FOR_SPQR (0): for SPQR but not GPU-accelerated // FOR_CHOLESKY (1): for Cholesky (GPU or not) // FOR_SPQRGPU (2): for SPQR with GPU acceleration cholmod_sparse *A, // matrix to analyze cholmod_sparse *F, // F = A' or A(:,f)' int32_t *Parent, // elimination tree // input/output: cholmod_factor *L, // simplicial symbolic on input, // supernodal symbolic on output cholmod_common *Common ) ; int cholmod_l_super_symbolic2 (int, cholmod_sparse *, cholmod_sparse *, int64_t *, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_super_numeric //------------------------------------------------------------------------------ // Computes the numeric LL' factorization of A, AA', or A(:,f)*A(:,f)' using // a BLAS-based supernodal method. The user need not call this directly; // cholmod_factorize is a "simple" wrapper for this routine. int cholmod_super_numeric ( // input: cholmod_sparse *A, // matrix to factorize cholmod_sparse *F, // F = A' or A(:,f)' double beta [2], // beta*I is added to diagonal of matrix to factorize // input/output: cholmod_factor *L, // factorization cholmod_common *Common ) ; int cholmod_l_super_numeric (cholmod_sparse *, cholmod_sparse *, double [2], cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_super_lsolve //------------------------------------------------------------------------------ // Solve Lx=b where L is from a supernodal numeric factorization. The user // need not call this routine directly. cholmod_solve is a "simple" wrapper // for this routine. int cholmod_super_lsolve ( // input: cholmod_factor *L, // factor to use for the forward solve // input/output: cholmod_dense *X, // b on input, solution to Lx=b on output // workspace: cholmod_dense *E, // workspace of size nrhs*(L->maxesize) cholmod_common *Common ) ; int cholmod_l_super_lsolve (cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_super_ltsolve //------------------------------------------------------------------------------ // Solve L'x=b where L is from a supernodal numeric factorization. The user // need not call this routine directly. cholmod_solve is a "simple" wrapper // for this routine. int cholmod_super_ltsolve ( // input: cholmod_factor *L, // factor to use for the backsolve // input/output: cholmod_dense *X, // b on input, solution to L'x=b on output // workspace: cholmod_dense *E, // workspace of size nrhs*(L->maxesize) cholmod_common *Common ) ; int cholmod_l_super_ltsolve (cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; #endif #ifdef __cplusplus } #endif //============================================================================== // CHOLMOD:SupernodalGPU Module //============================================================================== //------------------------------------------------------------------------------ // cholmod_score_comp: for sorting descendant supernodes with qsort //------------------------------------------------------------------------------ #ifdef __cplusplus extern "C" { #endif typedef struct cholmod_descendant_score_t { double score ; int64_t d ; } descendantScore ; int cholmod_score_comp (struct cholmod_descendant_score_t *i, struct cholmod_descendant_score_t *j) ; int cholmod_l_score_comp (struct cholmod_descendant_score_t *i, struct cholmod_descendant_score_t *j) ; #ifdef __cplusplus } #endif //------------------------------------------------------------------------------ // remainder of SupernodalGPU Module //------------------------------------------------------------------------------ #ifdef CHOLMOD_HAS_CUDA #include "omp.h" #include #ifndef SUITESPARSE_GPU_EXTERN_ON #include #include #endif // CHOLMOD_GPU_PRINTF: for printing GPU debug error messages // #define CHOLMOD_GPU_PRINTF(args) printf args #define CHOLMOD_GPU_PRINTF(args) // define supernode requirements for processing on GPU #define CHOLMOD_ND_ROW_LIMIT 256 /* required descendant rows */ #define CHOLMOD_ND_COL_LIMIT 32 /* required descendnat cols */ #define CHOLMOD_POTRF_LIMIT 512 /* required cols for POTRF & TRSM on GPU */ // # of host supernodes to perform before checking for free pinned buffers #define CHOLMOD_GPU_SKIP 3 #define CHOLMOD_HANDLE_CUDA_ERROR(e,s) {if (e) {ERROR(CHOLMOD_GPU_PROBLEM,s);}} #ifdef __cplusplus extern "C" { #endif typedef struct cholmod_gpu_pointers { double *h_Lx [CHOLMOD_HOST_SUPERNODE_BUFFERS] ; double *d_Lx [CHOLMOD_DEVICE_STREAMS] ; double *d_C ; double *d_A [CHOLMOD_DEVICE_STREAMS] ; void *d_Ls ; void *d_Map ; void *d_RelativeMap ; } cholmod_gpu_pointers ; int cholmod_gpu_memorysize // GPU memory size available, 1 if no GPU ( size_t *total_mem, size_t *available_mem, cholmod_common *Common ) ; int cholmod_l_gpu_memorysize // GPU memory size available, 1 if no GPU ( size_t *total_mem, size_t *available_mem, cholmod_common *Common ) ; int cholmod_gpu_probe ( cholmod_common *Common ) ; int cholmod_l_gpu_probe ( cholmod_common *Common ) ; int cholmod_gpu_deallocate ( cholmod_common *Common ) ; int cholmod_l_gpu_deallocate ( cholmod_common *Common ) ; int cholmod_gpu_start ( cholmod_common *Common ) ; int cholmod_l_gpu_start ( cholmod_common *Common ) ; void cholmod_gpu_end ( cholmod_common *Common ) ; void cholmod_l_gpu_end ( cholmod_common *Common ) ; int cholmod_gpu_allocate ( cholmod_common *Common ) ; int cholmod_l_gpu_allocate ( cholmod_common *Common ) ; #ifdef __cplusplus } #endif #endif #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Include/cholmod_template.h�������������������������������������������0000644�0001751�0000144�00000043442�14552026002�022736� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Include/cholmod_template.h: template definitions for CHOLMOD //------------------------------------------------------------------------------ // CHOLMOD/Include/cholmod_internal.h. Copyright (C) 2005-2023, // Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 //------------------------------------------------------------------------------ // The #including file must #define the following: // // Floating-point value, one of the following (default is DOUBLE): // // #define DOUBLE // #define SINGLE // // pattern/real/complex/zomplex, one of (no default): // // #define PATTERN // #define REAL // #define COMPLEX // #define ZOMPLEX //------------------------------------------------------------------------------ // undefine current xtype macros, and then define macros for current type //------------------------------------------------------------------------------ #undef TEMPLATE #undef TEMPLATE2 #undef TEMPLATE_DTYPE #undef XTYPE #undef XTYPE2 #undef XTYPE_OK #undef ENTRY_IS_NONZERO #undef ENTRY_IS_ZERO #undef ENTRY_IS_ONE #undef IMAG_IS_NONZERO #undef ABS #undef ASSEMBLE #undef ASSIGN #undef ASSIGN_CONJ #undef ASSIGN2 #undef ASSIGN2_CONJ #undef ASSIGN_REAL #undef ASSIGN_CONJ_OR_NCONJ #undef MULT #undef MULTADD #undef ADD #undef ADD_REAL #undef MULTSUB #undef MULTADDCONJ #undef MULTSUBCONJ #undef LLDOT #undef CLEAR #undef DIV #undef DIV_REAL #undef MULT_REAL #undef CLEAR_IMAG #undef LDLDOT #undef PREFIX #undef ENTRY_SIZE #undef XPRINT0 #undef XPRINT1 #undef XPRINT2 #undef XPRINT3 #undef Real //------------------------------------------------------------------------------ // single/double //------------------------------------------------------------------------------ #ifdef SINGLE // single precision #define Real float #define TEMPLATE_DTYPE(name) s_ ## name #else // double precision #ifndef DOUBLE #define DOUBLE #endif #define Real double #define TEMPLATE_DTYPE(name) d_ ## name #endif //------------------------------------------------------------------------------ // xtype: pattern/real/complex/zomplex //------------------------------------------------------------------------------ #ifdef PATTERN //-------------------------------------------------------------------------- // pattern: both double and single //-------------------------------------------------------------------------- #ifdef SINGLE #define PREFIX ps_ #define TEMPLATE(name) PS_TEMPLATE(name) #define TEMPLATE2(name) PS_TEMPLATE(name) #define TEMPLATE3(name) PS_TEMPLATE(name) #else #define PREFIX p_ #define TEMPLATE(name) P_TEMPLATE(name) #define TEMPLATE2(name) P_TEMPLATE(name) #endif #define XTYPE CHOLMOD_PATTERN #define XTYPE2 CHOLMOD_REAL #define XTYPE_OK(type) (TRUE) #define ENTRY_IS_NONZERO(ax,az,q) (TRUE) #define ENTRY_IS_ZERO(ax,az,q) (FALSE) #define ENTRY_IS_ONE(ax,az,q) (TRUE) #define IMAG_IS_NONZERO(ax,az,q) (FALSE) #define ENTRY_SIZE 0 #define ABS(ax,az,p) ((double) 1) #define ASSEMBLE(x,z,p,ax,az,q) #define ASSIGN(x,z,p,ax,az,q) #define ASSIGN_CONJ(x,z,p,ax,az,q) #define ASSIGN2(x,z,p,ax,az,q) P_ASSIGN2(x,z,p,ax,az,q) #define ASSIGN2_CONJ(x,z,p,ax,az,q) P_ASSIGN2(x,z,p,ax,az,q) #define ASSIGN_REAL(x,p,ax,q) #define MULT(x,z,p,ax,az,q,bx,bz,pb) #define MULTADD(x,z,p,ax,az,q,bx,bz,pb) #define ADD(x,z,p,ax,az,q,bx,bz,pb) #define ADD_REAL(x,p, ax,q, bx,r) #define MULTSUB(x,z,p,ax,az,q,bx,bz,pb) #define MULTADDCONJ(x,z,p,ax,az,q,bx,bz,pb) #define MULTSUBCONJ(x,z,p,ax,az,q,bx,bz,pb) #define LLDOT(x,p,ax,az,q) #define CLEAR(x,z,p) #define CLEAR_IMAG(x,z,p) #define DIV(x,z,p,ax,az,q) #define DIV_REAL(x,z,p, ax,az,q, bx,r) #define MULT_REAL(x,z,p, ax,az,q, bx,r) #define LDLDOT(x,p, ax,az,q, bx,r) #define XPRINT0(x,z,p) P_PRINT(0,x,z,p) #define XPRINT1(x,z,p) P_PRINT(1,x,z,p) #define XPRINT2(x,z,p) P_PRINT(2,x,z,p) #define XPRINT3(x,z,p) P_PRINT(3,x,z,p) #elif defined (REAL) //-------------------------------------------------------------------------- // real: double and single //-------------------------------------------------------------------------- #ifdef SINGLE #define PREFIX rs_ #define TEMPLATE(name) RS_TEMPLATE(name) #define TEMPLATE2(name) RS_TEMPLATE(name) #else #define PREFIX rd_ #define TEMPLATE(name) RD_TEMPLATE(name) #define TEMPLATE2(name) RD_TEMPLATE(name) #endif #define XTYPE CHOLMOD_REAL #define XTYPE2 CHOLMOD_REAL #define XTYPE_OK(type) R_XTYPE_OK(type) #define ENTRY_IS_NONZERO(ax,az,q) R_IS_NONZERO(ax,az,q) #define ENTRY_IS_ZERO(ax,az,q) R_IS_ZERO(ax,az,q) #define ENTRY_IS_ONE(ax,az,q) R_IS_ONE(ax,az,q) #define IMAG_IS_NONZERO(ax,az,q) (FALSE) #define ENTRY_SIZE 1 #define ABS(ax,az,p) R_ABS(ax,az,p) #define ASSEMBLE(x,z,p,ax,az,q) R_ASSEMBLE(x,z,p,ax,az,q) #define ASSIGN(x,z,p,ax,az,q) R_ASSIGN(x,z,p,ax,az,q) #define ASSIGN_CONJ(x,z,p,ax,az,q) R_ASSIGN(x,z,p,ax,az,q) #define ASSIGN2(x,z,p,ax,az,q) R_ASSIGN(x,z,p,ax,az,q) #define ASSIGN2_CONJ(x,z,p,ax,az,q) R_ASSIGN(x,z,p,ax,az,q) #define ASSIGN_REAL(x,p,ax,q) R_ASSIGN_REAL(x,p,ax,q) #define MULT(x,z,p,ax,az,q,bx,bz,pb) R_MULT(x,z,p,ax,az,q,bx,bz,pb) #define MULTADD(x,z,p,ax,az,q,bx,bz,pb) R_MULTADD(x,z,p,ax,az,q,bx,bz,pb) #define ADD(x,z,p,ax,az,q,bx,bz,pb) R_ADD(x,z,p,ax,az,q,bx,bz,pb) #define ADD_REAL(x,p, ax,q, bx,r) R_ADD_REAL(x,p, ax,q, bx,r) #define MULTSUB(x,z,p,ax,az,q,bx,bz,pb) R_MULTSUB(x,z,p,ax,az,q,bx,bz,pb) #define MULTADDCONJ(x,z,p,ax,az,q,bx,bz,pb) \ R_MULTADDCONJ(x,z,p,ax,az,q,bx,bz,pb) #define MULTSUBCONJ(x,z,p,ax,az,q,bx,bz,pb) \ R_MULTSUBCONJ(x,z,p,ax,az,q,bx,bz,pb) #define LLDOT(x,p,ax,az,q) R_LLDOT(x,p,ax,az,q) #define CLEAR(x,z,p) R_CLEAR(x,z,p) #define CLEAR_IMAG(x,z,p) R_CLEAR_IMAG(x,z,p) #define DIV(x,z,p,ax,az,q) R_DIV(x,z,p,ax,az,q) #define DIV_REAL(x,z,p, ax,az,q, bx,r) R_DIV_REAL(x,z,p, ax,az,q, bx,r) #define MULT_REAL(x,z,p, ax,az,q, bx,r) R_MULT_REAL(x,z,p, ax,az,q, bx,r) #define LDLDOT(x,p, ax,az,q, bx,r) R_LDLDOT(x,p, ax,az,q, bx,r) #define XPRINT0(x,z,p) R_PRINT(0,x,z,p) #define XPRINT1(x,z,p) R_PRINT(1,x,z,p) #define XPRINT2(x,z,p) R_PRINT(2,x,z,p) #define XPRINT3(x,z,p) R_PRINT(3,x,z,p) #elif defined (COMPLEX) //-------------------------------------------------------------------------- // complex: both double and single //-------------------------------------------------------------------------- #ifdef SINGLE #define PREFIX cs_ #ifdef NCONJUGATE // non-conjugate #define TEMPLATE(name) CS_T_TEMPLATE(name) #define TEMPLATE2(name) CS_T_TEMPLATE(name) #else // conjugate #define TEMPLATE(name) CS_TEMPLATE(name) #define TEMPLATE2(name) CS_TEMPLATE(name) #endif #else #define PREFIX cd_ #ifdef NCONJUGATE // non-conjugate #define TEMPLATE(name) CD_T_TEMPLATE(name) #define TEMPLATE2(name) CD_T_TEMPLATE(name) #else // conjugate #define TEMPLATE(name) CD_TEMPLATE(name) #define TEMPLATE2(name) CD_TEMPLATE(name) #endif #endif #define ABS(ax,az,p) C_ABS(ax,az,p) #define ASSEMBLE(x,z,p,ax,az,q) C_ASSEMBLE(x,z,p,ax,az,q) #define ASSIGN(x,z,p,ax,az,q) C_ASSIGN(x,z,p,ax,az,q) #define ASSIGN_CONJ(x,z,p,ax,az,q) C_ASSIGN_CONJ(x,z,p,ax,az,q) #define ASSIGN2(x,z,p,ax,az,q) C_ASSIGN(x,z,p,ax,az,q) #define ASSIGN2_CONJ(x,z,p,ax,az,q) C_ASSIGN_CONJ(x,z,p,ax,az,q) #define ASSIGN_REAL(x,p,ax,q) C_ASSIGN_REAL(x,p,ax,q) #define XTYPE CHOLMOD_COMPLEX #define XTYPE2 CHOLMOD_COMPLEX #define XTYPE_OK(type) C_XTYPE_OK(type) #define ENTRY_IS_NONZERO(ax,az,q) C_IS_NONZERO(ax,az,q) #define ENTRY_IS_ZERO(ax,az,q) C_IS_ZERO(ax,az,q) #define ENTRY_IS_ONE(ax,az,q) C_IS_ONE(ax,az,q) #define IMAG_IS_NONZERO(ax,az,q) C_IMAG_IS_NONZERO(ax,az,q) #define ENTRY_SIZE 2 #define MULTADD(x,z,p,ax,az,q,bx,bz,pb) C_MULTADD(x,z,p,ax,az,q,bx,bz,pb) #define MULT(x,z,p,ax,az,q,bx,bz,pb) C_MULT(x,z,p,ax,az,q,bx,bz,pb) #define ADD(x,z,p,ax,az,q,bx,bz,pb) C_ADD(x,z,p,ax,az,q,bx,bz,pb) #define ADD_REAL(x,p, ax,q, bx,r) C_ADD_REAL(x,p, ax,q, bx,r) #define MULTSUB(x,z,p,ax,az,q,bx,bz,pb) C_MULTSUB(x,z,p,ax,az,q,bx,bz,pb) #define MULTADDCONJ(x,z,p,ax,az,q,bx,bz,pb) \ C_MULTADDCONJ(x,z,p,ax,az,q,bx,bz,pb) #define MULTSUBCONJ(x,z,p,ax,az,q,bx,bz,pb) \ C_MULTSUBCONJ(x,z,p,ax,az,q,bx,bz,pb) #define LLDOT(x,p,ax,az,q) C_LLDOT(x,p,ax,az,q) #define CLEAR(x,z,p) C_CLEAR(x,z,p) #define CLEAR_IMAG(x,z,p) C_CLEAR_IMAG(x,z,p) #ifdef SINGLE #define DIV(x,z,p,ax,az,q) C_S_DIV(x,z,p,ax,az,q) #else #define DIV(x,z,p,ax,az,q) C_DIV(x,z,p,ax,az,q) #endif #define DIV_REAL(x,z,p, ax,az,q, bx,r) C_DIV_REAL(x,z,p, ax,az,q, bx,r) #define MULT_REAL(x,z,p, ax,az,q, bx,r) C_MULT_REAL(x,z,p, ax,az,q, bx,r) #define LDLDOT(x,p, ax,az,q, bx,r) C_LDLDOT(x,p, ax,az,q, bx,r) #define XPRINT0(x,z,p) C_PRINT(0,x,z,p) #define XPRINT1(x,z,p) C_PRINT(1,x,z,p) #define XPRINT2(x,z,p) C_PRINT(2,x,z,p) #define XPRINT3(x,z,p) C_PRINT(3,x,z,p) #elif defined (ZOMPLEX) //-------------------------------------------------------------------------- // zomplex: both double and single //-------------------------------------------------------------------------- #ifdef SINGLE #define PREFIX zs_ #ifdef NCONJUGATE // non-conjugate #define TEMPLATE(name) ZS_T_TEMPLATE(name) #define TEMPLATE2(name) CS_T_TEMPLATE(name) #else // conjugate #define TEMPLATE(name) ZS_TEMPLATE(name) #define TEMPLATE2(name) CS_TEMPLATE(name) #endif #else #define PREFIX zd_ #ifdef NCONJUGATE // non-conjugate #define TEMPLATE(name) ZD_T_TEMPLATE(name) #define TEMPLATE2(name) CD_T_TEMPLATE(name) #else #define TEMPLATE(name) ZD_TEMPLATE(name) #define TEMPLATE2(name) CD_TEMPLATE(name) #endif #endif #define ABS(ax,az,p) Z_ABS(ax,az,p) #define ASSEMBLE(x,z,p,ax,az,q) Z_ASSEMBLE(x,z,p,ax,az,q) #define ASSIGN(x,z,p,ax,az,q) Z_ASSIGN(x,z,p,ax,az,q) #define ASSIGN_CONJ(x,z,p,ax,az,q) Z_ASSIGN_CONJ(x,z,p,ax,az,q) #define ASSIGN2(x,z,p,ax,az,q) Z_ASSIGN(x,z,p,ax,az,q) #define ASSIGN2_CONJ(x,z,p,ax,az,q) Z_ASSIGN_CONJ(x,z,p,ax,az,q) #define ASSIGN_REAL(x,p,ax,q) Z_ASSIGN_REAL(x,p,ax,q) #define XTYPE CHOLMOD_ZOMPLEX #define XTYPE2 CHOLMOD_ZOMPLEX #define XTYPE_OK(type) Z_XTYPE_OK(type) #define ENTRY_IS_NONZERO(ax,az,q) Z_IS_NONZERO(ax,az,q) #define ENTRY_IS_ZERO(ax,az,q) Z_IS_ZERO(ax,az,q) #define ENTRY_IS_ONE(ax,az,q) Z_IS_ONE(ax,az,q) #define IMAG_IS_NONZERO(ax,az,q) Z_IMAG_IS_NONZERO(ax,az,q) #define ENTRY_SIZE 1 #define MULTADD(x,z,p,ax,az,q,bx,bz,pb) Z_MULTADD(x,z,p,ax,az,q,bx,bz,pb) #define MULT(x,z,p,ax,az,q,bx,bz,pb) Z_MULT(x,z,p,ax,az,q,bx,bz,pb) #define ADD(x,z,p,ax,az,q,bx,bz,pb) Z_ADD(x,z,p,ax,az,q,bx,bz,pb) #define ADD_REAL(x,p, ax,q, bx,r) Z_ADD_REAL(x,p, ax,q, bx,r) #define MULTSUB(x,z,p,ax,az,q,bx,bz,pb) Z_MULTSUB(x,z,p,ax,az,q,bx,bz,pb) #define MULTADDCONJ(x,z,p,ax,az,q,bx,bz,pb) \ Z_MULTADDCONJ(x,z,p,ax,az,q,bx,bz,pb) #define MULTSUBCONJ(x,z,p,ax,az,q,bx,bz,pb) \ Z_MULTSUBCONJ(x,z,p,ax,az,q,bx,bz,pb) #define LLDOT(x,p,ax,az,q) Z_LLDOT(x,p,ax,az,q) #define CLEAR(x,z,p) Z_CLEAR(x,z,p) #define CLEAR_IMAG(x,z,p) Z_CLEAR_IMAG(x,z,p) #ifdef SINGLE #define DIV(x,z,p,ax,az,q) Z_S_DIV(x,z,p,ax,az,q) #else #define DIV(x,z,p,ax,az,q) Z_DIV(x,z,p,ax,az,q) #endif #define DIV_REAL(x,z,p, ax,az,q, bx,r) Z_DIV_REAL(x,z,p, ax,az,q, bx,r) #define MULT_REAL(x,z,p, ax,az,q, bx,r) Z_MULT_REAL(x,z,p, ax,az,q, bx,r) #define LDLDOT(x,p, ax,az,q, bx,r) Z_LDLDOT(x,p, ax,az,q, bx,r) #define XPRINT0(x,z,p) Z_PRINT(0,x,z,p) #define XPRINT1(x,z,p) Z_PRINT(1,x,z,p) #define XPRINT2(x,z,p) Z_PRINT(2,x,z,p) #define XPRINT3(x,z,p) Z_PRINT(3,x,z,p) #endif //------------------------------------------------------------------------------ // conjugate/non-conjugate assignment (for pattern/real/complex/zomplex) //------------------------------------------------------------------------------ #ifdef NCONJUGATE // non-conjugate assign #define ASSIGN_CONJ_OR_NCONJ(x,z,p,ax,az,q) ASSIGN(x,z,p,ax,az,q) #else // conjugate assign #define ASSIGN_CONJ_OR_NCONJ(x,z,p,ax,az,q) ASSIGN_CONJ(x,z,p,ax,az,q) #endif //------------------------------------------------------------------------------ // macros for finding untested code (for developent only) //------------------------------------------------------------------------------ // These macros are xtype and/or dtype-type specific versions of the GOTCHA // macro #defined in cholmod_internal.h. #if 0 #undef PI_GOTCHA #undef PL_GOTCHA #undef PDI_GOTCHA #undef RDI_GOTCHA #undef CDI_GOTCHA #undef ZDI_GOTCHA #undef PDL_GOTCHA #undef RDL_GOTCHA #undef CDL_GOTCHA #undef ZDL_GOTCHA #undef PSI_GOTCHA #undef RSI_GOTCHA #undef CSI_GOTCHA #undef ZSI_GOTCHA #undef PSL_GOTCHA #undef RSL_GOTCHA #undef CSL_GOTCHA #undef ZSL_GOTCHA #ifdef DOUBLE #ifdef CHOLMOD_INT64 #if defined ( PATTERN ) #define PL_GOTCHA GOTCHA #define PDL_GOTCHA GOTCHA #elif defined ( REAL ) #define RDL_GOTCHA GOTCHA #elif defined ( COMPLEX ) #define CDL_GOTCHA GOTCHA #elif defined ( ZOMPLEX ) #define ZDL_GOTCHA GOTCHA #endif #else #if defined ( PATTERN ) #define PI_GOTCHA GOTCHA #define PDI_GOTCHA GOTCHA #elif defined ( REAL ) #define RDI_GOTCHA GOTCHA #elif defined ( COMPLEX ) #define CDI_GOTCHA GOTCHA #elif defined ( ZOMPLEX ) #define ZDI_GOTCHA GOTCHA #endif #endif #else #ifdef CHOLMOD_INT64 #if defined ( PATTERN ) #define PL_GOTCHA GOTCHA #define PSL_GOTCHA GOTCHA #elif defined ( REAL ) #define RSL_GOTCHA GOTCHA #elif defined ( COMPLEX ) #define CSL_GOTCHA GOTCHA #elif defined ( ZOMPLEX ) #define ZSL_GOTCHA GOTCHA #endif #else #if defined ( PATTERN ) #define PI_GOTCHA GOTCHA #define PSI_GOTCHA GOTCHA #elif defined ( REAL ) #define RSI_GOTCHA GOTCHA #elif defined ( COMPLEX ) #define CSI_GOTCHA GOTCHA #elif defined ( ZOMPLEX ) #define ZSI_GOTCHA GOTCHA #endif #endif #endif #ifndef PI_GOTCHA #define PI_GOTCHA ; #endif #ifndef PL_GOTCHA #define PL_GOTCHA ; #endif #ifndef PDI_GOTCHA #define PDI_GOTCHA ; #endif #ifndef RDI_GOTCHA #define RDI_GOTCHA ; #endif #ifndef CDI_GOTCHA #define CDI_GOTCHA ; #endif #ifndef ZDI_GOTCHA #define ZDI_GOTCHA ; #endif #ifndef PDL_GOTCHA #define PDL_GOTCHA ; #endif #ifndef RDL_GOTCHA #define RDL_GOTCHA ; #endif #ifndef CDL_GOTCHA #define CDL_GOTCHA ; #endif #ifndef ZDL_GOTCHA #define ZDL_GOTCHA ; #endif #ifndef PSI_GOTCHA #define PSI_GOTCHA ; #endif #ifndef RSI_GOTCHA #define RSI_GOTCHA ; #endif #ifndef CSI_GOTCHA #define CSI_GOTCHA ; #endif #ifndef ZSI_GOTCHA #define ZSI_GOTCHA ; #endif #ifndef PSL_GOTCHA #define PSL_GOTCHA ; #endif #ifndef RSL_GOTCHA #define RSL_GOTCHA ; #endif #ifndef CSL_GOTCHA #define CSL_GOTCHA ; #endif #ifndef ZSL_GOTCHA #define ZSL_GOTCHA ; #endif #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/������������������������������������������������������������0000755�0001751�0000144�00000000000�14576344041�017450� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_solve.c���������������������������������������������0000644�0001751�0000144�00000072111�14552026002�022437� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_solve: solve a linear system //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Solve one of the following systems. D is identity for an LL' factorization, // in which the D operation is skipped: // // Ax=b 0: CHOLMOD_A x = P' * (L' \ (D \ (L \ (P * b)))) // LDL'x=b 1: CHOLMOD_LDLt x = (L' \ (D \ (L \ ( b)))) // LDx=b 2: CHOLMOD_LD x = ( (D \ (L \ ( b)))) // DL'x=b 3: CHOLMOD_DLt x = (L' \ (D \ ( ( b)))) // Lx=b 4: CHOLMOD_L x = ( ( (L \ ( b)))) // L'x=b 5: CHOLMOD_Lt x = (L' \ ( ( ( b)))) // Dx=b 6: CHOLMOD_D x = ( (D \ ( ( b)))) // x=Pb 7: CHOLMOD_P x = ( ( ( (P * b)))) // x=P'b 8: CHOLMOD_Pt x = P' * ( ( ( ( b)))) // // The factorization can be simplicial LDL', simplicial LL', or supernodal LL'. // For an LL' factorization, D is the identity matrix. Thus CHOLMOD_LD and // CHOLMOD_L solve the same system if an LL' factorization was performed, // for example. // // The supernodal solver uses BLAS routines: // // dtrsv, dgemv, dtrsm, dgemm: double real // ztrsv, zgemv, ztrsm, zgemm: double complex // strsv, sgemv, strsm, sgemm: float real // ctrsv, cgemv, ctrsm, cgemm: float complex // // If both L and B are real, then X is returned real. If either is complex // or zomplex, X is returned as either complex or zomplex, depending on the // Common->prefer_zomplex parameter. // // Supports any numeric xtype (real, complex, or zomplex; pattern-only matrices // not supported), and any dtype. // // This routine does not check to see if the diagonal of L or D is zero, // because sometimes a partial solve can be done with indefinite or singular // matrix. If you wish to check in your own code, test L->minor. If L->minor // == L->n, then the matrix has no zero diagonal entries. If k = L->minor < // L->n, then L(k,k) is zero for an LL' factorization, or D(k,k) is zero for an // LDL' factorization. // // This routine returns X as NULL only if it runs out of memory. If L is // indefinite or singular, then X may contain Inf's or NaN's, but it will exist // on output. #include "cholmod_internal.h" #ifndef NCHOLESKY //------------------------------------------------------------------------------ // P(k): permutation macro for t_cholmod_*_worker methods //------------------------------------------------------------------------------ // If Perm is NULL, it is interpretted as the identity permutation #define P(k) ((Perm == NULL) ? (k) : Perm [k]) //------------------------------------------------------------------------------ // t_cholmod_solve_worker //------------------------------------------------------------------------------ #define DOUBLE #include "t_cholmod_psolve_worker.c" #define REAL #include "t_cholmod_solve_worker.c" #define COMPLEX #include "t_cholmod_solve_worker.c" #define ZOMPLEX #include "t_cholmod_solve_worker.c" #undef DOUBLE #define SINGLE #include "t_cholmod_psolve_worker.c" #define REAL #include "t_cholmod_solve_worker.c" #define COMPLEX #include "t_cholmod_solve_worker.c" #define ZOMPLEX #include "t_cholmod_solve_worker.c" //------------------------------------------------------------------------------ // cholmod_solve //------------------------------------------------------------------------------ // Solve a linear system. // // The factorization can be simplicial LDL', simplicial LL', or supernodal LL'. // The Dx=b solve returns silently for the LL' factorizations (it is implicitly // identity). cholmod_dense *CHOLMOD(solve) // returns solution X ( // input: int sys, // system to solve cholmod_factor *L, // factorization to use cholmod_dense *B, // right-hand-side cholmod_common *Common ) { cholmod_dense *Y = NULL, *X = NULL, *E = NULL ; // do the solve, allocating workspaces as needed int ok = CHOLMOD (solve2) (sys, L, B, NULL, &X, NULL, &Y, &E, Common) ; // free workspaces if allocated, and free result if an error occured CHOLMOD(free_dense) (&Y, Common) ; CHOLMOD(free_dense) (&E, Common) ; if (!ok) { CHOLMOD(free_dense) (&X, Common) ; } return (X) ; } //------------------------------------------------------------------------------ // cholmod_solve2 //------------------------------------------------------------------------------ // This function acts just like cholmod_solve, except that the solution X and // the internal workspace (Y and E) can be passed in preallocated. If the // solution X or any required workspaces are not allocated on input, or if they // are the wrong size or type, then this function frees them and reallocates // them as the proper size and type. Thus, if you have a sequence of solves to // do, you can let this function allocate X, Y, and E on the first call. // Subsequent calls to cholmod_solve2 can then reuse this space. You must then // free the workspaces Y and E (and X if desired) when you are finished. For // example, the first call to cholmod_l_solve2, below, will solve the requested // system. The next 2 calls (with different right-hand-sides but the same // value of "sys") will resuse the workspace and solution X from the first // call. Finally, when all solves are done, you must free the workspaces Y and // E (otherwise you will have a memory leak), and you should also free X when // you are done with it. Note that on input, X, Y, and E must be either valid // cholmod_dense matrices, or initialized to NULL. You cannot pass in an // uninitialized X, Y, or E. // // cholmod_dense *X = NULL, *Y = NULL, *E = NULL ; // ... // cholmod_l_solve2 (sys, L, B1, NULL, &X, NULL, &Y, &E, Common) ; // cholmod_l_solve2 (sys, L, B2, NULL, &X, NULL, &Y, &E, Common) ; // cholmod_l_solve2 (sys, L, B3, NULL, &X, NULL, &Y, &E, Common) ; // cholmod_l_free_dense (&X, Common) ; // cholmod_l_free_dense (&Y, Common) ; // cholmod_l_free_dense (&E, Common) ; // // The equivalent when using cholmod_l_solve is: // // cholmod_dense *X = NULL, *Y = NULL, *E = NULL ; // ... // X = cholmod_l_solve (sys, L, B1, Common) ; // cholmod_l_free_dense (&X, Common) ; // X = cholmod_l_solve (sys, L, B2, Common) ; // cholmod_l_free_dense (&X, Common) ; // X = cholmod_l_solve (sys, L, B3, Common) ; // cholmod_l_free_dense (&X, Common) ; // // Both methods work fine, but in the 2nd method with cholmod_solve, the // internal workspaces (Y and E) are allocated and freed on each call. // // Bset is an optional sparse column (pattern only) that specifies a set of row // indices. It is ignored if NULL, or if sys is CHOLMOD_P or CHOLMOD_Pt. If // it is present and not ignored, B must be a dense column vector, and only // entries B(i) where i is in the pattern of Bset are considered. All others // are treated as if they were zero (they are not accessed). L must be a // simplicial factorization, not supernodal. L is converted from supernodal to // simplicial if necessary. The solution X is defined only for entries in the // output sparse pattern of Xset. The xtype (real/complex/zomplex) of L and B // must match. // // NOTE: If Bset is present and L is supernodal, it is converted to simplicial // on output. int CHOLMOD(solve2) // returns TRUE on success, FALSE on failure ( // input: int sys, // system to solve cholmod_factor *L, // factorization to use cholmod_dense *B, // right-hand-side cholmod_sparse *Bset, // output: cholmod_dense **X_Handle, // solution, allocated if need be cholmod_sparse **Xset_Handle, // workspace: cholmod_dense **Y_Handle, // workspace, or NULL cholmod_dense **E_Handle, // workspace, or NULL cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- cholmod_dense *Y = NULL, *X = NULL ; cholmod_sparse *C, *Yset, C_header, Yset_header, *Xset ; Int *Perm = NULL, *IPerm = NULL ; Int n, nrhs, ncols, k1, nr, ytype, k, blen, p, d, nrow ; Int Cp [2], Ysetp [2], *Ci, *Yseti ; RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (L, FALSE) ; RETURN_IF_NULL (B, FALSE) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (B, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ; if (sys < CHOLMOD_A || sys > CHOLMOD_Pt) { ERROR (CHOLMOD_INVALID, "invalid system") ; return (FALSE) ; } if (L->dtype != B->dtype) { ERROR (CHOLMOD_INVALID, "dtype of L and B must match") ; return (FALSE) ; } DEBUG (CHOLMOD(dump_factor) (L, "L", Common)) ; DEBUG (CHOLMOD(dump_dense) (B, "B", Common)) ; nrhs = B->ncol ; n = (Int) L->n ; d = (Int) B->d ; nrow = (Int) B->nrow ; if (d < n || nrow != n) { ERROR (CHOLMOD_INVALID, "dimensions of L and B do not match") ; return (FALSE) ; } if (sys == CHOLMOD_P || sys == CHOLMOD_Pt) { // Bset is ignored when solving Px=b or P'x=b Bset = NULL ; } if (Bset) { if (nrhs != 1) { ERROR (CHOLMOD_INVALID, "Bset requires a single right-hand side") ; return (FALSE) ; } if (L->xtype != B->xtype) { ERROR (CHOLMOD_INVALID, "Bset requires xtype of L and B to match") ; return (FALSE) ; } DEBUG (CHOLMOD(dump_sparse) (Bset, "Bset", Common)) ; } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- if ((sys == CHOLMOD_P || sys == CHOLMOD_Pt || sys == CHOLMOD_A) && L->ordering != CHOLMOD_NATURAL) { // otherwise, Perm is NULL, and the identity permutation is used Perm = L->Perm ; } //-------------------------------------------------------------------------- // allocate the result X (or resuse the space from a prior call) //-------------------------------------------------------------------------- int ctype = (Common->prefer_zomplex) ? CHOLMOD_ZOMPLEX : CHOLMOD_COMPLEX ; int X_xtype ; if (Bset) { X_xtype = L->xtype ; } else if (sys == CHOLMOD_P || sys == CHOLMOD_Pt) { // x=Pb and x=P'b return X real if B is real; X is the preferred // complex/zcomplex type if B is complex or zomplex X_xtype = (B->xtype == CHOLMOD_REAL) ? CHOLMOD_REAL : ctype ; } else if (L->xtype == CHOLMOD_REAL && B->xtype == CHOLMOD_REAL) { // X is real if both L and B are real X_xtype = CHOLMOD_REAL ; } else { // X is complex, use the preferred complex/zomplex type X_xtype = ctype ; } // ensure X has the right size and type X = CHOLMOD(ensure_dense) (X_Handle, n, nrhs, n, X_xtype + L->dtype, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } //-------------------------------------------------------------------------- // solve using L, D, L', P, or some combination //-------------------------------------------------------------------------- if (Bset) { //---------------------------------------------------------------------- // solve for a subset of x, with a sparse b //---------------------------------------------------------------------- #ifndef NSUPERNODAL // convert a supernodal L to simplicial when using Bset if (L->is_super) { // Can only use Bset on a simplicial factorization. The supernodal // factor L is converted to simplicial, leaving the xtype unchanged // (real, complex, or zomplex). Since the supernodal factorization // is already LL', it is left in that form. This conversion uses // the super_num_to_simplicial_num function in // cholmod_change_factor. CHOLMOD(change_factor) ( CHOLMOD_REAL, // ignored, since L is already numeric TRUE, // convert to LL' (no change to num. values) FALSE, // convert to simplicial FALSE, // do not pack the columns of L FALSE, // (ignored) L, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory, L is returned unchanged return (FALSE) ; } } #endif // L, X, and B are all the same xtype // ensure Y is the the right size Y = CHOLMOD(ensure_dense) (Y_Handle, 1, n, 1, L->xtype + L->dtype, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (FALSE) ; } //---------------------------------------------------------------------- // get the inverse permutation, constructing it if needed //---------------------------------------------------------------------- DEBUG (CHOLMOD (dump_perm) (Perm, n,n, "Perm", Common)) ; if ((sys == CHOLMOD_A || sys == CHOLMOD_P) && Perm != NULL) { // The inverse permutation IPerm is used for the c=Pb step, // which is needed only for solving Ax=b or x=Pb. No other // steps should use IPerm if (L->IPerm == NULL) { // construct the inverse permutation. This is done only once // and then stored in L permanently. L->IPerm = CHOLMOD(malloc) (n, sizeof (Int), Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (FALSE) ; } IPerm = L->IPerm ; for (k = 0 ; k < n ; k++) { IPerm [Perm [k]] = k ; } } // x=A\b and x=Pb both need IPerm IPerm = L->IPerm ; } DEBUG (CHOLMOD (dump_perm) (Perm, n,n, "Perm", Common)) ; DEBUG (CHOLMOD (dump_perm) (IPerm, n,n, "IPerm", Common)) ; //---------------------------------------------------------------------- // ensure Xset is the right size and type //---------------------------------------------------------------------- // Xset is n-by-1, nzmax >= n, pattern-only, packed, unsorted Xset = *Xset_Handle ; if (Xset == NULL || (Int) Xset->nrow != n || (Int) Xset->ncol != 1 || (Int) Xset->nzmax < n || Xset->itype != CHOLMOD_PATTERN) { // this is done only once, for the 1st call to cholmod_solve CHOLMOD(free_sparse) (Xset_Handle, Common) ; Xset = CHOLMOD(allocate_sparse) (n, 1, n, FALSE, TRUE, 0, CHOLMOD_PATTERN + L->dtype, Common) ; (*Xset_Handle) = Xset ; } if (Common->status < CHOLMOD_OK) { // out of memory return (FALSE) ; } Xset->sorted = FALSE ; Xset->stype = 0 ; //---------------------------------------------------------------------- // ensure Flag of size n, and 3*n Int workspace is available //---------------------------------------------------------------------- // does no work if prior calls already allocated enough space CHOLMOD(allocate_work) (n, 3*n, 0, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (FALSE) ; } // [ use Iwork (n:3n-1) for Ci and Yseti Int *Iwork = Common->Iwork ; // Iwork (0:n-1) is not used because it is used by check_perm, // print_perm, check_sparse, and print_sparse Ci = Iwork + n ; Yseti = Ci + n ; // reallocating workspace would break Ci and Yseti int save_realloc_state = Common->no_workspace_reallocate ; Common->no_workspace_reallocate = TRUE ; //---------------------------------------------------------------------- // C = permuted Bset, to correspond to the permutation of L //---------------------------------------------------------------------- // C = IPerm (Bset) DEBUG (CHOLMOD(dump_sparse) (Bset, "Bset", Common)) ; Int *Bsetp = Bset->p ; Int *Bseti = Bset->i ; Int *Bsetnz = Bset->nz ; blen = (Bset->packed) ? Bsetp [1] : Bsetnz [0] ; // C = spones (P*B) or C = spones (B) if IPerm is NULL C = &C_header ; C->nrow = n ; C->ncol = 1 ; C->nzmax = n ; C->packed = TRUE ; C->stype = 0 ; C->itype = ITYPE ; C->xtype = CHOLMOD_PATTERN ; C->dtype = L->dtype ; C->nz = NULL ; C->p = Cp ; C->i = Ci ; C->x = NULL ; C->z = NULL ; C->sorted = FALSE ; Cp [0] = 0 ; Cp [1] = blen ; for (p = 0 ; p < blen ; p++) { Int iold = Bseti [p] ; Ci [p] = IPerm ? IPerm [iold] : iold ; } DEBUG (CHOLMOD (dump_sparse) (C, "C", Common)) ; // create a sparse column Yset from Iwork (n:2n-1) Yset = &Yset_header ; Yset->nrow = n ; Yset->ncol = 1 ; Yset->nzmax = n ; Yset->packed = TRUE ; Yset->stype = 0 ; Yset->itype = ITYPE ; Yset->xtype = CHOLMOD_PATTERN ; Yset->dtype = L->dtype ; Yset->nz = NULL ; Yset->p = Ysetp ; Yset->i = Yseti ; Yset->x = NULL ; Yset->z = NULL ; Yset->sorted = FALSE ; Ysetp [0] = 0 ; Ysetp [1] = 0 ; DEBUG (CHOLMOD (dump_sparse) (Yset, "Yset empty", Common)) ; //---------------------------------------------------------------------- // Yset = nonzero pattern of L\C, or just C itself //---------------------------------------------------------------------- // this takes O(ysetlen) time int ok = true ; if (sys == CHOLMOD_P || sys == CHOLMOD_Pt || sys == CHOLMOD_D) { Ysetp [1] = blen ; for (p = 0 ; p < blen ; p++) { Yseti [p] = Ci [p] ; } } else { ok = CHOLMOD(lsolve_pattern) (C, L, Yset, Common) ; } if (ok) { DEBUG (CHOLMOD (dump_sparse) (Yset, "Yset", Common)) ; //------------------------------------------------------------------ // Y (C) = B (Bset) //------------------------------------------------------------------ switch ((L->xtype + L->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_bset_perm (B, Bset, Yset, C, Y) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_bset_perm (B, Bset, Yset, C, Y) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_bset_perm (B, Bset, Yset, C, Y) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_bset_perm (B, Bset, Yset, C, Y) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_bset_perm (B, Bset, Yset, C, Y) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_bset_perm (B, Bset, Yset, C, Y) ; break ; } DEBUG (CHOLMOD (dump_dense) (Y, "Y (C) = B (Bset)", Common)) ; //------------------------------------------------------------------ // solve Y = (L' \ (L \ Y'))', or other system, with template //------------------------------------------------------------------ // the solve only iterates over columns in Yseti [0...ysetlen-1] if (! (sys == CHOLMOD_P || sys == CHOLMOD_Pt)) { switch ((L->xtype + L->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_simplicial_solver (sys, L, Y, Yset) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_simplicial_solver (sys, L, Y, Yset) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_simplicial_solver (sys, L, Y, Yset) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_simplicial_solver (sys, L, Y, Yset) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_simplicial_solver (sys, L, Y, Yset) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_simplicial_solver (sys, L, Y, Yset) ; break ; } } DEBUG (CHOLMOD (dump_dense) (Y, "Y after solve", Common)) ; //------------------------------------------------------------------ // X = P'*Y, but only for rows in Yset, and create Xset //------------------------------------------------------------------ switch ((L->xtype + L->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_bset_iperm (Y, Yset, Perm, X, Xset) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_bset_iperm (Y, Yset, Perm, X, Xset) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_bset_iperm (Y, Yset, Perm, X, Xset) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_bset_iperm (Y, Yset, Perm, X, Xset) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_bset_iperm (Y, Yset, Perm, X, Xset) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_bset_iperm (Y, Yset, Perm, X, Xset) ; break ; } DEBUG (CHOLMOD(dump_sparse) (Xset, "Xset", Common)) ; DEBUG (CHOLMOD(dump_dense) (X, "X", Common)) ; } Common->no_workspace_reallocate = save_realloc_state ; // done using Iwork (n:3n-1) for Ci and Yseti ] } else if (sys == CHOLMOD_P) { //---------------------------------------------------------------------- // x = P*b //---------------------------------------------------------------------- if (L->dtype == CHOLMOD_DOUBLE) { d_perm (B, Perm, 0, nrhs, X) ; } else { s_perm (B, Perm, 0, nrhs, X) ; } } else if (sys == CHOLMOD_Pt) { //---------------------------------------------------------------------- // x = P'*b //---------------------------------------------------------------------- if (L->dtype == CHOLMOD_DOUBLE) { d_iperm (B, Perm, 0, nrhs, X) ; } else { s_iperm (B, Perm, 0, nrhs, X) ; } } else if (L->is_super) { //---------------------------------------------------------------------- // solve using a supernodal LL' factorization //---------------------------------------------------------------------- #ifndef NSUPERNODAL // allocate workspace cholmod_dense *E ; size_t dual ; Common->blas_ok = TRUE ; dual = (L->xtype == CHOLMOD_REAL && B->xtype != CHOLMOD_REAL) ? 2 : 1 ; Y = CHOLMOD(ensure_dense) (Y_Handle, n, dual*nrhs, n, L->xtype + L->dtype, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (FALSE) ; } E = CHOLMOD(ensure_dense) (E_Handle, dual*nrhs, L->maxesize, dual*nrhs, L->xtype + L->dtype, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (FALSE) ; } if (L->dtype == CHOLMOD_DOUBLE) { d_perm (B, Perm, 0, nrhs, Y) ; // Y = P*B } else { s_perm (B, Perm, 0, nrhs, Y) ; // Y = P*B } if (sys == CHOLMOD_A || sys == CHOLMOD_LDLt) { CHOLMOD(super_lsolve) (L, Y, E, Common) ; // Y = L\Y CHOLMOD(super_ltsolve) (L, Y, E, Common) ; // Y = L'\Y } else if (sys == CHOLMOD_L || sys == CHOLMOD_LD) { CHOLMOD(super_lsolve) (L, Y, E, Common) ; // Y = L\Y } else if (sys == CHOLMOD_Lt || sys == CHOLMOD_DLt) { CHOLMOD(super_ltsolve) (L, Y, E, Common) ; // Y = L'\Y } if (L->dtype == CHOLMOD_DOUBLE) { d_iperm (Y, Perm, 0, nrhs, X) ; // X = P'*Y } else { s_iperm (Y, Perm, 0, nrhs, X) ; // X = P'*Y } #else // CHOLMOD Supernodal module not installed ERROR (CHOLMOD_NOT_INSTALLED,"Supernodal module not installed") ; #endif } else { //---------------------------------------------------------------------- // solve using a simplicial LL' or LDL' factorization //---------------------------------------------------------------------- if (L->xtype == CHOLMOD_REAL && B->xtype == CHOLMOD_REAL) { // L, B, and Y are all real // solve with up to 4 columns of B at a time ncols = 4 ; nr = MAX (4, nrhs) ; ytype = CHOLMOD_REAL ; } else if (L->xtype == CHOLMOD_REAL) { // L is real and B is complex or zomplex // solve with one column of B (real/imag), at a time ncols = 1 ; nr = 2 ; ytype = CHOLMOD_REAL ; } else { // L is complex or zomplex, B is real/complex/zomplex, Y has the // same complexity as L. Solve with one column of B at a time. ncols = 1 ; nr = 1 ; ytype = L->xtype ; } Y = CHOLMOD(ensure_dense) (Y_Handle, nr, n, nr, ytype + L->dtype, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (FALSE) ; } for (k1 = 0 ; k1 < nrhs ; k1 += ncols) { //------------------------------------------------------------------ // Y = B (P, k1:k1+ncols-1)' = (P * B (:,...))' //------------------------------------------------------------------ if (L->dtype == CHOLMOD_DOUBLE) { d_ptrans (B, Perm, k1, ncols, Y) ; } else { s_ptrans (B, Perm, k1, ncols, Y) ; } //------------------------------------------------------------------ // solve Y = (L' \ (L \ Y'))', or other system, with template //------------------------------------------------------------------ switch ((L->xtype + L->dtype) % 8) { case CHOLMOD_SINGLE + CHOLMOD_REAL: rs_simplicial_solver (sys, L, Y, NULL) ; break ; case CHOLMOD_SINGLE + CHOLMOD_COMPLEX: cs_simplicial_solver (sys, L, Y, NULL) ; break ; case CHOLMOD_SINGLE + CHOLMOD_ZOMPLEX: zs_simplicial_solver (sys, L, Y, NULL) ; break ; case CHOLMOD_DOUBLE + CHOLMOD_REAL: rd_simplicial_solver (sys, L, Y, NULL) ; break ; case CHOLMOD_DOUBLE + CHOLMOD_COMPLEX: cd_simplicial_solver (sys, L, Y, NULL) ; break ; case CHOLMOD_DOUBLE + CHOLMOD_ZOMPLEX: zd_simplicial_solver (sys, L, Y, NULL) ; break ; } //------------------------------------------------------------------ // X (P, k1:k2+ncols-1) = Y' //------------------------------------------------------------------ if (L->dtype == CHOLMOD_DOUBLE) { d_iptrans (Y, Perm, k1, ncols, X) ; } else { s_iptrans (Y, Perm, k1, ncols, X) ; } } } DEBUG (CHOLMOD(dump_dense) (X, "X result", Common)) ; return (Common->status == CHOLMOD_OK) ; } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_solve_worker.c������������������������������������0000644�0001751�0000144�00000020770�14552026002�024357� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/t_cholmod_solve: template for cholmod_solve //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Template routine for cholmod_solve. Supports any numeric xtype (real, // complex, or zomplex). The xtypes of all matrices (L and Y) must match. #include "cholmod_template.h" //------------------------------------------------------------------------------ // simplicial template solvers //------------------------------------------------------------------------------ // LL': solve Lx=b with non-unit diagonal #define LL #include "t_cholmod_lsolve_template.c" // LDL': solve LDx=b #define LD #include "t_cholmod_lsolve_template.c" // LDL': solve Lx=b with unit diagonal #include "t_cholmod_lsolve_template.c" // LL': solve L'x=b with non-unit diagonal #define LL #include "t_cholmod_ltsolve_template.c" // LDL': solve DL'x=b #define LD #include "t_cholmod_ltsolve_template.c" // LDL': solve L'x=b with unit diagonal #include "t_cholmod_ltsolve_template.c" //------------------------------------------------------------------------------ // t_ldl_dsolve //------------------------------------------------------------------------------ // Solve Dx=b for an LDL' factorization, where Y holds b' on input and x' on // output. // // The number of right-hand-sides (nrhs) is not restricted, even if Yset // is present. static void TEMPLATE (ldl_dsolve) ( cholmod_factor *L, cholmod_dense *Y, // nr-by-n with leading dimension nr cholmod_sparse *Yset // input pattern Yset ) { ASSERT (L->xtype == Y->xtype) ; // L and Y must have the same xtype ASSERT (L->dtype == Y->dtype) ; // L and Y must have the same dtype ASSERT (L->n == Y->ncol) ; // dimensions must match ASSERT (Y->nrow == Y->d) ; // leading dimension of Y = # rows of Y ASSERT (L->xtype != CHOLMOD_PATTERN) ; // L is not symbolic ASSERT (!(L->is_super) && !(L->is_ll)) ; // L is simplicial LDL' Real d [1] ; Int nrhs = Y->nrow ; Int n = L->n ; Int *Lp = L->p ; Real *Lx = L->x ; Real *Yx = Y->x ; #ifdef ZOMPLEX Real *Yz = Y->z ; #endif if (Yset) { Int *Yseti = Yset->i ; Int *Ysetp = Yset->p ; Int ysetlen = Ysetp [1] ; for (Int kk = 0 ; kk < ysetlen ; kk++) { Int k = Yseti [kk] ; Int k1 = k*nrhs ; Int k2 = (k+1)*nrhs ; // d = L (k,k) ASSIGN_REAL (d,0, Lx,Lp[k]) ; for (Int p = k1 ; p < k2 ; p++) { // Y (p) = Y (p) / d DIV_REAL (Yx,Yz,p, Yx,Yz,p, d,0) ; } } } else { for (Int k = 0 ; k < n ; k++) { Int k1 = k*nrhs ; Int k2 = (k+1)*nrhs ; // d = L (k,k) ASSIGN_REAL (d,0, Lx,Lp[k]) ; for (Int p = k1 ; p < k2 ; p++) { // Y (p) = Y (p) / d DIV_REAL (Yx,Yz,p, Yx,Yz,p, d,0) ; } } } } //------------------------------------------------------------------------------ // t_simplicial_solver //------------------------------------------------------------------------------ // Solve a linear system, where Y' contains the (array-transposed) right-hand // side on input, and the solution on output. No permutations are applied; // these must have already been applied to Y on input. // // Yset is an optional list of indices from cholmod_lsolve_pattern. The solve // is performed only on the columns of L corresponding to entries in Yset. // Ignored if NULL. If present, most functions require that Y' consist of a // single dense column. static void TEMPLATE (simplicial_solver) ( int sys, // system to solve cholmod_factor *L, // factor to use, a simplicial LL' or LDL' cholmod_dense *Y, // right-hand-side on input, solution on output cholmod_sparse *Yset // input pattern Yset ) { if (L->is_ll) { // The factorization is LL' if (sys == CHOLMOD_A || sys == CHOLMOD_LDLt) { // Solve Ax=b or LL'x=b TEMPLATE (ll_lsolve_k) (L, Y, Yset) ; TEMPLATE (ll_ltsolve_k) (L, Y, Yset) ; } else if (sys == CHOLMOD_L || sys == CHOLMOD_LD) { // Solve Lx=b TEMPLATE (ll_lsolve_k) (L, Y, Yset) ; } else if (sys == CHOLMOD_Lt || sys == CHOLMOD_DLt) { // Solve L'x=b TEMPLATE (ll_ltsolve_k) (L, Y, Yset) ; } } else { // The factorization is LDL' if (sys == CHOLMOD_A || sys == CHOLMOD_LDLt) { // Solve Ax=b or LDL'x=b TEMPLATE (ldl_lsolve_k) (L, Y, Yset) ; TEMPLATE (ldl_dltsolve_k) (L, Y, Yset) ; } else if (sys == CHOLMOD_LD) { // Solve LDx=b TEMPLATE (ldl_ldsolve_k) (L, Y, Yset) ; } else if (sys == CHOLMOD_L) { // Solve Lx=b TEMPLATE (ldl_lsolve_k) (L, Y, Yset) ; } else if (sys == CHOLMOD_Lt) { // Solve L'x=b TEMPLATE (ldl_ltsolve_k) (L, Y, Yset) ; } else if (sys == CHOLMOD_DLt) { // Solve DL'x=b TEMPLATE (ldl_dltsolve_k) (L, Y, Yset) ; } else if (sys == CHOLMOD_D) { // Solve Dx=b TEMPLATE (ldl_dsolve) (L, Y, Yset) ; } } } //------------------------------------------------------------------------------ // bset_perm //------------------------------------------------------------------------------ // Y (C) = B (Bset) static void TEMPLATE (bset_perm) ( // input: cholmod_dense *B, // input matrix B cholmod_sparse *Bset, // input pattern Bset cholmod_sparse *Yset, // input pattern Yset cholmod_sparse *C, // input pattern C // input/output: cholmod_dense *Y // output matrix Y, already allocated ) { //-------------------------------------------------------------------------- // clear the parts of Y that we will use in the solve //-------------------------------------------------------------------------- Real *Yx = Y->x ; #ifdef ZOMPLEX Real *Yz = Y->z ; #endif Int *Ysetp = Yset->p ; Int *Yseti = Yset->i ; Int ysetlen = Ysetp [1] ; for (Int p = 0 ; p < ysetlen ; p++) { Int i = Yseti [p] ; // Y (i) = 0 CLEAR (Yx, Yz, i) ; } //-------------------------------------------------------------------------- // scatter and permute B into Y //-------------------------------------------------------------------------- // Y (C) = B (Bset) Real *Bx = B->x ; #ifdef ZOMPLEX Real *Bz = B->z ; #endif Int *Bsetp = Bset->p ; Int *Bseti = Bset->i ; Int *Bsetnz = Bset->nz ; Int blen = (Bset->packed) ? Bsetp [1] : Bsetnz [0] ; Int *Ci = C->i ; for (Int p = 0 ; p < blen ; p++) { Int iold = Bseti [p] ; Int inew = Ci [p] ; // Y (inew) = B (iold) ASSIGN (Yx, Yz, inew, Bx, Bz, iold) ; } } //------------------------------------------------------------------------------ // bset_iperm //------------------------------------------------------------------------------ // X (P (Yset)) = Y (Yset) static void TEMPLATE (bset_iperm) ( // input: cholmod_dense *Y, // input matrix Y cholmod_sparse *Yset, // input pattern Yset Int *Perm, // optional input permutation (can be NULL) // input/output: cholmod_dense *X, // output matrix X, already allocated cholmod_sparse *Xset // output pattern Xset ) { Real *Xx = X->x ; #ifdef ZOMPLEX Real *Xz = X->z ; #endif Int *Xseti = Xset->i ; Int *Xsetp = Xset->p ; Real *Yx = Y->x ; #ifdef ZOMPLEX Real *Yz = Y->z ; #endif Int *Ysetp = Yset->p ; Int *Yseti = Yset->i ; Int ysetlen = Ysetp [1] ; for (Int p = 0 ; p < ysetlen ; p++) { Int inew = Yseti [p] ; Int iold = P(inew) ; // was: (Perm ? Perm [inew] : inew) ; // X (iold) = Y (inew) ASSIGN (Xx, Xz, iold, Yx, Yz, inew) ; Xseti [p] = iold ; } Xsetp [0] = 0 ; Xsetp [1] = ysetlen ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX ��������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_resymbol_worker.c���������������������������������0000644�0001751�0000144�00000014261�14552026002�025061� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/t_cholmod_resymbol_worker: recompute symbolic pattern of L //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_resymbol_worker) ( cholmod_sparse *A, bool pack, cholmod_factor *L, cholmod_common *Common ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int nrow = A->nrow ; Int *Ai = A->i ; Int *Ap = A->p ; Int *Anz = A->nz ; bool apacked = A->packed ; int stype = A->stype ; Int *Li = L->i ; Real *Lx = L->x ; #ifdef ZOMPLEX Real *Lz = L->z ; #endif Int *Lp = L->p ; Int *Lnz = L->nz ; Int *Flag = Common->Flag ; // size nrow Int *Head = Common->Head ; // size nrow+1 Int *Iwork = Common->Iwork ; Int *Link = Iwork ; // size nrow Int *Anext = Iwork + nrow ; // size ncol, unsym. only Int pdest = 0 ; //-------------------------------------------------------------------------- // resymbol //-------------------------------------------------------------------------- for (Int k = 0 ; k < nrow ; k++) { #ifndef NDEBUG PRINT1 (("\n\n================== Initial column k = "ID"\n", k)) ; for (Int p = Lp [k] ; p < Lp [k] + Lnz [k] ; p++) { PRINT1 ((" row: "ID" value: ", Li [p])) ; PRINT1 (("\n")) ; } PRINT1 (("Recomputing LDL, column k = "ID"\n", k)) ; #endif //---------------------------------------------------------------------- // compute column k of I+F*F' or I+A //---------------------------------------------------------------------- // flag the diagonal entry CLEAR_FLAG (Common) ; Int mark = Common->mark ; Flag [k] = mark ; PRINT1 (("row: "ID" (diagonal)\n", k)) ; if (stype != 0) { // merge column k of A into Flag (lower triangular part only) Int p = Ap [k] ; Int pend = (apacked) ? (Ap [k+1]) : (p + Anz [k]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; if (i > k) { Flag [i] = mark ; } } } else { // for each column j whos first row index is in row k for (Int j = Head [k] ; j != EMPTY ; j = Anext [j]) { // merge column j of A into Flag PRINT1 ((" ---- A column "ID"\n", j)) ; Int p = Ap [j] ; Int pend = (apacked) ? (Ap [j+1]) : (p + Anz [j]) ; PRINT1 ((" length "ID" adding\n", pend-p)) ; for ( ; p < pend ; p++) { #ifndef NDEBUG ASSERT (Ai [p] >= k && Ai [p] < nrow) ; if (Flag [Ai [p]] < mark) PRINT1 ((" row "ID"\n", Ai [p])) ; #endif Flag [Ai [p]] = mark ; } } // clear the kth link list Head [k] = EMPTY ; } //---------------------------------------------------------------------- // compute pruned pattern of kth column of L = union of children //---------------------------------------------------------------------- // for each column j of L whose parent is k for (Int j = Link [k] ; j != EMPTY ; j = Link [j]) { // merge column j of L into Flag PRINT1 ((" ---- L column "ID"\n", k)) ; ASSERT (j < k) ; ASSERT (Lnz [j] > 0) ; Int p = Lp [j] ; Int pend = p + Lnz [j] ; ASSERT (Li [p] == j && Li [p+1] == k) ; p++ ; // skip past the diagonal entry for ( ; p < pend ; p++) { // add to pattern ASSERT (Li [p] >= k && Li [p] < nrow) ; Flag [Li [p]] = mark ; } } //---------------------------------------------------------------------- // prune the kth column of L //---------------------------------------------------------------------- PRINT1 (("Final column of L:\n")) ; Int p = Lp [k] ; Int pend = p + Lnz [k] ; if (pack) { // shift column k upwards Lp [k] = pdest ; } else { // leave column k in place, just reduce Lnz [k] pdest = p ; } for ( ; p < pend ; p++) { ASSERT (pdest < pend) ; ASSERT (pdest <= p) ; Int row = Li [p] ; ASSERT (row >= k && row < nrow) ; if (Flag [row] == mark) { // keep this entry Li [pdest] = row ; // Lx,Lz [pdest] = Lx,Lz [p] ASSIGN (Lx, Lz, pdest, Lx, Lz, p) ; pdest++ ; } } //---------------------------------------------------------------------- // prepare this column for its parent //---------------------------------------------------------------------- Lnz [k] = pdest - Lp [k] ; PRINT1 ((" L("ID") length "ID"\n", k, Lnz [k])) ; ASSERT (Lnz [k] > 0) ; // parent is the first entry in the column after the diagonal Int parent = (Lnz [k] > 1) ? (Li [Lp [k] + 1]) : EMPTY ; PRINT1 (("parent ("ID") = "ID"\n", k, parent)) ; ASSERT ((parent > k && parent < nrow) || (parent == EMPTY)) ; if (parent != EMPTY) { Link [k] = Link [parent] ; Link [parent] = k ; } } if (pack) { // finalize Lp Lp [nrow] = pdest ; } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_spsolve_worker.c����������������������������������0000644�0001751�0000144�00000014427�14552026002�024724� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/t_cholmod_spsolve_worker //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" //------------------------------------------------------------------------------ // t_cholmod_spsolve_B_scatter_worker: scatter the sparse B into the dense B4 //------------------------------------------------------------------------------ static void TEMPLATE (cholmod_spsolve_B_scatter_worker) ( cholmod_dense *B4, // output dense matrix cholmod_sparse *B, // input sparse matrix Int jfirst, Int jlast ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Bp = B->p ; Int *Bi = B->i ; Real *Bx = B->x ; #ifdef ZOMPLEX Real *Bz = B->z ; #endif Int *Bnz = B->nz ; bool packed = B->packed ; Real *B4x = B4->x ; #ifdef ZOMPLEX Real *B4z = B4->z ; #endif Int n = B4->nrow ; //-------------------------------------------------------------------------- // B4 = B (:, jfirst:jlast-1) //-------------------------------------------------------------------------- for (Int j = jfirst ; j < jlast ; j++) { Int p = Bp [j] ; Int pend = (packed) ? (Bp [j+1]) : (p + Bnz [j]) ; Int j_n = (j-jfirst)*n ; for ( ; p < pend ; p++) { Int q = Bi [p] + j_n ; ASSIGN (B4x, B4z, q, Bx, Bz, p) ; } } } //------------------------------------------------------------------------------ // t_cholmod_spsolve_X_worker: append entries from X4 onto X //------------------------------------------------------------------------------ static bool TEMPLATE (cholmod_spsolve_X_worker) ( cholmod_sparse *X, // append X4 onto X cholmod_dense *X4, Int jfirst, Int jlast, size_t *xnz, // position to place entries into X cholmod_common *Common ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Xp = X->p ; Int *Xi = X->i ; Real *Xx = X->x ; #ifdef ZOMPLEX Real *Xz = X->z ; #endif size_t px = (*xnz) ; size_t nzmax = X->nzmax ; Real *X4x = X4->x ; #ifdef ZOMPLEX Real *X4z = X4->z ; #endif Int n = X4->nrow ; //-------------------------------------------------------------------------- // append nonzeros from X4 onto X //-------------------------------------------------------------------------- for (Int j = jfirst ; j < jlast ; j++) { Xp [j] = px ; Int j_n = (j-jfirst)*n ; if (px + n <= nzmax) { //------------------------------------------------------------------ // X is guaranteed to be large enough //------------------------------------------------------------------ for (Int i = 0 ; i < n ; i++) { // append X4 (i,j) to X if nonzero Int p = i + j_n ; if (ENTRY_IS_NONZERO (X4x, X4z, p)) { Xi [px] = i ; ASSIGN (Xx, Xz, px, X4x, X4z, p) ; px++ ; } } } else { //------------------------------------------------------------------ // X may need to increase in size //------------------------------------------------------------------ for (Int i = 0 ; i < n ; i++) { // append X4 (i,j) to X if nonzero Int p = i + j_n ; if (ENTRY_IS_NONZERO (X4x, X4z, p)) { if (px >= nzmax) { // increase the size of X nzmax *= 2 ; CHOLMOD(reallocate_sparse) (nzmax, X, Common) ; if (Common->status < CHOLMOD_OK) { return (false) ; } Xi = X->i ; Xx = X->x ; #ifdef ZOMPLEX Xz = X->z ; #endif } Xi [px] = i ; ASSIGN (Xx, Xz, px, X4x, X4z, p) ; px++ ; } } } } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- (*xnz) = px ; return (true) ; } //------------------------------------------------------------------------------ // t_cholmod_spsolve_B_clear_worker: clear B4 for the next iteration //------------------------------------------------------------------------------ static void TEMPLATE (cholmod_spsolve_B_clear_worker) ( cholmod_dense *B4, // output dense matrix cholmod_sparse *B, // input sparse matrix Int jfirst, Int jlast ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Bp = B->p ; Int *Bi = B->i ; Int *Bnz = B->nz ; bool packed = B->packed ; Real *B4x = B4->x ; #ifdef ZOMPLEX Real *B4z = B4->z ; #endif Int n = B4->nrow ; //-------------------------------------------------------------------------- // clear the entries B4 that were scattered from B (:, jfirst:jast-1) //-------------------------------------------------------------------------- for (Int j = jfirst ; j < jlast ; j++) { Int p = Bp [j] ; Int pend = (packed) ? (Bp [j+1]) : (p + Bnz [j]) ; Int j_n = (j-jfirst)*n ; for ( ; p < pend ; p++) { Int q = Bi [p] + j_n ; CLEAR (B4x, B4z, q) ; } } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_etree.c���������������������������������������������0000644�0001751�0000144�00000016142�14552026002�022415� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_etree: elimination tree of A or A'*A //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Compute the elimination tree of A or A'*A // // In the symmetric case, the upper triangular part of A is used. Entries not // in this part of the matrix are ignored. Computing the etree of a symmetric // matrix from just its lower triangular entries is not supported. // // In the unsymmetric case, all of A is used, and the etree of A'*A is computed. // // References: // // J. Liu, "A compact row storage scheme for Cholesky factors", ACM Trans. // Math. Software, vol 12, 1986, pp. 127-148. // // J. Liu, "The role of elimination trees in sparse factorization", SIAM J. // Matrix Analysis & Applic., vol 11, 1990, pp. 134-172. // // J. Gilbert, X. Li, E. Ng, B. Peyton, "Computing row and column counts for // sparse QR and LU factorization", BIT, vol 41, 2001, pp. 693-710. // // workspace: symmetric: Iwork (nrow), unsymmetric: Iwork (nrow+ncol) // // Supports any xtype (pattern, real, complex, or zomplex) and any dtype. #include "cholmod_internal.h" #ifndef NCHOLESKY //------------------------------------------------------------------------------ // update_etree //------------------------------------------------------------------------------ static void update_etree ( // input: Int k, // process the edge (k,i) in the input graph Int i, // input/output: Int Parent [ ], // Parent [t] = p if p is the parent of t Int Ancestor [ ] // Ancestor [t] is the ancestor of node t in the // partially-constructed etree ) { Int a ; for ( ; ; ) // traverse the path from k to the root of the tree { a = Ancestor [k] ; if (a == i) { // final ancestor reached; no change to tree return ; } // perform path compression Ancestor [k] = i ; if (a == EMPTY) { // final ancestor undefined; this is a new edge in the tree Parent [k] = i ; return ; } // traverse up to the ancestor of k k = a ; } } //------------------------------------------------------------------------------ // cholmod_etree //------------------------------------------------------------------------------ // Find the elimination tree of A or A'*A int CHOLMOD(etree) ( // input: cholmod_sparse *A, // output: Int *Parent, // size ncol. Parent [j] = p if p is the parent of j cholmod_common *Common ) { Int *Ap, *Ai, *Anz, *Ancestor, *Prev, *Iwork ; Int i, j, jprev, p, pend, nrow, ncol, packed, stype ; //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (Parent, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- stype = A->stype ; // s = A->nrow + (stype ? 0 : A->ncol) int ok = TRUE ; size_t s = CHOLMOD(add_size_t) (A->nrow, (stype ? 0 : A->ncol), &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (FALSE) ; } CHOLMOD(allocate_work) (0, s, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; // out of memory } ASSERT (CHOLMOD(dump_sparse) (A, "etree", Common) >= 0) ; Iwork = Common->Iwork ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- ncol = A->ncol ; // the number of columns of A nrow = A->nrow ; // the number of rows of A Ap = A->p ; // size ncol+1, column pointers for A Ai = A->i ; // the row indices of A Anz = A->nz ; // number of nonzeros in each column of A packed = A->packed ; Ancestor = Iwork ; // size ncol for (j = 0 ; j < ncol ; j++) { Parent [j] = EMPTY ; Ancestor [j] = EMPTY ; } //-------------------------------------------------------------------------- // compute the etree //-------------------------------------------------------------------------- if (stype > 0) { //---------------------------------------------------------------------- // symmetric (upper) case: compute etree (A) //---------------------------------------------------------------------- for (j = 0 ; j < ncol ; j++) { // for each row i in column j of triu(A), excluding the diagonal p = Ap [j] ; pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { i = Ai [p] ; if (i < j) { update_etree (i, j, Parent, Ancestor) ; } } } } else if (stype == 0) { //---------------------------------------------------------------------- // unsymmetric case: compute etree (A'*A) //---------------------------------------------------------------------- Prev = Iwork + ncol ; // size nrow for (i = 0 ; i < nrow ; i++) { Prev [i] = EMPTY ; } for (j = 0 ; j < ncol ; j++) { // for each row i in column j of A p = Ap [j] ; pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { // a graph is constructed dynamically with one path per row // of A. If the ith row of A contains column indices // (j1,j2,j3,j4) then the new graph has edges (j1,j2), (j2,j3), // and (j3,j4). When at node i of this path-graph, all edges // (jprev,j) are considered, where jprevstatus is set to CHOLMOD_INVALID if fset is invalid. // // In both cases, the columns of A need not be sorted. // A can be packed or unpacked. // // References: // J. Gilbert, E. Ng, B. Peyton, "An efficient algorithm to compute row and // column counts for sparse Cholesky factorization", SIAM J. Matrix Analysis & // Applic., vol 15, 1994, pp. 1075-1091. // // J. Gilbert, X. Li, E. Ng, B. Peyton, "Computing row and column counts for // sparse QR and LU factorization", BIT, vol 41, 2001, pp. 693-710. // // workspace: // if symmetric: Flag (nrow), Iwork (2*nrow) // if unsymmetric: Flag (nrow), Iwork (2*nrow+ncol), Head (nrow+1) // // Supports any xtype (pattern, real, complex, or zomplex) and any dtype. #include "cholmod_internal.h" #ifndef NCHOLESKY //------------------------------------------------------------------------------ // initialize_node //------------------------------------------------------------------------------ static Int initialize_node // initial work for kth node in postordered etree ( Int k, // at the kth step of the algorithm (and kth node) Int Post [ ], // Post [k] = i, the kth node in postordered etree Int Parent [ ], // Parent [i] is the parent of i in the etree Int ColCount [ ], // ColCount [c] is the current weight of node c Int PrevNbr [ ] // PrevNbr [u] = k if u was last considered at step k ) { Int p, parent ; // determine p, the kth node in the postordered etree p = Post [k] ; // adjust the weight if p is not a root of the etree parent = Parent [p] ; if (parent != EMPTY) { ColCount [parent]-- ; } // flag node p to exclude self edges (p,p) PrevNbr [p] = k ; return (p) ; } //------------------------------------------------------------------------------ // process_edge //------------------------------------------------------------------------------ // edge (p,u) is being processed. p < u is a descendant of its ancestor u in // the etree. node p is the kth node in the postordered etree. static void process_edge ( Int p, // process edge (p,u) of the matrix Int u, Int k, // we are at the kth node in the postordered etree Int First [ ], // First [i] = k if the postordering of first // descendent of node i is k Int PrevNbr [ ], // u was last considered at step k = PrevNbr [u] Int ColCount [ ], // ColCount [c] is the current weight of node c Int PrevLeaf [ ], // s = PrevLeaf [u] means that s was the last leaf // seen in the subtree rooted at u. Int RowCount [ ], // RowCount [i] is # of nonzeros in row i of L, // including the diagonal. Not computed if NULL. Int SetParent [ ], // the FIND/UNION data structure, which forms a set // of trees. A root i has i = SetParent [i]. Following // a path from i to the root q of the subtree containing // i means that q is the SetParent representative of i. // All nodes in the tree could have their SetParent // equal to the root q; the tree representation is used // to save time. When a path is traced from i to its // root q, the path is re-traversed to set the SetParent // of the whole path to be the root q. Int Level [ ] // Level [i] = length of path from node i to root ) { Int prevleaf, q, s, sparent ; if (First [p] > PrevNbr [u]) { // p is a leaf of the subtree of u ColCount [p]++ ; prevleaf = PrevLeaf [u] ; if (prevleaf == EMPTY) { // p is the first leaf of subtree of u; RowCount will be incremented // by the length of the path in the etree from p up to u. q = u ; } else { // q = FIND (prevleaf): find the root q of the // SetParent tree containing prevleaf for (q = prevleaf ; q != SetParent [q] ; q = SetParent [q]) { ; } // the root q has been found; re-traverse the path and // perform path compression s = prevleaf ; for (s = prevleaf ; s != q ; s = sparent) { sparent = SetParent [s] ; SetParent [s] = q ; } // adjust the RowCount and ColCount; RowCount will be incremented by // the length of the path from p to the SetParent root q, and // decrement the ColCount of q by one. ColCount [q]-- ; } if (RowCount != NULL) { // if RowCount is being computed, increment it by the length of // the path from p to q RowCount [u] += (Level [p] - Level [q]) ; } // p is a leaf of the subtree of u, so mark PrevLeaf [u] to be p PrevLeaf [u] = p ; } // flag u has having been processed at step k PrevNbr [u] = k ; } //------------------------------------------------------------------------------ // finalize_node //------------------------------------------------------------------------------ static void finalize_node // compute UNION (p, Parent [p]) ( Int p, Int Parent [ ], // Parent [p] is the parent of p in the etree Int SetParent [ ] // see process_edge, above ) { // all nodes in the SetParent tree rooted at p now have as their final // root the node Parent [p]. This computes UNION (p, Parent [p]) if (Parent [p] != EMPTY) { SetParent [p] = Parent [p] ; } } //------------------------------------------------------------------------------ // cholmod_rowcolcounts //------------------------------------------------------------------------------ int CHOLMOD(rowcolcounts) ( // input: cholmod_sparse *A, // matrix to analyze Int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset Int *Parent, // size nrow. Parent [i] = p if p is the parent of i Int *Post, // size nrow. Post [k] = i if i is the kth node in // the postordered etree. // output: Int *RowCount, // size nrow. RowCount [i] = # entries in the ith // row of L, including the diagonal. Int *ColCount, // size nrow. ColCount [i] = # entries in the ith // column of L, including the diagonal. Int *First, // size nrow. First [i] = k is the least // postordering of any descendant of i. Int *Level, // size nrow. Level [i] is the length of the path // from i to the root, with Level [root] = 0. cholmod_common *Common ) { double fl, ff ; Int *Ap, *Ai, *Anz, *PrevNbr, *SetParent, *Head, *PrevLeaf, *Anext, *Ipost, *Iwork ; Int i, j, r, k, len, s, p, pend, inew, stype, nf, anz, inode, parent, nrow, ncol, packed, use_fset, jj ; //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (Parent, FALSE) ; RETURN_IF_NULL (Post, FALSE) ; RETURN_IF_NULL (ColCount, FALSE) ; RETURN_IF_NULL (First, FALSE) ; RETURN_IF_NULL (Level, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; stype = A->stype ; if (stype > 0) { // symmetric with upper triangular part not supported ERROR (CHOLMOD_INVALID, "symmetric upper not supported") ; return (FALSE) ; } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- nrow = A->nrow ; // the number of rows of A ncol = A->ncol ; // the number of columns of A // w = 2*nrow + (stype ? 0 : ncol) int ok = TRUE ; size_t w = CHOLMOD(mult_size_t) (A->nrow, 2, &ok) ; w = CHOLMOD(add_size_t) (w, (stype ? 0 : A->ncol), &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (FALSE) ; } CHOLMOD(allocate_work) (nrow, w, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } ASSERT (CHOLMOD(dump_perm) (Post, nrow, nrow, "Post", Common)) ; ASSERT (CHOLMOD(dump_parent) (Parent, nrow, "Parent", Common)) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Ap = A->p ; // size ncol+1, column pointers for A Ai = A->i ; // the row indices of A, of size nz=Ap[ncol+1] Anz = A->nz ; packed = A->packed ; ASSERT (IMPLIES (!packed, Anz != NULL)) ; //-------------------------------------------------------------------------- // get workspace //-------------------------------------------------------------------------- Iwork = Common->Iwork ; SetParent = Iwork ; // size nrow PrevNbr = Iwork + nrow ; // size nrow Anext = Iwork + 2*((size_t) nrow) ; // size ncol (unsym only) PrevLeaf = Common->Flag ; // size nrow Head = Common->Head ; // size nrow+1 (unsym only) //-------------------------------------------------------------------------- // find the first descendant and level of each node in the tree //-------------------------------------------------------------------------- // First [i] = k if the postordering of first descendent of node i is k // Level [i] = length of path from node i to the root (Level [root] = 0) for (i = 0 ; i < nrow ; i++) { First [i] = EMPTY ; } // postorder traversal of the etree for (k = 0 ; k < nrow ; k++) { // node i of the etree is the kth node in the postordered etree i = Post [k] ; // i is a leaf if First [i] is still EMPTY // ColCount [i] starts at 1 if i is a leaf, zero otherwise ColCount [i] = (First [i] == EMPTY) ? 1 : 0 ; // traverse the path from node i to the root, stopping if we find a // node r whose First [r] is already defined. len = 0 ; for (r = i ; (r != EMPTY) && (First [r] == EMPTY) ; r = Parent [r]) { First [r] = k ; len++ ; } if (r == EMPTY) { // we hit a root node, the level of which is zero len-- ; } else { // we stopped at node r, where Level [r] is already defined len += Level [r] ; } // re-traverse the path from node i to r; set the level of each node for (s = i ; s != r ; s = Parent [s]) { Level [s] = len-- ; } } //-------------------------------------------------------------------------- // AA' case: sort columns of A according to first postordered row index //-------------------------------------------------------------------------- fl = 0.0 ; if (stype == 0) { // [ use PrevNbr [0..nrow-1] as workspace for Ipost Ipost = PrevNbr ; // Ipost [i] = k if i is the kth node in the postordered etree. for (k = 0 ; k < nrow ; k++) { Ipost [Post [k]] = k ; } use_fset = (fset != NULL) ; if (use_fset) { nf = fsize ; // clear Anext to check fset for (j = 0 ; j < ncol ; j++) { Anext [j] = -2 ; } // find the first postordered row in each column of A (post,f) // and place the column in the corresponding link list for (jj = 0 ; jj < nf ; jj++) { j = fset [jj] ; if (j < 0 || j > ncol || Anext [j] != -2) { // out-of-range or duplicate entry in fset ERROR (CHOLMOD_INVALID, "fset invalid") ; return (FALSE) ; } // flag column j as having been seen Anext [j] = EMPTY ; } // fset is now valid ASSERT (CHOLMOD(dump_perm) (fset, nf, ncol, "fset", Common)) ; } else { nf = ncol ; } for (jj = 0 ; jj < nf ; jj++) { j = (use_fset) ? (fset [jj]) : jj ; // column j is in the fset; find the smallest row (if any) p = Ap [j] ; pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; ff = (double) MAX (0, pend - p) ; fl += ff*ff + ff ; if (pend > p) { k = Ipost [Ai [p]] ; for ( ; p < pend ; p++) { inew = Ipost [Ai [p]] ; k = MIN (k, inew) ; } // place column j in link list k ASSERT (k >= 0 && k < nrow) ; Anext [j] = Head [k] ; Head [k] = j ; } } // Ipost no longer needed for inverse postordering ] // Head [k] contains a link list of all columns whose first // postordered row index is equal to k, for k = 0 to nrow-1. } //-------------------------------------------------------------------------- // compute the row counts and node weights //-------------------------------------------------------------------------- if (RowCount != NULL) { for (i = 0 ; i < nrow ; i++) { RowCount [i] = 1 ; } } for (i = 0 ; i < nrow ; i++) { PrevLeaf [i] = EMPTY ; PrevNbr [i] = EMPTY ; SetParent [i] = i ; // every node is in its own set, by itself } if (stype != 0) { //---------------------------------------------------------------------- // symmetric case: LL' = A //---------------------------------------------------------------------- // also determine the number of entries in triu(A) anz = nrow ; for (k = 0 ; k < nrow ; k++) { // j is the kth node in the postordered etree j = initialize_node (k, Post, Parent, ColCount, PrevNbr) ; // for all nonzeros A(i,j) below the diagonal, in column j of A p = Ap [j] ; pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { i = Ai [p] ; if (i > j) { // j is a descendant of i in etree(A) anz++ ; process_edge (j, i, k, First, PrevNbr, ColCount, PrevLeaf, RowCount, SetParent, Level) ; } } // update SetParent: UNION (j, Parent [j]) finalize_node (j, Parent, SetParent) ; } Common->anz = anz ; } else { //---------------------------------------------------------------------- // unsymmetric case: LL' = AA' //---------------------------------------------------------------------- for (k = 0 ; k < nrow ; k++) { // inode is the kth node in the postordered etree inode = initialize_node (k, Post, Parent, ColCount, PrevNbr) ; // for all cols j whose first postordered row is k: for (j = Head [k] ; j != EMPTY ; j = Anext [j]) { // k is the first postordered row in column j of A // for all rows i in column j: p = Ap [j] ; pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { i = Ai [p] ; // has i already been considered at this step k if (PrevNbr [i] < k) { // inode is a descendant of i in etree(AA') // process edge (inode,i) and set PrevNbr[i] to k process_edge (inode, i, k, First, PrevNbr, ColCount, PrevLeaf, RowCount, SetParent, Level) ; } } } // clear link list k Head [k] = EMPTY ; // update SetParent: UNION (inode, Parent [inode]) finalize_node (inode, Parent, SetParent) ; } } //-------------------------------------------------------------------------- // finish computing the column counts //-------------------------------------------------------------------------- for (j = 0 ; j < nrow ; j++) { parent = Parent [j] ; if (parent != EMPTY) { // add the ColCount of j to its parent ColCount [parent] += ColCount [j] ; } } //-------------------------------------------------------------------------- // clear workspace //-------------------------------------------------------------------------- Common->mark = EMPTY ; CLEAR_FLAG (Common) ; ASSERT (check_flag (Common)) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; //-------------------------------------------------------------------------- // flop count and nnz(L) for subsequent LL' numerical factorization //-------------------------------------------------------------------------- // use double to avoid integer overflow. lnz cannot be NaN. Common->aatfl = fl ; Common->lnz = 0. ; fl = 0 ; for (j = 0 ; j < nrow ; j++) { ff = (double) (ColCount [j]) ; Common->lnz += ff ; fl += ff*ff ; } Common->fl = fl ; PRINT1 (("rowcol fl %g lnz %g\n", Common->fl, Common->lnz)) ; return (TRUE) ; } #endif �������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_postorder.c���������������������������������������0000644�0001751�0000144�00000001001�14552026002�023631� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_l_postorder.c: int64_t version of cholmod_postorder //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_postorder.c" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_resymbol.c����������������������������������������0000644�0001751�0000144�00000000776�14552026002�023466� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_l_resymbol.c: int64_t version of cholmod_resymbol //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_resymbol.c" ��Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_factorize.c���������������������������������������0000644�0001751�0000144�00000001001�14552026002�023576� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_l_factorize.c: int64_t version of cholmod_factorize //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_factorize.c" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_rowcolcounts.c������������������������������������0000644�0001751�0000144�00000000774�14552026002�024371� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_l_rowcolcounts: compute row/col counts of L //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_rowcolcounts.c" ����Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_resymbol.c������������������������������������������0000644�0001751�0000144�00000037615�14552026002�023155� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_resymbol: recompute symbolic pattern of L //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Recompute the symbolic pattern of L. Entries not in the symbolic pattern // are dropped. L->Perm can be used (or not) to permute the input matrix A. // // These routines are used after a supernodal factorization is converted into // a simplicial one, to remove zero entries that were added due to relaxed // supernode amalgamation. They can also be used after a series of downdates // to remove entries that would no longer be present if the matrix were // factorized from scratch. A downdate (cholmod_updown) does not remove any // entries from L. // // workspace: Flag (nrow), Head (nrow+1), // if symmetric: Iwork (2*nrow) // if unsymmetric: Iwork (2*nrow+ncol). // Allocates up to 2 copies of its input matrix A (pattern only). #include "cholmod_internal.h" #ifndef NCHOLESKY //------------------------------------------------------------------------------ // t_cholmod_resymbol_worker //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_resymbol_worker.c" #define COMPLEX #include "t_cholmod_resymbol_worker.c" #define ZOMPLEX #include "t_cholmod_resymbol_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_resymbol_worker.c" #define COMPLEX #include "t_cholmod_resymbol_worker.c" #define ZOMPLEX #include "t_cholmod_resymbol_worker.c" //------------------------------------------------------------------------------ // cholmod_resymbol //------------------------------------------------------------------------------ // Remove entries from L that are not in the factorization of P*A*P', P*A*A'*P', // or P*F*F'*P' (depending on A->stype and whether fset is NULL or not). // // cholmod_resymbol is the same as cholmod_resymbol_noperm, except that it // first permutes A according to L->Perm. A can be upper/lower/unsymmetric, // in contrast to cholmod_resymbol_noperm (which can be lower or unsym). int CHOLMOD(resymbol) // recompute symbolic pattern of L ( // input: cholmod_sparse *A, // matrix to analyze Int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int pack, // if TRUE, pack the columns of L // input/output: cholmod_factor *L, // factorization, entries pruned on output cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- cholmod_sparse *H = NULL, *F = NULL, *G = NULL ; RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (L, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ; Common->status = CHOLMOD_OK ; if (L->is_super) { // cannot operate on a supernodal factorization ERROR (CHOLMOD_INVALID, "cannot operate on supernodal L") ; return (FALSE) ; } if (L->n != A->nrow) { // dimensions must agree ERROR (CHOLMOD_INVALID, "A and L dimensions do not match") ; return (FALSE) ; } //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- Int stype = A->stype ; // s = 2*nrow + (stype ? 0 : ncol) int ok = TRUE ; size_t s = CHOLMOD(mult_size_t) (A->nrow, 2, &ok) ; s = CHOLMOD(add_size_t) (s, (stype ? 0 : A->ncol), &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (FALSE) ; } CHOLMOD(allocate_work) (A->nrow, s, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } //-------------------------------------------------------------------------- // permute the input matrix if necessary //-------------------------------------------------------------------------- H = NULL ; G = NULL ; if (stype > 0) { if (L->ordering == CHOLMOD_NATURAL) { // F = triu(A)' // workspace: Iwork (nrow) G = CHOLMOD(ptranspose) (A, 0, NULL, NULL, 0, Common) ; } else { // F = triu(A(p,p))' // workspace: Iwork (2*nrow) G = CHOLMOD(ptranspose) (A, 0, L->Perm, NULL, 0, Common) ; } F = G ; } else if (stype < 0) { if (L->ordering == CHOLMOD_NATURAL) { F = A ; } else { // G = triu(A(p,p))' // workspace: Iwork (2*nrow) G = CHOLMOD(ptranspose) (A, 0, L->Perm, NULL, 0, Common) ; // H = G' // workspace: Iwork (nrow) H = CHOLMOD(ptranspose) (G, 0, NULL, NULL, 0, Common) ; F = H ; } } else { if (L->ordering == CHOLMOD_NATURAL) { F = A ; } else { // G = A(p,f)' // workspace: Iwork (nrow if no fset; MAX (nrow,ncol) if fset) G = CHOLMOD(ptranspose) (A, 0, L->Perm, fset, fsize, Common) ; // H = G' // workspace: Iwork (ncol) H = CHOLMOD(ptranspose) (G, 0, NULL, NULL, 0, Common) ; F = H ; } } // No need to check for failure here. cholmod_resymbol_noperm will return // FALSE if F is NULL. //-------------------------------------------------------------------------- // resymbol //-------------------------------------------------------------------------- ok = CHOLMOD(resymbol_noperm) (F, fset, fsize, pack, L, Common) ; //-------------------------------------------------------------------------- // free the temporary matrices, if they exist //-------------------------------------------------------------------------- CHOLMOD(free_sparse) (&H, Common) ; CHOLMOD(free_sparse) (&G, Common) ; return (ok) ; } //------------------------------------------------------------------------------ // cholmod_resymbol_noperm //------------------------------------------------------------------------------ // Redo symbolic LDL' or LL' factorization of I + F*F' or I+A, where F=A(:,f). // // L already exists, but is a superset of the true dynamic pattern (simple // column downdates and row deletions haven't pruned anything). Just redo the // symbolic factorization and drop entries that are no longer there. The // diagonal is not modified. The number of nonzeros in column j of L // (L->nz[j]) can decrease. The column pointers (L->p[j]) remain unchanged if // pack is FALSE or if L is not monotonic. Otherwise, the columns of L are // packed in place. // // For the symmetric case, the columns of the lower triangular part of A // are accessed by column. NOTE that this the transpose of the general case. // // For the unsymmetric case, F=A(:,f) is accessed by column. // // A need not be sorted, and can be packed or unpacked. If L->Perm is not // identity, then A must already be permuted according to the permutation used // to factorize L. The advantage of using this routine is that it does not // need to create permuted copies of A first. // // This routine can be called if L is only partially factored via cholmod_rowfac // since all it does is prune. If an entry is in F*F' or A, but not in L, it // isn't added to L. // // L must be simplicial LDL' or LL'; it cannot be supernodal or symbolic. // // The set f is held in fset and fsize. // fset = NULL means ":" in MATLAB. fset is ignored. // fset != NULL means f = fset [0..fset-1]. // fset != NULL and fsize = 0 means f is the empty set. // There can be no duplicates in fset. // Common->status is set to CHOLMOD_INVALID if fset is invalid. // // workspace: Flag (nrow), Head (nrow+1), // if symmetric: Iwork (2*nrow) // if unsymmetric: Iwork (2*nrow+ncol). // Unlike cholmod_resymbol, this routine does not allocate any temporary // copies of its input matrix. int CHOLMOD(resymbol_noperm) // recompute symbolic pattern of L ( // input: cholmod_sparse *A, // matrix to analyze Int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int pack, // if TRUE, pack the columns of L // input/output: cholmod_factor *L, // factorization, entries pruned on output cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (L, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ; Int ncol = A->ncol ; Int nrow = A->nrow ; Int stype = A->stype ; ASSERT (IMPLIES (stype != 0, nrow == ncol)) ; if (stype > 0) { // symmetric, with upper triangular part, not supported ERROR (CHOLMOD_INVALID, "symmetric upper not supported ") ; return (FALSE) ; } if (L->is_super) { // cannot operate on a supernodal or symbolic factorization ERROR (CHOLMOD_INVALID, "cannot operate on supernodal L") ; return (FALSE) ; } if (L->n != A->nrow) { // dimensions must agree ERROR (CHOLMOD_INVALID, "A and L dimensions do not match") ; return (FALSE) ; } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- // s = nrow + (stype ? 0 : ncol) size_t s = A->nrow ; int ok = TRUE ; if (stype != 0) { s = CHOLMOD(add_size_t) (s, A->ncol, &ok) ; } if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (FALSE) ; } CHOLMOD(allocate_work) (A->nrow, s, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; // out of memory } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Ai = A->i ; Int *Ap = A->p ; Int *Anz = A->nz ; bool apacked = A->packed ; bool sorted = A->sorted ; Int *Lp = L->p ; // If L is monotonic on input, then it can be packed or // unpacked on output, depending on the pack input parameter. // cannot pack a non-monotonic matrix if (!(L->is_monotonic)) { pack = FALSE ; } ASSERT (L->nzmax >= (size_t) (Lp [L->n])) ; PRINT1 (("\n\n===================== Resymbol pack %d Apacked %d\n", pack, A->packed)) ; ASSERT (CHOLMOD(dump_sparse) (A, "ReSymbol A:", Common) >= 0) ; DEBUG (CHOLMOD(dump_factor) (L, "ReSymbol initial L (i, x):", Common)) ; //-------------------------------------------------------------------------- // get workspace //-------------------------------------------------------------------------- Int *Head = Common->Head ; // size nrow+1 Int *Iwork = Common->Iwork ; Int *Link = Iwork ; // size nrow [ Int *Anext = Iwork + nrow ; // size ncol, unsym. only for (Int j = 0 ; j < nrow ; j++) { Link [j] = EMPTY ; } //-------------------------------------------------------------------------- // for the unsymmetric case, queue each column of A (:,f) //-------------------------------------------------------------------------- // place each column of the basis set on the link list corresponding to // the smallest row index in that column if (stype == 0) { Int nf ; bool use_fset = (fset != NULL) ; if (use_fset) { nf = fsize ; // This is the only O(ncol) loop in cholmod_resymbol. // It is required only to check the fset. for (Int j = 0 ; j < ncol ; j++) { Anext [j] = -2 ; } for (Int jj = 0 ; jj < nf ; jj++) { Int j = fset [jj] ; if (j < 0 || j > ncol || Anext [j] != -2) { // out-of-range or duplicate entry in fset ERROR (CHOLMOD_INVALID, "fset invalid") ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; return (FALSE) ; } // flag column j as having been seen Anext [j] = EMPTY ; } // the fset is now valid ASSERT (CHOLMOD(dump_perm) (fset, nf, ncol, "fset", Common)) ; } else { nf = ncol ; } for (Int jj = 0 ; jj < nf ; jj++) { Int j = (use_fset) ? (fset [jj]) : jj ; // column j is the fset; find the smallest row (if any) Int p = Ap [j] ; Int pend = (apacked) ? (Ap [j+1]) : (p + Anz [j]) ; if (pend > p) { Int k = Ai [p] ; if (!sorted) { for ( ; p < pend ; p++) { k = MIN (k, Ai [p]) ; } } // place column j on link list k ASSERT (k >= 0 && k < nrow) ; Anext [j] = Head [k] ; Head [k] = j ; } } } //-------------------------------------------------------------------------- // recompute symbolic LDL' factorization //-------------------------------------------------------------------------- switch ((L->xtype + L->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_resymbol_worker (A, pack, L, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_resymbol_worker (A, pack, L, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_resymbol_worker (A, pack, L, Common) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_resymbol_worker (A, pack, L, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_resymbol_worker (A, pack, L, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_resymbol_worker (A, pack, L, Common) ; break ; } // done using Iwork for Link and Anext ] //-------------------------------------------------------------------------- // convert L to packed, if requested //-------------------------------------------------------------------------- if (pack) { // Shrink L to be just large enough. It cannot fail. // workspace: none ASSERT ((size_t) (Lp [nrow]) <= L->nzmax) ; CHOLMOD(reallocate_factor) (Lp [nrow], L, Common) ; ASSERT (Common->status >= CHOLMOD_OK) ; } //-------------------------------------------------------------------------- // clear workspace and return result //-------------------------------------------------------------------------- CLEAR_FLAG (Common) ; ASSERT (check_flag (Common)) ; DEBUG (CHOLMOD(dump_factor) (L, "ReSymbol final L (i, x):", Common)) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; return (TRUE) ; } #endif �������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_spsolve.c�������������������������������������������0000644�0001751�0000144�00000023265�14552026002�023010� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_spsolve: solve a linear system with sparse x and b //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Given an LL' or LDL' factorization of A, solve one of the following systems: // // Ax=b 0: CHOLMOD_A also applies the permutation L->Perm // LDL'x=b 1: CHOLMOD_LDLt does not apply L->Perm // LDx=b 2: CHOLMOD_LD // DL'x=b : CHOLMOD_DLt // Lx=b 4: CHOLMOD_L // L'x=b 5: CHOLMOD_Lt // Dx=b 6: CHOLMOD_D // x=Pb 7: CHOLMOD_P apply a permutation (P is L->Perm) // x=P'b 8: CHOLMOD_Pt apply an inverse permutation // // where b and x are sparse. If L and b are real, then x is real. Otherwise, // x is complex or zomplex, depending on the Common->prefer_zomplex parameter. // All xtypes of x and b are supported (real, complex, and zomplex), and // all dtypes. #include "cholmod_internal.h" #ifndef NCHOLESKY //------------------------------------------------------------------------------ // t_cholmod_spsolve_worker //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_spsolve_worker.c" #define COMPLEX #include "t_cholmod_spsolve_worker.c" #define ZOMPLEX #include "t_cholmod_spsolve_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_spsolve_worker.c" #define COMPLEX #include "t_cholmod_spsolve_worker.c" #define ZOMPLEX #include "t_cholmod_spsolve_worker.c" //------------------------------------------------------------------------------ // cholmod_spsolve //------------------------------------------------------------------------------ cholmod_sparse *CHOLMOD(spsolve) // returns the sparse solution X ( // input: int sys, // system to solve cholmod_factor *L, // factorization to use cholmod_sparse *B, // right-hand-side cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- cholmod_dense *X4 = NULL, *B4 = NULL ; cholmod_sparse *X = NULL ; RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_NULL (L, NULL) ; RETURN_IF_NULL (B, NULL) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, NULL) ; RETURN_IF_XTYPE_INVALID (B, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, NULL) ; if (L->n != B->nrow) { ERROR (CHOLMOD_INVALID, "dimensions of L and B do not match") ; return (NULL) ; } if (B->stype) { ERROR (CHOLMOD_INVALID, "B cannot be stored in symmetric mode") ; return (NULL) ; } if (L->dtype != B->dtype) { ERROR (CHOLMOD_INVALID, "dtype of L and B must match") ; return (NULL) ; } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate workspace B4 and initial result X //-------------------------------------------------------------------------- Int n = L->n ; Int nrhs = B->ncol ; // X is real if both L and B are real, complex/zomplex otherwise int X_xtype = (L->xtype == CHOLMOD_REAL && B->xtype == CHOLMOD_REAL) ? CHOLMOD_REAL : (Common->prefer_zomplex ? CHOLMOD_ZOMPLEX : CHOLMOD_COMPLEX) ; // solve up to 4 columns at a time Int block = MIN (nrhs, 4) ; // initial size of X is at most 4*n size_t nzmax = ((size_t) n) * ((size_t) block) ; X = CHOLMOD(spzeros) (n, nrhs, nzmax, X_xtype + B->dtype, Common) ; B4 = CHOLMOD(zeros) (n, block, B->xtype + B->dtype, Common) ; if (Common->status < CHOLMOD_OK) { CHOLMOD(free_sparse) (&X, Common) ; CHOLMOD(free_dense) (&B4, Common) ; return (NULL) ; } size_t xnz = 0 ; //-------------------------------------------------------------------------- // solve in chunks of 4 columns at a time //-------------------------------------------------------------------------- for (Int jfirst = 0 ; jfirst < nrhs ; jfirst += block) { //---------------------------------------------------------------------- // adjust the number of columns of B4 //---------------------------------------------------------------------- Int jlast = MIN (nrhs, jfirst + block) ; B4->ncol = jlast - jfirst ; //---------------------------------------------------------------------- // scatter B(jfirst:jlast-1) into B4 //---------------------------------------------------------------------- switch ((B->xtype + B->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_spsolve_B_scatter_worker (B4, B, jfirst, jlast) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_spsolve_B_scatter_worker (B4, B, jfirst, jlast) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_spsolve_B_scatter_worker (B4, B, jfirst, jlast) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_spsolve_B_scatter_worker (B4, B, jfirst, jlast) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_spsolve_B_scatter_worker (B4, B, jfirst, jlast) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_spsolve_B_scatter_worker (B4, B, jfirst, jlast) ; break ; } //---------------------------------------------------------------------- // solve the system (X4 = A\B4 or other system) //---------------------------------------------------------------------- X4 = CHOLMOD(solve) (sys, L, B4, Common) ; if (Common->status < CHOLMOD_OK) { CHOLMOD(free_sparse) (&X, Common) ; CHOLMOD(free_dense) (&B4, Common) ; CHOLMOD(free_dense) (&X4, Common) ; return (NULL) ; } ASSERT (X4->xtype == X_xtype) ; //---------------------------------------------------------------------- // append the solution onto X //---------------------------------------------------------------------- bool ok = true ; switch ((X->xtype + X->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: ok = rs_cholmod_spsolve_X_worker (X, X4, jfirst, jlast, &xnz, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: ok = cs_cholmod_spsolve_X_worker (X, X4, jfirst, jlast, &xnz, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: ok = zs_cholmod_spsolve_X_worker (X, X4, jfirst, jlast, &xnz, Common) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: ok = rd_cholmod_spsolve_X_worker (X, X4, jfirst, jlast, &xnz, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: ok = cd_cholmod_spsolve_X_worker (X, X4, jfirst, jlast, &xnz, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: ok = zd_cholmod_spsolve_X_worker (X, X4, jfirst, jlast, &xnz, Common) ; break ; } CHOLMOD(free_dense) (&X4, Common) ; if (!ok) { // out of memory CHOLMOD(free_sparse) (&X, Common) ; CHOLMOD(free_dense) (&B4, Common) ; return (NULL) ; } //---------------------------------------------------------------------- // clear B4 for next iteration //---------------------------------------------------------------------- if (jlast < nrhs) { switch ((B->xtype + B->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_spsolve_B_clear_worker (B4, B, jfirst, jlast) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_spsolve_B_clear_worker (B4, B, jfirst, jlast) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_spsolve_B_clear_worker (B4, B, jfirst, jlast) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_spsolve_B_clear_worker (B4, B, jfirst, jlast) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_spsolve_B_clear_worker (B4, B, jfirst, jlast) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_spsolve_B_clear_worker (B4, B, jfirst, jlast) ; break ; } } } //-------------------------------------------------------------------------- // finalize X, reduce it in size, free workspace, and return result //-------------------------------------------------------------------------- Int *Xp = X->p ; Xp [nrhs] = xnz ; ASSERT (xnz <= X->nzmax) ; CHOLMOD(reallocate_sparse) (xnz, X, Common) ; ASSERT (Common->status == CHOLMOD_OK) ; CHOLMOD(free_dense) (&B4, Common) ; return (X) ; } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_rowfac_worker.c�����������������������������������0000644�0001751�0000144�00000037437�14552026002�024520� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/t_cholmod_rowfac_worker: template for cholmod_rowfac //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Template routine for cholmod_rowfac. Supports any numeric xtype // (real, complex, or zomplex) but not pattern, and any dtype. // // workspace: Iwork (n), Flag (n), Xwork (n if real, 2*n if complex) #include "cholmod_template.h" #ifdef MASK static int TEMPLATE (cholmod_rowfac_mask_worker) #else static int TEMPLATE (cholmod_rowfac_worker) #endif ( // input: cholmod_sparse *A, // matrix to factorize cholmod_sparse *F, // used for A*A' case only. F=A' or A(:,f)' Real beta [2], // factorize beta*I+A or beta*I+AA' (beta [0] only) size_t kstart, // first row to factorize size_t kend, // last row to factorize is kend-1 #ifdef MASK // These inputs are used for cholmod_rowfac_mask only Int *mask, // size A->nrow. if mask[i] >= maskmark // then W(i) is set to zero Int maskmark, Int *RLinkUp, // size A->nrow. link list of rows to compute #endif // input/output: cholmod_factor *L, cholmod_common *Common ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- double fl = 0 ; Real yx [2], lx [2], fx [2], dk [1], di [1] ; #ifdef ZOMPLEX Real yz [1], lz [1], fz [1] ; #endif Real *Ax, *Lx, *Wx, *Fx ; #ifdef ZOMPLEX Real *Az, *Lz, *Wz, *Fz ; #endif Int *Ap, *Anz, *Ai, *Lp, *Lnz, *Li, *Lnext, *Flag, *Stack, *Fp, *Fi, *Fnz, *Iwork ; Int i, p, k, t, pf, pfend, top, s, mark, pend, n, lnz, is_ll, multadds, use_bound, packed, stype, Fpacked, sorted, len, parent ; #ifndef REAL Int dk_imaginary ; #endif PRINT1 (("\nin cholmod_rowfac, kstart %d kend %d stype %d\n", kstart, kend, A->stype)) ; DEBUG (CHOLMOD(dump_factor) (L, "Initial L", Common)) ; n = A->nrow ; stype = A->stype ; if (stype > 0) { // symmetric upper case: F is not needed. It may be NULL Fp = NULL ; Fi = NULL ; Fx = NULL ; #ifdef ZOMPLEX Fz = NULL ; #endif Fnz = NULL ; Fpacked = TRUE ; } else { // unsymmetric case: F is required. Fp = F->p ; Fi = F->i ; Fx = F->x ; #ifdef ZOMPLEX Fz = F->z ; #endif Fnz = F->nz ; Fpacked = F->packed ; } Ap = A->p ; // size A->ncol+1, column pointers of A Ai = A->i ; // size nz = Ap [A->ncol], row indices of A Ax = A->x ; // size nz, numeric values of A #ifdef ZOMPLEX Az = A->z ; #endif Anz = A->nz ; packed = A->packed ; sorted = A->sorted ; #ifdef DOUBLE use_bound = (Common->dbound > 0) ; #else use_bound = (Common->sbound > 0) ; #endif //-------------------------------------------------------------------------- // get the current factors L (and D for LDL'); allocate space if needed //-------------------------------------------------------------------------- is_ll = L->is_ll ; if (L->xtype == CHOLMOD_PATTERN) { //---------------------------------------------------------------------- // L is symbolic only; allocate and initialize L (and D for LDL') //---------------------------------------------------------------------- // workspace: none L->dtype = A->dtype ; // ensure L has the same dtype as A CHOLMOD(change_factor) (A->xtype, is_ll, FALSE, FALSE, TRUE, L, Common); if (Common->status < CHOLMOD_OK) { // out of memory return (FALSE) ; } ASSERT (L->minor == (size_t) n) ; } else if (kstart == 0 && kend == (size_t) n) { //---------------------------------------------------------------------- // refactorization; reset L->nz and L->minor to restart factorization //---------------------------------------------------------------------- L->minor = n ; Lnz = L->nz ; for (k = 0 ; k < n ; k++) { Lnz [k] = 1 ; } } ASSERT (is_ll == L->is_ll) ; ASSERT (L->xtype != CHOLMOD_PATTERN) ; DEBUG (CHOLMOD(dump_factor) (L, "L ready", Common)) ; DEBUG (CHOLMOD(dump_sparse) (A, "A ready", Common)) ; DEBUG (if (stype == 0) CHOLMOD(dump_sparse) (F, "F ready", Common)) ; // inputs, can be modified on output: Lp = L->p ; // size n+1 ASSERT (Lp != NULL) ; // outputs, contents defined on input for incremental case only: Lnz = L->nz ; // size n Lnext = L->next ; // size n+2 Li = L->i ; // size L->nzmax, can change in size Lx = L->x ; // size L->nzmax or 2*L->nzmax, can change in size #ifdef ZOMPLEX Lz = L->z ; // size L->nzmax for zomplex case, can change in size #endif ASSERT (Lnz != NULL && Li != NULL && Lx != NULL) ; //-------------------------------------------------------------------------- // get workspace //-------------------------------------------------------------------------- Iwork = Common->Iwork ; Stack = Iwork ; // size n Flag = Common->Flag ; // size n, Flag [i] < mark must hold Wx = Common->Xwork ; // size n if real, 2*n if complex or // zomplex. Xwork [i] == 0 must hold. #ifdef ZOMPLEX Wz = Wx + n ; // size n for zomplex case only #endif mark = Common->mark ; #ifndef NDEBUG size_t wsize = (L->xtype == CHOLMOD_REAL ? 1:2) * ((size_t) n) ; #endif ASSERT (Common->xworkbytes >= wsize * sizeof (Real)) ; //-------------------------------------------------------------------------- // compute LDL' or LL' factorization by rows //-------------------------------------------------------------------------- #ifdef MASK #define NEXT(k) k = RLinkUp [k] #else #define NEXT(k) k++ #endif for (k = kstart ; k < ((Int) kend) ; NEXT(k)) { //---------------------------------------------------------------------- // compute pattern of kth row of L and scatter kth input column //---------------------------------------------------------------------- PRINT1 (("\n===============K "ID" Lnz [k] "ID"\n", k, Lnz [k])) ; // column k of L is currently empty ASSERT (Lnz [k] == 1) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, wsize, A->dtype, Common)) ; top = n ; // Stack is empty Flag [k] = mark ; // do not include diagonal entry in Stack // use Li [Lp [i]+1] for etree #define PARENT(i) (Lnz [i] > 1) ? (Li [Lp [i] + 1]) : EMPTY if (stype > 0) { // scatter kth col of triu (beta*I+AA'), get pattern L(k,:) p = Ap [k] ; pend = (packed) ? (Ap [k+1]) : (p + Anz [k]) ; // W [i] = Ax [i] ; scatter column of A #define SCATTER ASSIGN(Wx,Wz,i, Ax,Az,p) SUBTREE ; #undef SCATTER } else { // scatter kth col of triu (beta*I+AA'), get pattern L(k,:) pf = Fp [k] ; pfend = (Fpacked) ? (Fp [k+1]) : (pf + Fnz [k]) ; for ( ; pf < pfend ; pf++) { // get nonzero entry F (t,k) t = Fi [pf] ; // fk = Fx [pf] ASSIGN (fx, fz, 0, Fx, Fz, pf) ; p = Ap [t] ; pend = (packed) ? (Ap [t+1]) : (p + Anz [t]) ; multadds = 0 ; // W [i] += Ax [p] * fx ; scatter column of A*A' #define SCATTER MULTADD (Wx,Wz,i,Ax,Az,p,fx,fz,0) ; multadds++ ; SUBTREE ; #undef SCATTER #ifdef REAL fl += 2 * ((double) multadds) ; #else fl += 8 * ((double) multadds) ; #endif } } #undef PARENT //---------------------------------------------------------------------- // if mask is present, set the corresponding entries in W to zero //---------------------------------------------------------------------- #ifdef MASK // remove the dead element of Wx if (mask != NULL) { for (s = top ; s < n ; s++) { i = Stack [s] ; if (mask [i] >= maskmark) { CLEAR (Wx,Wz,i) ; // set W(i) to zero } } } #endif // nonzero pattern of kth row of L is now in Stack [top..n-1]. // Flag [Stack [top..n-1]] is equal to mark, but no longer needed CLEAR_FLAG (Common) ; mark = Common->mark ; //---------------------------------------------------------------------- // compute kth row of L and store in column form //---------------------------------------------------------------------- // Solve L (0:k-1, 0:k-1) * y (0:k-1) = b (0:k-1) where // b (0:k) = A (0:k,k) or A(0:k,:) * F(:,k) is in W and Stack. // // For LDL' factorization: // L (k, 0:k-1) = y (0:k-1) ./ D (0:k-1) // D (k) = b (k) - L (k, 0:k-1) * y (0:k-1) // // For LL' factorization: // L (k, 0:k-1) = y (0:k-1) // L (k,k) = sqrt (b (k) - L (k, 0:k-1) * L (0:k-1, k)) // dk = W [k] + beta ADD_REAL (dk,0, Wx,k, beta,0) ; #ifndef REAL // In the unsymmetric case, the imaginary part of W[k] must be real, // since F is assumed to be the complex conjugate transpose of A. In // the symmetric case, W[k] is the diagonal of A. If the imaginary part // of W[k] is nonzero, then the Cholesky factorization cannot be // computed; A is not positive definite dk_imaginary = (stype > 0) ? (IMAG_IS_NONZERO (Wx,Wz,k)) : FALSE ; #endif // W [k] = 0.0 ; CLEAR (Wx,Wz,k) ; for (s = top ; s < n ; s++) { // get i for each nonzero entry L(k,i) i = Stack [s] ; // y = W [i] ; ASSIGN (yx,yz,0, Wx,Wz,i) ; // W [i] = 0.0 ; CLEAR (Wx,Wz,i) ; lnz = Lnz [i] ; p = Lp [i] ; ASSERT (lnz > 0 && Li [p] == i) ; pend = p + lnz ; // di = Lx [p] ; the diagonal entry L or D(i,i), which is real ASSIGN_REAL (di,0, Lx,p) ; if (i >= (Int) L->minor || (di [0] == 0)) { // For the LL' factorization, L(i,i) is zero. For the LDL', // D(i,i) is zero. Skip column i of L, and set L(k,i) = 0. CLEAR (lx,lz,0) ; p = pend ; } else if (is_ll) { #ifdef REAL fl += 2 * ((double) (pend - p - 1)) + 3 ; #else fl += 8 * ((double) (pend - p - 1)) + 6 ; #endif // forward solve using L (i:(k-1),i) // divide by L(i,i), which must be real and nonzero // y /= di [0] DIV_REAL (yx,yz,0, yx,yz,0, di,0) ; for (p++ ; p < pend ; p++) { // W [Li [p]] -= Lx [p] * y ; MULTSUB (Wx,Wz,Li[p], Lx,Lz,p, yx,yz,0) ; } // do not scale L; compute dot product for L(k,k) // L(k,i) = conj(y) ; ASSIGN_CONJ (lx,lz,0, yx,yz,0) ; // d -= conj(y) * y ; LLDOT (dk,0, yx,yz,0) ; } else { #ifdef REAL fl += 2 * ((double) (pend - p - 1)) + 3 ; #else fl += 8 * ((double) (pend - p - 1)) + 6 ; #endif // forward solve using D (i,i) and L ((i+1):(k-1),i) for (p++ ; p < pend ; p++) { // W [Li [p]] -= Lx [p] * y ; MULTSUB (Wx,Wz,Li[p], Lx,Lz,p, yx,yz,0) ; } // Scale L (k,0:k-1) for LDL' factorization, compute D (k,k) #ifdef REAL // L(k,i) = y/d lx [0] = yx [0] / di [0] ; // d -= L(k,i) * y dk [0] -= lx [0] * yx [0] ; #else // L(k,i) = conj(y) ; ASSIGN_CONJ (lx,lz,0, yx,yz,0) ; // L(k,i) /= di ; DIV_REAL (lx,lz,0, lx,lz,0, di,0) ; // d -= conj(y) * y / di LDLDOT (dk,0, yx,yz,0, di,0) ; #endif } // determine if column i of L can hold the new L(k,i) entry if (p >= Lp [Lnext [i]]) { // column i needs to grow PRINT1 (("Factor Colrealloc "ID", old Lnz "ID"\n", i, Lnz [i])); if (!CHOLMOD(reallocate_column) (i, lnz + 1, L, Common)) { // out of memory, L is now simplicial symbolic for (i = 0 ; i < n ; i++) { // W [i] = 0 ; CLEAR (Wx,Wz,i) ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, wsize, A->dtype, Common)) ; return (FALSE) ; } Li = L->i ; // L->i, L->x, L->z may have moved Lx = L->x ; #ifdef ZOMPLEX Lz = L->z ; #endif p = Lp [i] + lnz ; // contents of L->p changed ASSERT (p < Lp [Lnext [i]]) ; } // store L (k,i) in the column form matrix of L Li [p] = k ; // Lx [p] = L(k,i) ; ASSIGN (Lx,Lz,p, lx,lz,0) ; Lnz [i]++ ; } //---------------------------------------------------------------------- // ensure abs (d) >= bound if dbound/sbound is given, and store it in L //---------------------------------------------------------------------- p = Lp [k] ; Li [p] = k ; if (k >= (Int) L->minor) { // the matrix is already not positive definite dk [0] = 0 ; } else if (use_bound) { // modify the diagonal to force LL' or LDL' to exist #ifdef DOUBLE dk [0] = CHOLMOD(dbound) (is_ll ? fabs (dk [0]) : dk [0], Common) ; #else dk [0] = CHOLMOD(sbound) (is_ll ? fabs (dk [0]) : dk [0], Common) ; #endif } else if ((is_ll ? (dk [0] <= 0) : (dk [0] == 0)) #ifndef REAL || dk_imaginary #endif ) { // the matrix has just been found to be not positive definite dk [0] = 0 ; L->minor = k ; ERROR (CHOLMOD_NOT_POSDEF, "not positive definite") ; } if (is_ll) { // this is counted as one flop, below dk [0] = sqrt (dk [0]) ; } // Lx [p] = D(k,k) = d ; real part only ASSIGN_REAL (Lx,p, dk,0) ; CLEAR_IMAG (Lx,Lz,p) ; } #undef NEXT if (is_ll) fl += MAX ((Int) kend - (Int) kstart, 0) ; // count sqrt's Common->rowfacfl = fl ; DEBUG (CHOLMOD(dump_factor) (L, "final cholmod_rowfac", Common)) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, wsize, A->dtype, Common)) ; return (TRUE) ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_rowfac.c������������������������������������������0000644�0001751�0000144�00000000770�14552026002�023105� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_l_rowfac.c: int64_t version of cholmod_rowfac //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_rowfac.c" ��������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_rcond_worker.c������������������������������������0000644�0001751�0000144�00000011352�14552026002�024330� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/t_cholmod_rcond_worker: estimate rcond of a factorization //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Return a rough estimate of the reciprocal of the condition number. //------------------------------------------------------------------------------ // LMINMAX macros //------------------------------------------------------------------------------ // Update lmin and lmax for one entry L(j,j) #define FIRST_LMINMAX(Ljj,lmin,lmax) \ { \ Real ljj = Ljj ; \ if (isnan (ljj)) \ { \ return (0) ; \ } \ lmin = ljj ; \ lmax = ljj ; \ } #define LMINMAX(Ljj,lmin,lmax) \ { \ Real ljj = Ljj ; \ if (isnan (ljj)) \ { \ return (0) ; \ } \ if (ljj < lmin) \ { \ lmin = ljj ; \ } \ else if (ljj > lmax) \ { \ lmax = ljj ; \ } \ } //------------------------------------------------------------------------------ // t_cholmod_rcond_worker //------------------------------------------------------------------------------ #include "cholmod_template.h" static double TEMPLATE (cholmod_rcond_worker) ( cholmod_factor *L ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Real lmin = 0 ; Real lmax = 0 ; Real *Lx = L->x ; Int n = L->n ; Int e = (L->xtype == CHOLMOD_COMPLEX) ? 2 : 1 ; //-------------------------------------------------------------------------- // compute the approximate rcond of L //-------------------------------------------------------------------------- if (L->is_super) { //---------------------------------------------------------------------- // L is supernodal //---------------------------------------------------------------------- Int nsuper = L->nsuper ; // number of supernodes in L Int *Lpi = L->pi ; // column pointers for integer pattern Int *Lpx = L->px ; // column pointers for numeric values Int *Super = L->super ; // supernode sizes FIRST_LMINMAX (Lx [0], lmin, lmax) ; // first diagonal entry of L for (Int s = 0 ; s < nsuper ; s++) { Int k1 = Super [s] ; // first column in supernode s Int k2 = Super [s+1] ; // last column in supernode is k2-1 Int psi = Lpi [s] ; // first row index is L->s [psi] Int psend = Lpi [s+1] ; // last row index is L->s [psend-1] Int psx = Lpx [s] ; // first numeric entry is Lx [psx] Int nsrow = psend - psi ; // supernode is nsrow-by-nscol Int nscol = k2 - k1 ; for (Int jj = 0 ; jj < nscol ; jj++) { LMINMAX (Lx [e * (psx + jj + jj*nsrow)], lmin, lmax) ; } } } else { //---------------------------------------------------------------------- // L is simplicial //---------------------------------------------------------------------- Int *Lp = L->p ; if (L->is_ll) { // LL' factorization FIRST_LMINMAX (Lx [Lp [0]], lmin, lmax) ; for (Int j = 1 ; j < n ; j++) { LMINMAX (Lx [e * Lp [j]], lmin, lmax) ; } } else { // LDL' factorization, the diagonal might be negative FIRST_LMINMAX (fabs (Lx [Lp [0]]), lmin, lmax) ; for (Int j = 1 ; j < n ; j++) { LMINMAX (fabs (Lx [e * Lp [j]]), lmin, lmax) ; } } } double rcond = ((double) lmin) / ((double) lmax) ; if (L->is_ll) { rcond = rcond*rcond ; } return (rcond) ; } #undef LMINMAX #undef FIRST_LMINMAX #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_postorder.c�����������������������������������������0000644�0001751�0000144�00000023271�14552026002�023333� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_postorder: postordering of a tree //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Compute the postorder of a tree. #include "cholmod_internal.h" #ifndef NCHOLESKY //------------------------------------------------------------------------------ // dfs //------------------------------------------------------------------------------ // The code below includes both a recursive and non-recursive depth-first-search // of a tree. The recursive code is simpler, but can lead to stack overflow. // It is left here for reference, to understand what the non-recursive code // is computing. To try the recursive version, uncomment the following // #define, or compile the code with -DRECURSIVE. Be aware that stack // overflow may occur. // #define RECURSIVE // #ifdef RECURSIVE // recursive version: a working code for reference only, not actual use static Int dfs // return the new value of k ( Int p, // start a DFS at node p Int k, // start the node numbering at k Int Post [ ], // Post ordering, modified on output Int Head [ ], // Head [p] = youngest child of p; EMPTY on output Int Next [ ], // Next [j] = sibling of j; unmodified Int Pstack [ ] // unused ) { Int j ; // start a DFS at each child of node p for (j = Head [p] ; j != EMPTY ; j = Next [j]) { // start a DFS at child node j k = dfs (j, k, Post, Head, Next, Pstack) ; } Post [k++] = p ; // order node p as the kth node Head [p] = EMPTY ; // link list p no longer needed return (k) ; // the next node will be numbered k } #else // non-recursive version for actual use static Int dfs // return the new value of k ( Int p, // start the DFS at a root node p Int k, // start the node numbering at k Int Post [ ], // Post ordering, modified on output Int Head [ ], // Head [p] = youngest child of p; EMPTY on output Int Next [ ], // Next [j] = sibling of j; unmodified Int Pstack [ ] // workspace of size n, undefined on input or output ) { Int j, phead ; // put the root node on the stack Pstack [0] = p ; phead = 0 ; // while the stack is not empty, do: while (phead >= 0) { // grab the node p from top of the stack and get its youngest child j p = Pstack [phead] ; j = Head [p] ; if (j == EMPTY) { // all children of p ordered. remove p from stack and order it phead-- ; Post [k++] = p ; // order node p as the kth node } else { // leave p on the stack. Start a DFS at child node j by putting // j on the stack and removing j from the list of children of p. Head [p] = Next [j] ; Pstack [++phead] = j ; } } return (k) ; // the next node will be numbered k } #endif //------------------------------------------------------------------------------ // cholmod_postorder //------------------------------------------------------------------------------ // Postorder a tree. The tree is either an elimination tree (the output from // from cholmod_etree) or a component tree (from cholmod_nested_dissection). // // An elimination tree is a complete tree of n nodes with Parent [j] > j or // Parent [j] = EMPTY if j is a root. On output Post [0..n-1] is a complete // permutation vector. // // A component tree is a subset of 0..n-1. Parent [j] = -2 if node j is not // in the component tree. Parent [j] = EMPTY if j is a root of the component // tree, and Parent [j] is in the range 0 to n-1 if j is in the component // tree but not a root. On output, Post [k] is defined only for nodes in // the component tree. Post [k] = j if node j is the kth node in the // postordered component tree, where k is in the range 0 to the number of // components minus 1. // // Node j is ignored and not included in the postorder if Parent [j] < EMPTY. // // As a result, check_parent (Parent, n,...) may fail on input, since // cholmod_check_parent assumes Parent is an elimination tree. Similarly, // cholmod_check_perm (Post, ...) may fail on output, since Post is a partial // permutation if Parent is a component tree. // // An optional node weight can be given. When starting a postorder at node j, // the children of j are ordered in increasing order of their weight. // If no weights are given (Weight is NULL) then children are ordered in // increasing order of their node number. The weight of a node must be in the // range 0 to n-1. Weights outside that range are silently converted to that // range (weights < 0 are treated as zero, and weights >= n are treated as n-1). // // // workspace: Head (n), Iwork (2*n) Int CHOLMOD(postorder) // return # of nodes postordered ( // input: Int *Parent, // size n. Parent [j] = p if p is the parent of j size_t n_input, Int *Weight, // size n, optional. Weight [j] is weight of node j // output: Int *Post, // size n. Post [k] = j is kth in postordered tree cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- Int *Head, *Next, *Pstack, *Iwork ; Int j, p, k, w, nextj ; size_t s ; int ok = TRUE ; Int n = (Int) n_input ; RETURN_IF_NULL_COMMON (EMPTY) ; RETURN_IF_NULL (Parent, EMPTY) ; RETURN_IF_NULL (Post, EMPTY) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- // s = 2*n s = CHOLMOD(mult_size_t) (n_input, (size_t) 2, &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (EMPTY) ; } CHOLMOD(allocate_work) (n, s, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (EMPTY) ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Head = Common->Head ; // size n+1, initially all EMPTY Iwork = Common->Iwork ; Next = Iwork ; // size n Pstack = Iwork + n ; // size n //-------------------------------------------------------------------------- // construct a link list of children for each node //-------------------------------------------------------------------------- if (Weight == NULL) { // in reverse order so children are in ascending order in each list for (j = n-1 ; j >= 0 ; j--) { p = Parent [j] ; if (p >= 0 && p < ((Int) n)) { // add j to the list of children for node p Next [j] = Head [p] ; Head [p] = j ; } } // Head [p] = j if j is the youngest (least-numbered) child of p // Next [j1] = j2 if j2 is the next-oldest sibling of j1 } else { // First, construct a set of link lists according to Weight. // // Whead [w] = j if node j is the first node in bucket w. // Next [j1] = j2 if node j2 follows j1 in a link list. Int *Whead = Pstack ; // use Pstack as workspace for Whead [ for (w = 0 ; w < ((Int) n) ; w++) { Whead [w] = EMPTY ; } // do in forward order, so nodes that ties are ordered by node index for (j = 0 ; j < ((Int) n) ; j++) { p = Parent [j] ; if (p >= 0 && p < ((Int) n)) { w = Weight [j] ; w = MAX (0, w) ; w = MIN (w, ((Int) n) - 1) ; // place node j at the head of link list for weight w Next [j] = Whead [w] ; Whead [w] = j ; } } // traverse weight buckets, placing each node in its parent's list for (w = n-1 ; w >= 0 ; w--) { for (j = Whead [w] ; j != EMPTY ; j = nextj) { nextj = Next [j] ; // put node j in the link list of its parent p = Parent [j] ; ASSERT (p >= 0 && p < ((Int) n)) ; Next [j] = Head [p] ; Head [p] = j ; } } // Whead no longer needed ] // Head [p] = j if j is the lightest child of p // Next [j1] = j2 if j2 is the next-heaviest sibling of j1 } //-------------------------------------------------------------------------- // start a DFS at each root node of the etree //-------------------------------------------------------------------------- k = 0 ; for (j = 0 ; j < ((Int) n) ; j++) { if (Parent [j] == EMPTY) { // j is the root of a tree; start a DFS here k = dfs (j, k, Post, Head, Next, Pstack) ; } } // this would normally be EMPTY already, unless Parent is invalid for (j = 0 ; j < ((Int) n) ; j++) { Head [j] = EMPTY ; } PRINT1 (("postordered "ID" nodes\n", k)) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; return (k) ; } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_psolve_worker.c�����������������������������������0000644�0001751�0000144�00000070643�14552026002�024543� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/t_cholmod_psolve_worker: permutations for cholmod_solve //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // This worker is included just twice into cholmod_solve.c, for both dtypes. // Each method below handles all xtypes (real, complex, and zomplex) itself. #include "cholmod_template.h" //------------------------------------------------------------------------------ // perm //------------------------------------------------------------------------------ // Y = B (P (1:nrow), k1 : min (k1+ncols,ncol)-1) where B is nrow-by-ncol. // // Creates a permuted copy of a contiguous set of columns of B. // Y is already allocated on input. Y must be of sufficient size. Let nk be // the number of columns accessed in B. Y->xtype determines the complexity of // the result. // // If B is real and Y is complex (or zomplex), only the real part of B is // copied into Y. The imaginary part of Y is set to zero. // // If B is complex (or zomplex) and Y is real, both the real and imaginary and // parts of B are returned in Y. Y is returned as nrow-by-2*nk. The even // columns of Y contain the real part of B and the odd columns contain the // imaginary part of B. Y->nzmax must be >= 2*nrow*nk. Otherise, Y is // returned as nrow-by-nk with leading dimension nrow. Y->nzmax must be >= // nrow*nk. // // The case where the input (B) is real and the output (Y) is zomplex is // not used. static void TEMPLATE_DTYPE (perm) ( // input: cholmod_dense *B, // input matrix B Int *Perm, // optional input permutation (can be NULL) Int k1, // first column of B to copy Int ncols, // last column to copy is min(k1+ncols,B->ncol)-1 // input/output: cholmod_dense *Y // output matrix Y, already allocated ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Real *Yx, *Yz, *Bx, *Bz ; Int k2, nk, p, k, j, nrow, ncol, d, dj, j2 ; size_t dual ; ncol = B->ncol ; nrow = B->nrow ; k2 = MIN (k1+ncols, ncol) ; nk = MAX (k2 - k1, 0) ; dual = (Y->xtype == CHOLMOD_REAL && B->xtype != CHOLMOD_REAL) ? 2 : 1 ; d = B->d ; Bx = B->x ; Bz = B->z ; Yx = Y->x ; Yz = Y->z ; Y->nrow = nrow ; Y->ncol = dual*nk ; Y->d = nrow ; ASSERT (((Int) Y->nzmax) >= nrow*nk*dual) ; ASSERT (Y->dtype == B->dtype) ; //-------------------------------------------------------------------------- // Y = B (P (1:nrow), k1:k2-1) //-------------------------------------------------------------------------- switch (Y->xtype) { case CHOLMOD_REAL: switch (B->xtype) { case CHOLMOD_REAL: // Y real, B real for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = nrow * (j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [k + j2] = Bx [p] ; // real } } break ; case CHOLMOD_COMPLEX: // Y real, B complex. Y is nrow-by-2*nk for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = nrow * 2 * (j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [k + j2 ] = Bx [2*p ] ; // real Yx [k + j2 + nrow] = Bx [2*p+1] ; // imag } } break ; case CHOLMOD_ZOMPLEX: // Y real, B zomplex. Y is nrow-by-2*nk for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = nrow * 2 * (j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [k + j2 ] = Bx [p] ; // real Yx [k + j2 + nrow] = Bz [p] ; // imag } } break ; } break ; case CHOLMOD_COMPLEX: switch (B->xtype) { case CHOLMOD_REAL: // Y complex, B real for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = nrow * 2 * (j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [2*k + j2] = Bx [p] ; // real Yx [2*k+1 + j2] = 0 ; // imag } } break ; case CHOLMOD_COMPLEX: // Y complex, B complex for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = nrow * 2 * (j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [2*k + j2] = Bx [2*p ] ; // real Yx [2*k+1 + j2] = Bx [2*p+1] ; // imag } } break ; case CHOLMOD_ZOMPLEX: // Y complex, B zomplex for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = nrow * 2 * (j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [2*k + j2] = Bx [p] ; // real Yx [2*k+1 + j2] = Bz [p] ; // imag } } break ; } break ; case CHOLMOD_ZOMPLEX: switch (B->xtype) { case CHOLMOD_COMPLEX: // Y zomplex, B complex for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = nrow * (j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [k + j2] = Bx [2*p ] ; // real Yz [k + j2] = Bx [2*p+1] ; // imag } } break ; case CHOLMOD_ZOMPLEX: // Y zomplex, B zomplex for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = nrow * (j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [k + j2] = Bx [p] ; // real Yz [k + j2] = Bz [p] ; // imag } } break ; } break ; } } //------------------------------------------------------------------------------ // iperm //------------------------------------------------------------------------------ // X (P (1:nrow), k1 : min (k1+ncols,ncol)-1) = Y where X is nrow-by-ncol. // // Copies and permutes Y into a contiguous set of columns of X. X is already // allocated on input. Y must be of sufficient size. Let nk be the number // of columns accessed in X. X->xtype determines the complexity of the result. // // If X is real and Y is complex (or zomplex), only the real part of B is // copied into X. The imaginary part of Y is ignored. // // If X is complex (or zomplex) and Y is real, both the real and imaginary and // parts of Y are returned in X. Y is nrow-by-2*nk. The even // columns of Y contain the real part of B and the odd columns contain the // imaginary part of B. Y->nzmax must be >= 2*nrow*nk. Otherise, Y is // nrow-by-nk with leading dimension nrow. Y->nzmax must be >= nrow*nk. // // The case where the input (Y) is complex and the output (X) is real, // and the case where the input (Y) is zomplex and the output (X) is real, // are not used. static void TEMPLATE_DTYPE (iperm) ( // input: cholmod_dense *Y, // input matrix Y Int *Perm, // optional input permutation (can be NULL) Int k1, // first column of B to copy Int ncols, // last column to copy is min(k1+ncols,B->ncol)-1 // input/output: cholmod_dense *X // output matrix X, already allocated ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Real *Yx, *Yz, *Xx, *Xz ; Int k2, p, k, j, nrow, ncol, d, dj, j2 ; #ifndef NDEBUG Int nk ; #endif ncol = X->ncol ; nrow = X->nrow ; k2 = MIN (k1+ncols, ncol) ; #ifndef NDEBUG nk = MAX (k2 - k1, 0) ; #endif d = X->d ; Xx = X->x ; Xz = X->z ; Yx = Y->x ; Yz = Y->z ; ASSERT (((Int) Y->nzmax) >= nrow*nk* ((X->xtype != CHOLMOD_REAL && Y->xtype == CHOLMOD_REAL) ? 2:1)) ; ASSERT (Y->dtype == X->dtype) ; //-------------------------------------------------------------------------- // X (P (1:nrow), k1:k2-1) = Y //-------------------------------------------------------------------------- switch (Y->xtype) { case CHOLMOD_REAL: switch (X->xtype) { case CHOLMOD_REAL: // Y real, X real for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = nrow * (j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Xx [p] = Yx [k + j2] ; // real } } break ; case CHOLMOD_COMPLEX: // Y real, X complex. Y is nrow-by-2*nk for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = nrow * 2 * (j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Xx [2*p ] = Yx [k + j2 ] ; // real Xx [2*p+1] = Yx [k + j2 + nrow] ; // imag } } break ; case CHOLMOD_ZOMPLEX: // Y real, X zomplex. Y is nrow-by-2*nk for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = nrow * 2 * (j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Xx [p] = Yx [k + j2 ] ; // real Xz [p] = Yx [k + j2 + nrow] ; // imag } } break ; } break ; case CHOLMOD_COMPLEX: switch (X->xtype) { case CHOLMOD_COMPLEX: // Y complex, X complex for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = nrow * 2 * (j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Xx [2*p ] = Yx [2*k + j2] ; // real Xx [2*p+1] = Yx [2*k+1 + j2] ; // imag } } break ; case CHOLMOD_ZOMPLEX: // Y complex, X zomplex for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = nrow * 2 * (j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Xx [p] = Yx [2*k + j2] ; // real Xz [p] = Yx [2*k+1 + j2] ; // imag } } break ; } break ; case CHOLMOD_ZOMPLEX: switch (X->xtype) { case CHOLMOD_COMPLEX: // Y zomplex, X complex for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = nrow * (j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Xx [2*p ] = Yx [k + j2] ; // real Xx [2*p+1] = Yz [k + j2] ; // imag } } break ; case CHOLMOD_ZOMPLEX: // Y zomplex, X zomplex for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = nrow * (j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Xx [p] = Yx [k + j2] ; // real Xz [p] = Yz [k + j2] ; // imag } } break ; } break ; } } //------------------------------------------------------------------------------ // ptrans //------------------------------------------------------------------------------ // Y = B (P (1:nrow), k1 : min (k1+ncols,ncol)-1)' where B is nrow-by-ncol. // // Creates a permuted and transposed copy of a contiguous set of columns of B. // Y is already allocated on input. Y must be of sufficient size. Let nk be // the number of columns accessed in B. Y->xtype determines the complexity of // the result. // // If B is real and Y is complex (or zomplex), only the real part of B is // copied into Y. The imaginary part of Y is set to zero. // // If B is complex (or zomplex) and Y is real, both the real and imaginary and // parts of B are returned in Y. Y is returned as 2*nk-by-nrow. The even // rows of Y contain the real part of B and the odd rows contain the // imaginary part of B. Y->nzmax must be >= 2*nrow*nk. Otherise, Y is // returned as nk-by-nrow with leading dimension nk. Y->nzmax must be >= // nrow*nk. // // The array transpose is performed, not the complex conjugate transpose. static void TEMPLATE_DTYPE (ptrans) ( // input: cholmod_dense *B, // input matrix B Int *Perm, // optional input permutation (can be NULL) Int k1, // first column of B to copy Int ncols, // last column to copy is min(k1+ncols,B->ncol)-1 // input/output: cholmod_dense *Y // output matrix Y, already allocated ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Real *Yx, *Yz, *Bx, *Bz ; Int k2, nk, p, k, j, nrow, ncol, d, dj, j2 ; size_t dual ; ncol = B->ncol ; nrow = B->nrow ; k2 = MIN (k1+ncols, ncol) ; nk = MAX (k2 - k1, 0) ; dual = (Y->xtype == CHOLMOD_REAL && B->xtype != CHOLMOD_REAL) ? 2 : 1 ; d = B->d ; Bx = B->x ; Bz = B->z ; Yx = Y->x ; Yz = Y->z ; Y->nrow = dual*nk ; Y->ncol = nrow ; Y->d = dual*nk ; ASSERT (((Int) Y->nzmax) >= nrow*nk*dual) ; ASSERT (Y->dtype == B->dtype) ; //-------------------------------------------------------------------------- // Y = B (P (1:nrow), k1:k2-1)' //-------------------------------------------------------------------------- switch (Y->xtype) { case CHOLMOD_REAL: switch (B->xtype) { case CHOLMOD_REAL: // Y real, B real for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = j-k1 ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [j2 + k*nk] = Bx [p] ; // real } } break ; case CHOLMOD_COMPLEX: // Y real, B complex. Y is 2*nk-by-nrow for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = 2*(j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [j2 + k*2*nk] = Bx [2*p ] ; // real Yx [j2+1 + k*2*nk] = Bx [2*p+1] ; // imag } } break ; case CHOLMOD_ZOMPLEX: // Y real, B zomplex. Y is 2*nk-by-nrow for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = 2*(j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [j2 + k*2*nk] = Bx [p] ; // real Yx [j2+1 + k*2*nk] = Bz [p] ; // imag } } break ; } break ; case CHOLMOD_COMPLEX: switch (B->xtype) { case CHOLMOD_REAL: // Y complex, B real for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = 2*(j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [j2 + k*2*nk] = Bx [p] ; // real Yx [j2+1 + k*2*nk] = 0 ; // imag } } break ; case CHOLMOD_COMPLEX: // Y complex, B complex for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = 2*(j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [j2 + k*2*nk] = Bx [2*p ] ; // real Yx [j2+1 + k*2*nk] = Bx [2*p+1] ; // imag } } break ; case CHOLMOD_ZOMPLEX: // Y complex, B zomplex for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = 2*(j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [j2 + k*2*nk] = Bx [p] ; // real Yx [j2+1 + k*2*nk] = Bz [p] ; // imag } } break ; } break ; case CHOLMOD_ZOMPLEX: switch (B->xtype) { case CHOLMOD_REAL: // Y zomplex, B real for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = j-k1 ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [j2 + k*nk] = Bx [p] ; // real Yz [j2 + k*nk] = 0 ; // imag } } break ; case CHOLMOD_COMPLEX: // Y zomplex, B complex for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = j-k1 ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [j2 + k*nk] = Bx [2*p ] ; // real Yz [j2 + k*nk] = Bx [2*p+1] ; // imag } } break ; case CHOLMOD_ZOMPLEX: // Y zomplex, B zomplex for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = j-k1 ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Yx [j2 + k*nk] = Bx [p] ; // real Yz [j2 + k*nk] = Bz [p] ; // imag } } break ; } break ; } } //------------------------------------------------------------------------------ // iptrans //------------------------------------------------------------------------------ // X (P (1:nrow), k1 : min (k1+ncols,ncol)-1) = Y' where X is nrow-by-ncol. // // Copies into a permuted and transposed contiguous set of columns of X. // X is already allocated on input. Y must be of sufficient size. Let nk be // the number of columns accessed in X. X->xtype determines the complexity of // the result. // // If X is real and Y is complex (or zomplex), only the real part of Y is // copied into X. The imaginary part of Y is ignored. // // If X is complex (or zomplex) and Y is real, both the real and imaginary and // parts of X are returned in Y. Y is 2*nk-by-nrow. The even // rows of Y contain the real part of X and the odd rows contain the // imaginary part of X. Y->nzmax must be >= 2*nrow*nk. Otherise, Y is // nk-by-nrow with leading dimension nk. Y->nzmax must be >= nrow*nk. // // The case where Y is complex or zomplex, and X is real, is not used. // // The array transpose is performed, not the complex conjugate transpose. static void TEMPLATE_DTYPE (iptrans) ( // input: cholmod_dense *Y, // input matrix Y Int *Perm, // optional input permutation (can be NULL) Int k1, // first column of X to copy into Int ncols, // last column to copy is min(k1+ncols,X->ncol)-1 // input/output: cholmod_dense *X // output matrix X, already allocated ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Real *Yx, *Yz, *Xx, *Xz ; Int k2, nk, p, k, j, nrow, ncol, d, dj, j2 ; ncol = X->ncol ; nrow = X->nrow ; k2 = MIN (k1+ncols, ncol) ; nk = MAX (k2 - k1, 0) ; d = X->d ; Xx = X->x ; Xz = X->z ; Yx = Y->x ; Yz = Y->z ; ASSERT (((Int) Y->nzmax) >= nrow*nk* ((X->xtype != CHOLMOD_REAL && Y->xtype == CHOLMOD_REAL) ? 2:1)) ; ASSERT (Y->dtype == X->dtype) ; //-------------------------------------------------------------------------- // X (P (1:nrow), k1:k2-1) = Y' //-------------------------------------------------------------------------- switch (Y->xtype) { case CHOLMOD_REAL: switch (X->xtype) { case CHOLMOD_REAL: // Y real, X real for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = j-k1 ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Xx [p] = Yx [j2 + k*nk] ; // real } } break ; case CHOLMOD_COMPLEX: // Y real, X complex. Y is 2*nk-by-nrow for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = 2*(j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Xx [2*p ] = Yx [j2 + k*2*nk] ; // real Xx [2*p+1] = Yx [j2+1 + k*2*nk] ; // imag } } break ; case CHOLMOD_ZOMPLEX: // Y real, X zomplex. Y is 2*nk-by-nrow for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = 2*(j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Xx [p] = Yx [j2 + k*2*nk] ; // real Xz [p] = Yx [j2+1 + k*2*nk] ; // imag } } break ; } break ; case CHOLMOD_COMPLEX: switch (X->xtype) { case CHOLMOD_COMPLEX: // Y complex, X complex for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = 2*(j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Xx [2*p ] = Yx [j2 + k*2*nk] ; // real Xx [2*p+1] = Yx [j2+1 + k*2*nk] ; // imag } } break ; case CHOLMOD_ZOMPLEX: // Y complex, X zomplex for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = 2*(j-k1) ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Xx [p] = Yx [j2 + k*2*nk] ; // real Xz [p] = Yx [j2+1 + k*2*nk] ; // imag } } break ; } break ; case CHOLMOD_ZOMPLEX: switch (X->xtype) { case CHOLMOD_COMPLEX: // Y zomplex, X complex for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = j-k1 ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Xx [2*p ] = Yx [j2 + k*nk] ; // real Xx [2*p+1] = Yz [j2 + k*nk] ; // imag } } break ; case CHOLMOD_ZOMPLEX: // Y zomplex, X zomplex for (j = k1 ; j < k2 ; j++) { dj = d*j ; j2 = j-k1 ; for (k = 0 ; k < nrow ; k++) { p = P(k) + dj ; Xx [p] = Yx [j2 + k*nk] ; // real Xz [p] = Yz [j2 + k*nk] ; // imag } } break ; } break ; } } ���������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_analyze.c�����������������������������������������0000644�0001751�0000144�00000000773�14552026002�023272� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_l_analyze.c: int64_t version of cholmod_analyze //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_analyze.c" �����Matrix/src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_lsolve_template.c���������������������������������0000644�0001751�0000144�00000073651�14552026002�025043� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/t_cholmod_lsolve_template: template for Lx=b or LDx=b //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Template routine to solve Lx=b with unit or non-unit diagonal, or solve // LDx=b. // // The numeric xtype of L and Y must match. Y contains b on input and x on // output, stored in row-form. Y is nrow-by-n, where nrow must equal 1 for the // complex or zomplex cases, and nrow <= 4 for the real case. // // This file is not compiled separately. It is included in // t_cholmod_solve_worker.c instead. It contains no user-callable routines. // // workspace: none // // Supports real, complex, and zomplex factors, and any dtype. // undefine all prior definitions #undef FORM_NAME #undef LSOLVE //------------------------------------------------------------------------------ // define the method //------------------------------------------------------------------------------ #ifdef LL // LL': solve Lx=b with non-unit diagonal #define FORM_NAME(prefix,rank) prefix ## ll_lsolve_ ## rank #elif defined (LD) // LDL': solve LDx=b #define FORM_NAME(prefix,rank) prefix ## ldl_ldsolve_ ## rank #else // LDL': solve Lx=b with unit diagonal #define FORM_NAME(prefix,rank) prefix ## ldl_lsolve_ ## rank #endif // LSOLVE(k) defines the name of a routine for an n-by-k right-hand-side. #define LSOLVE(prefix,rank) FORM_NAME(prefix,rank) #ifdef REAL //------------------------------------------------------------------------------ // LSOLVE (1) //------------------------------------------------------------------------------ // Solve Lx=b, where b has 1 column. static void LSOLVE (PREFIX,1) ( cholmod_factor *L, Real X [ ] // n-by-1 in row form ) { Real *Lx = L->x ; Int *Li = L->i ; Int *Lp = L->p ; Int *Lnz = L->nz ; Int j, n = L->n ; for (j = 0 ; j < n ; ) { // get the start, end, and length of column j Int p = Lp [j] ; Int lnz = Lnz [j] ; Int pend = p + lnz ; // find a chain of supernodes (up to j, j+1, and j+2) if (lnz < 4 || lnz != Lnz [j+1] + 1 || Li [p+1] != j+1) { //------------------------------------------------------------------ // solve with a single column of L //------------------------------------------------------------------ Real y = X [j] ; #ifdef LL y /= Lx [p] ; X [j] = y ; #elif defined (LD) X [j] = y / Lx [p] ; #endif for (p++ ; p < pend ; p++) { X [Li [p]] -= Lx [p] * y ; } j++ ; // advance to next column of L } else if (lnz != Lnz [j+2] + 2 || Li [p+2] != j+2) { //------------------------------------------------------------------ // solve with a supernode of two columns of L //------------------------------------------------------------------ Real y [2] ; Int q = Lp [j+1] ; #ifdef LL y [0] = X [j] / Lx [p] ; y [1] = (X [j+1] - Lx [p+1] * y [0]) / Lx [q] ; X [j ] = y [0] ; X [j+1] = y [1] ; #elif defined (LD) y [0] = X [j] ; y [1] = X [j+1] - Lx [p+1] * y [0] ; X [j ] = y [0] / Lx [p] ; X [j+1] = y [1] / Lx [q] ; #else y [0] = X [j] ; y [1] = X [j+1] - Lx [p+1] * y [0] ; X [j+1] = y [1] ; #endif for (p += 2, q++ ; p < pend ; p++, q++) { X [Li [p]] -= Lx [p] * y [0] + Lx [q] * y [1] ; } j += 2 ; // advance to next column of L } else { //------------------------------------------------------------------ // solve with a supernode of three columns of L //------------------------------------------------------------------ Real y [3] ; Int q = Lp [j+1] ; Int r = Lp [j+2] ; #ifdef LL y [0] = X [j] / Lx [p] ; y [1] = (X [j+1] - Lx [p+1] * y [0]) / Lx [q] ; y [2] = (X [j+2] - Lx [p+2] * y [0] - Lx [q+1] * y [1]) / Lx [r] ; X [j ] = y [0] ; X [j+1] = y [1] ; X [j+2] = y [2] ; #elif defined (LD) y [0] = X [j] ; y [1] = X [j+1] - Lx [p+1] * y [0] ; y [2] = X [j+2] - Lx [p+2] * y [0] - Lx [q+1] * y [1] ; X [j ] = y [0] / Lx [p] ; X [j+1] = y [1] / Lx [q] ; X [j+2] = y [2] / Lx [r] ; #else y [0] = X [j] ; y [1] = X [j+1] - Lx [p+1] * y [0] ; y [2] = X [j+2] - Lx [p+2] * y [0] - Lx [q+1] * y [1] ; X [j+1] = y [1] ; X [j+2] = y [2] ; #endif for (p += 3, q += 2, r++ ; p < pend ; p++, q++, r++) { X [Li [p]] -= Lx [p] * y [0] + Lx [q] * y [1] + Lx [r] * y [2] ; } j += 3 ; // advance to next column of L } } } //------------------------------------------------------------------------------ // LSOLVE (2) //------------------------------------------------------------------------------ // Solve Lx=b, where b has 2 columns static void LSOLVE (PREFIX,2) ( cholmod_factor *L, Real X [ ][2] // n-by-2 in row form ) { Real *Lx = L->x ; Int *Li = L->i ; Int *Lp = L->p ; Int *Lnz = L->nz ; Int j, n = L->n ; for (j = 0 ; j < n ; ) { // get the start, end, and length of column j Int p = Lp [j] ; Int lnz = Lnz [j] ; Int pend = p + lnz ; // find a chain of supernodes (up to j, j+1, and j+2) if (lnz < 4 || lnz != Lnz [j+1] + 1 || Li [p+1] != j+1) { //------------------------------------------------------------------ // solve with a single column of L //------------------------------------------------------------------ Real y [2] ; y [0] = X [j][0] ; y [1] = X [j][1] ; #ifdef LL y [0] /= Lx [p] ; y [1] /= Lx [p] ; X [j][0] = y [0] ; X [j][1] = y [1] ; #elif defined (LD) X [j][0] = y [0] / Lx [p] ; X [j][1] = y [1] / Lx [p] ; #endif for (p++ ; p < pend ; p++) { Int i = Li [p] ; X [i][0] -= Lx [p] * y [0] ; X [i][1] -= Lx [p] * y [1] ; } j++ ; // advance to next column of L } else if (lnz != Lnz [j+2] + 2 || Li [p+2] != j+2) { //------------------------------------------------------------------ // solve with a supernode of two columns of L //------------------------------------------------------------------ Real y [2][2] ; Int q = Lp [j+1] ; y [0][0] = X [j][0] ; y [0][1] = X [j][1] ; #ifdef LL y [0][0] /= Lx [p] ; y [0][1] /= Lx [p] ; y [1][0] = (X [j+1][0] - Lx [p+1] * y [0][0]) / Lx [q] ; y [1][1] = (X [j+1][1] - Lx [p+1] * y [0][1]) / Lx [q] ; X [j ][0] = y [0][0] ; X [j ][1] = y [0][1] ; X [j+1][0] = y [1][0] ; X [j+1][1] = y [1][1] ; #elif defined (LD) y [1][0] = X [j+1][0] - Lx [p+1] * y [0][0] ; y [1][1] = X [j+1][1] - Lx [p+1] * y [0][1] ; X [j ][0] = y [0][0] / Lx [p] ; X [j ][1] = y [0][1] / Lx [p] ; X [j+1][0] = y [1][0] / Lx [q] ; X [j+1][1] = y [1][1] / Lx [q] ; #else y [1][0] = X [j+1][0] - Lx [p+1] * y [0][0] ; y [1][1] = X [j+1][1] - Lx [p+1] * y [0][1] ; X [j+1][0] = y [1][0] ; X [j+1][1] = y [1][1] ; #endif for (p += 2, q++ ; p < pend ; p++, q++) { Int i = Li [p] ; X [i][0] -= Lx [p] * y [0][0] + Lx [q] * y [1][0] ; X [i][1] -= Lx [p] * y [0][1] + Lx [q] * y [1][1] ; } j += 2 ; // advance to next column of L } else { //------------------------------------------------------------------ // solve with a supernode of three columns of L //------------------------------------------------------------------ Real y [3][2] ; Int q = Lp [j+1] ; Int r = Lp [j+2] ; y [0][0] = X [j][0] ; y [0][1] = X [j][1] ; #ifdef LL y [0][0] /= Lx [p] ; y [0][1] /= Lx [p] ; y [1][0] = (X [j+1][0] - Lx[p+1] * y[0][0]) / Lx [q] ; y [1][1] = (X [j+1][1] - Lx[p+1] * y[0][1]) / Lx [q] ; y [2][0] = (X [j+2][0] - Lx[p+2] * y[0][0] - Lx[q+1]*y[1][0])/Lx[r]; y [2][1] = (X [j+2][1] - Lx[p+2] * y[0][1] - Lx[q+1]*y[1][1])/Lx[r]; X [j ][0] = y [0][0] ; X [j ][1] = y [0][1] ; X [j+1][0] = y [1][0] ; X [j+1][1] = y [1][1] ; X [j+2][0] = y [2][0] ; X [j+2][1] = y [2][1] ; #elif defined (LD) y [1][0] = X [j+1][0] - Lx [p+1] * y [0][0] ; y [1][1] = X [j+1][1] - Lx [p+1] * y [0][1] ; y [2][0] = X [j+2][0] - Lx [p+2] * y [0][0] - Lx [q+1] * y [1][0] ; y [2][1] = X [j+2][1] - Lx [p+2] * y [0][1] - Lx [q+1] * y [1][1] ; X [j ][0] = y [0][0] / Lx [p] ; X [j ][1] = y [0][1] / Lx [p] ; X [j+1][0] = y [1][0] / Lx [q] ; X [j+1][1] = y [1][1] / Lx [q] ; X [j+2][0] = y [2][0] / Lx [r] ; X [j+2][1] = y [2][1] / Lx [r] ; #else y [1][0] = X [j+1][0] - Lx [p+1] * y [0][0] ; y [1][1] = X [j+1][1] - Lx [p+1] * y [0][1] ; y [2][0] = X [j+2][0] - Lx [p+2] * y [0][0] - Lx [q+1] * y [1][0] ; y [2][1] = X [j+2][1] - Lx [p+2] * y [0][1] - Lx [q+1] * y [1][1] ; X [j+1][0] = y [1][0] ; X [j+1][1] = y [1][1] ; X [j+2][0] = y [2][0] ; X [j+2][1] = y [2][1] ; #endif for (p += 3, q += 2, r++ ; p < pend ; p++, q++, r++) { Int i = Li [p] ; X[i][0] -= Lx[p] * y[0][0] + Lx[q] * y[1][0] + Lx[r] * y[2][0] ; X[i][1] -= Lx[p] * y[0][1] + Lx[q] * y[1][1] + Lx[r] * y[2][1] ; } j += 3 ; // advance to next column of L } } } //------------------------------------------------------------------------------ // LSOLVE (3) //------------------------------------------------------------------------------ // Solve Lx=b, where b has 3 columns static void LSOLVE (PREFIX,3) ( cholmod_factor *L, Real X [ ][3] // n-by-3 in row form ) { Real *Lx = L->x ; Int *Li = L->i ; Int *Lp = L->p ; Int *Lnz = L->nz ; Int j, n = L->n ; for (j = 0 ; j < n ; ) { // get the start, end, and length of column j Int p = Lp [j] ; Int lnz = Lnz [j] ; Int pend = p + lnz ; // find a chain of supernodes (up to j, j+1, and j+2) if (lnz < 4 || lnz != Lnz [j+1] + 1 || Li [p+1] != j+1) { //------------------------------------------------------------------ // solve with a single column of L //------------------------------------------------------------------ Real y [3] ; y [0] = X [j][0] ; y [1] = X [j][1] ; y [2] = X [j][2] ; #ifdef LL y [0] /= Lx [p] ; y [1] /= Lx [p] ; y [2] /= Lx [p] ; X [j][0] = y [0] ; X [j][1] = y [1] ; X [j][2] = y [2] ; #elif defined (LD) X [j][0] = y [0] / Lx [p] ; X [j][1] = y [1] / Lx [p] ; X [j][2] = y [2] / Lx [p] ; #endif for (p++ ; p < pend ; p++) { Int i = Li [p] ; Real lx = Lx [p] ; X [i][0] -= lx * y [0] ; X [i][1] -= lx * y [1] ; X [i][2] -= lx * y [2] ; } j++ ; // advance to next column of L } else if (lnz != Lnz [j+2] + 2 || Li [p+2] != j+2) { //------------------------------------------------------------------ // solve with a supernode of two columns of L //------------------------------------------------------------------ Real y [2][3] ; Int q = Lp [j+1] ; y [0][0] = X [j][0] ; y [0][1] = X [j][1] ; y [0][2] = X [j][2] ; #ifdef LL y [0][0] /= Lx [p] ; y [0][1] /= Lx [p] ; y [0][2] /= Lx [p] ; y [1][0] = (X [j+1][0] - Lx [p+1] * y [0][0]) / Lx [q] ; y [1][1] = (X [j+1][1] - Lx [p+1] * y [0][1]) / Lx [q] ; y [1][2] = (X [j+1][2] - Lx [p+1] * y [0][2]) / Lx [q] ; X [j ][0] = y [0][0] ; X [j ][1] = y [0][1] ; X [j ][2] = y [0][2] ; X [j+1][0] = y [1][0] ; X [j+1][1] = y [1][1] ; X [j+1][2] = y [1][2] ; #elif defined (LD) y [1][0] = X [j+1][0] - Lx [p+1] * y [0][0] ; y [1][1] = X [j+1][1] - Lx [p+1] * y [0][1] ; y [1][2] = X [j+1][2] - Lx [p+1] * y [0][2] ; X [j ][0] = y [0][0] / Lx [p] ; X [j ][1] = y [0][1] / Lx [p] ; X [j ][2] = y [0][2] / Lx [p] ; X [j+1][0] = y [1][0] / Lx [q] ; X [j+1][1] = y [1][1] / Lx [q] ; X [j+1][2] = y [1][2] / Lx [q] ; #else y [1][0] = X [j+1][0] - Lx [p+1] * y [0][0] ; y [1][1] = X [j+1][1] - Lx [p+1] * y [0][1] ; y [1][2] = X [j+1][2] - Lx [p+1] * y [0][2] ; X [j+1][0] = y [1][0] ; X [j+1][1] = y [1][1] ; X [j+1][2] = y [1][2] ; #endif for (p += 2, q++ ; p < pend ; p++, q++) { Int i = Li [p] ; Real lx [2] ; lx [0] = Lx [p] ; lx [1] = Lx [q] ; X [i][0] -= lx [0] * y [0][0] + lx [1] * y [1][0] ; X [i][1] -= lx [0] * y [0][1] + lx [1] * y [1][1] ; X [i][2] -= lx [0] * y [0][2] + lx [1] * y [1][2] ; } j += 2 ; // advance to next column of L } else { //------------------------------------------------------------------ // solve with a supernode of three columns of L //------------------------------------------------------------------ Real y [3][3] ; Int q = Lp [j+1] ; Int r = Lp [j+2] ; y [0][0] = X [j][0] ; y [0][1] = X [j][1] ; y [0][2] = X [j][2] ; #ifdef LL y [0][0] /= Lx [p] ; y [0][1] /= Lx [p] ; y [0][2] /= Lx [p] ; y [1][0] = (X [j+1][0] - Lx[p+1] * y[0][0]) / Lx [q] ; y [1][1] = (X [j+1][1] - Lx[p+1] * y[0][1]) / Lx [q] ; y [1][2] = (X [j+1][2] - Lx[p+1] * y[0][2]) / Lx [q] ; y [2][0] = (X [j+2][0] - Lx[p+2] * y[0][0] - Lx[q+1]*y[1][0])/Lx[r]; y [2][1] = (X [j+2][1] - Lx[p+2] * y[0][1] - Lx[q+1]*y[1][1])/Lx[r]; y [2][2] = (X [j+2][2] - Lx[p+2] * y[0][2] - Lx[q+1]*y[1][2])/Lx[r]; X [j ][0] = y [0][0] ; X [j ][1] = y [0][1] ; X [j ][2] = y [0][2] ; X [j+1][0] = y [1][0] ; X [j+1][1] = y [1][1] ; X [j+1][2] = y [1][2] ; X [j+2][0] = y [2][0] ; X [j+2][1] = y [2][1] ; X [j+2][2] = y [2][2] ; #elif defined (LD) y [1][0] = X [j+1][0] - Lx [p+1] * y [0][0] ; y [1][1] = X [j+1][1] - Lx [p+1] * y [0][1] ; y [1][2] = X [j+1][2] - Lx [p+1] * y [0][2] ; y [2][0] = X [j+2][0] - Lx [p+2] * y [0][0] - Lx [q+1] * y [1][0] ; y [2][1] = X [j+2][1] - Lx [p+2] * y [0][1] - Lx [q+1] * y [1][1] ; y [2][2] = X [j+2][2] - Lx [p+2] * y [0][2] - Lx [q+1] * y [1][2] ; X [j ][0] = y [0][0] / Lx [p] ; X [j ][1] = y [0][1] / Lx [p] ; X [j ][2] = y [0][2] / Lx [p] ; X [j+1][0] = y [1][0] / Lx [q] ; X [j+1][1] = y [1][1] / Lx [q] ; X [j+1][2] = y [1][2] / Lx [q] ; X [j+2][0] = y [2][0] / Lx [r] ; X [j+2][1] = y [2][1] / Lx [r] ; X [j+2][2] = y [2][2] / Lx [r] ; #else y [1][0] = X [j+1][0] - Lx [p+1] * y [0][0] ; y [1][1] = X [j+1][1] - Lx [p+1] * y [0][1] ; y [1][2] = X [j+1][2] - Lx [p+1] * y [0][2] ; y [2][0] = X [j+2][0] - Lx [p+2] * y [0][0] - Lx [q+1] * y [1][0] ; y [2][1] = X [j+2][1] - Lx [p+2] * y [0][1] - Lx [q+1] * y [1][1] ; y [2][2] = X [j+2][2] - Lx [p+2] * y [0][2] - Lx [q+1] * y [1][2] ; X [j+1][0] = y [1][0] ; X [j+1][1] = y [1][1] ; X [j+1][2] = y [1][2] ; X [j+2][0] = y [2][0] ; X [j+2][1] = y [2][1] ; X [j+2][2] = y [2][2] ; #endif for (p += 3, q += 2, r++ ; p < pend ; p++, q++, r++) { Int i = Li [p] ; Real lx [3] ; lx [0] = Lx [p] ; lx [1] = Lx [q] ; lx [2] = Lx [r] ; X [i][0] -= lx[0] * y[0][0] + lx[1] * y[1][0] + lx[2] * y[2][0]; X [i][1] -= lx[0] * y[0][1] + lx[1] * y[1][1] + lx[2] * y[2][1]; X [i][2] -= lx[0] * y[0][2] + lx[1] * y[1][2] + lx[2] * y[2][2]; } j += 3 ; // advance to next column of L } } } //------------------------------------------------------------------------------ // LSOLVE (4) //------------------------------------------------------------------------------ // Solve Lx=b, where b has 4 columns static void LSOLVE (PREFIX,4) ( cholmod_factor *L, Real X [ ][4] // n-by-4 in row form ) { Real *Lx = L->x ; Int *Li = L->i ; Int *Lp = L->p ; Int *Lnz = L->nz ; Int j, n = L->n ; for (j = 0 ; j < n ; ) { // get the start, end, and length of column j Int p = Lp [j] ; Int lnz = Lnz [j] ; Int pend = p + lnz ; // find a chain of supernodes (up to j, j+1, and j+2) if (lnz < 4 || lnz != Lnz [j+1] + 1 || Li [p+1] != j+1) { //------------------------------------------------------------------ // solve with a single column of L //------------------------------------------------------------------ Real y [4] ; y [0] = X [j][0] ; y [1] = X [j][1] ; y [2] = X [j][2] ; y [3] = X [j][3] ; #ifdef LL y [0] /= Lx [p] ; y [1] /= Lx [p] ; y [2] /= Lx [p] ; y [3] /= Lx [p] ; X [j][0] = y [0] ; X [j][1] = y [1] ; X [j][2] = y [2] ; X [j][3] = y [3] ; #elif defined (LD) X [j][0] = y [0] / Lx [p] ; X [j][1] = y [1] / Lx [p] ; X [j][2] = y [2] / Lx [p] ; X [j][3] = y [3] / Lx [p] ; #endif for (p++ ; p < pend ; p++) { Int i = Li [p] ; Real lx = Lx [p] ; X [i][0] -= lx * y [0] ; X [i][1] -= lx * y [1] ; X [i][2] -= lx * y [2] ; X [i][3] -= lx * y [3] ; } j++ ; // advance to next column of L } else if (lnz != Lnz [j+2] + 2 || Li [p+2] != j+2) { //------------------------------------------------------------------ // solve with a supernode of two columns of L //------------------------------------------------------------------ Real y [2][4] ; Int q = Lp [j+1] ; y [0][0] = X [j][0] ; y [0][1] = X [j][1] ; y [0][2] = X [j][2] ; y [0][3] = X [j][3] ; #ifdef LL y [0][0] /= Lx [p] ; y [0][1] /= Lx [p] ; y [0][2] /= Lx [p] ; y [0][3] /= Lx [p] ; y [1][0] = (X [j+1][0] - Lx [p+1] * y [0][0]) / Lx [q] ; y [1][1] = (X [j+1][1] - Lx [p+1] * y [0][1]) / Lx [q] ; y [1][2] = (X [j+1][2] - Lx [p+1] * y [0][2]) / Lx [q] ; y [1][3] = (X [j+1][3] - Lx [p+1] * y [0][3]) / Lx [q] ; X [j ][0] = y [0][0] ; X [j ][1] = y [0][1] ; X [j ][2] = y [0][2] ; X [j ][3] = y [0][3] ; X [j+1][0] = y [1][0] ; X [j+1][1] = y [1][1] ; X [j+1][2] = y [1][2] ; X [j+1][3] = y [1][3] ; #elif defined (LD) y [1][0] = X [j+1][0] - Lx [p+1] * y [0][0] ; y [1][1] = X [j+1][1] - Lx [p+1] * y [0][1] ; y [1][2] = X [j+1][2] - Lx [p+1] * y [0][2] ; y [1][3] = X [j+1][3] - Lx [p+1] * y [0][3] ; X [j ][0] = y [0][0] / Lx [p] ; X [j ][1] = y [0][1] / Lx [p] ; X [j ][2] = y [0][2] / Lx [p] ; X [j ][3] = y [0][3] / Lx [p] ; X [j+1][0] = y [1][0] / Lx [q] ; X [j+1][1] = y [1][1] / Lx [q] ; X [j+1][2] = y [1][2] / Lx [q] ; X [j+1][3] = y [1][3] / Lx [q] ; #else y [1][0] = X [j+1][0] - Lx [p+1] * y [0][0] ; y [1][1] = X [j+1][1] - Lx [p+1] * y [0][1] ; y [1][2] = X [j+1][2] - Lx [p+1] * y [0][2] ; y [1][3] = X [j+1][3] - Lx [p+1] * y [0][3] ; X [j+1][0] = y [1][0] ; X [j+1][1] = y [1][1] ; X [j+1][2] = y [1][2] ; X [j+1][3] = y [1][3] ; #endif for (p += 2, q++ ; p < pend ; p++, q++) { Int i = Li [p] ; Real lx [2] ; lx [0] = Lx [p] ; lx [1] = Lx [q] ; X [i][0] -= lx [0] * y [0][0] + lx [1] * y [1][0] ; X [i][1] -= lx [0] * y [0][1] + lx [1] * y [1][1] ; X [i][2] -= lx [0] * y [0][2] + lx [1] * y [1][2] ; X [i][3] -= lx [0] * y [0][3] + lx [1] * y [1][3] ; } j += 2 ; // advance to next column of L } else { //------------------------------------------------------------------ // solve with a supernode of three columns of L //------------------------------------------------------------------ Real y [3][4] ; Int q = Lp [j+1] ; Int r = Lp [j+2] ; y [0][0] = X [j][0] ; y [0][1] = X [j][1] ; y [0][2] = X [j][2] ; y [0][3] = X [j][3] ; #ifdef LL y [0][0] /= Lx [p] ; y [0][1] /= Lx [p] ; y [0][2] /= Lx [p] ; y [0][3] /= Lx [p] ; y [1][0] = (X [j+1][0] - Lx[p+1] * y[0][0]) / Lx [q] ; y [1][1] = (X [j+1][1] - Lx[p+1] * y[0][1]) / Lx [q] ; y [1][2] = (X [j+1][2] - Lx[p+1] * y[0][2]) / Lx [q] ; y [1][3] = (X [j+1][3] - Lx[p+1] * y[0][3]) / Lx [q] ; y [2][0] = (X [j+2][0] - Lx[p+2] * y[0][0] - Lx[q+1]*y[1][0])/Lx[r]; y [2][1] = (X [j+2][1] - Lx[p+2] * y[0][1] - Lx[q+1]*y[1][1])/Lx[r]; y [2][2] = (X [j+2][2] - Lx[p+2] * y[0][2] - Lx[q+1]*y[1][2])/Lx[r]; y [2][3] = (X [j+2][3] - Lx[p+2] * y[0][3] - Lx[q+1]*y[1][3])/Lx[r]; X [j ][0] = y [0][0] ; X [j ][1] = y [0][1] ; X [j ][2] = y [0][2] ; X [j ][3] = y [0][3] ; X [j+1][0] = y [1][0] ; X [j+1][1] = y [1][1] ; X [j+1][2] = y [1][2] ; X [j+1][3] = y [1][3] ; X [j+2][0] = y [2][0] ; X [j+2][1] = y [2][1] ; X [j+2][2] = y [2][2] ; X [j+2][3] = y [2][3] ; #elif defined (LD) y [1][0] = X [j+1][0] - Lx [p+1] * y [0][0] ; y [1][1] = X [j+1][1] - Lx [p+1] * y [0][1] ; y [1][2] = X [j+1][2] - Lx [p+1] * y [0][2] ; y [1][3] = X [j+1][3] - Lx [p+1] * y [0][3] ; y [2][0] = X [j+2][0] - Lx [p+2] * y [0][0] - Lx [q+1] * y [1][0] ; y [2][1] = X [j+2][1] - Lx [p+2] * y [0][1] - Lx [q+1] * y [1][1] ; y [2][2] = X [j+2][2] - Lx [p+2] * y [0][2] - Lx [q+1] * y [1][2] ; y [2][3] = X [j+2][3] - Lx [p+2] * y [0][3] - Lx [q+1] * y [1][3] ; X [j ][0] = y [0][0] / Lx [p] ; X [j ][1] = y [0][1] / Lx [p] ; X [j ][2] = y [0][2] / Lx [p] ; X [j ][3] = y [0][3] / Lx [p] ; X [j+1][0] = y [1][0] / Lx [q] ; X [j+1][1] = y [1][1] / Lx [q] ; X [j+1][2] = y [1][2] / Lx [q] ; X [j+1][3] = y [1][3] / Lx [q] ; X [j+2][0] = y [2][0] / Lx [r] ; X [j+2][1] = y [2][1] / Lx [r] ; X [j+2][2] = y [2][2] / Lx [r] ; X [j+2][3] = y [2][3] / Lx [r] ; #else y [1][0] = X [j+1][0] - Lx [p+1] * y [0][0] ; y [1][1] = X [j+1][1] - Lx [p+1] * y [0][1] ; y [1][2] = X [j+1][2] - Lx [p+1] * y [0][2] ; y [1][3] = X [j+1][3] - Lx [p+1] * y [0][3] ; y [2][0] = X [j+2][0] - Lx [p+2] * y [0][0] - Lx [q+1] * y [1][0] ; y [2][1] = X [j+2][1] - Lx [p+2] * y [0][1] - Lx [q+1] * y [1][1] ; y [2][2] = X [j+2][2] - Lx [p+2] * y [0][2] - Lx [q+1] * y [1][2] ; y [2][3] = X [j+2][3] - Lx [p+2] * y [0][3] - Lx [q+1] * y [1][3] ; X [j+1][0] = y [1][0] ; X [j+1][1] = y [1][1] ; X [j+1][2] = y [1][2] ; X [j+1][3] = y [1][3] ; X [j+2][0] = y [2][0] ; X [j+2][1] = y [2][1] ; X [j+2][2] = y [2][2] ; X [j+2][3] = y [2][3] ; #endif for (p += 3, q += 2, r++ ; p < pend ; p++, q++, r++) { Int i = Li [p] ; Real lx [3] ; lx [0] = Lx [p] ; lx [1] = Lx [q] ; lx [2] = Lx [r] ; X [i][0] -= lx[0] * y[0][0] + lx[1] * y[1][0] + lx[2] * y[2][0]; X [i][1] -= lx[0] * y[0][1] + lx[1] * y[1][1] + lx[2] * y[2][1]; X [i][2] -= lx[0] * y[0][2] + lx[1] * y[1][2] + lx[2] * y[2][2]; X [i][3] -= lx[0] * y[0][3] + lx[1] * y[1][3] + lx[2] * y[2][3]; } j += 3 ; // advance to next column of L } } } #endif //------------------------------------------------------------------------------ // LSOLVE (k) //------------------------------------------------------------------------------ static void LSOLVE (PREFIX,k) ( cholmod_factor *L, cholmod_dense *Y, // nr-by-n where nr is 1 to 4 cholmod_sparse *Yset // input pattern Yset ) { Real yx [2] ; #ifdef ZOMPLEX Real yz [1] ; Real *Lz = L->z ; Real *Xz = Y->z ; #endif Real *Lx = L->x ; Real *Xx = Y->x ; Int *Li = L->i ; Int *Lp = L->p ; Int *Lnz = L->nz ; Int n = L->n ; ASSERT (L->xtype == Y->xtype) ; // L and Y must have the same xtype ASSERT (L->dtype == Y->dtype) ; // L and Y must have the same dtype ASSERT (L->n == Y->ncol) ; // dimensions must match ASSERT (Y->nrow == Y->d) ; // leading dimension of Y = # rows of Y ASSERT (L->xtype != CHOLMOD_PATTERN) ; // L is not symbolic ASSERT (!(L->is_super)) ; // L is simplicial LL' or LDL' #ifdef REAL if (Yset == NULL) { //---------------------------------------------------------------------- // real case, no Yset, with 1 to 4 RHS's and dynamic supernodes //---------------------------------------------------------------------- ASSERT (Y->nrow <= 4) ; switch (Y->nrow) { case 1: LSOLVE (PREFIX,1) (L, Y->x) ; break ; case 2: LSOLVE (PREFIX,2) (L, Y->x) ; break ; case 3: LSOLVE (PREFIX,3) (L, Y->x) ; break ; case 4: LSOLVE (PREFIX,4) (L, Y->x) ; break ; } } else #endif { //---------------------------------------------------------------------- // solve a complex linear system or solve with Yset //---------------------------------------------------------------------- ASSERT (Y->nrow == 1) ; Int *Ysetp = (Yset == NULL) ? NULL : Yset->p ; Int *Yseti = (Yset == NULL) ? NULL : Yset->i ; Int ysetlen = (Yset == NULL) ? n : Ysetp [1] ; for (Int jj = 0 ; jj < ysetlen ; jj++) { Int j = Yseti ? Yseti [jj] : jj ; // get the start, end, and length of column j Int p = Lp [j] ; Int lnz = Lnz [j] ; Int pend = p + lnz ; // y = X [j] ASSIGN (yx,yz,0, Xx,Xz,j) ; #ifdef LL // y /= Lx [p] // X [j] = y DIV_REAL (yx,yz,0, yx,yz,0, Lx,p) ; ASSIGN (Xx,Xz,j, yx,yz,0) ; #elif defined (LD) // X [j] = y / Lx [p] DIV_REAL (Xx,Xz,j, yx,yz,0, Lx,p) ; #endif for (p++ ; p < pend ; p++) { // X [Li [p]] -= Lx [p] * y Int i = Li [p] ; MULTSUB (Xx,Xz,i, Lx,Lz,p, yx,yz,0) ; } } } } // prepare for the next inclusion of this file in cholmod_solve.c #undef LL #undef LD ���������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_analyze.c�������������������������������������������0000644�0001751�0000144�00000104176�14552026002�022761� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_analyze: order and analyze a matrix //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Order and analyze a matrix (either simplicial or supernodal), in prepartion // for numerical factorization via cholmod_factorize or via the "expert" // routines cholmod_rowfac and cholmod_super_numeric. // // symmetric case: A or A(p,p) // unsymmetric case: AA', A(p,:)*A(p,:)', A(:,f)*A(:,f)', or A(p,f)*A(p,f)' // // For the symmetric case, only the upper or lower triangular part of A is // accessed (depending on the type of A). LL'=A (or permuted A) is analzed. // For the unsymmetric case (LL'=AA' or permuted A). // // There can be no duplicate entries in p or f. p is of length m if A is // m-by-n. f can be length 0 to n. // // In both cases, the columns of A need not be sorted. A can be in packed // or unpacked form. // // Ordering options include: // // natural: A is not permuted to reduce fill-in // given: a permutation can be provided to this routine (UserPerm) // AMD: approximate minumum degree (AMD for the symmetric case, // COLAMD for the AA' case). // METIS: nested dissection with METIS_NodeND // NESDIS: nested dissection using METIS_ComputeVertexSeparator, // typically followed by a constrained minimum degree // (CAMD for the symmetric case, CCOLAMD for the AA' case). // // Multiple ordering options can be tried (up to 9 of them), and the best one // is selected (the one that gives the smallest number of nonzeros in the // simplicial factor L). If one method fails, cholmod_analyze keeps going, and // picks the best among the methods that succeeded. This routine fails (and // returns NULL) if either initial memory allocation fails, all ordering methods // fail, or the supernodal analysis (if requested) fails. By default, the 9 // methods available are: // // 1) given permutation (skipped if UserPerm is NULL) // 2) AMD (symmetric case) or COLAMD (unsymmetric case) // 3) METIS with default parameters // 4) NESDIS with default parameters (stopping the partitioning when // the graph is of size nd_small = 200 or less, remove nodes with // more than max (16, prune_dense * sqrt (n)) nodes where // prune_dense = 10, and follow partitioning with CCOLAMD, a // constrained minimum degree ordering). // 5) natural // 6) NESDIS, nd_small = 20000, prune_dense = 10 // 7) NESDIS, nd_small = 4, prune_dense = 10, no min degree // 8) NESDIS, nd_small = 200, prune_dense = 0 // 9) COLAMD for A*A' or AMD for A // // By default, the first two are tried, and METIS is tried if AMD reports a high // flop count and fill-in. Let fl denote the flop count for the AMD, ordering, // nnz(L) the # of nonzeros in L, and nnz(tril(A)) (or A*A'). If // fl/nnz(L) >= 500 and nnz(L)/nnz(tril(A)) >= 5, then METIS is attempted. The // best ordering is used (UserPerm if given, AMD, and METIS if attempted). If // you do not have METIS, only the first two will be tried (user permutation, // if provided, and AMD/COLAMD). This default behavior is obtained when // Common->nmethods is zero. In this case, methods 0, 1, and 2 in // Common->method [..] are reset to User-provided, AMD, and METIS (or NESDIS // if Common->default_nesdis is set to the non-default value of TRUE), // respectively. // // You can modify these 9 methods and the number of methods tried by changing // parameters in the Common argument. If you know the best ordering for your // matrix, set Common->nmethods to 1 and set Common->method[0].ordering to the // requested ordering method. Parameters for each method can also be modified // (refer to cholmod.h for details). // // Note that it is possible for METIS to terminate your program if it runs out // of memory. This is not the case for any CHOLMOD or minimum degree ordering // routine (AMD, COLAMD, CAMD, CCOLAMD, or CSYMAMD). Since NESDIS relies on // METIS, it too can terminate your program. // // The factor L is returned as simplicial symbolic (L->is_super FALSE) if // Common->supernodal <= CHOLMOD_SIMPLICIAL (0) or as supernodal symbolic if // Common->supernodal >= CHOLMOD_SUPERNODAL (2). If Common->supernodal is // equal to CHOLMOD_AUTO (1), then L is simplicial if the flop count per // nonzero in L is less than Common->supernodal_switch (default: 40), and // is returned as a supernodal factor otherwise. // // In both cases, L->xtype is CHOLMOD_PATTERN. // A subsequent call to cholmod_factorize will perform a // simplicial or supernodal factorization, depending on the type of L. // // For the simplicial case, L contains the fill-reducing permutation (L->Perm) // and the counts of nonzeros in each column of L (L->ColCount). For the // supernodal case, L also contains the nonzero pattern of each supernode. // // workspace: Flag (nrow), Head (nrow+1) // if symmetric: Iwork (6*nrow) // if unsymmetric: Iwork (6*nrow+ncol). // calls various ordering routines, which typically allocate O(nnz(A)) // temporary workspace ((2 to 3)*nnz(A) * sizeof (Int) is typical, but it // can be much higher if A*A' must be explicitly formed for METIS). Also // allocates up to 2 temporary (permuted/transpose) copies of the nonzero // pattern of A, and up to 3*n*sizeof(Int) additional workspace. // // Supports any xtype (pattern, real, complex, or zomplex) and any dtype. #include "cholmod_internal.h" #ifndef NCHOLESKY //------------------------------------------------------------------------------ // cholmod_analyze //------------------------------------------------------------------------------ // Orders and analyzes A, AA', PAP', or PAA'P' and returns a symbolic factor // that can later be passed to cholmod_factorize. cholmod_factor *CHOLMOD(analyze) // returns symbolic factor L ( // input: cholmod_sparse *A, // matrix to order and analyze cholmod_common *Common ) { return (CHOLMOD(analyze_p2) (TRUE, A, NULL, NULL, 0, Common)) ; } //------------------------------------------------------------------------------ // cholmod_analyze_p //------------------------------------------------------------------------------ // Orders and analyzes A, AA', PAP', PAA'P', FF', or PFF'P and returns a // symbolic factor that can later be passed to cholmod_factorize, where // F = A(:,fset) if fset is not NULL and A->stype is zero. // UserPerm is tried if non-NULL. cholmod_factor *CHOLMOD(analyze_p) // returns symbolic factor L ( // input: cholmod_sparse *A, // matrix to order and analyze Int *UserPerm, // user-provided permutation, size A->nrow Int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset cholmod_common *Common ) { return (CHOLMOD(analyze_p2) (TRUE, A, UserPerm, fset, fsize, Common)) ; } //------------------------------------------------------------------------------ // permute_matrices //------------------------------------------------------------------------------ // Permute and transpose a matrix. Allocates the A1 and A2 matrices, if needed, // or returns them as NULL if not needed. static int permute_matrices ( // input: cholmod_sparse *A, // matrix to permute Int ordering, // ordering method used Int *Perm, // fill-reducing permutation Int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset Int do_rowcolcounts,// if TRUE, compute both S and F. If FALSE, only // S is needed for the symmetric case, and only F for // the unsymmetric case // output: cholmod_sparse **A1_handle, // see comments below for A1, A2, S, F cholmod_sparse **A2_handle, cholmod_sparse **S_handle, cholmod_sparse **F_handle, cholmod_common *Common ) { cholmod_sparse *A1, *A2, *S, *F ; *A1_handle = NULL ; *A2_handle = NULL ; *S_handle = NULL ; *F_handle = NULL ; A1 = NULL ; A2 = NULL ; if (ordering == CHOLMOD_NATURAL) { //---------------------------------------------------------------------- // natural ordering of A //---------------------------------------------------------------------- if (A->stype < 0) { // symmetric lower case: A already in lower form, so S=A' // workspace: Iwork (nrow) A2 = CHOLMOD(ptranspose) (A, 0, NULL, NULL, 0, Common) ; F = A ; S = A2 ; } else if (A->stype > 0) { // symmetric upper case: F = pattern of triu (A)', S = A // workspace: Iwork (nrow) if (do_rowcolcounts) { // F not needed for symmetric case if do_rowcolcounts FALSE A1 = CHOLMOD(ptranspose) (A, 0, NULL, fset, fsize, Common) ; } F = A1 ; S = A ; } else { // unsymmetric case: F = pattern of A (:,f)', S = A // workspace: Iwork (nrow if no fset, MAX(nrow,ncol) if fset) A1 = CHOLMOD(ptranspose) (A, 0, NULL, fset, fsize, Common) ; F = A1 ; S = A ; } } else { //---------------------------------------------------------------------- // A is permuted //---------------------------------------------------------------------- if (A->stype < 0) { // symmetric lower case: S = tril (A (p,p))' and F = S' // workspace: Iwork (2*nrow) A2 = CHOLMOD(ptranspose) (A, 0, Perm, NULL, 0, Common) ; S = A2 ; // workspace: Iwork (nrow) if (do_rowcolcounts) { // F not needed for symmetric case if do_rowcolcounts FALSE A1 = CHOLMOD(ptranspose) (A2, 0, NULL, NULL, 0, Common) ; } F = A1 ; } else if (A->stype > 0) { // symmetric upper case: F = triu (A (p,p))' and S = F' // workspace: Iwork (2*nrow) A1 = CHOLMOD(ptranspose) (A, 0, Perm, NULL, 0, Common) ; F = A1 ; // workspace: Iwork (nrow) A2 = CHOLMOD(ptranspose) (A1, 0, NULL, NULL, 0, Common) ; S = A2 ; } else { // unsymmetric case: F = A (p,f)' and S = F' // workspace: Iwork (nrow if no fset, MAX(nrow,ncol) if fset) A1 = CHOLMOD(ptranspose) (A, 0, Perm, fset, fsize, Common) ; F = A1 ; if (do_rowcolcounts) { // S not needed for unsymmetric case if do_rowcolcounts FALSE // workspace: Iwork (nrow) A2 = CHOLMOD(ptranspose) (A1, 0, NULL, NULL, 0, Common) ; } S = A2 ; } } // If any cholmod_*transpose fails, one or more matrices will be NULL *A1_handle = A1 ; *A2_handle = A2 ; *S_handle = S ; *F_handle = F ; return (Common->status == CHOLMOD_OK) ; } //------------------------------------------------------------------------------ // cholmod_analyze_ordering //------------------------------------------------------------------------------ // Given a matrix A and its fill-reducing permutation, compute the elimination // tree, its (non-weighted) postordering, and the number of nonzeros in each // column of L. Also computes the flop count, the total nonzeros in L, and // the nonzeros in A (Common->fl, Common->lnz, and Common->anz). // // The column counts of L, flop count, and other statistics from // cholmod_rowcolcounts are not computed if ColCount is NULL. // // workspace: Iwork (2*nrow if symmetric, 2*nrow+ncol if unsymmetric), // Flag (nrow), Head (nrow+1) int CHOLMOD(analyze_ordering) ( // input: cholmod_sparse *A, // matrix to analyze int ordering, // ordering method used Int *Perm, // size n, fill-reducing permutation to analyze Int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset // output: Int *Parent, // size n, elimination tree Int *Post, // size n, postordering of elimination tree Int *ColCount, // size n, nnz in each column of L // workspace: Int *First, // size n workspace for cholmod_postorder Int *Level, // size n workspace for cholmod_postorder cholmod_common *Common ) { cholmod_sparse *A1, *A2, *S, *F ; Int n, ok, do_rowcolcounts ; // check inputs RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; n = A->nrow ; do_rowcolcounts = (ColCount != NULL) ; // permute A according to Perm and fset ok = permute_matrices (A, ordering, Perm, fset, fsize, do_rowcolcounts, &A1, &A2, &S, &F, Common) ; // find etree of S (symmetric upper/lower case) or F (unsym case) // workspace: symmmetric: Iwork (nrow), unsym: Iwork (nrow+ncol) ok = ok && CHOLMOD(etree) (A->stype ? S:F, Parent, Common) ; // postorder the etree (required by cholmod_rowcolcounts) // workspace: Iwork (2*nrow) ok = ok && (CHOLMOD(postorder) (Parent, n, NULL, Post, Common) == n) ; // cholmod_postorder doesn't set Common->status if it returns < n Common->status = (!ok && Common->status == CHOLMOD_OK) ? CHOLMOD_INVALID : Common->status ; // analyze LL'=S or SS' or S(:,f)*S(:,f)' // workspace: // if symmetric: Flag (nrow), Iwork (2*nrow) // if unsymmetric: Flag (nrow), Iwork (2*nrow+ncol), Head (nrow+1) if (do_rowcolcounts) { ok = ok && CHOLMOD(rowcolcounts) (A->stype ? F:S, fset, fsize, Parent, Post, NULL, ColCount, First, Level, Common) ; } // free temporary matrices and return result CHOLMOD(free_sparse) (&A1, Common) ; CHOLMOD(free_sparse) (&A2, Common) ; return (ok) ; } //------------------------------------------------------------------------------ // Free workspace and return L //------------------------------------------------------------------------------ #define FREE_WORKSPACE_AND_RETURN \ { \ Common->no_workspace_reallocate = FALSE ; \ CHOLMOD(free) (n, sizeof (Int), Lparent, Common) ; \ CHOLMOD(free) (n, sizeof (Int), Perm, Common) ; \ CHOLMOD(free) (n, sizeof (Int), ColCount, Common) ; \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_factor) (&L, Common) ; \ } \ ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; \ return (L) ; \ } //------------------------------------------------------------------------------ // cholmod_analyze_p2 //------------------------------------------------------------------------------ // Ordering and analysis for sparse Cholesky or sparse QR. cholmod_factor *CHOLMOD(analyze_p2) ( // input: int for_whom, // FOR_SPQR (0): for SPQR but not GPU-accelerated // FOR_CHOLESKY (1): for Cholesky (GPU or not) // FOR_SPQRGPU (2): for SPQR with GPU acceleration cholmod_sparse *A, // matrix to order and analyze Int *UserPerm, // user-provided permutation, size A->nrow Int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset cholmod_common *Common ) { double lnz_best ; Int *First, *Level, *Work4n, *Cmember, *CParent, *ColCount, *Lperm, *Parent, *Post, *Perm, *Lparent, *Lcolcount ; cholmod_factor *L ; Int k, n, method, nmethods, status, default_strategy, skip_analysis, skip_best ; Int amd_backup ; int ok = TRUE ; //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_NULL (A, NULL) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, NULL) ; Common->status = CHOLMOD_OK ; status = CHOLMOD_OK ; Common->selected = EMPTY ; Common->called_nd = FALSE ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- n = A->nrow ; //-------------------------------------------------------------------------- // set the default strategy //-------------------------------------------------------------------------- lnz_best = (double) EMPTY ; skip_best = FALSE ; nmethods = MIN (Common->nmethods, CHOLMOD_MAXMETHODS) ; nmethods = MAX (0, nmethods) ; #ifndef NDEBUG PRINT1 (("cholmod_analyze_p2 :: nmethods "ID"\n", nmethods)) ; for (method = 0 ; method < nmethods ; method++) { PRINT1 ((" "ID": ordering "ID"\n", method, Common->method [method].ordering)) ; } #endif default_strategy = (nmethods == 0) ; if (default_strategy) { // default strategy: try UserPerm, if given. Try AMD for A, or AMD // to order A*A'. Try METIS for the symmetric case only if AMD reports // a high degree of fill-in and flop count. METIS is not tried if the // Partition Module isn't installed. If Common->default_nesdis is // TRUE, then NESDIS is used as the 3rd ordering instead. Common->method [0].ordering = CHOLMOD_GIVEN ; // skip if UserPerm NULL Common->method [1].ordering = CHOLMOD_AMD ; Common->method [2].ordering = (Common->default_nesdis ? CHOLMOD_NESDIS : CHOLMOD_METIS) ; amd_backup = FALSE ; #ifndef NPARTITION nmethods = 3 ; #else nmethods = 2 ; #endif } else { // If only METIS and NESDIS are selected, or if 2 or more methods are // being tried, then enable AMD backup amd_backup = (nmethods > 1) || (nmethods == 1 && (Common->method [0].ordering == CHOLMOD_METIS || Common->method [0].ordering == CHOLMOD_NESDIS || (Common->method [0].ordering == CHOLMOD_GIVEN && UserPerm == NULL))) ; } #ifdef NSUPERNODAL // CHOLMOD Supernodal module not installed, just do simplicial analysis Common->supernodal = CHOLMOD_SIMPLICIAL ; #endif //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- // Note: enough space needs to be allocated here so that routines called by // cholmod_analyze do not reallocate the space. // s = 6*nrow + uncol size_t uncol = (A->stype == 0) ? (A->ncol) : 0 ; size_t s = CHOLMOD(mult_size_t) (A->nrow, 6, &ok) ; s = CHOLMOD(add_size_t) (s, uncol, &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (NULL) ; } CHOLMOD(allocate_work) (A->nrow, s, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (NULL) ; // out of memory } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; // ensure that subsequent routines, called by cholmod_analyze, do not // reallocate any workspace. This is set back to FALSE in the // FREE_WORKSPACE_AND_RETURN macro, which is the only way this function // returns to its caller. Common->no_workspace_reallocate = TRUE ; // Use the last 4*n Int's in Iwork for Parent, First, Level, and Post, since // other CHOLMOD routines will use the first 2n+uncol space. The ordering // routines (cholmod_amd, cholmod_colamd, cholmod_ccolamd, cholmod_metis) // are an exception. They can use all 6n + ncol space, since the contents // of Parent, First, Level, and Post are not needed across calls to those // routines. Work4n = Common->Iwork ; Work4n += 2*((size_t) n) + uncol ; Parent = Work4n ; First = Work4n + n ; Level = Work4n + 2*((size_t) n) ; Post = Work4n + 3*((size_t) n) ; // note that this assignment means that cholmod_nested_dissection, // cholmod_ccolamd, and cholmod_camd can use only the first 4n+uncol // space in Common->Iwork Cmember = Post ; CParent = Level ; //-------------------------------------------------------------------------- // allocate more workspace, and an empty simplicial symbolic factor //-------------------------------------------------------------------------- // Numerical values are not yet in L for the symbolic analysis here, but // set its dtype the same as A, for the numerical factorization: L = CHOLMOD(alloc_factor) (n, A->dtype, Common) ; Lparent = CHOLMOD(malloc) (n, sizeof (Int), Common) ; Perm = CHOLMOD(malloc) (n, sizeof (Int), Common) ; ColCount = CHOLMOD(malloc) (n, sizeof (Int), Common) ; if (Common->status < CHOLMOD_OK) { // out of memory FREE_WORKSPACE_AND_RETURN ; } Lperm = L->Perm ; Lcolcount = L->ColCount ; Common->anz = EMPTY ; //-------------------------------------------------------------------------- // try all the requested ordering options and backup to AMD if needed //-------------------------------------------------------------------------- // turn off error handling [ Common->try_catch = TRUE ; for (method = 0 ; method <= nmethods ; method++) { //---------------------------------------------------------------------- // determine the method to try //---------------------------------------------------------------------- Int ordering ; Common->fl = EMPTY ; Common->lnz = EMPTY ; skip_analysis = FALSE ; if (method == nmethods) { // All methods failed: backup to AMD if (Common->selected == EMPTY && amd_backup) { ordering = CHOLMOD_AMD ; } else { break ; } } else { ordering = Common->method [method].ordering ; } Common->current = method ; //---------------------------------------------------------------------- // find the fill-reducing permutation //---------------------------------------------------------------------- if (ordering == CHOLMOD_NATURAL) { //------------------------------------------------------------------ // natural ordering //------------------------------------------------------------------ for (k = 0 ; k < n ; k++) { Perm [k] = k ; } } else if (ordering == CHOLMOD_GIVEN) { //------------------------------------------------------------------ // use given ordering of A, if provided //------------------------------------------------------------------ if (UserPerm == NULL) { // this is not an error condition continue ; } for (k = 0 ; k < n ; k++) { // UserPerm is checked in cholmod_ptranspose Perm [k] = UserPerm [k] ; } } else if (ordering == CHOLMOD_AMD) { //------------------------------------------------------------------ // AMD ordering of A, A*A', or A(:,f)*A(:,f)' //------------------------------------------------------------------ amd_backup = FALSE ; // no need to try AMD twice ... CHOLMOD(amd) (A, fset, fsize, Perm, Common) ; skip_analysis = TRUE ; } else if (ordering == CHOLMOD_COLAMD) { //------------------------------------------------------------------ // AMD for symmetric case, COLAMD for A*A' or A(:,f)*A(:,f)' //------------------------------------------------------------------ if (A->stype) { CHOLMOD(amd) (A, fset, fsize, Perm, Common) ; skip_analysis = TRUE ; } else { // do not postorder, it is done later, below // workspace: Iwork (4*nrow+uncol), Flag (nrow), Head (nrow+1) CHOLMOD(colamd) (A, fset, fsize, FALSE, Perm, Common) ; } } else if (ordering == CHOLMOD_METIS) { //------------------------------------------------------------------ // use METIS_NodeND directly (via a CHOLMOD wrapper) //------------------------------------------------------------------ #ifndef NPARTITION // postorder parameter is false, because it will be later, below // workspace: Iwork (4*nrow+uncol), Flag (nrow), Head (nrow+1) Common->called_nd = TRUE ; CHOLMOD(metis) (A, fset, fsize, FALSE, Perm, Common) ; #else Common->status = CHOLMOD_NOT_INSTALLED ; #endif } else if (ordering == CHOLMOD_NESDIS) { //------------------------------------------------------------------ // use CHOLMOD's nested dissection //------------------------------------------------------------------ // this method is based on METIS' node bissection routine // (METIS_ComputeVertexSeparator). In contrast to METIS_NodeND, // it calls CAMD or CCOLAMD on the whole graph, instead of MMD // on just the leaves. #ifndef NPARTITION // workspace: Flag (nrow), Head (nrow+1), Iwork (2*nrow) Common->called_nd = TRUE ; CHOLMOD(nested_dissection) (A, fset, fsize, Perm, CParent, Cmember, Common) ; #else Common->status = CHOLMOD_NOT_INSTALLED ; #endif } else { //------------------------------------------------------------------ // invalid ordering method //------------------------------------------------------------------ Common->status = CHOLMOD_INVALID ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; if (Common->status < CHOLMOD_OK) { // out of memory, or method failed status = MIN (status, Common->status) ; Common->status = CHOLMOD_OK ; continue ; } //---------------------------------------------------------------------- // analyze the ordering //---------------------------------------------------------------------- if (!skip_analysis) { if (!CHOLMOD(analyze_ordering) (A, ordering, Perm, fset, fsize, Parent, Post, ColCount, First, Level, Common)) { // ordering method failed; clear status and try next method status = MIN (status, Common->status) ; Common->status = CHOLMOD_OK ; continue ; } } ASSERT (Common->fl >= 0 && Common->lnz >= 0) ; Common->method [method].fl = Common->fl ; Common->method [method].lnz = Common->lnz ; //---------------------------------------------------------------------- // pick the best method //---------------------------------------------------------------------- // fl.pt. compare, but lnz can never be NaN if (Common->selected == EMPTY || Common->lnz < lnz_best) { Common->selected = method ; L->ordering = ordering ; lnz_best = Common->lnz ; for (k = 0 ; k < n ; k++) { Lperm [k] = Perm [k] ; } // save the results of cholmod_analyze_ordering, if it was called skip_best = skip_analysis ; if (!skip_analysis) { // save the column count; becomes permanent part of L for (k = 0 ; k < n ; k++) { Lcolcount [k] = ColCount [k] ; } // Parent is needed for weighted postordering and for supernodal // analysis. Does not become a permanent part of L for (k = 0 ; k < n ; k++) { Lparent [k] = Parent [k] ; } } } //---------------------------------------------------------------------- // determine if METIS is to be skipped //---------------------------------------------------------------------- if (default_strategy && ordering == CHOLMOD_AMD) { if ((Common->fl < 500 * Common->lnz) || (Common->lnz < 5 * Common->anz)) { // AMD found an ordering with less than 500 flops per nonzero in // L, or one with a fill-in ratio (nnz(L)/nnz(A)) of less than // 5. This is pretty good, and it's unlikely that METIS will do // better (this heuristic is based on tests on all symmetric // positive definite matrices in the SuiteSparse Matrix // Collection, and it works well across a wide range of // problems). METIS can take much more time than AMD. break ; } } } // turn error printing back on ] Common->try_catch = FALSE ; //-------------------------------------------------------------------------- // return if no ordering method succeeded //-------------------------------------------------------------------------- if (Common->selected == EMPTY) { // All methods failed. // If two or more methods failed, they may have failed for different // reasons. Both would clear Common->status and skip to the next // method. Common->status needs to be restored here to the worst error // obtained in any of the methods. CHOLMOD_INVALID is worse // than CHOLMOD_OUT_OF_MEMORY, since the former implies something may // be wrong with the user's input. CHOLMOD_OUT_OF_MEMORY is simply an // indication of lack of resources. status = (status >= CHOLMOD_OK) ? CHOLMOD_INVALID : status ; ERROR (status, "all methods failed") ; FREE_WORKSPACE_AND_RETURN ; } //-------------------------------------------------------------------------- // do the analysis for AMD, if skipped //-------------------------------------------------------------------------- Common->fl = Common->method [Common->selected].fl ; Common->lnz = Common->method [Common->selected].lnz ; ASSERT (Common->lnz >= 0) ; if (skip_best) { if (!CHOLMOD(analyze_ordering) (A, L->ordering, Lperm, fset, fsize, Lparent, Post, Lcolcount, First, Level, Common)) { // out of memory, or method failed FREE_WORKSPACE_AND_RETURN ; } } //-------------------------------------------------------------------------- // postorder the etree, weighted by the column counts //-------------------------------------------------------------------------- if (Common->postorder) { // combine the fill-reducing ordering with the weighted postorder // workspace: Iwork (2*nrow) if (CHOLMOD(postorder) (Lparent, n, Lcolcount, Post, Common) == n) { // use First and Level as workspace [ Int *Wi = First, *InvPost = Level ; Int newchild, oldchild, newparent, oldparent ; for (k = 0 ; k < n ; k++) { Wi [k] = Lperm [Post [k]] ; } for (k = 0 ; k < n ; k++) { Lperm [k] = Wi [k] ; } for (k = 0 ; k < n ; k++) { Wi [k] = Lcolcount [Post [k]] ; } for (k = 0 ; k < n ; k++) { Lcolcount [k] = Wi [k] ; } for (k = 0 ; k < n ; k++) { InvPost [Post [k]] = k ; } // updated Lparent needed only for supernodal case for (newchild = 0 ; newchild < n ; newchild++) { oldchild = Post [newchild] ; oldparent = Lparent [oldchild] ; newparent = (oldparent == EMPTY) ? EMPTY : InvPost [oldparent] ; Wi [newchild] = newparent ; } for (k = 0 ; k < n ; k++) { Lparent [k] = Wi [k] ; } // done using Iwork as workspace ] // L is now postordered, no longer in natural ordering if (L->ordering == CHOLMOD_NATURAL) { L->ordering = CHOLMOD_POSTORDERED ; } } } //-------------------------------------------------------------------------- // supernodal analysis, if requested or if selected automatically //-------------------------------------------------------------------------- #ifndef NSUPERNODAL if (Common->supernodal > CHOLMOD_AUTO || (Common->supernodal == CHOLMOD_AUTO && Common->lnz > 0 && (Common->fl / Common->lnz) >= Common->supernodal_switch)) { cholmod_sparse *S, *F, *A2, *A1 ; permute_matrices (A, L->ordering, Lperm, fset, fsize, TRUE, &A1, &A2, &S, &F, Common) ; // workspace: Flag (nrow), Head (nrow), Iwork (5*nrow) CHOLMOD(super_symbolic2) (for_whom, S, F, Lparent, L, Common) ; CHOLMOD(free_sparse) (&A1, Common) ; CHOLMOD(free_sparse) (&A2, Common) ; } #endif //-------------------------------------------------------------------------- // free temporary matrices and workspace, and return result L //-------------------------------------------------------------------------- FREE_WORKSPACE_AND_RETURN ; } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_amd.c�����������������������������������������������0000644�0001751�0000144�00000014715�14552026002�022056� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_amd: AMD interface for CHOLMOD //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // CHOLMOD interface to the AMD ordering routine. Orders A if the matrix is // symmetric. On output, Perm [k] = i if row/column i of A is the kth // row/column of P*A*P'. This corresponds to A(p,p) in MATLAB notation. // // If A is unsymmetric, cholmod_amd orders A*A'. On output, Perm [k] = i if // row/column i of A*A' is the kth row/column of P*A*A'*P'. This corresponds to // A(p,:)*A(p,:)' in MATLAB notation. If f is present, A(p,f)*A(p,f)' is // ordered. // // Computes the flop count for a subsequent LL' factorization, the number // of nonzeros in L, and the number of nonzeros in the matrix ordered (A, // A*A' or A(:,f)*A(:,f)'). // // workspace: Iwork (6*nrow). Head (nrow). // // Allocates a temporary copy of A+A' or A*A' (with // both upper and lower triangular parts) as input to AMD. // // Supports any xtype (pattern, real, complex, or zomplex) and any dtype. #include "cholmod_internal.h" #ifndef NCHOLESKY #include "amd.h" #if (!defined (AMD_VERSION) || (AMD_VERSION < AMD_VERSION_CODE (3,3))) #error "CHOLMOD:Cholesky requires AMD 3.3.1 or later" #endif //------------------------------------------------------------------------------ // cholmod_amd //------------------------------------------------------------------------------ int CHOLMOD(amd) ( // input: cholmod_sparse *A, // matrix to order Int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset // output: Int *Perm, // size A->nrow, output permutation cholmod_common *Common ) { double Info [AMD_INFO], Control2 [AMD_CONTROL], *Control ; Int *Cp, *Len, *Nv, *Head, *Elen, *Degree, *Wi, *Iwork, *Next ; cholmod_sparse *C ; Int j, n, cnz ; int ok = TRUE ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; n = A->nrow ; RETURN_IF_NULL (Perm, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; Common->status = CHOLMOD_OK ; if (n == 0) { // nothing to do Common->fl = 0 ; Common->lnz = 0 ; Common->anz = 0 ; return (TRUE) ; } //-------------------------------------------------------------------------- // get workspace //-------------------------------------------------------------------------- // Note: this is less than the space used in cholmod_analyze, so if // cholmod_amd is being called by that routine, no space will be // allocated. // s = MAX (6*nrow, ncol) size_t s = CHOLMOD(mult_size_t) (A->nrow, 6, &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (FALSE) ; } s = MAX (s, A->ncol) ; CHOLMOD(allocate_work) (A->nrow, s, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } Iwork = Common->Iwork ; Degree = Iwork ; // size n Wi = Iwork + n ; // size n Len = Iwork + 2*((size_t) n) ; // size n Nv = Iwork + 3*((size_t) n) ; // size n Next = Iwork + 4*((size_t) n) ; // size n Elen = Iwork + 5*((size_t) n) ; // size n Head = Common->Head ; // size n+1, but only n is used //-------------------------------------------------------------------------- // construct the input matrix for AMD //-------------------------------------------------------------------------- if (A->stype == 0) { // C = A*A' or A(:,f)*A(:,f)', add extra space of nnz(C)/2+n to C C = CHOLMOD(aat) (A, fset, fsize, -2, Common) ; } else { // C = A+A', but use only the upper triangular part of A if A->stype = 1 // and only the lower part of A if A->stype = -1. Add extra space of // nnz(C)/2+n to C. C = CHOLMOD(copy) (A, 0, -2, Common) ; } if (Common->status < CHOLMOD_OK) { // out of memory, fset invalid, or other error return (FALSE) ; } Cp = C->p ; for (j = 0 ; j < n ; j++) { Len [j] = Cp [j+1] - Cp [j] ; } // C does not include the diagonal, and both upper and lower parts. // Common->anz includes the diagonal, and just the lower part of C cnz = Cp [n] ; Common->anz = cnz / 2 + n ; //-------------------------------------------------------------------------- // order C using AMD //-------------------------------------------------------------------------- // get parameters if (Common->current < 0 || Common->current >= CHOLMOD_MAXMETHODS) { // use AMD defaults Control = NULL ; } else { Control = Control2 ; Control [AMD_DENSE] = Common->method [Common->current].prune_dense ; Control [AMD_AGGRESSIVE] = Common->method [Common->current].aggressive ; } #if defined ( CHOLMOD_INT64 ) amd_l2 (n, C->p, C->i, Len, C->nzmax, cnz, Nv, Next, Perm, Head, Elen, Degree, Wi, Control, Info) ; #else amd_2 (n, C->p, C->i, Len, C->nzmax, cnz, Nv, Next, Perm, Head, Elen, Degree, Wi, Control, Info) ; #endif // LL' flop count. Need to subtract n for LL' flop count. Note that this // is a slight upper bound which is often exact (see AMD/Source/amd_2.c for // details). cholmod_analyze computes an exact flop count and fill-in. Common->fl = Info [AMD_NDIV] + 2 * Info [AMD_NMULTSUBS_LDL] + n ; // Info [AMD_LNZ] excludes the diagonal Common->lnz = n + Info [AMD_LNZ] ; //-------------------------------------------------------------------------- // free the AMD workspace and clear the persistent workspace in Common //-------------------------------------------------------------------------- ASSERT (IMPLIES (Common->status == CHOLMOD_OK, CHOLMOD(dump_perm) (Perm, n, n, "AMD2 perm", Common))) ; CHOLMOD(free_sparse) (&C, Common) ; for (j = 0 ; j <= n ; j++) { Head [j] = EMPTY ; } return (TRUE) ; } #endif ���������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_rcond.c���������������������������������������������0000644�0001751�0000144�00000007120�14552026002�022412� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_rcond: estimate the reciprocal of condition number //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Return a rough estimate of the reciprocal of the condition number: // the minimum entry on the diagonal of L (or absolute entry of D for an LDL' // factorization) divided by the maximum entry (squared for LL'). L can be // real, complex, or zomplex. Returns -1 on error, 0 if the matrix is singular // or has a zero entry on the diagonal of L, 1 if the matrix is 0-by-0, or // min(diag(L))/max(diag(L)) otherwise. Never returns NaN; if L has a NaN on // the diagonal it returns zero instead. // // For an LL' factorization, (min(diag(L))/max(diag(L)))^2 is returned. // For an LDL' factorization, (min(diag(D))/max(diag(D))) is returned. // // The real and zomplex cases are the same, since this method only accesses the // the diagonal of L for an LL' factorization, or D for LDL' factorization, // and these entries are always real. #include "cholmod_internal.h" #ifndef NCHOLESKY //------------------------------------------------------------------------------ // t_cholmod_rcond_worker template //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_rcond_worker.c" #define COMPLEX #include "t_cholmod_rcond_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_rcond_worker.c" #define COMPLEX #include "t_cholmod_rcond_worker.c" //------------------------------------------------------------------------------ // cholmod_rcond //------------------------------------------------------------------------------ double CHOLMOD(rcond) // return rcond estimate ( // input: cholmod_factor *L, // factorization to query; not modified cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (EMPTY) ; RETURN_IF_NULL (L, EMPTY) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, EMPTY) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // handle special cases //-------------------------------------------------------------------------- if (L->n == 0) { return (1) ; } if (L->minor < L->n) { return (0) ; } //-------------------------------------------------------------------------- // compute rcond //-------------------------------------------------------------------------- double rcond = 0 ; switch ((L->xtype + L->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: rcond = rs_cholmod_rcond_worker (L) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: rcond = cs_cholmod_rcond_worker (L) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: rcond = rd_cholmod_rcond_worker (L) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: rcond = cd_cholmod_rcond_worker (L) ; break ; } return (rcond) ; } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_factorize.c�����������������������������������������0000644�0001751�0000144�00000037074�14552026002�023306� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_factorize: numerical Cholesky factorization //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Computes the numerical factorization of a symmetric matrix. The primary // inputs to this routine are a sparse matrix A and the symbolic factor L from // cholmod_analyze or a prior numerical factor L. If A is symmetric, this // routine factorizes A(p,p)+beta*I (beta can be zero), where p is the // fill-reducing permutation (L->Perm). If A is unsymmetric, either // A(p,:)*A(p,:)'+beta*I or A(p,f)*A(p,f)'+beta*I is factorized. The set f and // the nonzero pattern of the matrix A must be the same as the matrix passed to // cholmod_analyze for the supernodal case. For the simplicial case, it can // be different, but it should be the same for best performance. beta is real. // // A simplicial factorization or supernodal factorization is chosen, based on // the type of the factor L. If L->is_super is TRUE, a supernodal LL' // factorization is computed. Otherwise, a simplicial numeric factorization // is computed, either LL' or LDL', depending on Common->final_ll. // // Once the factorization is complete, it can be left as is or optionally // converted into any simplicial numeric type, depending on the // Common->final_* parameters. If converted from a supernodal to simplicial // type, and the Common->final_resymbol parameter is true, then numerically // zero entries in L due to relaxed supernodal amalgamation are removed from // the simplicial factor (they are always left in the supernodal form of L). // Entries that are numerically zero but present in the simplicial symbolic // pattern of L are left in place (that is, the graph of L remains chordal). // This is required for the update/downdate/rowadd/rowdel routines to work // properly. // // workspace: Flag (nrow), Head (nrow+1), // if symmetric: Iwork (2*nrow+2*nsuper) // if unsymmetric: Iwork (2*nrow+MAX(2*nsuper,ncol)) // where nsuper is 0 if simplicial, or the # of relaxed supernodes in // L otherwise (nsuper <= nrow). // if simplicial: W (nrow). // Allocates up to two temporary copies of its input matrix (including // both pattern and numerical values). // // If the matrix is not positive definite the routine returns TRUE, but // sets Common->status to CHOLMOD_NOT_POSDEF and L->minor is set to the // column at which the failure occurred. Columns L->minor to L->n-1 are // set to zero. // // Supports any xtype (pattern, real, complex, or zomplex), except that the // input matrix A cannot be pattern-only. If L is simplicial, its numeric // xtype matches A on output. If L is supernodal, its xtype is real if A is // real, or complex if A is complex or zomplex. // // The factorization L is computed with the same dtype as A (L->dtype will // be the same as A->dtype). #include "cholmod_internal.h" #ifndef NCHOLESKY //------------------------------------------------------------------------------ // cholmod_factorize //------------------------------------------------------------------------------ // Factorizes PAP' (or PAA'P' if A->stype is 0), using a factor obtained // from cholmod_analyze. The analysis can be re-used simply by calling this // routine a second time with another matrix. A must have the same nonzero // pattern as that passed to cholmod_analyze. int CHOLMOD(factorize) ( // input: cholmod_sparse *A, // matrix to factorize // input/output: cholmod_factor *L, // resulting factorization cholmod_common *Common ) { double zero [2] ; zero [0] = 0 ; zero [1] = 0 ; return (CHOLMOD(factorize_p) (A, zero, NULL, 0, L, Common)) ; } //------------------------------------------------------------------------------ // cholmod_factorize_p //------------------------------------------------------------------------------ // Same as cholmod_factorize, but with more options. int CHOLMOD(factorize_p) ( // input: cholmod_sparse *A, // matrix to factorize double beta [2], // factorize beta*I+A or beta*I+A'*A Int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset // input/output: cholmod_factor *L, // resulting factorization cholmod_common *Common ) { cholmod_sparse *S, *F, *A1, *A2 ; Int nrow, ncol, stype, convert, grow2, status ; int ok = TRUE ; //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (L, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; nrow = A->nrow ; ncol = A->ncol ; stype = A->stype ; if (L->n != A->nrow) { ERROR (CHOLMOD_INVALID, "A and L dimensions do not match") ; return (FALSE) ; } if (stype != 0 && nrow != ncol) { ERROR (CHOLMOD_INVALID, "matrix invalid") ; return (FALSE) ; } DEBUG (CHOLMOD(dump_sparse) (A, "A for cholmod_factorize", Common)) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- size_t nsuper = (L->is_super ? L->nsuper : 0) ; size_t uncol = ((stype != 0) ? 0 : A->ncol) ; // s = 2*nrow + MAX (uncol, 2*nsuper) size_t s = CHOLMOD(mult_size_t) (nsuper, 2, &ok) ; s = MAX (uncol, s) ; size_t t = CHOLMOD(mult_size_t) (A->nrow, 2, &ok) ; s = CHOLMOD(add_size_t) (s, t, &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (FALSE) ; } CHOLMOD(allocate_work) (nrow, s, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } S = NULL ; F = NULL ; A1 = NULL ; A2 = NULL ; // convert to another form when done, if requested convert = !(Common->final_asis) ; //-------------------------------------------------------------------------- // perform supernodal LL' or simplicial LDL' factorization //-------------------------------------------------------------------------- if (L->is_super) { #ifndef NSUPERNODAL //---------------------------------------------------------------------- // supernodal factorization //---------------------------------------------------------------------- if (L->ordering == CHOLMOD_NATURAL) { //------------------------------------------------------------------ // natural ordering //------------------------------------------------------------------ if (stype > 0) { // S = tril (A'), F not needed // workspace: Iwork (nrow) A1 = CHOLMOD(ptranspose) (A, 2, NULL, NULL, 0, Common) ; S = A1 ; } else if (stype < 0) { // This is the fastest option for the natural ordering // S = A; F not needed S = A ; } else { // F = A(:,f)' // workspace: Iwork (nrow) // workspace: Iwork (nrow if no fset; MAX (nrow,ncol) if fset) A1 = CHOLMOD(ptranspose) (A, 2, NULL, fset, fsize, Common) ; F = A1 ; // S = A S = A ; } } else { //------------------------------------------------------------------ // permute the input matrix before factorization //------------------------------------------------------------------ if (stype > 0) { // This is the fastest option for factoring a permuted matrix // S = tril (PAP'); F not needed // workspace: Iwork (2*nrow) A1 = CHOLMOD(ptranspose) (A, 2, L->Perm, NULL, 0, Common) ; S = A1 ; } else if (stype < 0) { // A2 = triu (PAP') // workspace: Iwork (2*nrow) A2 = CHOLMOD(ptranspose) (A, 2, L->Perm, NULL, 0, Common) ; // S = tril (A2'); F not needed // workspace: Iwork (nrow) A1 = CHOLMOD(ptranspose) (A2, 2, NULL, NULL, 0, Common) ; S = A1 ; CHOLMOD(free_sparse) (&A2, Common) ; ASSERT (A2 == NULL) ; } else { // F = A(p,f)' // workspace: Iwork (nrow if no fset; MAX (nrow,ncol) if fset) A1 = CHOLMOD(ptranspose) (A, 2, L->Perm, fset, fsize, Common) ; F = A1 ; // S = F' // workspace: Iwork (nrow) A2 = CHOLMOD(ptranspose) (F, 2, NULL, NULL, 0, Common) ; S = A2 ; } } //---------------------------------------------------------------------- // supernodal factorization //---------------------------------------------------------------------- // workspace: Flag (nrow), Head (nrow+1), Iwork (2*nrow+2*nsuper) if (Common->status == CHOLMOD_OK) { CHOLMOD(super_numeric) (S, F, beta, L, Common) ; } status = Common->status ; ASSERT (IMPLIES (status >= CHOLMOD_OK, L->xtype != CHOLMOD_PATTERN)) ; //---------------------------------------------------------------------- // convert to final form, if requested //---------------------------------------------------------------------- if (Common->status >= CHOLMOD_OK && convert) { // workspace: none ok = CHOLMOD(change_factor) (L->xtype, Common->final_ll, Common->final_super, Common->final_pack, Common->final_monotonic, L, Common) ; if (ok && Common->final_resymbol && !(L->is_super)) { // workspace: Flag (nrow), Head (nrow+1), // if symmetric: Iwork (2*nrow) // if unsymmetric: Iwork (2*nrow+ncol) CHOLMOD(resymbol_noperm) (S, fset, fsize, Common->final_pack, L, Common) ; } } #else //---------------------------------------------------------------------- // CHOLMOD Supernodal module not installed //---------------------------------------------------------------------- status = CHOLMOD_NOT_INSTALLED ; ERROR (CHOLMOD_NOT_INSTALLED,"Supernodal module not installed") ; #endif } else { //---------------------------------------------------------------------- // simplicial LDL' factorization //---------------------------------------------------------------------- // Permute the input matrix A if necessary. cholmod_rowfac requires // triu(A) in column form for the symmetric case, and A in column form // for the unsymmetric case (the matrix S). The unsymmetric case // requires A in row form, or equivalently A' in column form (the // matrix F). if (L->ordering == CHOLMOD_NATURAL) { //------------------------------------------------------------------ // natural ordering //------------------------------------------------------------------ if (stype > 0) { // F is not needed, S = A S = A ; } else if (stype < 0) { // F is not needed, S = A' // workspace: Iwork (nrow) A2 = CHOLMOD(ptranspose) (A, 2, NULL, NULL, 0, Common) ; S = A2 ; } else { // F = A (:,f)' // workspace: Iwork (nrow if no fset; MAX (nrow,ncol) if fset) A1 = CHOLMOD(ptranspose) (A, 2, NULL, fset, fsize, Common) ; F = A1 ; S = A ; } } else { //------------------------------------------------------------------ // permute the input matrix before factorization //------------------------------------------------------------------ if (stype > 0) { // F = tril (A (p,p)') // workspace: Iwork (2*nrow) A1 = CHOLMOD(ptranspose) (A, 2, L->Perm, NULL, 0, Common) ; // A2 = triu (F') // workspace: Iwork (nrow) A2 = CHOLMOD(ptranspose) (A1, 2, NULL, NULL, 0, Common) ; // the symmetric case does not need F, free it and set to NULL CHOLMOD(free_sparse) (&A1, Common) ; } else if (stype < 0) { // A2 = triu (A (p,p)'), F not needed. This is the fastest // way to factorize a matrix using the simplicial routine // (cholmod_rowfac). // workspace: Iwork (2*nrow) A2 = CHOLMOD(ptranspose) (A, 2, L->Perm, NULL, 0, Common) ; } else { // F = A (p,f)' // workspace: Iwork (nrow if no fset; MAX (nrow,ncol) if fset) A1 = CHOLMOD(ptranspose) (A, 2, L->Perm, fset, fsize, Common) ; F = A1 ; // A2 = F' // workspace: Iwork (nrow) A2 = CHOLMOD(ptranspose) (F, 2, NULL, NULL, 0, Common) ; } S = A2 ; } //---------------------------------------------------------------------- // simplicial LDL' or LL' factorization //---------------------------------------------------------------------- // factorize beta*I+S (symmetric) or beta*I+F*F' (unsymmetric) // workspace: Flag (nrow), W (nrow), Iwork (2*nrow) if (Common->status == CHOLMOD_OK) { grow2 = Common->grow2 ; L->is_ll = (Common->final_ll) ? 1 : 0 ; if (L->xtype == CHOLMOD_PATTERN && Common->final_pack) { // allocate a factor with exactly the space required Common->grow2 = 0 ; } CHOLMOD(rowfac) (S, F, beta, 0, nrow, L, Common) ; Common->grow2 = grow2 ; } status = Common->status ; //---------------------------------------------------------------------- // convert to final form, if requested //---------------------------------------------------------------------- if (Common->status >= CHOLMOD_OK && convert) { // workspace: none CHOLMOD(change_factor) (L->xtype, L->is_ll, FALSE, Common->final_pack, Common->final_monotonic, L, Common) ; } } //-------------------------------------------------------------------------- // free A1 and A2 if they exist //-------------------------------------------------------------------------- CHOLMOD(free_sparse) (&A1, Common) ; CHOLMOD(free_sparse) (&A2, Common) ; Common->status = MAX (Common->status, status) ; return (Common->status >= CHOLMOD_OK) ; } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_spsolve.c�����������������������������������������0000644�0001751�0000144�00000000773�14552026002�023322� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_l_spsolve.c: int64_t version of cholmod_spsolve //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_spsolve.c" �����Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_rowfac.c��������������������������������������������0000644�0001751�0000144�00000067357�14552026002�022610� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_rowfac: row-wise numerical LDL' or LL' factorization //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Full or incremental numerical LDL' or LL' factorization (simplicial, not // supernodal) cholmod_factorize is the "easy" wrapper for this code, but it // does not provide access to incremental factorization. // // cholmod_rowfac computes the full or incremental LDL' or LL' factorization of // A+beta*I (where A is symmetric) or A*F+beta*I (where A and F are unsymmetric // and only the upper triangular part of A*F+beta*I is used). It computes // L (and D, for LDL') one row at a time. beta is real. // // A is nrow-by-ncol or nrow-by-nrow. In "packed" form it is a conventional // column-oriented sparse matrix. Row indices of column j are in // Ai [Ap [j] ... Ap [j+1]-1] and values in the same locations of Ax. // will be faster if A has sorted columns. In "unpacked" form the column // of A ends at Ap [j] + Anz [j] - 1 instead of Ap [j+1] - 1. // // Row indices in each column of A can be sorted or unsorted, but the routine // routine works fastest if A is sorted, or if only triu(A) is provided // for the symmetric case. // // The unit-diagonal nrow-by-nrow output matrix L is returned in "unpacked" // column form, with row indices of column j in Li [Lp [j] ... // Lp [j] + Lnz [j] - 1] and values in the same location in Lx. The row // indices in each column of L are in sorted order. The unit diagonal of L // is not stored. // // L can be a simplicial symbolic or numeric (L->is_super must be FALSE). // A symbolic factor is converted immediately into a numeric factor containing // the identity matrix. // // For a full factorization, kstart = 0 and kend = nrow. The existing nonzero // entries (numerical values in L->x and L->z for the zomplex case, and indices // in L->i), if any, are overwritten. // // To compute an incremental factorization, select kstart and kend as the range // of rows of L you wish to compute. A correct factorization will be computed // only if all descendants of all nodes k = kstart to kend-1 in the etree have // been factorized by a prior call to this routine, and if rows kstart to kend-1 // have not been factorized. This condition is NOT checked on input. // // --------------- // Symmetric case: // --------------- // // The factorization (in MATLAB notation) is: // // S = beta*I + A // S = triu (S) + triu (S,1)' // L*D*L' = S, or L*L' = S // // A is a conventional sparse matrix in compressed column form. Only the // diagonal and upper triangular part of A is accessed; the lower // triangular part is ignored and assumed to be equal to the upper // triangular part. For an incremental factorization, only columns kstart // to kend-1 of A are accessed. F is not used. // // --------------- // Unsymmetric case: // --------------- // // The factorization (in MATLAB notation) is: // // S = beta*I + A*F // S = triu (S) + triu (S,1)' // L*D*L' = S, or L*L' = S // // The typical case is F=A'. Alternatively, if F=A(:,f)', then this // routine factorizes S = beta*I + A(:,f)*A(:,f)'. // // All of A and F are accessed, but only the upper triangular part of A*F // is used. F must be of size A->ncol by A->nrow. F is used for the // unsymmetric case only. F can be packed or unpacked and it need not be // sorted. // // For a complete factorization of beta*I + A*A', // this routine performs a number of flops exactly equal to: // // sum (for each column j of A) of (Anz (j)^2 + Anz (j)), to form S // + // sum (for each column j of L) of (Lnz (j)^2 + 3*Lnz (j)), to factorize S // // where Anz (j) is the number of nonzeros in column j of A, and Lnz (j) // is the number of nonzero in column j of L below the diagonal. // // // workspace: Flag (nrow), W (nrow if real, 2*nrow if complex/zomplex), // Iwork (nrow) // // Supports any xtype and dtype, except a pattern-only input matrix A cannot be // factorized. #include "cholmod_internal.h" #ifndef NCHOLESKY //------------------------------------------------------------------------------ // subtree //------------------------------------------------------------------------------ // Compute the nonzero pattern of the sparse triangular solve Lx=b, where L in // this case is L(0:k-1,0:k-1), and b is a column of A. This is done by // traversing the kth row-subtree of the elimination tree of L, starting from // each nonzero entry in b. The pattern is returned postordered, and is valid // for a subsequent numerical triangular solve of Lx=b. The elimination tree // can be provided in a Parent array, or extracted from the pattern of L itself. // // The pattern of x = inv(L)*b is returned in Stack [top...]. // Also scatters b, or a multiple of b, into the work vector W. // // The SCATTER macro is defines how the numerical values of A or A*A' are to be // scattered. // // PARENT(i) is a macro the defines how the etree is accessed. It is either: // #define PARENT(i) Parent [i] // #define PARENT(i) (Lnz [i] > 1) ? (Li [Lp [i] + 1]) : EMPTY // #define SUBTREE \ for ( ; p < pend ; p++) \ { \ i = Ai [p] ; \ if (i <= k) \ { \ /* scatter the column of A, or A*A' into Wx and Wz */ \ SCATTER ; \ /* start at node i and traverse up the subtree, stop at node k */ \ for (len = 0 ; i < k && i != EMPTY && Flag [i] < mark ; i = parent) \ { \ /* L(k,i) is nonzero, and seen for the first time */ \ Stack [len++] = i ; /* place i on the stack */ \ Flag [i] = mark ; /* mark i as visited */ \ parent = PARENT (i) ; /* traverse up the etree to parent */ \ } \ /* move the path down to the bottom of the stack */ \ while (len > 0) \ { \ Stack [--top] = Stack [--len] ; \ } \ } \ else if (sorted) \ { \ break ; \ } \ } //------------------------------------------------------------------------------ // t_cholmod_rowfac template //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_rowfac_worker.c" #define COMPLEX #include "t_cholmod_rowfac_worker.c" #define ZOMPLEX #include "t_cholmod_rowfac_worker.c" #define MASK #define REAL #include "t_cholmod_rowfac_worker.c" #define COMPLEX #include "t_cholmod_rowfac_worker.c" #define ZOMPLEX #include "t_cholmod_rowfac_worker.c" #undef MASK #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_rowfac_worker.c" #define COMPLEX #include "t_cholmod_rowfac_worker.c" #define ZOMPLEX #include "t_cholmod_rowfac_worker.c" #define MASK #define REAL #include "t_cholmod_rowfac_worker.c" #define COMPLEX #include "t_cholmod_rowfac_worker.c" #define ZOMPLEX #include "t_cholmod_rowfac_worker.c" #undef MASK //------------------------------------------------------------------------------ // cholmod_row_subtree //------------------------------------------------------------------------------ // Compute the nonzero pattern of the solution to the lower triangular system // L(0:k-1,0:k-1) * x = A (0:k-1,k) if A is symmetric, or // L(0:k-1,0:k-1) * x = A (0:k-1,:) * A (:,k)' if A is unsymmetric. // This gives the nonzero pattern of row k of L (excluding the diagonal). // The pattern is returned postordered. // // The symmetric case requires A to be in symmetric-upper form. // // The result is returned in R, a pre-allocated sparse matrix of size nrow-by-1, // with R->nzmax >= nrow. R is assumed to be packed (Rnz [0] is not updated); // the number of entries in R is given by Rp [0]. // // FUTURE WORK: a very minor change to this routine could allow it to compute // the nonzero pattern of x for any system Lx=b. The SUBTREE macro would need // to change, to eliminate its dependence on k. // // workspace: Flag (nrow) int CHOLMOD(row_subtree) ( // input: cholmod_sparse *A, // matrix to analyze cholmod_sparse *F, // used for A*A' case only. F=A' or A(:,f)' size_t krow, // row k of L Int *Parent, // elimination tree // output: cholmod_sparse *R, // pattern of L(k,:), 1-by-n with R->nzmax >= n cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- Int *Rp, *Stack, *Flag, *Ap, *Ai, *Anz, *Fp, *Fi, *Fnz ; Int p, pend, parent, t, stype, nrow, k, pf, pfend, Fpacked, packed, sorted, top, len, i, mark ; RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (R, FALSE) ; RETURN_IF_NULL (Parent, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (R, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; stype = A->stype ; if (stype == 0) { RETURN_IF_NULL (F, FALSE) ; RETURN_IF_XTYPE_INVALID (F, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; } if (krow >= A->nrow) { ERROR (CHOLMOD_INVALID, "subtree: k invalid") ; return (FALSE) ; } if (R->ncol != 1 || A->nrow != R->nrow || A->nrow > R->nzmax) { ERROR (CHOLMOD_INVALID, "subtree: R invalid") ; return (FALSE) ; } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- nrow = A->nrow ; CHOLMOD(allocate_work) (nrow, 0, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- if (stype > 0) { // symmetric upper case: F is not needed. It may be NULL Fp = NULL ; Fi = NULL ; Fnz = NULL ; Fpacked = TRUE ; } else if (stype == 0) { // unsymmetric case: F is required. Fp = F->p ; Fi = F->i ; Fnz = F->nz ; Fpacked = F->packed ; } else { // symmetric lower triangular form not supported ERROR (CHOLMOD_INVALID, "symmetric lower not supported") ; return (FALSE) ; } Ap = A->p ; Ai = A->i ; Anz = A->nz ; packed = A->packed ; sorted = A->sorted ; k = krow ; Stack = R->i ; //-------------------------------------------------------------------------- // get workspace //-------------------------------------------------------------------------- Flag = Common->Flag ; // size nrow, Flag [i] < mark must hold CLEAR_FLAG (Common) ; ASSERT (check_flag (Common)) ; mark = Common->mark ; //-------------------------------------------------------------------------- // compute the pattern of L(k,:) //-------------------------------------------------------------------------- top = nrow ; // Stack is empty Flag [k] = mark ; // do not include diagonal entry in Stack #define SCATTER /* do not scatter numerical values */ #define PARENT(i) Parent [i] /* use Parent for etree */ if (stype != 0) { // scatter kth col of triu (A), get pattern L(k,:) p = Ap [k] ; pend = (packed) ? (Ap [k+1]) : (p + Anz [k]) ; SUBTREE ; } else { // scatter kth col of triu (beta*I+AA'), get pattern L(k,:) pf = Fp [k] ; pfend = (Fpacked) ? (Fp [k+1]) : (pf + Fnz [k]) ; for ( ; pf < pfend ; pf++) { // get nonzero entry F (t,k) t = Fi [pf] ; p = Ap [t] ; pend = (packed) ? (Ap [t+1]) : (p + Anz [t]) ; SUBTREE ; } } #undef SCATTER #undef PARENT // shift the stack upwards, to the first part of R len = nrow - top ; for (i = 0 ; i < len ; i++) { Stack [i] = Stack [top + i] ; } Rp = R->p ; Rp [0] = 0 ; Rp [1] = len ; R->sorted = FALSE ; CHOLMOD(clear_flag) (Common) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; return (TRUE) ; } //------------------------------------------------------------------------------ // cholmod_lsolve_pattern //------------------------------------------------------------------------------ // Compute the nonzero pattern of Y=L\B. L must be simplicial, and B // must be a single sparse column vector with B->stype = 0. The values of // B are not used; it just specifies a nonzero pattern. The pattern of // Y is not sorted, but is in topological order instead (suitable for a // sparse forward/backsolve). int CHOLMOD(lsolve_pattern) ( // input: cholmod_sparse *B, // sparse right-hand-side (a single sparse column) cholmod_factor *L, // the factor L from which parent(i) is derived // output: cholmod_sparse *Yset, // pattern of Y=L\B, n-by-1 with Y->nzmax >= n cholmod_common *Common ) { size_t krow ; RETURN_IF_NULL (B, FALSE) ; krow = B->nrow ; return (CHOLMOD(row_lsubtree) (B, NULL, 0, krow, L, Yset, Common)) ; } //------------------------------------------------------------------------------ // cholmod_row_lsubtree //------------------------------------------------------------------------------ // Identical to cholmod_row_subtree, except that the elimination tree is // obtained from L itself, as the first off-diagonal entry in each column. // L must be simplicial, not supernodal. // // If krow = A->nrow, then A must be a single sparse column vector, (A->stype // must be zero), and the nonzero pattern of x=L\b is computed, where b=A(:,0) // is the single sparse right-hand-side. The inputs Fi and fnz are ignored. // See CHOLMOD(lsolve_pattern) above for a simpler interface for this case. int CHOLMOD(row_lsubtree) ( // input: cholmod_sparse *A, // matrix to analyze Int *Fi, // nonzero pattern of kth row of A', not required // for the symmetric case. Need not be sorted. size_t fnz, // size of Fi size_t krow, // row k of L cholmod_factor *L, // the factor L from which parent(i) is derived // output: cholmod_sparse *R, // pattern of L(k,:), n-by-1 with R->nzmax >= n cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- Int *Rp, *Stack, *Flag, *Ap, *Ai, *Anz, *Lp, *Li, *Lnz ; Int p, pend, parent, t, stype, nrow, k, pf, packed, sorted, top, len, i, mark, ka ; RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (R, FALSE) ; RETURN_IF_NULL (L, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (R, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ; nrow = A->nrow ; stype = A->stype ; if (stype < 0) { // symmetric lower triangular form not supported ERROR (CHOLMOD_INVALID, "symmetric lower not supported") ; return (FALSE) ; } if (krow > nrow) { ERROR (CHOLMOD_INVALID, "lsubtree: krow invalid") ; return (FALSE) ; } else if (krow == nrow) { // find pattern of x=L\b where b=A(:,0) k = nrow ; // compute all of the result; don't stop in SUBTREE ka = 0 ; // use column A(:,0) if (stype != 0 || A->ncol != 1) { // A must be unsymmetric (it's a single sparse column vector) ERROR (CHOLMOD_INVALID, "lsubtree: A invalid") ; return (FALSE) ; } } else { // find pattern of L(k,:) using A(:,k) and Fi if A unsymmetric k = krow ; // which row of L to compute ka = k ; // which column of A to use if (stype == 0) { RETURN_IF_NULL (Fi, FALSE) ; } } if (R->ncol != 1 || nrow != R->nrow || nrow > R->nzmax || ((krow == nrow || stype != 0) && ka >= A->ncol)) { ERROR (CHOLMOD_INVALID, "lsubtree: R invalid") ; return (FALSE) ; } if (L->is_super) { ERROR (CHOLMOD_INVALID, "lsubtree: L invalid (cannot be supernodal)") ; return (FALSE) ; } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- CHOLMOD(allocate_work) (nrow, 0, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Ap = A->p ; Ai = A->i ; Anz = A->nz ; packed = A->packed ; sorted = A->sorted ; Stack = R->i ; Lp = L->p ; Li = L->i ; Lnz = L->nz ; //-------------------------------------------------------------------------- // get workspace //-------------------------------------------------------------------------- Flag = Common->Flag ; // size nrow, Flag [i] < mark must hold mark = CHOLMOD(clear_flag) (Common) ; //-------------------------------------------------------------------------- // compute the pattern of L(k,:) //-------------------------------------------------------------------------- top = nrow ; // Stack is empty if (k < nrow) { Flag [k] = mark ; // do not include diagonal entry in Stack } #define SCATTER /* do not scatter numerical values */ #define PARENT(i) (Lnz [i] > 1) ? (Li [Lp [i] + 1]) : EMPTY if (krow == nrow || stype != 0) { // scatter kth col of triu (A), get pattern L(k,:) p = Ap [ka] ; pend = (packed) ? (Ap [ka+1]) : (p + Anz [ka]) ; SUBTREE ; } else { // scatter kth col of triu (beta*I+AA'), get pattern L(k,:) for (pf = 0 ; pf < (Int) fnz ; pf++) { // get nonzero entry F (t,k) t = Fi [pf] ; p = Ap [t] ; pend = (packed) ? (Ap [t+1]) : (p + Anz [t]) ; SUBTREE ; } } #undef SCATTER #undef PARENT // shift the stack upwards, to the first part of R len = nrow - top ; for (i = 0 ; i < len ; i++) { Stack [i] = Stack [top + i] ; } Rp = R->p ; Rp [0] = 0 ; Rp [1] = len ; R->sorted = FALSE ; CHOLMOD(clear_flag) (Common) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; return (TRUE) ; } //------------------------------------------------------------------------------ // cholmod_rowfac //------------------------------------------------------------------------------ // This is the incremental factorization for general purpose usage. int CHOLMOD(rowfac) ( // input: cholmod_sparse *A, // matrix to factorize cholmod_sparse *F, // used for A*A' case only. F=A' or A(:,f)' double beta [2], // factorize beta*I+A or beta*I+AA' size_t kstart, // first row to factorize size_t kend, // last row to factorize is kend-1 // input/output: cholmod_factor *L, cholmod_common *Common ) { return (CHOLMOD(rowfac_mask2) (A, F, beta, kstart, kend, NULL, 0, NULL, L, Common)) ; } //------------------------------------------------------------------------------ // cholmod_rowfac_mask //------------------------------------------------------------------------------ // This is meant for use in LPDASA only. int CHOLMOD(rowfac_mask) ( // input: cholmod_sparse *A, // matrix to factorize cholmod_sparse *F, // used for A*A' case only. F=A' or A(:,f)' double beta [2], // factorize beta*I+A or beta*I+AA' size_t kstart, // first row to factorize size_t kend, // last row to factorize is kend-1 Int *mask, // size A->nrow. if mask[i] >= 0 row i is set to zero Int *RLinkUp, // size A->nrow. link list of rows to compute // input/output: cholmod_factor *L, cholmod_common *Common ) { Int maskmark = 0 ; return (CHOLMOD(rowfac_mask2) (A, F, beta, kstart, kend, mask, maskmark, RLinkUp, L, Common)) ; } //------------------------------------------------------------------------------ // cholmod_rowfac_mask2 //------------------------------------------------------------------------------ // This is meant for use in LPDASA only. For general usage, see // cholmod_rowfac. int CHOLMOD(rowfac_mask2) ( // input: cholmod_sparse *A, // matrix to factorize cholmod_sparse *F, // used for A*A' case only. F=A' or A(:,f)' double beta [2], // factorize beta*I+A or beta*I+AA' size_t kstart, // first row to factorize size_t kend, // last row to factorize is kend-1 Int *mask, // size A->nrow. if mask[i] >= maskmark row i is set // to zero Int maskmark, // for mask [i] test Int *RLinkUp, // size A->nrow. link list of rows to compute // input/output: cholmod_factor *L, cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- Int n ; size_t s ; RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (L, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; if (L->xtype != CHOLMOD_PATTERN && (A->xtype != L->xtype || A->dtype != L->dtype)) { ERROR (CHOLMOD_INVALID, "xtype or dtype of A and L do not match") ; return (FALSE) ; } if (L->is_super) { ERROR (CHOLMOD_INVALID, "can only do simplicial factorization"); return (FALSE) ; } if (A->stype == 0) { RETURN_IF_NULL (F, FALSE) ; if (A->xtype != F->xtype) { ERROR (CHOLMOD_INVALID, "xtype of A and F do not match") ; return (FALSE) ; } } if (A->stype < 0) { // symmetric lower triangular form not supported ERROR (CHOLMOD_INVALID, "symmetric lower not supported") ; return (FALSE) ; } if (kend > L->n) { ERROR (CHOLMOD_INVALID, "kend invalid") ; return (FALSE) ; } if (A->nrow != L->n) { ERROR (CHOLMOD_INVALID, "dimensions of A and L do not match") ; return (FALSE) ; } Common->status = CHOLMOD_OK ; Common->rowfacfl = 0 ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- // Xwork is of size n for the real case, 2*n for complex/zomplex n = L->n ; // s = n * ((A->xtype != CHOLMOD_REAL) ? 2:1) int ok = TRUE ; s = CHOLMOD(mult_size_t) (L->n, ((A->xtype != CHOLMOD_REAL) ? 2:1), &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (FALSE) ; } CHOLMOD(alloc_work) (n, n, s, A->dtype, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, A->nrow, A->dtype, Common)) ; //-------------------------------------------------------------------------- // factorize the matrix, using template routine //-------------------------------------------------------------------------- float s_beta [2] ; s_beta [0] = (float) beta [0] ; s_beta [1] = (float) beta [1] ; if (RLinkUp == NULL) { switch ((A->xtype + A->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: ok = rs_cholmod_rowfac_worker (A, F, s_beta, kstart, kend, L, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: ok = cs_cholmod_rowfac_worker (A, F, s_beta, kstart, kend, L, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: ok = zs_cholmod_rowfac_worker (A, F, s_beta, kstart, kend, L, Common) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: ok = rd_cholmod_rowfac_worker (A, F, beta, kstart, kend, L, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: ok = cd_cholmod_rowfac_worker (A, F, beta, kstart, kend, L, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: ok = zd_cholmod_rowfac_worker (A, F, beta, kstart, kend, L, Common) ; break ; } } else { switch ((A->xtype + A->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: ok = rs_cholmod_rowfac_mask_worker (A, F, s_beta, kstart, kend, mask, maskmark, RLinkUp, L, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: ok = cs_cholmod_rowfac_mask_worker (A, F, s_beta, kstart, kend, mask, maskmark, RLinkUp, L, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: ok = zs_cholmod_rowfac_mask_worker (A, F, s_beta, kstart, kend, mask, maskmark, RLinkUp, L, Common) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: ok = rd_cholmod_rowfac_mask_worker (A, F, beta, kstart, kend, mask, maskmark, RLinkUp, L, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: ok = cd_cholmod_rowfac_mask_worker (A, F, beta, kstart, kend, mask, maskmark, RLinkUp, L, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: ok = zd_cholmod_rowfac_mask_worker (A, F, beta, kstart, kend, mask, maskmark, RLinkUp, L, Common) ; break ; } } return (ok) ; } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_colamd.c��������������������������������������������0000644�0001751�0000144�00000015633�14552026002�022554� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_colamd: COLAMD interface for CHOLMOD //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // CHOLMOD interface to the COLAMD ordering routine (version 2.4 or later). // Finds a permutation p such that the Cholesky factorization of PAA'P' is // sparser than AA' using colamd. If the postorder input parameter is TRUE, // the column etree is found and postordered, and the colamd ordering is then // combined with its postordering. A must be unsymmetric. // // There can be no duplicate entries in f. // f can be length 0 to n if A is m-by-n. // // workspace: Iwork (4*nrow+ncol), Head (nrow+1), Flag (nrow) // Allocates a copy of its input matrix, which // is then used as CCOLAMD's workspace. // // Supports any xtype (pattern, real, complex, or zomplex) #include "cholmod_internal.h" #ifndef NCHOLESKY #include "colamd.h" #if (!defined (COLAMD_VERSION) || (COLAMD_VERSION < COLAMD_VERSION_CODE (3,3))) #error "CHOLMOD:Cholesky requires COLAMD 3.3.1 or later" #endif //------------------------------------------------------------------------------ // cholmod_colamd //------------------------------------------------------------------------------ int CHOLMOD(colamd) ( // input: cholmod_sparse *A, // matrix to order Int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int postorder, // if TRUE, follow with a coletree postorder // output: Int *Perm, // size A->nrow, output permutation cholmod_common *Common ) { double knobs [COLAMD_KNOBS] ; cholmod_sparse *C ; Int *NewPerm, *Parent, *Post, *Work2n ; Int k, nrow, ncol ; //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (Perm, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; if (A->stype != 0) { ERROR (CHOLMOD_INVALID, "matrix must be unsymmetric") ; return (FALSE) ; } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- nrow = A->nrow ; ncol = A->ncol ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- // Note: this is less than the space used in cholmod_analyze, so if // cholmod_colamd is being called by that routine, no space will be // allocated. // s = 4*nrow + ncol int ok = TRUE ; size_t s = CHOLMOD(mult_size_t) (A->nrow, 4, &ok) ; s = CHOLMOD(add_size_t) (s, A->ncol, &ok) ; #if defined ( CHOLMOD_INT64 ) size_t alen = colamd_l_recommended (A->nzmax, ncol, nrow) ; colamd_l_set_defaults (knobs) ; #else size_t alen = colamd_recommended (A->nzmax, ncol, nrow) ; colamd_set_defaults (knobs) ; #endif if (!ok || alen == 0) { ERROR (CHOLMOD_TOO_LARGE, "matrix invalid or too large") ; return (FALSE) ; } CHOLMOD(allocate_work) (0, s, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } //-------------------------------------------------------------------------- // allocate COLAMD workspace //-------------------------------------------------------------------------- // C is purely symbolic, so C->dtype doesn't actually matter, but it must // match A->dtype for the call to cholmod_transpose_unsym below. C = CHOLMOD(allocate_sparse) (ncol, nrow, alen, TRUE, TRUE, 0, CHOLMOD_PATTERN + A->dtype, Common) ; //-------------------------------------------------------------------------- // copy (and transpose) the input matrix A into the colamd workspace //-------------------------------------------------------------------------- // C = A (:,f)', which also packs A if needed. // workspace: Iwork (nrow if no fset; MAX (nrow,ncol) if fset) ok = CHOLMOD(transpose_unsym) (A, 0, NULL, fset, fsize, C, Common) ; //-------------------------------------------------------------------------- // order the matrix (destroys the contents of C->i and C->p) //-------------------------------------------------------------------------- // get parameters if (Common->current < 0 || Common->current >= CHOLMOD_MAXMETHODS) { // this is the CHOLMOD default, not the COLAMD default knobs [COLAMD_DENSE_ROW] = -1 ; } else { // get the knobs from the Common parameters knobs [COLAMD_DENSE_COL] = Common->method[Common->current].prune_dense ; knobs [COLAMD_DENSE_ROW] = Common->method[Common->current].prune_dense2; knobs [COLAMD_AGGRESSIVE] = Common->method[Common->current].aggressive ; } if (ok) { Int *Cp ; Int stats [COLAMD_STATS] ; Cp = C->p ; #if defined ( CHOLMOD_INT64 ) colamd_l (ncol, nrow, alen, C->i, Cp, knobs, stats) ; #else colamd (ncol, nrow, alen, C->i, Cp, knobs, stats) ; #endif ok = stats [COLAMD_STATUS] ; ok = (ok == COLAMD_OK || ok == COLAMD_OK_BUT_JUMBLED) ; // permutation returned in C->p, if the ordering succeeded for (k = 0 ; k < nrow ; k++) { Perm [k] = Cp [k] ; } } CHOLMOD(free_sparse) (&C, Common) ; //-------------------------------------------------------------------------- // column etree postordering //-------------------------------------------------------------------------- if (postorder) { // use the last 2*n space in Iwork for Parent and Post Work2n = Common->Iwork ; Work2n += 2*((size_t) nrow) + ncol ; Parent = Work2n ; // size nrow Post = Work2n + nrow ; // size nrow // workspace: Iwork (2*nrow+ncol), Flag (nrow), Head (nrow+1) ok = ok && CHOLMOD(analyze_ordering) (A, CHOLMOD_COLAMD, Perm, fset, fsize, Parent, Post, NULL, NULL, NULL, Common) ; // combine the colamd permutation with its postordering if (ok) { NewPerm = Common->Iwork ; // size nrow for (k = 0 ; k < nrow ; k++) { NewPerm [k] = Perm [Post [k]] ; } for (k = 0 ; k < nrow ; k++) { Perm [k] = NewPerm [k] ; } } } return (ok) ; } #endif �����������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_solve.c�������������������������������������������0000644�0001751�0000144�00000000765�14552026002�022760� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_l_solve.c: int64_t version of cholmod_solve //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_solve.c" �����������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_amd.c���������������������������������������������0000644�0001751�0000144�00000000757�14552026002�022372� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_l_amd.c: int64_t version of cholmod_amd //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_amd.c" �����������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_etree.c�������������������������������������������0000644�0001751�0000144�00000000765�14552026002�022734� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_l_etree.c: int64_t version of cholmod_etree //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_etree.c" �����������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_ltsolve_template.c��������������������������������0000644�0001751�0000144�00000065070�14552026002�025223� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/t_cholmod_ltsolve_template: template for L'x=b or DL'x=b //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Template routine to solve L'x=b with unit or non-unit diagonal, or solve // DL'x=b. // // The numeric xtype of L and Y must match. Y contains b on input and x on // output, stored in row-form. Y is nrow-by-n, where nrow must equal 1 for the // complex or zomplex cases, and nrow <= 4 for the real case. // // This file is not compiled separately. It is included in // t_cholmod_solve_worker.c instead. It contains no user-callable routines. // // workspace: none // // Supports real, complex, and zomplex factors, and any dtype. // undefine all prior definitions #undef FORM_NAME #undef LSOLVE #undef DIAG //------------------------------------------------------------------------------ // define the method //------------------------------------------------------------------------------ #ifdef LL // LL': solve Lx=b with non-unit diagonal #define FORM_NAME(prefix,rank) prefix ## ll_ltsolve_ ## rank #define DIAG #elif defined (LD) // LDL': solve LDx=b #define FORM_NAME(prefix,rank) prefix ## ldl_dltsolve_ ## rank #define DIAG #else // LDL': solve Lx=b with unit diagonal #define FORM_NAME(prefix,rank) prefix ## ldl_ltsolve_ ## rank #endif // LSOLVE(k) defines the name of a routine for an n-by-k right-hand-side. #define LSOLVE(prefix,rank) FORM_NAME(prefix,rank) #ifdef REAL //------------------------------------------------------------------------------ // LSOLVE (1) //------------------------------------------------------------------------------ // Solve L'x=b, where b has 1 column static void LSOLVE (PREFIX,1) ( cholmod_factor *L, Real X [ ] // n-by-1 in row form ) { Real *Lx = L->x ; Int *Li = L->i ; Int *Lp = L->p ; Int *Lnz = L->nz ; Int j, n = L->n ; for (j = n-1 ; j >= 0 ; ) { // get the start, end, and length of column j Int p = Lp [j] ; Int lnz = Lnz [j] ; Int pend = p + lnz ; // find a chain of supernodes (up to j, j-1, and j-2) if (j < 4 || lnz != Lnz [j-1] - 1 || Li [Lp [j-1]+1] != j) { //------------------------------------------------------------------ // solve with a single column of L //------------------------------------------------------------------ Real y = X [j] ; #ifdef DIAG Real d = Lx [p] ; #endif #ifdef LD y /= d ; #endif for (p++ ; p < pend ; p++) { y -= Lx [p] * X [Li [p]] ; } #ifdef LL X [j] = y / d ; #else X [j] = y ; #endif j-- ; // advance to the next column of L } else if (lnz != Lnz [j-2]-2 || Li [Lp [j-2]+2] != j) { //------------------------------------------------------------------ // solve with a supernode of two columns of L //------------------------------------------------------------------ Real y [2], t ; Int q = Lp [j-1] ; #ifdef DIAG Real d [2] ; d [0] = Lx [p] ; d [1] = Lx [q] ; #endif t = Lx [q+1] ; #ifdef LD y [0] = X [j ] / d [0] ; y [1] = X [j-1] / d [1] ; #else y [0] = X [j ] ; y [1] = X [j-1] ; #endif for (p++, q += 2 ; p < pend ; p++, q++) { Int i = Li [p] ; y [0] -= Lx [p] * X [i] ; y [1] -= Lx [q] * X [i] ; } #ifdef LL y [0] /= d [0] ; y [1] = (y [1] - t * y [0]) / d [1] ; #else y [1] -= t * y [0] ; #endif X [j ] = y [0] ; X [j-1] = y [1] ; j -= 2 ; // advance to the next column of L } else { //------------------------------------------------------------------ // solve with a supernode of three columns of L //------------------------------------------------------------------ Real y [3], t [3] ; Int q = Lp [j-1] ; Int r = Lp [j-2] ; #ifdef DIAG Real d [3] ; d [0] = Lx [p] ; d [1] = Lx [q] ; d [2] = Lx [r] ; #endif t [0] = Lx [q+1] ; t [1] = Lx [r+1] ; t [2] = Lx [r+2] ; #ifdef LD y [0] = X [j] / d [0] ; y [1] = X [j-1] / d [1] ; y [2] = X [j-2] / d [2] ; #else y [0] = X [j] ; y [1] = X [j-1] ; y [2] = X [j-2] ; #endif for (p++, q += 2, r += 3 ; p < pend ; p++, q++, r++) { Int i = Li [p] ; y [0] -= Lx [p] * X [i] ; y [1] -= Lx [q] * X [i] ; y [2] -= Lx [r] * X [i] ; } #ifdef LL y [0] /= d [0] ; y [1] = (y [1] - t [0] * y [0]) / d [1] ; y [2] = (y [2] - t [2] * y [0] - t [1] * y [1]) / d [2] ; #else y [1] -= t [0] * y [0] ; y [2] -= t [2] * y [0] + t [1] * y [1] ; #endif X [j-2] = y [2] ; X [j-1] = y [1] ; X [j ] = y [0] ; j -= 3 ; // advance to the next column of L } } } //------------------------------------------------------------------------------ // LSOLVE (2) //------------------------------------------------------------------------------ // Solve L'x=b, where b has 2 columns static void LSOLVE (PREFIX,2) ( cholmod_factor *L, Real X [ ][2] // n-by-2 in row form ) { Real *Lx = L->x ; Int *Li = L->i ; Int *Lp = L->p ; Int *Lnz = L->nz ; Int j, n = L->n ; for (j = n-1 ; j >= 0 ; ) { // get the start, end, and length of column j Int p = Lp [j] ; Int lnz = Lnz [j] ; Int pend = p + lnz ; // find a chain of supernodes (up to j, j-1, and j-2) if (j < 4 || lnz != Lnz [j-1] - 1 || Li [Lp [j-1]+1] != j) { //------------------------------------------------------------------ // solve with a single column of L //------------------------------------------------------------------ Real y [2] ; #ifdef DIAG Real d = Lx [p] ; #endif #ifdef LD y [0] = X [j][0] / d ; y [1] = X [j][1] / d ; #else y [0] = X [j][0] ; y [1] = X [j][1] ; #endif for (p++ ; p < pend ; p++) { Int i = Li [p] ; y [0] -= Lx [p] * X [i][0] ; y [1] -= Lx [p] * X [i][1] ; } #ifdef LL X [j][0] = y [0] / d ; X [j][1] = y [1] / d ; #else X [j][0] = y [0] ; X [j][1] = y [1] ; #endif j-- ; // advance to the next column of L } else if (lnz != Lnz [j-2]-2 || Li [Lp [j-2]+2] != j) { //------------------------------------------------------------------ // solve with a supernode of two columns of L //------------------------------------------------------------------ Real y [2][2], t ; Int q = Lp [j-1] ; #ifdef DIAG Real d [2] ; d [0] = Lx [p] ; d [1] = Lx [q] ; #endif t = Lx [q+1] ; #ifdef LD y [0][0] = X [j ][0] / d [0] ; y [0][1] = X [j ][1] / d [0] ; y [1][0] = X [j-1][0] / d [1] ; y [1][1] = X [j-1][1] / d [1] ; #else y [0][0] = X [j ][0] ; y [0][1] = X [j ][1] ; y [1][0] = X [j-1][0] ; y [1][1] = X [j-1][1] ; #endif for (p++, q += 2 ; p < pend ; p++, q++) { Int i = Li [p] ; y [0][0] -= Lx [p] * X [i][0] ; y [0][1] -= Lx [p] * X [i][1] ; y [1][0] -= Lx [q] * X [i][0] ; y [1][1] -= Lx [q] * X [i][1] ; } #ifdef LL y [0][0] /= d [0] ; y [0][1] /= d [0] ; y [1][0] = (y [1][0] - t * y [0][0]) / d [1] ; y [1][1] = (y [1][1] - t * y [0][1]) / d [1] ; #else y [1][0] -= t * y [0][0] ; y [1][1] -= t * y [0][1] ; #endif X [j ][0] = y [0][0] ; X [j ][1] = y [0][1] ; X [j-1][0] = y [1][0] ; X [j-1][1] = y [1][1] ; j -= 2 ; // advance to the next column of L } else { //------------------------------------------------------------------ // solve with a supernode of three columns of L //------------------------------------------------------------------ Real y [3][2], t [3] ; Int q = Lp [j-1] ; Int r = Lp [j-2] ; #ifdef DIAG Real d [3] ; d [0] = Lx [p] ; d [1] = Lx [q] ; d [2] = Lx [r] ; #endif t [0] = Lx [q+1] ; t [1] = Lx [r+1] ; t [2] = Lx [r+2] ; #ifdef LD y [0][0] = X [j ][0] / d [0] ; y [0][1] = X [j ][1] / d [0] ; y [1][0] = X [j-1][0] / d [1] ; y [1][1] = X [j-1][1] / d [1] ; y [2][0] = X [j-2][0] / d [2] ; y [2][1] = X [j-2][1] / d [2] ; #else y [0][0] = X [j ][0] ; y [0][1] = X [j ][1] ; y [1][0] = X [j-1][0] ; y [1][1] = X [j-1][1] ; y [2][0] = X [j-2][0] ; y [2][1] = X [j-2][1] ; #endif for (p++, q += 2, r += 3 ; p < pend ; p++, q++, r++) { Int i = Li [p] ; y [0][0] -= Lx [p] * X [i][0] ; y [0][1] -= Lx [p] * X [i][1] ; y [1][0] -= Lx [q] * X [i][0] ; y [1][1] -= Lx [q] * X [i][1] ; y [2][0] -= Lx [r] * X [i][0] ; y [2][1] -= Lx [r] * X [i][1] ; } #ifdef LL y [0][0] /= d [0] ; y [0][1] /= d [0] ; y [1][0] = (y [1][0] - t [0] * y [0][0]) / d [1] ; y [1][1] = (y [1][1] - t [0] * y [0][1]) / d [1] ; y [2][0] = (y [2][0] - t [2] * y [0][0] - t [1] * y [1][0]) / d [2]; y [2][1] = (y [2][1] - t [2] * y [0][1] - t [1] * y [1][1]) / d [2]; #else y [1][0] -= t [0] * y [0][0] ; y [1][1] -= t [0] * y [0][1] ; y [2][0] -= t [2] * y [0][0] + t [1] * y [1][0] ; y [2][1] -= t [2] * y [0][1] + t [1] * y [1][1] ; #endif X [j ][0] = y [0][0] ; X [j ][1] = y [0][1] ; X [j-1][0] = y [1][0] ; X [j-1][1] = y [1][1] ; X [j-2][0] = y [2][0] ; X [j-2][1] = y [2][1] ; j -= 3 ; // advance to the next column of L } } } //------------------------------------------------------------------------------ // LSOLVE (3) //------------------------------------------------------------------------------ // Solve L'x=b, where b has 3 columns static void LSOLVE (PREFIX,3) ( cholmod_factor *L, Real X [ ][3] // n-by-3 in row form ) { Real *Lx = L->x ; Int *Li = L->i ; Int *Lp = L->p ; Int *Lnz = L->nz ; Int j, n = L->n ; for (j = n-1 ; j >= 0 ; ) { // get the start, end, and length of column j Int p = Lp [j] ; Int lnz = Lnz [j] ; Int pend = p + lnz ; // find a chain of supernodes (up to j, j-1, and j-2) if (j < 4 || lnz != Lnz [j-1] - 1 || Li [Lp [j-1]+1] != j) { //------------------------------------------------------------------ // solve with a single column of L //------------------------------------------------------------------ Real y [3] ; #ifdef DIAG Real d = Lx [p] ; #endif #ifdef LD y [0] = X [j][0] / d ; y [1] = X [j][1] / d ; y [2] = X [j][2] / d ; #else y [0] = X [j][0] ; y [1] = X [j][1] ; y [2] = X [j][2] ; #endif for (p++ ; p < pend ; p++) { Int i = Li [p] ; y [0] -= Lx [p] * X [i][0] ; y [1] -= Lx [p] * X [i][1] ; y [2] -= Lx [p] * X [i][2] ; } #ifdef LL X [j][0] = y [0] / d ; X [j][1] = y [1] / d ; X [j][2] = y [2] / d ; #else X [j][0] = y [0] ; X [j][1] = y [1] ; X [j][2] = y [2] ; #endif j-- ; // advance to the next column of L } else if (lnz != Lnz [j-2]-2 || Li [Lp [j-2]+2] != j) { //------------------------------------------------------------------ // solve with a supernode of two columns of L //------------------------------------------------------------------ Real y [2][3], t ; Int q = Lp [j-1] ; #ifdef DIAG Real d [2] ; d [0] = Lx [p] ; d [1] = Lx [q] ; #endif t = Lx [q+1] ; #ifdef LD y [0][0] = X [j ][0] / d [0] ; y [0][1] = X [j ][1] / d [0] ; y [0][2] = X [j ][2] / d [0] ; y [1][0] = X [j-1][0] / d [1] ; y [1][1] = X [j-1][1] / d [1] ; y [1][2] = X [j-1][2] / d [1] ; #else y [0][0] = X [j ][0] ; y [0][1] = X [j ][1] ; y [0][2] = X [j ][2] ; y [1][0] = X [j-1][0] ; y [1][1] = X [j-1][1] ; y [1][2] = X [j-1][2] ; #endif for (p++, q += 2 ; p < pend ; p++, q++) { Int i = Li [p] ; y [0][0] -= Lx [p] * X [i][0] ; y [0][1] -= Lx [p] * X [i][1] ; y [0][2] -= Lx [p] * X [i][2] ; y [1][0] -= Lx [q] * X [i][0] ; y [1][1] -= Lx [q] * X [i][1] ; y [1][2] -= Lx [q] * X [i][2] ; } #ifdef LL y [0][0] /= d [0] ; y [0][1] /= d [0] ; y [0][2] /= d [0] ; y [1][0] = (y [1][0] - t * y [0][0]) / d [1] ; y [1][1] = (y [1][1] - t * y [0][1]) / d [1] ; y [1][2] = (y [1][2] - t * y [0][2]) / d [1] ; #else y [1][0] -= t * y [0][0] ; y [1][1] -= t * y [0][1] ; y [1][2] -= t * y [0][2] ; #endif X [j ][0] = y [0][0] ; X [j ][1] = y [0][1] ; X [j ][2] = y [0][2] ; X [j-1][0] = y [1][0] ; X [j-1][1] = y [1][1] ; X [j-1][2] = y [1][2] ; j -= 2 ; // advance to the next column of L } else { //------------------------------------------------------------------ // solve with a supernode of three columns of L //------------------------------------------------------------------ Real y [3][3], t [3] ; Int q = Lp [j-1] ; Int r = Lp [j-2] ; #ifdef DIAG Real d [3] ; d [0] = Lx [p] ; d [1] = Lx [q] ; d [2] = Lx [r] ; #endif t [0] = Lx [q+1] ; t [1] = Lx [r+1] ; t [2] = Lx [r+2] ; #ifdef LD y [0][0] = X [j ][0] / d [0] ; y [0][1] = X [j ][1] / d [0] ; y [0][2] = X [j ][2] / d [0] ; y [1][0] = X [j-1][0] / d [1] ; y [1][1] = X [j-1][1] / d [1] ; y [1][2] = X [j-1][2] / d [1] ; y [2][0] = X [j-2][0] / d [2] ; y [2][1] = X [j-2][1] / d [2] ; y [2][2] = X [j-2][2] / d [2] ; #else y [0][0] = X [j ][0] ; y [0][1] = X [j ][1] ; y [0][2] = X [j ][2] ; y [1][0] = X [j-1][0] ; y [1][1] = X [j-1][1] ; y [1][2] = X [j-1][2] ; y [2][0] = X [j-2][0] ; y [2][1] = X [j-2][1] ; y [2][2] = X [j-2][2] ; #endif for (p++, q += 2, r += 3 ; p < pend ; p++, q++, r++) { Int i = Li [p] ; y [0][0] -= Lx [p] * X [i][0] ; y [0][1] -= Lx [p] * X [i][1] ; y [0][2] -= Lx [p] * X [i][2] ; y [1][0] -= Lx [q] * X [i][0] ; y [1][1] -= Lx [q] * X [i][1] ; y [1][2] -= Lx [q] * X [i][2] ; y [2][0] -= Lx [r] * X [i][0] ; y [2][1] -= Lx [r] * X [i][1] ; y [2][2] -= Lx [r] * X [i][2] ; } #ifdef LL y [0][0] /= d [0] ; y [0][1] /= d [0] ; y [0][2] /= d [0] ; y [1][0] = (y [1][0] - t [0] * y [0][0]) / d [1] ; y [1][1] = (y [1][1] - t [0] * y [0][1]) / d [1] ; y [1][2] = (y [1][2] - t [0] * y [0][2]) / d [1] ; y [2][0] = (y [2][0] - t [2] * y [0][0] - t [1] * y [1][0]) / d [2]; y [2][1] = (y [2][1] - t [2] * y [0][1] - t [1] * y [1][1]) / d [2]; y [2][2] = (y [2][2] - t [2] * y [0][2] - t [1] * y [1][2]) / d [2]; #else y [1][0] -= t [0] * y [0][0] ; y [1][1] -= t [0] * y [0][1] ; y [1][2] -= t [0] * y [0][2] ; y [2][0] -= t [2] * y [0][0] + t [1] * y [1][0] ; y [2][1] -= t [2] * y [0][1] + t [1] * y [1][1] ; y [2][2] -= t [2] * y [0][2] + t [1] * y [1][2] ; #endif X [j ][0] = y [0][0] ; X [j ][1] = y [0][1] ; X [j ][2] = y [0][2] ; X [j-1][0] = y [1][0] ; X [j-1][1] = y [1][1] ; X [j-1][2] = y [1][2] ; X [j-2][0] = y [2][0] ; X [j-2][1] = y [2][1] ; X [j-2][2] = y [2][2] ; j -= 3 ; // advance to the next column of L } } } //------------------------------------------------------------------------------ // LSOLVE (4) //------------------------------------------------------------------------------ // Solve L'x=b, where b has 4 columns static void LSOLVE (PREFIX,4) ( cholmod_factor *L, Real X [ ][4] // n-by-4 in row form ) { Real *Lx = L->x ; Int *Li = L->i ; Int *Lp = L->p ; Int *Lnz = L->nz ; Int j, n = L->n ; for (j = n-1 ; j >= 0 ; ) { // get the start, end, and length of column j Int p = Lp [j] ; Int lnz = Lnz [j] ; Int pend = p + lnz ; // find a chain of supernodes (up to j, j-1, and j-2) if (j < 4 || lnz != Lnz [j-1] - 1 || Li [Lp [j-1]+1] != j) { //------------------------------------------------------------------ // solve with a single column of L //------------------------------------------------------------------ Real y [4] ; #ifdef DIAG Real d = Lx [p] ; #endif #ifdef LD y [0] = X [j][0] / d ; y [1] = X [j][1] / d ; y [2] = X [j][2] / d ; y [3] = X [j][3] / d ; #else y [0] = X [j][0] ; y [1] = X [j][1] ; y [2] = X [j][2] ; y [3] = X [j][3] ; #endif for (p++ ; p < pend ; p++) { Int i = Li [p] ; y [0] -= Lx [p] * X [i][0] ; y [1] -= Lx [p] * X [i][1] ; y [2] -= Lx [p] * X [i][2] ; y [3] -= Lx [p] * X [i][3] ; } #ifdef LL X [j][0] = y [0] / d ; X [j][1] = y [1] / d ; X [j][2] = y [2] / d ; X [j][3] = y [3] / d ; #else X [j][0] = y [0] ; X [j][1] = y [1] ; X [j][2] = y [2] ; X [j][3] = y [3] ; #endif j-- ; // advance to the next column of L } else // if (j == 1 || lnz != Lnz [j-2]-2 || Li [Lp [j-2]+2] != j) { //------------------------------------------------------------------ // solve with a supernode of two columns of L //------------------------------------------------------------------ Real y [2][4], t ; Int q = Lp [j-1] ; #ifdef DIAG Real d [2] ; d [0] = Lx [p] ; d [1] = Lx [q] ; #endif t = Lx [q+1] ; #ifdef LD y [0][0] = X [j ][0] / d [0] ; y [0][1] = X [j ][1] / d [0] ; y [0][2] = X [j ][2] / d [0] ; y [0][3] = X [j ][3] / d [0] ; y [1][0] = X [j-1][0] / d [1] ; y [1][1] = X [j-1][1] / d [1] ; y [1][2] = X [j-1][2] / d [1] ; y [1][3] = X [j-1][3] / d [1] ; #else y [0][0] = X [j ][0] ; y [0][1] = X [j ][1] ; y [0][2] = X [j ][2] ; y [0][3] = X [j ][3] ; y [1][0] = X [j-1][0] ; y [1][1] = X [j-1][1] ; y [1][2] = X [j-1][2] ; y [1][3] = X [j-1][3] ; #endif for (p++, q += 2 ; p < pend ; p++, q++) { Int i = Li [p] ; y [0][0] -= Lx [p] * X [i][0] ; y [0][1] -= Lx [p] * X [i][1] ; y [0][2] -= Lx [p] * X [i][2] ; y [0][3] -= Lx [p] * X [i][3] ; y [1][0] -= Lx [q] * X [i][0] ; y [1][1] -= Lx [q] * X [i][1] ; y [1][2] -= Lx [q] * X [i][2] ; y [1][3] -= Lx [q] * X [i][3] ; } #ifdef LL y [0][0] /= d [0] ; y [0][1] /= d [0] ; y [0][2] /= d [0] ; y [0][3] /= d [0] ; y [1][0] = (y [1][0] - t * y [0][0]) / d [1] ; y [1][1] = (y [1][1] - t * y [0][1]) / d [1] ; y [1][2] = (y [1][2] - t * y [0][2]) / d [1] ; y [1][3] = (y [1][3] - t * y [0][3]) / d [1] ; #else y [1][0] -= t * y [0][0] ; y [1][1] -= t * y [0][1] ; y [1][2] -= t * y [0][2] ; y [1][3] -= t * y [0][3] ; #endif X [j ][0] = y [0][0] ; X [j ][1] = y [0][1] ; X [j ][2] = y [0][2] ; X [j ][3] = y [0][3] ; X [j-1][0] = y [1][0] ; X [j-1][1] = y [1][1] ; X [j-1][2] = y [1][2] ; X [j-1][3] = y [1][3] ; j -= 2 ; // advance to the next column of L } // NOTE: with 4 right-hand-sides, it suffices to exploit dynamic // supernodes of just size 1 and 2. 3-column supernodes are not // needed. } } #endif //------------------------------------------------------------------------------ // LSOLVE (k) //------------------------------------------------------------------------------ static void LSOLVE (PREFIX,k) ( cholmod_factor *L, cholmod_dense *Y, // nr-by-n where nr is 1 to 4 cholmod_sparse *Yset // input pattern Yset ) { #ifdef DIAG Real d [1] ; #endif Real yx [2] ; #ifdef ZOMPLEX Real yz [1] ; Real *Lz = L->z ; Real *Xz = Y->z ; #endif Real *Lx = L->x ; Real *Xx = Y->x ; Int *Li = L->i ; Int *Lp = L->p ; Int *Lnz = L->nz ; Int n = L->n ; ASSERT (L->xtype == Y->xtype) ; // L and Y must have the same xtype ASSERT (L->dtype == Y->dtype) ; // L and Y must have the same dtype ASSERT (L->n == Y->ncol) ; // dimensions must match ASSERT (Y->nrow == Y->d) ; // leading dimension of Y = # rows of Y ASSERT (L->xtype != CHOLMOD_PATTERN) ; // L is not symbolic ASSERT (!(L->is_super)) ; // L is simplicial LL' or LDL' #ifdef REAL if (Yset == NULL) { //---------------------------------------------------------------------- // real case, no Yset, with 1 to 4 RHS's and dynamic supernodes //---------------------------------------------------------------------- ASSERT (Y->nrow <= 4) ; switch (Y->nrow) { case 1: LSOLVE (PREFIX,1) (L, Y->x) ; break ; case 2: LSOLVE (PREFIX,2) (L, Y->x) ; break ; case 3: LSOLVE (PREFIX,3) (L, Y->x) ; break ; case 4: LSOLVE (PREFIX,4) (L, Y->x) ; break ; } } else #endif { //---------------------------------------------------------------------- // solve a complex linear system or solve with Yset //---------------------------------------------------------------------- ASSERT (Y->nrow == 1) ; Int *Ysetp = (Yset == NULL) ? NULL : Yset->p ; Int *Yseti = (Yset == NULL) ? NULL : Yset->i ; Int ysetlen = (Yset == NULL) ? n : Ysetp [1] ; for (Int jj = ysetlen-1 ; jj >= 0 ; jj--) { Int j = Yseti ? Yseti [jj] : jj ; // get the start, end, and length of column j Int p = Lp [j] ; Int lnz = Lnz [j] ; Int pend = p + lnz ; // y = X [j] ASSIGN (yx,yz,0, Xx,Xz,j) ; #ifdef DIAG // d = Lx [p] ASSIGN_REAL (d,0, Lx,p) ; #endif #ifdef LD // y /= d DIV_REAL (yx,yz,0, yx,yz,0, d,0) ; #endif for (p++ ; p < pend ; p++) { // y -= conj (Lx [p]) * X [Li [p]] Int i = Li [p] ; MULTSUBCONJ (yx,yz,0, Lx,Lz,p, Xx,Xz,i) ; } #ifdef LL // X [j] = y / d DIV_REAL (Xx,Xz,j, yx,yz,0, d,0) ; #else // X [j] = y ASSIGN (Xx,Xz,j, yx,yz,0) ; #endif } } } // prepare for the next inclusion of this file in cholmod_solve.c #undef LL #undef LD ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_colamd.c������������������������������������������0000644�0001751�0000144�00000000770�14552026002�023063� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//------------------------------------------------------------------------------ // CHOLMOD/Cholesky/cholmod_l_colamd.c: int64_t version of cholmod_colamd //------------------------------------------------------------------------------ // CHOLMOD/Cholesky Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_colamd.c" ��������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/���������������������������������������������������0000755�0001751�0000144�00000000000�14576343415�021343� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/include/�������������������������������������������0000755�0001751�0000144�00000000000�14576343415�022766� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/include/original/����������������������������������0000755�0001751�0000144�00000000000�14576343415�024572� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/include/original/metis.h���������������������������0000644�0001751�0000144�00000023701�14552026002�026047� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*! \file metis.h \brief This file contains function prototypes and constant definitions for METIS * \author George \date Started 8/9/02 \version\verbatim $Id$\endverbatim */ #ifndef _METIS_H_ #define _METIS_H_ /**************************************************************************** * A set of defines that can be modified by the user *****************************************************************************/ /*-------------------------------------------------------------------------- Specifies the width of the elementary data type that will hold information about vertices and their adjacency lists. Possible values: 32 : Use 32 bit signed integers 64 : Use 64 bit signed integers A width of 64 should be specified if the number of vertices or the total number of edges in the graph exceed the limits of a 32 bit signed integer i.e., 2^31-1. Proper use of 64 bit integers requires that the c99 standard datatypes int32_t and int64_t are supported by the compiler. GCC does provides these definitions in stdint.h, but it may require some modifications on other architectures. --------------------------------------------------------------------------*/ #define IDXTYPEWIDTH 32 /*-------------------------------------------------------------------------- Specifies the data type that will hold floating-point style information. Possible values: 32 : single precission floating point (float) 64 : double precission floating point (double) --------------------------------------------------------------------------*/ #define REALTYPEWIDTH 32 /**************************************************************************** * In principle, nothing needs to be changed beyond this point, unless the * int32_t and int64_t cannot be found in the normal places. *****************************************************************************/ /* Uniform definitions for various compilers */ #if defined(_MSC_VER) #define COMPILER_MSC #endif #if defined(__ICC) #define COMPILER_ICC #endif #if defined(__GNUC__) #define COMPILER_GCC #endif /* Include c99 int definitions and need constants. When building the library, * these are already defined by GKlib; hence the test for _GKLIB_H_ */ #ifndef _GKLIB_H_ #ifdef COMPILER_MSC #include typedef __int32 int32_t; typedef __int64 int64_t; #define PRId32 "I32d" #define PRId64 "I64d" #define SCNd32 "ld" #define SCNd64 "I64d" #define INT32_MIN ((int32_t)_I32_MIN) #define INT32_MAX _I32_MAX #define INT64_MIN ((int64_t)_I64_MIN) #define INT64_MAX _I64_MAX #else #include #endif #endif /*------------------------------------------------------------------------ * Setup the basic datatypes *-------------------------------------------------------------------------*/ #if IDXTYPEWIDTH == 32 typedef int32_t idx_t; #define IDX_MAX INT32_MAX #define IDX_MIN INT32_MIN #define SCIDX SCNd32 #define PRIDX PRId32 #define strtoidx strtol #define iabs abs #elif IDXTYPEWIDTH == 64 typedef int64_t idx_t; #define IDX_MAX INT64_MAX #define IDX_MIN INT64_MIN #define SCIDX SCNd64 #define PRIDX PRId64 #ifdef COMPILER_MSC #define strtoidx _strtoi64 #else #define strtoidx strtoll #endif #define iabs labs #else #error "Incorrect user-supplied value fo IDXTYPEWIDTH" #endif #if REALTYPEWIDTH == 32 typedef float real_t; #define SCREAL "f" #define PRREAL "f" #define REAL_MAX FLT_MAX #define REAL_MIN FLT_MIN #define REAL_EPSILON FLT_EPSILON #define rabs fabsf #define REALEQ(x,y) ((rabs((x)-(y)) <= FLT_EPSILON)) #ifdef COMPILER_MSC #define strtoreal (float)strtod #else #define strtoreal strtof #endif #elif REALTYPEWIDTH == 64 typedef double real_t; #define SCREAL "lf" #define PRREAL "lf" #define REAL_MAX DBL_MAX #define REAL_MIN DBL_MIN #define REAL_EPSILON DBL_EPSILON #define rabs fabs #define REALEQ(x,y) ((rabs((x)-(y)) <= DBL_EPSILON)) #define strtoreal strtod #else #error "Incorrect user-supplied value for REALTYPEWIDTH" #endif /*------------------------------------------------------------------------ * Constant definitions *-------------------------------------------------------------------------*/ /* Metis's version number */ #define METIS_VER_MAJOR 5 #define METIS_VER_MINOR 1 #define METIS_VER_SUBMINOR 0 /* The maximum length of the options[] array */ #define METIS_NOPTIONS 40 /*------------------------------------------------------------------------ * Function prototypes *-------------------------------------------------------------------------*/ #ifdef _WINDLL #define METIS_API(type) __declspec(dllexport) type __cdecl #elif defined(__cdecl) #define METIS_API(type) type __cdecl #else #define METIS_API(type) type #endif #ifdef __cplusplus extern "C" { #endif METIS_API(int) METIS_PartGraphRecursive(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt, idx_t *nparts, real_t *tpwgts, real_t *ubvec, idx_t *options, idx_t *edgecut, idx_t *part); METIS_API(int) METIS_PartGraphKway(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt, idx_t *nparts, real_t *tpwgts, real_t *ubvec, idx_t *options, idx_t *edgecut, idx_t *part); METIS_API(int) METIS_MeshToDual(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *ncommon, idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy); METIS_API(int) METIS_MeshToNodal(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy); METIS_API(int) METIS_PartMeshNodal(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *vwgt, idx_t *vsize, idx_t *nparts, real_t *tpwgts, idx_t *options, idx_t *objval, idx_t *epart, idx_t *npart); METIS_API(int) METIS_PartMeshDual(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *vwgt, idx_t *vsize, idx_t *ncommon, idx_t *nparts, real_t *tpwgts, idx_t *options, idx_t *objval, idx_t *epart, idx_t *npart); METIS_API(int) METIS_NodeND(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *options, idx_t *perm, idx_t *iperm); METIS_API(int) METIS_Free(void *ptr); METIS_API(int) METIS_SetDefaultOptions(idx_t *options); /* These functions are used by ParMETIS */ METIS_API(int) METIS_NodeNDP(idx_t nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t npes, idx_t *options, idx_t *perm, idx_t *iperm, idx_t *sizes); METIS_API(int) METIS_ComputeVertexSeparator(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *options, idx_t *sepsize, idx_t *part); METIS_API(int) METIS_NodeRefine(idx_t nvtxs, idx_t *xadj, idx_t *vwgt, idx_t *adjncy, idx_t *where, idx_t *hmarker, real_t ubfactor); #ifdef __cplusplus } #endif /*------------------------------------------------------------------------ * Enum type definitions *-------------------------------------------------------------------------*/ /*! Return codes */ typedef enum { METIS_OK = 1, /*!< Returned normally */ METIS_ERROR_INPUT = -2, /*!< Returned due to erroneous inputs and/or options */ METIS_ERROR_MEMORY = -3, /*!< Returned due to insufficient memory */ METIS_ERROR = -4 /*!< Some other errors */ } rstatus_et; /*! Operation type codes */ typedef enum { METIS_OP_PMETIS, METIS_OP_KMETIS, METIS_OP_OMETIS } moptype_et; /*! Options codes (i.e., options[]) */ typedef enum { METIS_OPTION_PTYPE, METIS_OPTION_OBJTYPE, METIS_OPTION_CTYPE, METIS_OPTION_IPTYPE, METIS_OPTION_RTYPE, METIS_OPTION_DBGLVL, METIS_OPTION_NITER, METIS_OPTION_NCUTS, METIS_OPTION_SEED, METIS_OPTION_NO2HOP, METIS_OPTION_MINCONN, METIS_OPTION_CONTIG, METIS_OPTION_COMPRESS, METIS_OPTION_CCORDER, METIS_OPTION_PFACTOR, METIS_OPTION_NSEPS, METIS_OPTION_UFACTOR, METIS_OPTION_NUMBERING, /* Used for command-line parameter purposes */ METIS_OPTION_HELP, METIS_OPTION_TPWGTS, METIS_OPTION_NCOMMON, METIS_OPTION_NOOUTPUT, METIS_OPTION_BALANCE, METIS_OPTION_GTYPE, METIS_OPTION_UBVEC } moptions_et; /*! Partitioning Schemes */ typedef enum { METIS_PTYPE_RB, METIS_PTYPE_KWAY } mptype_et; /*! Graph types for meshes */ typedef enum { METIS_GTYPE_DUAL, METIS_GTYPE_NODAL } mgtype_et; /*! Coarsening Schemes */ typedef enum { METIS_CTYPE_RM, METIS_CTYPE_SHEM } mctype_et; /*! Initial partitioning schemes */ typedef enum { METIS_IPTYPE_GROW, METIS_IPTYPE_RANDOM, METIS_IPTYPE_EDGE, METIS_IPTYPE_NODE, METIS_IPTYPE_METISRB } miptype_et; /*! Refinement schemes */ typedef enum { METIS_RTYPE_FM, METIS_RTYPE_GREEDY, METIS_RTYPE_SEP2SIDED, METIS_RTYPE_SEP1SIDED } mrtype_et; /*! Debug Levels */ typedef enum { METIS_DBG_INFO = 1, /*!< Shows various diagnostic messages */ METIS_DBG_TIME = 2, /*!< Perform timing analysis */ METIS_DBG_COARSEN = 4, /*!< Show the coarsening progress */ METIS_DBG_REFINE = 8, /*!< Show the refinement progress */ METIS_DBG_IPART = 16, /*!< Show info on initial partitioning */ METIS_DBG_MOVEINFO = 32, /*!< Show info on vertex moves during refinement */ METIS_DBG_SEPINFO = 64, /*!< Show info on vertex moves during sep refinement */ METIS_DBG_CONNINFO = 128, /*!< Show info on minimization of subdomain connectivity */ METIS_DBG_CONTIGINFO = 256, /*!< Show info on elimination of connected components */ METIS_DBG_MEMORY = 2048, /*!< Show info related to wspace allocation */ } mdbglvl_et; /* Types of objectives */ typedef enum { METIS_OBJTYPE_CUT, METIS_OBJTYPE_VOL, METIS_OBJTYPE_NODE } mobjtype_et; #endif /* _METIS_H_ */ ���������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/include/metis.h������������������������������������0000644�0001751�0000144�00000025535�14552244506�024265� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file metis.h \brief This file contains function prototypes and constant definitions for METIS * \author George \date Started 8/9/02 \version\verbatim $Id$\endverbatim */ #ifndef _METIS_H_ #define _METIS_H_ /**************************************************************************** * A set of defines that can be modified by the user *****************************************************************************/ /*-------------------------------------------------------------------------- Specifies the width of the elementary data type that will hold information about vertices and their adjacency lists. Possible values: 32 : Use 32 bit signed integers 64 : Use 64 bit signed integers A width of 64 should be specified if the number of vertices or the total number of edges in the graph exceed the limits of a 32 bit signed integer i.e., 2^31-1. Proper use of 64 bit integers requires that the c99 standard datatypes int32_t and int64_t are supported by the compiler. GCC does provides these definitions in stdint.h, but it may require some modifications on other architectures. --------------------------------------------------------------------------*/ // Revised for SuiteSparse: #define IDXTYPEWIDTH 64 /*-------------------------------------------------------------------------- Specifies the data type that will hold floating-point style information. Possible values: 32 : single precission floating point (float) 64 : double precission floating point (double) --------------------------------------------------------------------------*/ #define REALTYPEWIDTH 32 /**************************************************************************** * In principle, nothing needs to be changed beyond this point, unless the * int32_t and int64_t cannot be found in the normal places. *****************************************************************************/ /* Uniform definitions for various compilers */ #if defined(_MSC_VER) #define COMPILER_MSC #endif #if defined(__ICC) #define COMPILER_ICC #endif #if defined(__GNUC__) #define COMPILER_GCC #endif /* Include c99 int definitions and need constants. When building the library, * these are already defined by GKlib; hence the test for _GKLIB_H_ */ #ifndef _GKLIB_H_ #ifdef COMPILER_MSC #include typedef __int32 int32_t; typedef __int64 int64_t; #define PRId32 "I32d" #define PRId64 "I64d" #define SCNd32 "ld" #define SCNd64 "I64d" #define INT32_MIN ((int32_t)_I32_MIN) #define INT32_MAX _I32_MAX #define INT64_MIN ((int64_t)_I64_MIN) #define INT64_MAX _I64_MAX #else #include #endif #endif /*------------------------------------------------------------------------ * Setup the basic datatypes *-------------------------------------------------------------------------*/ #if IDXTYPEWIDTH == 32 typedef int32_t idx_t; #define IDX_MAX INT32_MAX #define IDX_MIN INT32_MIN #define SCIDX SCNd32 #define PRIDX PRId32 #define strtoidx strtol #define iabs abs #elif IDXTYPEWIDTH == 64 typedef int64_t idx_t; #define IDX_MAX INT64_MAX #define IDX_MIN INT64_MIN #define SCIDX SCNd64 #define PRIDX PRId64 #ifdef COMPILER_MSC #define strtoidx _strtoi64 #else #define strtoidx strtoll #endif // iabs replaced with SuiteSparse_metis_abs, Dec 2022 #if 0 #define iabs labs #else #define iabs SuiteSparse_metis_abs64 static inline int64_t SuiteSparse_metis_abs64 (int64_t x) { return ((x < 0) ? (-x) : x) ; } #endif #else #error "Incorrect user-supplied value fo IDXTYPEWIDTH" #endif #if REALTYPEWIDTH == 32 typedef float real_t; #define SCREAL "f" #define PRREAL "f" #define REAL_MAX FLT_MAX #define REAL_MIN FLT_MIN #define REAL_EPSILON FLT_EPSILON #define rabs fabsf #define REALEQ(x,y) ((rabs((x)-(y)) <= FLT_EPSILON)) #ifdef COMPILER_MSC #define strtoreal (float)strtod #else #define strtoreal strtof #endif #elif REALTYPEWIDTH == 64 typedef double real_t; #define SCREAL "lf" #define PRREAL "lf" #define REAL_MAX DBL_MAX #define REAL_MIN DBL_MIN #define REAL_EPSILON DBL_EPSILON #define rabs fabs #define REALEQ(x,y) ((rabs((x)-(y)) <= DBL_EPSILON)) #define strtoreal strtod #else #error "Incorrect user-supplied value for REALTYPEWIDTH" #endif /*------------------------------------------------------------------------ * Constant definitions *-------------------------------------------------------------------------*/ /* Metis's version number */ #define METIS_VER_MAJOR 5 #define METIS_VER_MINOR 1 #define METIS_VER_SUBMINOR 0 /* The maximum length of the options[] array */ #define METIS_NOPTIONS 40 /*------------------------------------------------------------------------ * Function prototypes *-------------------------------------------------------------------------*/ #if 0 // Windows __declspec removed for SuiteSparse, Jan 2023 #ifdef _WINDLL #define METIS_API(type) __declspec(dllexport) type __cdecl #elif defined(__cdecl) #define METIS_API(type) type __cdecl #else #define METIS_API(type) type #endif #else #define METIS_API(type) type #endif #ifdef __cplusplus extern "C" { #endif METIS_API(int) METIS_PartGraphRecursive(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt, idx_t *nparts, real_t *tpwgts, real_t *ubvec, idx_t *options, idx_t *edgecut, idx_t *part); METIS_API(int) METIS_PartGraphKway(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt, idx_t *nparts, real_t *tpwgts, real_t *ubvec, idx_t *options, idx_t *edgecut, idx_t *part); METIS_API(int) METIS_MeshToDual(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *ncommon, idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy); METIS_API(int) METIS_MeshToNodal(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy); METIS_API(int) METIS_PartMeshNodal(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *vwgt, idx_t *vsize, idx_t *nparts, real_t *tpwgts, idx_t *options, idx_t *objval, idx_t *epart, idx_t *npart); METIS_API(int) METIS_PartMeshDual(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *vwgt, idx_t *vsize, idx_t *ncommon, idx_t *nparts, real_t *tpwgts, idx_t *options, idx_t *objval, idx_t *epart, idx_t *npart); METIS_API(int) METIS_NodeND(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *options, idx_t *perm, idx_t *iperm); METIS_API(int) METIS_Free(void *ptr); METIS_API(int) METIS_SetDefaultOptions(idx_t *options); /* These functions are used by ParMETIS */ METIS_API(int) METIS_NodeNDP(idx_t nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t npes, idx_t *options, idx_t *perm, idx_t *iperm, idx_t *sizes); METIS_API(int) METIS_ComputeVertexSeparator(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *options, idx_t *sepsize, idx_t *part); METIS_API(int) METIS_NodeRefine(idx_t nvtxs, idx_t *xadj, idx_t *vwgt, idx_t *adjncy, idx_t *where, idx_t *hmarker, real_t ubfactor); #ifdef __cplusplus } #endif /*------------------------------------------------------------------------ * Enum type definitions *-------------------------------------------------------------------------*/ /*! Return codes */ typedef enum { METIS_OK = 1, /*!< Returned normally */ METIS_ERROR_INPUT = -2, /*!< Returned due to erroneous inputs and/or options */ METIS_ERROR_MEMORY = -3, /*!< Returned due to insufficient memory */ METIS_ERROR = -4 /*!< Some other errors */ } rstatus_et; /*! Operation type codes */ typedef enum { METIS_OP_PMETIS, METIS_OP_KMETIS, METIS_OP_OMETIS } moptype_et; /*! Options codes (i.e., options[]) */ typedef enum { METIS_OPTION_PTYPE, METIS_OPTION_OBJTYPE, METIS_OPTION_CTYPE, METIS_OPTION_IPTYPE, METIS_OPTION_RTYPE, METIS_OPTION_DBGLVL, METIS_OPTION_NITER, METIS_OPTION_NCUTS, METIS_OPTION_SEED, METIS_OPTION_NO2HOP, METIS_OPTION_MINCONN, METIS_OPTION_CONTIG, METIS_OPTION_COMPRESS, METIS_OPTION_CCORDER, METIS_OPTION_PFACTOR, METIS_OPTION_NSEPS, METIS_OPTION_UFACTOR, METIS_OPTION_NUMBERING, /* Used for command-line parameter purposes */ METIS_OPTION_HELP, METIS_OPTION_TPWGTS, METIS_OPTION_NCOMMON, METIS_OPTION_NOOUTPUT, METIS_OPTION_BALANCE, METIS_OPTION_GTYPE, METIS_OPTION_UBVEC } moptions_et; /*! Partitioning Schemes */ typedef enum { METIS_PTYPE_RB, METIS_PTYPE_KWAY } mptype_et; /*! Graph types for meshes */ typedef enum { METIS_GTYPE_DUAL, METIS_GTYPE_NODAL } mgtype_et; /*! Coarsening Schemes */ typedef enum { METIS_CTYPE_RM, METIS_CTYPE_SHEM } mctype_et; /*! Initial partitioning schemes */ typedef enum { METIS_IPTYPE_GROW, METIS_IPTYPE_RANDOM, METIS_IPTYPE_EDGE, METIS_IPTYPE_NODE, METIS_IPTYPE_METISRB } miptype_et; /*! Refinement schemes */ typedef enum { METIS_RTYPE_FM, METIS_RTYPE_GREEDY, METIS_RTYPE_SEP2SIDED, METIS_RTYPE_SEP1SIDED } mrtype_et; /*! Debug Levels */ typedef enum { METIS_DBG_INFO = 1, /*!< Shows various diagnostic messages */ METIS_DBG_TIME = 2, /*!< Perform timing analysis */ METIS_DBG_COARSEN = 4, /*!< Show the coarsening progress */ METIS_DBG_REFINE = 8, /*!< Show the refinement progress */ METIS_DBG_IPART = 16, /*!< Show info on initial partitioning */ METIS_DBG_MOVEINFO = 32, /*!< Show info on vertex moves during refinement */ METIS_DBG_SEPINFO = 64, /*!< Show info on vertex moves during sep refinement */ METIS_DBG_CONNINFO = 128, /*!< Show info on minimization of subdomain connectivity */ METIS_DBG_CONTIGINFO = 256, /*!< Show info on elimination of connected components */ METIS_DBG_MEMORY = 2048, /*!< Show info related to wspace allocation */ } mdbglvl_et; /* Types of objectives */ typedef enum { METIS_OBJTYPE_CUT, METIS_OBJTYPE_VOL, METIS_OBJTYPE_NODE } mobjtype_et; #endif /* _METIS_H_ */ �������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/���������������������������������������������0000755�0001751�0000144�00000000000�14576343415�022333� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/mcore.c��������������������������������������0000644�0001751�0000144�00000030413�14575233601�023577� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file \brief Functions dealing with creating and allocating mcores \date Started 5/30/11 \author George \author Copyright 1997-2011, Regents of the University of Minnesota \version $Id: mcore.c 13953 2013-03-30 16:20:07Z karypis $ */ #include "GKlib.h" /*************************************************************************/ /*! This function creates an mcore */ /*************************************************************************/ gk_mcore_t *gk_mcoreCreate(size_t coresize) { gk_mcore_t *mcore; mcore = (gk_mcore_t *)gk_malloc(sizeof(gk_mcore_t), "gk_mcoreCreate: mcore"); memset(mcore, 0, sizeof(gk_mcore_t)); mcore->coresize = coresize; mcore->corecpos = 0; mcore->core = (coresize == 0 ? NULL : gk_malloc(mcore->coresize, "gk_mcoreCreate: core")); /* allocate the memory for keeping track of malloc ops */ mcore->nmops = 2048; mcore->cmop = 0; mcore->mops = (gk_mop_t *)gk_malloc(mcore->nmops*sizeof(gk_mop_t), "gk_mcoreCreate: mcore->mops"); return mcore; } /*************************************************************************/ /*! This function creates an mcore. This version is used for gkmcore. */ /*************************************************************************/ gk_mcore_t *gk_gkmcoreCreate(void) { gk_mcore_t *mcore; if ((mcore = (gk_mcore_t *)malloc(sizeof(gk_mcore_t))) == NULL) return NULL; memset(mcore, 0, sizeof(gk_mcore_t)); /* allocate the memory for keeping track of malloc ops */ mcore->nmops = 2048; mcore->cmop = 0; if ((mcore->mops = (gk_mop_t *)malloc(mcore->nmops*sizeof(gk_mop_t))) == NULL) { free(mcore); return NULL; } return mcore; } /*************************************************************************/ /*! This function destroys an mcore. */ /*************************************************************************/ void gk_mcoreDestroy(gk_mcore_t **r_mcore, int showstats) { gk_mcore_t *mcore = *r_mcore; if (mcore == NULL) return; #ifndef NDEBUG if (showstats) printf("\n gk_mcore statistics\n" " coresize: %12zu nmops: %12zu cmop: %6zu\n" " num_callocs: %12zu num_hallocs: %12zu\n" " size_callocs: %12zu size_hallocs: %12zu\n" " cur_callocs: %12zu cur_hallocs: %12zu\n" " max_callocs: %12zu max_hallocs: %12zu\n", mcore->coresize, mcore->nmops, mcore->cmop, mcore->num_callocs, mcore->num_hallocs, mcore->size_callocs, mcore->size_hallocs, mcore->cur_callocs, mcore->cur_hallocs, mcore->max_callocs, mcore->max_hallocs); if (mcore->cur_callocs != 0 || mcore->cur_hallocs != 0 || mcore->cmop != 0) { printf("***Warning: mcore memory was not fully freed when destroyed.\n" " cur_callocs: %6zu cur_hallocs: %6zu cmop: %6zu\n", mcore->cur_callocs, mcore->cur_hallocs, mcore->cmop); } #endif gk_free((void **)&mcore->core, &mcore->mops, &mcore, LTERM); *r_mcore = NULL; } /*************************************************************************/ /*! This function destroys an mcore. This version is for gkmcore. */ /*************************************************************************/ void gk_gkmcoreDestroy(gk_mcore_t **r_mcore, int showstats) { gk_mcore_t *mcore = *r_mcore; if (mcore == NULL) return; #ifndef NDEBUG if (showstats) printf("\n gk_mcore statistics\n" " nmops: %12zu cmop: %6zu\n" " num_hallocs: %12zu\n" " size_hallocs: %12zu\n" " cur_hallocs: %12zu\n" " max_hallocs: %12zu\n", mcore->nmops, mcore->cmop, mcore->num_hallocs, mcore->size_hallocs, mcore->cur_hallocs, mcore->max_hallocs); if (mcore->cur_hallocs != 0 || mcore->cmop != 0) { printf("***Warning: mcore memory was not fully freed when destroyed.\n" " cur_hallocs: %6zu cmop: %6zu\n", mcore->cur_hallocs, mcore->cmop); } #endif free(mcore->mops); free(mcore); *r_mcore = NULL; } /*************************************************************************/ /*! This function allocate space from the core/heap */ /*************************************************************************/ void *gk_mcoreMalloc(gk_mcore_t *mcore, size_t nbytes) { void *ptr; /* pad to make pointers 8-byte aligned */ nbytes += (nbytes%8 == 0 ? 0 : 8 - nbytes%8); if (mcore->corecpos + nbytes < mcore->coresize) { /* service this request from the core */ ptr = ((char *)mcore->core)+mcore->corecpos; mcore->corecpos += nbytes; gk_mcoreAdd(mcore, GK_MOPT_CORE, nbytes, ptr); } else { /* service this request from the heap */ ptr = gk_malloc(nbytes, "gk_mcoremalloc: ptr"); gk_mcoreAdd(mcore, GK_MOPT_HEAP, nbytes, ptr); } /* printf("MCMALLOC: %zu %d %8zu\n", mcore->cmop-1, mcore->mops[mcore->cmop-1].type, mcore->mops[mcore->cmop-1].nbytes); */ return ptr; } /*************************************************************************/ /*! This function sets a marker in the stack of malloc ops to be used subsequently for freeing purposes */ /*************************************************************************/ void gk_mcorePush(gk_mcore_t *mcore) { gk_mcoreAdd(mcore, GK_MOPT_MARK, 0, NULL); /* printf("MCPPUSH: %zu\n", mcore->cmop-1); */ } /*************************************************************************/ /*! This function sets a marker in the stack of malloc ops to be used subsequently for freeing purposes. This is the gkmcore version. */ /*************************************************************************/ void gk_gkmcorePush(gk_mcore_t *mcore) { gk_gkmcoreAdd(mcore, GK_MOPT_MARK, 0, NULL); /* printf("MCPPUSH: %zu\n", mcore->cmop-1); */ } /*************************************************************************/ /*! This function frees all mops since the last push */ /*************************************************************************/ void gk_mcorePop(gk_mcore_t *mcore) { while (mcore->cmop > 0) { mcore->cmop--; switch (mcore->mops[mcore->cmop].type) { case GK_MOPT_MARK: /* push marker */ goto DONE; break; case GK_MOPT_CORE: /* core free */ if (mcore->corecpos < mcore->mops[mcore->cmop].nbytes) errexit("Internal Error: wspace's core is about to be over-freed [%zu, %zu, %zd]\n", mcore->coresize, mcore->corecpos, mcore->mops[mcore->cmop].nbytes); mcore->corecpos -= mcore->mops[mcore->cmop].nbytes; mcore->cur_callocs -= mcore->mops[mcore->cmop].nbytes; break; case GK_MOPT_HEAP: /* heap free */ gk_free((void **)&mcore->mops[mcore->cmop].ptr, LTERM); mcore->cur_hallocs -= mcore->mops[mcore->cmop].nbytes; break; default: gk_errexit(SIGMEM, "Unknown mop type of %d\n", mcore->mops[mcore->cmop].type); } } DONE: ; /*printf("MCPPOP: %zu\n", mcore->cmop); */ } /*************************************************************************/ /*! This function frees all mops since the last push. This version is for poping the gkmcore and it uses free instead of gk_free. */ /*************************************************************************/ void gk_gkmcorePop(gk_mcore_t *mcore) { while (mcore->cmop > 0) { mcore->cmop--; switch (mcore->mops[mcore->cmop].type) { case GK_MOPT_MARK: /* push marker */ goto DONE; break; case GK_MOPT_HEAP: /* heap free */ free(mcore->mops[mcore->cmop].ptr); mcore->cur_hallocs -= mcore->mops[mcore->cmop].nbytes; break; default: gk_errexit(SIGMEM, "Unknown mop type of %d\n", mcore->mops[mcore->cmop].type); } } DONE: ; } /*************************************************************************/ /*! Adds a memory allocation at the end of the list. */ /*************************************************************************/ void gk_mcoreAdd(gk_mcore_t *mcore, int type, size_t nbytes, void *ptr) { if (mcore->cmop == mcore->nmops) { mcore->nmops *= 2; mcore->mops = realloc(mcore->mops, mcore->nmops*sizeof(gk_mop_t)); if (mcore->mops == NULL) gk_errexit(SIGMEM, "***Memory allocation for gkmcore failed.\n"); } mcore->mops[mcore->cmop].type = type; mcore->mops[mcore->cmop].nbytes = nbytes; mcore->mops[mcore->cmop].ptr = ptr; mcore->cmop++; switch (type) { case GK_MOPT_MARK: break; case GK_MOPT_CORE: mcore->num_callocs++; mcore->size_callocs += nbytes; mcore->cur_callocs += nbytes; if (mcore->max_callocs < mcore->cur_callocs) mcore->max_callocs = mcore->cur_callocs; break; case GK_MOPT_HEAP: mcore->num_hallocs++; mcore->size_hallocs += nbytes; mcore->cur_hallocs += nbytes; if (mcore->max_hallocs < mcore->cur_hallocs) mcore->max_hallocs = mcore->cur_hallocs; break; default: gk_errexit(SIGMEM, "Incorrect mcore type operation.\n"); } } /*************************************************************************/ /*! Adds a memory allocation at the end of the list. This is the gkmcore version. */ /*************************************************************************/ void gk_gkmcoreAdd(gk_mcore_t *mcore, int type, size_t nbytes, void *ptr) { if (mcore->cmop == mcore->nmops) { mcore->nmops *= 2; mcore->mops = realloc(mcore->mops, mcore->nmops*sizeof(gk_mop_t)); if (mcore->mops == NULL) gk_errexit(SIGMEM, "***Memory allocation for gkmcore failed.\n"); } mcore->mops[mcore->cmop].type = type; mcore->mops[mcore->cmop].nbytes = nbytes; mcore->mops[mcore->cmop].ptr = ptr; mcore->cmop++; switch (type) { case GK_MOPT_MARK: break; case GK_MOPT_HEAP: mcore->num_hallocs++; mcore->size_hallocs += nbytes; mcore->cur_hallocs += nbytes; if (mcore->max_hallocs < mcore->cur_hallocs) mcore->max_hallocs = mcore->cur_hallocs; break; default: gk_errexit(SIGMEM, "Incorrect mcore type operation.\n"); } } /*************************************************************************/ /*! This function deletes the mop associated with the supplied pointer. The mop has to be a heap allocation, otherwise it fails violently. */ /*************************************************************************/ void gk_mcoreDel(gk_mcore_t *mcore, void *ptr) { int i; for (i=mcore->cmop-1; i>=0; i--) { if (mcore->mops[i].type == GK_MOPT_MARK) gk_errexit(SIGMEM, "Could not find pointer %p in mcore\n", ptr); if (mcore->mops[i].ptr == ptr) { if (mcore->mops[i].type != GK_MOPT_HEAP) gk_errexit(SIGMEM, "Trying to delete a non-HEAP mop.\n"); mcore->cur_hallocs -= mcore->mops[i].nbytes; mcore->mops[i] = mcore->mops[--mcore->cmop]; return; } } gk_errexit(SIGMEM, "mcoreDel should never have been here!\n"); } /*************************************************************************/ /*! This function deletes the mop associated with the supplied pointer. The mop has to be a heap allocation, otherwise it fails violently. This is the gkmcore version. */ /*************************************************************************/ void gk_gkmcoreDel(gk_mcore_t *mcore, void *ptr) { int i; for (i=mcore->cmop-1; i>=0; i--) { if (mcore->mops[i].type == GK_MOPT_MARK) gk_errexit(SIGMEM, "Could not find pointer %p in mcore\n", ptr); if (mcore->mops[i].ptr == ptr) { if (mcore->mops[i].type != GK_MOPT_HEAP) gk_errexit(SIGMEM, "Trying to delete a non-HEAP mop.\n"); mcore->cur_hallocs -= mcore->mops[i].nbytes; mcore->mops[i] = mcore->mops[--mcore->cmop]; return; } } gk_errexit(SIGMEM, "gkmcoreDel should never have been here!\n"); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/sort.c���������������������������������������0000644�0001751�0000144�00000025236�14552244506�023471� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file sort.c \brief This file contains GKlib's various sorting routines These routines are implemented using the GKSORT macro that is defined in gk_qsort.h and is based on GNU's GLIBC qsort() implementation. Additional sorting routines can be created using the same way that these routines where defined. \date Started 4/4/07 \author George \version\verbatim $Id: sort.c 10796 2011-09-23 21:33:09Z karypis $ \endverbatim */ #include "GKlib.h" /*************************************************************************/ /*! Sorts an array of chars in increasing order */ /*************************************************************************/ void gk_csorti(size_t n, char *base) { #define char_lt(a, b) ((*a) < (*b)) GK_MKQSORT(char, base, n, char_lt); #undef char_lt } /*************************************************************************/ /*! Sorts an array of chars in decreasing order */ /*************************************************************************/ void gk_csortd(size_t n, char *base) { #define char_gt(a, b) ((*a) > (*b)) GK_MKQSORT(char, base, n, char_gt); #undef char_gt } /*************************************************************************/ /*! Sorts an array of integers in increasing order */ /*************************************************************************/ void gk_isorti(size_t n, int *base) { #define int_lt(a, b) ((*a) < (*b)) GK_MKQSORT(int, base, n, int_lt); #undef int_lt } /*************************************************************************/ /*! Sorts an array of integers in decreasing order */ /*************************************************************************/ void gk_isortd(size_t n, int *base) { #define int_gt(a, b) ((*a) > (*b)) GK_MKQSORT(int, base, n, int_gt); #undef int_gt } /*************************************************************************/ /*! Sorts an array of floats in increasing order */ /*************************************************************************/ void gk_fsorti(size_t n, float *base) { #define float_lt(a, b) ((*a) < (*b)) GK_MKQSORT(float, base, n, float_lt); #undef float_lt } /*************************************************************************/ /*! Sorts an array of floats in decreasing order */ /*************************************************************************/ void gk_fsortd(size_t n, float *base) { #define float_gt(a, b) ((*a) > (*b)) GK_MKQSORT(float, base, n, float_gt); #undef float_gt } /*************************************************************************/ /*! Sorts an array of doubles in increasing order */ /*************************************************************************/ void gk_dsorti(size_t n, double *base) { #define double_lt(a, b) ((*a) < (*b)) GK_MKQSORT(double, base, n, double_lt); #undef double_lt } /*************************************************************************/ /*! Sorts an array of doubles in decreasing order */ /*************************************************************************/ void gk_dsortd(size_t n, double *base) { #define double_gt(a, b) ((*a) > (*b)) GK_MKQSORT(double, base, n, double_gt); #undef double_gt } /*************************************************************************/ /*! Sorts an array of gk_idx_t in increasing order */ /*************************************************************************/ void gk_idxsorti(size_t n, gk_idx_t *base) { #define idx_lt(a, b) ((*a) < (*b)) GK_MKQSORT(gk_idx_t, base, n, idx_lt); #undef idx_lt } /*************************************************************************/ /*! Sorts an array of gk_idx_t in decreasing order */ /*************************************************************************/ void gk_idxsortd(size_t n, gk_idx_t *base) { #define idx_gt(a, b) ((*a) > (*b)) GK_MKQSORT(gk_idx_t, base, n, idx_gt); #undef idx_gt } /*************************************************************************/ /*! Sorts an array of gk_ckv_t in increasing order */ /*************************************************************************/ void gk_ckvsorti(size_t n, gk_ckv_t *base) { #define ckey_lt(a, b) ((a)->key < (b)->key) GK_MKQSORT(gk_ckv_t, base, n, ckey_lt); #undef ckey_lt } /*************************************************************************/ /*! Sorts an array of gk_ckv_t in decreasing order */ /*************************************************************************/ void gk_ckvsortd(size_t n, gk_ckv_t *base) { #define ckey_gt(a, b) ((a)->key > (b)->key) GK_MKQSORT(gk_ckv_t, base, n, ckey_gt); #undef ckey_gt } /*************************************************************************/ /*! Sorts an array of gk_ikv_t in increasing order */ /*************************************************************************/ void gk_ikvsorti(size_t n, gk_ikv_t *base) { #define ikey_lt(a, b) ((a)->key < (b)->key) GK_MKQSORT(gk_ikv_t, base, n, ikey_lt); #undef ikey_lt } /*************************************************************************/ /*! Sorts an array of gk_ikv_t in decreasing order */ /*************************************************************************/ void gk_ikvsortd(size_t n, gk_ikv_t *base) { #define ikey_gt(a, b) ((a)->key > (b)->key) GK_MKQSORT(gk_ikv_t, base, n, ikey_gt); #undef ikey_gt } /*************************************************************************/ /*! Sorts an array of gk_i32kv_t in increasing order */ /*************************************************************************/ void gk_i32kvsorti(size_t n, gk_i32kv_t *base) { #define ikey_lt(a, b) ((a)->key < (b)->key) GK_MKQSORT(gk_i32kv_t, base, n, ikey_lt); #undef ikey_lt } /*************************************************************************/ /*! Sorts an array of gk_i32kv_t in decreasing order */ /*************************************************************************/ void gk_i32kvsortd(size_t n, gk_i32kv_t *base) { #define ikey_gt(a, b) ((a)->key > (b)->key) GK_MKQSORT(gk_i32kv_t, base, n, ikey_gt); #undef ikey_gt } /*************************************************************************/ /*! Sorts an array of gk_i64kv_t in increasing order */ /*************************************************************************/ void gk_i64kvsorti(size_t n, gk_i64kv_t *base) { #define ikey_lt(a, b) ((a)->key < (b)->key) GK_MKQSORT(gk_i64kv_t, base, n, ikey_lt); #undef ikey_lt } /*************************************************************************/ /*! Sorts an array of gk_i64kv_t in decreasing order */ /*************************************************************************/ void gk_i64kvsortd(size_t n, gk_i64kv_t *base) { #define ikey_gt(a, b) ((a)->key > (b)->key) GK_MKQSORT(gk_i64kv_t, base, n, ikey_gt); #undef ikey_gt } /*************************************************************************/ /*! Sorts an array of gk_zkv_t in increasing order */ /*************************************************************************/ void gk_zkvsorti(size_t n, gk_zkv_t *base) { #define zkey_lt(a, b) ((a)->key < (b)->key) GK_MKQSORT(gk_zkv_t, base, n, zkey_lt); #undef zkey_lt } /*************************************************************************/ /*! Sorts an array of gk_zkv_t in decreasing order */ /*************************************************************************/ void gk_zkvsortd(size_t n, gk_zkv_t *base) { #define zkey_gt(a, b) ((a)->key > (b)->key) GK_MKQSORT(gk_zkv_t, base, n, zkey_gt); #undef zkey_gt } /*************************************************************************/ /*! Sorts an array of gk_fkv_t in increasing order */ /*************************************************************************/ void gk_fkvsorti(size_t n, gk_fkv_t *base) { #define fkey_lt(a, b) ((a)->key < (b)->key) GK_MKQSORT(gk_fkv_t, base, n, fkey_lt); #undef fkey_lt } /*************************************************************************/ /*! Sorts an array of gk_fkv_t in decreasing order */ /*************************************************************************/ void gk_fkvsortd(size_t n, gk_fkv_t *base) { #define fkey_gt(a, b) ((a)->key > (b)->key) GK_MKQSORT(gk_fkv_t, base, n, fkey_gt); #undef fkey_gt } /*************************************************************************/ /*! Sorts an array of gk_dkv_t in increasing order */ /*************************************************************************/ void gk_dkvsorti(size_t n, gk_dkv_t *base) { #define dkey_lt(a, b) ((a)->key < (b)->key) GK_MKQSORT(gk_dkv_t, base, n, dkey_lt); #undef dkey_lt } /*************************************************************************/ /*! Sorts an array of gk_fkv_t in decreasing order */ /*************************************************************************/ void gk_dkvsortd(size_t n, gk_dkv_t *base) { #define dkey_gt(a, b) ((a)->key > (b)->key) GK_MKQSORT(gk_dkv_t, base, n, dkey_gt); #undef dkey_gt } /*************************************************************************/ /*! Sorts an array of gk_skv_t in increasing order */ /*************************************************************************/ void gk_skvsorti(size_t n, gk_skv_t *base) { #define skey_lt(a, b) (strcmp((a)->key, (b)->key) < 0) GK_MKQSORT(gk_skv_t, base, n, skey_lt); #undef skey_lt } /*************************************************************************/ /*! Sorts an array of gk_skv_t in decreasing order */ /*************************************************************************/ void gk_skvsortd(size_t n, gk_skv_t *base) { #define skey_gt(a, b) (strcmp((a)->key, (b)->key) > 0) GK_MKQSORT(gk_skv_t, base, n, skey_gt); #undef skey_gt } /*************************************************************************/ /*! Sorts an array of gk_idxkv_t in increasing order */ /*************************************************************************/ void gk_idxkvsorti(size_t n, gk_idxkv_t *base) { #define idxkey_lt(a, b) ((a)->key < (b)->key) GK_MKQSORT(gk_idxkv_t, base, n, idxkey_lt); #undef idxkey_lt } /*************************************************************************/ /*! Sorts an array of gk_idxkv_t in decreasing order */ /*************************************************************************/ void gk_idxkvsortd(size_t n, gk_idxkv_t *base) { #define idxkey_gt(a, b) ((a)->key > (b)->key) GK_MKQSORT(gk_idxkv_t, base, n, idxkey_gt); #undef idxkey_gt } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_macros.h����������������������������������0000644�0001751�0000144�00000014015�14552244506�024445� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file gk_macros.h \brief This file contains various macros \date Started 3/27/2007 \author George \version\verbatim $Id: gk_macros.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim */ #ifndef _GK_MACROS_H_ #define _GK_MACROS_H_ /*------------------------------------------------------------- * Usefull commands *-------------------------------------------------------------*/ #define gk_max(a, b) ((a) >= (b) ? (a) : (b)) #define gk_min(a, b) ((a) >= (b) ? (b) : (a)) #define gk_max3(a, b, c) ((a) >= (b) && (a) >= (c) ? (a) : ((b) >= (a) && (b) >= (c) ? (b) : (c))) #define gk_SWAP(a, b, tmp) do {(tmp) = (a); (a) = (b); (b) = (tmp);} while(0) #define INC_DEC(a, b, val) do {(a) += (val); (b) -= (val);} while(0) #define sign(a, b) ((a >= 0 ? b : -b)) #define ONEOVERRANDMAX (1.0/(RAND_MAX+1.0)) #define RandomInRange(u) ((int) (ONEOVERRANDMAX*(u)*rand())) #define gk_abs(x) ((x) >= 0 ? (x) : -(x)) /*------------------------------------------------------------- * Timing macros *-------------------------------------------------------------*/ #define gk_clearcputimer(tmr) (tmr = 0.0) #define gk_startcputimer(tmr) (tmr -= gk_CPUSeconds()) #define gk_stopcputimer(tmr) (tmr += gk_CPUSeconds()) #define gk_getcputimer(tmr) (tmr) #define gk_clearwctimer(tmr) (tmr = 0.0) #define gk_startwctimer(tmr) (tmr -= gk_WClockSeconds()) #define gk_stopwctimer(tmr) (tmr += gk_WClockSeconds()) #define gk_getwctimer(tmr) (tmr) /*------------------------------------------------------------- * dbglvl handling macros *-------------------------------------------------------------*/ #define IFSET(a, flag, cmd) if ((a)&(flag)) (cmd); /*------------------------------------------------------------- * gracefull library exit macro *-------------------------------------------------------------*/ #define GKSETJMP() (setjmp(gk_return_to_entry)) #define gk_sigcatch() (setjmp(gk_jbufs[gk_cur_jbufs])) /*------------------------------------------------------------- * Debuging memory leaks *-------------------------------------------------------------*/ #ifdef DMALLOC # define MALLOC_CHECK(ptr) \ if (malloc_verify((ptr)) == DMALLOC_VERIFY_ERROR) { \ printf("***MALLOC_CHECK failed on line %d of file %s: " #ptr "\n", \ __LINE__, __FILE__); \ abort(); \ } #else # define MALLOC_CHECK(ptr) ; #endif /*------------------------------------------------------------- * CSR conversion macros *-------------------------------------------------------------*/ #define MAKECSR(i, n, a) \ do { \ for (i=1; i0; i--) a[i] = a[i-1]; \ a[0] = 0; \ } while(0) #define SHIFTCSR(i, n, a) \ do { \ for (i=n; i>0; i--) a[i] = a[i-1]; \ a[0] = 0; \ } while(0) /*------------------------------------------------------------- * ASSERTS that cannot be turned off! *-------------------------------------------------------------*/ #define GKASSERT(expr) \ if (!(expr)) { \ printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ __LINE__, __FILE__); \ abort(); \ } #define GKASSERTP(expr,msg) \ if (!(expr)) { \ printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ __LINE__, __FILE__); \ printf msg ; \ printf("\n"); \ abort(); \ } #define GKCUASSERT(expr) \ if (!(expr)) { \ printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ __LINE__, __FILE__); \ } #define GKCUASSERTP(expr,msg) \ if (!(expr)) { \ printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ __LINE__, __FILE__); \ printf msg ; \ printf("\n"); \ } /*------------------------------------------------------------- * Program Assertions *-------------------------------------------------------------*/ #ifndef NDEBUG # define ASSERT(expr) \ if (!(expr)) { \ printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ __LINE__, __FILE__); \ assert(expr); \ } # define ASSERTP(expr,msg) \ if (!(expr)) { \ printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ __LINE__, __FILE__); \ printf msg ; \ printf("\n"); \ assert(expr); \ } #else # define ASSERT(expr) ; # define ASSERTP(expr,msg) ; #endif #ifndef NDEBUG2 # define ASSERT2 ASSERT # define ASSERTP2 ASSERTP #else # define ASSERT2(expr) ; # define ASSERTP2(expr,msg) ; #endif #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/error.c��������������������������������������0000644�0001751�0000144�00000014673�14552244506�023636� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file error.c \brief Various error-handling functions This file contains functions dealing with error reporting and termination \author George \date 1/1/2007 \version\verbatim $Id: error.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim */ #define _GK_ERROR_C_ /* this is needed to properly declare the gk_jub* variables as an extern function in GKlib.h */ #include "GKlib.h" /* These are the jmp_buf for the graceful exit in case of severe errors. Multiple buffers are defined to allow for recursive invokation. */ #define MAX_JBUFS 128 __thread int gk_cur_jbufs=-1; __thread jmp_buf gk_jbufs[MAX_JBUFS]; __thread jmp_buf gk_jbuf; typedef void (*gksighandler_t)(int); /* These are the holders of the old singal handlers for the trapped signals */ static __thread gksighandler_t old_SIGMEM_handler; /* Custom signal */ static __thread gksighandler_t old_SIGERR_handler; /* Custom signal */ static __thread gksighandler_t old_SIGMEM_handlers[MAX_JBUFS]; /* Custom signal */ static __thread gksighandler_t old_SIGERR_handlers[MAX_JBUFS]; /* Custom signal */ /* The following is used to control if the gk_errexit() will actually abort or not. There is always a single copy of this variable */ static int gk_exit_on_error = 1; /*************************************************************************/ /*! This function sets the gk_exit_on_error variable */ /*************************************************************************/ void gk_set_exit_on_error(int value) { gk_exit_on_error = value; } /*************************************************************************/ /*! This function prints an error message and exits */ /*************************************************************************/ void errexit(char *f_str,...) { va_list argp; va_start(argp, f_str); vfprintf(stderr, f_str, argp); va_end(argp); if (strlen(f_str) == 0 || f_str[strlen(f_str)-1] != '\n') fprintf(stderr,"\n"); fflush(stderr); if (gk_exit_on_error) exit(-2); /* abort(); */ } /*************************************************************************/ /*! This function prints an error message and raises a signum signal */ /*************************************************************************/ void gk_errexit(int signum, char *f_str,...) { va_list argp; va_start(argp, f_str); vfprintf(stderr, f_str, argp); va_end(argp); fprintf(stderr,"\n"); fflush(stderr); if (gk_exit_on_error) raise(signum); } /***************************************************************************/ /*! This function sets a number of signal handlers and sets the return point of a longjmp */ /***************************************************************************/ int gk_sigtrap(void) { if (gk_cur_jbufs+1 >= MAX_JBUFS) return 0; gk_cur_jbufs++; old_SIGMEM_handlers[gk_cur_jbufs] = signal(SIGMEM, gk_sigthrow); old_SIGERR_handlers[gk_cur_jbufs] = signal(SIGERR, gk_sigthrow); return 1; } /***************************************************************************/ /*! This function sets the handlers for the signals to their default handlers */ /***************************************************************************/ int gk_siguntrap(void) { if (gk_cur_jbufs == -1) return 0; signal(SIGMEM, old_SIGMEM_handlers[gk_cur_jbufs]); signal(SIGERR, old_SIGERR_handlers[gk_cur_jbufs]); gk_cur_jbufs--; return 1; } /*************************************************************************/ /*! This function is the custome signal handler, which all it does is to perform a longjump to the most recent saved environment */ /*************************************************************************/ void gk_sigthrow(int signum) { longjmp(gk_jbufs[gk_cur_jbufs], signum); } /*************************************************************************** * This function sets a number of signal handlers and sets the return point * of a longjmp ****************************************************************************/ void gk_SetSignalHandlers(void) { old_SIGMEM_handler = signal(SIGMEM, gk_NonLocalExit_Handler); old_SIGERR_handler = signal(SIGERR, gk_NonLocalExit_Handler); } /*************************************************************************** * This function sets the handlers for the signals to their default handlers ****************************************************************************/ void gk_UnsetSignalHandlers(void) { signal(SIGMEM, old_SIGMEM_handler); signal(SIGERR, old_SIGERR_handler); } /************************************************************************* * This function is the handler for SIGUSR1 that implements the cleaning up * process prior to a non-local exit. **************************************************************************/ void gk_NonLocalExit_Handler(int signum) { longjmp(gk_jbuf, signum); } /*************************************************************************/ /*! \brief Thread-safe implementation of strerror() */ /**************************************************************************/ #if 0 // gk_strerror disabled for SuiteSparse, Jan 2023 char *gk_strerror(int errnum) { #if defined(WIN32) || defined(__MINGW32__) return strerror(errnum); #else #ifndef SUNOS static __thread char buf[1024]; strerror_r(errnum, buf, 1024); buf[1023] = '\0'; return buf; #else return strerror(errnum); #endif #endif } #endif /************************************************************************* * This function prints a backtrace of calling functions **************************************************************************/ void PrintBackTrace(void) { #ifdef HAVE_EXECINFO_H void *array[10]; int i, size; char **strings; size = backtrace(array, 10); strings = backtrace_symbols(array, size); printf("Obtained %d stack frames.\n", size); for (i=0; inrows = mat->ncols = -1; } /*************************************************************************/ /*! Frees all the memory allocated for matrix. \param mat is the matrix to be freed. */ /*************************************************************************/ void gk_csr_Free(gk_csr_t **mat) { if (*mat == NULL) return; gk_csr_FreeContents(*mat); gk_free((void **)mat, LTERM); } /*************************************************************************/ /*! Frees only the memory allocated for the matrix's different fields and sets them to NULL. \param mat is the matrix whose contents will be freed. */ /*************************************************************************/ void gk_csr_FreeContents(gk_csr_t *mat) { gk_free((void *)&mat->rowptr, &mat->rowind, &mat->rowval, &mat->rowids, &mat->colptr, &mat->colind, &mat->colval, &mat->colids, &mat->rnorms, &mat->cnorms, &mat->rsums, &mat->csums, &mat->rsizes, &mat->csizes, &mat->rvols, &mat->cvols, &mat->rwgts, &mat->cwgts, LTERM); } /*************************************************************************/ /*! Returns a copy of a matrix. \param mat is the matrix to be duplicated. \returns the newly created copy of the matrix. */ /**************************************************************************/ gk_csr_t *gk_csr_Dup(gk_csr_t *mat) { gk_csr_t *nmat; nmat = gk_csr_Create(); nmat->nrows = mat->nrows; nmat->ncols = mat->ncols; /* copy the row structure */ if (mat->rowptr) nmat->rowptr = gk_zcopy(mat->nrows+1, mat->rowptr, gk_zmalloc(mat->nrows+1, "gk_csr_Dup: rowptr")); if (mat->rowids) nmat->rowids = gk_icopy(mat->nrows, mat->rowids, gk_imalloc(mat->nrows, "gk_csr_Dup: rowids")); if (mat->rnorms) nmat->rnorms = gk_fcopy(mat->nrows, mat->rnorms, gk_fmalloc(mat->nrows, "gk_csr_Dup: rnorms")); if (mat->rowind) nmat->rowind = gk_icopy(mat->rowptr[mat->nrows], mat->rowind, gk_imalloc(mat->rowptr[mat->nrows], "gk_csr_Dup: rowind")); if (mat->rowval) nmat->rowval = gk_fcopy(mat->rowptr[mat->nrows], mat->rowval, gk_fmalloc(mat->rowptr[mat->nrows], "gk_csr_Dup: rowval")); /* copy the col structure */ if (mat->colptr) nmat->colptr = gk_zcopy(mat->ncols+1, mat->colptr, gk_zmalloc(mat->ncols+1, "gk_csr_Dup: colptr")); if (mat->colids) nmat->colids = gk_icopy(mat->ncols, mat->colids, gk_imalloc(mat->ncols, "gk_csr_Dup: colids")); if (mat->cnorms) nmat->cnorms = gk_fcopy(mat->ncols, mat->cnorms, gk_fmalloc(mat->ncols, "gk_csr_Dup: cnorms")); if (mat->colind) nmat->colind = gk_icopy(mat->colptr[mat->ncols], mat->colind, gk_imalloc(mat->colptr[mat->ncols], "gk_csr_Dup: colind")); if (mat->colval) nmat->colval = gk_fcopy(mat->colptr[mat->ncols], mat->colval, gk_fmalloc(mat->colptr[mat->ncols], "gk_csr_Dup: colval")); return nmat; } /*************************************************************************/ /*! Returns a submatrix containint a set of consecutive rows. \param mat is the original matrix. \param rstart is the starting row. \param nrows is the number of rows from rstart to extract. \returns the row structure of the newly created submatrix. */ /**************************************************************************/ gk_csr_t *gk_csr_ExtractSubmatrix(gk_csr_t *mat, int rstart, int nrows) { ssize_t i; gk_csr_t *nmat; if (rstart+nrows > mat->nrows) return NULL; nmat = gk_csr_Create(); nmat->nrows = nrows; nmat->ncols = mat->ncols; /* copy the row structure */ if (mat->rowptr) nmat->rowptr = gk_zcopy(nrows+1, mat->rowptr+rstart, gk_zmalloc(nrows+1, "gk_csr_ExtractSubmatrix: rowptr")); for (i=nrows; i>=0; i--) nmat->rowptr[i] -= nmat->rowptr[0]; ASSERT(nmat->rowptr[0] == 0); if (mat->rowids) nmat->rowids = gk_icopy(nrows, mat->rowids+rstart, gk_imalloc(nrows, "gk_csr_ExtractSubmatrix: rowids")); if (mat->rnorms) nmat->rnorms = gk_fcopy(nrows, mat->rnorms+rstart, gk_fmalloc(nrows, "gk_csr_ExtractSubmatrix: rnorms")); if (mat->rsums) nmat->rsums = gk_fcopy(nrows, mat->rsums+rstart, gk_fmalloc(nrows, "gk_csr_ExtractSubmatrix: rsums")); ASSERT(nmat->rowptr[nrows] == mat->rowptr[rstart+nrows]-mat->rowptr[rstart]); if (mat->rowind) nmat->rowind = gk_icopy(mat->rowptr[rstart+nrows]-mat->rowptr[rstart], mat->rowind+mat->rowptr[rstart], gk_imalloc(mat->rowptr[rstart+nrows]-mat->rowptr[rstart], "gk_csr_ExtractSubmatrix: rowind")); if (mat->rowval) nmat->rowval = gk_fcopy(mat->rowptr[rstart+nrows]-mat->rowptr[rstart], mat->rowval+mat->rowptr[rstart], gk_fmalloc(mat->rowptr[rstart+nrows]-mat->rowptr[rstart], "gk_csr_ExtractSubmatrix: rowval")); return nmat; } /*************************************************************************/ /*! Returns a submatrix containing a certain set of rows. \param mat is the original matrix. \param nrows is the number of rows to extract. \param rind is the set of row numbers to extract. \returns the row structure of the newly created submatrix. */ /**************************************************************************/ gk_csr_t *gk_csr_ExtractRows(gk_csr_t *mat, int nrows, int *rind) { ssize_t i, ii, j, nnz; gk_csr_t *nmat; nmat = gk_csr_Create(); nmat->nrows = nrows; nmat->ncols = mat->ncols; for (nnz=0, i=0; irowptr[rind[i]+1]-mat->rowptr[rind[i]]; nmat->rowptr = gk_zmalloc(nmat->nrows+1, "gk_csr_ExtractPartition: rowptr"); nmat->rowind = gk_imalloc(nnz, "gk_csr_ExtractPartition: rowind"); nmat->rowval = gk_fmalloc(nnz, "gk_csr_ExtractPartition: rowval"); nmat->rowptr[0] = 0; for (nnz=0, j=0, ii=0; iirowptr[i+1]-mat->rowptr[i], mat->rowind+mat->rowptr[i], nmat->rowind+nnz); gk_fcopy(mat->rowptr[i+1]-mat->rowptr[i], mat->rowval+mat->rowptr[i], nmat->rowval+nnz); nnz += mat->rowptr[i+1]-mat->rowptr[i]; nmat->rowptr[++j] = nnz; } ASSERT(j == nmat->nrows); return nmat; } /*************************************************************************/ /*! Returns a submatrix corresponding to a specified partitioning of rows. \param mat is the original matrix. \param part is the partitioning vector of the rows. \param pid is the partition ID that will be extracted. \returns the row structure of the newly created submatrix. */ /**************************************************************************/ gk_csr_t *gk_csr_ExtractPartition(gk_csr_t *mat, int *part, int pid) { ssize_t i, j, nnz; gk_csr_t *nmat; nmat = gk_csr_Create(); nmat->nrows = 0; nmat->ncols = mat->ncols; for (nnz=0, i=0; inrows; i++) { if (part[i] == pid) { nmat->nrows++; nnz += mat->rowptr[i+1]-mat->rowptr[i]; } } nmat->rowptr = gk_zmalloc(nmat->nrows+1, "gk_csr_ExtractPartition: rowptr"); nmat->rowind = gk_imalloc(nnz, "gk_csr_ExtractPartition: rowind"); nmat->rowval = gk_fmalloc(nnz, "gk_csr_ExtractPartition: rowval"); nmat->rowptr[0] = 0; for (nnz=0, j=0, i=0; inrows; i++) { if (part[i] == pid) { gk_icopy(mat->rowptr[i+1]-mat->rowptr[i], mat->rowind+mat->rowptr[i], nmat->rowind+nnz); gk_fcopy(mat->rowptr[i+1]-mat->rowptr[i], mat->rowval+mat->rowptr[i], nmat->rowval+nnz); nnz += mat->rowptr[i+1]-mat->rowptr[i]; nmat->rowptr[++j] = nnz; } } ASSERT(j == nmat->nrows); return nmat; } /*************************************************************************/ /*! Splits the matrix into multiple sub-matrices based on the provided color array. \param mat is the original matrix. \param color is an array of size equal to the number of non-zeros in the matrix (row-wise structure). The matrix is split into as many parts as the number of colors. For meaningfull results, the colors should be numbered consecutively starting from 0. \returns an array of matrices for each supplied color number. */ /**************************************************************************/ gk_csr_t **gk_csr_Split(gk_csr_t *mat, int *color) { ssize_t i, j; int nrows, ncolors; ssize_t *rowptr; int *rowind; float *rowval; gk_csr_t **smats; nrows = mat->nrows; rowptr = mat->rowptr; rowind = mat->rowind; rowval = mat->rowval; ncolors = gk_imax(rowptr[nrows], color)+1; smats = (gk_csr_t **)gk_malloc(sizeof(gk_csr_t *)*ncolors, "gk_csr_Split: smats"); for (i=0; inrows = mat->nrows; smats[i]->ncols = mat->ncols; smats[i]->rowptr = gk_zsmalloc(nrows+1, 0, "gk_csr_Split: smats[i]->rowptr"); } for (i=0; irowptr[i]++; } for (i=0; irowptr); for (i=0; irowind = gk_imalloc(smats[i]->rowptr[nrows], "gk_csr_Split: smats[i]->rowind"); smats[i]->rowval = gk_fmalloc(smats[i]->rowptr[nrows], "gk_csr_Split: smats[i]->rowval"); } for (i=0; irowind[smats[color[j]]->rowptr[i]] = rowind[j]; smats[color[j]]->rowval[smats[color[j]]->rowptr[i]] = rowval[j]; smats[color[j]]->rowptr[i]++; } } for (i=0; irowptr); return smats; } /**************************************************************************/ /*! Reads a CSR matrix from the supplied file and stores it the matrix's forward structure. \param filename is the file that stores the data. \param format is either GK_CSR_FMT_METIS, GK_CSR_FMT_CLUTO, GK_CSR_FMT_CSR, GK_CSR_FMT_BINROW, GK_CSR_FMT_BINCOL specifying the type of the input format. The GK_CSR_FMT_CSR does not contain a header line, whereas the GK_CSR_FMT_BINROW is a binary format written by gk_csr_Write() using the same format specifier. \param readvals is either 1 or 0, indicating if the CSR file contains values or it does not. It only applies when GK_CSR_FMT_CSR is used. \param numbering is either 1 or 0, indicating if the numbering of the indices start from 1 or 0, respectively. If they start from 1, they are automatically decreamented during input so that they will start from 0. It only applies when GK_CSR_FMT_CSR is used. \returns the matrix that was read. */ /**************************************************************************/ gk_csr_t *gk_csr_Read(char *filename, int format, int readvals, int numbering) { ssize_t i, k, l; size_t nfields, nrows, ncols, nnz, fmt, ncon; size_t lnlen; ssize_t *rowptr; int *rowind, ival; float *rowval=NULL, fval; int readsizes, readwgts; char *line=NULL, *head, *tail, fmtstr[256]; FILE *fpin; gk_csr_t *mat=NULL; if (!gk_fexists(filename)) gk_errexit(SIGERR, "File %s does not exist!\n", filename); if (format == GK_CSR_FMT_BINROW) { mat = gk_csr_Create(); fpin = gk_fopen(filename, "rb", "gk_csr_Read: fpin"); if (fread(&(mat->nrows), sizeof(int32_t), 1, fpin) != 1) gk_errexit(SIGERR, "Failed to read the nrows from file %s!\n", filename); if (fread(&(mat->ncols), sizeof(int32_t), 1, fpin) != 1) gk_errexit(SIGERR, "Failed to read the ncols from file %s!\n", filename); mat->rowptr = gk_zmalloc(mat->nrows+1, "gk_csr_Read: rowptr"); if (fread(mat->rowptr, sizeof(ssize_t), mat->nrows+1, fpin) != mat->nrows+1) gk_errexit(SIGERR, "Failed to read the rowptr from file %s!\n", filename); mat->rowind = gk_imalloc(mat->rowptr[mat->nrows], "gk_csr_Read: rowind"); if (fread(mat->rowind, sizeof(int32_t), mat->rowptr[mat->nrows], fpin) != mat->rowptr[mat->nrows]) gk_errexit(SIGERR, "Failed to read the rowind from file %s!\n", filename); if (readvals == 1) { mat->rowval = gk_fmalloc(mat->rowptr[mat->nrows], "gk_csr_Read: rowval"); if (fread(mat->rowval, sizeof(float), mat->rowptr[mat->nrows], fpin) != mat->rowptr[mat->nrows]) gk_errexit(SIGERR, "Failed to read the rowval from file %s!\n", filename); } gk_fclose(fpin); return mat; } if (format == GK_CSR_FMT_BINCOL) { mat = gk_csr_Create(); fpin = gk_fopen(filename, "rb", "gk_csr_Read: fpin"); if (fread(&(mat->nrows), sizeof(int32_t), 1, fpin) != 1) gk_errexit(SIGERR, "Failed to read the nrows from file %s!\n", filename); if (fread(&(mat->ncols), sizeof(int32_t), 1, fpin) != 1) gk_errexit(SIGERR, "Failed to read the ncols from file %s!\n", filename); mat->colptr = gk_zmalloc(mat->ncols+1, "gk_csr_Read: colptr"); if (fread(mat->colptr, sizeof(ssize_t), mat->ncols+1, fpin) != mat->ncols+1) gk_errexit(SIGERR, "Failed to read the colptr from file %s!\n", filename); mat->colind = gk_imalloc(mat->colptr[mat->ncols], "gk_csr_Read: colind"); if (fread(mat->colind, sizeof(int32_t), mat->colptr[mat->ncols], fpin) != mat->colptr[mat->ncols]) gk_errexit(SIGERR, "Failed to read the colind from file %s!\n", filename); if (readvals) { mat->colval = gk_fmalloc(mat->colptr[mat->ncols], "gk_csr_Read: colval"); if (fread(mat->colval, sizeof(float), mat->colptr[mat->ncols], fpin) != mat->colptr[mat->ncols]) gk_errexit(SIGERR, "Failed to read the colval from file %s!\n", filename); } gk_fclose(fpin); return mat; } if (format == GK_CSR_FMT_CLUTO) { fpin = gk_fopen(filename, "r", "gk_csr_Read: fpin"); do { if (gk_getline(&line, &lnlen, fpin) <= 0) gk_errexit(SIGERR, "Premature end of input file: file:%s\n", filename); } while (line[0] == '%'); if (sscanf(line, "%zu %zu %zu", &nrows, &ncols, &nnz) != 3) gk_errexit(SIGERR, "Header line must contain 3 integers.\n"); readsizes = 0; readwgts = 0; readvals = 1; numbering = 1; } else if (format == GK_CSR_FMT_METIS) { fpin = gk_fopen(filename, "r", "gk_csr_Read: fpin"); do { if (gk_getline(&line, &lnlen, fpin) <= 0) gk_errexit(SIGERR, "Premature end of input file: file:%s\n", filename); } while (line[0] == '%'); fmt = ncon = 0; nfields = sscanf(line, "%zu %zu %zu %zu", &nrows, &nnz, &fmt, &ncon); if (nfields < 2) gk_errexit(SIGERR, "Header line must contain at least 2 integers (#vtxs and #edges).\n"); ncols = nrows; nnz *= 2; if (fmt > 111) gk_errexit(SIGERR, "Cannot read this type of file format [fmt=%zu]!\n", fmt); sprintf(fmtstr, "%03zu", fmt%1000); readsizes = (fmtstr[0] == '1'); readwgts = (fmtstr[1] == '1'); readvals = (fmtstr[2] == '1'); numbering = 1; ncon = (ncon == 0 ? 1 : ncon); } else { readsizes = 0; readwgts = 0; gk_getfilestats(filename, &nrows, &nnz, NULL, NULL); if (readvals == 1 && nnz%2 == 1) gk_errexit(SIGERR, "Error: The number of numbers (%zd %d) in the input file is not even.\n", nnz, readvals); if (readvals == 1) nnz = nnz/2; fpin = gk_fopen(filename, "r", "gk_csr_Read: fpin"); } mat = gk_csr_Create(); mat->nrows = nrows; rowptr = mat->rowptr = gk_zmalloc(nrows+1, "gk_csr_Read: rowptr"); rowind = mat->rowind = gk_imalloc(nnz, "gk_csr_Read: rowind"); if (readvals != 2) rowval = mat->rowval = gk_fsmalloc(nnz, 1.0, "gk_csr_Read: rowval"); if (readsizes) mat->rsizes = gk_fsmalloc(nrows, 0.0, "gk_csr_Read: rsizes"); if (readwgts) mat->rwgts = gk_fsmalloc(nrows*ncon, 0.0, "gk_csr_Read: rwgts"); /*---------------------------------------------------------------------- * Read the sparse matrix file *---------------------------------------------------------------------*/ numbering = (numbering ? - 1 : 0); for (ncols=0, rowptr[0]=0, k=0, i=0; irsizes[i] = (float)strtod(head, &tail); #else mat->rsizes[i] = strtof(head, &tail); #endif if (tail == head) gk_errexit(SIGERR, "The line for vertex %zd does not have size information\n", i+1); if (mat->rsizes[i] < 0) errexit("The size for vertex %zd must be >= 0\n", i+1); head = tail; } /* Read vertex weights */ if (readwgts) { for (l=0; lrwgts[i*ncon+l] = (float)strtod(head, &tail); #else mat->rwgts[i*ncon+l] = strtof(head, &tail); #endif if (tail == head) errexit("The line for vertex %zd does not have enough weights " "for the %d constraints.\n", i+1, ncon); if (mat->rwgts[i*ncon+l] < 0) errexit("The weight vertex %zd and constraint %zd must be >= 0\n", i+1, l); head = tail; } } /* Read the rest of the row */ while (1) { ival = (int)strtol(head, &tail, 0); if (tail == head) break; head = tail; if ((rowind[k] = ival + numbering) < 0) gk_errexit(SIGERR, "Error: Invalid column number %d at row %zd.\n", ival, i); ncols = gk_max(rowind[k], ncols); if (readvals == 1) { #ifdef __MSC__ fval = (float)strtod(head, &tail); #else fval = strtof(head, &tail); #endif if (tail == head) gk_errexit(SIGERR, "Value could not be found for column! Row:%zd, NNZ:%zd\n", i, k); head = tail; rowval[k] = fval; } k++; } rowptr[i+1] = k; } if (format == GK_CSR_FMT_METIS) { ASSERT(ncols+1 == mat->nrows); mat->ncols = mat->nrows; } else { mat->ncols = ncols+1; } if (k != nnz) gk_errexit(SIGERR, "gk_csr_Read: Something wrong with the number of nonzeros in " "the input file. NNZ=%zd, ActualNNZ=%zd.\n", nnz, k); gk_fclose(fpin); gk_free((void **)&line, LTERM); return mat; } /**************************************************************************/ /*! Writes the row-based structure of a matrix into a file. \param mat is the matrix to be written, \param filename is the name of the output file. \param format is one of: GK_CSR_FMT_CLUTO, GK_CSR_FMT_CSR, GK_CSR_FMT_BINROW, GK_CSR_FMT_BINCOL. \param writevals is either 1 or 0 indicating if the values will be written or not. This is only applicable when GK_CSR_FMT_CSR is used. \param numbering is either 1 or 0 indicating if the internal 0-based numbering will be shifted by one or not during output. This is only applicable when GK_CSR_FMT_CSR is used. */ /**************************************************************************/ void gk_csr_Write(gk_csr_t *mat, char *filename, int format, int writevals, int numbering) { ssize_t i, j; FILE *fpout; if (format == GK_CSR_FMT_BINROW) { if (filename == NULL) gk_errexit(SIGERR, "The filename parameter cannot be NULL.\n"); fpout = gk_fopen(filename, "wb", "gk_csr_Write: fpout"); fwrite(&(mat->nrows), sizeof(int32_t), 1, fpout); fwrite(&(mat->ncols), sizeof(int32_t), 1, fpout); fwrite(mat->rowptr, sizeof(ssize_t), mat->nrows+1, fpout); fwrite(mat->rowind, sizeof(int32_t), mat->rowptr[mat->nrows], fpout); if (writevals) fwrite(mat->rowval, sizeof(float), mat->rowptr[mat->nrows], fpout); gk_fclose(fpout); return; } if (format == GK_CSR_FMT_BINCOL) { if (filename == NULL) gk_errexit(SIGERR, "The filename parameter cannot be NULL.\n"); fpout = gk_fopen(filename, "wb", "gk_csr_Write: fpout"); fwrite(&(mat->nrows), sizeof(int32_t), 1, fpout); fwrite(&(mat->ncols), sizeof(int32_t), 1, fpout); fwrite(mat->colptr, sizeof(ssize_t), mat->ncols+1, fpout); fwrite(mat->colind, sizeof(int32_t), mat->colptr[mat->ncols], fpout); if (writevals) fwrite(mat->colval, sizeof(float), mat->colptr[mat->ncols], fpout); gk_fclose(fpout); return; } if (filename) fpout = gk_fopen(filename, "w", "gk_csr_Write: fpout"); else fpout = stdout; if (format == GK_CSR_FMT_CLUTO) { fprintf(fpout, "%d %d %zd\n", mat->nrows, mat->ncols, mat->rowptr[mat->nrows]); writevals = 1; numbering = 1; } for (i=0; inrows; i++) { for (j=mat->rowptr[i]; jrowptr[i+1]; j++) { fprintf(fpout, " %d", mat->rowind[j]+(numbering ? 1 : 0)); if (writevals) fprintf(fpout, " %f", mat->rowval[j]); } fprintf(fpout, "\n"); } if (filename) gk_fclose(fpout); } /*************************************************************************/ /*! Prunes certain rows/columns of the matrix. The prunning takes place by analyzing the row structure of the matrix. The prunning takes place by removing rows/columns but it does not affect the numbering of the remaining rows/columns. \param mat the matrix to be prunned, \param what indicates if the rows (GK_CSR_ROW) or the columns (GK_CSR_COL) of the matrix will be prunned, \param minf is the minimum number of rows (columns) that a column (row) must be present in order to be kept, \param maxf is the maximum number of rows (columns) that a column (row) must be present at in order to be kept. \returns the prunned matrix consisting only of its row-based structure. The input matrix is not modified. */ /**************************************************************************/ gk_csr_t *gk_csr_Prune(gk_csr_t *mat, int what, int minf, int maxf) { ssize_t i, j, nnz; int nrows, ncols; ssize_t *rowptr, *nrowptr; int *rowind, *nrowind, *collen; float *rowval, *nrowval; gk_csr_t *nmat; nmat = gk_csr_Create(); nrows = nmat->nrows = mat->nrows; ncols = nmat->ncols = mat->ncols; rowptr = mat->rowptr; rowind = mat->rowind; rowval = mat->rowval; nrowptr = nmat->rowptr = gk_zmalloc(nrows+1, "gk_csr_Prune: nrowptr"); nrowind = nmat->rowind = gk_imalloc(rowptr[nrows], "gk_csr_Prune: nrowind"); nrowval = nmat->rowval = gk_fmalloc(rowptr[nrows], "gk_csr_Prune: nrowval"); switch (what) { case GK_CSR_COL: collen = gk_ismalloc(ncols, 0, "gk_csr_Prune: collen"); for (i=0; i= minf && collen[i] <= maxf ? 1 : 0); nrowptr[0] = 0; for (nnz=0, i=0; i= minf && rowptr[i+1]-rowptr[i] <= maxf) { for (j=rowptr[i]; jnrows = mat->nrows; ncols = nmat->ncols = mat->ncols; rowptr = mat->rowptr; rowind = mat->rowind; rowval = mat->rowval; colptr = mat->colptr; colind = mat->colind; colval = mat->colval; nrowptr = nmat->rowptr = gk_zmalloc(nrows+1, "gk_csr_LowFilter: nrowptr"); nrowind = nmat->rowind = gk_imalloc(rowptr[nrows], "gk_csr_LowFilter: nrowind"); nrowval = nmat->rowval = gk_fmalloc(rowptr[nrows], "gk_csr_LowFilter: nrowval"); switch (what) { case GK_CSR_COL: if (mat->colptr == NULL) gk_errexit(SIGERR, "Cannot filter columns when column-based structure has not been created.\n"); gk_zcopy(nrows+1, rowptr, nrowptr); for (i=0; irowptr == NULL) gk_errexit(SIGERR, "Cannot filter rows when row-based structure has not been created.\n"); for (i=0; inrows = mat->nrows; ncols = nmat->ncols = mat->ncols; rowptr = mat->rowptr; rowind = mat->rowind; rowval = mat->rowval; colptr = mat->colptr; colind = mat->colind; colval = mat->colval; nrowptr = nmat->rowptr = gk_zmalloc(nrows+1, "gk_csr_LowFilter: nrowptr"); nrowind = nmat->rowind = gk_imalloc(rowptr[nrows], "gk_csr_LowFilter: nrowind"); nrowval = nmat->rowval = gk_fmalloc(rowptr[nrows], "gk_csr_LowFilter: nrowval"); switch (what) { case GK_CSR_COL: if (mat->colptr == NULL) gk_errexit(SIGERR, "Cannot filter columns when column-based structure has not been created.\n"); cand = gk_fkvmalloc(nrows, "gk_csr_LowFilter: cand"); gk_zcopy(nrows+1, rowptr, nrowptr); for (i=0; irowptr == NULL) gk_errexit(SIGERR, "Cannot filter rows when row-based structure has not been created.\n"); cand = gk_fkvmalloc(ncols, "gk_csr_LowFilter: cand"); nrowptr[0] = 0; for (nnz=0, i=0; inrows = mat->nrows; nmat->ncols = mat->ncols; nrows = mat->nrows; rowptr = mat->rowptr; rowind = mat->rowind; rowval = mat->rowval; nrowptr = nmat->rowptr = gk_zmalloc(nrows+1, "gk_csr_ZScoreFilter: nrowptr"); nrowind = nmat->rowind = gk_imalloc(rowptr[nrows], "gk_csr_ZScoreFilter: nrowind"); nrowval = nmat->rowval = gk_fmalloc(rowptr[nrows], "gk_csr_ZScoreFilter: nrowval"); switch (what) { case GK_CSR_COL: gk_errexit(SIGERR, "This has not been implemented yet.\n"); break; case GK_CSR_ROW: if (mat->rowptr == NULL) gk_errexit(SIGERR, "Cannot filter rows when row-based structure has not been created.\n"); nrowptr[0] = 0; for (nnz=0, i=0; i avgwgt) { nrowind[nnz] = rowind[j]; nrowval[nnz] = rowval[j]; nnz++; } } nrowptr[i+1] = nnz; } break; default: gk_csr_Free(&nmat); gk_errexit(SIGERR, "Unknown prunning type of %d\n", what); return NULL; } return nmat; } /*************************************************************************/ /*! Compacts the column-space of the matrix by removing empty columns. As a result of the compaction, the column numbers are renumbered. The compaction operation is done in place and only affects the row-based representation of the matrix. The new columns are ordered in decreasing frequency. \param mat the matrix whose empty columns will be removed. */ /**************************************************************************/ void gk_csr_CompactColumns(gk_csr_t *mat) { ssize_t i; int nrows, ncols, nncols; ssize_t *rowptr; int *rowind, *colmap; gk_ikv_t *clens; nrows = mat->nrows; ncols = mat->ncols; rowptr = mat->rowptr; rowind = mat->rowind; colmap = gk_imalloc(ncols, "gk_csr_CompactColumns: colmap"); clens = gk_ikvmalloc(ncols, "gk_csr_CompactColumns: clens"); for (i=0; i 0) colmap[clens[i].val] = nncols++; else break; } for (i=0; incols = nncols; gk_free((void **)&colmap, &clens, LTERM); } /*************************************************************************/ /*! Sorts the indices in increasing order \param mat the matrix itself, \param what is either GK_CSR_ROW or GK_CSR_COL indicating which set of indices to sort. */ /**************************************************************************/ void gk_csr_SortIndices(gk_csr_t *mat, int what) { int n, nn=0; ssize_t *ptr; int *ind; float *val; switch (what) { case GK_CSR_ROW: if (!mat->rowptr) gk_errexit(SIGERR, "Row-based view of the matrix does not exists.\n"); n = mat->nrows; ptr = mat->rowptr; ind = mat->rowind; val = mat->rowval; break; case GK_CSR_COL: if (!mat->colptr) gk_errexit(SIGERR, "Column-based view of the matrix does not exists.\n"); n = mat->ncols; ptr = mat->colptr; ind = mat->colind; val = mat->colval; break; default: gk_errexit(SIGERR, "Invalid index type of %d.\n", what); return; } #pragma omp parallel if (n > 100) { ssize_t i, j, k; gk_ikv_t *cand; float *tval; #pragma omp single for (i=0; i ptr[i] && ind[j] < ind[j-1]) k = 1; /* an inversion */ cand[j-ptr[i]].val = j-ptr[i]; cand[j-ptr[i]].key = ind[j]; tval[j-ptr[i]] = val[j]; } if (k) { gk_ikvsorti(ptr[i+1]-ptr[i], cand); for (j=ptr[i]; jnrows; fptr = mat->rowptr; find = mat->rowind; fval = mat->rowval; if (mat->colptr) gk_free((void **)&mat->colptr, LTERM); if (mat->colind) gk_free((void **)&mat->colind, LTERM); if (mat->colval) gk_free((void **)&mat->colval, LTERM); nr = mat->ncols; rptr = mat->colptr = gk_zsmalloc(nr+1, 0, "gk_csr_CreateIndex: rptr"); rind = mat->colind = gk_imalloc(fptr[nf], "gk_csr_CreateIndex: rind"); rval = mat->colval = (fval ? gk_fmalloc(fptr[nf], "gk_csr_CreateIndex: rval") : NULL); break; case GK_CSR_ROW: nf = mat->ncols; fptr = mat->colptr; find = mat->colind; fval = mat->colval; if (mat->rowptr) gk_free((void **)&mat->rowptr, LTERM); if (mat->rowind) gk_free((void **)&mat->rowind, LTERM); if (mat->rowval) gk_free((void **)&mat->rowval, LTERM); nr = mat->nrows; rptr = mat->rowptr = gk_zsmalloc(nr+1, 0, "gk_csr_CreateIndex: rptr"); rind = mat->rowind = gk_imalloc(fptr[nf], "gk_csr_CreateIndex: rind"); rval = mat->rowval = (fval ? gk_fmalloc(fptr[nf], "gk_csr_CreateIndex: rval") : NULL); break; default: gk_errexit(SIGERR, "Invalid index type of %d.\n", what); return; } for (i=0; i 6*nr) { for (i=0; irowval) { n = mat->nrows; ptr = mat->rowptr; val = mat->rowval; #pragma omp parallel if (ptr[n] > OMPMINOPS) { #pragma omp for private(j,sum) schedule(static) for (i=0; i 0 */ } if (sum > 0) { if (norm == 2) sum=1.0/sqrt(sum); else if (norm == 1) sum=1.0/sum; for (j=ptr[i]; jcolval) { n = mat->ncols; ptr = mat->colptr; val = mat->colval; #pragma omp parallel if (ptr[n] > OMPMINOPS) { #pragma omp for private(j,sum) schedule(static) for (i=0; i 0) { if (norm == 2) sum=1.0/sqrt(sum); else if (norm == 1) sum=1.0/sum; for (j=ptr[i]; jnrows; rowptr = mat->rowptr; rowind = mat->rowind; rowval = mat->rowval; switch (type) { case GK_CSR_MAXTF: /* TF' = .5 + .5*TF/MAX(TF) */ #pragma omp parallel if (rowptr[nrows] > OMPMINOPS) { #pragma omp for private(j, maxtf) schedule(static) for (i=0; i OMPMINOPS) { #pragma omp for private(j, maxtf) schedule(static) for (i=0; i OMPMINOPS) { #pragma omp for private(j) schedule(static) for (i=0; i OMPMINOPS) { #pragma omp for private(j) schedule(static) for (i=0; i OMPMINOPS) { #pragma omp for private(j) schedule(static) for (i=0; i OMPMINOPS) { #pragma omp for private(j) schedule(static) for (i=0; i OMPMINOPS) { #pragma omp for private(j) schedule(static) for (i=0; i OMPMINOPS) { double logscale = 1.0/log(2.0); #pragma omp for schedule(static,32) for (i=0; i0.0 ? log(rowval[i]) : -log(-rowval[i]))*logscale; } #ifdef XXX #pragma omp for private(j) schedule(static) for (i=0; i0.0 ? log(rowval[j]) : -log(-rowval[j]))*logscale; //rowval[j] = 1+sign(rowval[j], log(fabs(rowval[j]))*logscale); } } #endif } break; case GK_CSR_IDF: /* TF' = TF*IDF */ ncols = mat->ncols; cscale = gk_fmalloc(ncols, "gk_csr_Scale: cscale"); collen = gk_ismalloc(ncols, 0, "gk_csr_Scale: collen"); for (i=0; i OMPMINOPS) { #pragma omp for schedule(static) for (i=0; i 0 ? log(1.0*nrows/collen[i]) : 0.0); } #pragma omp parallel if (rowptr[nrows] > OMPMINOPS) { #pragma omp for private(j) schedule(static) for (i=0; incols; cscale = gk_fmalloc(ncols, "gk_csr_Scale: cscale"); collen = gk_ismalloc(ncols, 0, "gk_csr_Scale: collen"); for (i=0; i OMPMINOPS) { #pragma omp for schedule(static) reduction(+:nnzcols) for (i=0; i 0 ? 1 : 0); bgfreq = gk_max(10, (ssize_t)(.5*rowptr[nrows]/nnzcols)); printf("nnz: %zd, nnzcols: %d, bgfreq: %d\n", rowptr[nrows], nnzcols, bgfreq); #pragma omp for schedule(static) for (i=0; i 0 ? log(1.0*(nrows+2*bgfreq)/(bgfreq+collen[i])) : 0.0); } #pragma omp parallel if (rowptr[nrows] > OMPMINOPS) { #pragma omp for private(j) schedule(static) for (i=0; inrows; ptr = mat->rowptr; val = mat->rowval; if (mat->rsums) gk_free((void **)&mat->rsums, LTERM); sums = mat->rsums = gk_fsmalloc(n, 0, "gk_csr_ComputeSums: sums"); break; case GK_CSR_COL: n = mat->ncols; ptr = mat->colptr; val = mat->colval; if (mat->csums) gk_free((void **)&mat->csums, LTERM); sums = mat->csums = gk_fsmalloc(n, 0, "gk_csr_ComputeSums: sums"); break; default: gk_errexit(SIGERR, "Invalid sum type of %d.\n", what); return; } #pragma omp parallel for if (ptr[n] > OMPMINOPS) schedule(static) for (i=0; inrows; ptr = mat->rowptr; val = mat->rowval; if (mat->rnorms) gk_free((void **)&mat->rnorms, LTERM); norms = mat->rnorms = gk_fsmalloc(n, 0, "gk_csr_ComputeSums: norms"); break; case GK_CSR_COL: n = mat->ncols; ptr = mat->colptr; val = mat->colval; if (mat->cnorms) gk_free((void **)&mat->cnorms, LTERM); norms = mat->cnorms = gk_fsmalloc(n, 0, "gk_csr_ComputeSums: norms"); break; default: gk_errexit(SIGERR, "Invalid norm type of %d.\n", what); return; } #pragma omp parallel for if (ptr[n] > OMPMINOPS) schedule(static) for (i=0; irowptr) gk_errexit(SIGERR, "Row-based view of the matrix does not exists.\n"); nind1 = mat->rowptr[i1+1]-mat->rowptr[i1]; nind2 = mat->rowptr[i2+1]-mat->rowptr[i2]; ind1 = mat->rowind + mat->rowptr[i1]; ind2 = mat->rowind + mat->rowptr[i2]; val1 = mat->rowval + mat->rowptr[i1]; val2 = mat->rowval + mat->rowptr[i2]; break; case GK_CSR_COL: if (!mat->colptr) gk_errexit(SIGERR, "Column-based view of the matrix does not exists.\n"); nind1 = mat->colptr[i1+1]-mat->colptr[i1]; nind2 = mat->colptr[i2+1]-mat->colptr[i2]; ind1 = mat->colind + mat->colptr[i1]; ind2 = mat->colind + mat->colptr[i2]; val1 = mat->colval + mat->colptr[i1]; val2 = mat->colval + mat->colptr[i2]; break; default: gk_errexit(SIGERR, "Invalid index type of %d.\n", what); return 0.0; } switch (simtype) { case GK_CSR_COS: case GK_CSR_JAC: sim = stat1 = stat2 = 0.0; i1 = i2 = 0; while (i1 ind2[i2]) { stat2 += val2[i2]*val2[i2]; i2++; } else { sim += val1[i1]*val2[i2]; stat1 += val1[i1]*val1[i1]; stat2 += val2[i2]*val2[i2]; i1++; i2++; } } if (simtype == GK_CSR_COS) sim = (stat1*stat2 > 0.0 ? sim/sqrt(stat1*stat2) : 0.0); else sim = (stat1+stat2-sim > 0.0 ? sim/(stat1+stat2-sim) : 0.0); break; case GK_CSR_MIN: sim = stat1 = stat2 = 0.0; i1 = i2 = 0; while (i1 ind2[i2]) { stat2 += val2[i2]; i2++; } else { sim += gk_min(val1[i1],val2[i2]); stat1 += val1[i1]; stat2 += val2[i2]; i1++; i2++; } } sim = (stat1+stat2-sim > 0.0 ? sim/(stat1+stat2-sim) : 0.0); break; case GK_CSR_AMIN: sim = stat1 = stat2 = 0.0; i1 = i2 = 0; while (i1 ind2[i2]) { stat2 += val2[i2]; i2++; } else { sim += gk_min(val1[i1],val2[i2]); stat1 += val1[i1]; stat2 += val2[i2]; i1++; i2++; } } sim = (stat1 > 0.0 ? sim/stat1 : 0.0); break; default: gk_errexit(SIGERR, "Unknown similarity measure %d\n", simtype); return -1; } return sim; } /*************************************************************************/ /*! Finds the n most similar rows (neighbors) to the query using cosine similarity. \param mat the matrix itself \param nqterms is the number of columns in the query \param qind is the list of query columns \param qval is the list of correspodning query weights \param simtype is the type of similarity and is one of GK_CSR_COS, GK_CSR_JAC, GK_CSR_MIN, GK_CSR_AMIN \param nsim is the maximum number of requested most similar rows. If -1 is provided, then everything is returned unsorted. \param minsim is the minimum similarity of the requested most similar rows \param hits is the result set. This array should be at least of length nsim. \param i_marker is an array of size equal to the number of rows whose values are initialized to -1. If NULL is provided then this array is allocated and freed internally. \param i_cand is an array of size equal to the number of rows. If NULL is provided then this array is allocated and freed internally. \returns the number of identified most similar rows, which can be smaller than the requested number of nnbrs in those cases in which there are no sufficiently many neighbors. */ /**************************************************************************/ int gk_csr_GetSimilarRows(gk_csr_t *mat, int nqterms, int *qind, float *qval, int simtype, int nsim, float minsim, gk_fkv_t *hits, int *i_marker, gk_fkv_t *i_cand) { ssize_t i, ii, j, k; int nrows, ncols, ncand; ssize_t *colptr; int *colind, *marker; float *colval, *rnorms, mynorm, *rsums, mysum; gk_fkv_t *cand; if (nqterms == 0) return 0; nrows = mat->nrows; ncols = mat->ncols; colptr = mat->colptr; colind = mat->colind; colval = mat->colval; marker = (i_marker ? i_marker : gk_ismalloc(nrows, -1, "gk_csr_SimilarRows: marker")); cand = (i_cand ? i_cand : gk_fkvmalloc(nrows, "gk_csr_SimilarRows: cand")); switch (simtype) { case GK_CSR_COS: for (ncand=0, ii=0; iirnorms; mynorm = gk_fdot(nqterms, qval, 1, qval, 1); for (i=0; irsums; mysum = gk_fsum(nqterms, qval, 1); for (i=0; i= minsim) cand[j++] = cand[i]; } ncand = j; if (nsim == -1 || nsim >= ncand) { nsim = ncand; } else { nsim = gk_min(nsim, ncand); gk_dfkvkselect(ncand, nsim, cand); gk_fkvsortd(nsim, cand); } gk_fkvcopy(nsim, cand, hits); if (i_marker == NULL) gk_free((void **)&marker, LTERM); if (i_cand == NULL) gk_free((void **)&cand, LTERM); return nsim; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/util.c���������������������������������������0000644�0001751�0000144�00000006441�14552244506�023454� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file util.c \brief Various utility routines \date Started 4/12/2007 \author George \version\verbatim $Id: util.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim */ #include "GKlib.h" /************************************************************************* * This file randomly permutes the contents of an array. * flag == 0, don't initialize perm * flag == 1, set p[i] = i **************************************************************************/ void gk_RandomPermute(size_t n, int *p, int flag) { gk_idx_t i, u, v; int tmp; if (flag == 1) { for (i=0; i 1; i++, a = a>>1); return i-1; } /************************************************************************* * This function checks if the argument is a power of 2 **************************************************************************/ int gk_ispow2(int a) { return (a == (1<long_options must be an array of these structures, one for each long option. Terminate the array with an element containing all zeros. */ struct gk_option { char *name; /*!< This field is the name of the option. */ int has_arg; /*!< This field says whether the option takes an argument. It is an integer, and there are three legitimate values: no_argument, required_argument and optional_argument. */ int *flag; /*!< See the discussion on ::gk_option#val */ int val; /*!< These fields control how to report or act on the option when it occurs. If flag is a null pointer, then the val is a value which identifies this option. Often these values are chosen to uniquely identify particular long options. If flag is not a null pointer, it should be the address of an int variable which is the flag for this option. The value in val is the value to store in the flag to indicate that the option was seen. */ }; /* Names for the values of the `has_arg' field of `struct gk_option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 /* Function prototypes */ int gk_getopt(int, char **, char *); int gk_getopt_long(int, char **, char *, struct gk_option *, int *); int gk_getopt_long_only (int, char **, char *, struct gk_option *, int *); #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_struct.h����������������������������������0000644�0001751�0000144�00000022252�14552244506�024507� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file gk_struct.h \brief This file contains various datastructures used/provided by GKlib \date Started 3/27/2007 \author George \version\verbatim $Id: gk_struct.h 13005 2012-10-23 22:34:36Z karypis $ \endverbatim */ #ifndef _GK_STRUCT_H_ #define _GK_STRUCT_H_ /********************************************************************/ /*! Generator for gk_??KeyVal_t data structure */ /********************************************************************/ #define GK_MKKEYVALUE_T(NAME, KEYTYPE, VALTYPE) \ typedef struct {\ KEYTYPE key;\ VALTYPE val;\ } NAME;\ /* The actual KeyVal data structures */ GK_MKKEYVALUE_T(gk_ckv_t, char, ssize_t) GK_MKKEYVALUE_T(gk_ikv_t, int, ssize_t) GK_MKKEYVALUE_T(gk_i32kv_t, int32_t, ssize_t) GK_MKKEYVALUE_T(gk_i64kv_t, int64_t, ssize_t) GK_MKKEYVALUE_T(gk_zkv_t, ssize_t, ssize_t) GK_MKKEYVALUE_T(gk_fkv_t, float, ssize_t) GK_MKKEYVALUE_T(gk_dkv_t, double, ssize_t) GK_MKKEYVALUE_T(gk_skv_t, char *, ssize_t) GK_MKKEYVALUE_T(gk_idxkv_t, gk_idx_t, gk_idx_t) /********************************************************************/ /*! Generator for gk_?pq_t data structure */ /********************************************************************/ #define GK_MKPQUEUE_T(NAME, KVTYPE)\ typedef struct {\ gk_idx_t nnodes;\ gk_idx_t maxnodes;\ \ /* Heap version of the data structure */ \ KVTYPE *heap;\ gk_idx_t *locator;\ } NAME;\ GK_MKPQUEUE_T(gk_ipq_t, gk_ikv_t) GK_MKPQUEUE_T(gk_i32pq_t, gk_i32kv_t) GK_MKPQUEUE_T(gk_i64pq_t, gk_i64kv_t) GK_MKPQUEUE_T(gk_fpq_t, gk_fkv_t) GK_MKPQUEUE_T(gk_dpq_t, gk_dkv_t) GK_MKPQUEUE_T(gk_idxpq_t, gk_idxkv_t) #define GK_MKPQUEUE2_T(NAME, KTYPE, VTYPE)\ typedef struct {\ ssize_t nnodes;\ ssize_t maxnodes;\ \ /* Heap version of the data structure */ \ KTYPE *keys;\ VTYPE *vals;\ } NAME;\ /*------------------------------------------------------------- * The following data structure stores a sparse CSR format *-------------------------------------------------------------*/ typedef struct gk_csr_t { int32_t nrows, ncols; ssize_t *rowptr, *colptr; int32_t *rowind, *colind; int32_t *rowids, *colids; float *rowval, *colval; float *rnorms, *cnorms; float *rsums, *csums; float *rsizes, *csizes; float *rvols, *cvols; float *rwgts, *cwgts; } gk_csr_t; /*------------------------------------------------------------- * The following data structure stores a sparse graph *-------------------------------------------------------------*/ typedef struct gk_graph_t { int32_t nvtxs; /*!< The number of vertices in the graph */ ssize_t *xadj; /*!< The ptr-structure of the adjncy list */ int32_t *adjncy; /*!< The adjacency list of the graph */ int32_t *iadjwgt; /*!< The integer edge weights */ float *fadjwgt; /*!< The floating point edge weights */ int32_t *ivwgts; /*!< The integer vertex weights */ float *fvwgts; /*!< The floating point vertex weights */ int32_t *ivsizes; /*!< The integer vertex sizes */ float *fvsizes; /*!< The floating point vertex sizes */ int32_t *vlabels; /*!< The labels of the vertices */ } gk_graph_t; /*------------------------------------------------------------- * The following data structure stores stores a string as a * pair of its allocated buffer and the buffer itself. *-------------------------------------------------------------*/ typedef struct gk_str_t { size_t len; char *buf; } gk_str_t; /*------------------------------------------------------------- * The following data structure implements a string-2-int mapping * table used for parsing command-line options *-------------------------------------------------------------*/ typedef struct gk_StringMap_t { char *name; int id; } gk_StringMap_t; /*------------------------------------------------------------ * This structure implements a simple hash table *------------------------------------------------------------*/ typedef struct gk_HTable_t { int nelements; /* The overall size of the hash-table */ int htsize; /* The current size of the hash-table */ gk_ikv_t *harray; /* The actual hash-table */ } gk_HTable_t; /*------------------------------------------------------------ * This structure implements a gk_Tokens_t list returned by the * string tokenizer *------------------------------------------------------------*/ typedef struct gk_Tokens_t { int ntoks; /* The number of tokens in the input string */ char *strbuf; /* The memory that stores all the entries */ char **list; /* Pointers to the strbuf for each element */ } gk_Tokens_t; /*------------------------------------------------------------ * This structure implements storage for an atom in a pdb file *------------------------------------------------------------*/ typedef struct atom { int serial; char *name; char altLoc; char *resname; char chainid; int rserial; char icode; char element; double x; double y; double z; double opcy; double tmpt; } atom; /*------------------------------------------------------------ * This structure implements storage for a center of mass for * a single residue. *------------------------------------------------------------*/ typedef struct center_of_mass { char name; double x; double y; double z; } center_of_mass; /*------------------------------------------------------------ * This structure implements storage for a pdb protein *------------------------------------------------------------*/ typedef struct pdbf { int natoms; /* Number of atoms */ int nresidues; /* Number of residues based on coordinates */ int ncas; int nbbs; int corruption; char *resSeq; /* Residue sequence based on coordinates */ char **threeresSeq; /* three-letter residue sequence */ atom *atoms; atom **bbs; atom **cas; center_of_mass *cm; } pdbf; /************************************************************* * Localization Structures for converting characters to integers **************************************************************/ typedef struct gk_i2cc2i_t { int n; char *i2c; int *c2i; } gk_i2cc2i_t; /******************************************************************* *This structure implements storage of a protein sequence * *****************************************************************/ typedef struct gk_seq_t { int len; /*Number of Residues */ int *sequence; /* Stores the sequence*/ int **pssm; /* Stores the pssm matrix */ int **psfm; /* Stores the psfm matrix */ char *name; /* Stores the name of the sequence */ int nsymbols; } gk_seq_t; /*************************************************************************/ /*! The following data structure stores information about a memory allocation operation that can either be served from gk_mcore_t or by a gk_malloc if not sufficient workspace memory is available. */ /*************************************************************************/ typedef struct gk_mop_t { int type; ssize_t nbytes; void *ptr; } gk_mop_t; /*************************************************************************/ /*! The following structure stores information used by Metis */ /*************************************************************************/ typedef struct gk_mcore_t { /* Workspace information */ size_t coresize; /*!< The amount of core memory that has been allocated */ size_t corecpos; /*!< Index of the first free location in core */ void *core; /*!< Pointer to the core itself */ /* These are for implementing a stack-based allocation scheme using both core and also dynamically allocated memory */ size_t nmops; /*!< The number of maop_t entries that have been allocated */ size_t cmop; /*!< Index of the first free location in maops */ gk_mop_t *mops; /*!< The array recording the maop_t operations */ /* These are for keeping various statistics for wspacemalloc */ size_t num_callocs; /*!< The number of core mallocs */ size_t num_hallocs; /*!< The number of heap mallocs */ size_t size_callocs; /*!< The total # of bytes in core mallocs */ size_t size_hallocs; /*!< The total # of bytes in heap mallocs */ size_t cur_callocs; /*!< The current # of bytes in core mallocs */ size_t cur_hallocs; /*!< The current # of bytes in heap mallocs */ size_t max_callocs; /*!< The maximum # of bytes in core mallocs at any given time */ size_t max_hallocs; /*!< The maximum # of bytes in heap mallocs at any given time */ } gk_mcore_t; #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/pqueue.c�������������������������������������0000644�0001751�0000144�00000003254�14552244506�024002� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file pqueue.c \brief This file implements various max-priority queues. The priority queues are generated using the GK_MKPQUEUE macro. \date Started 3/27/2007 \author George \version\verbatim $Id: pqueue.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim */ #include "GKlib.h" /*************************************************************************/ /*! Create the various max priority queues */ /*************************************************************************/ #define key_gt(a, b) ((a) > (b)) GK_MKPQUEUE(gk_ipq, gk_ipq_t, gk_ikv_t, int, gk_idx_t, gk_ikvmalloc, INT_MAX, key_gt) GK_MKPQUEUE(gk_i32pq, gk_i32pq_t, gk_i32kv_t, int32_t, gk_idx_t, gk_i32kvmalloc, INT32_MAX, key_gt) GK_MKPQUEUE(gk_i64pq, gk_i64pq_t, gk_i64kv_t, int64_t, gk_idx_t, gk_i64kvmalloc, INT64_MAX, key_gt) GK_MKPQUEUE(gk_fpq, gk_fpq_t, gk_fkv_t, float, gk_idx_t, gk_fkvmalloc, FLT_MAX, key_gt) GK_MKPQUEUE(gk_dpq, gk_dpq_t, gk_dkv_t, double, gk_idx_t, gk_dkvmalloc, DBL_MAX, key_gt) GK_MKPQUEUE(gk_idxpq, gk_idxpq_t, gk_idxkv_t, gk_idx_t, gk_idx_t, gk_idxkvmalloc, GK_IDX_MAX, key_gt) #undef key_gt ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gkregex.c������������������������������������0000644�0001751�0000144�00001140662�14552244506�024140� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* Extended regular expression matching and search library. Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ /* this is for removing a compiler warning */ void gkfooo(void) { return; } #ifdef USE_GKREGEX #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef _LIBC /* We have to keep the namespace clean. */ # define regfree(preg) __regfree (preg) # define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) # define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) # define regerror(errcode, preg, errbuf, errbuf_size) \ __regerror(errcode, preg, errbuf, errbuf_size) # define re_set_registers(bu, re, nu, st, en) \ __re_set_registers (bu, re, nu, st, en) # define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) # define re_match(bufp, string, size, pos, regs) \ __re_match (bufp, string, size, pos, regs) # define re_search(bufp, string, size, startpos, range, regs) \ __re_search (bufp, string, size, startpos, range, regs) # define re_compile_pattern(pattern, length, bufp) \ __re_compile_pattern (pattern, length, bufp) # define re_set_syntax(syntax) __re_set_syntax (syntax) # define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) # define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) # include "../locale/localeinfo.h" #endif #include "GKlib.h" /******************************************************************************/ /******************************************************************************/ /******************************************************************************/ /* GKINCLUDE #include "regex_internal.h" */ /******************************************************************************/ /******************************************************************************/ /******************************************************************************/ /* Extended regular expression matching and search library. Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef _REGEX_INTERNAL_H #define _REGEX_INTERNAL_H 1 #include #include #include #include #include #if defined(__MINGW32_VERSION) || defined(_MSC_VER) #define strcasecmp stricmp #endif #if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC # include #endif #if defined HAVE_LOCALE_H || defined _LIBC # include #endif #if defined HAVE_WCHAR_H || defined _LIBC # include #endif /* HAVE_WCHAR_H || _LIBC */ #if defined HAVE_WCTYPE_H || defined _LIBC # include #endif /* HAVE_WCTYPE_H || _LIBC */ #if defined HAVE_STDBOOL_H || defined _LIBC # include #else typedef enum { false, true } bool; #endif /* HAVE_STDBOOL_H || _LIBC */ #if defined HAVE_STDINT_H || defined _LIBC # include #endif /* HAVE_STDINT_H || _LIBC */ #if defined _LIBC # include #else # define __libc_lock_define(CLASS,NAME) # define __libc_lock_init(NAME) do { } while (0) # define __libc_lock_lock(NAME) do { } while (0) # define __libc_lock_unlock(NAME) do { } while (0) #endif /* In case that the system doesn't have isblank(). */ #if !defined _LIBC && !defined HAVE_ISBLANK && !defined isblank # define isblank(ch) ((ch) == ' ' || (ch) == '\t') #endif #ifdef _LIBC # ifndef _RE_DEFINE_LOCALE_FUNCTIONS # define _RE_DEFINE_LOCALE_FUNCTIONS 1 # include # include # include # endif #endif /* This is for other GNU distributions with internationalized messages. */ #if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC # include # ifdef _LIBC # undef gettext # define gettext(msgid) \ INTUSE(__dcgettext) (_libc_intl_domainname, msgid, LC_MESSAGES) # endif #else # define gettext(msgid) (msgid) #endif #ifndef gettext_noop /* This define is so xgettext can find the internationalizable strings. */ # define gettext_noop(String) String #endif /* For loser systems without the definition. */ #ifndef SIZE_MAX # define SIZE_MAX ((size_t) -1) #endif #if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) || _LIBC # define RE_ENABLE_I18N #endif #if __GNUC__ >= 3 # define BE(expr, val) __builtin_expect (expr, val) #else # define BE(expr, val) (expr) # define inline #endif /* Number of single byte character. */ #define SBC_MAX 256 #define COLL_ELEM_LEN_MAX 8 /* The character which represents newline. */ #define NEWLINE_CHAR '\n' #define WIDE_NEWLINE_CHAR L'\n' /* Rename to standard API for using out of glibc. */ #ifndef _LIBC # define __wctype wctype # define __iswctype iswctype # define __btowc btowc # define __mempcpy mempcpy # define __wcrtomb wcrtomb # define __regfree regfree # define attribute_hidden #endif /* not _LIBC */ #ifdef __GNUC__ # define __attribute(arg) __attribute__ (arg) #else # define __attribute(arg) #endif extern const char __re_error_msgid[] attribute_hidden; extern const size_t __re_error_msgid_idx[] attribute_hidden; /* An integer used to represent a set of bits. It must be unsigned, and must be at least as wide as unsigned int. */ typedef unsigned long int bitset_word_t; /* All bits set in a bitset_word_t. */ #define BITSET_WORD_MAX ULONG_MAX /* Number of bits in a bitset_word_t. */ #define BITSET_WORD_BITS (sizeof (bitset_word_t) * CHAR_BIT) /* Number of bitset_word_t in a bit_set. */ #define BITSET_WORDS (SBC_MAX / BITSET_WORD_BITS) typedef bitset_word_t bitset_t[BITSET_WORDS]; typedef bitset_word_t *re_bitset_ptr_t; typedef const bitset_word_t *re_const_bitset_ptr_t; #define bitset_set(set,i) \ (set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS) #define bitset_clear(set,i) \ (set[i / BITSET_WORD_BITS] &= ~((bitset_word_t) 1 << i % BITSET_WORD_BITS)) #define bitset_contain(set,i) \ (set[i / BITSET_WORD_BITS] & ((bitset_word_t) 1 << i % BITSET_WORD_BITS)) #define bitset_empty(set) memset (set, '\0', sizeof (bitset_t)) #define bitset_set_all(set) memset (set, '\xff', sizeof (bitset_t)) #define bitset_copy(dest,src) memcpy (dest, src, sizeof (bitset_t)) #define PREV_WORD_CONSTRAINT 0x0001 #define PREV_NOTWORD_CONSTRAINT 0x0002 #define NEXT_WORD_CONSTRAINT 0x0004 #define NEXT_NOTWORD_CONSTRAINT 0x0008 #define PREV_NEWLINE_CONSTRAINT 0x0010 #define NEXT_NEWLINE_CONSTRAINT 0x0020 #define PREV_BEGBUF_CONSTRAINT 0x0040 #define NEXT_ENDBUF_CONSTRAINT 0x0080 #define WORD_DELIM_CONSTRAINT 0x0100 #define NOT_WORD_DELIM_CONSTRAINT 0x0200 typedef enum { INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, LINE_FIRST = PREV_NEWLINE_CONSTRAINT, LINE_LAST = NEXT_NEWLINE_CONSTRAINT, BUF_FIRST = PREV_BEGBUF_CONSTRAINT, BUF_LAST = NEXT_ENDBUF_CONSTRAINT, WORD_DELIM = WORD_DELIM_CONSTRAINT, NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT } re_context_type; typedef struct { int alloc; int nelem; int *elems; } re_node_set; typedef enum { NON_TYPE = 0, /* Node type, These are used by token, node, tree. */ CHARACTER = 1, END_OF_RE = 2, SIMPLE_BRACKET = 3, OP_BACK_REF = 4, OP_PERIOD = 5, #ifdef RE_ENABLE_I18N COMPLEX_BRACKET = 6, OP_UTF8_PERIOD = 7, #endif /* RE_ENABLE_I18N */ /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used when the debugger shows values of this enum type. */ #define EPSILON_BIT 8 OP_OPEN_SUBEXP = EPSILON_BIT | 0, OP_CLOSE_SUBEXP = EPSILON_BIT | 1, OP_ALT = EPSILON_BIT | 2, OP_DUP_ASTERISK = EPSILON_BIT | 3, ANCHOR = EPSILON_BIT | 4, /* Tree type, these are used only by tree. */ CONCAT = 16, SUBEXP = 17, /* Token type, these are used only by token. */ OP_DUP_PLUS = 18, OP_DUP_QUESTION, OP_OPEN_BRACKET, OP_CLOSE_BRACKET, OP_CHARSET_RANGE, OP_OPEN_DUP_NUM, OP_CLOSE_DUP_NUM, OP_NON_MATCH_LIST, OP_OPEN_COLL_ELEM, OP_CLOSE_COLL_ELEM, OP_OPEN_EQUIV_CLASS, OP_CLOSE_EQUIV_CLASS, OP_OPEN_CHAR_CLASS, OP_CLOSE_CHAR_CLASS, OP_WORD, OP_NOTWORD, OP_SPACE, OP_NOTSPACE, BACK_SLASH } re_token_type_t; #ifdef RE_ENABLE_I18N typedef struct { /* Multibyte characters. */ wchar_t *mbchars; /* Collating symbols. */ # ifdef _LIBC int32_t *coll_syms; # endif /* Equivalence classes. */ # ifdef _LIBC int32_t *equiv_classes; # endif /* Range expressions. */ # ifdef _LIBC uint32_t *range_starts; uint32_t *range_ends; # else /* not _LIBC */ wchar_t *range_starts; wchar_t *range_ends; # endif /* not _LIBC */ /* Character classes. */ wctype_t *char_classes; /* If this character set is the non-matching list. */ unsigned int non_match : 1; /* # of multibyte characters. */ int nmbchars; /* # of collating symbols. */ int ncoll_syms; /* # of equivalence classes. */ int nequiv_classes; /* # of range expressions. */ int nranges; /* # of character classes. */ int nchar_classes; } re_charset_t; #endif /* RE_ENABLE_I18N */ typedef struct { union { unsigned char c; /* for CHARACTER */ re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */ #ifdef RE_ENABLE_I18N re_charset_t *mbcset; /* for COMPLEX_BRACKET */ #endif /* RE_ENABLE_I18N */ int idx; /* for BACK_REF */ re_context_type ctx_type; /* for ANCHOR */ } opr; #if __GNUC__ >= 2 re_token_type_t type : 8; #else re_token_type_t type; #endif unsigned int constraint : 10; /* context constraint */ unsigned int duplicated : 1; unsigned int opt_subexp : 1; #ifdef RE_ENABLE_I18N unsigned int accept_mb : 1; /* These 2 bits can be moved into the union if needed (e.g. if running out of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */ unsigned int mb_partial : 1; #endif unsigned int word_char : 1; } re_token_t; #define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT) struct re_string_t { /* Indicate the raw buffer which is the original string passed as an argument of regexec(), re_search(), etc.. */ const unsigned char *raw_mbs; /* Store the multibyte string. In case of "case insensitive mode" like REG_ICASE, upper cases of the string are stored, otherwise MBS points the same address that RAW_MBS points. */ unsigned char *mbs; #ifdef RE_ENABLE_I18N /* Store the wide character string which is corresponding to MBS. */ wint_t *wcs; int *offsets; mbstate_t cur_state; #endif /* Index in RAW_MBS. Each character mbs[i] corresponds to raw_mbs[raw_mbs_idx + i]. */ int raw_mbs_idx; /* The length of the valid characters in the buffers. */ int valid_len; /* The corresponding number of bytes in raw_mbs array. */ int valid_raw_len; /* The length of the buffers MBS and WCS. */ int bufs_len; /* The index in MBS, which is updated by re_string_fetch_byte. */ int cur_idx; /* length of RAW_MBS array. */ int raw_len; /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */ int len; /* End of the buffer may be shorter than its length in the cases such as re_match_2, re_search_2. Then, we use STOP for end of the buffer instead of LEN. */ int raw_stop; /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */ int stop; /* The context of mbs[0]. We store the context independently, since the context of mbs[0] may be different from raw_mbs[0], which is the beginning of the input string. */ unsigned int tip_context; /* The translation passed as a part of an argument of re_compile_pattern. */ RE_TRANSLATE_TYPE trans; /* Copy of re_dfa_t's word_char. */ re_const_bitset_ptr_t word_char; /* 1 if REG_ICASE. */ unsigned char icase; unsigned char is_utf8; unsigned char map_notascii; unsigned char mbs_allocated; unsigned char offsets_needed; unsigned char newline_anchor; unsigned char word_ops_used; int mb_cur_max; }; typedef struct re_string_t re_string_t; struct re_dfa_t; typedef struct re_dfa_t re_dfa_t; #ifndef _LIBC # ifdef __i386__ # define internal_function __attribute ((regparm (3), stdcall)) # else # define internal_function # endif #endif static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr, int new_buf_len) internal_function; #ifdef RE_ENABLE_I18N static void build_wcs_buffer (re_string_t *pstr) internal_function; static int build_wcs_upper_buffer (re_string_t *pstr) internal_function; #endif /* RE_ENABLE_I18N */ static void build_upper_buffer (re_string_t *pstr) internal_function; static void re_string_translate_buffer (re_string_t *pstr) internal_function; static unsigned int re_string_context_at (const re_string_t *input, int idx, int eflags) internal_function __attribute ((pure)); #define re_string_peek_byte(pstr, offset) \ ((pstr)->mbs[(pstr)->cur_idx + offset]) #define re_string_fetch_byte(pstr) \ ((pstr)->mbs[(pstr)->cur_idx++]) #define re_string_first_byte(pstr, idx) \ ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF) #define re_string_is_single_byte_char(pstr, idx) \ ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \ || (pstr)->wcs[(idx) + 1] != WEOF)) #define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx) #define re_string_cur_idx(pstr) ((pstr)->cur_idx) #define re_string_get_buffer(pstr) ((pstr)->mbs) #define re_string_length(pstr) ((pstr)->len) #define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx]) #define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx)) #define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx)) #ifdef __GNUC__ # define alloca(size) __builtin_alloca (size) # define HAVE_ALLOCA 1 #elif defined(_MSC_VER) # include # define alloca _alloca # define HAVE_ALLOCA 1 #else # error No alloca() #endif #ifndef _LIBC # if HAVE_ALLOCA /* The OS usually guarantees only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely allocate anything larger than 4096 bytes. Also care for the possibility of a few compiler-allocated temporary stack slots. */ # define __libc_use_alloca(n) ((n) < 4032) # else /* alloca is implemented with malloc, so just use malloc. */ # define __libc_use_alloca(n) 0 # endif #endif #define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) #define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) #define re_free(p) free (p) struct bin_tree_t { struct bin_tree_t *parent; struct bin_tree_t *left; struct bin_tree_t *right; struct bin_tree_t *first; struct bin_tree_t *next; re_token_t token; /* `node_idx' is the index in dfa->nodes, if `type' == 0. Otherwise `type' indicate the type of this node. */ int node_idx; }; typedef struct bin_tree_t bin_tree_t; #define BIN_TREE_STORAGE_SIZE \ ((1024 - sizeof (void *)) / sizeof (bin_tree_t)) struct bin_tree_storage_t { struct bin_tree_storage_t *next; bin_tree_t data[BIN_TREE_STORAGE_SIZE]; }; typedef struct bin_tree_storage_t bin_tree_storage_t; #define CONTEXT_WORD 1 #define CONTEXT_NEWLINE (CONTEXT_WORD << 1) #define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1) #define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1) #define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD) #define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE) #define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF) #define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF) #define IS_ORDINARY_CONTEXT(c) ((c) == 0) #define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_') #define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR) #define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_') #define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR) #define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \ ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\ || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context))) #define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \ ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \ || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context))) struct re_dfastate_t { unsigned int hash; re_node_set nodes; re_node_set non_eps_nodes; re_node_set inveclosure; re_node_set *entrance_nodes; struct re_dfastate_t **trtable, **word_trtable; unsigned int context : 4; unsigned int halt : 1; /* If this state can accept `multi byte'. Note that we refer to multibyte characters, and multi character collating elements as `multi byte'. */ unsigned int accept_mb : 1; /* If this state has backreference node(s). */ unsigned int has_backref : 1; unsigned int has_constraint : 1; }; typedef struct re_dfastate_t re_dfastate_t; struct re_state_table_entry { int num; int alloc; re_dfastate_t **array; }; /* Array type used in re_sub_match_last_t and re_sub_match_top_t. */ typedef struct { int next_idx; int alloc; re_dfastate_t **array; } state_array_t; /* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */ typedef struct { int node; int str_idx; /* The position NODE match at. */ state_array_t path; } re_sub_match_last_t; /* Store information about the node NODE whose type is OP_OPEN_SUBEXP. And information about the node, whose type is OP_CLOSE_SUBEXP, corresponding to NODE is stored in LASTS. */ typedef struct { int str_idx; int node; state_array_t *path; int alasts; /* Allocation size of LASTS. */ int nlasts; /* The number of LASTS. */ re_sub_match_last_t **lasts; } re_sub_match_top_t; struct re_backref_cache_entry { int node; int str_idx; int subexp_from; int subexp_to; char more; char unused; unsigned short int eps_reachable_subexps_map; }; typedef struct { /* The string object corresponding to the input string. */ re_string_t input; #if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) const re_dfa_t *const dfa; #else const re_dfa_t *dfa; #endif /* EFLAGS of the argument of regexec. */ int eflags; /* Where the matching ends. */ int match_last; int last_node; /* The state log used by the matcher. */ re_dfastate_t **state_log; int state_log_top; /* Back reference cache. */ int nbkref_ents; int abkref_ents; struct re_backref_cache_entry *bkref_ents; int max_mb_elem_len; int nsub_tops; int asub_tops; re_sub_match_top_t **sub_tops; } re_match_context_t; typedef struct { re_dfastate_t **sifted_states; re_dfastate_t **limited_states; int last_node; int last_str_idx; re_node_set limits; } re_sift_context_t; struct re_fail_stack_ent_t { int idx; int node; regmatch_t *regs; re_node_set eps_via_nodes; }; struct re_fail_stack_t { int num; int alloc; struct re_fail_stack_ent_t *stack; }; struct re_dfa_t { re_token_t *nodes; size_t nodes_alloc; size_t nodes_len; int *nexts; int *org_indices; re_node_set *edests; re_node_set *eclosures; re_node_set *inveclosures; struct re_state_table_entry *state_table; re_dfastate_t *init_state; re_dfastate_t *init_state_word; re_dfastate_t *init_state_nl; re_dfastate_t *init_state_begbuf; bin_tree_t *str_tree; bin_tree_storage_t *str_tree_storage; re_bitset_ptr_t sb_char; int str_tree_storage_idx; /* number of subexpressions `re_nsub' is in regex_t. */ unsigned int state_hash_mask; int init_node; int nbackref; /* The number of backreference in this dfa. */ /* Bitmap expressing which backreference is used. */ bitset_word_t used_bkref_map; bitset_word_t completed_bkref_map; unsigned int has_plural_match : 1; /* If this dfa has "multibyte node", which is a backreference or a node which can accept multibyte character or multi character collating element. */ unsigned int has_mb_node : 1; unsigned int is_utf8 : 1; unsigned int map_notascii : 1; unsigned int word_ops_used : 1; int mb_cur_max; bitset_t word_char; reg_syntax_t syntax; int *subexp_map; #ifdef DEBUG char* re_str; #endif __libc_lock_define (, lock) }; #define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) #define re_node_set_remove(set,id) \ (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) #define re_node_set_empty(p) ((p)->nelem = 0) #define re_node_set_free(set) re_free ((set)->elems) typedef enum { SB_CHAR, MB_CHAR, EQUIV_CLASS, COLL_SYM, CHAR_CLASS } bracket_elem_type; typedef struct { bracket_elem_type type; union { unsigned char ch; unsigned char *name; wchar_t wch; } opr; } bracket_elem_t; /* Inline functions for bitset operation. */ static inline void bitset_not (bitset_t set) { int bitset_i; for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) set[bitset_i] = ~set[bitset_i]; } static inline void bitset_merge (bitset_t dest, const bitset_t src) { int bitset_i; for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) dest[bitset_i] |= src[bitset_i]; } static inline void bitset_mask (bitset_t dest, const bitset_t src) { int bitset_i; for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) dest[bitset_i] &= src[bitset_i]; } #ifdef RE_ENABLE_I18N /* Inline functions for re_string. */ static inline int internal_function __attribute ((pure)) re_string_char_size_at (const re_string_t *pstr, int idx) { int byte_idx; if (pstr->mb_cur_max == 1) return 1; for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx) if (pstr->wcs[idx + byte_idx] != WEOF) break; return byte_idx; } static inline wint_t internal_function __attribute ((pure)) re_string_wchar_at (const re_string_t *pstr, int idx) { if (pstr->mb_cur_max == 1) return (wint_t) pstr->mbs[idx]; return (wint_t) pstr->wcs[idx]; } static int internal_function __attribute ((pure)) re_string_elem_size_at (const re_string_t *pstr, int idx) { # ifdef _LIBC const unsigned char *p, *extra; const int32_t *table, *indirect; int32_t tmp; # include uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules != 0) { table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); p = pstr->mbs + idx; tmp = findidx (&p); return p - pstr->mbs - idx; } else # endif /* _LIBC */ return 1; } #endif /* RE_ENABLE_I18N */ #endif /* _REGEX_INTERNAL_H */ /******************************************************************************/ /******************************************************************************/ /******************************************************************************/ /* GKINCLUDE #include "regex_internal.c" */ /******************************************************************************/ /******************************************************************************/ /******************************************************************************/ /* Extended regular expression matching and search library. Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ static void re_string_construct_common (const char *str, int len, re_string_t *pstr, RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) internal_function; static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, unsigned int hash) internal_function; static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, unsigned int context, unsigned int hash) internal_function; /* Functions for string operation. */ /* This function allocate the buffers. It is necessary to call re_string_reconstruct before using the object. */ static reg_errcode_t internal_function re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len, RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) { reg_errcode_t ret; int init_buf_len; /* Ensure at least one character fits into the buffers. */ if (init_len < dfa->mb_cur_max) init_len = dfa->mb_cur_max; init_buf_len = (len + 1 < init_len) ? len + 1: init_len; re_string_construct_common (str, len, pstr, trans, icase, dfa); ret = re_string_realloc_buffers (pstr, init_buf_len); if (BE (ret != REG_NOERROR, 0)) return ret; pstr->word_char = dfa->word_char; pstr->word_ops_used = dfa->word_ops_used; pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len; pstr->valid_raw_len = pstr->valid_len; return REG_NOERROR; } /* This function allocate the buffers, and initialize them. */ static reg_errcode_t internal_function re_string_construct (re_string_t *pstr, const char *str, int len, RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) { reg_errcode_t ret; memset (pstr, '\0', sizeof (re_string_t)); re_string_construct_common (str, len, pstr, trans, icase, dfa); if (len > 0) { ret = re_string_realloc_buffers (pstr, len + 1); if (BE (ret != REG_NOERROR, 0)) return ret; } pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; if (icase) { #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { while (1) { ret = build_wcs_upper_buffer (pstr); if (BE (ret != REG_NOERROR, 0)) return ret; if (pstr->valid_raw_len >= len) break; if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max) break; ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); if (BE (ret != REG_NOERROR, 0)) return ret; } } else #endif /* RE_ENABLE_I18N */ build_upper_buffer (pstr); } else { #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) build_wcs_buffer (pstr); else #endif /* RE_ENABLE_I18N */ { if (trans != NULL) re_string_translate_buffer (pstr); else { pstr->valid_len = pstr->bufs_len; pstr->valid_raw_len = pstr->bufs_len; } } } return REG_NOERROR; } /* Helper functions for re_string_allocate, and re_string_construct. */ static reg_errcode_t internal_function re_string_realloc_buffers (re_string_t *pstr, int new_buf_len) { #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { wint_t *new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len); if (BE (new_wcs == NULL, 0)) return REG_ESPACE; pstr->wcs = new_wcs; if (pstr->offsets != NULL) { int *new_offsets = re_realloc (pstr->offsets, int, new_buf_len); if (BE (new_offsets == NULL, 0)) return REG_ESPACE; pstr->offsets = new_offsets; } } #endif /* RE_ENABLE_I18N */ if (pstr->mbs_allocated) { unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char, new_buf_len); if (BE (new_mbs == NULL, 0)) return REG_ESPACE; pstr->mbs = new_mbs; } pstr->bufs_len = new_buf_len; return REG_NOERROR; } static void internal_function re_string_construct_common (const char *str, int len, re_string_t *pstr, RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) { pstr->raw_mbs = (const unsigned char *) str; pstr->len = len; pstr->raw_len = len; pstr->trans = trans; pstr->icase = icase ? 1 : 0; pstr->mbs_allocated = (trans != NULL || icase); pstr->mb_cur_max = dfa->mb_cur_max; pstr->is_utf8 = dfa->is_utf8; pstr->map_notascii = dfa->map_notascii; pstr->stop = pstr->len; pstr->raw_stop = pstr->stop; } #ifdef RE_ENABLE_I18N /* Build wide character buffer PSTR->WCS. If the byte sequence of the string are: (0), (1), (0), (1), Then wide character buffer will be: , WEOF , , WEOF , We use WEOF for padding, they indicate that the position isn't a first byte of a multibyte character. Note that this function assumes PSTR->VALID_LEN elements are already built and starts from PSTR->VALID_LEN. */ static void internal_function build_wcs_buffer (re_string_t *pstr) { #ifdef _LIBC unsigned char buf[MB_LEN_MAX]; assert (MB_LEN_MAX >= pstr->mb_cur_max); #else unsigned char buf[64]; #endif mbstate_t prev_st; int byte_idx, end_idx, remain_len; size_t mbclen; /* Build the buffers from pstr->valid_len to either pstr->len or pstr->bufs_len. */ end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; for (byte_idx = pstr->valid_len; byte_idx < end_idx;) { wchar_t wc; const char *p; remain_len = end_idx - byte_idx; prev_st = pstr->cur_state; /* Apply the translation if we need. */ if (BE (pstr->trans != NULL, 0)) { int i, ch; for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) { ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i]; buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch]; } p = (const char *) buf; } else p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx; mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state); if (BE (mbclen == (size_t) -2, 0)) { /* The buffer doesn't have enough space, finish to build. */ pstr->cur_state = prev_st; break; } else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0)) { /* We treat these cases as a singlebyte character. */ mbclen = 1; wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; if (BE (pstr->trans != NULL, 0)) wc = pstr->trans[wc]; pstr->cur_state = prev_st; } /* Write wide character and padding. */ pstr->wcs[byte_idx++] = wc; /* Write paddings. */ for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) pstr->wcs[byte_idx++] = WEOF; } pstr->valid_len = byte_idx; pstr->valid_raw_len = byte_idx; } /* Build wide character buffer PSTR->WCS like build_wcs_buffer, but for REG_ICASE. */ static reg_errcode_t internal_function build_wcs_upper_buffer (re_string_t *pstr) { mbstate_t prev_st; int src_idx, byte_idx, end_idx, remain_len; size_t mbclen; #ifdef _LIBC char buf[MB_LEN_MAX]; assert (MB_LEN_MAX >= pstr->mb_cur_max); #else char buf[64]; #endif byte_idx = pstr->valid_len; end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; /* The following optimization assumes that ASCII characters can be mapped to wide characters with a simple cast. */ if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed) { while (byte_idx < end_idx) { wchar_t wc; if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]) && mbsinit (&pstr->cur_state)) { /* In case of a singlebyte character. */ pstr->mbs[byte_idx] = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]); /* The next step uses the assumption that wchar_t is encoded ASCII-safe: all ASCII values can be converted like this. */ pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx]; ++byte_idx; continue; } remain_len = end_idx - byte_idx; prev_st = pstr->cur_state; mbclen = mbrtowc (&wc, ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx), remain_len, &pstr->cur_state); if (BE (mbclen + 2 > 2, 1)) { wchar_t wcu = wc; if (iswlower (wc)) { size_t mbcdlen; wcu = towupper (wc); mbcdlen = wcrtomb (buf, wcu, &prev_st); if (BE (mbclen == mbcdlen, 1)) memcpy (pstr->mbs + byte_idx, buf, mbclen); else { src_idx = byte_idx; goto offsets_needed; } } else memcpy (pstr->mbs + byte_idx, pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen); pstr->wcs[byte_idx++] = wcu; /* Write paddings. */ for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) pstr->wcs[byte_idx++] = WEOF; } else if (mbclen == (size_t) -1 || mbclen == 0) { /* It is an invalid character or '\0'. Just use the byte. */ int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; pstr->mbs[byte_idx] = ch; /* And also cast it to wide char. */ pstr->wcs[byte_idx++] = (wchar_t) ch; if (BE (mbclen == (size_t) -1, 0)) pstr->cur_state = prev_st; } else { /* The buffer doesn't have enough space, finish to build. */ pstr->cur_state = prev_st; break; } } pstr->valid_len = byte_idx; pstr->valid_raw_len = byte_idx; return REG_NOERROR; } else for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;) { wchar_t wc; const char *p; offsets_needed: remain_len = end_idx - byte_idx; prev_st = pstr->cur_state; if (BE (pstr->trans != NULL, 0)) { int i, ch; for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) { ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i]; buf[i] = pstr->trans[ch]; } p = (const char *) buf; } else p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx; mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state); if (BE (mbclen + 2 > 2, 1)) { wchar_t wcu = wc; if (iswlower (wc)) { size_t mbcdlen; wcu = towupper (wc); mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st); if (BE (mbclen == mbcdlen, 1)) memcpy (pstr->mbs + byte_idx, buf, mbclen); else if (mbcdlen != (size_t) -1) { size_t i; if (byte_idx + mbcdlen > pstr->bufs_len) { pstr->cur_state = prev_st; break; } if (pstr->offsets == NULL) { pstr->offsets = re_malloc (int, pstr->bufs_len); if (pstr->offsets == NULL) return REG_ESPACE; } if (!pstr->offsets_needed) { for (i = 0; i < (size_t) byte_idx; ++i) pstr->offsets[i] = i; pstr->offsets_needed = 1; } memcpy (pstr->mbs + byte_idx, buf, mbcdlen); pstr->wcs[byte_idx] = wcu; pstr->offsets[byte_idx] = src_idx; for (i = 1; i < mbcdlen; ++i) { pstr->offsets[byte_idx + i] = src_idx + (i < mbclen ? i : mbclen - 1); pstr->wcs[byte_idx + i] = WEOF; } pstr->len += mbcdlen - mbclen; if (pstr->raw_stop > src_idx) pstr->stop += mbcdlen - mbclen; end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; byte_idx += mbcdlen; src_idx += mbclen; continue; } else memcpy (pstr->mbs + byte_idx, p, mbclen); } else memcpy (pstr->mbs + byte_idx, p, mbclen); if (BE (pstr->offsets_needed != 0, 0)) { size_t i; for (i = 0; i < mbclen; ++i) pstr->offsets[byte_idx + i] = src_idx + i; } src_idx += mbclen; pstr->wcs[byte_idx++] = wcu; /* Write paddings. */ for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) pstr->wcs[byte_idx++] = WEOF; } else if (mbclen == (size_t) -1 || mbclen == 0) { /* It is an invalid character or '\0'. Just use the byte. */ int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx]; if (BE (pstr->trans != NULL, 0)) ch = pstr->trans [ch]; pstr->mbs[byte_idx] = ch; if (BE (pstr->offsets_needed != 0, 0)) pstr->offsets[byte_idx] = src_idx; ++src_idx; /* And also cast it to wide char. */ pstr->wcs[byte_idx++] = (wchar_t) ch; if (BE (mbclen == (size_t) -1, 0)) pstr->cur_state = prev_st; } else { /* The buffer doesn't have enough space, finish to build. */ pstr->cur_state = prev_st; break; } } pstr->valid_len = byte_idx; pstr->valid_raw_len = src_idx; return REG_NOERROR; } /* Skip characters until the index becomes greater than NEW_RAW_IDX. Return the index. */ static int internal_function re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc) { mbstate_t prev_st; int rawbuf_idx; size_t mbclen; wchar_t wc = WEOF; /* Skip the characters which are not necessary to check. */ for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len; rawbuf_idx < new_raw_idx;) { int remain_len; remain_len = pstr->len - rawbuf_idx; prev_st = pstr->cur_state; mbclen = mbrtowc (&wc, (const char *) pstr->raw_mbs + rawbuf_idx, remain_len, &pstr->cur_state); if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0)) { /* We treat these cases as a single byte character. */ if (mbclen == 0 || remain_len == 0) wc = L'\0'; else wc = *(unsigned char *) (pstr->raw_mbs + rawbuf_idx); mbclen = 1; pstr->cur_state = prev_st; } /* Then proceed the next character. */ rawbuf_idx += mbclen; } *last_wc = (wint_t) wc; return rawbuf_idx; } #endif /* RE_ENABLE_I18N */ /* Build the buffer PSTR->MBS, and apply the translation if we need. This function is used in case of REG_ICASE. */ static void internal_function build_upper_buffer (re_string_t *pstr) { int char_idx, end_idx; end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx) { int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx]; if (BE (pstr->trans != NULL, 0)) ch = pstr->trans[ch]; if (islower (ch)) pstr->mbs[char_idx] = toupper (ch); else pstr->mbs[char_idx] = ch; } pstr->valid_len = char_idx; pstr->valid_raw_len = char_idx; } /* Apply TRANS to the buffer in PSTR. */ static void internal_function re_string_translate_buffer (re_string_t *pstr) { int buf_idx, end_idx; end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx) { int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx]; pstr->mbs[buf_idx] = pstr->trans[ch]; } pstr->valid_len = buf_idx; pstr->valid_raw_len = buf_idx; } /* This function re-construct the buffers. Concretely, convert to wide character in case of pstr->mb_cur_max > 1, convert to upper case in case of REG_ICASE, apply translation. */ static reg_errcode_t internal_function re_string_reconstruct (re_string_t *pstr, int idx, int eflags) { int offset = idx - pstr->raw_mbs_idx; if (BE (offset < 0, 0)) { /* Reset buffer. */ #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); #endif /* RE_ENABLE_I18N */ pstr->len = pstr->raw_len; pstr->stop = pstr->raw_stop; pstr->valid_len = 0; pstr->raw_mbs_idx = 0; pstr->valid_raw_len = 0; pstr->offsets_needed = 0; pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF : CONTEXT_NEWLINE | CONTEXT_BEGBUF); if (!pstr->mbs_allocated) pstr->mbs = (unsigned char *) pstr->raw_mbs; offset = idx; } if (BE (offset != 0, 1)) { /* Should the already checked characters be kept? */ if (BE (offset < pstr->valid_raw_len, 1)) { /* Yes, move them to the front of the buffer. */ #ifdef RE_ENABLE_I18N if (BE (pstr->offsets_needed, 0)) { int low = 0, high = pstr->valid_len, mid; do { mid = (high + low) / 2; if (pstr->offsets[mid] > offset) high = mid; else if (pstr->offsets[mid] < offset) low = mid + 1; else break; } while (low < high); if (pstr->offsets[mid] < offset) ++mid; pstr->tip_context = re_string_context_at (pstr, mid - 1, eflags); /* This can be quite complicated, so handle specially only the common and easy case where the character with different length representation of lower and upper case is present at or after offset. */ if (pstr->valid_len > offset && mid == offset && pstr->offsets[mid] == offset) { memmove (pstr->wcs, pstr->wcs + offset, (pstr->valid_len - offset) * sizeof (wint_t)); memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset); pstr->valid_len -= offset; pstr->valid_raw_len -= offset; for (low = 0; low < pstr->valid_len; low++) pstr->offsets[low] = pstr->offsets[low + offset] - offset; } else { /* Otherwise, just find out how long the partial multibyte character at offset is and fill it with WEOF/255. */ pstr->len = pstr->raw_len - idx + offset; pstr->stop = pstr->raw_stop - idx + offset; pstr->offsets_needed = 0; while (mid > 0 && pstr->offsets[mid - 1] == offset) --mid; while (mid < pstr->valid_len) if (pstr->wcs[mid] != WEOF) break; else ++mid; if (mid == pstr->valid_len) pstr->valid_len = 0; else { pstr->valid_len = pstr->offsets[mid] - offset; if (pstr->valid_len) { for (low = 0; low < pstr->valid_len; ++low) pstr->wcs[low] = WEOF; memset (pstr->mbs, 255, pstr->valid_len); } } pstr->valid_raw_len = pstr->valid_len; } } else #endif { pstr->tip_context = re_string_context_at (pstr, offset - 1, eflags); #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) memmove (pstr->wcs, pstr->wcs + offset, (pstr->valid_len - offset) * sizeof (wint_t)); #endif /* RE_ENABLE_I18N */ if (BE (pstr->mbs_allocated, 0)) memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset); pstr->valid_len -= offset; pstr->valid_raw_len -= offset; #if DEBUG assert (pstr->valid_len > 0); #endif } } else { /* No, skip all characters until IDX. */ int prev_valid_len = pstr->valid_len; #ifdef RE_ENABLE_I18N if (BE (pstr->offsets_needed, 0)) { pstr->len = pstr->raw_len - idx + offset; pstr->stop = pstr->raw_stop - idx + offset; pstr->offsets_needed = 0; } #endif pstr->valid_len = 0; #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { int wcs_idx; wint_t wc = WEOF; if (pstr->is_utf8) { const unsigned char *raw, *p, *q, *end; /* Special case UTF-8. Multi-byte chars start with any byte other than 0x80 - 0xbf. */ raw = pstr->raw_mbs + pstr->raw_mbs_idx; end = raw + (offset - pstr->mb_cur_max); if (end < pstr->raw_mbs) end = pstr->raw_mbs; p = raw + offset - 1; #ifdef _LIBC /* We know the wchar_t encoding is UCS4, so for the simple case, ASCII characters, skip the conversion step. */ if (isascii (*p) && BE (pstr->trans == NULL, 1)) { memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); /* pstr->valid_len = 0; */ wc = (wchar_t) *p; } else #endif for (; p >= end; --p) if ((*p & 0xc0) != 0x80) { mbstate_t cur_state; wchar_t wc2; int mlen = raw + pstr->len - p; unsigned char buf[6]; size_t mbclen; q = p; if (BE (pstr->trans != NULL, 0)) { int i = mlen < 6 ? mlen : 6; while (--i >= 0) buf[i] = pstr->trans[p[i]]; q = buf; } /* XXX Don't use mbrtowc, we know which conversion to use (UTF-8 -> UCS4). */ memset (&cur_state, 0, sizeof (cur_state)); mbclen = mbrtowc (&wc2, (const char *) p, mlen, &cur_state); if (raw + offset - p <= mbclen && mbclen < (size_t) -2) { memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); pstr->valid_len = mbclen - (raw + offset - p); wc = wc2; } break; } } if (wc == WEOF) pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx; if (wc == WEOF) pstr->tip_context = re_string_context_at (pstr, prev_valid_len - 1, eflags); else pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc)) ? CONTEXT_WORD : ((IS_WIDE_NEWLINE (wc) && pstr->newline_anchor) ? CONTEXT_NEWLINE : 0)); if (BE (pstr->valid_len, 0)) { for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx) pstr->wcs[wcs_idx] = WEOF; if (pstr->mbs_allocated) memset (pstr->mbs, 255, pstr->valid_len); } pstr->valid_raw_len = pstr->valid_len; } else #endif /* RE_ENABLE_I18N */ { int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1]; pstr->valid_raw_len = 0; if (pstr->trans) c = pstr->trans[c]; pstr->tip_context = (bitset_contain (pstr->word_char, c) ? CONTEXT_WORD : ((IS_NEWLINE (c) && pstr->newline_anchor) ? CONTEXT_NEWLINE : 0)); } } if (!BE (pstr->mbs_allocated, 0)) pstr->mbs += offset; } pstr->raw_mbs_idx = idx; pstr->len -= offset; pstr->stop -= offset; /* Then build the buffers. */ #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { if (pstr->icase) { reg_errcode_t ret = build_wcs_upper_buffer (pstr); if (BE (ret != REG_NOERROR, 0)) return ret; } else build_wcs_buffer (pstr); } else #endif /* RE_ENABLE_I18N */ if (BE (pstr->mbs_allocated, 0)) { if (pstr->icase) build_upper_buffer (pstr); else if (pstr->trans != NULL) re_string_translate_buffer (pstr); } else pstr->valid_len = pstr->len; pstr->cur_idx = 0; return REG_NOERROR; } static unsigned char internal_function __attribute ((pure)) re_string_peek_byte_case (const re_string_t *pstr, int idx) { int ch, off; /* Handle the common (easiest) cases first. */ if (BE (!pstr->mbs_allocated, 1)) return re_string_peek_byte (pstr, idx); #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1 && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) return re_string_peek_byte (pstr, idx); #endif off = pstr->cur_idx + idx; #ifdef RE_ENABLE_I18N if (pstr->offsets_needed) off = pstr->offsets[off]; #endif ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; #ifdef RE_ENABLE_I18N /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I this function returns CAPITAL LETTER I instead of first byte of DOTLESS SMALL LETTER I. The latter would confuse the parser, since peek_byte_case doesn't advance cur_idx in any way. */ if (pstr->offsets_needed && !isascii (ch)) return re_string_peek_byte (pstr, idx); #endif return ch; } static unsigned char internal_function __attribute ((pure)) re_string_fetch_byte_case (re_string_t *pstr) { if (BE (!pstr->mbs_allocated, 1)) return re_string_fetch_byte (pstr); #ifdef RE_ENABLE_I18N if (pstr->offsets_needed) { int off, ch; /* For tr_TR.UTF-8 [[:islower:]] there is [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip in that case the whole multi-byte character and return the original letter. On the other side, with [[: DOTLESS SMALL LETTER I return [[:I, as doing anything else would complicate things too much. */ if (!re_string_first_byte (pstr, pstr->cur_idx)) return re_string_fetch_byte (pstr); off = pstr->offsets[pstr->cur_idx]; ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; if (! isascii (ch)) return re_string_fetch_byte (pstr); re_string_skip_bytes (pstr, re_string_char_size_at (pstr, pstr->cur_idx)); return ch; } #endif return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++]; } static void internal_function re_string_destruct (re_string_t *pstr) { #ifdef RE_ENABLE_I18N re_free (pstr->wcs); re_free (pstr->offsets); #endif /* RE_ENABLE_I18N */ if (pstr->mbs_allocated) re_free (pstr->mbs); } /* Return the context at IDX in INPUT. */ static unsigned int internal_function re_string_context_at (const re_string_t *input, int idx, int eflags) { int c; if (BE (idx < 0, 0)) /* In this case, we use the value stored in input->tip_context, since we can't know the character in input->mbs[-1] here. */ return input->tip_context; if (BE (idx == input->len, 0)) return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF : CONTEXT_NEWLINE | CONTEXT_ENDBUF); #ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1) { wint_t wc; int wc_idx = idx; while(input->wcs[wc_idx] == WEOF) { #ifdef DEBUG /* It must not happen. */ assert (wc_idx >= 0); #endif --wc_idx; if (wc_idx < 0) return input->tip_context; } wc = input->wcs[wc_idx]; if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc)) return CONTEXT_WORD; return (IS_WIDE_NEWLINE (wc) && input->newline_anchor ? CONTEXT_NEWLINE : 0); } else #endif { c = re_string_byte_at (input, idx); if (bitset_contain (input->word_char, c)) return CONTEXT_WORD; return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0; } } /* Functions for set operation. */ static reg_errcode_t internal_function re_node_set_alloc (re_node_set *set, int size) { set->alloc = size; set->nelem = 0; set->elems = re_malloc (int, size); if (BE (set->elems == NULL, 0)) return REG_ESPACE; return REG_NOERROR; } static reg_errcode_t internal_function re_node_set_init_1 (re_node_set *set, int elem) { set->alloc = 1; set->nelem = 1; set->elems = re_malloc (int, 1); if (BE (set->elems == NULL, 0)) { set->alloc = set->nelem = 0; return REG_ESPACE; } set->elems[0] = elem; return REG_NOERROR; } static reg_errcode_t internal_function re_node_set_init_2 (re_node_set *set, int elem1, int elem2) { set->alloc = 2; set->elems = re_malloc (int, 2); if (BE (set->elems == NULL, 0)) return REG_ESPACE; if (elem1 == elem2) { set->nelem = 1; set->elems[0] = elem1; } else { set->nelem = 2; if (elem1 < elem2) { set->elems[0] = elem1; set->elems[1] = elem2; } else { set->elems[0] = elem2; set->elems[1] = elem1; } } return REG_NOERROR; } static reg_errcode_t internal_function re_node_set_init_copy (re_node_set *dest, const re_node_set *src) { dest->nelem = src->nelem; if (src->nelem > 0) { dest->alloc = dest->nelem; dest->elems = re_malloc (int, dest->alloc); if (BE (dest->elems == NULL, 0)) { dest->alloc = dest->nelem = 0; return REG_ESPACE; } memcpy (dest->elems, src->elems, src->nelem * sizeof (int)); } else re_node_set_init_empty (dest); return REG_NOERROR; } /* Calculate the intersection of the sets SRC1 and SRC2. And merge it to DEST. Return value indicate the error code or REG_NOERROR if succeeded. Note: We assume dest->elems is NULL, when dest->alloc is 0. */ static reg_errcode_t internal_function re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, const re_node_set *src2) { int i1, i2, is, id, delta, sbase; if (src1->nelem == 0 || src2->nelem == 0) return REG_NOERROR; /* We need dest->nelem + 2 * elems_in_intersection; this is a conservative estimate. */ if (src1->nelem + src2->nelem + dest->nelem > dest->alloc) { int new_alloc = src1->nelem + src2->nelem + dest->alloc; int *new_elems = re_realloc (dest->elems, int, new_alloc); if (BE (new_elems == NULL, 0)) return REG_ESPACE; dest->elems = new_elems; dest->alloc = new_alloc; } /* Find the items in the intersection of SRC1 and SRC2, and copy into the top of DEST those that are not already in DEST itself. */ sbase = dest->nelem + src1->nelem + src2->nelem; i1 = src1->nelem - 1; i2 = src2->nelem - 1; id = dest->nelem - 1; for (;;) { if (src1->elems[i1] == src2->elems[i2]) { /* Try to find the item in DEST. Maybe we could binary search? */ while (id >= 0 && dest->elems[id] > src1->elems[i1]) --id; if (id < 0 || dest->elems[id] != src1->elems[i1]) dest->elems[--sbase] = src1->elems[i1]; if (--i1 < 0 || --i2 < 0) break; } /* Lower the highest of the two items. */ else if (src1->elems[i1] < src2->elems[i2]) { if (--i2 < 0) break; } else { if (--i1 < 0) break; } } id = dest->nelem - 1; is = dest->nelem + src1->nelem + src2->nelem - 1; delta = is - sbase + 1; /* Now copy. When DELTA becomes zero, the remaining DEST elements are already in place; this is more or less the same loop that is in re_node_set_merge. */ dest->nelem += delta; if (delta > 0 && id >= 0) for (;;) { if (dest->elems[is] > dest->elems[id]) { /* Copy from the top. */ dest->elems[id + delta--] = dest->elems[is--]; if (delta == 0) break; } else { /* Slide from the bottom. */ dest->elems[id + delta] = dest->elems[id]; if (--id < 0) break; } } /* Copy remaining SRC elements. */ memcpy (dest->elems, dest->elems + sbase, delta * sizeof (int)); return REG_NOERROR; } /* Calculate the union set of the sets SRC1 and SRC2. And store it to DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ static reg_errcode_t internal_function re_node_set_init_union (re_node_set *dest, const re_node_set *src1, const re_node_set *src2) { int i1, i2, id; if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0) { dest->alloc = src1->nelem + src2->nelem; dest->elems = re_malloc (int, dest->alloc); if (BE (dest->elems == NULL, 0)) return REG_ESPACE; } else { if (src1 != NULL && src1->nelem > 0) return re_node_set_init_copy (dest, src1); else if (src2 != NULL && src2->nelem > 0) return re_node_set_init_copy (dest, src2); else re_node_set_init_empty (dest); return REG_NOERROR; } for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;) { if (src1->elems[i1] > src2->elems[i2]) { dest->elems[id++] = src2->elems[i2++]; continue; } if (src1->elems[i1] == src2->elems[i2]) ++i2; dest->elems[id++] = src1->elems[i1++]; } if (i1 < src1->nelem) { memcpy (dest->elems + id, src1->elems + i1, (src1->nelem - i1) * sizeof (int)); id += src1->nelem - i1; } else if (i2 < src2->nelem) { memcpy (dest->elems + id, src2->elems + i2, (src2->nelem - i2) * sizeof (int)); id += src2->nelem - i2; } dest->nelem = id; return REG_NOERROR; } /* Calculate the union set of the sets DEST and SRC. And store it to DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ static reg_errcode_t internal_function re_node_set_merge (re_node_set *dest, const re_node_set *src) { int is, id, sbase, delta; if (src == NULL || src->nelem == 0) return REG_NOERROR; if (dest->alloc < 2 * src->nelem + dest->nelem) { int new_alloc = 2 * (src->nelem + dest->alloc); int *new_buffer = re_realloc (dest->elems, int, new_alloc); if (BE (new_buffer == NULL, 0)) return REG_ESPACE; dest->elems = new_buffer; dest->alloc = new_alloc; } if (BE (dest->nelem == 0, 0)) { dest->nelem = src->nelem; memcpy (dest->elems, src->elems, src->nelem * sizeof (int)); return REG_NOERROR; } /* Copy into the top of DEST the items of SRC that are not found in DEST. Maybe we could binary search in DEST? */ for (sbase = dest->nelem + 2 * src->nelem, is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; ) { if (dest->elems[id] == src->elems[is]) is--, id--; else if (dest->elems[id] < src->elems[is]) dest->elems[--sbase] = src->elems[is--]; else /* if (dest->elems[id] > src->elems[is]) */ --id; } if (is >= 0) { /* If DEST is exhausted, the remaining items of SRC must be unique. */ sbase -= is + 1; memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (int)); } id = dest->nelem - 1; is = dest->nelem + 2 * src->nelem - 1; delta = is - sbase + 1; if (delta == 0) return REG_NOERROR; /* Now copy. When DELTA becomes zero, the remaining DEST elements are already in place. */ dest->nelem += delta; for (;;) { if (dest->elems[is] > dest->elems[id]) { /* Copy from the top. */ dest->elems[id + delta--] = dest->elems[is--]; if (delta == 0) break; } else { /* Slide from the bottom. */ dest->elems[id + delta] = dest->elems[id]; if (--id < 0) { /* Copy remaining SRC elements. */ memcpy (dest->elems, dest->elems + sbase, delta * sizeof (int)); break; } } } return REG_NOERROR; } /* Insert the new element ELEM to the re_node_set* SET. SET should not already have ELEM. return -1 if an error is occured, return 1 otherwise. */ static int internal_function re_node_set_insert (re_node_set *set, int elem) { int idx; /* In case the set is empty. */ if (set->alloc == 0) { if (BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1)) return 1; else return -1; } if (BE (set->nelem, 0) == 0) { /* We already guaranteed above that set->alloc != 0. */ set->elems[0] = elem; ++set->nelem; return 1; } /* Realloc if we need. */ if (set->alloc == set->nelem) { int *new_elems; set->alloc = set->alloc * 2; new_elems = re_realloc (set->elems, int, set->alloc); if (BE (new_elems == NULL, 0)) return -1; set->elems = new_elems; } /* Move the elements which follows the new element. Test the first element separately to skip a check in the inner loop. */ if (elem < set->elems[0]) { idx = 0; for (idx = set->nelem; idx > 0; idx--) set->elems[idx] = set->elems[idx - 1]; } else { for (idx = set->nelem; set->elems[idx - 1] > elem; idx--) set->elems[idx] = set->elems[idx - 1]; } /* Insert the new element. */ set->elems[idx] = elem; ++set->nelem; return 1; } /* Insert the new element ELEM to the re_node_set* SET. SET should not already have any element greater than or equal to ELEM. Return -1 if an error is occured, return 1 otherwise. */ static int internal_function re_node_set_insert_last (re_node_set *set, int elem) { /* Realloc if we need. */ if (set->alloc == set->nelem) { int *new_elems; set->alloc = (set->alloc + 1) * 2; new_elems = re_realloc (set->elems, int, set->alloc); if (BE (new_elems == NULL, 0)) return -1; set->elems = new_elems; } /* Insert the new element. */ set->elems[set->nelem++] = elem; return 1; } /* Compare two node sets SET1 and SET2. return 1 if SET1 and SET2 are equivalent, return 0 otherwise. */ static int internal_function __attribute ((pure)) re_node_set_compare (const re_node_set *set1, const re_node_set *set2) { int i; if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem) return 0; for (i = set1->nelem ; --i >= 0 ; ) if (set1->elems[i] != set2->elems[i]) return 0; return 1; } /* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */ static int internal_function __attribute ((pure)) re_node_set_contains (const re_node_set *set, int elem) { unsigned int idx, right, mid; if (set->nelem <= 0) return 0; /* Binary search the element. */ idx = 0; right = set->nelem - 1; while (idx < right) { mid = (idx + right) / 2; if (set->elems[mid] < elem) idx = mid + 1; else right = mid; } return set->elems[idx] == elem ? idx + 1 : 0; } static void internal_function re_node_set_remove_at (re_node_set *set, int idx) { if (idx < 0 || idx >= set->nelem) return; --set->nelem; for (; idx < set->nelem; idx++) set->elems[idx] = set->elems[idx + 1]; } /* Add the token TOKEN to dfa->nodes, and return the index of the token. Or return -1, if an error will be occured. */ static int internal_function re_dfa_add_node (re_dfa_t *dfa, re_token_t token) { int type = token.type; if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0)) { size_t new_nodes_alloc = dfa->nodes_alloc * 2; int *new_nexts, *new_indices; re_node_set *new_edests, *new_eclosures; re_token_t *new_nodes; /* Avoid overflows. */ if (BE (new_nodes_alloc < dfa->nodes_alloc, 0)) return -1; new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); if (BE (new_nodes == NULL, 0)) return -1; dfa->nodes = new_nodes; new_nexts = re_realloc (dfa->nexts, int, new_nodes_alloc); new_indices = re_realloc (dfa->org_indices, int, new_nodes_alloc); new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc); new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc); if (BE (new_nexts == NULL || new_indices == NULL || new_edests == NULL || new_eclosures == NULL, 0)) return -1; dfa->nexts = new_nexts; dfa->org_indices = new_indices; dfa->edests = new_edests; dfa->eclosures = new_eclosures; dfa->nodes_alloc = new_nodes_alloc; } dfa->nodes[dfa->nodes_len] = token; dfa->nodes[dfa->nodes_len].constraint = 0; #ifdef RE_ENABLE_I18N dfa->nodes[dfa->nodes_len].accept_mb = (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET; #endif dfa->nexts[dfa->nodes_len] = -1; re_node_set_init_empty (dfa->edests + dfa->nodes_len); re_node_set_init_empty (dfa->eclosures + dfa->nodes_len); return dfa->nodes_len++; } static inline unsigned int internal_function calc_state_hash (const re_node_set *nodes, unsigned int context) { unsigned int hash = nodes->nelem + context; int i; for (i = 0 ; i < nodes->nelem ; i++) hash += nodes->elems[i]; return hash; } /* Search for the state whose node_set is equivalent to NODES. Return the pointer to the state, if we found it in the DFA. Otherwise create the new one and return it. In case of an error return NULL and set the error code in ERR. Note: - We assume NULL as the invalid state, then it is possible that return value is NULL and ERR is REG_NOERROR. - We never return non-NULL value in case of any errors, it is for optimization. */ static re_dfastate_t * internal_function re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa, const re_node_set *nodes) { unsigned int hash; re_dfastate_t *new_state; struct re_state_table_entry *spot; int i; if (BE (nodes->nelem == 0, 0)) { *err = REG_NOERROR; return NULL; } hash = calc_state_hash (nodes, 0); spot = dfa->state_table + (hash & dfa->state_hash_mask); for (i = 0 ; i < spot->num ; i++) { re_dfastate_t *state = spot->array[i]; if (hash != state->hash) continue; if (re_node_set_compare (&state->nodes, nodes)) return state; } /* There are no appropriate state in the dfa, create the new one. */ new_state = create_ci_newstate (dfa, nodes, hash); if (BE (new_state == NULL, 0)) *err = REG_ESPACE; return new_state; } /* Search for the state whose node_set is equivalent to NODES and whose context is equivalent to CONTEXT. Return the pointer to the state, if we found it in the DFA. Otherwise create the new one and return it. In case of an error return NULL and set the error code in ERR. Note: - We assume NULL as the invalid state, then it is possible that return value is NULL and ERR is REG_NOERROR. - We never return non-NULL value in case of any errors, it is for optimization. */ static re_dfastate_t * internal_function re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, const re_node_set *nodes, unsigned int context) { unsigned int hash; re_dfastate_t *new_state; struct re_state_table_entry *spot; int i; if (nodes->nelem == 0) { *err = REG_NOERROR; return NULL; } hash = calc_state_hash (nodes, context); spot = dfa->state_table + (hash & dfa->state_hash_mask); for (i = 0 ; i < spot->num ; i++) { re_dfastate_t *state = spot->array[i]; if (state->hash == hash && state->context == context && re_node_set_compare (state->entrance_nodes, nodes)) return state; } /* There are no appropriate state in `dfa', create the new one. */ new_state = create_cd_newstate (dfa, nodes, context, hash); if (BE (new_state == NULL, 0)) *err = REG_ESPACE; return new_state; } /* Finish initialization of the new state NEWSTATE, and using its hash value HASH put in the appropriate bucket of DFA's state table. Return value indicates the error code if failed. */ static reg_errcode_t register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, unsigned int hash) { struct re_state_table_entry *spot; reg_errcode_t err; int i; newstate->hash = hash; err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem); if (BE (err != REG_NOERROR, 0)) return REG_ESPACE; for (i = 0; i < newstate->nodes.nelem; i++) { int elem = newstate->nodes.elems[i]; if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) re_node_set_insert_last (&newstate->non_eps_nodes, elem); } spot = dfa->state_table + (hash & dfa->state_hash_mask); if (BE (spot->alloc <= spot->num, 0)) { int new_alloc = 2 * spot->num + 2; re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *, new_alloc); if (BE (new_array == NULL, 0)) return REG_ESPACE; spot->array = new_array; spot->alloc = new_alloc; } spot->array[spot->num++] = newstate; return REG_NOERROR; } static void free_state (re_dfastate_t *state) { re_node_set_free (&state->non_eps_nodes); re_node_set_free (&state->inveclosure); if (state->entrance_nodes != &state->nodes) { re_node_set_free (state->entrance_nodes); re_free (state->entrance_nodes); } re_node_set_free (&state->nodes); re_free (state->word_trtable); re_free (state->trtable); re_free (state); } /* Create the new state which is independ of contexts. Return the new state if succeeded, otherwise return NULL. */ static re_dfastate_t * internal_function create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, unsigned int hash) { int i; reg_errcode_t err; re_dfastate_t *newstate; newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); if (BE (newstate == NULL, 0)) return NULL; err = re_node_set_init_copy (&newstate->nodes, nodes); if (BE (err != REG_NOERROR, 0)) { re_free (newstate); return NULL; } newstate->entrance_nodes = &newstate->nodes; for (i = 0 ; i < nodes->nelem ; i++) { re_token_t *node = dfa->nodes + nodes->elems[i]; re_token_type_t type = node->type; if (type == CHARACTER && !node->constraint) continue; #ifdef RE_ENABLE_I18N newstate->accept_mb |= node->accept_mb; #endif /* RE_ENABLE_I18N */ /* If the state has the halt node, the state is a halt state. */ if (type == END_OF_RE) newstate->halt = 1; else if (type == OP_BACK_REF) newstate->has_backref = 1; else if (type == ANCHOR || node->constraint) newstate->has_constraint = 1; } err = register_state (dfa, newstate, hash); if (BE (err != REG_NOERROR, 0)) { free_state (newstate); newstate = NULL; } return newstate; } /* Create the new state which is depend on the context CONTEXT. Return the new state if succeeded, otherwise return NULL. */ static re_dfastate_t * internal_function create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, unsigned int context, unsigned int hash) { int i, nctx_nodes = 0; reg_errcode_t err; re_dfastate_t *newstate; newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); if (BE (newstate == NULL, 0)) return NULL; err = re_node_set_init_copy (&newstate->nodes, nodes); if (BE (err != REG_NOERROR, 0)) { re_free (newstate); return NULL; } newstate->context = context; newstate->entrance_nodes = &newstate->nodes; for (i = 0 ; i < nodes->nelem ; i++) { unsigned int constraint = 0; re_token_t *node = dfa->nodes + nodes->elems[i]; re_token_type_t type = node->type; if (node->constraint) constraint = node->constraint; if (type == CHARACTER && !constraint) continue; #ifdef RE_ENABLE_I18N newstate->accept_mb |= node->accept_mb; #endif /* RE_ENABLE_I18N */ /* If the state has the halt node, the state is a halt state. */ if (type == END_OF_RE) newstate->halt = 1; else if (type == OP_BACK_REF) newstate->has_backref = 1; else if (type == ANCHOR) constraint = node->opr.ctx_type; if (constraint) { if (newstate->entrance_nodes == &newstate->nodes) { newstate->entrance_nodes = re_malloc (re_node_set, 1); if (BE (newstate->entrance_nodes == NULL, 0)) { free_state (newstate); return NULL; } re_node_set_init_copy (newstate->entrance_nodes, nodes); nctx_nodes = 0; newstate->has_constraint = 1; } if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context)) { re_node_set_remove_at (&newstate->nodes, i - nctx_nodes); ++nctx_nodes; } } } err = register_state (dfa, newstate, hash); if (BE (err != REG_NOERROR, 0)) { free_state (newstate); newstate = NULL; } return newstate; } /******************************************************************************/ /******************************************************************************/ /******************************************************************************/ /* GKINCLUDE #include "regcomp.c" */ /******************************************************************************/ /******************************************************************************/ /******************************************************************************/ /* Extended regular expression matching and search library. Copyright (C) 2002,2003,2004,2005,2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, size_t length, reg_syntax_t syntax); static void re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, char *fastmap); static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len); #ifdef RE_ENABLE_I18N static void free_charset (re_charset_t *cset); #endif /* RE_ENABLE_I18N */ static void free_workarea_compile (regex_t *preg); static reg_errcode_t create_initial_state (re_dfa_t *dfa); #ifdef RE_ENABLE_I18N static void optimize_utf8 (re_dfa_t *dfa); #endif static reg_errcode_t analyze (regex_t *preg); static reg_errcode_t preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), void *extra); static reg_errcode_t postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), void *extra); static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node); static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node); static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node); static reg_errcode_t calc_first (void *extra, bin_tree_t *node); static reg_errcode_t calc_next (void *extra, bin_tree_t *node); static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node); static int duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint); static int search_duplicated_node (const re_dfa_t *dfa, int org_node, unsigned int constraint); static reg_errcode_t calc_eclosure (re_dfa_t *dfa); static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root); static reg_errcode_t calc_inveclosure (re_dfa_t *dfa); static int fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax); static int peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) internal_function; static bin_tree_t *parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, reg_errcode_t *err); static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err); static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err); static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err); static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err); static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err); static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err); static reg_errcode_t parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, re_token_t *token, int token_len, re_dfa_t *dfa, reg_syntax_t syntax, int accept_hyphen); static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, re_token_t *token); #ifdef RE_ENABLE_I18N static reg_errcode_t build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, int *equiv_class_alloc, const unsigned char *name); static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, re_charset_t *mbcset, int *char_class_alloc, const unsigned char *class_name, reg_syntax_t syntax); #else /* not RE_ENABLE_I18N */ static reg_errcode_t build_equiv_class (bitset_t sbcset, const unsigned char *name); static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, const unsigned char *class_name, reg_syntax_t syntax); #endif /* not RE_ENABLE_I18N */ static bin_tree_t *build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, const unsigned char *class_name, const unsigned char *extra, int non_match, reg_errcode_t *err); static bin_tree_t *create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, re_token_type_t type); static bin_tree_t *create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, const re_token_t *token); static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa); static void free_token (re_token_t *node); static reg_errcode_t free_tree (void *extra, bin_tree_t *node); static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node); /* This table gives an error message for each of the error codes listed in regex.h. Obviously the order here has to be same as there. POSIX doesn't require that we do anything for REG_NOERROR, but why not be nice? */ const char __re_error_msgid[] attribute_hidden = { #define REG_NOERROR_IDX 0 gettext_noop ("Success") /* REG_NOERROR */ "\0" #define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") gettext_noop ("No match") /* REG_NOMATCH */ "\0" #define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") gettext_noop ("Invalid regular expression") /* REG_BADPAT */ "\0" #define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") gettext_noop ("Invalid collation character") /* REG_ECOLLATE */ "\0" #define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") gettext_noop ("Invalid character class name") /* REG_ECTYPE */ "\0" #define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") gettext_noop ("Trailing backslash") /* REG_EESCAPE */ "\0" #define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") gettext_noop ("Invalid back reference") /* REG_ESUBREG */ "\0" #define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */ "\0" #define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^") gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */ "\0" #define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") gettext_noop ("Unmatched \\{") /* REG_EBRACE */ "\0" #define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */ "\0" #define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") gettext_noop ("Invalid range end") /* REG_ERANGE */ "\0" #define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") gettext_noop ("Memory exhausted") /* REG_ESPACE */ "\0" #define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */ "\0" #define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") gettext_noop ("Premature end of regular expression") /* REG_EEND */ "\0" #define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") gettext_noop ("Regular expression too big") /* REG_ESIZE */ "\0" #define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ }; const size_t __re_error_msgid_idx[] attribute_hidden = { REG_NOERROR_IDX, REG_NOMATCH_IDX, REG_BADPAT_IDX, REG_ECOLLATE_IDX, REG_ECTYPE_IDX, REG_EESCAPE_IDX, REG_ESUBREG_IDX, REG_EBRACK_IDX, REG_EPAREN_IDX, REG_EBRACE_IDX, REG_BADBR_IDX, REG_ERANGE_IDX, REG_ESPACE_IDX, REG_BADRPT_IDX, REG_EEND_IDX, REG_ESIZE_IDX, REG_ERPAREN_IDX }; /* Entry points for GNU code. */ /* re_compile_pattern is the GNU regular expression compiler: it compiles PATTERN (of length LENGTH) and puts the result in BUFP. Returns 0 if the pattern was valid, otherwise an error string. Assumes the `allocated' (and perhaps `buffer') and `translate' fields are set in BUFP on entry. */ const char * re_compile_pattern (pattern, length, bufp) const char *pattern; size_t length; struct re_pattern_buffer *bufp; { reg_errcode_t ret; /* And GNU code determines whether or not to get register information by passing null for the REGS argument to re_match, etc., not by setting no_sub, unless RE_NO_SUB is set. */ bufp->no_sub = !!(re_syntax_options & RE_NO_SUB); /* Match anchors at newline. */ bufp->newline_anchor = 1; ret = re_compile_internal (bufp, pattern, length, re_syntax_options); if (!ret) return NULL; return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); } #ifdef _LIBC weak_alias (__re_compile_pattern, re_compile_pattern) #endif /* Set by `re_set_syntax' to the current regexp syntax to recognize. Can also be assigned to arbitrarily: each pattern buffer stores its own syntax, so it can be changed between regex compilations. */ /* This has no initializer because initialized variables in Emacs become read-only after dumping. */ reg_syntax_t re_syntax_options; /* Specify the precise syntax of regexps for compilation. This provides for compatibility for various utilities which historically have different, incompatible syntaxes. The argument SYNTAX is a bit mask comprised of the various bits defined in regex.h. We return the old syntax. */ reg_syntax_t re_set_syntax (syntax) reg_syntax_t syntax; { reg_syntax_t ret = re_syntax_options; re_syntax_options = syntax; return ret; } #ifdef _LIBC weak_alias (__re_set_syntax, re_set_syntax) #endif int re_compile_fastmap (bufp) struct re_pattern_buffer *bufp; { re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; char *fastmap = bufp->fastmap; memset (fastmap, '\0', sizeof (char) * SBC_MAX); re_compile_fastmap_iter (bufp, dfa->init_state, fastmap); if (dfa->init_state != dfa->init_state_word) re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap); if (dfa->init_state != dfa->init_state_nl) re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap); if (dfa->init_state != dfa->init_state_begbuf) re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap); bufp->fastmap_accurate = 1; return 0; } #ifdef _LIBC weak_alias (__re_compile_fastmap, re_compile_fastmap) #endif static inline void __attribute ((always_inline)) re_set_fastmap (char *fastmap, int icase, int ch) { fastmap[ch] = 1; if (icase) fastmap[tolower (ch)] = 1; } /* Helper function for re_compile_fastmap. Compile fastmap for the initial_state INIT_STATE. */ static void re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, char *fastmap) { re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; int node_cnt; int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) { int node = init_state->nodes.elems[node_cnt]; re_token_type_t type = dfa->nodes[node].type; if (type == CHARACTER) { re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); #ifdef RE_ENABLE_I18N if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) { unsigned char *buf = alloca (dfa->mb_cur_max), *p; wchar_t wc; mbstate_t state; p = buf; *p++ = dfa->nodes[node].opr.c; while (++node < dfa->nodes_len && dfa->nodes[node].type == CHARACTER && dfa->nodes[node].mb_partial) *p++ = dfa->nodes[node].opr.c; memset (&state, '\0', sizeof (state)); if (mbrtowc (&wc, (const char *) buf, p - buf, &state) == p - buf && (__wcrtomb ((char *) buf, towlower (wc), &state) != (size_t) -1)) re_set_fastmap (fastmap, 0, buf[0]); } #endif } else if (type == SIMPLE_BRACKET) { int i, ch; for (i = 0, ch = 0; i < BITSET_WORDS; ++i) { int j; bitset_word_t w = dfa->nodes[node].opr.sbcset[i]; for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) if (w & ((bitset_word_t) 1 << j)) re_set_fastmap (fastmap, icase, ch); } } #ifdef RE_ENABLE_I18N else if (type == COMPLEX_BRACKET) { int i; re_charset_t *cset = dfa->nodes[node].opr.mbcset; if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes || cset->nranges || cset->nchar_classes) { # ifdef _LIBC if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0) { /* In this case we want to catch the bytes which are the first byte of any collation elements. e.g. In da_DK, we want to catch 'a' since "aa" is a valid collation element, and don't catch 'b' since 'b' is the only collation element which starts from 'b'. */ const int32_t *table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); for (i = 0; i < SBC_MAX; ++i) if (table[i] < 0) re_set_fastmap (fastmap, icase, i); } # else if (dfa->mb_cur_max > 1) for (i = 0; i < SBC_MAX; ++i) if (__btowc (i) == WEOF) re_set_fastmap (fastmap, icase, i); # endif /* not _LIBC */ } for (i = 0; i < cset->nmbchars; ++i) { char buf[256]; mbstate_t state; memset (&state, '\0', sizeof (state)); if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) re_set_fastmap (fastmap, icase, *(unsigned char *) buf); if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) { if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state) != (size_t) -1) re_set_fastmap (fastmap, 0, *(unsigned char *) buf); } } } #endif /* RE_ENABLE_I18N */ else if (type == OP_PERIOD #ifdef RE_ENABLE_I18N || type == OP_UTF8_PERIOD #endif /* RE_ENABLE_I18N */ || type == END_OF_RE) { memset (fastmap, '\1', sizeof (char) * SBC_MAX); if (type == END_OF_RE) bufp->can_be_null = 1; return; } } } /* Entry point for POSIX code. */ /* regcomp takes a regular expression as a string and compiles it. PREG is a regex_t *. We do not expect any fields to be initialized, since POSIX says we shouldn't. Thus, we set `buffer' to the compiled pattern; `used' to the length of the compiled pattern; `syntax' to RE_SYNTAX_POSIX_EXTENDED if the REG_EXTENDED bit in CFLAGS is set; otherwise, to RE_SYNTAX_POSIX_BASIC; `newline_anchor' to REG_NEWLINE being set in CFLAGS; `fastmap' to an allocated space for the fastmap; `fastmap_accurate' to zero; `re_nsub' to the number of subexpressions in PATTERN. PATTERN is the address of the pattern string. CFLAGS is a series of bits which affect compilation. If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we use POSIX basic syntax. If REG_NEWLINE is set, then . and [^...] don't match newline. Also, regexec will try a match beginning after every newline. If REG_ICASE is set, then we considers upper- and lowercase versions of letters to be equivalent when matching. If REG_NOSUB is set, then when PREG is passed to regexec, that routine will report only success or failure, and nothing about the registers. It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for the return codes and their meanings.) */ int regcomp (preg, pattern, cflags) regex_t *__restrict preg; const char *__restrict pattern; int cflags; { reg_errcode_t ret; reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC); preg->buffer = NULL; preg->allocated = 0; preg->used = 0; /* Try to allocate space for the fastmap. */ preg->fastmap = re_malloc (char, SBC_MAX); if (BE (preg->fastmap == NULL, 0)) return REG_ESPACE; syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0; /* If REG_NEWLINE is set, newlines are treated differently. */ if (cflags & REG_NEWLINE) { /* REG_NEWLINE implies neither . nor [^...] match newline. */ syntax &= ~RE_DOT_NEWLINE; syntax |= RE_HAT_LISTS_NOT_NEWLINE; /* It also changes the matching behavior. */ preg->newline_anchor = 1; } else preg->newline_anchor = 0; preg->no_sub = !!(cflags & REG_NOSUB); preg->translate = NULL; ret = re_compile_internal (preg, pattern, strlen (pattern), syntax); /* POSIX doesn't distinguish between an unmatched open-group and an unmatched close-group: both are REG_EPAREN. */ if (ret == REG_ERPAREN) ret = REG_EPAREN; /* We have already checked preg->fastmap != NULL. */ if (BE (ret == REG_NOERROR, 1)) /* Compute the fastmap now, since regexec cannot modify the pattern buffer. This function never fails in this implementation. */ (void) re_compile_fastmap (preg); else { /* Some error occurred while compiling the expression. */ re_free (preg->fastmap); preg->fastmap = NULL; } return (int) ret; } #ifdef _LIBC weak_alias (__regcomp, regcomp) #endif /* Returns a message corresponding to an error code, ERRCODE, returned from either regcomp or regexec. We don't use PREG here. */ /* regerror ( int errcode, preg, errbuf, errbuf_size) */ size_t regerror ( int errcode, const regex_t *__restrict preg, char *__restrict errbuf, size_t errbuf_size) { const char *msg; size_t msg_size; if (BE (errcode < 0 || errcode >= (int) (sizeof (__re_error_msgid_idx) / sizeof (__re_error_msgid_idx[0])), 0)) /* Only error codes returned by the rest of the code should be passed to this routine. If we are given anything else, or if other regex code generates an invalid error code, then the program has a bug. Dump core so we can fix it. */ abort (); msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); msg_size = strlen (msg) + 1; /* Includes the null. */ if (BE (errbuf_size != 0, 1)) { if (BE (msg_size > errbuf_size, 0)) { #if defined HAVE_MEMPCPY || defined _LIBC *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0'; #else memcpy (errbuf, msg, errbuf_size - 1); errbuf[errbuf_size - 1] = 0; #endif } else memcpy (errbuf, msg, msg_size); } return msg_size; } #ifdef _LIBC weak_alias (__regerror, regerror) #endif #ifdef RE_ENABLE_I18N /* This static array is used for the map to single-byte characters when UTF-8 is used. Otherwise we would allocate memory just to initialize it the same all the time. UTF-8 is the preferred encoding so this is a worthwhile optimization. */ static const bitset_t utf8_sb_map = { /* Set the first 128 bits. */ [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX }; #endif static void free_dfa_content (re_dfa_t *dfa) { int i, j; if (dfa->nodes) for (i = 0; i < dfa->nodes_len; ++i) free_token (dfa->nodes + i); re_free (dfa->nexts); for (i = 0; i < dfa->nodes_len; ++i) { if (dfa->eclosures != NULL) re_node_set_free (dfa->eclosures + i); if (dfa->inveclosures != NULL) re_node_set_free (dfa->inveclosures + i); if (dfa->edests != NULL) re_node_set_free (dfa->edests + i); } re_free (dfa->edests); re_free (dfa->eclosures); re_free (dfa->inveclosures); re_free (dfa->nodes); if (dfa->state_table) for (i = 0; i <= dfa->state_hash_mask; ++i) { struct re_state_table_entry *entry = dfa->state_table + i; for (j = 0; j < entry->num; ++j) { re_dfastate_t *state = entry->array[j]; free_state (state); } re_free (entry->array); } re_free (dfa->state_table); #ifdef RE_ENABLE_I18N if (dfa->sb_char != utf8_sb_map) re_free (dfa->sb_char); #endif re_free (dfa->subexp_map); #ifdef DEBUG re_free (dfa->re_str); #endif re_free (dfa); } /* Free dynamically allocated space used by PREG. */ void regfree (preg) regex_t *preg; { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; if (BE (dfa != NULL, 1)) free_dfa_content (dfa); preg->buffer = NULL; preg->allocated = 0; re_free (preg->fastmap); preg->fastmap = NULL; re_free (preg->translate); preg->translate = NULL; } #ifdef _LIBC weak_alias (__regfree, regfree) #endif /* Entry points compatible with 4.2 BSD regex library. We don't define them unless specifically requested. */ #if defined _REGEX_RE_COMP || defined _LIBC /* BSD has one and only one pattern buffer. */ static struct re_pattern_buffer re_comp_buf; char * # ifdef _LIBC /* Make these definitions weak in libc, so POSIX programs can redefine these names if they don't use our functions, and still use regcomp/regexec above without link errors. */ weak_function # endif re_comp (s) const char *s; { reg_errcode_t ret; char *fastmap; if (!s) { if (!re_comp_buf.buffer) return gettext ("No previous regular expression"); return 0; } if (re_comp_buf.buffer) { fastmap = re_comp_buf.fastmap; re_comp_buf.fastmap = NULL; __regfree (&re_comp_buf); memset (&re_comp_buf, '\0', sizeof (re_comp_buf)); re_comp_buf.fastmap = fastmap; } if (re_comp_buf.fastmap == NULL) { re_comp_buf.fastmap = (char *) malloc (SBC_MAX); if (re_comp_buf.fastmap == NULL) return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) REG_ESPACE]); } /* Since `re_exec' always passes NULL for the `regs' argument, we don't need to initialize the pattern buffer fields which affect it. */ /* Match anchors at newlines. */ re_comp_buf.newline_anchor = 1; ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options); if (!ret) return NULL; /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); } #ifdef _LIBC libc_freeres_fn (free_mem) { __regfree (&re_comp_buf); } #endif #endif /* _REGEX_RE_COMP */ /* Internal entry point. Compile the regular expression PATTERN, whose length is LENGTH. SYNTAX indicate regular expression's syntax. */ static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, size_t length, reg_syntax_t syntax) { reg_errcode_t err = REG_NOERROR; re_dfa_t *dfa; re_string_t regexp; /* Initialize the pattern buffer. */ preg->fastmap_accurate = 0; preg->syntax = syntax; preg->not_bol = preg->not_eol = 0; preg->used = 0; preg->re_nsub = 0; preg->can_be_null = 0; preg->regs_allocated = REGS_UNALLOCATED; /* Initialize the dfa. */ dfa = (re_dfa_t *) preg->buffer; if (BE (preg->allocated < sizeof (re_dfa_t), 0)) { /* If zero allocated, but buffer is non-null, try to realloc enough space. This loses if buffer's address is bogus, but that is the user's responsibility. If ->buffer is NULL this is a simple allocation. */ dfa = re_realloc (preg->buffer, re_dfa_t, 1); if (dfa == NULL) return REG_ESPACE; preg->allocated = sizeof (re_dfa_t); preg->buffer = (unsigned char *) dfa; } preg->used = sizeof (re_dfa_t); err = init_dfa (dfa, length); if (BE (err != REG_NOERROR, 0)) { free_dfa_content (dfa); preg->buffer = NULL; preg->allocated = 0; return err; } #ifdef DEBUG /* Note: length+1 will not overflow since it is checked in init_dfa. */ dfa->re_str = re_malloc (char, length + 1); strncpy (dfa->re_str, pattern, length + 1); #endif __libc_lock_init (dfa->lock); err = re_string_construct (®exp, pattern, length, preg->translate, syntax & RE_ICASE, dfa); if (BE (err != REG_NOERROR, 0)) { re_compile_internal_free_return: free_workarea_compile (preg); re_string_destruct (®exp); free_dfa_content (dfa); preg->buffer = NULL; preg->allocated = 0; return err; } /* Parse the regular expression, and build a structure tree. */ preg->re_nsub = 0; dfa->str_tree = parse (®exp, preg, syntax, &err); if (BE (dfa->str_tree == NULL, 0)) goto re_compile_internal_free_return; /* Analyze the tree and create the nfa. */ err = analyze (preg); if (BE (err != REG_NOERROR, 0)) goto re_compile_internal_free_return; #ifdef RE_ENABLE_I18N /* If possible, do searching in single byte encoding to speed things up. */ if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL) optimize_utf8 (dfa); #endif /* Then create the initial state of the dfa. */ err = create_initial_state (dfa); /* Release work areas. */ free_workarea_compile (preg); re_string_destruct (®exp); if (BE (err != REG_NOERROR, 0)) { free_dfa_content (dfa); preg->buffer = NULL; preg->allocated = 0; } return err; } /* Initialize DFA. We use the length of the regular expression PAT_LEN as the initial length of some arrays. */ static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len) { unsigned int table_size; #ifndef _LIBC char *codeset_name; #endif memset (dfa, '\0', sizeof (re_dfa_t)); /* Force allocation of str_tree_storage the first time. */ dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; /* Avoid overflows. */ if (pat_len == SIZE_MAX) return REG_ESPACE; dfa->nodes_alloc = pat_len + 1; dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc); /* table_size = 2 ^ ceil(log pat_len) */ for (table_size = 1; ; table_size <<= 1) if (table_size > pat_len) break; dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size); dfa->state_hash_mask = table_size - 1; dfa->mb_cur_max = MB_CUR_MAX; #ifdef _LIBC if (dfa->mb_cur_max == 6 && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0) dfa->is_utf8 = 1; dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII) != 0); #else # ifdef HAVE_LANGINFO_CODESET codeset_name = nl_langinfo (CODESET); # else codeset_name = getenv ("LC_ALL"); if (codeset_name == NULL || codeset_name[0] == '\0') codeset_name = getenv ("LC_CTYPE"); if (codeset_name == NULL || codeset_name[0] == '\0') codeset_name = getenv ("LANG"); if (codeset_name == NULL) codeset_name = ""; else if (strchr (codeset_name, '.') != NULL) codeset_name = strchr (codeset_name, '.') + 1; # endif if (strcasecmp (codeset_name, "UTF-8") == 0 || strcasecmp (codeset_name, "UTF8") == 0) dfa->is_utf8 = 1; /* We check exhaustively in the loop below if this charset is a superset of ASCII. */ dfa->map_notascii = 0; #endif #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { if (dfa->is_utf8) dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map; else { int i, j, ch; dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); if (BE (dfa->sb_char == NULL, 0)) return REG_ESPACE; /* Set the bits corresponding to single byte chars. */ for (i = 0, ch = 0; i < BITSET_WORDS; ++i) for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) { wint_t wch = __btowc (ch); if (wch != WEOF) dfa->sb_char[i] |= (bitset_word_t) 1 << j; # ifndef _LIBC if (isascii (ch) && wch != ch) dfa->map_notascii = 1; # endif } } } #endif if (BE (dfa->nodes == NULL || dfa->state_table == NULL, 0)) return REG_ESPACE; return REG_NOERROR; } /* Initialize WORD_CHAR table, which indicate which character is "word". In this case "word" means that it is the word construction character used by some operators like "\<", "\>", etc. */ static void internal_function init_word_char (re_dfa_t *dfa) { int i, j, ch; dfa->word_ops_used = 1; for (i = 0, ch = 0; i < BITSET_WORDS; ++i) for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) if (isalnum (ch) || ch == '_') dfa->word_char[i] |= (bitset_word_t) 1 << j; } /* Free the work area which are only used while compiling. */ static void free_workarea_compile (regex_t *preg) { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_storage_t *storage, *next; for (storage = dfa->str_tree_storage; storage; storage = next) { next = storage->next; re_free (storage); } dfa->str_tree_storage = NULL; dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; dfa->str_tree = NULL; re_free (dfa->org_indices); dfa->org_indices = NULL; } /* Create initial states for all contexts. */ static reg_errcode_t create_initial_state (re_dfa_t *dfa) { int first, i; reg_errcode_t err; re_node_set init_nodes; /* Initial states have the epsilon closure of the node which is the first node of the regular expression. */ first = dfa->str_tree->first->node_idx; dfa->init_node = first; err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first); if (BE (err != REG_NOERROR, 0)) return err; /* The back-references which are in initial states can epsilon transit, since in this case all of the subexpressions can be null. Then we add epsilon closures of the nodes which are the next nodes of the back-references. */ if (dfa->nbackref > 0) for (i = 0; i < init_nodes.nelem; ++i) { int node_idx = init_nodes.elems[i]; re_token_type_t type = dfa->nodes[node_idx].type; int clexp_idx; if (type != OP_BACK_REF) continue; for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx) { re_token_t *clexp_node; clexp_node = dfa->nodes + init_nodes.elems[clexp_idx]; if (clexp_node->type == OP_CLOSE_SUBEXP && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx) break; } if (clexp_idx == init_nodes.nelem) continue; if (type == OP_BACK_REF) { int dest_idx = dfa->edests[node_idx].elems[0]; if (!re_node_set_contains (&init_nodes, dest_idx)) { re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); i = 0; } } } /* It must be the first time to invoke acquire_state. */ dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0); /* We don't check ERR here, since the initial state must not be NULL. */ if (BE (dfa->init_state == NULL, 0)) return err; if (dfa->init_state->has_constraint) { dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes, CONTEXT_WORD); dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes, CONTEXT_NEWLINE); dfa->init_state_begbuf = re_acquire_state_context (&err, dfa, &init_nodes, CONTEXT_NEWLINE | CONTEXT_BEGBUF); if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL || dfa->init_state_begbuf == NULL, 0)) return err; } else dfa->init_state_word = dfa->init_state_nl = dfa->init_state_begbuf = dfa->init_state; re_node_set_free (&init_nodes); return REG_NOERROR; } #ifdef RE_ENABLE_I18N /* If it is possible to do searching in single byte encoding instead of UTF-8 to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change DFA nodes where needed. */ static void optimize_utf8 (re_dfa_t *dfa) { int node, i, mb_chars = 0, has_period = 0; for (node = 0; node < dfa->nodes_len; ++node) switch (dfa->nodes[node].type) { case CHARACTER: if (dfa->nodes[node].opr.c >= 0x80) mb_chars = 1; break; case ANCHOR: switch (dfa->nodes[node].opr.idx) { case LINE_FIRST: case LINE_LAST: case BUF_FIRST: case BUF_LAST: break; default: /* Word anchors etc. cannot be handled. */ return; } break; case OP_PERIOD: has_period = 1; break; case OP_BACK_REF: case OP_ALT: case END_OF_RE: case OP_DUP_ASTERISK: case OP_OPEN_SUBEXP: case OP_CLOSE_SUBEXP: break; case COMPLEX_BRACKET: return; case SIMPLE_BRACKET: /* Just double check. The non-ASCII range starts at 0x80. */ assert (0x80 % BITSET_WORD_BITS == 0); for (i = 0x80 / BITSET_WORD_BITS; i < BITSET_WORDS; ++i) if (dfa->nodes[node].opr.sbcset[i]) return; break; default: abort (); } if (mb_chars || has_period) for (node = 0; node < dfa->nodes_len; ++node) { if (dfa->nodes[node].type == CHARACTER && dfa->nodes[node].opr.c >= 0x80) dfa->nodes[node].mb_partial = 0; else if (dfa->nodes[node].type == OP_PERIOD) dfa->nodes[node].type = OP_UTF8_PERIOD; } /* The search can be in single byte locale. */ dfa->mb_cur_max = 1; dfa->is_utf8 = 0; dfa->has_mb_node = dfa->nbackref > 0 || has_period; } #endif /* Analyze the structure tree, and calculate "first", "next", "edest", "eclosure", and "inveclosure". */ static reg_errcode_t analyze (regex_t *preg) { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; reg_errcode_t ret; /* Allocate arrays. */ dfa->nexts = re_malloc (int, dfa->nodes_alloc); dfa->org_indices = re_malloc (int, dfa->nodes_alloc); dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc); dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc); if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL || dfa->eclosures == NULL, 0)) return REG_ESPACE; dfa->subexp_map = re_malloc (int, preg->re_nsub); if (dfa->subexp_map != NULL) { int i; for (i = 0; i < preg->re_nsub; i++) dfa->subexp_map[i] = i; preorder (dfa->str_tree, optimize_subexps, dfa); for (i = 0; i < preg->re_nsub; i++) if (dfa->subexp_map[i] != i) break; if (i == preg->re_nsub) { free (dfa->subexp_map); dfa->subexp_map = NULL; } } ret = postorder (dfa->str_tree, lower_subexps, preg); if (BE (ret != REG_NOERROR, 0)) return ret; ret = postorder (dfa->str_tree, calc_first, dfa); if (BE (ret != REG_NOERROR, 0)) return ret; preorder (dfa->str_tree, calc_next, dfa); ret = preorder (dfa->str_tree, link_nfa_nodes, dfa); if (BE (ret != REG_NOERROR, 0)) return ret; ret = calc_eclosure (dfa); if (BE (ret != REG_NOERROR, 0)) return ret; /* We only need this during the prune_impossible_nodes pass in regexec.c; skip it if p_i_n will not run, as calc_inveclosure can be quadratic. */ if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match) || dfa->nbackref) { dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len); if (BE (dfa->inveclosures == NULL, 0)) return REG_ESPACE; ret = calc_inveclosure (dfa); } return ret; } /* Our parse trees are very unbalanced, so we cannot use a stack to implement parse tree visits. Instead, we use parent pointers and some hairy code in these two functions. */ static reg_errcode_t postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), void *extra) { bin_tree_t *node, *prev; for (node = root; ; ) { /* Descend down the tree, preferably to the left (or to the right if that's the only child). */ while (node->left || node->right) if (node->left) node = node->left; else node = node->right; do { reg_errcode_t err = fn (extra, node); if (BE (err != REG_NOERROR, 0)) return err; if (node->parent == NULL) return REG_NOERROR; prev = node; node = node->parent; } /* Go up while we have a node that is reached from the right. */ while (node->right == prev || node->right == NULL); node = node->right; } } static reg_errcode_t preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), void *extra) { bin_tree_t *node; for (node = root; ; ) { reg_errcode_t err = fn (extra, node); if (BE (err != REG_NOERROR, 0)) return err; /* Go to the left node, or up and to the right. */ if (node->left) node = node->left; else { bin_tree_t *prev = NULL; while (node->right == prev || node->right == NULL) { prev = node; node = node->parent; if (!node) return REG_NOERROR; } node = node->right; } } } /* Optimization pass: if a SUBEXP is entirely contained, strip it and tell re_search_internal to map the inner one's opr.idx to this one's. Adjust backreferences as well. Requires a preorder visit. */ static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node) { re_dfa_t *dfa = (re_dfa_t *) extra; if (node->token.type == OP_BACK_REF && dfa->subexp_map) { int idx = node->token.opr.idx; node->token.opr.idx = dfa->subexp_map[idx]; dfa->used_bkref_map |= 1 << node->token.opr.idx; } else if (node->token.type == SUBEXP && node->left && node->left->token.type == SUBEXP) { int other_idx = node->left->token.opr.idx; node->left = node->left->left; if (node->left) node->left->parent = node; dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx]; if (other_idx < BITSET_WORD_BITS) dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx); } return REG_NOERROR; } /* Lowering pass: Turn each SUBEXP node into the appropriate concatenation of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP. */ static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node) { regex_t *preg = (regex_t *) extra; reg_errcode_t err = REG_NOERROR; if (node->left && node->left->token.type == SUBEXP) { node->left = lower_subexp (&err, preg, node->left); if (node->left) node->left->parent = node; } if (node->right && node->right->token.type == SUBEXP) { node->right = lower_subexp (&err, preg, node->right); if (node->right) node->right->parent = node; } return err; } static bin_tree_t * lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node) { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_t *body = node->left; bin_tree_t *op, *cls, *tree1, *tree; if (preg->no_sub /* We do not optimize empty subexpressions, because otherwise we may have bad CONCAT nodes with NULL children. This is obviously not very common, so we do not lose much. An example that triggers this case is the sed "script" /\(\)/x. */ && node->left != NULL && (node->token.opr.idx >= BITSET_WORD_BITS || !(dfa->used_bkref_map & ((bitset_word_t) 1 << node->token.opr.idx)))) return node->left; /* Convert the SUBEXP node to the concatenation of an OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */ op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP); cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP); tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls; tree = create_tree (dfa, op, tree1, CONCAT); if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0)) { *err = REG_ESPACE; return NULL; } op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx; op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp; return tree; } /* Pass 1 in building the NFA: compute FIRST and create unlinked automaton nodes. Requires a postorder visit. */ static reg_errcode_t calc_first (void *extra, bin_tree_t *node) { re_dfa_t *dfa = (re_dfa_t *) extra; if (node->token.type == CONCAT) { node->first = node->left->first; node->node_idx = node->left->node_idx; } else { node->first = node; node->node_idx = re_dfa_add_node (dfa, node->token); if (BE (node->node_idx == -1, 0)) return REG_ESPACE; } return REG_NOERROR; } /* Pass 2: compute NEXT on the tree. Preorder visit. */ static reg_errcode_t calc_next (void *extra, bin_tree_t *node) { switch (node->token.type) { case OP_DUP_ASTERISK: node->left->next = node; break; case CONCAT: node->left->next = node->right->first; node->right->next = node->next; break; default: if (node->left) node->left->next = node->next; if (node->right) node->right->next = node->next; break; } return REG_NOERROR; } /* Pass 3: link all DFA nodes to their NEXT node (any order will do). */ static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node) { re_dfa_t *dfa = (re_dfa_t *) extra; int idx = node->node_idx; reg_errcode_t err = REG_NOERROR; switch (node->token.type) { case CONCAT: break; case END_OF_RE: assert (node->next == NULL); break; case OP_DUP_ASTERISK: case OP_ALT: { int left, right; dfa->has_plural_match = 1; if (node->left != NULL) left = node->left->first->node_idx; else left = node->next->node_idx; if (node->right != NULL) right = node->right->first->node_idx; else right = node->next->node_idx; assert (left > -1); assert (right > -1); err = re_node_set_init_2 (dfa->edests + idx, left, right); } break; case ANCHOR: case OP_OPEN_SUBEXP: case OP_CLOSE_SUBEXP: err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx); break; case OP_BACK_REF: dfa->nexts[idx] = node->next->node_idx; if (node->token.type == OP_BACK_REF) re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]); break; default: assert (!IS_EPSILON_NODE (node->token.type)); dfa->nexts[idx] = node->next->node_idx; break; } return err; } /* Duplicate the epsilon closure of the node ROOT_NODE. Note that duplicated nodes have constraint INIT_CONSTRAINT in addition to their own constraint. */ static reg_errcode_t internal_function duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node, int root_node, unsigned int init_constraint) { int org_node, clone_node, ret; unsigned int constraint = init_constraint; for (org_node = top_org_node, clone_node = top_clone_node;;) { int org_dest, clone_dest; if (dfa->nodes[org_node].type == OP_BACK_REF) { /* If the back reference epsilon-transit, its destination must also have the constraint. Then duplicate the epsilon closure of the destination of the back reference, and store it in edests of the back reference. */ org_dest = dfa->nexts[org_node]; re_node_set_empty (dfa->edests + clone_node); clone_dest = duplicate_node (dfa, org_dest, constraint); if (BE (clone_dest == -1, 0)) return REG_ESPACE; dfa->nexts[clone_node] = dfa->nexts[org_node]; ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); if (BE (ret < 0, 0)) return REG_ESPACE; } else if (dfa->edests[org_node].nelem == 0) { /* In case of the node can't epsilon-transit, don't duplicate the destination and store the original destination as the destination of the node. */ dfa->nexts[clone_node] = dfa->nexts[org_node]; break; } else if (dfa->edests[org_node].nelem == 1) { /* In case of the node can epsilon-transit, and it has only one destination. */ org_dest = dfa->edests[org_node].elems[0]; re_node_set_empty (dfa->edests + clone_node); if (dfa->nodes[org_node].type == ANCHOR) { /* In case of the node has another constraint, append it. */ if (org_node == root_node && clone_node != org_node) { /* ...but if the node is root_node itself, it means the epsilon closure have a loop, then tie it to the destination of the root_node. */ ret = re_node_set_insert (dfa->edests + clone_node, org_dest); if (BE (ret < 0, 0)) return REG_ESPACE; break; } constraint |= dfa->nodes[org_node].opr.ctx_type; } clone_dest = duplicate_node (dfa, org_dest, constraint); if (BE (clone_dest == -1, 0)) return REG_ESPACE; ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); if (BE (ret < 0, 0)) return REG_ESPACE; } else /* dfa->edests[org_node].nelem == 2 */ { /* In case of the node can epsilon-transit, and it has two destinations. In the bin_tree_t and DFA, that's '|' and '*'. */ org_dest = dfa->edests[org_node].elems[0]; re_node_set_empty (dfa->edests + clone_node); /* Search for a duplicated node which satisfies the constraint. */ clone_dest = search_duplicated_node (dfa, org_dest, constraint); if (clone_dest == -1) { /* There are no such a duplicated node, create a new one. */ reg_errcode_t err; clone_dest = duplicate_node (dfa, org_dest, constraint); if (BE (clone_dest == -1, 0)) return REG_ESPACE; ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); if (BE (ret < 0, 0)) return REG_ESPACE; err = duplicate_node_closure (dfa, org_dest, clone_dest, root_node, constraint); if (BE (err != REG_NOERROR, 0)) return err; } else { /* There are a duplicated node which satisfy the constraint, use it to avoid infinite loop. */ ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); if (BE (ret < 0, 0)) return REG_ESPACE; } org_dest = dfa->edests[org_node].elems[1]; clone_dest = duplicate_node (dfa, org_dest, constraint); if (BE (clone_dest == -1, 0)) return REG_ESPACE; ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); if (BE (ret < 0, 0)) return REG_ESPACE; } org_node = org_dest; clone_node = clone_dest; } return REG_NOERROR; } /* Search for a node which is duplicated from the node ORG_NODE, and satisfies the constraint CONSTRAINT. */ static int search_duplicated_node (const re_dfa_t *dfa, int org_node, unsigned int constraint) { int idx; for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx) { if (org_node == dfa->org_indices[idx] && constraint == dfa->nodes[idx].constraint) return idx; /* Found. */ } return -1; /* Not found. */ } /* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT. Return the index of the new node, or -1 if insufficient storage is available. */ static int duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint) { int dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]); if (BE (dup_idx != -1, 1)) { dfa->nodes[dup_idx].constraint = constraint; if (dfa->nodes[org_idx].type == ANCHOR) dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].opr.ctx_type; dfa->nodes[dup_idx].duplicated = 1; /* Store the index of the original node. */ dfa->org_indices[dup_idx] = org_idx; } return dup_idx; } static reg_errcode_t calc_inveclosure (re_dfa_t *dfa) { int src, idx, ret; for (idx = 0; idx < dfa->nodes_len; ++idx) re_node_set_init_empty (dfa->inveclosures + idx); for (src = 0; src < dfa->nodes_len; ++src) { int *elems = dfa->eclosures[src].elems; for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx) { ret = re_node_set_insert_last (dfa->inveclosures + elems[idx], src); if (BE (ret == -1, 0)) return REG_ESPACE; } } return REG_NOERROR; } /* Calculate "eclosure" for all the node in DFA. */ static reg_errcode_t calc_eclosure (re_dfa_t *dfa) { int node_idx, incomplete; #ifdef DEBUG assert (dfa->nodes_len > 0); #endif incomplete = 0; /* For each nodes, calculate epsilon closure. */ for (node_idx = 0; ; ++node_idx) { reg_errcode_t err; re_node_set eclosure_elem; if (node_idx == dfa->nodes_len) { if (!incomplete) break; incomplete = 0; node_idx = 0; } #ifdef DEBUG assert (dfa->eclosures[node_idx].nelem != -1); #endif /* If we have already calculated, skip it. */ if (dfa->eclosures[node_idx].nelem != 0) continue; /* Calculate epsilon closure of `node_idx'. */ err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, 1); if (BE (err != REG_NOERROR, 0)) return err; if (dfa->eclosures[node_idx].nelem == 0) { incomplete = 1; re_node_set_free (&eclosure_elem); } } return REG_NOERROR; } /* Calculate epsilon closure of NODE. */ static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root) { reg_errcode_t err; unsigned int constraint; int i, incomplete; re_node_set eclosure; incomplete = 0; err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1); if (BE (err != REG_NOERROR, 0)) return err; /* This indicates that we are calculating this node now. We reference this value to avoid infinite loop. */ dfa->eclosures[node].nelem = -1; constraint = ((dfa->nodes[node].type == ANCHOR) ? dfa->nodes[node].opr.ctx_type : 0); /* If the current node has constraints, duplicate all nodes. Since they must inherit the constraints. */ if (constraint && dfa->edests[node].nelem && !dfa->nodes[dfa->edests[node].elems[0]].duplicated) { err = duplicate_node_closure (dfa, node, node, node, constraint); if (BE (err != REG_NOERROR, 0)) return err; } /* Expand each epsilon destination nodes. */ if (IS_EPSILON_NODE(dfa->nodes[node].type)) for (i = 0; i < dfa->edests[node].nelem; ++i) { re_node_set eclosure_elem; int edest = dfa->edests[node].elems[i]; /* If calculating the epsilon closure of `edest' is in progress, return intermediate result. */ if (dfa->eclosures[edest].nelem == -1) { incomplete = 1; continue; } /* If we haven't calculated the epsilon closure of `edest' yet, calculate now. Otherwise use calculated epsilon closure. */ if (dfa->eclosures[edest].nelem == 0) { err = calc_eclosure_iter (&eclosure_elem, dfa, edest, 0); if (BE (err != REG_NOERROR, 0)) return err; } else eclosure_elem = dfa->eclosures[edest]; /* Merge the epsilon closure of `edest'. */ re_node_set_merge (&eclosure, &eclosure_elem); /* If the epsilon closure of `edest' is incomplete, the epsilon closure of this node is also incomplete. */ if (dfa->eclosures[edest].nelem == 0) { incomplete = 1; re_node_set_free (&eclosure_elem); } } /* Epsilon closures include itself. */ re_node_set_insert (&eclosure, node); if (incomplete && !root) dfa->eclosures[node].nelem = 0; else dfa->eclosures[node] = eclosure; *new_set = eclosure; return REG_NOERROR; } /* Functions for token which are used in the parser. */ /* Fetch a token from INPUT. We must not use this function inside bracket expressions. */ static void internal_function fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax) { re_string_skip_bytes (input, peek_token (result, input, syntax)); } /* Peek a token from INPUT, and return the length of the token. We must not use this function inside bracket expressions. */ static int internal_function peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) { unsigned char c; if (re_string_eoi (input)) { token->type = END_OF_RE; return 0; } c = re_string_peek_byte (input, 0); token->opr.c = c; token->word_char = 0; #ifdef RE_ENABLE_I18N token->mb_partial = 0; if (input->mb_cur_max > 1 && !re_string_first_byte (input, re_string_cur_idx (input))) { token->type = CHARACTER; token->mb_partial = 1; return 1; } #endif if (c == '\\') { unsigned char c2; if (re_string_cur_idx (input) + 1 >= re_string_length (input)) { token->type = BACK_SLASH; return 1; } c2 = re_string_peek_byte_case (input, 1); token->opr.c = c2; token->type = CHARACTER; #ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1) { wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input) + 1); token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; } else #endif token->word_char = IS_WORD_CHAR (c2) != 0; switch (c2) { case '|': if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR)) token->type = OP_ALT; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (!(syntax & RE_NO_BK_REFS)) { token->type = OP_BACK_REF; token->opr.idx = c2 - '1'; } break; case '<': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = WORD_FIRST; } break; case '>': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = WORD_LAST; } break; case 'b': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = WORD_DELIM; } break; case 'B': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = NOT_WORD_DELIM; } break; case 'w': if (!(syntax & RE_NO_GNU_OPS)) token->type = OP_WORD; break; case 'W': if (!(syntax & RE_NO_GNU_OPS)) token->type = OP_NOTWORD; break; case 's': if (!(syntax & RE_NO_GNU_OPS)) token->type = OP_SPACE; break; case 'S': if (!(syntax & RE_NO_GNU_OPS)) token->type = OP_NOTSPACE; break; case '`': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = BUF_FIRST; } break; case '\'': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = BUF_LAST; } break; case '(': if (!(syntax & RE_NO_BK_PARENS)) token->type = OP_OPEN_SUBEXP; break; case ')': if (!(syntax & RE_NO_BK_PARENS)) token->type = OP_CLOSE_SUBEXP; break; case '+': if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) token->type = OP_DUP_PLUS; break; case '?': if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) token->type = OP_DUP_QUESTION; break; case '{': if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) token->type = OP_OPEN_DUP_NUM; break; case '}': if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) token->type = OP_CLOSE_DUP_NUM; break; default: break; } return 2; } token->type = CHARACTER; #ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1) { wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input)); token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; } else #endif token->word_char = IS_WORD_CHAR (token->opr.c); switch (c) { case '\n': if (syntax & RE_NEWLINE_ALT) token->type = OP_ALT; break; case '|': if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR)) token->type = OP_ALT; break; case '*': token->type = OP_DUP_ASTERISK; break; case '+': if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) token->type = OP_DUP_PLUS; break; case '?': if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) token->type = OP_DUP_QUESTION; break; case '{': if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) token->type = OP_OPEN_DUP_NUM; break; case '}': if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) token->type = OP_CLOSE_DUP_NUM; break; case '(': if (syntax & RE_NO_BK_PARENS) token->type = OP_OPEN_SUBEXP; break; case ')': if (syntax & RE_NO_BK_PARENS) token->type = OP_CLOSE_SUBEXP; break; case '[': token->type = OP_OPEN_BRACKET; break; case '.': token->type = OP_PERIOD; break; case '^': if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) && re_string_cur_idx (input) != 0) { char prev = re_string_peek_byte (input, -1); if (!(syntax & RE_NEWLINE_ALT) || prev != '\n') break; } token->type = ANCHOR; token->opr.ctx_type = LINE_FIRST; break; case '$': if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) && re_string_cur_idx (input) + 1 != re_string_length (input)) { re_token_t next; re_string_skip_bytes (input, 1); peek_token (&next, input, syntax); re_string_skip_bytes (input, -1); if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP) break; } token->type = ANCHOR; token->opr.ctx_type = LINE_LAST; break; default: break; } return 1; } /* Peek a token from INPUT, and return the length of the token. We must not use this function out of bracket expressions. */ static int internal_function peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) { unsigned char c; if (re_string_eoi (input)) { token->type = END_OF_RE; return 0; } c = re_string_peek_byte (input, 0); token->opr.c = c; #ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1 && !re_string_first_byte (input, re_string_cur_idx (input))) { token->type = CHARACTER; return 1; } #endif /* RE_ENABLE_I18N */ if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && re_string_cur_idx (input) + 1 < re_string_length (input)) { /* In this case, '\' escape a character. */ unsigned char c2; re_string_skip_bytes (input, 1); c2 = re_string_peek_byte (input, 0); token->opr.c = c2; token->type = CHARACTER; return 1; } if (c == '[') /* '[' is a special char in a bracket exps. */ { unsigned char c2; int token_len; if (re_string_cur_idx (input) + 1 < re_string_length (input)) c2 = re_string_peek_byte (input, 1); else c2 = 0; token->opr.c = c2; token_len = 2; switch (c2) { case '.': token->type = OP_OPEN_COLL_ELEM; break; case '=': token->type = OP_OPEN_EQUIV_CLASS; break; case ':': if (syntax & RE_CHAR_CLASSES) { token->type = OP_OPEN_CHAR_CLASS; break; } /* else fall through. */ default: token->type = CHARACTER; token->opr.c = c; token_len = 1; break; } return token_len; } switch (c) { case '-': token->type = OP_CHARSET_RANGE; break; case ']': token->type = OP_CLOSE_BRACKET; break; case '^': token->type = OP_NON_MATCH_LIST; break; default: token->type = CHARACTER; } return 1; } /* Functions for parser. */ /* Entry point of the parser. Parse the regular expression REGEXP and return the structure tree. If an error is occured, ERR is set by error code, and return NULL. This function build the following tree, from regular expression : CAT / \ / \ EOR CAT means concatenation. EOR means end of regular expression. */ static bin_tree_t * parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, reg_errcode_t *err) { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_t *tree, *eor, *root; re_token_t current_token; dfa->syntax = syntax; fetch_token (¤t_token, regexp, syntax | RE_CARET_ANCHORS_HERE); tree = parse_reg_exp (regexp, preg, ¤t_token, syntax, 0, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; eor = create_tree (dfa, NULL, NULL, END_OF_RE); if (tree != NULL) root = create_tree (dfa, tree, eor, CONCAT); else root = eor; if (BE (eor == NULL || root == NULL, 0)) { *err = REG_ESPACE; return NULL; } return root; } /* This function build the following tree, from regular expression |: ALT / \ / \ ALT means alternative, which represents the operator `|'. */ static bin_tree_t * parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err) { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_t *tree, *branch = NULL; tree = parse_branch (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; while (token->type == OP_ALT) { fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); if (token->type != OP_ALT && token->type != END_OF_RE && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) { branch = parse_branch (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && branch == NULL, 0)) return NULL; } else branch = NULL; tree = create_tree (dfa, tree, branch, OP_ALT); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } } return tree; } /* This function build the following tree, from regular expression : CAT / \ / \ CAT means concatenation. */ static bin_tree_t * parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err) { bin_tree_t *tree, *exp; re_dfa_t *dfa = (re_dfa_t *) preg->buffer; tree = parse_expression (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; while (token->type != OP_ALT && token->type != END_OF_RE && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) { exp = parse_expression (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && exp == NULL, 0)) { return NULL; } if (tree != NULL && exp != NULL) { tree = create_tree (dfa, tree, exp, CONCAT); if (tree == NULL) { *err = REG_ESPACE; return NULL; } } else if (tree == NULL) tree = exp; /* Otherwise exp == NULL, we don't need to create new tree. */ } return tree; } /* This function build the following tree, from regular expression a*: * | a */ static bin_tree_t * parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err) { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_t *tree; switch (token->type) { case CHARACTER: tree = create_token_tree (dfa, NULL, NULL, token); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { while (!re_string_eoi (regexp) && !re_string_first_byte (regexp, re_string_cur_idx (regexp))) { bin_tree_t *mbc_remain; fetch_token (token, regexp, syntax); mbc_remain = create_token_tree (dfa, NULL, NULL, token); tree = create_tree (dfa, tree, mbc_remain, CONCAT); if (BE (mbc_remain == NULL || tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } } } #endif break; case OP_OPEN_SUBEXP: tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; break; case OP_OPEN_BRACKET: tree = parse_bracket_exp (regexp, dfa, token, syntax, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; break; case OP_BACK_REF: if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1)) { *err = REG_ESUBREG; return NULL; } dfa->used_bkref_map |= 1 << token->opr.idx; tree = create_token_tree (dfa, NULL, NULL, token); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } ++dfa->nbackref; dfa->has_mb_node = 1; break; case OP_OPEN_DUP_NUM: if (syntax & RE_CONTEXT_INVALID_DUP) { *err = REG_BADRPT; return NULL; } /* FALLTHROUGH */ case OP_DUP_ASTERISK: case OP_DUP_PLUS: case OP_DUP_QUESTION: if (syntax & RE_CONTEXT_INVALID_OPS) { *err = REG_BADRPT; return NULL; } else if (syntax & RE_CONTEXT_INDEP_OPS) { fetch_token (token, regexp, syntax); return parse_expression (regexp, preg, token, syntax, nest, err); } /* else fall through */ case OP_CLOSE_SUBEXP: if ((token->type == OP_CLOSE_SUBEXP) && !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)) { *err = REG_ERPAREN; return NULL; } /* else fall through */ case OP_CLOSE_DUP_NUM: /* We treat it as a normal character. */ /* Then we can these characters as normal characters. */ token->type = CHARACTER; /* mb_partial and word_char bits should be initialized already by peek_token. */ tree = create_token_tree (dfa, NULL, NULL, token); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } break; case ANCHOR: if ((token->opr.ctx_type & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST)) && dfa->word_ops_used == 0) init_word_char (dfa); if (token->opr.ctx_type == WORD_DELIM || token->opr.ctx_type == NOT_WORD_DELIM) { bin_tree_t *tree_first, *tree_last; if (token->opr.ctx_type == WORD_DELIM) { token->opr.ctx_type = WORD_FIRST; tree_first = create_token_tree (dfa, NULL, NULL, token); token->opr.ctx_type = WORD_LAST; } else { token->opr.ctx_type = INSIDE_WORD; tree_first = create_token_tree (dfa, NULL, NULL, token); token->opr.ctx_type = INSIDE_NOTWORD; } tree_last = create_token_tree (dfa, NULL, NULL, token); tree = create_tree (dfa, tree_first, tree_last, OP_ALT); if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } } else { tree = create_token_tree (dfa, NULL, NULL, token); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } } /* We must return here, since ANCHORs can't be followed by repetition operators. eg. RE"^*" is invalid or "", it must not be "". */ fetch_token (token, regexp, syntax); return tree; case OP_PERIOD: tree = create_token_tree (dfa, NULL, NULL, token); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } if (dfa->mb_cur_max > 1) dfa->has_mb_node = 1; break; case OP_WORD: case OP_NOTWORD: tree = build_charclass_op (dfa, regexp->trans, (const unsigned char *) "alnum", (const unsigned char *) "_", token->type == OP_NOTWORD, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; break; case OP_SPACE: case OP_NOTSPACE: tree = build_charclass_op (dfa, regexp->trans, (const unsigned char *) "space", (const unsigned char *) "", token->type == OP_NOTSPACE, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; break; case OP_ALT: case END_OF_RE: return NULL; case BACK_SLASH: *err = REG_EESCAPE; return NULL; default: /* Must not happen? */ #ifdef DEBUG assert (0); #endif return NULL; } fetch_token (token, regexp, syntax); while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM) { tree = parse_dup_op (tree, regexp, dfa, token, syntax, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; /* In BRE consecutive duplications are not allowed. */ if ((syntax & RE_CONTEXT_INVALID_DUP) && (token->type == OP_DUP_ASTERISK || token->type == OP_OPEN_DUP_NUM)) { *err = REG_BADRPT; return NULL; } } return tree; } /* This function build the following tree, from regular expression (): SUBEXP | */ static bin_tree_t * parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err) { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_t *tree; size_t cur_nsub; cur_nsub = preg->re_nsub++; fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); /* The subexpression may be a null string. */ if (token->type == OP_CLOSE_SUBEXP) tree = NULL; else { tree = parse_reg_exp (regexp, preg, token, syntax, nest, err); if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0)) *err = REG_EPAREN; if (BE (*err != REG_NOERROR, 0)) return NULL; } if (cur_nsub <= '9' - '1') dfa->completed_bkref_map |= 1 << cur_nsub; tree = create_tree (dfa, tree, NULL, SUBEXP); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } tree->token.opr.idx = cur_nsub; return tree; } /* This function parse repetition operators like "*", "+", "{1,3}" etc. */ static bin_tree_t * parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err) { bin_tree_t *tree = NULL, *old_tree = NULL; int i, start, end, start_idx = re_string_cur_idx (regexp); re_token_t start_token = *token; if (token->type == OP_OPEN_DUP_NUM) { end = 0; start = fetch_number (regexp, token, syntax); if (start == -1) { if (token->type == CHARACTER && token->opr.c == ',') start = 0; /* We treat "{,m}" as "{0,m}". */ else { *err = REG_BADBR; /* {} is invalid. */ return NULL; } } if (BE (start != -2, 1)) { /* We treat "{n}" as "{n,n}". */ end = ((token->type == OP_CLOSE_DUP_NUM) ? start : ((token->type == CHARACTER && token->opr.c == ',') ? fetch_number (regexp, token, syntax) : -2)); } if (BE (start == -2 || end == -2, 0)) { /* Invalid sequence. */ if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0)) { if (token->type == END_OF_RE) *err = REG_EBRACE; else *err = REG_BADBR; return NULL; } /* If the syntax bit is set, rollback. */ re_string_set_index (regexp, start_idx); *token = start_token; token->type = CHARACTER; /* mb_partial and word_char bits should be already initialized by peek_token. */ return elem; } if (BE (end != -1 && start > end, 0)) { /* First number greater than second. */ *err = REG_BADBR; return NULL; } } else { start = (token->type == OP_DUP_PLUS) ? 1 : 0; end = (token->type == OP_DUP_QUESTION) ? 1 : -1; } fetch_token (token, regexp, syntax); if (BE (elem == NULL, 0)) return NULL; if (BE (start == 0 && end == 0, 0)) { postorder (elem, free_tree, NULL); return NULL; } /* Extract "{n,m}" to "...{0,}". */ if (BE (start > 0, 0)) { tree = elem; for (i = 2; i <= start; ++i) { elem = duplicate_tree (elem, dfa); tree = create_tree (dfa, tree, elem, CONCAT); if (BE (elem == NULL || tree == NULL, 0)) goto parse_dup_op_espace; } if (start == end) return tree; /* Duplicate ELEM before it is marked optional. */ elem = duplicate_tree (elem, dfa); old_tree = tree; } else old_tree = NULL; if (elem->token.type == SUBEXP) postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx); tree = create_tree (dfa, elem, NULL, (end == -1 ? OP_DUP_ASTERISK : OP_ALT)); if (BE (tree == NULL, 0)) goto parse_dup_op_espace; /* This loop is actually executed only when end != -1, to rewrite {0,n} as ((...?)?)?... We have already created the start+1-th copy. */ for (i = start + 2; i <= end; ++i) { elem = duplicate_tree (elem, dfa); tree = create_tree (dfa, tree, elem, CONCAT); if (BE (elem == NULL || tree == NULL, 0)) goto parse_dup_op_espace; tree = create_tree (dfa, tree, NULL, OP_ALT); if (BE (tree == NULL, 0)) goto parse_dup_op_espace; } if (old_tree) tree = create_tree (dfa, old_tree, tree, CONCAT); return tree; parse_dup_op_espace: *err = REG_ESPACE; return NULL; } /* Size of the names for collating symbol/equivalence_class/character_class. I'm not sure, but maybe enough. */ #define BRACKET_NAME_BUF_SIZE 32 #ifndef _LIBC /* Local function for parse_bracket_exp only used in case of NOT _LIBC. Build the range expression which starts from START_ELEM, and ends at END_ELEM. The result are written to MBCSET and SBCSET. RANGE_ALLOC is the allocated size of mbcset->range_starts, and mbcset->range_ends, is a pointer argument sinse we may update it. */ static reg_errcode_t internal_function # ifdef RE_ENABLE_I18N build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc, bracket_elem_t *start_elem, bracket_elem_t *end_elem) # else /* not RE_ENABLE_I18N */ build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem, bracket_elem_t *end_elem) # endif /* not RE_ENABLE_I18N */ { unsigned int start_ch, end_ch; /* Equivalence Classes and Character Classes can't be a range start/end. */ if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, 0)) return REG_ERANGE; /* We can handle no multi character collating elements without libc support. */ if (BE ((start_elem->type == COLL_SYM && strlen ((char *) start_elem->opr.name) > 1) || (end_elem->type == COLL_SYM && strlen ((char *) end_elem->opr.name) > 1), 0)) return REG_ECOLLATE; # ifdef RE_ENABLE_I18N { wchar_t wc; wint_t start_wc; wint_t end_wc; wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] : 0)); end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] : 0)); start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM) ? __btowc (start_ch) : start_elem->opr.wch); end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM) ? __btowc (end_ch) : end_elem->opr.wch); if (start_wc == WEOF || end_wc == WEOF) return REG_ECOLLATE; cmp_buf[0] = start_wc; cmp_buf[4] = end_wc; if (wcscoll (cmp_buf, cmp_buf + 4) > 0) return REG_ERANGE; /* Got valid collation sequence values, add them as a new entry. However, for !_LIBC we have no collation elements: if the character set is single byte, the single byte character set that we build below suffices. parse_bracket_exp passes no MBCSET if dfa->mb_cur_max == 1. */ if (mbcset) { /* Check the space of the arrays. */ if (BE (*range_alloc == mbcset->nranges, 0)) { /* There is not enough space, need realloc. */ wchar_t *new_array_start, *new_array_end; int new_nranges; /* +1 in case of mbcset->nranges is 0. */ new_nranges = 2 * mbcset->nranges + 1; /* Use realloc since mbcset->range_starts and mbcset->range_ends are NULL if *range_alloc == 0. */ new_array_start = re_realloc (mbcset->range_starts, wchar_t, new_nranges); new_array_end = re_realloc (mbcset->range_ends, wchar_t, new_nranges); if (BE (new_array_start == NULL || new_array_end == NULL, 0)) return REG_ESPACE; mbcset->range_starts = new_array_start; mbcset->range_ends = new_array_end; *range_alloc = new_nranges; } mbcset->range_starts[mbcset->nranges] = start_wc; mbcset->range_ends[mbcset->nranges++] = end_wc; } /* Build the table for single byte characters. */ for (wc = 0; wc < SBC_MAX; ++wc) { cmp_buf[2] = wc; if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) bitset_set (sbcset, wc); } } # else /* not RE_ENABLE_I18N */ { unsigned int ch; start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] : 0)); end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] : 0)); if (start_ch > end_ch) return REG_ERANGE; /* Build the table for single byte characters. */ for (ch = 0; ch < SBC_MAX; ++ch) if (start_ch <= ch && ch <= end_ch) bitset_set (sbcset, ch); } # endif /* not RE_ENABLE_I18N */ return REG_NOERROR; } #endif /* not _LIBC */ #ifndef _LIBC /* Helper function for parse_bracket_exp only used in case of NOT _LIBC.. Build the collating element which is represented by NAME. The result are written to MBCSET and SBCSET. COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a pointer argument since we may update it. */ static reg_errcode_t internal_function # ifdef RE_ENABLE_I18N build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, int *coll_sym_alloc, const unsigned char *name) # else /* not RE_ENABLE_I18N */ build_collating_symbol (bitset_t sbcset, const unsigned char *name) # endif /* not RE_ENABLE_I18N */ { size_t name_len = strlen ((const char *) name); if (BE (name_len != 1, 0)) return REG_ECOLLATE; else { bitset_set (sbcset, name[0]); return REG_NOERROR; } } #endif /* not _LIBC */ /* This function parse bracket expression like "[abc]", "[a-c]", "[[.a-a.]]" etc. */ static bin_tree_t * parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err) { #ifdef _LIBC const unsigned char *collseqmb; const char *collseqwc; uint32_t nrules; int32_t table_size; const int32_t *symb_table; const unsigned char *extra; /* Local function for parse_bracket_exp used in _LIBC environement. Seek the collating symbol entry correspondings to NAME. Return the index of the symbol in the SYMB_TABLE. */ auto inline int32_t __attribute ((always_inline)) seek_collating_symbol_entry (name, name_len) const unsigned char *name; size_t name_len; { int32_t hash = elem_hash ((const char *) name, name_len); int32_t elem = hash % table_size; if (symb_table[2 * elem] != 0) { int32_t second = hash % (table_size - 2) + 1; do { /* First compare the hashing value. */ if (symb_table[2 * elem] == hash /* Compare the length of the name. */ && name_len == extra[symb_table[2 * elem + 1]] /* Compare the name. */ && memcmp (name, &extra[symb_table[2 * elem + 1] + 1], name_len) == 0) { /* Yep, this is the entry. */ break; } /* Next entry. */ elem += second; } while (symb_table[2 * elem] != 0); } return elem; } /* Local function for parse_bracket_exp used in _LIBC environement. Look up the collation sequence value of BR_ELEM. Return the value if succeeded, UINT_MAX otherwise. */ auto inline unsigned int __attribute ((always_inline)) lookup_collation_sequence_value (br_elem) bracket_elem_t *br_elem; { if (br_elem->type == SB_CHAR) { /* if (MB_CUR_MAX == 1) */ if (nrules == 0) return collseqmb[br_elem->opr.ch]; else { wint_t wc = __btowc (br_elem->opr.ch); return __collseq_table_lookup (collseqwc, wc); } } else if (br_elem->type == MB_CHAR) { return __collseq_table_lookup (collseqwc, br_elem->opr.wch); } else if (br_elem->type == COLL_SYM) { size_t sym_name_len = strlen ((char *) br_elem->opr.name); if (nrules != 0) { int32_t elem, idx; elem = seek_collating_symbol_entry (br_elem->opr.name, sym_name_len); if (symb_table[2 * elem] != 0) { /* We found the entry. */ idx = symb_table[2 * elem + 1]; /* Skip the name of collating element name. */ idx += 1 + extra[idx]; /* Skip the byte sequence of the collating element. */ idx += 1 + extra[idx]; /* Adjust for the alignment. */ idx = (idx + 3) & ~3; /* Skip the multibyte collation sequence value. */ idx += sizeof (unsigned int); /* Skip the wide char sequence of the collating element. */ idx += sizeof (unsigned int) * (1 + *(unsigned int *) (extra + idx)); /* Return the collation sequence value. */ return *(unsigned int *) (extra + idx); } else if (symb_table[2 * elem] == 0 && sym_name_len == 1) { /* No valid character. Match it as a single byte character. */ return collseqmb[br_elem->opr.name[0]]; } } else if (sym_name_len == 1) return collseqmb[br_elem->opr.name[0]]; } return UINT_MAX; } /* Local function for parse_bracket_exp used in _LIBC environement. Build the range expression which starts from START_ELEM, and ends at END_ELEM. The result are written to MBCSET and SBCSET. RANGE_ALLOC is the allocated size of mbcset->range_starts, and mbcset->range_ends, is a pointer argument sinse we may update it. */ auto inline reg_errcode_t __attribute ((always_inline)) build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem) re_charset_t *mbcset; int *range_alloc; bitset_t sbcset; bracket_elem_t *start_elem, *end_elem; { unsigned int ch; uint32_t start_collseq; uint32_t end_collseq; /* Equivalence Classes and Character Classes can't be a range start/end. */ if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, 0)) return REG_ERANGE; start_collseq = lookup_collation_sequence_value (start_elem); end_collseq = lookup_collation_sequence_value (end_elem); /* Check start/end collation sequence values. */ if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0)) return REG_ECOLLATE; if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0)) return REG_ERANGE; /* Got valid collation sequence values, add them as a new entry. However, if we have no collation elements, and the character set is single byte, the single byte character set that we build below suffices. */ if (nrules > 0 || dfa->mb_cur_max > 1) { /* Check the space of the arrays. */ if (BE (*range_alloc == mbcset->nranges, 0)) { /* There is not enough space, need realloc. */ uint32_t *new_array_start; uint32_t *new_array_end; int new_nranges; /* +1 in case of mbcset->nranges is 0. */ new_nranges = 2 * mbcset->nranges + 1; new_array_start = re_realloc (mbcset->range_starts, uint32_t, new_nranges); new_array_end = re_realloc (mbcset->range_ends, uint32_t, new_nranges); if (BE (new_array_start == NULL || new_array_end == NULL, 0)) return REG_ESPACE; mbcset->range_starts = new_array_start; mbcset->range_ends = new_array_end; *range_alloc = new_nranges; } mbcset->range_starts[mbcset->nranges] = start_collseq; mbcset->range_ends[mbcset->nranges++] = end_collseq; } /* Build the table for single byte characters. */ for (ch = 0; ch < SBC_MAX; ch++) { uint32_t ch_collseq; /* if (MB_CUR_MAX == 1) */ if (nrules == 0) ch_collseq = collseqmb[ch]; else ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) bitset_set (sbcset, ch); } return REG_NOERROR; } /* Local function for parse_bracket_exp used in _LIBC environement. Build the collating element which is represented by NAME. The result are written to MBCSET and SBCSET. COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a pointer argument sinse we may update it. */ auto inline reg_errcode_t __attribute ((always_inline)) build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name) re_charset_t *mbcset; int *coll_sym_alloc; bitset_t sbcset; const unsigned char *name; { int32_t elem, idx; size_t name_len = strlen ((const char *) name); if (nrules != 0) { elem = seek_collating_symbol_entry (name, name_len); if (symb_table[2 * elem] != 0) { /* We found the entry. */ idx = symb_table[2 * elem + 1]; /* Skip the name of collating element name. */ idx += 1 + extra[idx]; } else if (symb_table[2 * elem] == 0 && name_len == 1) { /* No valid character, treat it as a normal character. */ bitset_set (sbcset, name[0]); return REG_NOERROR; } else return REG_ECOLLATE; /* Got valid collation sequence, add it as a new entry. */ /* Check the space of the arrays. */ if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0)) { /* Not enough, realloc it. */ /* +1 in case of mbcset->ncoll_syms is 0. */ int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1; /* Use realloc since mbcset->coll_syms is NULL if *alloc == 0. */ int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t, new_coll_sym_alloc); if (BE (new_coll_syms == NULL, 0)) return REG_ESPACE; mbcset->coll_syms = new_coll_syms; *coll_sym_alloc = new_coll_sym_alloc; } mbcset->coll_syms[mbcset->ncoll_syms++] = idx; return REG_NOERROR; } else { if (BE (name_len != 1, 0)) return REG_ECOLLATE; else { bitset_set (sbcset, name[0]); return REG_NOERROR; } } } #endif re_token_t br_token; re_bitset_ptr_t sbcset; #ifdef RE_ENABLE_I18N re_charset_t *mbcset; int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0; int equiv_class_alloc = 0, char_class_alloc = 0; #endif /* not RE_ENABLE_I18N */ int non_match = 0; bin_tree_t *work_tree; int token_len; int first_round = 1; #ifdef _LIBC collseqmb = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules) { /* if (MB_CUR_MAX > 1) */ collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB); symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_TABLEMB); extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); } #endif sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); #ifdef RE_ENABLE_I18N mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); #endif /* RE_ENABLE_I18N */ #ifdef RE_ENABLE_I18N if (BE (sbcset == NULL || mbcset == NULL, 0)) #else if (BE (sbcset == NULL, 0)) #endif /* RE_ENABLE_I18N */ { *err = REG_ESPACE; return NULL; } token_len = peek_token_bracket (token, regexp, syntax); if (BE (token->type == END_OF_RE, 0)) { *err = REG_BADPAT; goto parse_bracket_exp_free_return; } if (token->type == OP_NON_MATCH_LIST) { #ifdef RE_ENABLE_I18N mbcset->non_match = 1; #endif /* not RE_ENABLE_I18N */ non_match = 1; if (syntax & RE_HAT_LISTS_NOT_NEWLINE) bitset_set (sbcset, '\0'); re_string_skip_bytes (regexp, token_len); /* Skip a token. */ token_len = peek_token_bracket (token, regexp, syntax); if (BE (token->type == END_OF_RE, 0)) { *err = REG_BADPAT; goto parse_bracket_exp_free_return; } } /* We treat the first ']' as a normal character. */ if (token->type == OP_CLOSE_BRACKET) token->type = CHARACTER; while (1) { bracket_elem_t start_elem, end_elem; unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE]; unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE]; reg_errcode_t ret; int token_len2 = 0, is_range_exp = 0; re_token_t token2; start_elem.opr.name = start_name_buf; ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa, syntax, first_round); if (BE (ret != REG_NOERROR, 0)) { *err = ret; goto parse_bracket_exp_free_return; } first_round = 0; /* Get information about the next token. We need it in any case. */ token_len = peek_token_bracket (token, regexp, syntax); /* Do not check for ranges if we know they are not allowed. */ if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS) { if (BE (token->type == END_OF_RE, 0)) { *err = REG_EBRACK; goto parse_bracket_exp_free_return; } if (token->type == OP_CHARSET_RANGE) { re_string_skip_bytes (regexp, token_len); /* Skip '-'. */ token_len2 = peek_token_bracket (&token2, regexp, syntax); if (BE (token2.type == END_OF_RE, 0)) { *err = REG_EBRACK; goto parse_bracket_exp_free_return; } if (token2.type == OP_CLOSE_BRACKET) { /* We treat the last '-' as a normal character. */ re_string_skip_bytes (regexp, -token_len); token->type = CHARACTER; } else is_range_exp = 1; } } if (is_range_exp == 1) { end_elem.opr.name = end_name_buf; ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2, dfa, syntax, 1); if (BE (ret != REG_NOERROR, 0)) { *err = ret; goto parse_bracket_exp_free_return; } token_len = peek_token_bracket (token, regexp, syntax); #ifdef _LIBC *err = build_range_exp (sbcset, mbcset, &range_alloc, &start_elem, &end_elem); #else # ifdef RE_ENABLE_I18N *err = build_range_exp (sbcset, dfa->mb_cur_max > 1 ? mbcset : NULL, &range_alloc, &start_elem, &end_elem); # else *err = build_range_exp (sbcset, &start_elem, &end_elem); # endif #endif /* RE_ENABLE_I18N */ if (BE (*err != REG_NOERROR, 0)) goto parse_bracket_exp_free_return; } else { switch (start_elem.type) { case SB_CHAR: bitset_set (sbcset, start_elem.opr.ch); break; #ifdef RE_ENABLE_I18N case MB_CHAR: /* Check whether the array has enough space. */ if (BE (mbchar_alloc == mbcset->nmbchars, 0)) { wchar_t *new_mbchars; /* Not enough, realloc it. */ /* +1 in case of mbcset->nmbchars is 0. */ mbchar_alloc = 2 * mbcset->nmbchars + 1; /* Use realloc since array is NULL if *alloc == 0. */ new_mbchars = re_realloc (mbcset->mbchars, wchar_t, mbchar_alloc); if (BE (new_mbchars == NULL, 0)) goto parse_bracket_exp_espace; mbcset->mbchars = new_mbchars; } mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch; break; #endif /* RE_ENABLE_I18N */ case EQUIV_CLASS: *err = build_equiv_class (sbcset, #ifdef RE_ENABLE_I18N mbcset, &equiv_class_alloc, #endif /* RE_ENABLE_I18N */ start_elem.opr.name); if (BE (*err != REG_NOERROR, 0)) goto parse_bracket_exp_free_return; break; case COLL_SYM: *err = build_collating_symbol (sbcset, #ifdef RE_ENABLE_I18N mbcset, &coll_sym_alloc, #endif /* RE_ENABLE_I18N */ start_elem.opr.name); if (BE (*err != REG_NOERROR, 0)) goto parse_bracket_exp_free_return; break; case CHAR_CLASS: *err = build_charclass (regexp->trans, sbcset, #ifdef RE_ENABLE_I18N mbcset, &char_class_alloc, #endif /* RE_ENABLE_I18N */ start_elem.opr.name, syntax); if (BE (*err != REG_NOERROR, 0)) goto parse_bracket_exp_free_return; break; default: assert (0); break; } } if (BE (token->type == END_OF_RE, 0)) { *err = REG_EBRACK; goto parse_bracket_exp_free_return; } if (token->type == OP_CLOSE_BRACKET) break; } re_string_skip_bytes (regexp, token_len); /* Skip a token. */ /* If it is non-matching list. */ if (non_match) bitset_not (sbcset); #ifdef RE_ENABLE_I18N /* Ensure only single byte characters are set. */ if (dfa->mb_cur_max > 1) bitset_mask (sbcset, dfa->sb_char); if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes || mbcset->non_match))) { bin_tree_t *mbc_tree; int sbc_idx; /* Build a tree for complex bracket. */ dfa->has_mb_node = 1; br_token.type = COMPLEX_BRACKET; br_token.opr.mbcset = mbcset; mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); if (BE (mbc_tree == NULL, 0)) goto parse_bracket_exp_espace; for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx) if (sbcset[sbc_idx]) break; /* If there are no bits set in sbcset, there is no point of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */ if (sbc_idx < BITSET_WORDS) { /* Build a tree for simple bracket. */ br_token.type = SIMPLE_BRACKET; br_token.opr.sbcset = sbcset; work_tree = create_token_tree (dfa, NULL, NULL, &br_token); if (BE (work_tree == NULL, 0)) goto parse_bracket_exp_espace; /* Then join them by ALT node. */ work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT); if (BE (work_tree == NULL, 0)) goto parse_bracket_exp_espace; } else { re_free (sbcset); work_tree = mbc_tree; } } else #endif /* not RE_ENABLE_I18N */ { #ifdef RE_ENABLE_I18N free_charset (mbcset); #endif /* Build a tree for simple bracket. */ br_token.type = SIMPLE_BRACKET; br_token.opr.sbcset = sbcset; work_tree = create_token_tree (dfa, NULL, NULL, &br_token); if (BE (work_tree == NULL, 0)) goto parse_bracket_exp_espace; } return work_tree; parse_bracket_exp_espace: *err = REG_ESPACE; parse_bracket_exp_free_return: re_free (sbcset); #ifdef RE_ENABLE_I18N free_charset (mbcset); #endif /* RE_ENABLE_I18N */ return NULL; } /* Parse an element in the bracket expression. */ static reg_errcode_t parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, re_token_t *token, int token_len, re_dfa_t *dfa, reg_syntax_t syntax, int accept_hyphen) { #ifdef RE_ENABLE_I18N int cur_char_size; cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp)); if (cur_char_size > 1) { elem->type = MB_CHAR; elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp)); re_string_skip_bytes (regexp, cur_char_size); return REG_NOERROR; } #endif /* RE_ENABLE_I18N */ re_string_skip_bytes (regexp, token_len); /* Skip a token. */ if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS || token->type == OP_OPEN_EQUIV_CLASS) return parse_bracket_symbol (elem, regexp, token); if (BE (token->type == OP_CHARSET_RANGE, 0) && !accept_hyphen) { /* A '-' must only appear as anything but a range indicator before the closing bracket. Everything else is an error. */ re_token_t token2; (void) peek_token_bracket (&token2, regexp, syntax); if (token2.type != OP_CLOSE_BRACKET) /* The actual error value is not standardized since this whole case is undefined. But ERANGE makes good sense. */ return REG_ERANGE; } elem->type = SB_CHAR; elem->opr.ch = token->opr.c; return REG_NOERROR; } /* Parse a bracket symbol in the bracket expression. Bracket symbols are such as [::], [..], and [==]. */ static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, re_token_t *token) { unsigned char ch, delim = token->opr.c; int i = 0; if (re_string_eoi(regexp)) return REG_EBRACK; for (;; ++i) { if (i >= BRACKET_NAME_BUF_SIZE) return REG_EBRACK; if (token->type == OP_OPEN_CHAR_CLASS) ch = re_string_fetch_byte_case (regexp); else ch = re_string_fetch_byte (regexp); if (re_string_eoi(regexp)) return REG_EBRACK; if (ch == delim && re_string_peek_byte (regexp, 0) == ']') break; elem->opr.name[i] = ch; } re_string_skip_bytes (regexp, 1); elem->opr.name[i] = '\0'; switch (token->type) { case OP_OPEN_COLL_ELEM: elem->type = COLL_SYM; break; case OP_OPEN_EQUIV_CLASS: elem->type = EQUIV_CLASS; break; case OP_OPEN_CHAR_CLASS: elem->type = CHAR_CLASS; break; default: break; } return REG_NOERROR; } /* Helper function for parse_bracket_exp. Build the equivalence class which is represented by NAME. The result are written to MBCSET and SBCSET. EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes, is a pointer argument sinse we may update it. */ static reg_errcode_t #ifdef RE_ENABLE_I18N build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, int *equiv_class_alloc, const unsigned char *name) #else /* not RE_ENABLE_I18N */ build_equiv_class (bitset_t sbcset, const unsigned char *name) #endif /* not RE_ENABLE_I18N */ { #ifdef _LIBC uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules != 0) { const int32_t *table, *indirect; const unsigned char *weights, *extra, *cp; unsigned char char_buf[2]; int32_t idx1, idx2; unsigned int ch; size_t len; /* This #include defines a local function! */ # include /* Calculate the index for equivalence class. */ cp = name; table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); idx1 = findidx (&cp); if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0)) /* This isn't a valid character. */ return REG_ECOLLATE; /* Build single byte matcing table for this equivalence class. */ char_buf[1] = (unsigned char) '\0'; len = weights[idx1]; for (ch = 0; ch < SBC_MAX; ++ch) { char_buf[0] = ch; cp = char_buf; idx2 = findidx (&cp); /* idx2 = table[ch]; */ if (idx2 == 0) /* This isn't a valid character. */ continue; if (len == weights[idx2]) { int cnt = 0; while (cnt <= len && weights[idx1 + 1 + cnt] == weights[idx2 + 1 + cnt]) ++cnt; if (cnt > len) bitset_set (sbcset, ch); } } /* Check whether the array has enough space. */ if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0)) { /* Not enough, realloc it. */ /* +1 in case of mbcset->nequiv_classes is 0. */ int new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1; /* Use realloc since the array is NULL if *alloc == 0. */ int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes, int32_t, new_equiv_class_alloc); if (BE (new_equiv_classes == NULL, 0)) return REG_ESPACE; mbcset->equiv_classes = new_equiv_classes; *equiv_class_alloc = new_equiv_class_alloc; } mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1; } else #endif /* _LIBC */ { if (BE (strlen ((const char *) name) != 1, 0)) return REG_ECOLLATE; bitset_set (sbcset, *name); } return REG_NOERROR; } /* Helper function for parse_bracket_exp. Build the character class which is represented by NAME. The result are written to MBCSET and SBCSET. CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes, is a pointer argument sinse we may update it. */ static reg_errcode_t #ifdef RE_ENABLE_I18N build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, re_charset_t *mbcset, int *char_class_alloc, const unsigned char *class_name, reg_syntax_t syntax) #else /* not RE_ENABLE_I18N */ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, const unsigned char *class_name, reg_syntax_t syntax) #endif /* not RE_ENABLE_I18N */ { int i; const char *name = (const char *) class_name; /* In case of REG_ICASE "upper" and "lower" match the both of upper and lower cases. */ if ((syntax & RE_ICASE) && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0)) name = "alpha"; #ifdef RE_ENABLE_I18N /* Check the space of the arrays. */ if (BE (*char_class_alloc == mbcset->nchar_classes, 0)) { /* Not enough, realloc it. */ /* +1 in case of mbcset->nchar_classes is 0. */ int new_char_class_alloc = 2 * mbcset->nchar_classes + 1; /* Use realloc since array is NULL if *alloc == 0. */ wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t, new_char_class_alloc); if (BE (new_char_classes == NULL, 0)) return REG_ESPACE; mbcset->char_classes = new_char_classes; *char_class_alloc = new_char_class_alloc; } mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name); #endif /* RE_ENABLE_I18N */ #define BUILD_CHARCLASS_LOOP(ctype_func) \ do { \ if (BE (trans != NULL, 0)) \ { \ for (i = 0; i < SBC_MAX; ++i) \ if (ctype_func (i)) \ bitset_set (sbcset, trans[i]); \ } \ else \ { \ for (i = 0; i < SBC_MAX; ++i) \ if (ctype_func (i)) \ bitset_set (sbcset, i); \ } \ } while (0) if (strcmp (name, "alnum") == 0) BUILD_CHARCLASS_LOOP (isalnum); else if (strcmp (name, "cntrl") == 0) BUILD_CHARCLASS_LOOP (iscntrl); else if (strcmp (name, "lower") == 0) BUILD_CHARCLASS_LOOP (islower); else if (strcmp (name, "space") == 0) BUILD_CHARCLASS_LOOP (isspace); else if (strcmp (name, "alpha") == 0) BUILD_CHARCLASS_LOOP (isalpha); else if (strcmp (name, "digit") == 0) BUILD_CHARCLASS_LOOP (isdigit); else if (strcmp (name, "print") == 0) BUILD_CHARCLASS_LOOP (isprint); else if (strcmp (name, "upper") == 0) BUILD_CHARCLASS_LOOP (isupper); else if (strcmp (name, "blank") == 0) BUILD_CHARCLASS_LOOP (isblank); else if (strcmp (name, "graph") == 0) BUILD_CHARCLASS_LOOP (isgraph); else if (strcmp (name, "punct") == 0) BUILD_CHARCLASS_LOOP (ispunct); else if (strcmp (name, "xdigit") == 0) BUILD_CHARCLASS_LOOP (isxdigit); else return REG_ECTYPE; return REG_NOERROR; } static bin_tree_t * build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, const unsigned char *class_name, const unsigned char *extra, int non_match, reg_errcode_t *err) { re_bitset_ptr_t sbcset; #ifdef RE_ENABLE_I18N re_charset_t *mbcset; int alloc = 0; #endif /* not RE_ENABLE_I18N */ reg_errcode_t ret; re_token_t br_token; bin_tree_t *tree; sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); #ifdef RE_ENABLE_I18N mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); #endif /* RE_ENABLE_I18N */ #ifdef RE_ENABLE_I18N if (BE (sbcset == NULL || mbcset == NULL, 0)) #else /* not RE_ENABLE_I18N */ if (BE (sbcset == NULL, 0)) #endif /* not RE_ENABLE_I18N */ { *err = REG_ESPACE; return NULL; } if (non_match) { #ifdef RE_ENABLE_I18N /* if (syntax & RE_HAT_LISTS_NOT_NEWLINE) bitset_set(cset->sbcset, '\0'); */ mbcset->non_match = 1; #endif /* not RE_ENABLE_I18N */ } /* We don't care the syntax in this case. */ ret = build_charclass (trans, sbcset, #ifdef RE_ENABLE_I18N mbcset, &alloc, #endif /* RE_ENABLE_I18N */ class_name, 0); if (BE (ret != REG_NOERROR, 0)) { re_free (sbcset); #ifdef RE_ENABLE_I18N free_charset (mbcset); #endif /* RE_ENABLE_I18N */ *err = ret; return NULL; } /* \w match '_' also. */ for (; *extra; extra++) bitset_set (sbcset, *extra); /* If it is non-matching list. */ if (non_match) bitset_not (sbcset); #ifdef RE_ENABLE_I18N /* Ensure only single byte characters are set. */ if (dfa->mb_cur_max > 1) bitset_mask (sbcset, dfa->sb_char); #endif /* Build a tree for simple bracket. */ br_token.type = SIMPLE_BRACKET; br_token.opr.sbcset = sbcset; tree = create_token_tree (dfa, NULL, NULL, &br_token); if (BE (tree == NULL, 0)) goto build_word_op_espace; #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { bin_tree_t *mbc_tree; /* Build a tree for complex bracket. */ br_token.type = COMPLEX_BRACKET; br_token.opr.mbcset = mbcset; dfa->has_mb_node = 1; mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); if (BE (mbc_tree == NULL, 0)) goto build_word_op_espace; /* Then join them by ALT node. */ tree = create_tree (dfa, tree, mbc_tree, OP_ALT); if (BE (mbc_tree != NULL, 1)) return tree; } else { free_charset (mbcset); return tree; } #else /* not RE_ENABLE_I18N */ return tree; #endif /* not RE_ENABLE_I18N */ build_word_op_espace: re_free (sbcset); #ifdef RE_ENABLE_I18N free_charset (mbcset); #endif /* RE_ENABLE_I18N */ *err = REG_ESPACE; return NULL; } /* This is intended for the expressions like "a{1,3}". Fetch a number from `input', and return the number. Return -1, if the number field is empty like "{,1}". Return -2, If an error is occured. */ static int fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) { int num = -1; unsigned char c; while (1) { fetch_token (token, input, syntax); c = token->opr.c; if (BE (token->type == END_OF_RE, 0)) return -2; if (token->type == OP_CLOSE_DUP_NUM || c == ',') break; num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2) ? -2 : ((num == -1) ? c - '0' : num * 10 + c - '0')); num = (num > RE_DUP_MAX) ? -2 : num; } return num; } #ifdef RE_ENABLE_I18N static void free_charset (re_charset_t *cset) { re_free (cset->mbchars); # ifdef _LIBC re_free (cset->coll_syms); re_free (cset->equiv_classes); re_free (cset->range_starts); re_free (cset->range_ends); # endif re_free (cset->char_classes); re_free (cset); } #endif /* RE_ENABLE_I18N */ /* Functions for binary tree operation. */ /* Create a tree node. */ static bin_tree_t * create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, re_token_type_t type) { re_token_t t; t.type = type; return create_token_tree (dfa, left, right, &t); } static bin_tree_t * create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, const re_token_t *token) { bin_tree_t *tree; if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0)) { bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1); if (storage == NULL) return NULL; storage->next = dfa->str_tree_storage; dfa->str_tree_storage = storage; dfa->str_tree_storage_idx = 0; } tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++]; tree->parent = NULL; tree->left = left; tree->right = right; tree->token = *token; tree->token.duplicated = 0; tree->token.opt_subexp = 0; tree->first = NULL; tree->next = NULL; tree->node_idx = -1; if (left != NULL) left->parent = tree; if (right != NULL) right->parent = tree; return tree; } /* Mark the tree SRC as an optional subexpression. To be called from preorder or postorder. */ static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node) { int idx = (int) (long) extra; if (node->token.type == SUBEXP && node->token.opr.idx == idx) node->token.opt_subexp = 1; return REG_NOERROR; } /* Free the allocated memory inside NODE. */ static void free_token (re_token_t *node) { #ifdef RE_ENABLE_I18N if (node->type == COMPLEX_BRACKET && node->duplicated == 0) free_charset (node->opr.mbcset); else #endif /* RE_ENABLE_I18N */ if (node->type == SIMPLE_BRACKET && node->duplicated == 0) re_free (node->opr.sbcset); } /* Worker function for tree walking. Free the allocated memory inside NODE and its children. */ static reg_errcode_t free_tree (void *extra, bin_tree_t *node) { free_token (&node->token); return REG_NOERROR; } /* Duplicate the node SRC, and return new node. This is a preorder visit similar to the one implemented by the generic visitor, but we need more infrastructure to maintain two parallel trees --- so, it's easier to duplicate. */ static bin_tree_t * duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa) { const bin_tree_t *node; bin_tree_t *dup_root; bin_tree_t **p_new = &dup_root, *dup_node = root->parent; for (node = root; ; ) { /* Create a new tree and link it back to the current parent. */ *p_new = create_token_tree (dfa, NULL, NULL, &node->token); if (*p_new == NULL) return NULL; (*p_new)->parent = dup_node; (*p_new)->token.duplicated = 1; dup_node = *p_new; /* Go to the left node, or up and to the right. */ if (node->left) { node = node->left; p_new = &dup_node->left; } else { const bin_tree_t *prev = NULL; while (node->right == prev || node->right == NULL) { prev = node; node = node->parent; dup_node = dup_node->parent; if (!node) return dup_root; } node = node->right; p_new = &dup_node->right; } } } /******************************************************************************/ /******************************************************************************/ /******************************************************************************/ /* GKINCLUDE #include "regexec.c" */ /******************************************************************************/ /******************************************************************************/ /******************************************************************************/ static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, int n) internal_function; static void match_ctx_clean (re_match_context_t *mctx) internal_function; static void match_ctx_free (re_match_context_t *cache) internal_function; static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, int node, int str_idx, int from, int to) internal_function; static int search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx) internal_function; static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx) internal_function; static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop, int node, int str_idx) internal_function; static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, re_dfastate_t **limited_sts, int last_node, int last_str_idx) internal_function; static reg_errcode_t re_search_internal (const regex_t *preg, const char *string, int length, int start, int range, int stop, size_t nmatch, regmatch_t pmatch[], int eflags) internal_function; static int re_search_2_stub (struct re_pattern_buffer *bufp, const char *string1, int length1, const char *string2, int length2, int start, int range, struct re_registers *regs, int stop, int ret_len) internal_function; static int re_search_stub (struct re_pattern_buffer *bufp, const char *string, int length, int start, int range, int stop, struct re_registers *regs, int ret_len) internal_function; static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, int nregs, int regs_allocated) internal_function; static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx) internal_function; static int check_matching (re_match_context_t *mctx, int fl_longest_match, int *p_match_first) internal_function; static int check_halt_state_context (const re_match_context_t *mctx, const re_dfastate_t *state, int idx) internal_function; static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, regmatch_t *prev_idx_match, int cur_node, int cur_idx, int nmatch) internal_function; static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node, int nregs, regmatch_t *regs, re_node_set *eps_via_nodes) internal_function; static reg_errcode_t set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, regmatch_t *pmatch, int fl_backtrack) internal_function; static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs) internal_function; #ifdef RE_ENABLE_I18N static int sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, int node_idx, int str_idx, int max_str_idx) internal_function; #endif /* RE_ENABLE_I18N */ static reg_errcode_t sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx) internal_function; static reg_errcode_t build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, re_node_set *cur_dest) internal_function; static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, re_node_set *dest_nodes) internal_function; static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes, const re_node_set *candidates) internal_function; static int check_dst_limits (const re_match_context_t *mctx, re_node_set *limits, int dst_node, int dst_idx, int src_node, int src_idx) internal_function; static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries, int subexp_idx, int from_node, int bkref_idx) internal_function; static int check_dst_limits_calc_pos (const re_match_context_t *mctx, int limit, int subexp_idx, int node, int str_idx, int bkref_idx) internal_function; static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes, const re_node_set *candidates, re_node_set *limits, struct re_backref_cache_entry *bkref_ents, int str_idx) internal_function; static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, const re_node_set *candidates) internal_function; static reg_errcode_t merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst, re_dfastate_t **src, int num) internal_function; static re_dfastate_t *find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) internal_function; static re_dfastate_t *transit_state (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *state) internal_function; static re_dfastate_t *merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *next_state) internal_function; static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes, int str_idx) internal_function; #if 0 static re_dfastate_t *transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *pstate) internal_function; #endif #ifdef RE_ENABLE_I18N static reg_errcode_t transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) internal_function; #endif /* RE_ENABLE_I18N */ static reg_errcode_t transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) internal_function; static reg_errcode_t get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx) internal_function; static reg_errcode_t get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top, re_sub_match_last_t *sub_last, int bkref_node, int bkref_str) internal_function; static int find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, int subexp_idx, int type) internal_function; static reg_errcode_t check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node, int top_str, int last_node, int last_str, int type) internal_function; static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx, re_node_set *cur_nodes, re_node_set *next_nodes) internal_function; static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes, int ex_subexp, int type) internal_function; static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes, int target, int ex_subexp, int type) internal_function; static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, int cur_str, int subexp_num, int type) internal_function; static int build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) internal_function; #ifdef RE_ENABLE_I18N static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, const re_string_t *input, int idx) internal_function; # ifdef _LIBC static unsigned int find_collation_sequence_value (const unsigned char *mbs, size_t name_len) internal_function; # endif /* _LIBC */ #endif /* RE_ENABLE_I18N */ static int group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, re_node_set *states_node, bitset_t *states_ch) internal_function; static int check_node_accept (const re_match_context_t *mctx, const re_token_t *node, int idx) internal_function; static reg_errcode_t extend_buffers (re_match_context_t *mctx) internal_function; /* Entry point for POSIX code. */ /* regexec searches for a given pattern, specified by PREG, in the string STRING. If NMATCH is zero or REG_NOSUB was set in the cflags argument to `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at least NMATCH elements, and we set them to the offsets of the corresponding matched substrings. EFLAGS specifies `execution flags' which affect matching: if REG_NOTBOL is set, then ^ does not match at the beginning of the string; if REG_NOTEOL is set, then $ does not match at the end. We return 0 if we find a match and REG_NOMATCH if not. */ int regexec (preg, string, nmatch, pmatch, eflags) const regex_t *__restrict preg; const char *__restrict string; size_t nmatch; regmatch_t pmatch[]; int eflags; { reg_errcode_t err; int start, length; re_dfa_t *dfa = (re_dfa_t *) preg->buffer; if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND)) return REG_BADPAT; if (eflags & REG_STARTEND) { start = pmatch[0].rm_so; length = pmatch[0].rm_eo; } else { start = 0; length = strlen (string); } __libc_lock_lock (dfa->lock); if (preg->no_sub) err = re_search_internal (preg, string, length, start, length - start, length, 0, NULL, eflags); else err = re_search_internal (preg, string, length, start, length - start, length, nmatch, pmatch, eflags); __libc_lock_unlock (dfa->lock); return err != REG_NOERROR; } #ifdef _LIBC # include versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); # if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) __typeof__ (__regexec) __compat_regexec; int attribute_compat_text_section __compat_regexec (const regex_t *__restrict preg, const char *__restrict string, size_t nmatch, regmatch_t pmatch[], int eflags) { return regexec (preg, string, nmatch, pmatch, eflags & (REG_NOTBOL | REG_NOTEOL)); } compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); # endif #endif /* Entry points for GNU code. */ /* re_match, re_search, re_match_2, re_search_2 The former two functions operate on STRING with length LENGTH, while the later two operate on concatenation of STRING1 and STRING2 with lengths LENGTH1 and LENGTH2, respectively. re_match() matches the compiled pattern in BUFP against the string, starting at index START. re_search() first tries matching at index START, then it tries to match starting from index START + 1, and so on. The last start position tried is START + RANGE. (Thus RANGE = 0 forces re_search to operate the same way as re_match().) The parameter STOP of re_{match,search}_2 specifies that no match exceeding the first STOP characters of the concatenation of the strings should be concerned. If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match and all groups is stroed in REGS. (For the "_2" variants, the offsets are computed relative to the concatenation, not relative to the individual strings.) On success, re_match* functions return the length of the match, re_search* return the position of the start of the match. Return value -1 means no match was found and -2 indicates an internal error. */ int re_match (bufp, string, length, start, regs) struct re_pattern_buffer *bufp; const char *string; int length, start; struct re_registers *regs; { return re_search_stub (bufp, string, length, start, 0, length, regs, 1); } #ifdef _LIBC weak_alias (__re_match, re_match) #endif int re_search (bufp, string, length, start, range, regs) struct re_pattern_buffer *bufp; const char *string; int length, start, range; struct re_registers *regs; { return re_search_stub (bufp, string, length, start, range, length, regs, 0); } #ifdef _LIBC weak_alias (__re_search, re_search) #endif int re_match_2 (bufp, string1, length1, string2, length2, start, regs, stop) struct re_pattern_buffer *bufp; const char *string1, *string2; int length1, length2, start, stop; struct re_registers *regs; { return re_search_2_stub (bufp, string1, length1, string2, length2, start, 0, regs, stop, 1); } #ifdef _LIBC weak_alias (__re_match_2, re_match_2) #endif int re_search_2 (bufp, string1, length1, string2, length2, start, range, regs, stop) struct re_pattern_buffer *bufp; const char *string1, *string2; int length1, length2, start, range, stop; struct re_registers *regs; { return re_search_2_stub (bufp, string1, length1, string2, length2, start, range, regs, stop, 0); } #ifdef _LIBC weak_alias (__re_search_2, re_search_2) #endif static int re_search_2_stub (bufp, string1, length1, string2, length2, start, range, regs, stop, ret_len) struct re_pattern_buffer *bufp; const char *string1, *string2; int length1, length2, start, range, stop, ret_len; struct re_registers *regs; { const char *str; int rval; int len = length1 + length2; int free_str = 0; if (BE (length1 < 0 || length2 < 0 || stop < 0, 0)) return -2; /* Concatenate the strings. */ if (length2 > 0) if (length1 > 0) { char *s = re_malloc (char, len); if (BE (s == NULL, 0)) return -2; #ifdef _LIBC memcpy (__mempcpy (s, string1, length1), string2, length2); #else memcpy (s, string1, length1); memcpy (s + length1, string2, length2); #endif str = s; free_str = 1; } else str = string2; else str = string1; rval = re_search_stub (bufp, str, len, start, range, stop, regs, ret_len); if (free_str) re_free ((char *) str); return rval; } /* The parameters have the same meaning as those of re_search. Additional parameters: If RET_LEN is nonzero the length of the match is returned (re_match style); otherwise the position of the match is returned. */ static int re_search_stub (bufp, string, length, start, range, stop, regs, ret_len) struct re_pattern_buffer *bufp; const char *string; int length, start, range, stop, ret_len; struct re_registers *regs; { reg_errcode_t result; regmatch_t *pmatch; int nregs, rval; int eflags = 0; re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; /* Check for out-of-range. */ if (BE (start < 0 || start > length, 0)) return -1; if (BE (start + range > length, 0)) range = length - start; else if (BE (start + range < 0, 0)) range = -start; __libc_lock_lock (dfa->lock); eflags |= (bufp->not_bol) ? REG_NOTBOL : 0; eflags |= (bufp->not_eol) ? REG_NOTEOL : 0; /* Compile fastmap if we haven't yet. */ if (range > 0 && bufp->fastmap != NULL && !bufp->fastmap_accurate) re_compile_fastmap (bufp); if (BE (bufp->no_sub, 0)) regs = NULL; /* We need at least 1 register. */ if (regs == NULL) nregs = 1; else if (BE (bufp->regs_allocated == REGS_FIXED && regs->num_regs < bufp->re_nsub + 1, 0)) { nregs = regs->num_regs; if (BE (nregs < 1, 0)) { /* Nothing can be copied to regs. */ regs = NULL; nregs = 1; } } else nregs = bufp->re_nsub + 1; pmatch = re_malloc (regmatch_t, nregs); if (BE (pmatch == NULL, 0)) { rval = -2; goto out; } result = re_search_internal (bufp, string, length, start, range, stop, nregs, pmatch, eflags); rval = 0; /* I hope we needn't fill ther regs with -1's when no match was found. */ if (result != REG_NOERROR) rval = -1; else if (regs != NULL) { /* If caller wants register contents data back, copy them. */ bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs, bufp->regs_allocated); if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0)) rval = -2; } if (BE (rval == 0, 1)) { if (ret_len) { assert (pmatch[0].rm_so == start); rval = pmatch[0].rm_eo - start; } else rval = pmatch[0].rm_so; } re_free (pmatch); out: __libc_lock_unlock (dfa->lock); return rval; } static unsigned re_copy_regs (regs, pmatch, nregs, regs_allocated) struct re_registers *regs; regmatch_t *pmatch; int nregs, regs_allocated; { int rval = REGS_REALLOCATE; int i; int need_regs = nregs + 1; /* We need one extra element beyond `num_regs' for the `-1' marker GNU code uses. */ /* Have the register data arrays been allocated? */ if (regs_allocated == REGS_UNALLOCATED) { /* No. So allocate them with malloc. */ regs->start = re_malloc (regoff_t, need_regs); regs->end = re_malloc (regoff_t, need_regs); if (BE (regs->start == NULL, 0) || BE (regs->end == NULL, 0)) return REGS_UNALLOCATED; regs->num_regs = need_regs; } else if (regs_allocated == REGS_REALLOCATE) { /* Yes. If we need more elements than were already allocated, reallocate them. If we need fewer, just leave it alone. */ if (BE (need_regs > regs->num_regs, 0)) { regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs); regoff_t *new_end = re_realloc (regs->end, regoff_t, need_regs); if (BE (new_start == NULL, 0) || BE (new_end == NULL, 0)) return REGS_UNALLOCATED; regs->start = new_start; regs->end = new_end; regs->num_regs = need_regs; } } else { assert (regs_allocated == REGS_FIXED); /* This function may not be called with REGS_FIXED and nregs too big. */ assert (regs->num_regs >= nregs); rval = REGS_FIXED; } /* Copy the regs. */ for (i = 0; i < nregs; ++i) { regs->start[i] = pmatch[i].rm_so; regs->end[i] = pmatch[i].rm_eo; } for ( ; i < regs->num_regs; ++i) regs->start[i] = regs->end[i] = -1; return rval; } /* Set REGS to hold NUM_REGS registers, storing them in STARTS and ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use this memory for recording register information. STARTS and ENDS must be allocated using the malloc library routine, and must each be at least NUM_REGS * sizeof (regoff_t) bytes long. If NUM_REGS == 0, then subsequent matches should allocate their own register data. Unless this function is called, the first search or match using PATTERN_BUFFER will allocate its own register data, without freeing the old data. */ void re_set_registers (bufp, regs, num_regs, starts, ends) struct re_pattern_buffer *bufp; struct re_registers *regs; unsigned num_regs; regoff_t *starts, *ends; { if (num_regs) { bufp->regs_allocated = REGS_REALLOCATE; regs->num_regs = num_regs; regs->start = starts; regs->end = ends; } else { bufp->regs_allocated = REGS_UNALLOCATED; regs->num_regs = 0; regs->start = regs->end = (regoff_t *) 0; } } #ifdef _LIBC weak_alias (__re_set_registers, re_set_registers) #endif /* Entry points compatible with 4.2 BSD regex library. We don't define them unless specifically requested. */ #if defined _REGEX_RE_COMP || defined _LIBC int # ifdef _LIBC weak_function # endif re_exec (s) const char *s; { return 0 == regexec (&re_comp_buf, s, 0, NULL, 0); } #endif /* _REGEX_RE_COMP */ /* Internal entry point. */ /* Searches for a compiled pattern PREG in the string STRING, whose length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same mingings with regexec. START, and RANGE have the same meanings with re_search. Return REG_NOERROR if we find a match, and REG_NOMATCH if not, otherwise return the error code. Note: We assume front end functions already check ranges. (START + RANGE >= 0 && START + RANGE <= LENGTH) */ static reg_errcode_t re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch, eflags) const regex_t *preg; const char *string; int length, start, range, stop, eflags; size_t nmatch; regmatch_t pmatch[]; { reg_errcode_t err; const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; int left_lim, right_lim, incr; int fl_longest_match, match_first, match_kind, match_last = -1; int extra_nmatch; int sb, ch; #if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) re_match_context_t mctx = { .dfa = dfa }; #else re_match_context_t mctx; #endif char *fastmap = (preg->fastmap != NULL && preg->fastmap_accurate && range && !preg->can_be_null) ? preg->fastmap : NULL; RE_TRANSLATE_TYPE t = preg->translate; #if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) memset (&mctx, '\0', sizeof (re_match_context_t)); mctx.dfa = dfa; #endif extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0; nmatch -= extra_nmatch; /* Check if the DFA haven't been compiled. */ if (BE (preg->used == 0 || dfa->init_state == NULL || dfa->init_state_word == NULL || dfa->init_state_nl == NULL || dfa->init_state_begbuf == NULL, 0)) return REG_NOMATCH; #ifdef DEBUG /* We assume front-end functions already check them. */ assert (start + range >= 0 && start + range <= length); #endif /* If initial states with non-begbuf contexts have no elements, the regex must be anchored. If preg->newline_anchor is set, we'll never use init_state_nl, so do not check it. */ if (dfa->init_state->nodes.nelem == 0 && dfa->init_state_word->nodes.nelem == 0 && (dfa->init_state_nl->nodes.nelem == 0 || !preg->newline_anchor)) { if (start != 0 && start + range != 0) return REG_NOMATCH; start = range = 0; } /* We must check the longest matching, if nmatch > 0. */ fl_longest_match = (nmatch != 0 || dfa->nbackref); err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1, preg->translate, preg->syntax & RE_ICASE, dfa); if (BE (err != REG_NOERROR, 0)) goto free_return; mctx.input.stop = stop; mctx.input.raw_stop = stop; mctx.input.newline_anchor = preg->newline_anchor; err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2); if (BE (err != REG_NOERROR, 0)) goto free_return; /* We will log all the DFA states through which the dfa pass, if nmatch > 1, or this dfa has "multibyte node", which is a back-reference or a node which can accept multibyte character or multi character collating element. */ if (nmatch > 1 || dfa->has_mb_node) { mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1); if (BE (mctx.state_log == NULL, 0)) { err = REG_ESPACE; goto free_return; } } else mctx.state_log = NULL; match_first = start; mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF : CONTEXT_NEWLINE | CONTEXT_BEGBUF; /* Check incrementally whether of not the input string match. */ incr = (range < 0) ? -1 : 1; left_lim = (range < 0) ? start + range : start; right_lim = (range < 0) ? start : start + range; sb = dfa->mb_cur_max == 1; match_kind = (fastmap ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0) | (range >= 0 ? 2 : 0) | (t != NULL ? 1 : 0)) : 8); for (;; match_first += incr) { err = REG_NOMATCH; if (match_first < left_lim || right_lim < match_first) goto free_return; /* Advance as rapidly as possible through the string, until we find a plausible place to start matching. This may be done with varying efficiency, so there are various possibilities: only the most common of them are specialized, in order to save on code size. We use a switch statement for speed. */ switch (match_kind) { case 8: /* No fastmap. */ break; case 7: /* Fastmap with single-byte translation, match forward. */ while (BE (match_first < right_lim, 1) && !fastmap[t[(unsigned char) string[match_first]]]) ++match_first; goto forward_match_found_start_or_reached_end; case 6: /* Fastmap without translation, match forward. */ while (BE (match_first < right_lim, 1) && !fastmap[(unsigned char) string[match_first]]) ++match_first; forward_match_found_start_or_reached_end: if (BE (match_first == right_lim, 0)) { ch = match_first >= length ? 0 : (unsigned char) string[match_first]; if (!fastmap[t ? t[ch] : ch]) goto free_return; } break; case 4: case 5: /* Fastmap without multi-byte translation, match backwards. */ while (match_first >= left_lim) { ch = match_first >= length ? 0 : (unsigned char) string[match_first]; if (fastmap[t ? t[ch] : ch]) break; --match_first; } if (match_first < left_lim) goto free_return; break; default: /* In this case, we can't determine easily the current byte, since it might be a component byte of a multibyte character. Then we use the constructed buffer instead. */ for (;;) { /* If MATCH_FIRST is out of the valid range, reconstruct the buffers. */ unsigned int offset = match_first - mctx.input.raw_mbs_idx; if (BE (offset >= (unsigned int) mctx.input.valid_raw_len, 0)) { err = re_string_reconstruct (&mctx.input, match_first, eflags); if (BE (err != REG_NOERROR, 0)) goto free_return; offset = match_first - mctx.input.raw_mbs_idx; } /* If MATCH_FIRST is out of the buffer, leave it as '\0'. Note that MATCH_FIRST must not be smaller than 0. */ ch = (match_first >= length ? 0 : re_string_byte_at (&mctx.input, offset)); if (fastmap[ch]) break; match_first += incr; if (match_first < left_lim || match_first > right_lim) { err = REG_NOMATCH; goto free_return; } } break; } /* Reconstruct the buffers so that the matcher can assume that the matching starts from the beginning of the buffer. */ err = re_string_reconstruct (&mctx.input, match_first, eflags); if (BE (err != REG_NOERROR, 0)) goto free_return; #ifdef RE_ENABLE_I18N /* Don't consider this char as a possible match start if it part, yet isn't the head, of a multibyte character. */ if (!sb && !re_string_first_byte (&mctx.input, 0)) continue; #endif /* It seems to be appropriate one, then use the matcher. */ /* We assume that the matching starts from 0. */ mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0; match_last = check_matching (&mctx, fl_longest_match, range >= 0 ? &match_first : NULL); if (match_last != -1) { if (BE (match_last == -2, 0)) { err = REG_ESPACE; goto free_return; } else { mctx.match_last = match_last; if ((!preg->no_sub && nmatch > 1) || dfa->nbackref) { re_dfastate_t *pstate = mctx.state_log[match_last]; mctx.last_node = check_halt_state_context (&mctx, pstate, match_last); } if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match) || dfa->nbackref) { err = prune_impossible_nodes (&mctx); if (err == REG_NOERROR) break; if (BE (err != REG_NOMATCH, 0)) goto free_return; match_last = -1; } else break; /* We found a match. */ } } match_ctx_clean (&mctx); } #ifdef DEBUG assert (match_last != -1); assert (err == REG_NOERROR); #endif /* Set pmatch[] if we need. */ if (nmatch > 0) { int reg_idx; /* Initialize registers. */ for (reg_idx = 1; reg_idx < nmatch; ++reg_idx) pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1; /* Set the points where matching start/end. */ pmatch[0].rm_so = 0; pmatch[0].rm_eo = mctx.match_last; if (!preg->no_sub && nmatch > 1) { err = set_regs (preg, &mctx, nmatch, pmatch, dfa->has_plural_match && dfa->nbackref > 0); if (BE (err != REG_NOERROR, 0)) goto free_return; } /* At last, add the offset to the each registers, since we slided the buffers so that we could assume that the matching starts from 0. */ for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) if (pmatch[reg_idx].rm_so != -1) { #ifdef RE_ENABLE_I18N if (BE (mctx.input.offsets_needed != 0, 0)) { pmatch[reg_idx].rm_so = (pmatch[reg_idx].rm_so == mctx.input.valid_len ? mctx.input.valid_raw_len : mctx.input.offsets[pmatch[reg_idx].rm_so]); pmatch[reg_idx].rm_eo = (pmatch[reg_idx].rm_eo == mctx.input.valid_len ? mctx.input.valid_raw_len : mctx.input.offsets[pmatch[reg_idx].rm_eo]); } #else assert (mctx.input.offsets_needed == 0); #endif pmatch[reg_idx].rm_so += match_first; pmatch[reg_idx].rm_eo += match_first; } for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx) { pmatch[nmatch + reg_idx].rm_so = -1; pmatch[nmatch + reg_idx].rm_eo = -1; } if (dfa->subexp_map) for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++) if (dfa->subexp_map[reg_idx] != reg_idx) { pmatch[reg_idx + 1].rm_so = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so; pmatch[reg_idx + 1].rm_eo = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo; } } free_return: re_free (mctx.state_log); if (dfa->nbackref) match_ctx_free (&mctx); re_string_destruct (&mctx.input); return err; } static reg_errcode_t prune_impossible_nodes (mctx) re_match_context_t *mctx; { const re_dfa_t *const dfa = mctx->dfa; int halt_node, match_last; reg_errcode_t ret; re_dfastate_t **sifted_states; re_dfastate_t **lim_states = NULL; re_sift_context_t sctx; #ifdef DEBUG assert (mctx->state_log != NULL); #endif match_last = mctx->match_last; halt_node = mctx->last_node; sifted_states = re_malloc (re_dfastate_t *, match_last + 1); if (BE (sifted_states == NULL, 0)) { ret = REG_ESPACE; goto free_return; } if (dfa->nbackref) { lim_states = re_malloc (re_dfastate_t *, match_last + 1); if (BE (lim_states == NULL, 0)) { ret = REG_ESPACE; goto free_return; } while (1) { memset (lim_states, '\0', sizeof (re_dfastate_t *) * (match_last + 1)); sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last); ret = sift_states_backward (mctx, &sctx); re_node_set_free (&sctx.limits); if (BE (ret != REG_NOERROR, 0)) goto free_return; if (sifted_states[0] != NULL || lim_states[0] != NULL) break; do { --match_last; if (match_last < 0) { ret = REG_NOMATCH; goto free_return; } } while (mctx->state_log[match_last] == NULL || !mctx->state_log[match_last]->halt); halt_node = check_halt_state_context (mctx, mctx->state_log[match_last], match_last); } ret = merge_state_array (dfa, sifted_states, lim_states, match_last + 1); re_free (lim_states); lim_states = NULL; if (BE (ret != REG_NOERROR, 0)) goto free_return; } else { sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last); ret = sift_states_backward (mctx, &sctx); re_node_set_free (&sctx.limits); if (BE (ret != REG_NOERROR, 0)) goto free_return; } re_free (mctx->state_log); mctx->state_log = sifted_states; sifted_states = NULL; mctx->last_node = halt_node; mctx->match_last = match_last; ret = REG_NOERROR; free_return: re_free (sifted_states); re_free (lim_states); return ret; } /* Acquire an initial state and return it. We must select appropriate initial state depending on the context, since initial states may have constraints like "\<", "^", etc.. */ static inline re_dfastate_t * __attribute ((always_inline)) internal_function acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx, int idx) { const re_dfa_t *const dfa = mctx->dfa; if (dfa->init_state->has_constraint) { unsigned int context; context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags); if (IS_WORD_CONTEXT (context)) return dfa->init_state_word; else if (IS_ORDINARY_CONTEXT (context)) return dfa->init_state; else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context)) return dfa->init_state_begbuf; else if (IS_NEWLINE_CONTEXT (context)) return dfa->init_state_nl; else if (IS_BEGBUF_CONTEXT (context)) { /* It is relatively rare case, then calculate on demand. */ return re_acquire_state_context (err, dfa, dfa->init_state->entrance_nodes, context); } else /* Must not happen? */ return dfa->init_state; } else return dfa->init_state; } /* Check whether the regular expression match input string INPUT or not, and return the index where the matching end, return -1 if not match, or return -2 in case of an error. FL_LONGEST_MATCH means we want the POSIX longest matching. If P_MATCH_FIRST is not NULL, and the match fails, it is set to the next place where we may want to try matching. Note that the matcher assume that the maching starts from the current index of the buffer. */ static int internal_function check_matching (re_match_context_t *mctx, int fl_longest_match, int *p_match_first) { const re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int match = 0; int match_last = -1; int cur_str_idx = re_string_cur_idx (&mctx->input); re_dfastate_t *cur_state; int at_init_state = p_match_first != NULL; int next_start_idx = cur_str_idx; err = REG_NOERROR; cur_state = acquire_init_state_context (&err, mctx, cur_str_idx); /* An initial state must not be NULL (invalid). */ if (BE (cur_state == NULL, 0)) { assert (err == REG_ESPACE); return -2; } if (mctx->state_log != NULL) { mctx->state_log[cur_str_idx] = cur_state; /* Check OP_OPEN_SUBEXP in the initial state in case that we use them later. E.g. Processing back references. */ if (BE (dfa->nbackref, 0)) { at_init_state = 0; err = check_subexp_matching_top (mctx, &cur_state->nodes, 0); if (BE (err != REG_NOERROR, 0)) return err; if (cur_state->has_backref) { err = transit_state_bkref (mctx, &cur_state->nodes); if (BE (err != REG_NOERROR, 0)) return err; } } } /* If the RE accepts NULL string. */ if (BE (cur_state->halt, 0)) { if (!cur_state->has_constraint || check_halt_state_context (mctx, cur_state, cur_str_idx)) { if (!fl_longest_match) return cur_str_idx; else { match_last = cur_str_idx; match = 1; } } } while (!re_string_eoi (&mctx->input)) { re_dfastate_t *old_state = cur_state; int next_char_idx = re_string_cur_idx (&mctx->input) + 1; if (BE (next_char_idx >= mctx->input.bufs_len, 0) || (BE (next_char_idx >= mctx->input.valid_len, 0) && mctx->input.valid_len < mctx->input.len)) { err = extend_buffers (mctx); if (BE (err != REG_NOERROR, 0)) { assert (err == REG_ESPACE); return -2; } } cur_state = transit_state (&err, mctx, cur_state); if (mctx->state_log != NULL) cur_state = merge_state_with_log (&err, mctx, cur_state); if (cur_state == NULL) { /* Reached the invalid state or an error. Try to recover a valid state using the state log, if available and if we have not already found a valid (even if not the longest) match. */ if (BE (err != REG_NOERROR, 0)) return -2; if (mctx->state_log == NULL || (match && !fl_longest_match) || (cur_state = find_recover_state (&err, mctx)) == NULL) break; } if (BE (at_init_state, 0)) { if (old_state == cur_state) next_start_idx = next_char_idx; else at_init_state = 0; } if (cur_state->halt) { /* Reached a halt state. Check the halt state can satisfy the current context. */ if (!cur_state->has_constraint || check_halt_state_context (mctx, cur_state, re_string_cur_idx (&mctx->input))) { /* We found an appropriate halt state. */ match_last = re_string_cur_idx (&mctx->input); match = 1; /* We found a match, do not modify match_first below. */ p_match_first = NULL; if (!fl_longest_match) break; } } } if (p_match_first) *p_match_first += next_start_idx; return match_last; } /* Check NODE match the current context. */ static int internal_function check_halt_node_context (const re_dfa_t *dfa, int node, unsigned int context) { re_token_type_t type = dfa->nodes[node].type; unsigned int constraint = dfa->nodes[node].constraint; if (type != END_OF_RE) return 0; if (!constraint) return 1; if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context)) return 0; return 1; } /* Check the halt state STATE match the current context. Return 0 if not match, if the node, STATE has, is a halt node and match the context, return the node. */ static int internal_function check_halt_state_context (const re_match_context_t *mctx, const re_dfastate_t *state, int idx) { int i; unsigned int context; #ifdef DEBUG assert (state->halt); #endif context = re_string_context_at (&mctx->input, idx, mctx->eflags); for (i = 0; i < state->nodes.nelem; ++i) if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context)) return state->nodes.elems[i]; return 0; } /* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA corresponding to the DFA). Return the destination node, and update EPS_VIA_NODES, return -1 in case of errors. */ static int internal_function proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs, int *pidx, int node, re_node_set *eps_via_nodes, struct re_fail_stack_t *fs) { const re_dfa_t *const dfa = mctx->dfa; int i, err; if (IS_EPSILON_NODE (dfa->nodes[node].type)) { re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes; re_node_set *edests = &dfa->edests[node]; int dest_node; err = re_node_set_insert (eps_via_nodes, node); if (BE (err < 0, 0)) return -2; /* Pick up a valid destination, or return -1 if none is found. */ for (dest_node = -1, i = 0; i < edests->nelem; ++i) { int candidate = edests->elems[i]; if (!re_node_set_contains (cur_nodes, candidate)) continue; if (dest_node == -1) dest_node = candidate; else { /* In order to avoid infinite loop like "(a*)*", return the second epsilon-transition if the first was already considered. */ if (re_node_set_contains (eps_via_nodes, dest_node)) return candidate; /* Otherwise, push the second epsilon-transition on the fail stack. */ else if (fs != NULL && push_fail_stack (fs, *pidx, candidate, nregs, regs, eps_via_nodes)) return -2; /* We know we are going to exit. */ break; } } return dest_node; } else { int naccepted = 0; re_token_type_t type = dfa->nodes[node].type; #ifdef RE_ENABLE_I18N if (dfa->nodes[node].accept_mb) naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx); else #endif /* RE_ENABLE_I18N */ if (type == OP_BACK_REF) { int subexp_idx = dfa->nodes[node].opr.idx + 1; naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so; if (fs != NULL) { if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1) return -1; else if (naccepted) { char *buf = (char *) re_string_get_buffer (&mctx->input); if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx, naccepted) != 0) return -1; } } if (naccepted == 0) { int dest_node; err = re_node_set_insert (eps_via_nodes, node); if (BE (err < 0, 0)) return -2; dest_node = dfa->edests[node].elems[0]; if (re_node_set_contains (&mctx->state_log[*pidx]->nodes, dest_node)) return dest_node; } } if (naccepted != 0 || check_node_accept (mctx, dfa->nodes + node, *pidx)) { int dest_node = dfa->nexts[node]; *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted; if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL || !re_node_set_contains (&mctx->state_log[*pidx]->nodes, dest_node))) return -1; re_node_set_empty (eps_via_nodes); return dest_node; } } return -1; } static reg_errcode_t internal_function push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node, int nregs, regmatch_t *regs, re_node_set *eps_via_nodes) { reg_errcode_t err; int num = fs->num++; if (fs->num == fs->alloc) { struct re_fail_stack_ent_t *new_array; new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t) * fs->alloc * 2)); if (new_array == NULL) return REG_ESPACE; fs->alloc *= 2; fs->stack = new_array; } fs->stack[num].idx = str_idx; fs->stack[num].node = dest_node; fs->stack[num].regs = re_malloc (regmatch_t, nregs); if (fs->stack[num].regs == NULL) return REG_ESPACE; memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs); err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes); return err; } static int internal_function pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs, regmatch_t *regs, re_node_set *eps_via_nodes) { int num = --fs->num; assert (num >= 0); *pidx = fs->stack[num].idx; memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs); re_node_set_free (eps_via_nodes); re_free (fs->stack[num].regs); *eps_via_nodes = fs->stack[num].eps_via_nodes; return fs->stack[num].node; } /* Set the positions where the subexpressions are starts/ends to registers PMATCH. Note: We assume that pmatch[0] is already set, and pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */ static reg_errcode_t internal_function set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, regmatch_t *pmatch, int fl_backtrack) { const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; int idx, cur_node; re_node_set eps_via_nodes; struct re_fail_stack_t *fs; struct re_fail_stack_t fs_body = { 0, 2, NULL }; regmatch_t *prev_idx_match; int prev_idx_match_malloced = 0; #ifdef DEBUG assert (nmatch > 1); assert (mctx->state_log != NULL); #endif if (fl_backtrack) { fs = &fs_body; fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc); if (fs->stack == NULL) return REG_ESPACE; } else fs = NULL; cur_node = dfa->init_node; re_node_set_init_empty (&eps_via_nodes); if (__libc_use_alloca (nmatch * sizeof (regmatch_t))) prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t)); else { prev_idx_match = re_malloc (regmatch_t, nmatch); if (prev_idx_match == NULL) { free_fail_stack_return (fs); return REG_ESPACE; } prev_idx_match_malloced = 1; } memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;) { update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch); if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node) { int reg_idx; if (fs) { for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1) break; if (reg_idx == nmatch) { re_node_set_free (&eps_via_nodes); if (prev_idx_match_malloced) re_free (prev_idx_match); return free_fail_stack_return (fs); } cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, &eps_via_nodes); } else { re_node_set_free (&eps_via_nodes); if (prev_idx_match_malloced) re_free (prev_idx_match); return REG_NOERROR; } } /* Proceed to next node. */ cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node, &eps_via_nodes, fs); if (BE (cur_node < 0, 0)) { if (BE (cur_node == -2, 0)) { re_node_set_free (&eps_via_nodes); if (prev_idx_match_malloced) re_free (prev_idx_match); free_fail_stack_return (fs); return REG_ESPACE; } if (fs) cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, &eps_via_nodes); else { re_node_set_free (&eps_via_nodes); if (prev_idx_match_malloced) re_free (prev_idx_match); return REG_NOMATCH; } } } re_node_set_free (&eps_via_nodes); if (prev_idx_match_malloced) re_free (prev_idx_match); return free_fail_stack_return (fs); } static reg_errcode_t internal_function free_fail_stack_return (struct re_fail_stack_t *fs) { if (fs) { int fs_idx; for (fs_idx = 0; fs_idx < fs->num; ++fs_idx) { re_node_set_free (&fs->stack[fs_idx].eps_via_nodes); re_free (fs->stack[fs_idx].regs); } re_free (fs->stack); } return REG_NOERROR; } static void internal_function update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, regmatch_t *prev_idx_match, int cur_node, int cur_idx, int nmatch) { int type = dfa->nodes[cur_node].type; if (type == OP_OPEN_SUBEXP) { int reg_num = dfa->nodes[cur_node].opr.idx + 1; /* We are at the first node of this sub expression. */ if (reg_num < nmatch) { pmatch[reg_num].rm_so = cur_idx; pmatch[reg_num].rm_eo = -1; } } else if (type == OP_CLOSE_SUBEXP) { int reg_num = dfa->nodes[cur_node].opr.idx + 1; if (reg_num < nmatch) { /* We are at the last node of this sub expression. */ if (pmatch[reg_num].rm_so < cur_idx) { pmatch[reg_num].rm_eo = cur_idx; /* This is a non-empty match or we are not inside an optional subexpression. Accept this right away. */ memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); } else { if (dfa->nodes[cur_node].opt_subexp && prev_idx_match[reg_num].rm_so != -1) /* We transited through an empty match for an optional subexpression, like (a?)*, and this is not the subexp's first match. Copy back the old content of the registers so that matches of an inner subexpression are undone as well, like in ((a?))*. */ memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch); else /* We completed a subexpression, but it may be part of an optional one, so do not update PREV_IDX_MATCH. */ pmatch[reg_num].rm_eo = cur_idx; } } } } /* This function checks the STATE_LOG from the SCTX->last_str_idx to 0 and sift the nodes in each states according to the following rules. Updated state_log will be wrote to STATE_LOG. Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if... 1. When STR_IDX == MATCH_LAST(the last index in the state_log): If `a' isn't the LAST_NODE and `a' can't epsilon transit to the LAST_NODE, we throw away the node `a'. 2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts string `s' and transit to `b': i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw away the node `a'. ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is thrown away, we throw away the node `a'. 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b': i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the node `a'. ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away, we throw away the node `a'. */ #define STATE_NODE_CONTAINS(state,node) \ ((state) != NULL && re_node_set_contains (&(state)->nodes, node)) static reg_errcode_t internal_function sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx) { reg_errcode_t err; int null_cnt = 0; int str_idx = sctx->last_str_idx; re_node_set cur_dest; #ifdef DEBUG assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL); #endif /* Build sifted state_log[str_idx]. It has the nodes which can epsilon transit to the last_node and the last_node itself. */ err = re_node_set_init_1 (&cur_dest, sctx->last_node); if (BE (err != REG_NOERROR, 0)) return err; err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); if (BE (err != REG_NOERROR, 0)) goto free_return; /* Then check each states in the state_log. */ while (str_idx > 0) { /* Update counters. */ null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0; if (null_cnt > mctx->max_mb_elem_len) { memset (sctx->sifted_states, '\0', sizeof (re_dfastate_t *) * str_idx); re_node_set_free (&cur_dest); return REG_NOERROR; } re_node_set_empty (&cur_dest); --str_idx; if (mctx->state_log[str_idx]) { err = build_sifted_states (mctx, sctx, str_idx, &cur_dest); if (BE (err != REG_NOERROR, 0)) goto free_return; } /* Add all the nodes which satisfy the following conditions: - It can epsilon transit to a node in CUR_DEST. - It is in CUR_SRC. And update state_log. */ err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); if (BE (err != REG_NOERROR, 0)) goto free_return; } err = REG_NOERROR; free_return: re_node_set_free (&cur_dest); return err; } static reg_errcode_t internal_function build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, re_node_set *cur_dest) { const re_dfa_t *const dfa = mctx->dfa; const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes; int i; /* Then build the next sifted state. We build the next sifted state on `cur_dest', and update `sifted_states[str_idx]' with `cur_dest'. Note: `cur_dest' is the sifted state from `state_log[str_idx + 1]'. `cur_src' points the node_set of the old `state_log[str_idx]' (with the epsilon nodes pre-filtered out). */ for (i = 0; i < cur_src->nelem; i++) { int prev_node = cur_src->elems[i]; int naccepted = 0; int ret; #ifdef DEBUG re_token_type_t type = dfa->nodes[prev_node].type; assert (!IS_EPSILON_NODE (type)); #endif #ifdef RE_ENABLE_I18N /* If the node may accept `multi byte'. */ if (dfa->nodes[prev_node].accept_mb) naccepted = sift_states_iter_mb (mctx, sctx, prev_node, str_idx, sctx->last_str_idx); #endif /* RE_ENABLE_I18N */ /* We don't check backreferences here. See update_cur_sifted_state(). */ if (!naccepted && check_node_accept (mctx, dfa->nodes + prev_node, str_idx) && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1], dfa->nexts[prev_node])) naccepted = 1; if (naccepted == 0) continue; if (sctx->limits.nelem) { int to_idx = str_idx + naccepted; if (check_dst_limits (mctx, &sctx->limits, dfa->nexts[prev_node], to_idx, prev_node, str_idx)) continue; } ret = re_node_set_insert (cur_dest, prev_node); if (BE (ret == -1, 0)) return REG_ESPACE; } return REG_NOERROR; } /* Helper functions. */ static reg_errcode_t internal_function clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx) { int top = mctx->state_log_top; if (next_state_log_idx >= mctx->input.bufs_len || (next_state_log_idx >= mctx->input.valid_len && mctx->input.valid_len < mctx->input.len)) { reg_errcode_t err; err = extend_buffers (mctx); if (BE (err != REG_NOERROR, 0)) return err; } if (top < next_state_log_idx) { memset (mctx->state_log + top + 1, '\0', sizeof (re_dfastate_t *) * (next_state_log_idx - top)); mctx->state_log_top = next_state_log_idx; } return REG_NOERROR; } static reg_errcode_t internal_function merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst, re_dfastate_t **src, int num) { int st_idx; reg_errcode_t err; for (st_idx = 0; st_idx < num; ++st_idx) { if (dst[st_idx] == NULL) dst[st_idx] = src[st_idx]; else if (src[st_idx] != NULL) { re_node_set merged_set; err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes, &src[st_idx]->nodes); if (BE (err != REG_NOERROR, 0)) return err; dst[st_idx] = re_acquire_state (&err, dfa, &merged_set); re_node_set_free (&merged_set); if (BE (err != REG_NOERROR, 0)) return err; } } return REG_NOERROR; } static reg_errcode_t internal_function update_cur_sifted_state (const re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, re_node_set *dest_nodes) { const re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err = REG_NOERROR; const re_node_set *candidates; candidates = ((mctx->state_log[str_idx] == NULL) ? NULL : &mctx->state_log[str_idx]->nodes); if (dest_nodes->nelem == 0) sctx->sifted_states[str_idx] = NULL; else { if (candidates) { /* At first, add the nodes which can epsilon transit to a node in DEST_NODE. */ err = add_epsilon_src_nodes (dfa, dest_nodes, candidates); if (BE (err != REG_NOERROR, 0)) return err; /* Then, check the limitations in the current sift_context. */ if (sctx->limits.nelem) { err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits, mctx->bkref_ents, str_idx); if (BE (err != REG_NOERROR, 0)) return err; } } sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes); if (BE (err != REG_NOERROR, 0)) return err; } if (candidates && mctx->state_log[str_idx]->has_backref) { err = sift_states_bkref (mctx, sctx, str_idx, candidates); if (BE (err != REG_NOERROR, 0)) return err; } return REG_NOERROR; } static reg_errcode_t internal_function add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes, const re_node_set *candidates) { reg_errcode_t err = REG_NOERROR; int i; re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes); if (BE (err != REG_NOERROR, 0)) return err; if (!state->inveclosure.alloc) { err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem); if (BE (err != REG_NOERROR, 0)) return REG_ESPACE; for (i = 0; i < dest_nodes->nelem; i++) re_node_set_merge (&state->inveclosure, dfa->inveclosures + dest_nodes->elems[i]); } return re_node_set_add_intersect (dest_nodes, candidates, &state->inveclosure); } static reg_errcode_t internal_function sub_epsilon_src_nodes (const re_dfa_t *dfa, int node, re_node_set *dest_nodes, const re_node_set *candidates) { int ecl_idx; reg_errcode_t err; re_node_set *inv_eclosure = dfa->inveclosures + node; re_node_set except_nodes; re_node_set_init_empty (&except_nodes); for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) { int cur_node = inv_eclosure->elems[ecl_idx]; if (cur_node == node) continue; if (IS_EPSILON_NODE (dfa->nodes[cur_node].type)) { int edst1 = dfa->edests[cur_node].elems[0]; int edst2 = ((dfa->edests[cur_node].nelem > 1) ? dfa->edests[cur_node].elems[1] : -1); if ((!re_node_set_contains (inv_eclosure, edst1) && re_node_set_contains (dest_nodes, edst1)) || (edst2 > 0 && !re_node_set_contains (inv_eclosure, edst2) && re_node_set_contains (dest_nodes, edst2))) { err = re_node_set_add_intersect (&except_nodes, candidates, dfa->inveclosures + cur_node); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&except_nodes); return err; } } } } for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) { int cur_node = inv_eclosure->elems[ecl_idx]; if (!re_node_set_contains (&except_nodes, cur_node)) { int idx = re_node_set_contains (dest_nodes, cur_node) - 1; re_node_set_remove_at (dest_nodes, idx); } } re_node_set_free (&except_nodes); return REG_NOERROR; } static int internal_function check_dst_limits (const re_match_context_t *mctx, re_node_set *limits, int dst_node, int dst_idx, int src_node, int src_idx) { const re_dfa_t *const dfa = mctx->dfa; int lim_idx, src_pos, dst_pos; int dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx); int src_bkref_idx = search_cur_bkref_entry (mctx, src_idx); for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) { int subexp_idx; struct re_backref_cache_entry *ent; ent = mctx->bkref_ents + limits->elems[lim_idx]; subexp_idx = dfa->nodes[ent->node].opr.idx; dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], subexp_idx, dst_node, dst_idx, dst_bkref_idx); src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], subexp_idx, src_node, src_idx, src_bkref_idx); /* In case of: ( ) ( ) ( ) */ if (src_pos == dst_pos) continue; /* This is unrelated limitation. */ else return 1; } return 0; } static int internal_function check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries, int subexp_idx, int from_node, int bkref_idx) { const re_dfa_t *const dfa = mctx->dfa; const re_node_set *eclosures = dfa->eclosures + from_node; int node_idx; /* Else, we are on the boundary: examine the nodes on the epsilon closure. */ for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx) { int node = eclosures->elems[node_idx]; switch (dfa->nodes[node].type) { case OP_BACK_REF: if (bkref_idx != -1) { struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx; do { int dst, cpos; if (ent->node != node) continue; if (subexp_idx < BITSET_WORD_BITS && !(ent->eps_reachable_subexps_map & ((bitset_word_t) 1 << subexp_idx))) continue; /* Recurse trying to reach the OP_OPEN_SUBEXP and OP_CLOSE_SUBEXP cases below. But, if the destination node is the same node as the source node, don't recurse because it would cause an infinite loop: a regex that exhibits this behavior is ()\1*\1* */ dst = dfa->edests[node].elems[0]; if (dst == from_node) { if (boundaries & 1) return -1; else /* if (boundaries & 2) */ return 0; } cpos = check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, dst, bkref_idx); if (cpos == -1 /* && (boundaries & 1) */) return -1; if (cpos == 0 && (boundaries & 2)) return 0; if (subexp_idx < BITSET_WORD_BITS) ent->eps_reachable_subexps_map &= ~((bitset_word_t) 1 << subexp_idx); } while (ent++->more); } break; case OP_OPEN_SUBEXP: if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx) return -1; break; case OP_CLOSE_SUBEXP: if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx) return 0; break; default: break; } } return (boundaries & 2) ? 1 : 0; } static int internal_function check_dst_limits_calc_pos (const re_match_context_t *mctx, int limit, int subexp_idx, int from_node, int str_idx, int bkref_idx) { struct re_backref_cache_entry *lim = mctx->bkref_ents + limit; int boundaries; /* If we are outside the range of the subexpression, return -1 or 1. */ if (str_idx < lim->subexp_from) return -1; if (lim->subexp_to < str_idx) return 1; /* If we are within the subexpression, return 0. */ boundaries = (str_idx == lim->subexp_from); boundaries |= (str_idx == lim->subexp_to) << 1; if (boundaries == 0) return 0; /* Else, examine epsilon closure. */ return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, from_node, bkref_idx); } /* Check the limitations of sub expressions LIMITS, and remove the nodes which are against limitations from DEST_NODES. */ static reg_errcode_t internal_function check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes, const re_node_set *candidates, re_node_set *limits, struct re_backref_cache_entry *bkref_ents, int str_idx) { reg_errcode_t err; int node_idx, lim_idx; for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) { int subexp_idx; struct re_backref_cache_entry *ent; ent = bkref_ents + limits->elems[lim_idx]; if (str_idx <= ent->subexp_from || ent->str_idx < str_idx) continue; /* This is unrelated limitation. */ subexp_idx = dfa->nodes[ent->node].opr.idx; if (ent->subexp_to == str_idx) { int ops_node = -1; int cls_node = -1; for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) { int node = dest_nodes->elems[node_idx]; re_token_type_t type = dfa->nodes[node].type; if (type == OP_OPEN_SUBEXP && subexp_idx == dfa->nodes[node].opr.idx) ops_node = node; else if (type == OP_CLOSE_SUBEXP && subexp_idx == dfa->nodes[node].opr.idx) cls_node = node; } /* Check the limitation of the open subexpression. */ /* Note that (ent->subexp_to = str_idx != ent->subexp_from). */ if (ops_node >= 0) { err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes, candidates); if (BE (err != REG_NOERROR, 0)) return err; } /* Check the limitation of the close subexpression. */ if (cls_node >= 0) for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) { int node = dest_nodes->elems[node_idx]; if (!re_node_set_contains (dfa->inveclosures + node, cls_node) && !re_node_set_contains (dfa->eclosures + node, cls_node)) { /* It is against this limitation. Remove it form the current sifted state. */ err = sub_epsilon_src_nodes (dfa, node, dest_nodes, candidates); if (BE (err != REG_NOERROR, 0)) return err; --node_idx; } } } else /* (ent->subexp_to != str_idx) */ { for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) { int node = dest_nodes->elems[node_idx]; re_token_type_t type = dfa->nodes[node].type; if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP) { if (subexp_idx != dfa->nodes[node].opr.idx) continue; /* It is against this limitation. Remove it form the current sifted state. */ err = sub_epsilon_src_nodes (dfa, node, dest_nodes, candidates); if (BE (err != REG_NOERROR, 0)) return err; } } } } return REG_NOERROR; } static reg_errcode_t internal_function sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, const re_node_set *candidates) { const re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int node_idx, node; re_sift_context_t local_sctx; int first_idx = search_cur_bkref_entry (mctx, str_idx); if (first_idx == -1) return REG_NOERROR; local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */ for (node_idx = 0; node_idx < candidates->nelem; ++node_idx) { int enabled_idx; re_token_type_t type; struct re_backref_cache_entry *entry; node = candidates->elems[node_idx]; type = dfa->nodes[node].type; /* Avoid infinite loop for the REs like "()\1+". */ if (node == sctx->last_node && str_idx == sctx->last_str_idx) continue; if (type != OP_BACK_REF) continue; entry = mctx->bkref_ents + first_idx; enabled_idx = first_idx; do { int subexp_len; int to_idx; int dst_node; int ret; re_dfastate_t *cur_state; if (entry->node != node) continue; subexp_len = entry->subexp_to - entry->subexp_from; to_idx = str_idx + subexp_len; dst_node = (subexp_len ? dfa->nexts[node] : dfa->edests[node].elems[0]); if (to_idx > sctx->last_str_idx || sctx->sifted_states[to_idx] == NULL || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node) || check_dst_limits (mctx, &sctx->limits, node, str_idx, dst_node, to_idx)) continue; if (local_sctx.sifted_states == NULL) { local_sctx = *sctx; err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits); if (BE (err != REG_NOERROR, 0)) goto free_return; } local_sctx.last_node = node; local_sctx.last_str_idx = str_idx; ret = re_node_set_insert (&local_sctx.limits, enabled_idx); if (BE (ret < 0, 0)) { err = REG_ESPACE; goto free_return; } cur_state = local_sctx.sifted_states[str_idx]; err = sift_states_backward (mctx, &local_sctx); if (BE (err != REG_NOERROR, 0)) goto free_return; if (sctx->limited_states != NULL) { err = merge_state_array (dfa, sctx->limited_states, local_sctx.sifted_states, str_idx + 1); if (BE (err != REG_NOERROR, 0)) goto free_return; } local_sctx.sifted_states[str_idx] = cur_state; re_node_set_remove (&local_sctx.limits, enabled_idx); /* mctx->bkref_ents may have changed, reload the pointer. */ entry = mctx->bkref_ents + enabled_idx; } while (enabled_idx++, entry++->more); } err = REG_NOERROR; free_return: if (local_sctx.sifted_states != NULL) { re_node_set_free (&local_sctx.limits); } return err; } #ifdef RE_ENABLE_I18N static int internal_function sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, int node_idx, int str_idx, int max_str_idx) { const re_dfa_t *const dfa = mctx->dfa; int naccepted; /* Check the node can accept `multi byte'. */ naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx); if (naccepted > 0 && str_idx + naccepted <= max_str_idx && !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted], dfa->nexts[node_idx])) /* The node can't accept the `multi byte', or the destination was already thrown away, then the node could't accept the current input `multi byte'. */ naccepted = 0; /* Otherwise, it is sure that the node could accept `naccepted' bytes input. */ return naccepted; } #endif /* RE_ENABLE_I18N */ /* Functions for state transition. */ /* Return the next state to which the current state STATE will transit by accepting the current input byte, and update STATE_LOG if necessary. If STATE can accept a multibyte char/collating element/back reference update the destination of STATE_LOG. */ static re_dfastate_t * internal_function transit_state (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *state) { re_dfastate_t **trtable; unsigned char ch; #ifdef RE_ENABLE_I18N /* If the current state can accept multibyte. */ if (BE (state->accept_mb, 0)) { *err = transit_state_mb (mctx, state); if (BE (*err != REG_NOERROR, 0)) return NULL; } #endif /* RE_ENABLE_I18N */ /* Then decide the next state with the single byte. */ #if 0 if (0) /* don't use transition table */ return transit_state_sb (err, mctx, state); #endif /* Use transition table */ ch = re_string_fetch_byte (&mctx->input); for (;;) { trtable = state->trtable; if (BE (trtable != NULL, 1)) return trtable[ch]; trtable = state->word_trtable; if (BE (trtable != NULL, 1)) { unsigned int context; context = re_string_context_at (&mctx->input, re_string_cur_idx (&mctx->input) - 1, mctx->eflags); if (IS_WORD_CONTEXT (context)) return trtable[ch + SBC_MAX]; else return trtable[ch]; } if (!build_trtable (mctx->dfa, state)) { *err = REG_ESPACE; return NULL; } /* Retry, we now have a transition table. */ } } /* Update the state_log if we need */ re_dfastate_t * internal_function merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *next_state) { const re_dfa_t *const dfa = mctx->dfa; int cur_idx = re_string_cur_idx (&mctx->input); if (cur_idx > mctx->state_log_top) { mctx->state_log[cur_idx] = next_state; mctx->state_log_top = cur_idx; } else if (mctx->state_log[cur_idx] == 0) { mctx->state_log[cur_idx] = next_state; } else { re_dfastate_t *pstate; unsigned int context; re_node_set next_nodes, *log_nodes, *table_nodes = NULL; /* If (state_log[cur_idx] != 0), it implies that cur_idx is the destination of a multibyte char/collating element/ back reference. Then the next state is the union set of these destinations and the results of the transition table. */ pstate = mctx->state_log[cur_idx]; log_nodes = pstate->entrance_nodes; if (next_state != NULL) { table_nodes = next_state->entrance_nodes; *err = re_node_set_init_union (&next_nodes, table_nodes, log_nodes); if (BE (*err != REG_NOERROR, 0)) return NULL; } else next_nodes = *log_nodes; /* Note: We already add the nodes of the initial state, then we don't need to add them here. */ context = re_string_context_at (&mctx->input, re_string_cur_idx (&mctx->input) - 1, mctx->eflags); next_state = mctx->state_log[cur_idx] = re_acquire_state_context (err, dfa, &next_nodes, context); /* We don't need to check errors here, since the return value of this function is next_state and ERR is already set. */ if (table_nodes != NULL) re_node_set_free (&next_nodes); } if (BE (dfa->nbackref, 0) && next_state != NULL) { /* Check OP_OPEN_SUBEXP in the current state in case that we use them later. We must check them here, since the back references in the next state might use them. */ *err = check_subexp_matching_top (mctx, &next_state->nodes, cur_idx); if (BE (*err != REG_NOERROR, 0)) return NULL; /* If the next state has back references. */ if (next_state->has_backref) { *err = transit_state_bkref (mctx, &next_state->nodes); if (BE (*err != REG_NOERROR, 0)) return NULL; next_state = mctx->state_log[cur_idx]; } } return next_state; } /* Skip bytes in the input that correspond to part of a multi-byte match, then look in the log for a state from which to restart matching. */ re_dfastate_t * internal_function find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) { re_dfastate_t *cur_state; do { int max = mctx->state_log_top; int cur_str_idx = re_string_cur_idx (&mctx->input); do { if (++cur_str_idx > max) return NULL; re_string_skip_bytes (&mctx->input, 1); } while (mctx->state_log[cur_str_idx] == NULL); cur_state = merge_state_with_log (err, mctx, NULL); } while (*err == REG_NOERROR && cur_state == NULL); return cur_state; } /* Helper functions for transit_state. */ /* From the node set CUR_NODES, pick up the nodes whose types are OP_OPEN_SUBEXP and which have corresponding back references in the regular expression. And register them to use them later for evaluating the correspoding back references. */ static reg_errcode_t internal_function check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes, int str_idx) { const re_dfa_t *const dfa = mctx->dfa; int node_idx; reg_errcode_t err; /* TODO: This isn't efficient. Because there might be more than one nodes whose types are OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all nodes. E.g. RE: (a){2} */ for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx) { int node = cur_nodes->elems[node_idx]; if (dfa->nodes[node].type == OP_OPEN_SUBEXP && dfa->nodes[node].opr.idx < BITSET_WORD_BITS && (dfa->used_bkref_map & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx))) { err = match_ctx_add_subtop (mctx, node, str_idx); if (BE (err != REG_NOERROR, 0)) return err; } } return REG_NOERROR; } #if 0 /* Return the next state to which the current state STATE will transit by accepting the current input byte. */ static re_dfastate_t * transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *state) { const re_dfa_t *const dfa = mctx->dfa; re_node_set next_nodes; re_dfastate_t *next_state; int node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input); unsigned int context; *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1); if (BE (*err != REG_NOERROR, 0)) return NULL; for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt) { int cur_node = state->nodes.elems[node_cnt]; if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx)) { *err = re_node_set_merge (&next_nodes, dfa->eclosures + dfa->nexts[cur_node]); if (BE (*err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return NULL; } } } context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags); next_state = re_acquire_state_context (err, dfa, &next_nodes, context); /* We don't need to check errors here, since the return value of this function is next_state and ERR is already set. */ re_node_set_free (&next_nodes); re_string_skip_bytes (&mctx->input, 1); return next_state; } #endif #ifdef RE_ENABLE_I18N static reg_errcode_t internal_function transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) { const re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int i; for (i = 0; i < pstate->nodes.nelem; ++i) { re_node_set dest_nodes, *new_nodes; int cur_node_idx = pstate->nodes.elems[i]; int naccepted, dest_idx; unsigned int context; re_dfastate_t *dest_state; if (!dfa->nodes[cur_node_idx].accept_mb) continue; if (dfa->nodes[cur_node_idx].constraint) { context = re_string_context_at (&mctx->input, re_string_cur_idx (&mctx->input), mctx->eflags); if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint, context)) continue; } /* How many bytes the node can accept? */ naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input, re_string_cur_idx (&mctx->input)); if (naccepted == 0) continue; /* The node can accepts `naccepted' bytes. */ dest_idx = re_string_cur_idx (&mctx->input) + naccepted; mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted : mctx->max_mb_elem_len); err = clean_state_log_if_needed (mctx, dest_idx); if (BE (err != REG_NOERROR, 0)) return err; #ifdef DEBUG assert (dfa->nexts[cur_node_idx] != -1); #endif new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx]; dest_state = mctx->state_log[dest_idx]; if (dest_state == NULL) dest_nodes = *new_nodes; else { err = re_node_set_init_union (&dest_nodes, dest_state->entrance_nodes, new_nodes); if (BE (err != REG_NOERROR, 0)) return err; } context = re_string_context_at (&mctx->input, dest_idx - 1, mctx->eflags); mctx->state_log[dest_idx] = re_acquire_state_context (&err, dfa, &dest_nodes, context); if (dest_state != NULL) re_node_set_free (&dest_nodes); if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0)) return err; } return REG_NOERROR; } #endif /* RE_ENABLE_I18N */ static reg_errcode_t internal_function transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) { const re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int i; int cur_str_idx = re_string_cur_idx (&mctx->input); for (i = 0; i < nodes->nelem; ++i) { int dest_str_idx, prev_nelem, bkc_idx; int node_idx = nodes->elems[i]; unsigned int context; const re_token_t *node = dfa->nodes + node_idx; re_node_set *new_dest_nodes; /* Check whether `node' is a backreference or not. */ if (node->type != OP_BACK_REF) continue; if (node->constraint) { context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags); if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) continue; } /* `node' is a backreference. Check the substring which the substring matched. */ bkc_idx = mctx->nbkref_ents; err = get_subexp (mctx, node_idx, cur_str_idx); if (BE (err != REG_NOERROR, 0)) goto free_return; /* And add the epsilon closures (which is `new_dest_nodes') of the backreference to appropriate state_log. */ #ifdef DEBUG assert (dfa->nexts[node_idx] != -1); #endif for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx) { int subexp_len; re_dfastate_t *dest_state; struct re_backref_cache_entry *bkref_ent; bkref_ent = mctx->bkref_ents + bkc_idx; if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx) continue; subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from; new_dest_nodes = (subexp_len == 0 ? dfa->eclosures + dfa->edests[node_idx].elems[0] : dfa->eclosures + dfa->nexts[node_idx]); dest_str_idx = (cur_str_idx + bkref_ent->subexp_to - bkref_ent->subexp_from); context = re_string_context_at (&mctx->input, dest_str_idx - 1, mctx->eflags); dest_state = mctx->state_log[dest_str_idx]; prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0 : mctx->state_log[cur_str_idx]->nodes.nelem); /* Add `new_dest_node' to state_log. */ if (dest_state == NULL) { mctx->state_log[dest_str_idx] = re_acquire_state_context (&err, dfa, new_dest_nodes, context); if (BE (mctx->state_log[dest_str_idx] == NULL && err != REG_NOERROR, 0)) goto free_return; } else { re_node_set dest_nodes; err = re_node_set_init_union (&dest_nodes, dest_state->entrance_nodes, new_dest_nodes); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&dest_nodes); goto free_return; } mctx->state_log[dest_str_idx] = re_acquire_state_context (&err, dfa, &dest_nodes, context); re_node_set_free (&dest_nodes); if (BE (mctx->state_log[dest_str_idx] == NULL && err != REG_NOERROR, 0)) goto free_return; } /* We need to check recursively if the backreference can epsilon transit. */ if (subexp_len == 0 && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem) { err = check_subexp_matching_top (mctx, new_dest_nodes, cur_str_idx); if (BE (err != REG_NOERROR, 0)) goto free_return; err = transit_state_bkref (mctx, new_dest_nodes); if (BE (err != REG_NOERROR, 0)) goto free_return; } } } err = REG_NOERROR; free_return: return err; } /* Enumerate all the candidates which the backreference BKREF_NODE can match at BKREF_STR_IDX, and register them by match_ctx_add_entry(). Note that we might collect inappropriate candidates here. However, the cost of checking them strictly here is too high, then we delay these checking for prune_impossible_nodes(). */ static reg_errcode_t internal_function get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx) { const re_dfa_t *const dfa = mctx->dfa; int subexp_num, sub_top_idx; const char *buf = (const char *) re_string_get_buffer (&mctx->input); /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */ int cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx); if (cache_idx != -1) { const struct re_backref_cache_entry *entry = mctx->bkref_ents + cache_idx; do if (entry->node == bkref_node) return REG_NOERROR; /* We already checked it. */ while (entry++->more); } subexp_num = dfa->nodes[bkref_node].opr.idx; /* For each sub expression */ for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx) { reg_errcode_t err; re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx]; re_sub_match_last_t *sub_last; int sub_last_idx, sl_str, bkref_str_off; if (dfa->nodes[sub_top->node].opr.idx != subexp_num) continue; /* It isn't related. */ sl_str = sub_top->str_idx; bkref_str_off = bkref_str_idx; /* At first, check the last node of sub expressions we already evaluated. */ for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx) { int sl_str_diff; sub_last = sub_top->lasts[sub_last_idx]; sl_str_diff = sub_last->str_idx - sl_str; /* The matched string by the sub expression match with the substring at the back reference? */ if (sl_str_diff > 0) { if (BE (bkref_str_off + sl_str_diff > mctx->input.valid_len, 0)) { /* Not enough chars for a successful match. */ if (bkref_str_off + sl_str_diff > mctx->input.len) break; err = clean_state_log_if_needed (mctx, bkref_str_off + sl_str_diff); if (BE (err != REG_NOERROR, 0)) return err; buf = (const char *) re_string_get_buffer (&mctx->input); } if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0) /* We don't need to search this sub expression any more. */ break; } bkref_str_off += sl_str_diff; sl_str += sl_str_diff; err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, bkref_str_idx); /* Reload buf, since the preceding call might have reallocated the buffer. */ buf = (const char *) re_string_get_buffer (&mctx->input); if (err == REG_NOMATCH) continue; if (BE (err != REG_NOERROR, 0)) return err; } if (sub_last_idx < sub_top->nlasts) continue; if (sub_last_idx > 0) ++sl_str; /* Then, search for the other last nodes of the sub expression. */ for (; sl_str <= bkref_str_idx; ++sl_str) { int cls_node, sl_str_off; const re_node_set *nodes; sl_str_off = sl_str - sub_top->str_idx; /* The matched string by the sub expression match with the substring at the back reference? */ if (sl_str_off > 0) { if (BE (bkref_str_off >= mctx->input.valid_len, 0)) { /* If we are at the end of the input, we cannot match. */ if (bkref_str_off >= mctx->input.len) break; err = extend_buffers (mctx); if (BE (err != REG_NOERROR, 0)) return err; buf = (const char *) re_string_get_buffer (&mctx->input); } if (buf [bkref_str_off++] != buf[sl_str - 1]) break; /* We don't need to search this sub expression any more. */ } if (mctx->state_log[sl_str] == NULL) continue; /* Does this state have a ')' of the sub expression? */ nodes = &mctx->state_log[sl_str]->nodes; cls_node = find_subexp_node (dfa, nodes, subexp_num, OP_CLOSE_SUBEXP); if (cls_node == -1) continue; /* No. */ if (sub_top->path == NULL) { sub_top->path = calloc (sizeof (state_array_t), sl_str - sub_top->str_idx + 1); if (sub_top->path == NULL) return REG_ESPACE; } /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node in the current context? */ err = check_arrival (mctx, sub_top->path, sub_top->node, sub_top->str_idx, cls_node, sl_str, OP_CLOSE_SUBEXP); if (err == REG_NOMATCH) continue; if (BE (err != REG_NOERROR, 0)) return err; sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str); if (BE (sub_last == NULL, 0)) return REG_ESPACE; err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, bkref_str_idx); if (err == REG_NOMATCH) continue; } } return REG_NOERROR; } /* Helper functions for get_subexp(). */ /* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR. If it can arrive, register the sub expression expressed with SUB_TOP and SUB_LAST. */ static reg_errcode_t internal_function get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top, re_sub_match_last_t *sub_last, int bkref_node, int bkref_str) { reg_errcode_t err; int to_idx; /* Can the subexpression arrive the back reference? */ err = check_arrival (mctx, &sub_last->path, sub_last->node, sub_last->str_idx, bkref_node, bkref_str, OP_OPEN_SUBEXP); if (err != REG_NOERROR) return err; err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx, sub_last->str_idx); if (BE (err != REG_NOERROR, 0)) return err; to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx; return clean_state_log_if_needed (mctx, to_idx); } /* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX. Search '(' if FL_OPEN, or search ')' otherwise. TODO: This function isn't efficient... Because there might be more than one nodes whose types are OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all nodes. E.g. RE: (a){2} */ static int internal_function find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, int subexp_idx, int type) { int cls_idx; for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx) { int cls_node = nodes->elems[cls_idx]; const re_token_t *node = dfa->nodes + cls_node; if (node->type == type && node->opr.idx == subexp_idx) return cls_node; } return -1; } /* Check whether the node TOP_NODE at TOP_STR can arrive to the node LAST_NODE at LAST_STR. We record the path onto PATH since it will be heavily reused. Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */ static reg_errcode_t internal_function check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node, int top_str, int last_node, int last_str, int type) { const re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err = REG_NOERROR; int subexp_num, backup_cur_idx, str_idx, null_cnt; re_dfastate_t *cur_state = NULL; re_node_set *cur_nodes, next_nodes; re_dfastate_t **backup_state_log; unsigned int context; subexp_num = dfa->nodes[top_node].opr.idx; /* Extend the buffer if we need. */ if (BE (path->alloc < last_str + mctx->max_mb_elem_len + 1, 0)) { re_dfastate_t **new_array; int old_alloc = path->alloc; path->alloc += last_str + mctx->max_mb_elem_len + 1; new_array = re_realloc (path->array, re_dfastate_t *, path->alloc); if (BE (new_array == NULL, 0)) { path->alloc = old_alloc; return REG_ESPACE; } path->array = new_array; memset (new_array + old_alloc, '\0', sizeof (re_dfastate_t *) * (path->alloc - old_alloc)); } str_idx = path->next_idx ? path->next_idx : top_str; /* Temporary modify MCTX. */ backup_state_log = mctx->state_log; backup_cur_idx = mctx->input.cur_idx; mctx->state_log = path->array; mctx->input.cur_idx = str_idx; /* Setup initial node set. */ context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); if (str_idx == top_str) { err = re_node_set_init_1 (&next_nodes, top_node); if (BE (err != REG_NOERROR, 0)) return err; err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } } else { cur_state = mctx->state_log[str_idx]; if (cur_state && cur_state->has_backref) { err = re_node_set_init_copy (&next_nodes, &cur_state->nodes); if (BE (err != REG_NOERROR, 0)) return err; } else re_node_set_init_empty (&next_nodes); } if (str_idx == top_str || (cur_state && cur_state->has_backref)) { if (next_nodes.nelem) { err = expand_bkref_cache (mctx, &next_nodes, str_idx, subexp_num, type); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } } cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); if (BE (cur_state == NULL && err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } mctx->state_log[str_idx] = cur_state; } for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;) { re_node_set_empty (&next_nodes); if (mctx->state_log[str_idx + 1]) { err = re_node_set_merge (&next_nodes, &mctx->state_log[str_idx + 1]->nodes); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } } if (cur_state) { err = check_arrival_add_next_nodes (mctx, str_idx, &cur_state->non_eps_nodes, &next_nodes); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } } ++str_idx; if (next_nodes.nelem) { err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } err = expand_bkref_cache (mctx, &next_nodes, str_idx, subexp_num, type); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } } context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); if (BE (cur_state == NULL && err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } mctx->state_log[str_idx] = cur_state; null_cnt = cur_state == NULL ? null_cnt + 1 : 0; } re_node_set_free (&next_nodes); cur_nodes = (mctx->state_log[last_str] == NULL ? NULL : &mctx->state_log[last_str]->nodes); path->next_idx = str_idx; /* Fix MCTX. */ mctx->state_log = backup_state_log; mctx->input.cur_idx = backup_cur_idx; /* Then check the current node set has the node LAST_NODE. */ if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node)) return REG_NOERROR; return REG_NOMATCH; } /* Helper functions for check_arrival. */ /* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them to NEXT_NODES. TODO: This function is similar to the functions transit_state*(), however this function has many additional works. Can't we unify them? */ static reg_errcode_t internal_function check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx, re_node_set *cur_nodes, re_node_set *next_nodes) { const re_dfa_t *const dfa = mctx->dfa; int result; int cur_idx; reg_errcode_t err = REG_NOERROR; re_node_set union_set; re_node_set_init_empty (&union_set); for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx) { int naccepted = 0; int cur_node = cur_nodes->elems[cur_idx]; #ifdef DEBUG re_token_type_t type = dfa->nodes[cur_node].type; assert (!IS_EPSILON_NODE (type)); #endif #ifdef RE_ENABLE_I18N /* If the node may accept `multi byte'. */ if (dfa->nodes[cur_node].accept_mb) { naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input, str_idx); if (naccepted > 1) { re_dfastate_t *dest_state; int next_node = dfa->nexts[cur_node]; int next_idx = str_idx + naccepted; dest_state = mctx->state_log[next_idx]; re_node_set_empty (&union_set); if (dest_state) { err = re_node_set_merge (&union_set, &dest_state->nodes); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&union_set); return err; } } result = re_node_set_insert (&union_set, next_node); if (BE (result < 0, 0)) { re_node_set_free (&union_set); return REG_ESPACE; } mctx->state_log[next_idx] = re_acquire_state (&err, dfa, &union_set); if (BE (mctx->state_log[next_idx] == NULL && err != REG_NOERROR, 0)) { re_node_set_free (&union_set); return err; } } } #endif /* RE_ENABLE_I18N */ if (naccepted || check_node_accept (mctx, dfa->nodes + cur_node, str_idx)) { result = re_node_set_insert (next_nodes, dfa->nexts[cur_node]); if (BE (result < 0, 0)) { re_node_set_free (&union_set); return REG_ESPACE; } } } re_node_set_free (&union_set); return REG_NOERROR; } /* For all the nodes in CUR_NODES, add the epsilon closures of them to CUR_NODES, however exclude the nodes which are: - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN. - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN. */ static reg_errcode_t internal_function check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes, int ex_subexp, int type) { reg_errcode_t err; int idx, outside_node; re_node_set new_nodes; #ifdef DEBUG assert (cur_nodes->nelem); #endif err = re_node_set_alloc (&new_nodes, cur_nodes->nelem); if (BE (err != REG_NOERROR, 0)) return err; /* Create a new node set NEW_NODES with the nodes which are epsilon closures of the node in CUR_NODES. */ for (idx = 0; idx < cur_nodes->nelem; ++idx) { int cur_node = cur_nodes->elems[idx]; const re_node_set *eclosure = dfa->eclosures + cur_node; outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type); if (outside_node == -1) { /* There are no problematic nodes, just merge them. */ err = re_node_set_merge (&new_nodes, eclosure); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&new_nodes); return err; } } else { /* There are problematic nodes, re-calculate incrementally. */ err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node, ex_subexp, type); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&new_nodes); return err; } } } re_node_set_free (cur_nodes); *cur_nodes = new_nodes; return REG_NOERROR; } /* Helper function for check_arrival_expand_ecl. Check incrementally the epsilon closure of TARGET, and if it isn't problematic append it to DST_NODES. */ static reg_errcode_t internal_function check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes, int target, int ex_subexp, int type) { int cur_node; for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);) { int err; if (dfa->nodes[cur_node].type == type && dfa->nodes[cur_node].opr.idx == ex_subexp) { if (type == OP_CLOSE_SUBEXP) { err = re_node_set_insert (dst_nodes, cur_node); if (BE (err == -1, 0)) return REG_ESPACE; } break; } err = re_node_set_insert (dst_nodes, cur_node); if (BE (err == -1, 0)) return REG_ESPACE; if (dfa->edests[cur_node].nelem == 0) break; if (dfa->edests[cur_node].nelem == 2) { err = check_arrival_expand_ecl_sub (dfa, dst_nodes, dfa->edests[cur_node].elems[1], ex_subexp, type); if (BE (err != REG_NOERROR, 0)) return err; } cur_node = dfa->edests[cur_node].elems[0]; } return REG_NOERROR; } /* For all the back references in the current state, calculate the destination of the back references by the appropriate entry in MCTX->BKREF_ENTS. */ static reg_errcode_t internal_function expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, int cur_str, int subexp_num, int type) { const re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int cache_idx_start = search_cur_bkref_entry (mctx, cur_str); struct re_backref_cache_entry *ent; if (cache_idx_start == -1) return REG_NOERROR; restart: ent = mctx->bkref_ents + cache_idx_start; do { int to_idx, next_node; /* Is this entry ENT is appropriate? */ if (!re_node_set_contains (cur_nodes, ent->node)) continue; /* No. */ to_idx = cur_str + ent->subexp_to - ent->subexp_from; /* Calculate the destination of the back reference, and append it to MCTX->STATE_LOG. */ if (to_idx == cur_str) { /* The backreference did epsilon transit, we must re-check all the node in the current state. */ re_node_set new_dests; reg_errcode_t err2, err3; next_node = dfa->edests[ent->node].elems[0]; if (re_node_set_contains (cur_nodes, next_node)) continue; err = re_node_set_init_1 (&new_dests, next_node); err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type); err3 = re_node_set_merge (cur_nodes, &new_dests); re_node_set_free (&new_dests); if (BE (err != REG_NOERROR || err2 != REG_NOERROR || err3 != REG_NOERROR, 0)) { err = (err != REG_NOERROR ? err : (err2 != REG_NOERROR ? err2 : err3)); return err; } /* TODO: It is still inefficient... */ goto restart; } else { re_node_set union_set; next_node = dfa->nexts[ent->node]; if (mctx->state_log[to_idx]) { int ret; if (re_node_set_contains (&mctx->state_log[to_idx]->nodes, next_node)) continue; err = re_node_set_init_copy (&union_set, &mctx->state_log[to_idx]->nodes); ret = re_node_set_insert (&union_set, next_node); if (BE (err != REG_NOERROR || ret < 0, 0)) { re_node_set_free (&union_set); err = err != REG_NOERROR ? err : REG_ESPACE; return err; } } else { err = re_node_set_init_1 (&union_set, next_node); if (BE (err != REG_NOERROR, 0)) return err; } mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set); re_node_set_free (&union_set); if (BE (mctx->state_log[to_idx] == NULL && err != REG_NOERROR, 0)) return err; } } while (ent++->more); return REG_NOERROR; } /* Build transition table for the state. Return 1 if succeeded, otherwise return NULL. */ static int internal_function build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) { reg_errcode_t err; int i, j, ch, need_word_trtable = 0; bitset_word_t elem, mask; bool dests_node_malloced = false; bool dest_states_malloced = false; int ndests; /* Number of the destination states from `state'. */ re_dfastate_t **trtable; re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl; re_node_set follows, *dests_node; bitset_t *dests_ch; bitset_t acceptable; struct dests_alloc { re_node_set dests_node[SBC_MAX]; bitset_t dests_ch[SBC_MAX]; } *dests_alloc; /* We build DFA states which corresponds to the destination nodes from `state'. `dests_node[i]' represents the nodes which i-th destination state contains, and `dests_ch[i]' represents the characters which i-th destination state accepts. */ if (__libc_use_alloca (sizeof (struct dests_alloc))) dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc)); else { dests_alloc = re_malloc (struct dests_alloc, 1); if (BE (dests_alloc == NULL, 0)) return 0; dests_node_malloced = true; } dests_node = dests_alloc->dests_node; dests_ch = dests_alloc->dests_ch; /* Initialize transiton table. */ state->word_trtable = state->trtable = NULL; /* At first, group all nodes belonging to `state' into several destinations. */ ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch); if (BE (ndests <= 0, 0)) { if (dests_node_malloced) free (dests_alloc); /* Return 0 in case of an error, 1 otherwise. */ if (ndests == 0) { state->trtable = (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX); return 1; } return 0; } err = re_node_set_alloc (&follows, ndests + 1); if (BE (err != REG_NOERROR, 0)) goto out_free; if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX + ndests * 3 * sizeof (re_dfastate_t *))) dest_states = (re_dfastate_t **) alloca (ndests * 3 * sizeof (re_dfastate_t *)); else { dest_states = (re_dfastate_t **) malloc (ndests * 3 * sizeof (re_dfastate_t *)); if (BE (dest_states == NULL, 0)) { out_free: if (dest_states_malloced) free (dest_states); re_node_set_free (&follows); for (i = 0; i < ndests; ++i) re_node_set_free (dests_node + i); if (dests_node_malloced) free (dests_alloc); return 0; } dest_states_malloced = true; } dest_states_word = dest_states + ndests; dest_states_nl = dest_states_word + ndests; bitset_empty (acceptable); /* Then build the states for all destinations. */ for (i = 0; i < ndests; ++i) { int next_node; re_node_set_empty (&follows); /* Merge the follows of this destination states. */ for (j = 0; j < dests_node[i].nelem; ++j) { next_node = dfa->nexts[dests_node[i].elems[j]]; if (next_node != -1) { err = re_node_set_merge (&follows, dfa->eclosures + next_node); if (BE (err != REG_NOERROR, 0)) goto out_free; } } dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0); if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0)) goto out_free; /* If the new state has context constraint, build appropriate states for these contexts. */ if (dest_states[i]->has_constraint) { dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows, CONTEXT_WORD); if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0)) goto out_free; if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1) need_word_trtable = 1; dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows, CONTEXT_NEWLINE); if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0)) goto out_free; } else { dest_states_word[i] = dest_states[i]; dest_states_nl[i] = dest_states[i]; } bitset_merge (acceptable, dests_ch[i]); } if (!BE (need_word_trtable, 0)) { /* We don't care about whether the following character is a word character, or we are in a single-byte character set so we can discern by looking at the character code: allocate a 256-entry transition table. */ trtable = state->trtable = (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX); if (BE (trtable == NULL, 0)) goto out_free; /* For all characters ch...: */ for (i = 0; i < BITSET_WORDS; ++i) for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; elem; mask <<= 1, elem >>= 1, ++ch) if (BE (elem & 1, 0)) { /* There must be exactly one destination which accepts character ch. See group_nodes_into_DFAstates. */ for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) ; /* j-th destination accepts the word character ch. */ if (dfa->word_char[i] & mask) trtable[ch] = dest_states_word[j]; else trtable[ch] = dest_states[j]; } } else { /* We care about whether the following character is a word character, and we are in a multi-byte character set: discern by looking at the character code: build two 256-entry transition tables, one starting at trtable[0] and one starting at trtable[SBC_MAX]. */ trtable = state->word_trtable = (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX); if (BE (trtable == NULL, 0)) goto out_free; /* For all characters ch...: */ for (i = 0; i < BITSET_WORDS; ++i) for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; elem; mask <<= 1, elem >>= 1, ++ch) if (BE (elem & 1, 0)) { /* There must be exactly one destination which accepts character ch. See group_nodes_into_DFAstates. */ for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) ; /* j-th destination accepts the word character ch. */ trtable[ch] = dest_states[j]; trtable[ch + SBC_MAX] = dest_states_word[j]; } } /* new line */ if (bitset_contain (acceptable, NEWLINE_CHAR)) { /* The current state accepts newline character. */ for (j = 0; j < ndests; ++j) if (bitset_contain (dests_ch[j], NEWLINE_CHAR)) { /* k-th destination accepts newline character. */ trtable[NEWLINE_CHAR] = dest_states_nl[j]; if (need_word_trtable) trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j]; /* There must be only one destination which accepts newline. See group_nodes_into_DFAstates. */ break; } } if (dest_states_malloced) free (dest_states); re_node_set_free (&follows); for (i = 0; i < ndests; ++i) re_node_set_free (dests_node + i); if (dests_node_malloced) free (dests_alloc); return 1; } /* Group all nodes belonging to STATE into several destinations. Then for all destinations, set the nodes belonging to the destination to DESTS_NODE[i] and set the characters accepted by the destination to DEST_CH[i]. This function return the number of destinations. */ static int internal_function group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, re_node_set *dests_node, bitset_t *dests_ch) { reg_errcode_t err; int result; int i, j, k; int ndests; /* Number of the destinations from `state'. */ bitset_t accepts; /* Characters a node can accept. */ const re_node_set *cur_nodes = &state->nodes; bitset_empty (accepts); ndests = 0; /* For all the nodes belonging to `state', */ for (i = 0; i < cur_nodes->nelem; ++i) { re_token_t *node = &dfa->nodes[cur_nodes->elems[i]]; re_token_type_t type = node->type; unsigned int constraint = node->constraint; /* Enumerate all single byte character this node can accept. */ if (type == CHARACTER) bitset_set (accepts, node->opr.c); else if (type == SIMPLE_BRACKET) { bitset_merge (accepts, node->opr.sbcset); } else if (type == OP_PERIOD) { #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) bitset_merge (accepts, dfa->sb_char); else #endif bitset_set_all (accepts); if (!(dfa->syntax & RE_DOT_NEWLINE)) bitset_clear (accepts, '\n'); if (dfa->syntax & RE_DOT_NOT_NULL) bitset_clear (accepts, '\0'); } #ifdef RE_ENABLE_I18N else if (type == OP_UTF8_PERIOD) { memset (accepts, '\xff', sizeof (bitset_t) / 2); if (!(dfa->syntax & RE_DOT_NEWLINE)) bitset_clear (accepts, '\n'); if (dfa->syntax & RE_DOT_NOT_NULL) bitset_clear (accepts, '\0'); } #endif else continue; /* Check the `accepts' and sift the characters which are not match it the context. */ if (constraint) { if (constraint & NEXT_NEWLINE_CONSTRAINT) { bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR); bitset_empty (accepts); if (accepts_newline) bitset_set (accepts, NEWLINE_CHAR); else continue; } if (constraint & NEXT_ENDBUF_CONSTRAINT) { bitset_empty (accepts); continue; } if (constraint & NEXT_WORD_CONSTRAINT) { bitset_word_t any_set = 0; if (type == CHARACTER && !node->word_char) { bitset_empty (accepts); continue; } #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) for (j = 0; j < BITSET_WORDS; ++j) any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j])); else #endif for (j = 0; j < BITSET_WORDS; ++j) any_set |= (accepts[j] &= dfa->word_char[j]); if (!any_set) continue; } if (constraint & NEXT_NOTWORD_CONSTRAINT) { bitset_word_t any_set = 0; if (type == CHARACTER && node->word_char) { bitset_empty (accepts); continue; } #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) for (j = 0; j < BITSET_WORDS; ++j) any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j])); else #endif for (j = 0; j < BITSET_WORDS; ++j) any_set |= (accepts[j] &= ~dfa->word_char[j]); if (!any_set) continue; } } /* Then divide `accepts' into DFA states, or create a new state. Above, we make sure that accepts is not empty. */ for (j = 0; j < ndests; ++j) { bitset_t intersec; /* Intersection sets, see below. */ bitset_t remains; /* Flags, see below. */ bitset_word_t has_intersec, not_subset, not_consumed; /* Optimization, skip if this state doesn't accept the character. */ if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c)) continue; /* Enumerate the intersection set of this state and `accepts'. */ has_intersec = 0; for (k = 0; k < BITSET_WORDS; ++k) has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k]; /* And skip if the intersection set is empty. */ if (!has_intersec) continue; /* Then check if this state is a subset of `accepts'. */ not_subset = not_consumed = 0; for (k = 0; k < BITSET_WORDS; ++k) { not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k]; not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k]; } /* If this state isn't a subset of `accepts', create a new group state, which has the `remains'. */ if (not_subset) { bitset_copy (dests_ch[ndests], remains); bitset_copy (dests_ch[j], intersec); err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]); if (BE (err != REG_NOERROR, 0)) goto error_return; ++ndests; } /* Put the position in the current group. */ result = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]); if (BE (result < 0, 0)) goto error_return; /* If all characters are consumed, go to next node. */ if (!not_consumed) break; } /* Some characters remain, create a new group. */ if (j == ndests) { bitset_copy (dests_ch[ndests], accepts); err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]); if (BE (err != REG_NOERROR, 0)) goto error_return; ++ndests; bitset_empty (accepts); } } return ndests; error_return: for (j = 0; j < ndests; ++j) re_node_set_free (dests_node + j); return -1; } #ifdef RE_ENABLE_I18N /* Check how many bytes the node `dfa->nodes[node_idx]' accepts. Return the number of the bytes the node accepts. STR_IDX is the current index of the input string. This function handles the nodes which can accept one character, or one collating element like '.', '[a-z]', opposite to the other nodes can only accept one byte. */ static int internal_function check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, const re_string_t *input, int str_idx) { const re_token_t *node = dfa->nodes + node_idx; int char_len, elem_len; int i; if (BE (node->type == OP_UTF8_PERIOD, 0)) { unsigned char c = re_string_byte_at (input, str_idx), d; if (BE (c < 0xc2, 1)) return 0; if (str_idx + 2 > input->len) return 0; d = re_string_byte_at (input, str_idx + 1); if (c < 0xe0) return (d < 0x80 || d > 0xbf) ? 0 : 2; else if (c < 0xf0) { char_len = 3; if (c == 0xe0 && d < 0xa0) return 0; } else if (c < 0xf8) { char_len = 4; if (c == 0xf0 && d < 0x90) return 0; } else if (c < 0xfc) { char_len = 5; if (c == 0xf8 && d < 0x88) return 0; } else if (c < 0xfe) { char_len = 6; if (c == 0xfc && d < 0x84) return 0; } else return 0; if (str_idx + char_len > input->len) return 0; for (i = 1; i < char_len; ++i) { d = re_string_byte_at (input, str_idx + i); if (d < 0x80 || d > 0xbf) return 0; } return char_len; } char_len = re_string_char_size_at (input, str_idx); if (node->type == OP_PERIOD) { if (char_len <= 1) return 0; /* fixme: I don't think this if is needed, as both '\n' and '\0' are char_len == 1. */ /* '.' accepts any one character except the following two cases. */ if ((!(dfa->syntax & RE_DOT_NEWLINE) && re_string_byte_at (input, str_idx) == '\n') || ((dfa->syntax & RE_DOT_NOT_NULL) && re_string_byte_at (input, str_idx) == '\0')) return 0; return char_len; } elem_len = re_string_elem_size_at (input, str_idx); if ((elem_len <= 1 && char_len <= 1) || char_len == 0) return 0; if (node->type == COMPLEX_BRACKET) { const re_charset_t *cset = node->opr.mbcset; # ifdef _LIBC const unsigned char *pin = ((const unsigned char *) re_string_get_buffer (input) + str_idx); int j; uint32_t nrules; # endif /* _LIBC */ int match_len = 0; wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars) ? re_string_wchar_at (input, str_idx) : 0); /* match with multibyte character? */ for (i = 0; i < cset->nmbchars; ++i) if (wc == cset->mbchars[i]) { match_len = char_len; goto check_node_accept_bytes_match; } /* match with character_class? */ for (i = 0; i < cset->nchar_classes; ++i) { wctype_t wt = cset->char_classes[i]; if (__iswctype (wc, wt)) { match_len = char_len; goto check_node_accept_bytes_match; } } # ifdef _LIBC nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules != 0) { unsigned int in_collseq = 0; const int32_t *table, *indirect; const unsigned char *weights, *extra; const char *collseqwc; int32_t idx; /* This #include defines a local function! */ # include /* match with collating_symbol? */ if (cset->ncoll_syms) extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); for (i = 0; i < cset->ncoll_syms; ++i) { const unsigned char *coll_sym = extra + cset->coll_syms[i]; /* Compare the length of input collating element and the length of current collating element. */ if (*coll_sym != elem_len) continue; /* Compare each bytes. */ for (j = 0; j < *coll_sym; j++) if (pin[j] != coll_sym[1 + j]) break; if (j == *coll_sym) { /* Match if every bytes is equal. */ match_len = j; goto check_node_accept_bytes_match; } } if (cset->nranges) { if (elem_len <= char_len) { collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); in_collseq = __collseq_table_lookup (collseqwc, wc); } else in_collseq = find_collation_sequence_value (pin, elem_len); } /* match with range expression? */ for (i = 0; i < cset->nranges; ++i) if (cset->range_starts[i] <= in_collseq && in_collseq <= cset->range_ends[i]) { match_len = elem_len; goto check_node_accept_bytes_match; } /* match with equivalence_class? */ if (cset->nequiv_classes) { const unsigned char *cp = pin; table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); idx = findidx (&cp); if (idx > 0) for (i = 0; i < cset->nequiv_classes; ++i) { int32_t equiv_class_idx = cset->equiv_classes[i]; size_t weight_len = weights[idx]; if (weight_len == weights[equiv_class_idx]) { int cnt = 0; while (cnt <= weight_len && (weights[equiv_class_idx + 1 + cnt] == weights[idx + 1 + cnt])) ++cnt; if (cnt > weight_len) { match_len = elem_len; goto check_node_accept_bytes_match; } } } } } else # endif /* _LIBC */ { /* match with range expression? */ #if __GNUC__ >= 2 wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'}; #else wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; cmp_buf[2] = wc; #endif for (i = 0; i < cset->nranges; ++i) { cmp_buf[0] = cset->range_starts[i]; cmp_buf[4] = cset->range_ends[i]; if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) { match_len = char_len; goto check_node_accept_bytes_match; } } } check_node_accept_bytes_match: if (!cset->non_match) return match_len; else { if (match_len > 0) return 0; else return (elem_len > char_len) ? elem_len : char_len; } } return 0; } # ifdef _LIBC static unsigned int internal_function find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) { uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules == 0) { if (mbs_len == 1) { /* No valid character. Match it as a single byte character. */ const unsigned char *collseq = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); return collseq[mbs[0]]; } return UINT_MAX; } else { int32_t idx; const unsigned char *extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); int32_t extrasize = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra; for (idx = 0; idx < extrasize;) { int mbs_cnt, found = 0; int32_t elem_mbs_len; /* Skip the name of collating element name. */ idx = idx + extra[idx] + 1; elem_mbs_len = extra[idx++]; if (mbs_len == elem_mbs_len) { for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt) if (extra[idx + mbs_cnt] != mbs[mbs_cnt]) break; if (mbs_cnt == elem_mbs_len) /* Found the entry. */ found = 1; } /* Skip the byte sequence of the collating element. */ idx += elem_mbs_len; /* Adjust for the alignment. */ idx = (idx + 3) & ~3; /* Skip the collation sequence value. */ idx += sizeof (uint32_t); /* Skip the wide char sequence of the collating element. */ idx = idx + sizeof (uint32_t) * (extra[idx] + 1); /* If we found the entry, return the sequence value. */ if (found) return *(uint32_t *) (extra + idx); /* Skip the collation sequence value. */ idx += sizeof (uint32_t); } return UINT_MAX; } } # endif /* _LIBC */ #endif /* RE_ENABLE_I18N */ /* Check whether the node accepts the byte which is IDX-th byte of the INPUT. */ static int internal_function check_node_accept (const re_match_context_t *mctx, const re_token_t *node, int idx) { unsigned char ch; ch = re_string_byte_at (&mctx->input, idx); switch (node->type) { case CHARACTER: if (node->opr.c != ch) return 0; break; case SIMPLE_BRACKET: if (!bitset_contain (node->opr.sbcset, ch)) return 0; break; #ifdef RE_ENABLE_I18N case OP_UTF8_PERIOD: if (ch >= 0x80) return 0; /* FALLTHROUGH */ #endif case OP_PERIOD: if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE)) || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL))) return 0; break; default: return 0; } if (node->constraint) { /* The node has constraints. Check whether the current context satisfies the constraints. */ unsigned int context = re_string_context_at (&mctx->input, idx, mctx->eflags); if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) return 0; } return 1; } /* Extend the buffers, if the buffers have run out. */ static reg_errcode_t internal_function extend_buffers (re_match_context_t *mctx) { reg_errcode_t ret; re_string_t *pstr = &mctx->input; /* Double the lengthes of the buffers. */ ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); if (BE (ret != REG_NOERROR, 0)) return ret; if (mctx->state_log != NULL) { /* And double the length of state_log. */ /* XXX We have no indication of the size of this buffer. If this allocation fail we have no indication that the state_log array does not have the right size. */ re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *, pstr->bufs_len + 1); if (BE (new_array == NULL, 0)) return REG_ESPACE; mctx->state_log = new_array; } /* Then reconstruct the buffers. */ if (pstr->icase) { #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { ret = build_wcs_upper_buffer (pstr); if (BE (ret != REG_NOERROR, 0)) return ret; } else #endif /* RE_ENABLE_I18N */ build_upper_buffer (pstr); } else { #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) build_wcs_buffer (pstr); else #endif /* RE_ENABLE_I18N */ { if (pstr->trans != NULL) re_string_translate_buffer (pstr); } } return REG_NOERROR; } /* Functions for matching context. */ /* Initialize MCTX. */ static reg_errcode_t internal_function match_ctx_init (re_match_context_t *mctx, int eflags, int n) { mctx->eflags = eflags; mctx->match_last = -1; if (n > 0) { mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n); mctx->sub_tops = re_malloc (re_sub_match_top_t *, n); if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0)) return REG_ESPACE; } /* Already zero-ed by the caller. else mctx->bkref_ents = NULL; mctx->nbkref_ents = 0; mctx->nsub_tops = 0; */ mctx->abkref_ents = n; mctx->max_mb_elem_len = 1; mctx->asub_tops = n; return REG_NOERROR; } /* Clean the entries which depend on the current input in MCTX. This function must be invoked when the matcher changes the start index of the input, or changes the input string. */ static void internal_function match_ctx_clean (re_match_context_t *mctx) { int st_idx; for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx) { int sl_idx; re_sub_match_top_t *top = mctx->sub_tops[st_idx]; for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx) { re_sub_match_last_t *last = top->lasts[sl_idx]; re_free (last->path.array); re_free (last); } re_free (top->lasts); if (top->path) { re_free (top->path->array); re_free (top->path); } free (top); } mctx->nsub_tops = 0; mctx->nbkref_ents = 0; } /* Free all the memory associated with MCTX. */ static void internal_function match_ctx_free (re_match_context_t *mctx) { /* First, free all the memory associated with MCTX->SUB_TOPS. */ match_ctx_clean (mctx); re_free (mctx->sub_tops); re_free (mctx->bkref_ents); } /* Add a new backreference entry to MCTX. Note that we assume that caller never call this function with duplicate entry, and call with STR_IDX which isn't smaller than any existing entry. */ static reg_errcode_t internal_function match_ctx_add_entry (re_match_context_t *mctx, int node, int str_idx, int from, int to) { if (mctx->nbkref_ents >= mctx->abkref_ents) { struct re_backref_cache_entry* new_entry; new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry, mctx->abkref_ents * 2); if (BE (new_entry == NULL, 0)) { re_free (mctx->bkref_ents); return REG_ESPACE; } mctx->bkref_ents = new_entry; memset (mctx->bkref_ents + mctx->nbkref_ents, '\0', sizeof (struct re_backref_cache_entry) * mctx->abkref_ents); mctx->abkref_ents *= 2; } if (mctx->nbkref_ents > 0 && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx) mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1; mctx->bkref_ents[mctx->nbkref_ents].node = node; mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx; mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from; mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to; /* This is a cache that saves negative results of check_dst_limits_calc_pos. If bit N is clear, means that this entry won't epsilon-transition to an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression. If it is set, check_dst_limits_calc_pos_1 will recurse and try to find one such node. A backreference does not epsilon-transition unless it is empty, so set to all zeros if FROM != TO. */ mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map = (from == to ? ~0 : 0); mctx->bkref_ents[mctx->nbkref_ents++].more = 0; if (mctx->max_mb_elem_len < to - from) mctx->max_mb_elem_len = to - from; return REG_NOERROR; } /* Search for the first entry which has the same str_idx, or -1 if none is found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */ static int internal_function search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx) { int left, right, mid, last; last = right = mctx->nbkref_ents; for (left = 0; left < right;) { mid = (left + right) / 2; if (mctx->bkref_ents[mid].str_idx < str_idx) left = mid + 1; else right = mid; } if (left < last && mctx->bkref_ents[left].str_idx == str_idx) return left; else return -1; } /* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches at STR_IDX. */ static reg_errcode_t internal_function match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx) { #ifdef DEBUG assert (mctx->sub_tops != NULL); assert (mctx->asub_tops > 0); #endif if (BE (mctx->nsub_tops == mctx->asub_tops, 0)) { int new_asub_tops = mctx->asub_tops * 2; re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops, re_sub_match_top_t *, new_asub_tops); if (BE (new_array == NULL, 0)) return REG_ESPACE; mctx->sub_tops = new_array; mctx->asub_tops = new_asub_tops; } mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t)); if (BE (mctx->sub_tops[mctx->nsub_tops] == NULL, 0)) return REG_ESPACE; mctx->sub_tops[mctx->nsub_tops]->node = node; mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx; return REG_NOERROR; } /* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. */ static re_sub_match_last_t * internal_function match_ctx_add_sublast (re_sub_match_top_t *subtop, int node, int str_idx) { re_sub_match_last_t *new_entry; if (BE (subtop->nlasts == subtop->alasts, 0)) { int new_alasts = 2 * subtop->alasts + 1; re_sub_match_last_t **new_array = re_realloc (subtop->lasts, re_sub_match_last_t *, new_alasts); if (BE (new_array == NULL, 0)) return NULL; subtop->lasts = new_array; subtop->alasts = new_alasts; } new_entry = calloc (1, sizeof (re_sub_match_last_t)); if (BE (new_entry != NULL, 1)) { subtop->lasts[subtop->nlasts] = new_entry; new_entry->node = node; new_entry->str_idx = str_idx; ++subtop->nlasts; } return new_entry; } static void internal_function sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, re_dfastate_t **limited_sts, int last_node, int last_str_idx) { sctx->sifted_states = sifted_sts; sctx->limited_states = limited_sts; sctx->last_node = last_node; sctx->last_str_idx = last_str_idx; re_node_set_init_empty (&sctx->limits); } /* Binary backward compatibility. */ #if _LIBC # include # if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.") int re_max_failures = 2000; # endif #endif #endif ������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/rw.c�����������������������������������������0000644�0001751�0000144�00000007116�14552244506�023127� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! * \file * * \brief Various routines that perform random-walk based operations on graphs stored as gk_csr_t matrices. * * \author George Karypis * \version\verbatim $Id: rw.c 11078 2011-11-12 00:20:44Z karypis $ \endverbatim */ #include "GKlib.h" /*************************************************************************/ /*! Computes the (personalized) page-rank of the vertices in a graph. \param mat is the matrix storing the graph. \param lamda is the restart probability. \param eps is the error tolerance for convergance. \param max_niter is the maximum number of allowed iterations. \param pr on entry stores the restart distribution of the vertices. This allows for the computation of personalized page-rank scores by appropriately setting that parameter. On return, pr stores the computed page ranks. \returns the number of iterations that were performed. */ /**************************************************************************/ int gk_rw_PageRank(gk_csr_t *mat, float lamda, float eps, int max_niter, float *pr) { ssize_t i, j, k, iter, nrows; double *rscale, *prold, *prnew, *prtmp; double fromsinks, error; ssize_t *rowptr; int *rowind; float *rowval; nrows = mat->nrows; rowptr = mat->rowptr; rowind = mat->rowind; rowval = mat->rowval; prold = gk_dsmalloc(nrows, 0, "gk_rw_PageRank: prnew"); prnew = gk_dsmalloc(nrows, 0, "gk_rw_PageRank: prold"); rscale = gk_dsmalloc(nrows, 0, "gk_rw_PageRank: rscale"); /* compute the scaling factors to get adjacency weights into transition probabilities */ for (i=0; i 0) rscale[i] = 1.0/rscale[i]; } /* the restart distribution is the initial pr scores */ for (i=0; i error ? fabs(prnew[i]-prold[i]) : error); //printf("nrm1: %le maxfabserr: %le\n", gk_dsum(nrows, prnew, 1), error); if (error < eps) break; } /* store the computed pr scores into pr for output */ for (i=0; ikey < (b)->key) * GKQSORT(struct elt, arr, n, elt_lt); * } * * And so on. */ /* Swap two items pointed to by A and B using temporary buffer t. */ #define _GKQSORT_SWAP(a, b, t) ((void)((t = *a), (*a = *b), (*b = t))) /* Discontinue quicksort algorithm when partition gets below this size. This particular magic number was chosen to work best on a Sun 4/260. */ #define _GKQSORT_MAX_THRESH 4 /* The next 4 #defines implement a very fast in-line stack abstraction. */ #define _GKQSORT_STACK_SIZE (8 * sizeof(size_t)) #define _GKQSORT_PUSH(top, low, high) (((top->_lo = (low)), (top->_hi = (high)), ++top)) #define _GKQSORT_POP(low, high, top) ((--top, (low = top->_lo), (high = top->_hi))) #define _GKQSORT_STACK_NOT_EMPTY (_stack < _top) /* The main code starts here... */ #define GK_MKQSORT(GKQSORT_TYPE,GKQSORT_BASE,GKQSORT_NELT,GKQSORT_LT) \ { \ GKQSORT_TYPE *const _base = (GKQSORT_BASE); \ const size_t _elems = (GKQSORT_NELT); \ GKQSORT_TYPE _hold; \ \ if (_elems == 0) \ return; \ \ /* Don't declare two variables of type GKQSORT_TYPE in a single \ * statement: eg `TYPE a, b;', in case if TYPE is a pointer, \ * expands to `type* a, b;' wich isn't what we want. \ */ \ \ if (_elems > _GKQSORT_MAX_THRESH) { \ GKQSORT_TYPE *_lo = _base; \ GKQSORT_TYPE *_hi = _lo + _elems - 1; \ struct { \ GKQSORT_TYPE *_hi; GKQSORT_TYPE *_lo; \ } _stack[_GKQSORT_STACK_SIZE], *_top = _stack + 1; \ \ while (_GKQSORT_STACK_NOT_EMPTY) { \ GKQSORT_TYPE *_left_ptr; GKQSORT_TYPE *_right_ptr; \ \ /* Select median value from among LO, MID, and HI. Rearrange \ LO and HI so the three values are sorted. This lowers the \ probability of picking a pathological pivot value and \ skips a comparison for both the LEFT_PTR and RIGHT_PTR in \ the while loops. */ \ \ GKQSORT_TYPE *_mid = _lo + ((_hi - _lo) >> 1); \ \ if (GKQSORT_LT (_mid, _lo)) \ _GKQSORT_SWAP (_mid, _lo, _hold); \ if (GKQSORT_LT (_hi, _mid)) \ _GKQSORT_SWAP (_mid, _hi, _hold); \ else \ goto _jump_over; \ if (GKQSORT_LT (_mid, _lo)) \ _GKQSORT_SWAP (_mid, _lo, _hold); \ _jump_over:; \ \ _left_ptr = _lo + 1; \ _right_ptr = _hi - 1; \ \ /* Here's the famous ``collapse the walls'' section of quicksort. \ Gotta like those tight inner loops! They are the main reason \ that this algorithm runs much faster than others. */ \ do { \ while (GKQSORT_LT (_left_ptr, _mid)) \ ++_left_ptr; \ \ while (GKQSORT_LT (_mid, _right_ptr)) \ --_right_ptr; \ \ if (_left_ptr < _right_ptr) { \ _GKQSORT_SWAP (_left_ptr, _right_ptr, _hold); \ if (_mid == _left_ptr) \ _mid = _right_ptr; \ else if (_mid == _right_ptr) \ _mid = _left_ptr; \ ++_left_ptr; \ --_right_ptr; \ } \ else if (_left_ptr == _right_ptr) { \ ++_left_ptr; \ --_right_ptr; \ break; \ } \ } while (_left_ptr <= _right_ptr); \ \ /* Set up pointers for next iteration. First determine whether \ left and right partitions are below the threshold size. If so, \ ignore one or both. Otherwise, push the larger partition's \ bounds on the stack and continue sorting the smaller one. */ \ \ if (_right_ptr - _lo <= _GKQSORT_MAX_THRESH) { \ if (_hi - _left_ptr <= _GKQSORT_MAX_THRESH) \ /* Ignore both small partitions. */ \ _GKQSORT_POP (_lo, _hi, _top); \ else \ /* Ignore small left partition. */ \ _lo = _left_ptr; \ } \ else if (_hi - _left_ptr <= _GKQSORT_MAX_THRESH) \ /* Ignore small right partition. */ \ _hi = _right_ptr; \ else if (_right_ptr - _lo > _hi - _left_ptr) { \ /* Push larger left partition indices. */ \ _GKQSORT_PUSH (_top, _lo, _right_ptr); \ _lo = _left_ptr; \ } \ else { \ /* Push larger right partition indices. */ \ _GKQSORT_PUSH (_top, _left_ptr, _hi); \ _hi = _right_ptr; \ } \ } \ } \ \ /* Once the BASE array is partially sorted by quicksort the rest \ is completely sorted using insertion sort, since this is efficient \ for partitions below MAX_THRESH size. BASE points to the \ beginning of the array to sort, and END_PTR points at the very \ last element in the array (*not* one beyond it!). */ \ \ { \ GKQSORT_TYPE *const _end_ptr = _base + _elems - 1; \ GKQSORT_TYPE *_tmp_ptr = _base; \ register GKQSORT_TYPE *_run_ptr; \ GKQSORT_TYPE *_thresh; \ \ _thresh = _base + _GKQSORT_MAX_THRESH; \ if (_thresh > _end_ptr) \ _thresh = _end_ptr; \ \ /* Find smallest element in first threshold and place it at the \ array's beginning. This is the smallest array element, \ and the operation speeds up insertion sort's inner loop. */ \ \ for (_run_ptr = _tmp_ptr + 1; _run_ptr <= _thresh; ++_run_ptr) \ if (GKQSORT_LT (_run_ptr, _tmp_ptr)) \ _tmp_ptr = _run_ptr; \ \ if (_tmp_ptr != _base) \ _GKQSORT_SWAP (_tmp_ptr, _base, _hold); \ \ /* Insertion sort, running from left-hand-side \ * up to right-hand-side. */ \ \ _run_ptr = _base + 1; \ while (++_run_ptr <= _end_ptr) { \ _tmp_ptr = _run_ptr - 1; \ while (GKQSORT_LT (_run_ptr, _tmp_ptr)) \ --_tmp_ptr; \ \ ++_tmp_ptr; \ if (_tmp_ptr != _run_ptr) { \ GKQSORT_TYPE *_trav = _run_ptr + 1; \ while (--_trav >= _run_ptr) { \ GKQSORT_TYPE *_hi; GKQSORT_TYPE *_lo; \ _hold = *_trav; \ \ for (_hi = _lo = _trav; --_lo >= _tmp_ptr; _hi = _lo) \ *_hi = *_lo; \ *_hi = _hold; \ } \ } \ } \ } \ \ } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/conf/����������������������������������������0000755�0001751�0000144�00000000000�14576343415�023260� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/conf/check_thread_storage.c������������������0000644�0001751�0000144�00000000110�14552026002�027524� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������extern __thread int x; int main(int argc, char **argv) { return 0; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/memory.c�������������������������������������0000644�0001751�0000144�00000017114�14575233601�024005� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file memory.c \brief This file contains various allocation routines The allocation routines included are for 1D and 2D arrays of the most datatypes that GKlib support. Many of these routines are defined with the help of the macros in gk_memory.h. These macros can be used to define other memory allocation routines. \date Started 4/3/2007 \author George \version\verbatim $Id: memory.c 10783 2011-09-21 23:19:56Z karypis $ \endverbatim */ #include "GKlib.h" /* This is for the global mcore that tracks all heap allocations */ static __thread gk_mcore_t *gkmcore = NULL; /*************************************************************************/ /*! Define the set of memory allocation routines for each data type */ /**************************************************************************/ GK_MKALLOC(gk_c, char) GK_MKALLOC(gk_i, int) GK_MKALLOC(gk_i32, int32_t) GK_MKALLOC(gk_i64, int64_t) GK_MKALLOC(gk_z, ssize_t) GK_MKALLOC(gk_f, float) GK_MKALLOC(gk_d, double) GK_MKALLOC(gk_idx, gk_idx_t) GK_MKALLOC(gk_ckv, gk_ckv_t) GK_MKALLOC(gk_ikv, gk_ikv_t) GK_MKALLOC(gk_i32kv, gk_i32kv_t) GK_MKALLOC(gk_i64kv, gk_i64kv_t) GK_MKALLOC(gk_zkv, gk_zkv_t) GK_MKALLOC(gk_fkv, gk_fkv_t) GK_MKALLOC(gk_dkv, gk_dkv_t) GK_MKALLOC(gk_skv, gk_skv_t) GK_MKALLOC(gk_idxkv, gk_idxkv_t) /*************************************************************************/ /*! This function allocates a two-dimensional matrix. */ /*************************************************************************/ void gk_AllocMatrix(void ***r_matrix, size_t elmlen, size_t ndim1, size_t ndim2) { gk_idx_t i, j; void **matrix; *r_matrix = NULL; if ((matrix = (void **)gk_malloc(ndim1*sizeof(void *), "gk_AllocMatrix: matrix")) == NULL) return; for (i=0; icmop == 0) { gk_gkmcoreDestroy(&gkmcore, showstats); gkmcore = NULL; } } } /*************************************************************************/ /*! This function is my wrapper around malloc that provides the following enhancements over malloc: * It always allocates one byte of memory, even if 0 bytes are requested. This is to ensure that checks of returned values do not lead to NULL due to 0 bytes requested. * It zeros-out the memory that is allocated. This is for a quick init of the underlying datastructures. */ /**************************************************************************/ void *gk_malloc(size_t nbytes, char *msg) { void *ptr=NULL; if (nbytes == 0) nbytes++; /* Force mallocs to actually allocate some memory */ ptr = (void *)malloc(nbytes); if (ptr == NULL) { #ifndef NDEBUG fprintf(stderr, " Current memory used: %10zu bytes\n", gk_GetCurMemoryUsed()); fprintf(stderr, " Maximum memory used: %10zu bytes\n", gk_GetMaxMemoryUsed()); #endif gk_errexit(SIGMEM, "***Memory allocation failed for %s. Requested size: %zu bytes", msg, nbytes); return NULL; } /* add this memory allocation */ if (gkmcore != NULL) gk_gkmcoreAdd(gkmcore, GK_MOPT_HEAP, nbytes, ptr); /* zero-out the allocated space */ #ifndef NDEBUG memset(ptr, 0, nbytes); #endif return ptr; } /************************************************************************* * This function is my wrapper around realloc **************************************************************************/ void *gk_realloc(void *oldptr, size_t nbytes, char *msg) { void *ptr=NULL; if (nbytes == 0) nbytes++; /* Force mallocs to actually allocate some memory */ /* remove this memory de-allocation */ if (gkmcore != NULL && oldptr != NULL) gk_gkmcoreDel(gkmcore, oldptr); ptr = (void *)realloc(oldptr, nbytes); if (ptr == NULL) { #ifndef NDEBUG fprintf(stderr, " Maximum memory used: %10zu bytes\n", gk_GetMaxMemoryUsed()); fprintf(stderr, " Current memory used: %10zu bytes\n", gk_GetCurMemoryUsed()); #endif gk_errexit(SIGMEM, "***Memory realloc failed for %s. " "Requested size: %zu bytes", msg, nbytes); return NULL; } /* add this memory allocation */ if (gkmcore != NULL) gk_gkmcoreAdd(gkmcore, GK_MOPT_HEAP, nbytes, ptr); return ptr; } /************************************************************************* * This function is my wrapper around free, allows multiple pointers **************************************************************************/ void gk_free(void **ptr1,...) { va_list plist; void **ptr; if (*ptr1 != NULL) { free(*ptr1); /* remove this memory de-allocation */ if (gkmcore != NULL) gk_gkmcoreDel(gkmcore, *ptr1); } *ptr1 = NULL; va_start(plist, ptr1); while ((ptr = va_arg(plist, void **)) != LTERM) { if (*ptr != NULL) { free(*ptr); /* remove this memory de-allocation */ if (gkmcore != NULL) gk_gkmcoreDel(gkmcore, *ptr); } *ptr = NULL; } va_end(plist); } /************************************************************************* * This function returns the current ammount of dynamically allocated * memory that is used by the system **************************************************************************/ size_t gk_GetCurMemoryUsed(void) { if (gkmcore == NULL) return 0; else return gkmcore->cur_hallocs; } /************************************************************************* * This function returns the maximum ammount of dynamically allocated * memory that was used by the system **************************************************************************/ size_t gk_GetMaxMemoryUsed(void) { if (gkmcore == NULL) return 0; else return gkmcore->max_hallocs; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/tokenizer.c����������������������������������0000644�0001751�0000144�00000005134�14552244506�024507� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file tokenizer.c \brief String tokenization routines This file contains various routines for splitting an input string into tokens and returning them in form of a list. The goal is to mimic perl's split function. \date Started 11/23/04 \author George \version\verbatim $Id: tokenizer.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim */ #include "GKlib.h" /************************************************************************ * This function tokenizes a string based on the user-supplied delimiters * list. The resulting tokens are returned into an array of strings. *************************************************************************/ void gk_strtokenize(char *str, char *delim, gk_Tokens_t *tokens) { int i, ntoks, slen; tokens->strbuf = gk_strdup(str); slen = strlen(str); str = tokens->strbuf; /* Scan once to determine the number of tokens */ for (ntoks=0, i=0; intoks = ntoks; tokens->list = (char **)gk_malloc(ntoks*sizeof(char *), "strtokenize: tokens->list"); /* Scan a second time to mark and link the tokens */ for (ntoks=0, i=0; ilist[ntoks++] = str+i; /* Consume all the consecutive characters from the token */ while (ilist, &tokens->strbuf, LTERM); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/ms_stdint.h����������������������������������0000644�0001751�0000144�00000016667�14552244506�024523� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ // ISO C9x compliant stdint.h for Microsoft Visual Studio // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 // // Copyright (c) 2006 Alexander Chemeris // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. The name of the author may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // /////////////////////////////////////////////////////////////////////////////// #ifndef _MSC_VER // [ #error "Use this header only with Microsoft Visual C++ compilers!" #endif // _MSC_VER ] #ifndef _MSC_STDINT_H_ // [ #define _MSC_STDINT_H_ #if _MSC_VER > 1000 #pragma once #endif #include // For Visual Studio 6 in C++ mode wrap include with 'extern "C++" {}' // or compiler give many errors like this: // error C2733: second C linkage of overloaded function 'wmemchr' not allowed #if (_MSC_VER < 1300) && defined(__cplusplus) extern "C++" { #endif # include #if (_MSC_VER < 1300) && defined(__cplusplus) } #endif // 7.18.1 Integer types // 7.18.1.1 Exact-width integer types typedef __int8 int8_t; typedef __int16 int16_t; typedef __int32 int32_t; typedef __int64 int64_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; // 7.18.1.2 Minimum-width integer types typedef int8_t int_least8_t; typedef int16_t int_least16_t; typedef int32_t int_least32_t; typedef int64_t int_least64_t; typedef uint8_t uint_least8_t; typedef uint16_t uint_least16_t; typedef uint32_t uint_least32_t; typedef uint64_t uint_least64_t; // 7.18.1.3 Fastest minimum-width integer types typedef int8_t int_fast8_t; typedef int16_t int_fast16_t; typedef int32_t int_fast32_t; typedef int64_t int_fast64_t; typedef uint8_t uint_fast8_t; typedef uint16_t uint_fast16_t; typedef uint32_t uint_fast32_t; typedef uint64_t uint_fast64_t; // 7.18.1.4 Integer types capable of holding object pointers #ifdef _WIN64 // [ typedef __int64 intptr_t; typedef unsigned __int64 uintptr_t; #else // _WIN64 ][ typedef int intptr_t; typedef unsigned int uintptr_t; #endif // _WIN64 ] // 7.18.1.5 Greatest-width integer types typedef int64_t intmax_t; typedef uint64_t uintmax_t; // 7.18.2 Limits of specified-width integer types #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 // 7.18.2.1 Limits of exact-width integer types #define INT8_MIN ((int8_t)_I8_MIN) #define INT8_MAX _I8_MAX #define INT16_MIN ((int16_t)_I16_MIN) #define INT16_MAX _I16_MAX #define INT32_MIN ((int32_t)_I32_MIN) #define INT32_MAX _I32_MAX #define INT64_MIN ((int64_t)_I64_MIN) #define INT64_MAX _I64_MAX #define UINT8_MAX _UI8_MAX #define UINT16_MAX _UI16_MAX #define UINT32_MAX _UI32_MAX #define UINT64_MAX _UI64_MAX // 7.18.2.2 Limits of minimum-width integer types #define INT_LEAST8_MIN INT8_MIN #define INT_LEAST8_MAX INT8_MAX #define INT_LEAST16_MIN INT16_MIN #define INT_LEAST16_MAX INT16_MAX #define INT_LEAST32_MIN INT32_MIN #define INT_LEAST32_MAX INT32_MAX #define INT_LEAST64_MIN INT64_MIN #define INT_LEAST64_MAX INT64_MAX #define UINT_LEAST8_MAX UINT8_MAX #define UINT_LEAST16_MAX UINT16_MAX #define UINT_LEAST32_MAX UINT32_MAX #define UINT_LEAST64_MAX UINT64_MAX // 7.18.2.3 Limits of fastest minimum-width integer types #define INT_FAST8_MIN INT8_MIN #define INT_FAST8_MAX INT8_MAX #define INT_FAST16_MIN INT16_MIN #define INT_FAST16_MAX INT16_MAX #define INT_FAST32_MIN INT32_MIN #define INT_FAST32_MAX INT32_MAX #define INT_FAST64_MIN INT64_MIN #define INT_FAST64_MAX INT64_MAX #define UINT_FAST8_MAX UINT8_MAX #define UINT_FAST16_MAX UINT16_MAX #define UINT_FAST32_MAX UINT32_MAX #define UINT_FAST64_MAX UINT64_MAX // 7.18.2.4 Limits of integer types capable of holding object pointers #ifdef _WIN64 // [ # define INTPTR_MIN INT64_MIN # define INTPTR_MAX INT64_MAX # define UINTPTR_MAX UINT64_MAX #else // _WIN64 ][ # define INTPTR_MIN INT32_MIN # define INTPTR_MAX INT32_MAX # define UINTPTR_MAX UINT32_MAX #endif // _WIN64 ] // 7.18.2.5 Limits of greatest-width integer types #define INTMAX_MIN INT64_MIN #define INTMAX_MAX INT64_MAX #define UINTMAX_MAX UINT64_MAX // 7.18.3 Limits of other integer types #ifdef _WIN64 // [ # define PTRDIFF_MIN _I64_MIN # define PTRDIFF_MAX _I64_MAX #else // _WIN64 ][ # define PTRDIFF_MIN _I32_MIN # define PTRDIFF_MAX _I32_MAX #endif // _WIN64 ] #define SIG_ATOMIC_MIN INT_MIN #define SIG_ATOMIC_MAX INT_MAX #ifndef SIZE_MAX // [ # ifdef _WIN64 // [ # define SIZE_MAX _UI64_MAX # else // _WIN64 ][ # define SIZE_MAX _UI32_MAX # endif // _WIN64 ] #endif // SIZE_MAX ] // WCHAR_MIN and WCHAR_MAX are also defined in #ifndef WCHAR_MIN // [ # define WCHAR_MIN 0 #endif // WCHAR_MIN ] #ifndef WCHAR_MAX // [ # define WCHAR_MAX _UI16_MAX #endif // WCHAR_MAX ] #define WINT_MIN 0 #define WINT_MAX _UI16_MAX #endif // __STDC_LIMIT_MACROS ] // 7.18.4 Limits of other integer types #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 // 7.18.4.1 Macros for minimum-width integer constants #define INT8_C(val) val##i8 #define INT16_C(val) val##i16 #define INT32_C(val) val##i32 #define INT64_C(val) val##i64 #define UINT8_C(val) val##ui8 #define UINT16_C(val) val##ui16 #define UINT32_C(val) val##ui32 #define UINT64_C(val) val##ui64 // 7.18.4.2 Macros for greatest-width integer constants #define INTMAX_C INT64_C #define UINTMAX_C UINT64_C #endif // __STDC_CONSTANT_MACROS ] #endif // _MSC_STDINT_H_ ] �������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/fkvkselect.c���������������������������������0000644�0001751�0000144�00000007375�14552244506�024647� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file dfkvkselect.c \brief Sorts only the largest k values \date Started 7/14/00 \author George \version\verbatim $Id: fkvkselect.c 10711 2011-08-31 22:23:04Z karypis $\endverbatim */ #include "GKlib.h" /* Byte-wise swap two items of size SIZE. */ #define QSSWAP(a, b, stmp) do { stmp = (a); (a) = (b); (b) = stmp; } while (0) /******************************************************************************/ /*! This function puts the 'topk' largest values in the beginning of the array */ /*******************************************************************************/ int gk_dfkvkselect(size_t n, int topk, gk_fkv_t *cand) { int i, j, lo, hi, mid; gk_fkv_t stmp; float pivot; if (n <= topk) return n; /* return if the array has fewer elements than we want */ for (lo=0, hi=n-1; lo < hi;) { mid = lo + ((hi-lo) >> 1); /* select the median */ if (cand[lo].key < cand[mid].key) mid = lo; if (cand[hi].key > cand[mid].key) mid = hi; else goto jump_over; if (cand[lo].key < cand[mid].key) mid = lo; jump_over: QSSWAP(cand[mid], cand[hi], stmp); pivot = cand[hi].key; /* the partitioning algorithm */ for (i=lo-1, j=lo; j= pivot) { i++; QSSWAP(cand[i], cand[j], stmp); } } i++; QSSWAP(cand[i], cand[hi], stmp); if (i > topk) hi = i-1; else if (i < topk) lo = i+1; else break; } /* if (cand[lo].key < cand[hi].key) printf("Hmm Error: %d %d %d %f %f\n", i, lo, hi, cand[lo].key, cand[hi].key); for (i=topk; i cand[j].key) printf("Hmm Error: %d %d %f %f %d %d\n", i, j, cand[i].key, cand[j].key, lo, hi); } */ return topk; } /******************************************************************************/ /*! This function puts the 'topk' smallest values in the beginning of the array */ /*******************************************************************************/ int gk_ifkvkselect(size_t n, int topk, gk_fkv_t *cand) { int i, j, lo, hi, mid; gk_fkv_t stmp; float pivot; if (n <= topk) return n; /* return if the array has fewer elements than we want */ for (lo=0, hi=n-1; lo < hi;) { mid = lo + ((hi-lo) >> 1); /* select the median */ if (cand[lo].key > cand[mid].key) mid = lo; if (cand[hi].key < cand[mid].key) mid = hi; else goto jump_over; if (cand[lo].key > cand[mid].key) mid = lo; jump_over: QSSWAP(cand[mid], cand[hi], stmp); pivot = cand[hi].key; /* the partitioning algorithm */ for (i=lo-1, j=lo; j topk) hi = i-1; else if (i < topk) lo = i+1; else break; } /* if (cand[lo].key > cand[hi].key) printf("Hmm Error: %d %d %d %f %f\n", i, lo, hi, cand[lo].key, cand[hi].key); for (i=topk; i 1000 #pragma once #endif #include /* Test macros for file types. */ #define __S_ISTYPE(mode, mask) (((mode) & S_IFMT) == (mask)) #define S_ISDIR(mode) __S_ISTYPE((mode), S_IFDIR) #define S_ISCHR(mode) __S_ISTYPE((mode), S_IFCHR) #define S_ISBLK(mode) __S_ISTYPE((mode), S_IFBLK) #define S_ISREG(mode) __S_ISTYPE((mode), S_IFREG) #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/timers.c�������������������������������������0000644�0001751�0000144�00000003314�14552244506�023776� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file timers.c \brief Various timing functions \date Started 4/12/2007 \author George \version\verbatim $Id: timers.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim */ #include "GKlib.h" /************************************************************************* * This function returns the CPU seconds **************************************************************************/ double gk_WClockSeconds(void) { #ifdef __GNUC__ struct timeval ctime; gettimeofday(&ctime, NULL); return (double)ctime.tv_sec + (double).000001*ctime.tv_usec; #else return (double)time(NULL); #endif } /************************************************************************* * This function returns the CPU seconds **************************************************************************/ double gk_CPUSeconds(void) { //#ifdef __OPENMP__ #ifdef __OPENMPXXXX__ return omp_get_wtime(); #else #if defined(WIN32) || defined(__MINGW32__) return((double) clock()/CLOCKS_PER_SEC); #else struct rusage r; getrusage(RUSAGE_SELF, &r); return ((r.ru_utime.tv_sec + r.ru_stime.tv_sec) + 1.0e-6*(r.ru_utime.tv_usec + r.ru_stime.tv_usec)); #endif #endif } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_proto.h�����������������������������������0000644�0001751�0000144�00000035355�14552244506�024336� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file gk_proto.h \brief This file contains function prototypes \date Started 3/27/2007 \author George \version\verbatim $Id: gk_proto.h 12591 2012-09-01 19:03:15Z karypis $ \endverbatim */ #ifndef _GK_PROTO_H_ #define _GK_PROTO_H_ #ifdef __cplusplus extern "C" { #endif /*------------------------------------------------------------- * blas.c *-------------------------------------------------------------*/ GK_MKBLAS_PROTO(gk_c, char, int) GK_MKBLAS_PROTO(gk_i, int, int) GK_MKBLAS_PROTO(gk_i32, int32_t, int32_t) GK_MKBLAS_PROTO(gk_i64, int64_t, int64_t) GK_MKBLAS_PROTO(gk_z, ssize_t, ssize_t) GK_MKBLAS_PROTO(gk_f, float, float) GK_MKBLAS_PROTO(gk_d, double, double) GK_MKBLAS_PROTO(gk_idx, gk_idx_t, gk_idx_t) /*------------------------------------------------------------- * io.c *-------------------------------------------------------------*/ FILE *gk_fopen(char *, char *, const char *); void gk_fclose(FILE *); gk_idx_t gk_getline(char **lineptr, size_t *n, FILE *stream); char **gk_readfile(char *fname, gk_idx_t *r_nlines); int32_t *gk_i32readfile(char *fname, gk_idx_t *r_nlines); int64_t *gk_i64readfile(char *fname, gk_idx_t *r_nlines); int32_t *gk_i32readfilebin(char *fname, ssize_t *r_nelmnts); int64_t *gk_i64readfilebin(char *fname, ssize_t *r_nelmnts); float *gk_freadfilebin(char *fname, ssize_t *r_nelmnts); size_t gk_fwritefilebin(char *fname, size_t n, float *a); double *gk_dreadfilebin(char *fname, ssize_t *r_nelmnts); /*------------------------------------------------------------- * fs.c *-------------------------------------------------------------*/ int gk_fexists(char *); int gk_dexists(char *); intmax_t gk_getfsize(char *); void gk_getfilestats(char *fname, size_t *r_nlines, size_t *r_ntokens, size_t *r_max_nlntokens, size_t *r_nbytes); char *gk_getbasename(char *path); char *gk_getextname(char *path); char *gk_getfilename(char *path); char *gk_getpathname(char *path); int gk_mkpath(char *); int gk_rmpath(char *); /*------------------------------------------------------------- * memory.c *-------------------------------------------------------------*/ GK_MKALLOC_PROTO(gk_c, char) GK_MKALLOC_PROTO(gk_i, int) GK_MKALLOC_PROTO(gk_i32, int32_t) GK_MKALLOC_PROTO(gk_i64, int64_t) GK_MKALLOC_PROTO(gk_z, ssize_t) GK_MKALLOC_PROTO(gk_f, float) GK_MKALLOC_PROTO(gk_d, double) GK_MKALLOC_PROTO(gk_idx, gk_idx_t) GK_MKALLOC_PROTO(gk_ckv, gk_ckv_t) GK_MKALLOC_PROTO(gk_ikv, gk_ikv_t) GK_MKALLOC_PROTO(gk_i32kv, gk_i32kv_t) GK_MKALLOC_PROTO(gk_i64kv, gk_i64kv_t) GK_MKALLOC_PROTO(gk_zkv, gk_zkv_t) GK_MKALLOC_PROTO(gk_fkv, gk_fkv_t) GK_MKALLOC_PROTO(gk_dkv, gk_dkv_t) GK_MKALLOC_PROTO(gk_skv, gk_skv_t) GK_MKALLOC_PROTO(gk_idxkv, gk_idxkv_t) void gk_AllocMatrix(void ***, size_t, size_t , size_t); void gk_FreeMatrix(void ***, size_t, size_t); // int gk_malloc_init(); int gk_malloc_init(void); void gk_malloc_cleanup(int showstats); void *gk_malloc(size_t nbytes, char *msg); void *gk_realloc(void *oldptr, size_t nbytes, char *msg); void gk_free(void **ptr1,...); // size_t gk_GetCurMemoryUsed(); size_t gk_GetCurMemoryUsed(void); // size_t gk_GetMaxMemoryUsed(); size_t gk_GetMaxMemoryUsed(void); /*------------------------------------------------------------- * seq.c *-------------------------------------------------------------*/ gk_seq_t *gk_seq_ReadGKMODPSSM(char *file_name); gk_i2cc2i_t *gk_i2cc2i_create_common(char *alphabet); void gk_seq_init(gk_seq_t *seq); /*------------------------------------------------------------- * pdb.c *-------------------------------------------------------------*/ char gk_threetoone(char *res); void gk_freepdbf(pdbf *p); pdbf *gk_readpdbfile(char *fname); void gk_writefullatom(pdbf *p, char *fname); void gk_writebackbone(pdbf *p, char *fname); void gk_writealphacarbons(pdbf *p, char *fname); void gk_showcorruption(pdbf *p); /*------------------------------------------------------------- * error.c *-------------------------------------------------------------*/ void gk_set_exit_on_error(int value); void errexit(char *,...); void gk_errexit(int signum, char *,...); // int gk_sigtrap(); int gk_sigtrap(void); // int gk_siguntrap(); int gk_siguntrap(void); void gk_sigthrow(int signum); // void gk_SetSignalHandlers(); void gk_SetSignalHandlers(void); // void gk_SetSignalHandlers(); void gk_SetSignalHandlers(void); // void gk_UnsetSignalHandlers(); void gk_UnsetSignalHandlers(void); void gk_NonLocalExit_Handler(int signum); char *gk_strerror(int errnum); // void PrintBackTrace(); void PrintBackTrace(void); /*------------------------------------------------------------- * util.c *-------------------------------------------------------------*/ void gk_RandomPermute(size_t, int *, int); void gk_array2csr(size_t n, size_t range, int *array, int *ptr, int *ind); int gk_log2(int); int gk_ispow2(int); float gk_flog2(float); /*------------------------------------------------------------- * time.c *-------------------------------------------------------------*/ gk_wclock_t gk_WClockSeconds(void); double gk_CPUSeconds(void); /*------------------------------------------------------------- * string.c *-------------------------------------------------------------*/ char *gk_strchr_replace(char *str, char *fromlist, char *tolist); int gk_strstr_replace(char *str, char *pattern, char *replacement, char *options, char **new_str); char *gk_strtprune(char *, char *); char *gk_strhprune(char *, char *); char *gk_strtoupper(char *); char *gk_strtolower(char *); char *gk_strdup(char *orgstr); int gk_strcasecmp(char *s1, char *s2); int gk_strrcmp(char *s1, char *s2); char *gk_time2str(time_t time); time_t gk_str2time(char *str); int gk_GetStringID(gk_StringMap_t *strmap, char *key); /*------------------------------------------------------------- * sort.c *-------------------------------------------------------------*/ void gk_csorti(size_t, char *); void gk_csortd(size_t, char *); void gk_isorti(size_t, int *); void gk_isortd(size_t, int *); void gk_fsorti(size_t, float *); void gk_fsortd(size_t, float *); void gk_dsorti(size_t, double *); void gk_dsortd(size_t, double *); void gk_idxsorti(size_t, gk_idx_t *); void gk_idxsortd(size_t, gk_idx_t *); void gk_ckvsorti(size_t, gk_ckv_t *); void gk_ckvsortd(size_t, gk_ckv_t *); void gk_ikvsorti(size_t, gk_ikv_t *); void gk_ikvsortd(size_t, gk_ikv_t *); void gk_i32kvsorti(size_t, gk_i32kv_t *); void gk_i32kvsortd(size_t, gk_i32kv_t *); void gk_i64kvsorti(size_t, gk_i64kv_t *); void gk_i64kvsortd(size_t, gk_i64kv_t *); void gk_zkvsorti(size_t, gk_zkv_t *); void gk_zkvsortd(size_t, gk_zkv_t *); void gk_fkvsorti(size_t, gk_fkv_t *); void gk_fkvsortd(size_t, gk_fkv_t *); void gk_dkvsorti(size_t, gk_dkv_t *); void gk_dkvsortd(size_t, gk_dkv_t *); void gk_skvsorti(size_t, gk_skv_t *); void gk_skvsortd(size_t, gk_skv_t *); void gk_idxkvsorti(size_t, gk_idxkv_t *); void gk_idxkvsortd(size_t, gk_idxkv_t *); /*------------------------------------------------------------- * Selection routines *-------------------------------------------------------------*/ int gk_dfkvkselect(size_t, int, gk_fkv_t *); int gk_ifkvkselect(size_t, int, gk_fkv_t *); /*------------------------------------------------------------- * Priority queue *-------------------------------------------------------------*/ GK_MKPQUEUE_PROTO(gk_ipq, gk_ipq_t, int, gk_idx_t) GK_MKPQUEUE_PROTO(gk_i32pq, gk_i32pq_t, int32_t, gk_idx_t) GK_MKPQUEUE_PROTO(gk_i64pq, gk_i64pq_t, int64_t, gk_idx_t) GK_MKPQUEUE_PROTO(gk_fpq, gk_fpq_t, float, gk_idx_t) GK_MKPQUEUE_PROTO(gk_dpq, gk_dpq_t, double, gk_idx_t) GK_MKPQUEUE_PROTO(gk_idxpq, gk_idxpq_t, gk_idx_t, gk_idx_t) /*------------------------------------------------------------- * HTable routines *-------------------------------------------------------------*/ gk_HTable_t *HTable_Create(int nelements); void HTable_Reset(gk_HTable_t *htable); void HTable_Resize(gk_HTable_t *htable, int nelements); void HTable_Insert(gk_HTable_t *htable, int key, int val); void HTable_Delete(gk_HTable_t *htable, int key); int HTable_Search(gk_HTable_t *htable, int key); int HTable_GetNext(gk_HTable_t *htable, int key, int *val, int type); int HTable_SearchAndDelete(gk_HTable_t *htable, int key); void HTable_Destroy(gk_HTable_t *htable); int HTable_HFunction(int nelements, int key); /*------------------------------------------------------------- * Tokenizer routines *-------------------------------------------------------------*/ void gk_strtokenize(char *line, char *delim, gk_Tokens_t *tokens); void gk_freetokenslist(gk_Tokens_t *tokens); /*------------------------------------------------------------- * Encoder/Decoder *-------------------------------------------------------------*/ void encodeblock(unsigned char *in, unsigned char *out); void decodeblock(unsigned char *in, unsigned char *out); void GKEncodeBase64(int nbytes, unsigned char *inbuffer, unsigned char *outbuffer); void GKDecodeBase64(int nbytes, unsigned char *inbuffer, unsigned char *outbuffer); /*------------------------------------------------------------- * random.c *-------------------------------------------------------------*/ GK_MKRANDOM_PROTO(gk_c, size_t, char) GK_MKRANDOM_PROTO(gk_i, size_t, int) GK_MKRANDOM_PROTO(gk_f, size_t, float) GK_MKRANDOM_PROTO(gk_d, size_t, double) GK_MKRANDOM_PROTO(gk_idx, size_t, gk_idx_t) GK_MKRANDOM_PROTO(gk_z, size_t, ssize_t) void gk_randinit(uint64_t); uint64_t gk_randint64(void); uint32_t gk_randint32(void); /*------------------------------------------------------------- * OpenMP fake functions *-------------------------------------------------------------*/ #if 0 // disabled for SuiteSparse #if !defined(__OPENMP__) void omp_set_num_threads(int num_threads); int omp_get_num_threads(void); int omp_get_max_threads(void); int omp_get_thread_num(void); int omp_get_num_procs(void); int omp_in_parallel(void); void omp_set_dynamic(int num_threads); int omp_get_dynamic(void); void omp_set_nested(int nested); int omp_get_nested(void); #endif /* __OPENMP__ */ #endif /*------------------------------------------------------------- * CSR-related functions *-------------------------------------------------------------*/ // gk_csr_t *gk_csr_Create(); gk_csr_t *gk_csr_Create(void); void gk_csr_Init(gk_csr_t *mat); void gk_csr_Free(gk_csr_t **mat); void gk_csr_FreeContents(gk_csr_t *mat); gk_csr_t *gk_csr_Dup(gk_csr_t *mat); gk_csr_t *gk_csr_ExtractSubmatrix(gk_csr_t *mat, int rstart, int nrows); gk_csr_t *gk_csr_ExtractRows(gk_csr_t *mat, int nrows, int *rind); gk_csr_t *gk_csr_ExtractPartition(gk_csr_t *mat, int *part, int pid); gk_csr_t **gk_csr_Split(gk_csr_t *mat, int *color); gk_csr_t *gk_csr_Read(char *filename, int format, int readvals, int numbering); void gk_csr_Write(gk_csr_t *mat, char *filename, int format, int writevals, int numbering); gk_csr_t *gk_csr_Prune(gk_csr_t *mat, int what, int minf, int maxf); gk_csr_t *gk_csr_LowFilter(gk_csr_t *mat, int what, int norm, float fraction); gk_csr_t *gk_csr_TopKPlusFilter(gk_csr_t *mat, int what, int topk, float keepval); gk_csr_t *gk_csr_ZScoreFilter(gk_csr_t *mat, int what, float zscore); void gk_csr_CompactColumns(gk_csr_t *mat); void gk_csr_SortIndices(gk_csr_t *mat, int what); void gk_csr_CreateIndex(gk_csr_t *mat, int what); void gk_csr_Normalize(gk_csr_t *mat, int what, int norm); void gk_csr_Scale(gk_csr_t *mat, int type); void gk_csr_ComputeSums(gk_csr_t *mat, int what); void gk_csr_ComputeSquaredNorms(gk_csr_t *mat, int what); float gk_csr_ComputeSimilarity(gk_csr_t *mat, int i1, int i2, int what, int simtype); int gk_csr_GetSimilarRows(gk_csr_t *mat, int nqterms, int *qind, float *qval, int simtype, int nsim, float minsim, gk_fkv_t *hits, int *_imarker, gk_fkv_t *i_cand); /* itemsets.c */ void gk_find_frequent_itemsets(int ntrans, ssize_t *tranptr, int *tranind, int minfreq, int maxfreq, int minlen, int maxlen, void (*process_itemset)(void *stateptr, int nitems, int *itemind, int ntrans, int *tranind), void *stateptr); /* evaluate.c */ float ComputeAccuracy(int n, gk_fkv_t *list); float ComputeROCn(int n, int maxN, gk_fkv_t *list); float ComputeMedianRFP(int n, gk_fkv_t *list); float ComputeMean (int n, float *values); float ComputeStdDev(int n, float *values); /* mcore.c */ gk_mcore_t *gk_mcoreCreate(size_t coresize); // gk_mcore_t *gk_gkmcoreCreate(); gk_mcore_t *gk_gkmcoreCreate(void); void gk_mcoreDestroy(gk_mcore_t **r_mcore, int showstats); void gk_gkmcoreDestroy(gk_mcore_t **r_mcore, int showstats); void *gk_mcoreMalloc(gk_mcore_t *mcore, size_t nbytes); void gk_mcorePush(gk_mcore_t *mcore); void gk_gkmcorePush(gk_mcore_t *mcore); void gk_mcorePop(gk_mcore_t *mcore); void gk_gkmcorePop(gk_mcore_t *mcore); void gk_mcoreAdd(gk_mcore_t *mcore, int type, size_t nbytes, void *ptr); void gk_gkmcoreAdd(gk_mcore_t *mcore, int type, size_t nbytes, void *ptr); void gk_mcoreDel(gk_mcore_t *mcore, void *ptr); void gk_gkmcoreDel(gk_mcore_t *mcore, void *ptr); /* rw.c */ int gk_rw_PageRank(gk_csr_t *mat, float lamda, float eps, int max_niter, float *pr); #if 0 /* graph.c */ gk_graph_t *gk_graph_Create(); void gk_graph_Init(gk_graph_t *graph); void gk_graph_Free(gk_graph_t **graph); void gk_graph_FreeContents(gk_graph_t *graph); gk_graph_t *gk_graph_Read(char *filename, int format, int isfewgts, int isfvwgts, int isfvsizes); void gk_graph_Write(gk_graph_t *graph, char *filename, int format); gk_graph_t *gk_graph_Dup(gk_graph_t *graph); gk_graph_t *gk_graph_ExtractSubgraph(gk_graph_t *graph, int vstart, int nvtxs); gk_graph_t *gk_graph_Reorder(gk_graph_t *graph, int32_t *perm, int32_t *iperm); int gk_graph_FindComponents(gk_graph_t *graph, int32_t *cptr, int32_t *cind); void gk_graph_ComputeBFSOrdering(gk_graph_t *graph, int v, int32_t **r_perm, int32_t **r_iperm); void gk_graph_ComputeBestFOrdering0(gk_graph_t *graph, int v, int type, int32_t **r_perm, int32_t **r_iperm); void gk_graph_ComputeBestFOrdering(gk_graph_t *graph, int v, int type, int32_t **r_perm, int32_t **r_iperm); void gk_graph_SingleSourceShortestPaths(gk_graph_t *graph, int v, void **r_sps); #endif #ifdef __cplusplus } #endif #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/original/������������������������������������0000755�0001751�0000144�00000000000�14576343415�024137� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/original/error.c�����������������������������0000644�0001751�0000144�00000013467�14552026002�025427� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*! \file error.c \brief Various error-handling functions This file contains functions dealing with error reporting and termination \author George \date 1/1/2007 \version\verbatim $Id: error.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim */ #define _GK_ERROR_C_ /* this is needed to properly declare the gk_jub* variables as an extern function in GKlib.h */ #include /* These are the jmp_buf for the graceful exit in case of severe errors. Multiple buffers are defined to allow for recursive invokation. */ #define MAX_JBUFS 128 __thread int gk_cur_jbufs=-1; __thread jmp_buf gk_jbufs[MAX_JBUFS]; __thread jmp_buf gk_jbuf; typedef void (*gksighandler_t)(int); /* These are the holders of the old singal handlers for the trapped signals */ static __thread gksighandler_t old_SIGMEM_handler; /* Custom signal */ static __thread gksighandler_t old_SIGERR_handler; /* Custom signal */ static __thread gksighandler_t old_SIGMEM_handlers[MAX_JBUFS]; /* Custom signal */ static __thread gksighandler_t old_SIGERR_handlers[MAX_JBUFS]; /* Custom signal */ /* The following is used to control if the gk_errexit() will actually abort or not. There is always a single copy of this variable */ static int gk_exit_on_error = 1; /*************************************************************************/ /*! This function sets the gk_exit_on_error variable */ /*************************************************************************/ void gk_set_exit_on_error(int value) { gk_exit_on_error = value; } /*************************************************************************/ /*! This function prints an error message and exits */ /*************************************************************************/ void errexit(char *f_str,...) { va_list argp; va_start(argp, f_str); vfprintf(stderr, f_str, argp); va_end(argp); if (strlen(f_str) == 0 || f_str[strlen(f_str)-1] != '\n') fprintf(stderr,"\n"); fflush(stderr); if (gk_exit_on_error) exit(-2); /* abort(); */ } /*************************************************************************/ /*! This function prints an error message and raises a signum signal */ /*************************************************************************/ void gk_errexit(int signum, char *f_str,...) { va_list argp; va_start(argp, f_str); vfprintf(stderr, f_str, argp); va_end(argp); fprintf(stderr,"\n"); fflush(stderr); if (gk_exit_on_error) raise(signum); } /***************************************************************************/ /*! This function sets a number of signal handlers and sets the return point of a longjmp */ /***************************************************************************/ int gk_sigtrap() { if (gk_cur_jbufs+1 >= MAX_JBUFS) return 0; gk_cur_jbufs++; old_SIGMEM_handlers[gk_cur_jbufs] = signal(SIGMEM, gk_sigthrow); old_SIGERR_handlers[gk_cur_jbufs] = signal(SIGERR, gk_sigthrow); return 1; } /***************************************************************************/ /*! This function sets the handlers for the signals to their default handlers */ /***************************************************************************/ int gk_siguntrap() { if (gk_cur_jbufs == -1) return 0; signal(SIGMEM, old_SIGMEM_handlers[gk_cur_jbufs]); signal(SIGERR, old_SIGERR_handlers[gk_cur_jbufs]); gk_cur_jbufs--; return 1; } /*************************************************************************/ /*! This function is the custome signal handler, which all it does is to perform a longjump to the most recent saved environment */ /*************************************************************************/ void gk_sigthrow(int signum) { longjmp(gk_jbufs[gk_cur_jbufs], signum); } /*************************************************************************** * This function sets a number of signal handlers and sets the return point * of a longjmp ****************************************************************************/ void gk_SetSignalHandlers() { old_SIGMEM_handler = signal(SIGMEM, gk_NonLocalExit_Handler); old_SIGERR_handler = signal(SIGERR, gk_NonLocalExit_Handler); } /*************************************************************************** * This function sets the handlers for the signals to their default handlers ****************************************************************************/ void gk_UnsetSignalHandlers() { signal(SIGMEM, old_SIGMEM_handler); signal(SIGERR, old_SIGERR_handler); } /************************************************************************* * This function is the handler for SIGUSR1 that implements the cleaning up * process prior to a non-local exit. **************************************************************************/ void gk_NonLocalExit_Handler(int signum) { longjmp(gk_jbuf, signum); } /*************************************************************************/ /*! \brief Thread-safe implementation of strerror() */ /**************************************************************************/ char *gk_strerror(int errnum) { #if defined(WIN32) || defined(__MINGW32__) return strerror(errnum); #else #ifndef SUNOS static __thread char buf[1024]; strerror_r(errnum, buf, 1024); buf[1023] = '\0'; return buf; #else return strerror(errnum); #endif #endif } /************************************************************************* * This function prints a backtrace of calling functions **************************************************************************/ void PrintBackTrace() { #ifdef HAVE_EXECINFO_H void *array[10]; int i, size; char **strings; size = backtrace(array, 10); strings = backtrace_symbols(array, size); printf("Obtained %d stack frames.\n", size); for (i=0; i /* This is for the global mcore that tracks all heap allocations */ static __thread gk_mcore_t *gkmcore = NULL; /*************************************************************************/ /*! Define the set of memory allocation routines for each data type */ /**************************************************************************/ GK_MKALLOC(gk_c, char) GK_MKALLOC(gk_i, int) GK_MKALLOC(gk_i32, int32_t) GK_MKALLOC(gk_i64, int64_t) GK_MKALLOC(gk_z, ssize_t) GK_MKALLOC(gk_f, float) GK_MKALLOC(gk_d, double) GK_MKALLOC(gk_idx, gk_idx_t) GK_MKALLOC(gk_ckv, gk_ckv_t) GK_MKALLOC(gk_ikv, gk_ikv_t) GK_MKALLOC(gk_i32kv, gk_i32kv_t) GK_MKALLOC(gk_i64kv, gk_i64kv_t) GK_MKALLOC(gk_zkv, gk_zkv_t) GK_MKALLOC(gk_fkv, gk_fkv_t) GK_MKALLOC(gk_dkv, gk_dkv_t) GK_MKALLOC(gk_skv, gk_skv_t) GK_MKALLOC(gk_idxkv, gk_idxkv_t) /*************************************************************************/ /*! This function allocates a two-dimensional matrix. */ /*************************************************************************/ void gk_AllocMatrix(void ***r_matrix, size_t elmlen, size_t ndim1, size_t ndim2) { gk_idx_t i, j; void **matrix; *r_matrix = NULL; if ((matrix = (void **)gk_malloc(ndim1*sizeof(void *), "gk_AllocMatrix: matrix")) == NULL) return; for (i=0; icmop == 0) { gk_gkmcoreDestroy(&gkmcore, showstats); gkmcore = NULL; } } } /*************************************************************************/ /*! This function is my wrapper around malloc that provides the following enhancements over malloc: * It always allocates one byte of memory, even if 0 bytes are requested. This is to ensure that checks of returned values do not lead to NULL due to 0 bytes requested. * It zeros-out the memory that is allocated. This is for a quick init of the underlying datastructures. */ /**************************************************************************/ void *gk_malloc(size_t nbytes, char *msg) { void *ptr=NULL; if (nbytes == 0) nbytes++; /* Force mallocs to actually allocate some memory */ ptr = (void *)malloc(nbytes); if (ptr == NULL) { fprintf(stderr, " Current memory used: %10zu bytes\n", gk_GetCurMemoryUsed()); fprintf(stderr, " Maximum memory used: %10zu bytes\n", gk_GetMaxMemoryUsed()); gk_errexit(SIGMEM, "***Memory allocation failed for %s. Requested size: %zu bytes", msg, nbytes); return NULL; } /* add this memory allocation */ if (gkmcore != NULL) gk_gkmcoreAdd(gkmcore, GK_MOPT_HEAP, nbytes, ptr); /* zero-out the allocated space */ #ifndef NDEBUG memset(ptr, 0, nbytes); #endif return ptr; } /************************************************************************* * This function is my wrapper around realloc **************************************************************************/ void *gk_realloc(void *oldptr, size_t nbytes, char *msg) { void *ptr=NULL; if (nbytes == 0) nbytes++; /* Force mallocs to actually allocate some memory */ /* remove this memory de-allocation */ if (gkmcore != NULL && oldptr != NULL) gk_gkmcoreDel(gkmcore, oldptr); ptr = (void *)realloc(oldptr, nbytes); if (ptr == NULL) { fprintf(stderr, " Maximum memory used: %10zu bytes\n", gk_GetMaxMemoryUsed()); fprintf(stderr, " Current memory used: %10zu bytes\n", gk_GetCurMemoryUsed()); gk_errexit(SIGMEM, "***Memory realloc failed for %s. " "Requested size: %zu bytes", msg, nbytes); return NULL; } /* add this memory allocation */ if (gkmcore != NULL) gk_gkmcoreAdd(gkmcore, GK_MOPT_HEAP, nbytes, ptr); return ptr; } /************************************************************************* * This function is my wrapper around free, allows multiple pointers **************************************************************************/ void gk_free(void **ptr1,...) { va_list plist; void **ptr; if (*ptr1 != NULL) { free(*ptr1); /* remove this memory de-allocation */ if (gkmcore != NULL) gk_gkmcoreDel(gkmcore, *ptr1); } *ptr1 = NULL; va_start(plist, ptr1); while ((ptr = va_arg(plist, void **)) != LTERM) { if (*ptr != NULL) { free(*ptr); /* remove this memory de-allocation */ if (gkmcore != NULL) gk_gkmcoreDel(gkmcore, *ptr); } *ptr = NULL; } va_end(plist); } /************************************************************************* * This function returns the current ammount of dynamically allocated * memory that is used by the system **************************************************************************/ size_t gk_GetCurMemoryUsed() { if (gkmcore == NULL) return 0; else return gkmcore->cur_hallocs; } /************************************************************************* * This function returns the maximum ammount of dynamically allocated * memory that was used by the system **************************************************************************/ size_t gk_GetMaxMemoryUsed() { if (gkmcore == NULL) return 0; else return gkmcore->max_hallocs; } ������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/original/gk_proto.h��������������������������0000644�0001751�0000144�00000033326�14552026002�026123� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*! \file gk_proto.h \brief This file contains function prototypes \date Started 3/27/2007 \author George \version\verbatim $Id: gk_proto.h 12591 2012-09-01 19:03:15Z karypis $ \endverbatim */ #ifndef _GK_PROTO_H_ #define _GK_PROTO_H_ #ifdef __cplusplus extern "C" { #endif /*------------------------------------------------------------- * blas.c *-------------------------------------------------------------*/ GK_MKBLAS_PROTO(gk_c, char, int) GK_MKBLAS_PROTO(gk_i, int, int) GK_MKBLAS_PROTO(gk_i32, int32_t, int32_t) GK_MKBLAS_PROTO(gk_i64, int64_t, int64_t) GK_MKBLAS_PROTO(gk_z, ssize_t, ssize_t) GK_MKBLAS_PROTO(gk_f, float, float) GK_MKBLAS_PROTO(gk_d, double, double) GK_MKBLAS_PROTO(gk_idx, gk_idx_t, gk_idx_t) /*------------------------------------------------------------- * io.c *-------------------------------------------------------------*/ FILE *gk_fopen(char *, char *, const char *); void gk_fclose(FILE *); gk_idx_t gk_getline(char **lineptr, size_t *n, FILE *stream); char **gk_readfile(char *fname, gk_idx_t *r_nlines); int32_t *gk_i32readfile(char *fname, gk_idx_t *r_nlines); int64_t *gk_i64readfile(char *fname, gk_idx_t *r_nlines); int32_t *gk_i32readfilebin(char *fname, ssize_t *r_nelmnts); int64_t *gk_i64readfilebin(char *fname, ssize_t *r_nelmnts); float *gk_freadfilebin(char *fname, ssize_t *r_nelmnts); size_t gk_fwritefilebin(char *fname, size_t n, float *a); double *gk_dreadfilebin(char *fname, ssize_t *r_nelmnts); /*------------------------------------------------------------- * fs.c *-------------------------------------------------------------*/ int gk_fexists(char *); int gk_dexists(char *); intmax_t gk_getfsize(char *); void gk_getfilestats(char *fname, size_t *r_nlines, size_t *r_ntokens, size_t *r_max_nlntokens, size_t *r_nbytes); char *gk_getbasename(char *path); char *gk_getextname(char *path); char *gk_getfilename(char *path); char *gk_getpathname(char *path); int gk_mkpath(char *); int gk_rmpath(char *); /*------------------------------------------------------------- * memory.c *-------------------------------------------------------------*/ GK_MKALLOC_PROTO(gk_c, char) GK_MKALLOC_PROTO(gk_i, int) GK_MKALLOC_PROTO(gk_i32, int32_t) GK_MKALLOC_PROTO(gk_i64, int64_t) GK_MKALLOC_PROTO(gk_z, ssize_t) GK_MKALLOC_PROTO(gk_f, float) GK_MKALLOC_PROTO(gk_d, double) GK_MKALLOC_PROTO(gk_idx, gk_idx_t) GK_MKALLOC_PROTO(gk_ckv, gk_ckv_t) GK_MKALLOC_PROTO(gk_ikv, gk_ikv_t) GK_MKALLOC_PROTO(gk_i32kv, gk_i32kv_t) GK_MKALLOC_PROTO(gk_i64kv, gk_i64kv_t) GK_MKALLOC_PROTO(gk_zkv, gk_zkv_t) GK_MKALLOC_PROTO(gk_fkv, gk_fkv_t) GK_MKALLOC_PROTO(gk_dkv, gk_dkv_t) GK_MKALLOC_PROTO(gk_skv, gk_skv_t) GK_MKALLOC_PROTO(gk_idxkv, gk_idxkv_t) void gk_AllocMatrix(void ***, size_t, size_t , size_t); void gk_FreeMatrix(void ***, size_t, size_t); int gk_malloc_init(); void gk_malloc_cleanup(int showstats); void *gk_malloc(size_t nbytes, char *msg); void *gk_realloc(void *oldptr, size_t nbytes, char *msg); void gk_free(void **ptr1,...); size_t gk_GetCurMemoryUsed(); size_t gk_GetMaxMemoryUsed(); /*------------------------------------------------------------- * seq.c *-------------------------------------------------------------*/ gk_seq_t *gk_seq_ReadGKMODPSSM(char *file_name); gk_i2cc2i_t *gk_i2cc2i_create_common(char *alphabet); void gk_seq_init(gk_seq_t *seq); /*------------------------------------------------------------- * pdb.c *-------------------------------------------------------------*/ char gk_threetoone(char *res); void gk_freepdbf(pdbf *p); pdbf *gk_readpdbfile(char *fname); void gk_writefullatom(pdbf *p, char *fname); void gk_writebackbone(pdbf *p, char *fname); void gk_writealphacarbons(pdbf *p, char *fname); void gk_showcorruption(pdbf *p); /*------------------------------------------------------------- * error.c *-------------------------------------------------------------*/ void gk_set_exit_on_error(int value); void errexit(char *,...); void gk_errexit(int signum, char *,...); int gk_sigtrap(); int gk_siguntrap(); void gk_sigthrow(int signum); void gk_SetSignalHandlers(); void gk_UnsetSignalHandlers(); void gk_NonLocalExit_Handler(int signum); char *gk_strerror(int errnum); void PrintBackTrace(); /*------------------------------------------------------------- * util.c *-------------------------------------------------------------*/ void gk_RandomPermute(size_t, int *, int); void gk_array2csr(size_t n, size_t range, int *array, int *ptr, int *ind); int gk_log2(int); int gk_ispow2(int); float gk_flog2(float); /*------------------------------------------------------------- * time.c *-------------------------------------------------------------*/ gk_wclock_t gk_WClockSeconds(void); double gk_CPUSeconds(void); /*------------------------------------------------------------- * string.c *-------------------------------------------------------------*/ char *gk_strchr_replace(char *str, char *fromlist, char *tolist); int gk_strstr_replace(char *str, char *pattern, char *replacement, char *options, char **new_str); char *gk_strtprune(char *, char *); char *gk_strhprune(char *, char *); char *gk_strtoupper(char *); char *gk_strtolower(char *); char *gk_strdup(char *orgstr); int gk_strcasecmp(char *s1, char *s2); int gk_strrcmp(char *s1, char *s2); char *gk_time2str(time_t time); time_t gk_str2time(char *str); int gk_GetStringID(gk_StringMap_t *strmap, char *key); /*------------------------------------------------------------- * sort.c *-------------------------------------------------------------*/ void gk_csorti(size_t, char *); void gk_csortd(size_t, char *); void gk_isorti(size_t, int *); void gk_isortd(size_t, int *); void gk_fsorti(size_t, float *); void gk_fsortd(size_t, float *); void gk_dsorti(size_t, double *); void gk_dsortd(size_t, double *); void gk_idxsorti(size_t, gk_idx_t *); void gk_idxsortd(size_t, gk_idx_t *); void gk_ckvsorti(size_t, gk_ckv_t *); void gk_ckvsortd(size_t, gk_ckv_t *); void gk_ikvsorti(size_t, gk_ikv_t *); void gk_ikvsortd(size_t, gk_ikv_t *); void gk_i32kvsorti(size_t, gk_i32kv_t *); void gk_i32kvsortd(size_t, gk_i32kv_t *); void gk_i64kvsorti(size_t, gk_i64kv_t *); void gk_i64kvsortd(size_t, gk_i64kv_t *); void gk_zkvsorti(size_t, gk_zkv_t *); void gk_zkvsortd(size_t, gk_zkv_t *); void gk_fkvsorti(size_t, gk_fkv_t *); void gk_fkvsortd(size_t, gk_fkv_t *); void gk_dkvsorti(size_t, gk_dkv_t *); void gk_dkvsortd(size_t, gk_dkv_t *); void gk_skvsorti(size_t, gk_skv_t *); void gk_skvsortd(size_t, gk_skv_t *); void gk_idxkvsorti(size_t, gk_idxkv_t *); void gk_idxkvsortd(size_t, gk_idxkv_t *); /*------------------------------------------------------------- * Selection routines *-------------------------------------------------------------*/ int gk_dfkvkselect(size_t, int, gk_fkv_t *); int gk_ifkvkselect(size_t, int, gk_fkv_t *); /*------------------------------------------------------------- * Priority queue *-------------------------------------------------------------*/ GK_MKPQUEUE_PROTO(gk_ipq, gk_ipq_t, int, gk_idx_t) GK_MKPQUEUE_PROTO(gk_i32pq, gk_i32pq_t, int32_t, gk_idx_t) GK_MKPQUEUE_PROTO(gk_i64pq, gk_i64pq_t, int64_t, gk_idx_t) GK_MKPQUEUE_PROTO(gk_fpq, gk_fpq_t, float, gk_idx_t) GK_MKPQUEUE_PROTO(gk_dpq, gk_dpq_t, double, gk_idx_t) GK_MKPQUEUE_PROTO(gk_idxpq, gk_idxpq_t, gk_idx_t, gk_idx_t) /*------------------------------------------------------------- * HTable routines *-------------------------------------------------------------*/ gk_HTable_t *HTable_Create(int nelements); void HTable_Reset(gk_HTable_t *htable); void HTable_Resize(gk_HTable_t *htable, int nelements); void HTable_Insert(gk_HTable_t *htable, int key, int val); void HTable_Delete(gk_HTable_t *htable, int key); int HTable_Search(gk_HTable_t *htable, int key); int HTable_GetNext(gk_HTable_t *htable, int key, int *val, int type); int HTable_SearchAndDelete(gk_HTable_t *htable, int key); void HTable_Destroy(gk_HTable_t *htable); int HTable_HFunction(int nelements, int key); /*------------------------------------------------------------- * Tokenizer routines *-------------------------------------------------------------*/ void gk_strtokenize(char *line, char *delim, gk_Tokens_t *tokens); void gk_freetokenslist(gk_Tokens_t *tokens); /*------------------------------------------------------------- * Encoder/Decoder *-------------------------------------------------------------*/ void encodeblock(unsigned char *in, unsigned char *out); void decodeblock(unsigned char *in, unsigned char *out); void GKEncodeBase64(int nbytes, unsigned char *inbuffer, unsigned char *outbuffer); void GKDecodeBase64(int nbytes, unsigned char *inbuffer, unsigned char *outbuffer); /*------------------------------------------------------------- * random.c *-------------------------------------------------------------*/ GK_MKRANDOM_PROTO(gk_c, size_t, char) GK_MKRANDOM_PROTO(gk_i, size_t, int) GK_MKRANDOM_PROTO(gk_f, size_t, float) GK_MKRANDOM_PROTO(gk_d, size_t, double) GK_MKRANDOM_PROTO(gk_idx, size_t, gk_idx_t) GK_MKRANDOM_PROTO(gk_z, size_t, ssize_t) void gk_randinit(uint64_t); uint64_t gk_randint64(void); uint32_t gk_randint32(void); /*------------------------------------------------------------- * OpenMP fake functions *-------------------------------------------------------------*/ #if !defined(__OPENMP__) void omp_set_num_threads(int num_threads); int omp_get_num_threads(void); int omp_get_max_threads(void); int omp_get_thread_num(void); int omp_get_num_procs(void); int omp_in_parallel(void); void omp_set_dynamic(int num_threads); int omp_get_dynamic(void); void omp_set_nested(int nested); int omp_get_nested(void); #endif /* __OPENMP__ */ /*------------------------------------------------------------- * CSR-related functions *-------------------------------------------------------------*/ gk_csr_t *gk_csr_Create(); void gk_csr_Init(gk_csr_t *mat); void gk_csr_Free(gk_csr_t **mat); void gk_csr_FreeContents(gk_csr_t *mat); gk_csr_t *gk_csr_Dup(gk_csr_t *mat); gk_csr_t *gk_csr_ExtractSubmatrix(gk_csr_t *mat, int rstart, int nrows); gk_csr_t *gk_csr_ExtractRows(gk_csr_t *mat, int nrows, int *rind); gk_csr_t *gk_csr_ExtractPartition(gk_csr_t *mat, int *part, int pid); gk_csr_t **gk_csr_Split(gk_csr_t *mat, int *color); gk_csr_t *gk_csr_Read(char *filename, int format, int readvals, int numbering); void gk_csr_Write(gk_csr_t *mat, char *filename, int format, int writevals, int numbering); gk_csr_t *gk_csr_Prune(gk_csr_t *mat, int what, int minf, int maxf); gk_csr_t *gk_csr_LowFilter(gk_csr_t *mat, int what, int norm, float fraction); gk_csr_t *gk_csr_TopKPlusFilter(gk_csr_t *mat, int what, int topk, float keepval); gk_csr_t *gk_csr_ZScoreFilter(gk_csr_t *mat, int what, float zscore); void gk_csr_CompactColumns(gk_csr_t *mat); void gk_csr_SortIndices(gk_csr_t *mat, int what); void gk_csr_CreateIndex(gk_csr_t *mat, int what); void gk_csr_Normalize(gk_csr_t *mat, int what, int norm); void gk_csr_Scale(gk_csr_t *mat, int type); void gk_csr_ComputeSums(gk_csr_t *mat, int what); void gk_csr_ComputeSquaredNorms(gk_csr_t *mat, int what); float gk_csr_ComputeSimilarity(gk_csr_t *mat, int i1, int i2, int what, int simtype); int gk_csr_GetSimilarRows(gk_csr_t *mat, int nqterms, int *qind, float *qval, int simtype, int nsim, float minsim, gk_fkv_t *hits, int *_imarker, gk_fkv_t *i_cand); /* itemsets.c */ void gk_find_frequent_itemsets(int ntrans, ssize_t *tranptr, int *tranind, int minfreq, int maxfreq, int minlen, int maxlen, void (*process_itemset)(void *stateptr, int nitems, int *itemind, int ntrans, int *tranind), void *stateptr); /* evaluate.c */ float ComputeAccuracy(int n, gk_fkv_t *list); float ComputeROCn(int n, int maxN, gk_fkv_t *list); float ComputeMedianRFP(int n, gk_fkv_t *list); float ComputeMean (int n, float *values); float ComputeStdDev(int n, float *values); /* mcore.c */ gk_mcore_t *gk_mcoreCreate(size_t coresize); gk_mcore_t *gk_gkmcoreCreate(); void gk_mcoreDestroy(gk_mcore_t **r_mcore, int showstats); void gk_gkmcoreDestroy(gk_mcore_t **r_mcore, int showstats); void *gk_mcoreMalloc(gk_mcore_t *mcore, size_t nbytes); void gk_mcorePush(gk_mcore_t *mcore); void gk_gkmcorePush(gk_mcore_t *mcore); void gk_mcorePop(gk_mcore_t *mcore); void gk_gkmcorePop(gk_mcore_t *mcore); void gk_mcoreAdd(gk_mcore_t *mcore, int type, size_t nbytes, void *ptr); void gk_gkmcoreAdd(gk_mcore_t *mcore, int type, size_t nbytes, void *ptr); void gk_mcoreDel(gk_mcore_t *mcore, void *ptr); void gk_gkmcoreDel(gk_mcore_t *mcore, void *ptr); /* rw.c */ int gk_rw_PageRank(gk_csr_t *mat, float lamda, float eps, int max_niter, float *pr); /* graph.c */ gk_graph_t *gk_graph_Create(); void gk_graph_Init(gk_graph_t *graph); void gk_graph_Free(gk_graph_t **graph); void gk_graph_FreeContents(gk_graph_t *graph); gk_graph_t *gk_graph_Read(char *filename, int format, int isfewgts, int isfvwgts, int isfvsizes); void gk_graph_Write(gk_graph_t *graph, char *filename, int format); gk_graph_t *gk_graph_Dup(gk_graph_t *graph); gk_graph_t *gk_graph_ExtractSubgraph(gk_graph_t *graph, int vstart, int nvtxs); gk_graph_t *gk_graph_Reorder(gk_graph_t *graph, int32_t *perm, int32_t *iperm); int gk_graph_FindComponents(gk_graph_t *graph, int32_t *cptr, int32_t *cind); void gk_graph_ComputeBFSOrdering(gk_graph_t *graph, int v, int32_t **r_perm, int32_t **r_iperm); void gk_graph_ComputeBestFOrdering0(gk_graph_t *graph, int v, int type, int32_t **r_perm, int32_t **r_iperm); void gk_graph_ComputeBestFOrdering(gk_graph_t *graph, int v, int type, int32_t **r_perm, int32_t **r_iperm); void gk_graph_SingleSourceShortestPaths(gk_graph_t *graph, int v, void **r_sps); #ifdef __cplusplus } #endif #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/original/gk_mkrandom.h�����������������������0000644�0001751�0000144�00000007117�14552026002�026567� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*! \file \brief Templates for portable random number generation \date Started 5/17/07 \author George \version\verbatim $Id: gk_mkrandom.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim */ #ifndef _GK_MKRANDOM_H #define _GK_MKRANDOM_H /*************************************************************************/\ /*! The generator for the rand() related routines. \ \params RNGT the datatype that defines the range of values over which\ random numbers will be generated\ \params VALT the datatype that defines the contents of the array to \ be permuted by randArrayPermute() \ \params FPRFX the function prefix \ */\ /**************************************************************************/\ #define GK_MKRANDOM(FPRFX, RNGT, VALT)\ /*************************************************************************/\ /*! Initializes the generator */ \ /**************************************************************************/\ void FPRFX ## srand(RNGT seed) \ {\ gk_randinit((uint64_t) seed);\ }\ \ \ /*************************************************************************/\ /*! Returns a random number */ \ /**************************************************************************/\ RNGT FPRFX ## rand() \ {\ if (sizeof(RNGT) <= sizeof(int32_t)) \ return (RNGT)gk_randint32(); \ else \ return (RNGT)gk_randint64(); \ }\ \ \ /*************************************************************************/\ /*! Returns a random number between [0, max) */ \ /**************************************************************************/\ RNGT FPRFX ## randInRange(RNGT max) \ {\ return (RNGT)((FPRFX ## rand())%max); \ }\ \ \ /*************************************************************************/\ /*! Randomly permutes the elements of an array p[]. \ flag == 1, p[i] = i prior to permutation, \ flag == 0, p[] is not initialized. */\ /**************************************************************************/\ void FPRFX ## randArrayPermute(RNGT n, VALT *p, RNGT nshuffles, int flag)\ {\ RNGT i, u, v;\ VALT tmp;\ \ if (flag == 1) {\ for (i=0; i #endif #ifdef __MSC__ #include "ms_stdint.h" #include "ms_inttypes.h" #include "ms_stat.h" #else #ifndef SUNOS #include #endif #include #include #include #include #endif /************************************************************************* * Architecture-specific modifications **************************************************************************/ #ifdef WIN32 typedef ptrdiff_t ssize_t; #endif #ifdef SUNOS #define PTRDIFF_MAX INT64_MAX #endif #ifdef __MSC__ /* MSC does not have rint() function */ #define rint(x) ((int)((x)+0.5)) /* MSC does not have INFINITY defined */ #ifndef INFINITY #define INFINITY FLT_MAX #endif #endif #endif �������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/original/GKlib.h�����������������������������0000644�0001751�0000144�00000002661�14552026002�025265� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * GKlib.h * * George's library of most frequently used routines * * $Id: GKlib.h 13005 2012-10-23 22:34:36Z karypis $ * */ #ifndef _GKLIB_H_ #define _GKLIB_H_ 1 #define GKMSPACE #if defined(_MSC_VER) #define __MSC__ #endif #if defined(__ICC) #define __ICC__ #endif #include "gk_arch.h" /*!< This should be here, prior to the includes */ /************************************************************************* * Header file inclusion section **************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__WITHPCRE__) #include #else #if defined(USE_GKREGEX) #include "gkregex.h" #else #include #endif /* defined(USE_GKREGEX) */ #endif /* defined(__WITHPCRE__) */ #if defined(__OPENMP__) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif /* GKlib.h */ �������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/omp.c����������������������������������������0000644�0001751�0000144�00000002361�14552244506�023267� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * omp.c * * This file contains "fake" implementations of OpenMP's runtime libraries * */ #include "GKlib.h" #ifdef GK_NOOPENMP /* remove those for now */ #if !defined(_OPENMP) void omp_set_num_threads(int num_threads) { return; } int omp_get_num_threads(void) { return 1; } int omp_get_max_threads(void) { return 1; } int omp_get_thread_num(void) { return 0; } int omp_get_num_procs(void) { return 1; } int omp_in_parallel(void) { return 0; } void omp_set_dynamic(int num_threads) { return; } int omp_get_dynamic(void) { return 0; } void omp_set_nested(int nested) { return; } int omp_get_nested(void) { return 0; } #endif #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/blas.c���������������������������������������0000644�0001751�0000144�00000003213�14552244506�023412� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file blas.c \brief This file contains GKlib's implementation of BLAS-like routines The BLAS routines that are currently implemented are mostly level-one. They follow a naming convention of the type gk_[type][name], where [type] is one of c, i, f, and d, based on C's four standard scalar datatypes of characters, integers, floats, and doubles. These routines are implemented using a generic macro template, which is used for code generation. \date Started 9/28/95 \author George \version\verbatim $Id: blas.c 11848 2012-04-20 13:47:37Z karypis $ \endverbatim */ #include "GKlib.h" /*************************************************************************/ /*! Use the templates to generate BLAS routines for the scalar data types */ /*************************************************************************/ GK_MKBLAS(gk_c, char, int) GK_MKBLAS(gk_i, int, int) GK_MKBLAS(gk_i32, int32_t, int32_t) GK_MKBLAS(gk_i64, int64_t, int64_t) GK_MKBLAS(gk_z, ssize_t, ssize_t) GK_MKBLAS(gk_f, float, float) GK_MKBLAS(gk_d, double, double) GK_MKBLAS(gk_idx, gk_idx_t, gk_idx_t) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_defs.h������������������������������������0000644�0001751�0000144�00000004115�14552244506�024102� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file gk_defs.h \brief This file contains various constants definitions \date Started 3/27/2007 \author George \version\verbatim $Id: gk_defs.h 12732 2012-09-24 20:54:50Z karypis $ \endverbatim */ #ifndef _GK_DEFS_H_ #define _GK_DEFS_H_ #define LTERM (void **) 0 /* List terminator for GKfree() */ /* mopt_t types */ #define GK_MOPT_MARK 1 #define GK_MOPT_CORE 2 #define GK_MOPT_HEAP 3 #define HTABLE_EMPTY -1 #define HTABLE_DELETED -2 #define HTABLE_FIRST 1 #define HTABLE_NEXT 2 /* pdb corruption bit switches */ #define CRP_ALTLOCS 1 #define CRP_MISSINGCA 2 #define CRP_MISSINGBB 4 #define CRP_MULTICHAIN 8 #define CRP_MULTICA 16 #define CRP_MULTIBB 32 #define MAXLINELEN 300000 /* GKlib signals to standard signal mapping */ #define SIGMEM SIGABRT #define SIGERR SIGTERM /* CSR-related defines */ #define GK_CSR_ROW 1 #define GK_CSR_COL 2 #define GK_CSR_MAXTF 1 #define GK_CSR_SQRT 2 #define GK_CSR_POW25 3 #define GK_CSR_POW65 4 #define GK_CSR_POW75 5 #define GK_CSR_POW85 6 #define GK_CSR_LOG 7 #define GK_CSR_IDF 8 #define GK_CSR_IDF2 9 #define GK_CSR_MAXTF2 10 #define GK_CSR_COS 1 #define GK_CSR_JAC 2 #define GK_CSR_MIN 3 #define GK_CSR_AMIN 4 #define GK_CSR_FMT_CLUTO 1 #define GK_CSR_FMT_CSR 2 #define GK_CSR_FMT_METIS 3 #define GK_CSR_FMT_BINROW 4 #define GK_CSR_FMT_BINCOL 5 #define GK_GRAPH_FMT_METIS 1 #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/htable.c�������������������������������������0000644�0001751�0000144�00000016423�14552244506�023737� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 2004, Regents of the University of Minnesota * * This file contains routines for manipulating a direct-access hash table * * Started 3/22/04 * George * */ #include "GKlib.h" /****************************************************************************** * This function creates the hash-table *******************************************************************************/ gk_HTable_t *HTable_Create(int nelements) { gk_HTable_t *htable; htable = gk_malloc(sizeof(gk_HTable_t), "HTable_Create: htable"); htable->harray = gk_ikvmalloc(nelements, "HTable_Create: harray"); htable->nelements = nelements; HTable_Reset(htable); return htable; } /****************************************************************************** * This function resets the data-structures associated with the hash-table *******************************************************************************/ void HTable_Reset(gk_HTable_t *htable) { int i; for (i=0; inelements; i++) htable->harray[i].key = HTABLE_EMPTY; htable->htsize = 0; } /****************************************************************************** * This function resizes the hash-table *******************************************************************************/ void HTable_Resize(gk_HTable_t *htable, int nelements) { int i, old_nelements; gk_ikv_t *old_harray; old_nelements = htable->nelements; old_harray = htable->harray; /* prepare larger hash */ htable->nelements = nelements; htable->htsize = 0; htable->harray = gk_ikvmalloc(nelements, "HTable_Resize: harray"); for (i=0; iharray[i].key = HTABLE_EMPTY; /* reassign the values */ for (i=0; ihtsize > htable->nelements/2) HTable_Resize(htable, 2*htable->nelements); first = HTable_HFunction(htable->nelements, key); for (i=first; inelements; i++) { if (htable->harray[i].key == HTABLE_EMPTY || htable->harray[i].key == HTABLE_DELETED) { htable->harray[i].key = key; htable->harray[i].val = val; htable->htsize++; return; } } for (i=0; iharray[i].key == HTABLE_EMPTY || htable->harray[i].key == HTABLE_DELETED) { htable->harray[i].key = key; htable->harray[i].val = val; htable->htsize++; return; } } } /****************************************************************************** * This function deletes key from the htable *******************************************************************************/ void HTable_Delete(gk_HTable_t *htable, int key) { int i, first; first = HTable_HFunction(htable->nelements, key); for (i=first; inelements; i++) { if (htable->harray[i].key == key) { htable->harray[i].key = HTABLE_DELETED; htable->htsize--; return; } } for (i=0; iharray[i].key == key) { htable->harray[i].key = HTABLE_DELETED; htable->htsize--; return; } } } /****************************************************************************** * This function returns the data associated with the key in the hastable *******************************************************************************/ int HTable_Search(gk_HTable_t *htable, int key) { int i, first; first = HTable_HFunction(htable->nelements, key); for (i=first; inelements; i++) { if (htable->harray[i].key == key) return htable->harray[i].val; else if (htable->harray[i].key == HTABLE_EMPTY) return -1; } for (i=0; iharray[i].key == key) return htable->harray[i].val; else if (htable->harray[i].key == HTABLE_EMPTY) return -1; } return -1; } /****************************************************************************** * This function returns the next key/val *******************************************************************************/ int HTable_GetNext(gk_HTable_t *htable, int key, int *r_val, int type) { int i; static int first, last; if (type == HTABLE_FIRST) first = last = HTable_HFunction(htable->nelements, key); if (first > last) { for (i=first; inelements; i++) { if (htable->harray[i].key == key) { *r_val = htable->harray[i].val; first = i+1; return 1; } else if (htable->harray[i].key == HTABLE_EMPTY) return -1; } first = 0; } for (i=first; iharray[i].key == key) { *r_val = htable->harray[i].val; first = i+1; return 1; } else if (htable->harray[i].key == HTABLE_EMPTY) return -1; } return -1; } /****************************************************************************** * This function returns the data associated with the key in the hastable *******************************************************************************/ int HTable_SearchAndDelete(gk_HTable_t *htable, int key) { int i, first; first = HTable_HFunction(htable->nelements, key); for (i=first; inelements; i++) { if (htable->harray[i].key == key) { htable->harray[i].key = HTABLE_DELETED; htable->htsize--; return htable->harray[i].val; } else if (htable->harray[i].key == HTABLE_EMPTY) gk_errexit(SIGERR, "HTable_SearchAndDelete: Failed to find the key!\n"); } for (i=0; iharray[i].key == key) { htable->harray[i].key = HTABLE_DELETED; htable->htsize--; return htable->harray[i].val; } else if (htable->harray[i].key == HTABLE_EMPTY) gk_errexit(SIGERR, "HTable_SearchAndDelete: Failed to find the key!\n"); } return -1; } /****************************************************************************** * This function destroys the data structures associated with the hash-table *******************************************************************************/ void HTable_Destroy(gk_HTable_t *htable) { gk_free((void **)&htable->harray, &htable, LTERM); } /****************************************************************************** * This is the hash-function. Based on multiplication *******************************************************************************/ int HTable_HFunction(int nelements, int key) { return (int)(key%nelements); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/io.c�����������������������������������������0000644�0001751�0000144�00000025447�14552244506�023115� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file io.c \brief Various file I/O functions. This file contains various functions that perform I/O. \date Started 4/10/95 \author George \version\verbatim $Id: io.c 12591 2012-09-01 19:03:15Z karypis $ \endverbatim */ #ifdef HAVE_GETLINE /* Get getline to be defined. */ #define _GNU_SOURCE #include #undef _GNU_SOURCE #endif #include "GKlib.h" /************************************************************************* * This function opens a file **************************************************************************/ FILE *gk_fopen(char *fname, char *mode, const char *msg) { FILE *fp; char errmsg[8192]; fp = fopen(fname, mode); if (fp != NULL) return fp; sprintf(errmsg,"file: %s, mode: %s, [%s]", fname, mode, msg); perror(errmsg); errexit("Failed on gk_fopen()\n"); return NULL; } /************************************************************************* * This function closes a file **************************************************************************/ void gk_fclose(FILE *fp) { fclose(fp); } /*************************************************************************/ /*! This function is the GKlib implementation of glibc's getline() function. \returns -1 if the EOF has been reached, otherwise it returns the number of bytes read. */ /*************************************************************************/ gk_idx_t gk_getline(char **lineptr, size_t *n, FILE *stream) { #ifdef HAVE_GETLINE return getline(lineptr, n, stream); #else size_t i; int ch; if (feof(stream)) return -1; /* Initial memory allocation if *lineptr is NULL */ if (*lineptr == NULL || *n == 0) { *n = 1024; *lineptr = gk_malloc((*n)*sizeof(char), "gk_getline: lineptr"); } /* get into the main loop */ i = 0; while ((ch = getc(stream)) != EOF) { (*lineptr)[i++] = (char)ch; /* reallocate memory if reached at the end of the buffer. The +1 is for '\0' */ if (i+1 == *n) { *n = 2*(*n); *lineptr = gk_realloc(*lineptr, (*n)*sizeof(char), "gk_getline: lineptr"); } if (ch == '\n') break; } (*lineptr)[i] = '\0'; return (i == 0 ? -1 : i); #endif } /*************************************************************************/ /*! This function reads the contents of a text file and returns it in the form of an array of strings. \param fname is the name of the file \param r_nlines is the number of lines in the file. If it is NULL, this information is not returned. */ /*************************************************************************/ char **gk_readfile(char *fname, gk_idx_t *r_nlines) { size_t lnlen, nlines; char *line=NULL, **lines=NULL; FILE *fpin; gk_getfilestats(fname, &nlines, NULL, NULL, NULL); if (nlines > 0) { lines = (char **)gk_malloc(nlines*sizeof(char *), "gk_readfile: lines"); fpin = gk_fopen(fname, "r", "gk_readfile"); nlines = 0; while (gk_getline(&line, &lnlen, fpin) != -1) { gk_strtprune(line, "\n\r"); lines[nlines++] = gk_strdup(line); } gk_fclose(fpin); } gk_free((void **)&line, LTERM); if (r_nlines != NULL) *r_nlines = nlines; return lines; } /*************************************************************************/ /*! This function reads the contents of a file and returns it in the form of an array of int32_t. \param fname is the name of the file \param r_nlines is the number of lines in the file. If it is NULL, this information is not returned. */ /*************************************************************************/ int32_t *gk_i32readfile(char *fname, gk_idx_t *r_nlines) { size_t lnlen, nlines; char *line=NULL; int32_t *array=NULL; FILE *fpin; gk_getfilestats(fname, &nlines, NULL, NULL, NULL); if (nlines > 0) { array = gk_i32malloc(nlines, "gk_i32readfile: array"); fpin = gk_fopen(fname, "r", "gk_readfile"); nlines = 0; while (gk_getline(&line, &lnlen, fpin) != -1) { sscanf(line, "%"SCNd32, &array[nlines++]); } gk_fclose(fpin); } gk_free((void **)&line, LTERM); if (r_nlines != NULL) *r_nlines = nlines; return array; } /*************************************************************************/ /*! This function reads the contents of a file and returns it in the form of an array of int64_t. \param fname is the name of the file \param r_nlines is the number of lines in the file. If it is NULL, this information is not returned. */ /*************************************************************************/ int64_t *gk_i64readfile(char *fname, gk_idx_t *r_nlines) { size_t lnlen, nlines; char *line=NULL; int64_t *array=NULL; FILE *fpin; gk_getfilestats(fname, &nlines, NULL, NULL, NULL); if (nlines > 0) { array = gk_i64malloc(nlines, "gk_i64readfile: array"); fpin = gk_fopen(fname, "r", "gk_readfile"); nlines = 0; while (gk_getline(&line, &lnlen, fpin) != -1) { sscanf(line, "%"SCNd64, &array[nlines++]); } gk_fclose(fpin); } gk_free((void **)&line, LTERM); if (r_nlines != NULL) *r_nlines = nlines; return array; } /*************************************************************************/ /*! This function reads the contents of a binary file and returns it in the form of an array of int32_t. \param fname is the name of the file \param r_nlines is the number of lines in the file. If it is NULL, this information is not returned. */ /*************************************************************************/ int32_t *gk_i32readfilebin(char *fname, ssize_t *r_nelmnts) { ssize_t fsize, nelmnts; int32_t *array=NULL; FILE *fpin; *r_nelmnts = -1; fsize = (ssize_t) gk_getfsize(fname); if (fsize%sizeof(int32_t) != 0) { gk_errexit(SIGERR, "The size of the file is not in multiples of sizeof(int32_t).\n"); return NULL; } nelmnts = fsize/sizeof(int32_t); array = gk_i32malloc(nelmnts, "gk_i32readfilebin: array"); fpin = gk_fopen(fname, "rb", "gk_i32readfilebin"); if (fread(array, sizeof(int32_t), nelmnts, fpin) != nelmnts) { gk_errexit(SIGERR, "Failed to read the number of words requested. %zd\n", nelmnts); gk_free((void **)&array, LTERM); return NULL; } gk_fclose(fpin); *r_nelmnts = nelmnts; return array; } /*************************************************************************/ /*! This function reads the contents of a binary file and returns it in the form of an array of int64_t. \param fname is the name of the file \param r_nlines is the number of lines in the file. If it is NULL, this information is not returned. */ /*************************************************************************/ int64_t *gk_i64readfilebin(char *fname, ssize_t *r_nelmnts) { ssize_t fsize, nelmnts; int64_t *array=NULL; FILE *fpin; *r_nelmnts = -1; fsize = (ssize_t) gk_getfsize(fname); if (fsize%sizeof(int64_t) != 0) { gk_errexit(SIGERR, "The size of the file is not in multiples of sizeof(int64_t).\n"); return NULL; } nelmnts = fsize/sizeof(int64_t); array = gk_i64malloc(nelmnts, "gk_i64readfilebin: array"); fpin = gk_fopen(fname, "rb", "gk_i64readfilebin"); if (fread(array, sizeof(int64_t), nelmnts, fpin) != nelmnts) { gk_errexit(SIGERR, "Failed to read the number of words requested. %zd\n", nelmnts); gk_free((void **)&array, LTERM); return NULL; } gk_fclose(fpin); *r_nelmnts = nelmnts; return array; } /*************************************************************************/ /*! This function reads the contents of a binary file and returns it in the form of an array of float. \param fname is the name of the file \param r_nlines is the number of lines in the file. If it is NULL, this information is not returned. */ /*************************************************************************/ float *gk_freadfilebin(char *fname, ssize_t *r_nelmnts) { ssize_t fsize, nelmnts; float *array=NULL; FILE *fpin; *r_nelmnts = -1; fsize = (ssize_t) gk_getfsize(fname); if (fsize%sizeof(float) != 0) { gk_errexit(SIGERR, "The size of the file is not in multiples of sizeof(float).\n"); return NULL; } nelmnts = fsize/sizeof(float); array = gk_fmalloc(nelmnts, "gk_freadfilebin: array"); fpin = gk_fopen(fname, "rb", "gk_freadfilebin"); if (fread(array, sizeof(float), nelmnts, fpin) != nelmnts) { gk_errexit(SIGERR, "Failed to read the number of words requested. %zd\n", nelmnts); gk_free((void **)&array, LTERM); return NULL; } gk_fclose(fpin); *r_nelmnts = nelmnts; return array; } /*************************************************************************/ /*! This function writes the contents of an array into a binary file. \param fname is the name of the file \param n the number of elements in the array. \param a the array to be written out. */ /*************************************************************************/ size_t gk_fwritefilebin(char *fname, size_t n, float *a) { size_t fsize; FILE *fp; fp = gk_fopen(fname, "wb", "gk_fwritefilebin"); fsize = fwrite(a, sizeof(float), n, fp); gk_fclose(fp); return fsize; } /*************************************************************************/ /*! This function reads the contents of a binary file and returns it in the form of an array of double. \param fname is the name of the file \param r_nlines is the number of lines in the file. If it is NULL, this information is not returned. */ /*************************************************************************/ double *gk_dreadfilebin(char *fname, ssize_t *r_nelmnts) { ssize_t fsize, nelmnts; double *array=NULL; FILE *fpin; *r_nelmnts = -1; fsize = (ssize_t) gk_getfsize(fname); if (fsize%sizeof(double) != 0) { gk_errexit(SIGERR, "The size of the file is not in multiples of sizeof(double).\n"); return NULL; } nelmnts = fsize/sizeof(double); array = gk_dmalloc(nelmnts, "gk_dreadfilebin: array"); fpin = gk_fopen(fname, "rb", "gk_dreadfilebin"); if (fread(array, sizeof(double), nelmnts, fpin) != nelmnts) { gk_errexit(SIGERR, "Failed to read the number of words requested. %zd\n", nelmnts); gk_free((void **)&array, LTERM); return NULL; } gk_fclose(fpin); *r_nelmnts = nelmnts; return array; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/itemsets.c�����������������������������������0000644�0001751�0000144�00000016641�14552244506�024337� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! * \file * \brief Frequent/Closed itemset discovery routines * * This file contains the code for finding frequent/closed itemests. These routines * are implemented using a call-back mechanism to deal with the discovered itemsets. * * \date 6/13/2008 * \author George Karypis * \version\verbatim $Id: itemsets.c 11075 2011-11-11 22:31:52Z karypis $ \endverbatim */ #include "GKlib.h" /*-------------------------------------------------------------*/ /*! Data structures for use within this module */ /*-------------------------------------------------------------*/ typedef struct { int minfreq; /* the minimum frequency of a pattern */ int maxfreq; /* the maximum frequency of a pattern */ int minlen; /* the minimum length of the requested pattern */ int maxlen; /* the maximum length of the requested pattern */ int tnitems; /* the initial range of the item space */ /* the call-back function */ void (*callback)(void *stateptr, int nitems, int *itemids, int ntrans, int *transids); void *stateptr; /* the user-supplied pointer to pass to the callback */ /* workspace variables */ int *rmarker; gk_ikv_t *cand; } isparams_t; /*-------------------------------------------------------------*/ /*! Prototypes for this module */ /*-------------------------------------------------------------*/ void itemsets_find_frequent_itemsets(isparams_t *params, gk_csr_t *mat, int preflen, int *prefix); gk_csr_t *itemsets_project_matrix(isparams_t *param, gk_csr_t *mat, int cid); /*************************************************************************/ /*! The entry point of the frequent itemset discovery code */ /*************************************************************************/ void gk_find_frequent_itemsets(int ntrans, ssize_t *tranptr, int *tranind, int minfreq, int maxfreq, int minlen, int maxlen, void (*process_itemset)(void *stateptr, int nitems, int *itemids, int ntrans, int *transids), void *stateptr) { ssize_t i; gk_csr_t *mat, *pmat; isparams_t params; int *pattern; /* Create the matrix */ mat = gk_csr_Create(); mat->nrows = ntrans; mat->ncols = tranind[gk_iargmax(tranptr[ntrans], tranind)]+1; mat->rowptr = gk_zcopy(ntrans+1, tranptr, gk_zmalloc(ntrans+1, "gk_find_frequent_itemsets: mat.rowptr")); mat->rowind = gk_icopy(tranptr[ntrans], tranind, gk_imalloc(tranptr[ntrans], "gk_find_frequent_itemsets: mat.rowind")); mat->colids = gk_iincset(mat->ncols, 0, gk_imalloc(mat->ncols, "gk_find_frequent_itemsets: mat.colids")); /* Setup the parameters */ params.minfreq = minfreq; params.maxfreq = (maxfreq == -1 ? mat->nrows : maxfreq); params.minlen = minlen; params.maxlen = (maxlen == -1 ? mat->ncols : maxlen); params.tnitems = mat->ncols; params.callback = process_itemset; params.stateptr = stateptr; params.rmarker = gk_ismalloc(mat->nrows, 0, "gk_find_frequent_itemsets: rmarker"); params.cand = gk_ikvmalloc(mat->ncols, "gk_find_frequent_itemsets: cand"); /* Perform the initial projection */ gk_csr_CreateIndex(mat, GK_CSR_COL); pmat = itemsets_project_matrix(¶ms, mat, -1); gk_csr_Free(&mat); pattern = gk_imalloc(pmat->ncols, "gk_find_frequent_itemsets: pattern"); itemsets_find_frequent_itemsets(¶ms, pmat, 0, pattern); gk_csr_Free(&pmat); gk_free((void **)&pattern, ¶ms.rmarker, ¶ms.cand, LTERM); } /*************************************************************************/ /*! The recursive routine for DFS-based frequent pattern discovery */ /*************************************************************************/ void itemsets_find_frequent_itemsets(isparams_t *params, gk_csr_t *mat, int preflen, int *prefix) { ssize_t i; gk_csr_t *cmat; /* Project each frequent column */ for (i=0; incols; i++) { prefix[preflen] = mat->colids[i]; if (preflen+1 >= params->minlen) (*params->callback)(params->stateptr, preflen+1, prefix, mat->colptr[i+1]-mat->colptr[i], mat->colind+mat->colptr[i]); if (preflen+1 < params->maxlen) { cmat = itemsets_project_matrix(params, mat, i); itemsets_find_frequent_itemsets(params, cmat, preflen+1, prefix); gk_csr_Free(&cmat); } } } /******************************************************************************/ /*! This function projects a matrix w.r.t. to a particular column. It performs the following steps: - Determines the length of each column that is remaining - Sorts the columns in increasing length - Creates a column-based version of the matrix with the proper column ordering and renamed rowids. */ /*******************************************************************************/ gk_csr_t *itemsets_project_matrix(isparams_t *params, gk_csr_t *mat, int cid) { ssize_t i, j, k, ii, pnnz; int nrows, ncols, pnrows, pncols; ssize_t *colptr, *pcolptr; int *colind, *colids, *pcolind, *pcolids, *rmarker; gk_csr_t *pmat; gk_ikv_t *cand; nrows = mat->nrows; ncols = mat->ncols; colptr = mat->colptr; colind = mat->colind; colids = mat->colids; rmarker = params->rmarker; cand = params->cand; /* Allocate space for the projected matrix based on what you know thus far */ pmat = gk_csr_Create(); pmat->nrows = pnrows = (cid == -1 ? nrows : colptr[cid+1]-colptr[cid]); /* Mark the rows that will be kept and determine the prowids */ if (cid == -1) { /* Initial projection */ gk_iset(nrows, 1, rmarker); } else { /* The other projections */ for (i=colptr[cid]; i= params->minfreq && k <= params->maxfreq) { cand[pncols].val = i; cand[pncols++].key = k; pnnz += k; } } /* Sort the columns in increasing order */ gk_ikvsorti(pncols, cand); /* Allocate space for the remaining fields of the projected matrix */ pmat->ncols = pncols; pmat->colids = pcolids = gk_imalloc(pncols, "itemsets_project_matrix: pcolids"); pmat->colptr = pcolptr = gk_zmalloc(pncols+1, "itemsets_project_matrix: pcolptr"); pmat->colind = pcolind = gk_imalloc(pnnz, "itemsets_project_matrix: pcolind"); /* Populate the projected matrix */ pcolptr[0] = 0; for (pnnz=0, ii=0; iiheap;\ locator = queue->locator;\ nnodes = queue->nnodes;\ \ if (nnodes == 0)\ return 1;\ \ ASSERT(locator[heap[0].val] == 0);\ for (i=1; imaxnodes; i++) {\ if (locator[i] != -1)\ j++;\ }\ ASSERTP(j == nnodes, ("%jd %jd\n", (intmax_t)j, (intmax_t)nnodes));\ } while (0) #else #define DO_CHECKHEAP #endif #define GK_MKPQUEUE(FPRFX, PQT, KVT, KT, VT, KVMALLOC, KMAX, KEY_LT)\ /*************************************************************************/\ /*! This function creates and initializes a priority queue */\ /**************************************************************************/\ PQT *FPRFX ## Create(size_t maxnodes)\ {\ PQT *queue; \ \ queue = (PQT *)gk_malloc(sizeof(PQT), "gk_pqCreate: queue");\ FPRFX ## Init(queue, maxnodes);\ \ return queue;\ }\ \ \ /*************************************************************************/\ /*! This function initializes the data structures of the priority queue */\ /**************************************************************************/\ void FPRFX ## Init(PQT *queue, size_t maxnodes)\ {\ queue->nnodes = 0;\ queue->maxnodes = maxnodes;\ \ queue->heap = KVMALLOC(maxnodes, "gk_PQInit: heap");\ queue->locator = gk_idxsmalloc(maxnodes, -1, "gk_PQInit: locator");\ }\ \ \ /*************************************************************************/\ /*! This function resets the priority queue */\ /**************************************************************************/\ void FPRFX ## Reset(PQT *queue)\ {\ gk_idx_t i;\ gk_idx_t *locator=queue->locator;\ KVT *heap=queue->heap;\ \ for (i=queue->nnodes-1; i>=0; i--)\ locator[heap[i].val] = -1;\ queue->nnodes = 0;\ }\ \ \ /*************************************************************************/\ /*! This function frees the internal datastructures of the priority queue */\ /**************************************************************************/\ void FPRFX ## Free(PQT *queue)\ {\ if (queue == NULL) return;\ gk_free((void **)&queue->heap, &queue->locator, LTERM);\ queue->maxnodes = 0;\ }\ \ \ /*************************************************************************/\ /*! This function frees the internal datastructures of the priority queue \ and the queue itself */\ /**************************************************************************/\ void FPRFX ## Destroy(PQT *queue)\ {\ if (queue == NULL) return;\ FPRFX ## Free(queue);\ gk_free((void **)&queue, LTERM);\ }\ \ \ /*************************************************************************/\ /*! This function returns the length of the queue */\ /**************************************************************************/\ size_t FPRFX ## Length(PQT *queue)\ {\ return queue->nnodes;\ }\ \ \ /*************************************************************************/\ /*! This function adds an item in the priority queue */\ /**************************************************************************/\ int FPRFX ## Insert(PQT *queue, VT node, KT key)\ {\ gk_idx_t i, j;\ gk_idx_t *locator=queue->locator;\ KVT *heap=queue->heap;\ \ ASSERT2(FPRFX ## CheckHeap(queue));\ \ ASSERT(locator[node] == -1);\ \ i = queue->nnodes++;\ while (i > 0) {\ j = (i-1)>>1;\ if (KEY_LT(key, heap[j].key)) {\ heap[i] = heap[j];\ locator[heap[i].val] = i;\ i = j;\ }\ else\ break;\ }\ ASSERT(i >= 0);\ heap[i].key = key;\ heap[i].val = node;\ locator[node] = i;\ \ ASSERT2(FPRFX ## CheckHeap(queue));\ \ return 0;\ }\ \ \ /*************************************************************************/\ /*! This function deletes an item from the priority queue */\ /**************************************************************************/\ int FPRFX ## Delete(PQT *queue, VT node)\ {\ gk_idx_t i, j, nnodes;\ KT newkey, oldkey;\ gk_idx_t *locator=queue->locator;\ KVT *heap=queue->heap;\ \ ASSERT(locator[node] != -1);\ ASSERT(heap[locator[node]].val == node);\ \ ASSERT2(FPRFX ## CheckHeap(queue));\ \ i = locator[node];\ locator[node] = -1;\ \ if (--queue->nnodes > 0 && heap[queue->nnodes].val != node) {\ node = heap[queue->nnodes].val;\ newkey = heap[queue->nnodes].key;\ oldkey = heap[i].key;\ \ if (KEY_LT(newkey, oldkey)) { /* Filter-up */\ while (i > 0) {\ j = (i-1)>>1;\ if (KEY_LT(newkey, heap[j].key)) {\ heap[i] = heap[j];\ locator[heap[i].val] = i;\ i = j;\ }\ else\ break;\ }\ }\ else { /* Filter down */\ nnodes = queue->nnodes;\ while ((j=(i<<1)+1) < nnodes) {\ if (KEY_LT(heap[j].key, newkey)) {\ if (j+1 < nnodes && KEY_LT(heap[j+1].key, heap[j].key))\ j++;\ heap[i] = heap[j];\ locator[heap[i].val] = i;\ i = j;\ }\ else if (j+1 < nnodes && KEY_LT(heap[j+1].key, newkey)) {\ j++;\ heap[i] = heap[j];\ locator[heap[i].val] = i;\ i = j;\ }\ else\ break;\ }\ }\ \ heap[i].key = newkey;\ heap[i].val = node;\ locator[node] = i;\ }\ \ ASSERT2(FPRFX ## CheckHeap(queue));\ \ return 0;\ }\ \ \ /*************************************************************************/\ /*! This function updates the key values associated for a particular item */ \ /**************************************************************************/\ void FPRFX ## Update(PQT *queue, VT node, KT newkey)\ {\ gk_idx_t i, j, nnodes;\ KT oldkey;\ gk_idx_t *locator=queue->locator;\ KVT *heap=queue->heap;\ \ oldkey = heap[locator[node]].key;\ \ ASSERT(locator[node] != -1);\ ASSERT(heap[locator[node]].val == node);\ ASSERT2(FPRFX ## CheckHeap(queue));\ \ i = locator[node];\ \ if (KEY_LT(newkey, oldkey)) { /* Filter-up */\ while (i > 0) {\ j = (i-1)>>1;\ if (KEY_LT(newkey, heap[j].key)) {\ heap[i] = heap[j];\ locator[heap[i].val] = i;\ i = j;\ }\ else\ break;\ }\ }\ else { /* Filter down */\ nnodes = queue->nnodes;\ while ((j=(i<<1)+1) < nnodes) {\ if (KEY_LT(heap[j].key, newkey)) {\ if (j+1 < nnodes && KEY_LT(heap[j+1].key, heap[j].key))\ j++;\ heap[i] = heap[j];\ locator[heap[i].val] = i;\ i = j;\ }\ else if (j+1 < nnodes && KEY_LT(heap[j+1].key, newkey)) {\ j++;\ heap[i] = heap[j];\ locator[heap[i].val] = i;\ i = j;\ }\ else\ break;\ }\ }\ \ heap[i].key = newkey;\ heap[i].val = node;\ locator[node] = i;\ \ ASSERT2(FPRFX ## CheckHeap(queue));\ \ return;\ }\ \ \ /*************************************************************************/\ /*! This function returns the item at the top of the queue and removes\ it from the priority queue */\ /**************************************************************************/\ VT FPRFX ## GetTop(PQT *queue)\ {\ gk_idx_t i, j;\ gk_idx_t *locator;\ KVT *heap;\ VT vtx, node;\ KT key;\ \ ASSERT2(FPRFX ## CheckHeap(queue));\ \ if (queue->nnodes == 0)\ return -1;\ \ queue->nnodes--;\ \ heap = queue->heap;\ locator = queue->locator;\ \ vtx = heap[0].val;\ locator[vtx] = -1;\ \ if ((i = queue->nnodes) > 0) {\ key = heap[i].key;\ node = heap[i].val;\ i = 0;\ while ((j=2*i+1) < queue->nnodes) {\ if (KEY_LT(heap[j].key, key)) {\ if (j+1 < queue->nnodes && KEY_LT(heap[j+1].key, heap[j].key))\ j = j+1;\ heap[i] = heap[j];\ locator[heap[i].val] = i;\ i = j;\ }\ else if (j+1 < queue->nnodes && KEY_LT(heap[j+1].key, key)) {\ j = j+1;\ heap[i] = heap[j];\ locator[heap[i].val] = i;\ i = j;\ }\ else\ break;\ }\ \ heap[i].key = key;\ heap[i].val = node;\ locator[node] = i;\ }\ \ ASSERT2(FPRFX ## CheckHeap(queue));\ return vtx;\ }\ \ \ /*************************************************************************/\ /*! This function returns the item at the top of the queue. The item is not\ deleted from the queue. */\ /**************************************************************************/\ VT FPRFX ## SeeTopVal(PQT *queue)\ {\ return (queue->nnodes == 0 ? -1 : queue->heap[0].val);\ }\ \ \ /*************************************************************************/\ /*! This function returns the key of the top item. The item is not\ deleted from the queue. */\ /**************************************************************************/\ KT FPRFX ## SeeTopKey(PQT *queue)\ {\ return (queue->nnodes == 0 ? KMAX : queue->heap[0].key);\ }\ \ \ /*************************************************************************/\ /*! This function returns the key of a specific item */\ /**************************************************************************/\ KT FPRFX ## SeeKey(PQT *queue, VT node)\ {\ gk_idx_t *locator;\ KVT *heap;\ \ heap = queue->heap;\ locator = queue->locator;\ \ return heap[locator[node]].key;\ }\ \ \ /*************************************************************************/\ /*! This function returns the first item in a breadth-first traversal of\ the heap whose key is less than maxwgt. This function is here due to\ hMETIS and is not general!*/\ /**************************************************************************/\ /*\ VT FPRFX ## SeeConstraintTop(PQT *queue, KT maxwgt, KT *wgts)\ {\ gk_idx_t i;\ \ if (queue->nnodes == 0)\ return -1;\ \ if (maxwgt <= 1000)\ return FPRFX ## SeeTopVal(queue);\ \ for (i=0; innodes; i++) {\ if (queue->heap[i].key > 0) {\ if (wgts[queue->heap[i].val] <= maxwgt)\ return queue->heap[i].val;\ }\ else {\ if (queue->heap[i/2].key <= 0)\ break;\ }\ }\ \ return queue->heap[0].val;\ \ }\ */\ \ \ /*************************************************************************/\ /*! This functions checks the consistency of the heap */\ /**************************************************************************/\ int FPRFX ## CheckHeap(PQT *queue)\ {\ DO_CHECKHEAP;\ return 1;\ }\ #define GK_MKPQUEUE_PROTO(FPRFX, PQT, KT, VT)\ PQT * FPRFX ## Create(size_t maxnodes);\ void FPRFX ## Init(PQT *queue, size_t maxnodes);\ void FPRFX ## Reset(PQT *queue);\ void FPRFX ## Free(PQT *queue);\ void FPRFX ## Destroy(PQT *queue);\ size_t FPRFX ## Length(PQT *queue);\ int FPRFX ## Insert(PQT *queue, VT node, KT key);\ int FPRFX ## Delete(PQT *queue, VT node);\ void FPRFX ## Update(PQT *queue, VT node, KT newkey);\ VT FPRFX ## GetTop(PQT *queue);\ VT FPRFX ## SeeTopVal(PQT *queue);\ KT FPRFX ## SeeTopKey(PQT *queue);\ KT FPRFX ## SeeKey(PQT *queue, VT node);\ VT FPRFX ## SeeConstraintTop(PQT *queue, KT maxwgt, KT *wgts);\ int FPRFX ## CheckHeap(PQT *queue);\ /* This is how these macros are used GK_MKPQUEUE(gk_dkvPQ, gk_dkvPQ_t, double, gk_idx_t, gk_dkvmalloc, DBL_MAX) GK_MKPQUEUE_PROTO(gk_dkvPQ, gk_dkvPQ_t, double, gk_idx_t) */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_types.h�����������������������������������0000644�0001751�0000144�00000004027�14552244506�024327� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file gk_types.h \brief This file contains basic scalar datatype used in GKlib \date Started 3/27/2007 \author George \version\verbatim $Id: gk_types.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim */ #ifndef _GK_TYPES_H_ #define _GK_TYPES_H_ /************************************************************************* * Basic data type definitions. These definitions allow GKlib to separate * the following elemental types: * - loop iterator variables, which are set to size_t * - signed and unsigned int variables that can be set to any # of bits * - signed and unsigned long variables that can be set to any # of bits * - real variables, which can be set to single or double precision. **************************************************************************/ /*typedef ptrdiff_t gk_idx_t; */ /* index variable */ typedef ssize_t gk_idx_t; /* index variable */ typedef int32_t gk_int_t; /* integer values */ typedef uint32_t gk_uint_t; /* unsigned integer values */ typedef int64_t gk_long_t; /* long integer values */ typedef uint64_t gk_ulong_t; /* unsigned long integer values */ typedef float gk_real_t; /* real type */ typedef double gk_dreal_t; /* double precission real type */ typedef double gk_wclock_t; /* wall-clock time */ /*#define GK_IDX_MAX PTRDIFF_MAX*/ #define GK_IDX_MAX ((SIZE_MAX>>1)-2) #define PRIGKIDX "zd" #define SCNGKIDX "zd" #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_mkpqueue2.h�������������������������������0000644�0001751�0000144�00000014371�14552244506�025104� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file gk_mkpqueue2.h \brief Templates for priority queues that do not utilize locators and as such they can use different types of values. \date Started 4/09/07 \author George \version\verbatim $Id: gk_mkpqueue2.h 13005 2012-10-23 22:34:36Z karypis $ \endverbatim */ #ifndef _GK_MKPQUEUE2_H #define _GK_MKPQUEUE2_H #define GK_MKPQUEUE2(FPRFX, PQT, KT, VT, KMALLOC, VMALLOC, KMAX, KEY_LT)\ /*************************************************************************/\ /*! This function creates and initializes a priority queue */\ /**************************************************************************/\ PQT *FPRFX ## Create2(ssize_t maxnodes)\ {\ PQT *queue; \ \ if ((queue = (PQT *)gk_malloc(sizeof(PQT), "gk_pqCreate2: queue")) != NULL) {\ memset(queue, 0, sizeof(PQT));\ queue->nnodes = 0;\ queue->maxnodes = maxnodes;\ queue->keys = KMALLOC(maxnodes, "gk_pqCreate2: keys");\ queue->vals = VMALLOC(maxnodes, "gk_pqCreate2: vals");\ \ if (queue->keys == NULL || queue->vals == NULL)\ gk_free((void **)&queue->keys, &queue->vals, &queue, LTERM);\ }\ \ return queue;\ }\ \ \ /*************************************************************************/\ /*! This function resets the priority queue */\ /**************************************************************************/\ void FPRFX ## Reset2(PQT *queue)\ {\ queue->nnodes = 0;\ }\ \ \ /*************************************************************************/\ /*! This function frees the internal datastructures of the priority queue */\ /**************************************************************************/\ void FPRFX ## Destroy2(PQT **r_queue)\ {\ PQT *queue = *r_queue; \ if (queue == NULL) return;\ gk_free((void **)&queue->keys, &queue->vals, &queue, LTERM);\ *r_queue = NULL;\ }\ \ \ /*************************************************************************/\ /*! This function returns the length of the queue */\ /**************************************************************************/\ size_t FPRFX ## Length2(PQT *queue)\ {\ return queue->nnodes;\ }\ \ \ /*************************************************************************/\ /*! This function adds an item in the priority queue. */\ /**************************************************************************/\ int FPRFX ## Insert2(PQT *queue, VT val, KT key)\ {\ ssize_t i, j;\ KT *keys=queue->keys;\ VT *vals=queue->vals;\ \ ASSERT2(FPRFX ## CheckHeap2(queue));\ \ if (queue->nnodes == queue->maxnodes) \ return 0;\ \ ASSERT2(FPRFX ## CheckHeap2(queue));\ \ i = queue->nnodes++;\ while (i > 0) {\ j = (i-1)>>1;\ if (KEY_LT(key, keys[j])) {\ keys[i] = keys[j];\ vals[i] = vals[j];\ i = j;\ }\ else\ break;\ }\ ASSERT(i >= 0);\ keys[i] = key;\ vals[i] = val;\ \ ASSERT2(FPRFX ## CheckHeap2(queue));\ \ return 1;\ }\ \ \ /*************************************************************************/\ /*! This function returns the item at the top of the queue and removes\ it from the priority queue */\ /**************************************************************************/\ int FPRFX ## GetTop2(PQT *queue, VT *r_val)\ {\ ssize_t i, j;\ KT key, *keys=queue->keys;\ VT val, *vals=queue->vals;\ \ ASSERT2(FPRFX ## CheckHeap2(queue));\ \ if (queue->nnodes == 0)\ return 0;\ \ queue->nnodes--;\ \ *r_val = vals[0];\ \ if ((i = queue->nnodes) > 0) {\ key = keys[i];\ val = vals[i];\ i = 0;\ while ((j=2*i+1) < queue->nnodes) {\ if (KEY_LT(keys[j], key)) {\ if (j+1 < queue->nnodes && KEY_LT(keys[j+1], keys[j]))\ j = j+1;\ keys[i] = keys[j];\ vals[i] = vals[j];\ i = j;\ }\ else if (j+1 < queue->nnodes && KEY_LT(keys[j+1], key)) {\ j = j+1;\ keys[i] = keys[j];\ vals[i] = vals[j];\ i = j;\ }\ else\ break;\ }\ \ keys[i] = key;\ vals[i] = val;\ }\ \ ASSERT2(FPRFX ## CheckHeap2(queue));\ \ return 1;\ }\ \ \ /*************************************************************************/\ /*! This function returns the item at the top of the queue. The item is not\ deleted from the queue. */\ /**************************************************************************/\ int FPRFX ## SeeTopVal2(PQT *queue, VT *r_val)\ {\ if (queue->nnodes == 0) \ return 0;\ \ *r_val = queue->vals[0];\ \ return 1;\ }\ \ \ /*************************************************************************/\ /*! This function returns the key of the top item. The item is not\ deleted from the queue. */\ /**************************************************************************/\ KT FPRFX ## SeeTopKey2(PQT *queue)\ {\ return (queue->nnodes == 0 ? KMAX : queue->keys[0]);\ }\ \ \ /*************************************************************************/\ /*! This functions checks the consistency of the heap */\ /**************************************************************************/\ int FPRFX ## CheckHeap2(PQT *queue)\ {\ ssize_t i;\ KT *keys=queue->keys;\ \ if (queue->nnodes == 0)\ return 1;\ \ for (i=1; innodes; i++) {\ ASSERT(!KEY_LT(keys[i], keys[(i-1)/2]));\ }\ for (i=1; innodes; i++)\ ASSERT(!KEY_LT(keys[i], keys[0]));\ \ return 1;\ }\ #define GK_MKPQUEUE2_PROTO(FPRFX, PQT, KT, VT)\ PQT * FPRFX ## Create2(ssize_t maxnodes);\ void FPRFX ## Reset2(PQT *queue);\ void FPRFX ## Destroy2(PQT **r_queue);\ size_t FPRFX ## Length2(PQT *queue);\ int FPRFX ## Insert2(PQT *queue, VT node, KT key);\ int FPRFX ## GetTop2(PQT *queue, VT *r_val);\ int FPRFX ## SeeTopVal2(PQT *queue, VT *r_val);\ KT FPRFX ## SeeTopKey2(PQT *queue);\ int FPRFX ## CheckHeap2(PQT *queue);\ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_arch.h������������������������������������0000644�0001751�0000144�00000004431�14552244506�024077� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file gk_arch.h \brief This file contains various architecture-specific declerations \date Started 3/27/2007 \author George \version\verbatim $Id: gk_arch.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim */ #ifndef _GK_ARCH_H_ #define _GK_ARCH_H_ /************************************************************************* * Architecture-specific differences in header files **************************************************************************/ // stdint.h, inttypes.h: added for SuiteSparse, Dec 2022 #include #include #if 0 #ifdef LINUX #if !defined(__USE_XOPEN) #define __USE_XOPEN #endif #if !defined(_XOPEN_SOURCE) #define _XOPEN_SOURCE 600 #endif #if !defined(__USE_XOPEN2K) #define __USE_XOPEN2K #endif #endif #ifdef HAVE_EXECINFO_H #include #endif #ifdef __MSC__ #include "ms_stdint.h" #include "ms_inttypes.h" #include "ms_stat.h" #else #ifndef SUNOS #include #endif #include #include #include #include #endif #endif /************************************************************************* * Architecture-specific modifications **************************************************************************/ // revised for SuiteSparse, Jan 2023 #if defined ( NO_SSIZE_T ) // #ifdef WIN32 typedef ptrdiff_t ssize_t; #else // POSIX: ssize_t is defined in sys/types.h #include #endif #ifdef SUNOS #define PTRDIFF_MAX INT64_MAX #endif #if 0 // rint and INFINITY disabled for SuiteSparse, Dec 2022 #ifdef __MSC__ /* MSC does not have rint() function */ #define rint(x) ((int)((x)+0.5)) /* MSC does not have INFINITY defined */ #ifndef INFINITY #define INFINITY FLT_MAX #endif #endif #endif #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/GKlib.h��������������������������������������0000644�0001751�0000144�00000006666�14552244506�023505� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * GKlib.h * * George's library of most frequently used routines * * $Id: GKlib.h 13005 2012-10-23 22:34:36Z karypis $ * */ #ifndef _GKLIB_H_ #define _GKLIB_H_ 1 #define GKMSPACE #if defined(_MSC_VER) #define __MSC__ #endif #if defined(__ICC) #define __ICC__ #endif #include "gk_arch.h" /*!< This should be here, prior to the includes */ /************************************************************************* * Header file inclusion section **************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include /* -------------------------------------------------------------------------- */ /* Added for SuiteSparse, to disable signal handling when incorporated into * a MATLAB mexFunction. Tim Davis, Jan 30, 2016, Texas A&M University. */ #ifdef MATLAB_MEX_FILE #include "mex.h" #define SIGABRT 6 #define SIGTERM 15 #define jmp_buf int #define raise(sig) { mexErrMsgTxt ("METIS error") ; } #define signal(sig,func) NULL #define longjmp(env,val) { mexErrMsgTxt ("METIS error") ; } #define setjmp(x) (0) #define exit(x) { mexErrMsgTxt ("METIS error") ; } #else #include #include #endif /* -------------------------------------------------------------------------- */ #include #include #if 0 // regex.h and gk_regex.h disabled for SuiteSparse, Jan 1, 2023. #if defined(__WITHPCRE__) #include #else #if defined(USE_GKREGEX) #include "gkregex.h" #else #include #endif /* defined(USE_GKREGEX) */ #endif /* defined(__WITHPCRE__) */ #endif #if defined(__OPENMP__) #include #endif /* -------------------------------------------------------------------------- */ /* Added for incorporation into SuiteSparse. Tim Davis, Oct 31, 2022, Texas A&M University. */ #include "SuiteSparse_config.h" #define malloc SuiteSparse_config_malloc #define calloc SuiteSparse_config_calloc #define realloc SuiteSparse_config_realloc #define free(p) \ { \ if ((p) != NULL) \ { \ SuiteSparse_config_free (p) ; \ (p) = NULL ; \ } \ } /* -------------------------------------------------------------------------- */ #include "gk_types.h" #include "gk_struct.h" #include "gk_externs.h" #include "gk_defs.h" #include "gk_macros.h" #include "gk_getopt.h" #include "gk_mksort.h" #include "gk_mkblas.h" #include "gk_mkmemory.h" #include "gk_mkpqueue.h" #include "gk_mkpqueue2.h" #include "gk_mkrandom.h" #include "gk_mkutils.h" #include "gk_proto.h" #endif /* GKlib.h */ ��������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/test/����������������������������������������0000755�0001751�0000144�00000000000�14576343415�023312� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/test/rw.c������������������������������������0000644�0001751�0000144�00000022155�14552026002�024073� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*! \file \brief A simple frequent itemset discovery program to test GKlib's routines \date 6/12/2008 \author George \version \verbatim $Id: rw.c 11387 2012-01-21 23:36:23Z karypis $ \endverbatim */ #include "GKlib.h" /*************************************************************************/ /*! Data structures for the code */ /*************************************************************************/ typedef struct { int niter; int ntvs; int ppr; float eps; float lamda; char *infile; char *outfile; } params_t; /*************************************************************************/ /*! Constants */ /*************************************************************************/ #define CMD_NITER 1 #define CMD_EPS 2 #define CMD_LAMDA 3 #define CMD_PPR 4 #define CMD_NTVS 5 #define CMD_HELP 10 /*************************************************************************/ /*! Local variables */ /*************************************************************************/ static struct gk_option long_options[] = { {"niter", 1, 0, CMD_NITER}, {"lamda", 1, 0, CMD_LAMDA}, {"eps", 1, 0, CMD_EPS}, {"ppr", 1, 0, CMD_PPR}, {"ntvs", 1, 0, CMD_NTVS}, {"help", 0, 0, CMD_HELP}, {0, 0, 0, 0} }; /*-------------------------------------------------------------------*/ /* Mini help */ /*-------------------------------------------------------------------*/ static char helpstr[][100] = { " ", "Usage: rw [options] ", " ", " Required parameters", " graph-file", " The name of the file storing the transactions. The file is in ", " Metis' graph format.", " ", " Optional parameters", " -niter=int", " Specifies the maximum number of iterations. [default: 100]", " ", " -lamda=float", " Specifies the follow-the-adjacent-links probability. [default: 0.80]", " ", " -eps=float", " Specifies the error tollerance. [default: 1e-10]", " ", " -ppr=int", " Specifies the source of the personalized PR. [default: -1]", " ", " -ntvs=int", " Specifies the number of test-vectors to compute. [default: -1]", " ", " -help", " Prints this message.", "" }; static char shorthelpstr[][100] = { " ", " Usage: rw [options] ", " use 'rw -help' for a summary of the options.", "" }; /*************************************************************************/ /*! Function prototypes */ /*************************************************************************/ void print_init_info(params_t *params, gk_csr_t *mat); void print_final_info(params_t *params); params_t *parse_cmdline(int argc, char *argv[]); /*************************************************************************/ /*! the entry point */ /**************************************************************************/ int main(int argc, char *argv[]) { ssize_t i, j, niter; params_t *params; gk_csr_t *mat; FILE *fpout; /* get command-line options */ params = parse_cmdline(argc, argv); /* read the data */ mat = gk_csr_Read(params->infile, GK_CSR_FMT_METIS, 1, 1); /* display some basic stats */ print_init_info(params, mat); if (params->ntvs != -1) { /* compute the pr for different randomly generated restart-distribution vectors */ float **prs; prs = gk_fAllocMatrix(params->ntvs, mat->nrows, 0.0, "main: prs"); /* generate the random restart vectors */ for (j=0; jntvs; j++) { for (i=0; inrows; i++) prs[j][i] = RandomInRange(931); gk_fscale(mat->nrows, 1.0/gk_fsum(mat->nrows, prs[j], 1), prs[j], 1); niter = gk_rw_PageRank(mat, params->lamda, params->eps, params->niter, prs[j]); printf("tvs#: %zd; niters: %zd\n", j, niter); } /* output the computed pr scores */ fpout = gk_fopen(params->outfile, "w", "main: outfile"); for (i=0; inrows; i++) { for (j=0; jntvs; j++) fprintf(fpout, "%.4e ", prs[j][i]); fprintf(fpout, "\n"); } gk_fclose(fpout); gk_fFreeMatrix(&prs, params->ntvs, mat->nrows); } else if (params->ppr != -1) { /* compute the personalized pr from the specified vertex */ float *pr; pr = gk_fsmalloc(mat->nrows, 0.0, "main: pr"); pr[params->ppr-1] = 1.0; niter = gk_rw_PageRank(mat, params->lamda, params->eps, params->niter, pr); printf("ppr: %d; niters: %zd\n", params->ppr, niter); /* output the computed pr scores */ fpout = gk_fopen(params->outfile, "w", "main: outfile"); for (i=0; inrows; i++) fprintf(fpout, "%.4e\n", pr[i]); gk_fclose(fpout); gk_free((void **)&pr, LTERM); } else { /* compute the standard pr */ int jmax; float diff, maxdiff; float *pr; pr = gk_fsmalloc(mat->nrows, 1.0/mat->nrows, "main: pr"); niter = gk_rw_PageRank(mat, params->lamda, params->eps, params->niter, pr); printf("pr; niters: %zd\n", niter); /* output the computed pr scores */ fpout = gk_fopen(params->outfile, "w", "main: outfile"); for (i=0; inrows; i++) { for (jmax=i, maxdiff=0.0, j=mat->rowptr[i]; jrowptr[i+1]; j++) { if ((diff = fabs(pr[i]-pr[mat->rowind[j]])) > maxdiff) { maxdiff = diff; jmax = mat->rowind[j]; } } fprintf(fpout, "%.4e %10zd %.4e %10d\n", pr[i], mat->rowptr[i+1]-mat->rowptr[i], maxdiff, jmax+1); } gk_fclose(fpout); gk_free((void **)&pr, LTERM); } gk_csr_Free(&mat); /* display some final stats */ print_final_info(params); } /*************************************************************************/ /*! This function prints run parameters */ /*************************************************************************/ void print_init_info(params_t *params, gk_csr_t *mat) { printf("*******************************************************************************\n"); printf(" fis\n\n"); printf("Matrix Information ---------------------------------------------------------\n"); printf(" input file=%s, [%d, %d, %zd]\n", params->infile, mat->nrows, mat->ncols, mat->rowptr[mat->nrows]); printf("\n"); printf("Options --------------------------------------------------------------------\n"); printf(" niter=%d, ntvs=%d, ppr=%d, lamda=%f, eps=%e\n", params->niter, params->ntvs, params->ppr, params->lamda, params->eps); printf("\n"); printf("Performing random walks... ----------------------------------------------\n"); } /*************************************************************************/ /*! This function prints final statistics */ /*************************************************************************/ void print_final_info(params_t *params) { printf("\n"); printf("Memory Usage Information -----------------------------------------------------\n"); printf(" Maximum memory used: %10zd bytes\n", (ssize_t) gk_GetMaxMemoryUsed()); printf(" Current memory used: %10zd bytes\n", (ssize_t) gk_GetCurMemoryUsed()); printf("********************************************************************************\n"); } /*************************************************************************/ /*! This is the entry point of the command-line argument parser */ /*************************************************************************/ params_t *parse_cmdline(int argc, char *argv[]) { int i; int c, option_index; params_t *params; params = (params_t *)gk_malloc(sizeof(params_t), "parse_cmdline: params"); /* initialize the params data structure */ params->niter = 100; params->ppr = -1; params->ntvs = -1; params->eps = 1e-10; params->lamda = 0.80; params->infile = NULL; params->outfile = NULL; /* Parse the command line arguments */ while ((c = gk_getopt_long_only(argc, argv, "", long_options, &option_index)) != -1) { switch (c) { case CMD_NITER: if (gk_optarg) params->niter = atoi(gk_optarg); break; case CMD_NTVS: if (gk_optarg) params->ntvs = atoi(gk_optarg); break; case CMD_PPR: if (gk_optarg) params->ppr = atoi(gk_optarg); break; case CMD_EPS: if (gk_optarg) params->eps = atof(gk_optarg); break; case CMD_LAMDA: if (gk_optarg) params->lamda = atof(gk_optarg); break; case CMD_HELP: for (i=0; strlen(helpstr[i]) > 0; i++) printf("%s\n", helpstr[i]); exit(0); break; case '?': default: printf("Illegal command-line option(s)\nUse %s -help for a summary of the options.\n", argv[0]); exit(0); } } if (argc-gk_optind != 2) { printf("Unrecognized parameters."); for (i=0; strlen(shorthelpstr[i]) > 0; i++) printf("%s\n", shorthelpstr[i]); exit(0); } params->infile = gk_strdup(argv[gk_optind++]); params->outfile = gk_strdup(argv[gk_optind++]); if (!gk_fexists(params->infile)) errexit("input file %s does not exist.\n", params->infile); if (params->ppr != -1 && params->ntvs != -1) errexit("Only one of the -ppr and -ntvs options can be specified.\n"); return params; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/test/gksort.c��������������������������������0000644�0001751�0000144�00000021435�14552026002�024754� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*! \file gksort.c \brief Testing module for the various sorting routines in GKlib \date Started 4/4/2007 \author George \version\verbatim $Id: gksort.c 11058 2011-11-10 00:02:50Z karypis $ \endverbatim */ #include "GKlib.h" #define N 10000 /*************************************************************************/ /*! Testing module for gk_?isort() routine */ /*************************************************************************/ void test_isort() { gk_idx_t i; int array[N]; /* test the increasing sort */ printf("Testing iisort...\n"); for (i=0; i array[i+1]) printf("gk_isorti error at index %jd [%d %d]\n", (intmax_t)i, array[i], array[i+1]); } /* test the decreasing sort */ printf("Testing disort...\n"); for (i=0; i array[i+1]) printf("gk_fsorti error at index %jd [%f %f]\n", (intmax_t)i, array[i], array[i+1]); } /* test the decreasing sort */ printf("Testing dfsort...\n"); for (i=0; i array[i+1]) printf("gk_idxsorti error at index %zd [%zd %zd]\n", (ssize_t)i, (ssize_t)array[i], (ssize_t)array[i+1]); } /* test the decreasing sort */ printf("Testing idxsortd...\n"); for (i=0; i array[i+1].key) printf("gk_ikvsorti error at index %jd [%d %d] [%jd %jd]\n", (intmax_t)i, array[i].key, array[i+1].key, (intmax_t)array[i].val, (intmax_t)array[i+1].val); } /* test the decreasing sort */ printf("Testing ikvsortd...\n"); for (i=0; i array[i+1].key) printf("gk_fkvsorti error at index %jd [%f %f] [%jd %jd]\n", (intmax_t)i, array[i].key, array[i+1].key, (intmax_t)array[i].val, (intmax_t)array[i+1].val); } /* test the decreasing sort */ printf("Testing fkvsortd...\n"); for (i=0; i array[i+1].key) printf("gk_dkvsorti error at index %jd [%lf %lf] [%jd %jd]\n", (intmax_t)i, array[i].key, array[i+1].key, (intmax_t)array[i].val, (intmax_t)array[i+1].val); } /* test the decreasing sort */ printf("Testing dkvsortd...\n"); for (i=0; i 0) printf("gk_skvsorti error at index %jd [%s %s] [%jd %jd]\n", (intmax_t)i, array[i].key, array[i+1].key, (intmax_t)array[i].val, (intmax_t)array[i+1].val); } /* test the decreasing sort */ printf("Testing skvsortd...\n"); for (i=0; i array[i+1].key) printf("gk_idxkvsorti error at index %zd [%zd %zd] [%zd %zd]\n", (ssize_t)i, (ssize_t)array[i].key, (ssize_t)array[i+1].key, (ssize_t)array[i].val, (ssize_t)array[i+1].val); } /* test the decreasing sort */ printf("Testing idxkvsortd...\n"); for (i=0; i", " ", " Required parameters", " mat-file", " The name of the file storing the transactions. The file is in ", " Cluto's .mat format.", " ", " Optional parameters", " -minlen=int", " Specifies the minimum length of the patterns. [default: 1]", " ", " -maxlen=int", " Specifies the maximum length of the patterns. [default: none]", " ", " -minfreq=int", " Specifies the minimum frequency of the patterns. [default: 10]", " ", " -maxfreq=int", " Specifies the maximum frequency of the patterns. [default: none]", " ", " -silent", " Does not print the discovered itemsets.", " ", " -clabels=filename", " Specifies the name of the file that stores the column labels.", " ", " -help", " Prints this message.", "" }; static char shorthelpstr[][100] = { " ", " Usage: fis [options] ", " use 'fis -help' for a summary of the options.", "" }; /*************************************************************************/ /*! Function prototypes */ /*************************************************************************/ void print_init_info(params_t *params, gk_csr_t *mat); void print_final_info(params_t *params); params_t *parse_cmdline(int argc, char *argv[]); void print_an_itemset(void *stateptr, int nitems, int *itemind, int ntrans, int *tranind); /*************************************************************************/ /*! the entry point */ /**************************************************************************/ int main(int argc, char *argv[]) { ssize_t i; char line[8192]; FILE *fpin; params_t *params; gk_csr_t *mat; params = parse_cmdline(argc, argv); params->nitemsets = 0; /* read the data */ mat = gk_csr_Read(params->filename, GK_CSR_FMT_CLUTO, 1, 1); gk_csr_CreateIndex(mat, GK_CSR_COL); /* read the column labels */ params->clabels = (char **)gk_malloc(mat->ncols*sizeof(char *), "main: clabels"); if (params->clabelfile == NULL) { for (i=0; incols; i++) { sprintf(line, "%zd", i); params->clabels[i] = gk_strdup(line); } } else { fpin = gk_fopen(params->clabelfile, "r", "main: fpin"); for (i=0; incols; i++) { if (fgets(line, 8192, fpin) == NULL) errexit("Failed on fgets.\n"); params->clabels[i] = gk_strdup(gk_strtprune(line, " \n\t")); } gk_fclose(fpin); } print_init_info(params, mat); gk_find_frequent_itemsets(mat->nrows, mat->rowptr, mat->rowind, params->minfreq, params->maxfreq, params->minlen, params->maxlen, &print_an_itemset, (void *)params); printf("Total itemsets found: %zd\n", params->nitemsets); print_final_info(params); } /*************************************************************************/ /*! This function prints run parameters */ /*************************************************************************/ void print_init_info(params_t *params, gk_csr_t *mat) { printf("*******************************************************************************\n"); printf(" fis\n\n"); printf("Matrix Information ---------------------------------------------------------\n"); printf(" input file=%s, [%d, %d, %zd]\n", params->filename, mat->nrows, mat->ncols, mat->rowptr[mat->nrows]); printf("\n"); printf("Options --------------------------------------------------------------------\n"); printf(" minlen=%zd, maxlen=%zd, minfeq=%zd, maxfreq=%zd\n", params->minlen, params->maxlen, params->minfreq, params->maxfreq); printf("\n"); printf("Finding patterns... -----------------------------------------------------\n"); } /*************************************************************************/ /*! This function prints final statistics */ /*************************************************************************/ void print_final_info(params_t *params) { printf("\n"); printf("Memory Usage Information -----------------------------------------------------\n"); printf(" Maximum memory used: %10zd bytes\n", (ssize_t) gk_GetMaxMemoryUsed()); printf(" Current memory used: %10zd bytes\n", (ssize_t) gk_GetCurMemoryUsed()); printf("********************************************************************************\n"); } /*************************************************************************/ /*! This is the entry point of the command-line argument parser */ /*************************************************************************/ params_t *parse_cmdline(int argc, char *argv[]) { int i; int c, option_index; params_t *params; params = (params_t *)gk_malloc(sizeof(params_t), "parse_cmdline: params"); /* initialize the params data structure */ params->minlen = 1; params->maxlen = -1; params->minfreq = 10; params->maxfreq = -1; params->silent = 0; params->filename = NULL; params->clabelfile = NULL; /* Parse the command line arguments */ while ((c = gk_getopt_long_only(argc, argv, "", long_options, &option_index)) != -1) { switch (c) { case CMD_MINLEN: if (gk_optarg) params->minlen = atoi(gk_optarg); break; case CMD_MAXLEN: if (gk_optarg) params->maxlen = atoi(gk_optarg); break; case CMD_MINFREQ: if (gk_optarg) params->minfreq = atoi(gk_optarg); break; case CMD_MAXFREQ: if (gk_optarg) params->maxfreq = atoi(gk_optarg); break; case CMD_SILENT: params->silent = 1; break; case CMD_CLABELFILE: if (gk_optarg) params->clabelfile = gk_strdup(gk_optarg); break; case CMD_HELP: for (i=0; strlen(helpstr[i]) > 0; i++) printf("%s\n", helpstr[i]); exit(0); break; case '?': default: printf("Illegal command-line option(s)\nUse %s -help for a summary of the options.\n", argv[0]); exit(0); } } if (argc-gk_optind != 1) { printf("Unrecognized parameters."); for (i=0; strlen(shorthelpstr[i]) > 0; i++) printf("%s\n", shorthelpstr[i]); exit(0); } params->filename = gk_strdup(argv[gk_optind++]); if (!gk_fexists(params->filename)) errexit("input file %s does not exist.\n", params->filename); return params; } /*************************************************************************/ /*! This is the callback function for the itemset discovery routine */ /*************************************************************************/ void print_an_itemset(void *stateptr, int nitems, int *itemids, int ntrans, int *transids) { ssize_t i; params_t *params; params = (params_t *)stateptr; params->nitemsets++; if (!params->silent) { printf("%4zd %4d %4d => ", params->nitemsets, nitems, ntrans); for (i=0; iclabels[itemids[i]]); printf("\n"); for (i=0; i []", " ", " Required parameters", " graph-file", " The name of the file storing the graph. The file is in ", " Metis' graph format.", " ", " Optional parameters", " -niter=int", " Specifies the maximum number of iterations. [default: 100]", " ", " -lamda=float", " Specifies the follow-the-adjacent-links probability. [default: 0.80]", " ", " -eps=float", " Specifies the error tollerance. [default: 1e-10]", " ", " -help", " Prints this message.", "" }; static char shorthelpstr[][100] = { " ", " Usage: gkgraph [options] []", " use 'gkgraph -help' for a summary of the options.", "" }; /*************************************************************************/ /*! Function prototypes */ /*************************************************************************/ double compute_compactness(params_t *params, gk_graph_t *graph, int32_t *perm); void reorder_centroid(params_t *params, gk_graph_t *graph, int32_t *perm); void print_init_info(params_t *params, gk_graph_t *graph); void print_final_info(params_t *params); params_t *parse_cmdline(int argc, char *argv[]); /*************************************************************************/ /*! the entry point */ /**************************************************************************/ int main(int argc, char *argv[]) { ssize_t i, j, v; params_t *params; gk_graph_t *graph, *pgraph; int32_t *perm; /* get command-line options */ params = parse_cmdline(argc, argv); /* read the data */ graph = gk_graph_Read(params->infile, GK_GRAPH_FMT_METIS, 0, 0, 0); /* display some basic stats */ print_init_info(params, graph); /* determine the initial compactness of the graph */ printf("Initial compactness: %le\n", compute_compactness(params, graph, NULL)); /* compute the BFS ordering and re-order the graph */ //for (i=0; initer; i++) { for (i=0; i<1; i++) { v = RandomInRange(graph->nvtxs); gk_graph_ComputeBFSOrdering(graph, v, &perm, NULL); printf("BFS from %8d. Compactness: %le\n", (int) v, compute_compactness(params, graph, perm)); pgraph = gk_graph_Reorder(graph, perm, NULL); gk_graph_Write(pgraph, "bfs.metis", GK_GRAPH_FMT_METIS); gk_graph_Free(&pgraph); gk_graph_ComputeBestFOrdering(graph, v, params->type, &perm, NULL); printf("BestF from %8d. Compactness: %le\n", (int) v, compute_compactness(params, graph, perm)); pgraph = gk_graph_Reorder(graph, perm, NULL); gk_graph_Write(pgraph, "bestf.metis", GK_GRAPH_FMT_METIS); gk_graph_Free(&pgraph); #ifdef XXX for (j=0; jniter; j++) { reorder_centroid(params, graph, perm); printf("\tAfter centroid; Compactness: %le\n", compute_compactness(params, graph, perm)); } pgraph = gk_graph_Reorder(graph, perm, NULL); gk_graph_Write(pgraph, "centroid.metis", GK_GRAPH_FMT_METIS); gk_graph_Free(&pgraph); #endif gk_free((void **)&perm, LTERM); } gk_graph_Free(&graph); //gk_graph_Free(&pgraph); print_final_info(params); } /*************************************************************************/ /*! This function computes the compactness of the graph's adjacency list */ /*************************************************************************/ double compute_compactness(params_t *params, gk_graph_t *graph, int32_t *perm) { int i, v, u, nvtxs; ssize_t j, *xadj; int32_t *adjncy; double compactness=0.0; int *freq; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; freq = gk_ismalloc(nvtxs, 0, "compute_compactness: freq"); for (i=0; i 0) printf("%7d %6d\n", i, freq[i]); } */ printf("\tnsmall: %d\n", freq[1]+freq[2]+freq[3]); return compactness/xadj[nvtxs]; } /*************************************************************************/ /*! This function uses a centroid-based approach to refine the ordering */ /*************************************************************************/ void reorder_centroid(params_t *params, gk_graph_t *graph, int32_t *perm) { int i, v, u, nvtxs; ssize_t j, *xadj; int32_t *adjncy; gk_fkv_t *cand; double displacement; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; cand = gk_fkvmalloc(nvtxs, "reorder_centroid: cand"); for (i=0; ilamda/(xadj[i+1]-xadj[i]); } /* sort them based on the target position in increasing order */ gk_fkvsorti(nvtxs, cand); /* derive the permutation from the ordered list */ gk_i32set(nvtxs, -1, perm); for (i=0; iinfile, graph->nvtxs, graph->xadj[graph->nvtxs]); printf("\n"); printf("Options --------------------------------------------------------------------\n"); printf(" type=%d, niter=%d, lamda=%f, eps=%e\n", params->type, params->niter, params->lamda, params->eps); printf("\n"); printf("Working... -----------------------------------------------------------------\n"); } /*************************************************************************/ /*! This function prints final statistics */ /*************************************************************************/ void print_final_info(params_t *params) { printf("\n"); printf("Memory Usage Information -----------------------------------------------------\n"); printf(" Maximum memory used: %10zd bytes\n", (ssize_t) gk_GetMaxMemoryUsed()); printf(" Current memory used: %10zd bytes\n", (ssize_t) gk_GetCurMemoryUsed()); printf("********************************************************************************\n"); } /*************************************************************************/ /*! This is the entry point of the command-line argument parser */ /*************************************************************************/ params_t *parse_cmdline(int argc, char *argv[]) { int i; int c, option_index; params_t *params; params = (params_t *)gk_malloc(sizeof(params_t), "parse_cmdline: params"); /* initialize the params data structure */ params->type = 1; params->niter = 1; params->eps = 1e-10; params->lamda = 0.20; params->infile = NULL; /* Parse the command line arguments */ while ((c = gk_getopt_long_only(argc, argv, "", long_options, &option_index)) != -1) { switch (c) { case CMD_TYPE: if (gk_optarg) params->type = atoi(gk_optarg); break; case CMD_NITER: if (gk_optarg) params->niter = atoi(gk_optarg); break; case CMD_EPS: if (gk_optarg) params->eps = atof(gk_optarg); break; case CMD_LAMDA: if (gk_optarg) params->lamda = atof(gk_optarg); break; case CMD_HELP: for (i=0; strlen(helpstr[i]) > 0; i++) printf("%s\n", helpstr[i]); exit(0); break; case '?': default: printf("Illegal command-line option(s)\nUse %s -help for a summary of the options.\n", argv[0]); exit(0); } } if (argc-gk_optind != 1) { printf("Unrecognized parameters."); for (i=0; strlen(shorthelpstr[i]) > 0; i++) printf("%s\n", shorthelpstr[i]); exit(0); } params->infile = gk_strdup(argv[gk_optind++]); if (argc-gk_optind > 0) params->outfile = gk_strdup(argv[gk_optind++]); else params->outfile = gk_strdup("gkgraph.out"); if (!gk_fexists(params->infile)) errexit("input file %s does not exist.\n", params->infile); return params; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/test/strings.c�������������������������������0000644�0001751�0000144�00000004432�14552026002�025132� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*! \file strings.c \brief Testing module for the string functions in GKlib \date Started 3/5/2007 \author George \version\verbatim $Id: strings.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim */ #include "GKlib.h" /*************************************************************************/ /*! Testing module for gk_strstr_replace() */ /*************************************************************************/ void test_strstr_replace() { char *new_str; int rc; rc = gk_strstr_replace("This is a simple string", "s", "S", "", &new_str); printf("%d, %s.\n", rc, new_str); gk_free((void **)&new_str, LTERM); rc = gk_strstr_replace("This is a simple string", "s", "S", "g", &new_str); printf("%d, %s.\n", rc, new_str); gk_free((void **)&new_str, LTERM); rc = gk_strstr_replace("This is a simple SS & ss string", "s", "T", "g", &new_str); printf("%d, %s.\n", rc, new_str); gk_free((void **)&new_str, LTERM); rc = gk_strstr_replace("This is a simple SS & ss string", "s", "T", "ig", &new_str); printf("%d, %s.\n", rc, new_str); gk_free((void **)&new_str, LTERM); rc = gk_strstr_replace("This is a simple SS & ss string", "\\b\\w(\\w+)\\w\\b", "$1", "ig", &new_str); printf("%d, %s.\n", rc, new_str); gk_free((void **)&new_str, LTERM); rc = gk_strstr_replace("This is a simple SS & ss string", "\\b\\w+\\b", "word", "ig", &new_str); printf("%d, %s.\n", rc, new_str); gk_free((void **)&new_str, LTERM); rc = gk_strstr_replace("http://www.cs.umn.edu/This-is-something-T12323?pp=20&page=4", "(http://www\\.cs\\.umn\\.edu/)(.*)-T(\\d+)", "$1$2-P$3", "g", &new_str); printf("%d, %s.\n", rc, new_str); gk_free((void **)&new_str, LTERM); rc = gk_strstr_replace("http://www.cs.umn.edu/This-is-something-T12323?pp=20&page=4", "(\\d+)", "number:$1", "ig", &new_str); printf("%d, %s.\n", rc, new_str); gk_free((void **)&new_str, LTERM); rc = gk_strstr_replace("http://www.cs.umn.edu/This-is-something-T12323?pp=20&page=4", "(http://www\\.cs\\.umn\\.edu/)", "[$1]", "g", &new_str); printf("%d, %s.\n", rc, new_str); gk_free((void **)&new_str, LTERM); } int main() { test_strstr_replace(); /* { int i; for (i=0; i<1000; i++) printf("%d\n", RandomInRange(3)); } */ } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/random.c�������������������������������������0000644�0001751�0000144�00000012435�14552244506�023757� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file \brief Various routines for providing portable 32 and 64 bit random number generators. \date Started 5/17/2007 \author George \version\verbatim $Id: random.c 11793 2012-04-04 21:03:02Z karypis $ \endverbatim */ #include "GKlib.h" /*************************************************************************/ /*! Create the various random number functions */ /*************************************************************************/ GK_MKRANDOM(gk_c, size_t, char) GK_MKRANDOM(gk_i, size_t, int) GK_MKRANDOM(gk_f, size_t, float) GK_MKRANDOM(gk_d, size_t, double) GK_MKRANDOM(gk_idx, size_t, gk_idx_t) GK_MKRANDOM(gk_z, size_t, ssize_t) /*************************************************************************/ /*! GKlib's built in random number generator for portability across different architectures */ /*************************************************************************/ #ifdef USE_GKRAND /* A C-program for MT19937-64 (2004/9/29 version). Coded by Takuji Nishimura and Makoto Matsumoto. This is a 64-bit version of Mersenne Twister pseudorandom number generator. Before using, initialize the state by using init_genrand64(seed) or init_by_array64(init_key, key_length). Copyright (C) 2004, Makoto Matsumoto and Takuji Nishimura, All rights reserved. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define NN 312 #define MM 156 #define MATRIX_A 0xB5026F5AA96619E9ULL #define UM 0xFFFFFFFF80000000ULL /* Most significant 33 bits */ #define LM 0x7FFFFFFFULL /* Least significant 31 bits */ // added by Tim Davis for CHOLMOD: mt and mti state variables threadprivate #if defined ( _OPENMP ) // OpenMP threadprivate is preferred static uint64_t mt[NN]; static int mti=NN+1; #pragma omp threadprivate (mt,mti) #elif defined ( HAVE_KEYWORD__THREAD ) // gcc and many other compilers support the __thread keyword static __thread uint64_t mt[NN]; static __thread int mti=NN+1; #elif defined ( HAVE_KEYWORD__DECLSPEC_THREAD ) // Windows: __declspec (thread) __declspec ( thread ) static uint64_t mt[NN]; __declspec ( thread ) static int mti=NN+1; #elif defined ( HAVE_KEYWORD__THREAD_LOCAL ) // ANSI C11 threads #include _Thread_local static uint64_t mt[NN]; _Thread_local static int mti=NN+1; #else // original METIS uses global state: this is not thread-safe: /* The array for the state vector */ static uint64_t mt[NN]; /* mti==NN+1 means mt[NN] is not initialized */ static int mti=NN+1; #endif #endif /* USE_GKRAND */ /* initializes mt[NN] with a seed */ void gk_randinit(uint64_t seed) { #ifdef USE_GKRAND mt[0] = seed; for (mti=1; mti> 62)) + mti); #else srand((unsigned int) seed); #endif } /* generates a random number on [0, 2^64-1]-interval */ uint64_t gk_randint64(void) { #ifdef USE_GKRAND int i; unsigned long long x; static uint64_t mag01[2]={0ULL, MATRIX_A}; if (mti >= NN) { /* generate NN words at one time */ /* if init_genrand64() has not been called, */ /* a default initial seed is used */ if (mti == NN+1) gk_randinit(5489ULL); for (i=0; i>1) ^ mag01[(int)(x&1ULL)]; } for (; i>1) ^ mag01[(int)(x&1ULL)]; } x = (mt[NN-1]&UM)|(mt[0]&LM); mt[NN-1] = mt[MM-1] ^ (x>>1) ^ mag01[(int)(x&1ULL)]; mti = 0; } x = mt[mti++]; x ^= (x >> 29) & 0x5555555555555555ULL; x ^= (x << 17) & 0x71D67FFFEDA60000ULL; x ^= (x << 37) & 0xFFF7EEE000000000ULL; x ^= (x >> 43); return x & 0x7FFFFFFFFFFFFFFF; #else return (uint64_t)(((uint64_t) rand()) << 32 | ((uint64_t) rand())); #endif } /* generates a random number on [0, 2^32-1]-interval */ uint32_t gk_randint32(void) { #ifdef USE_GKRAND return (uint32_t)(gk_randint64() & 0x7FFFFFFF); #else return (uint32_t)rand(); #endif } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/pdb.c����������������������������������������0000644�0001751�0000144�00000037031�14552244506�023243� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /************************************************************************/ /*! \file pdb.c \brief Functions for parsing pdb files. Pdb reader (parser). Loads arrays of pointers for easy backbone access. \date Started 10/20/06 \author Kevin \version $Id: pdb.c 10711 2011-08-31 22:23:04Z karypis $ */ /************************************************************************/ #include "GKlib.h" /************************************************************************/ /*! \brief Converts three-letter amino acid codes to one-leter codes. This function takes a three letter \c * and converts it to a single \c \param res is the three-letter code to be converted. \returns A \c representing the amino acid. */ /************************************************************************/ char gk_threetoone(char *res) { /* {{{ */ /* make sure the matching works */ res[0] = toupper(res[0]); res[1] = toupper(res[1]); res[2] = toupper(res[2]); if(strcmp(res,"ALA") == 0) { return 'A'; } else if(strcmp(res,"CYS") == 0) { return 'C'; } else if(strcmp(res,"ASP") == 0) { return 'D'; } else if(strcmp(res,"GLU") == 0) { return 'E'; } else if(strcmp(res,"PHE") == 0) { return 'F'; } else if(strcmp(res,"GLY") == 0) { return 'G'; } else if(strcmp(res,"HIS") == 0) { return 'H'; } else if(strcmp(res,"ILE") == 0) { return 'I'; } else if(strcmp(res,"LYS") == 0) { return 'K'; } else if(strcmp(res,"LEU") == 0) { return 'L'; } else if(strcmp(res,"MET") == 0) { return 'M'; } else if(strcmp(res,"ASN") == 0) { return 'N'; } else if(strcmp(res,"PRO") == 0) { return 'P'; } else if(strcmp(res,"GLN") == 0) { return 'Q'; } else if(strcmp(res,"ARG") == 0) { return 'R'; } else if(strcmp(res,"SER") == 0) { return 'S'; } else if(strcmp(res,"THR") == 0) { return 'T'; } else if(strcmp(res,"SCY") == 0) { return 'U'; } else if(strcmp(res,"VAL") == 0) { return 'V'; } else if(strcmp(res,"TRP") == 0) { return 'W'; } else if(strcmp(res,"TYR") == 0) { return 'Y'; } else { return 'X'; } } /* }}} */ /************************************************************************/ /*! \brief Frees the memory of a pdbf structure. This function takes a pdbf pointer and frees all the memory below it. \param p is the pdbf structure to be freed. */ /************************************************************************/ void gk_freepdbf(pdbf *p) { /* {{{ */ int i; if(p != NULL) { gk_free((void **)&p->resSeq, LTERM); for(i=0; inatoms; i++) { gk_free((void **)&p->atoms[i].name, &p->atoms[i].resname, LTERM); } for(i=0; inresidues; i++) { gk_free((void *)&p->threeresSeq[i], LTERM); } /* this may look like it's wrong, but it's just a 1-d array of pointers, and the pointers themselves are freed above */ gk_free((void **)&p->bbs, &p->cas, &p->atoms, &p->cm, &p->threeresSeq, LTERM); } gk_free((void **)&p, LTERM); } /* }}} */ /************************************************************************/ /*! \brief Reads a pdb file into a pdbf structure This function allocates a pdbf structure and reads the file fname into that structure. \param fname is the file name to be read \returns A filled pdbf structure. */ /************************************************************************/ pdbf *gk_readpdbfile(char *fname) { /* {{{ */ int i=0, res=0; char linetype[6]; int aserial; char aname[5] = " \0"; char altLoc = ' '; char rname[4] = " \0"; char chainid = ' '; char oldchainid = ' '; int rserial; int oldRserial = -37; char icode = ' '; char element = ' '; double x; double y; double z; double avgx; double avgy; double avgz; double opcy; double tmpt; char line[MAXLINELEN]; int corruption=0; int nresatoms; int atoms=0, residues=0, cas=0, bbs=0, firstres=1; pdbf *toFill = gk_malloc(sizeof(pdbf),"fillme"); FILE *FPIN; FPIN = gk_fopen(fname,"r",fname); while(fgets(line, 256, FPIN)) { sscanf(line,"%s ",linetype); /* It seems the only reliable parts are through temperature, so we only use these parts */ /* if(strstr(linetype, "ATOM") != NULL || strstr(linetype, "HETATM") != NULL) { */ if(strstr(linetype, "ATOM") != NULL) { sscanf(line, "%6s%5d%*1c%4c%1c%3c%*1c%1c%4d%1c%*3c%8lf%8lf%8lf%6lf%6lf %c\n", linetype,&aserial,aname,&altLoc,rname,&chainid,&rserial,&icode,&x,&y,&z,&opcy,&tmpt,&element); sscanf(linetype, " %s ",linetype); sscanf(aname, " %s ",aname); sscanf(rname, " %s ",rname); if(altLoc != ' ') { corruption = corruption|CRP_ALTLOCS; } if(firstres == 1) { oldRserial = rserial; oldchainid = chainid; residues++; firstres = 0; } if(oldRserial != rserial) { residues++; oldRserial = rserial; } if(oldchainid != chainid) { corruption = corruption|CRP_MULTICHAIN; } oldchainid = chainid; atoms++; if(strcmp(aname,"CA") == 0) { cas++; } if(strcmp(aname,"N") == 0 || strcmp(aname,"CA") == 0 || strcmp(aname,"C") == 0 || strcmp(aname,"O") == 0) { bbs++; } } else if(strstr(linetype, "ENDMDL") != NULL || strstr(linetype, "END") != NULL || strstr(linetype, "TER") != NULL) { break; } } fclose(FPIN); /* printf("File has coordinates for %d atoms in %d residues\n",atoms,residues); */ toFill->natoms = atoms; toFill->ncas = cas; toFill->nbbs = bbs; toFill->nresidues = residues; toFill->resSeq = (char *) gk_malloc (residues*sizeof(char),"residue seq"); toFill->threeresSeq = (char **)gk_malloc (residues*sizeof(char *),"residue seq"); toFill->atoms = (atom *) gk_malloc (atoms*sizeof(atom), "atoms"); toFill->bbs = (atom **)gk_malloc ( bbs*sizeof(atom *),"bbs"); toFill->cas = (atom **)gk_malloc ( cas*sizeof(atom *),"cas"); toFill->cm = (center_of_mass *)gk_malloc(residues*sizeof(center_of_mass),"center of mass"); res=0; firstres=1; cas=0; bbs=0; i=0; avgx = 0.0; avgy = 0.0; avgz = 0.0; nresatoms = 0; FPIN = gk_fopen(fname,"r",fname); while(fgets(line, 256, FPIN)) { sscanf(line,"%s ",linetype); /* It seems the only reliable parts are through temperature, so we only use these parts */ /* if(strstr(linetype, "ATOM") != NULL || strstr(linetype, "HETATM") != NULL) { */ if(strstr(linetype, "ATOM") != NULL ) { /* to ensure our memory doesn't get corrupted by the biologists, we only read this far */ sscanf(line, "%6s%5d%*1c%4c%1c%3c%*1c%1c%4d%1c%*3c%8lf%8lf%8lf%6lf%6lf %c\n", linetype,&aserial,aname,&altLoc,rname,&chainid,&rserial,&icode,&x,&y,&z,&opcy,&tmpt,&element); sscanf(aname, "%s",aname); sscanf(rname, "%s",rname); if(firstres == 1) { toFill->resSeq[res] = gk_threetoone(rname); toFill->threeresSeq[res] = gk_strdup(rname); oldRserial = rserial; res++; firstres = 0; } if(oldRserial != rserial) { /* we're changing residues. store the center of mass from the last one & reset */ toFill->cm[res-1].x = avgx/nresatoms; toFill->cm[res-1].y = avgy/nresatoms; toFill->cm[res-1].z = avgz/nresatoms; avgx = 0.0; avgy = 0.0; avgz = 0.0; nresatoms = 0; toFill->cm[res-1].name = toFill->resSeq[res-1]; toFill->threeresSeq[res] = gk_strdup(rname); toFill->resSeq[res] = gk_threetoone(rname); res++; oldRserial = rserial; } avgx += x; avgy += y; avgz += z; nresatoms++; toFill->atoms[i].x = x; toFill->atoms[i].y = y; toFill->atoms[i].z = z; toFill->atoms[i].opcy = opcy; toFill->atoms[i].tmpt = tmpt; toFill->atoms[i].element = element; toFill->atoms[i].serial = aserial; toFill->atoms[i].chainid = chainid; toFill->atoms[i].altLoc = altLoc; toFill->atoms[i].rserial = rserial; toFill->atoms[i].icode = icode; toFill->atoms[i].name = gk_strdup(aname); toFill->atoms[i].resname = gk_strdup(rname); /* Set up pointers for the backbone and c-alpha shortcuts */ if(strcmp(aname,"CA") == 0) { toFill->cas[cas] = &(toFill->atoms[i]); cas++; } if(strcmp(aname,"N") == 0 || strcmp(aname,"CA") == 0 || strcmp(aname,"C") == 0 || strcmp(aname,"O") == 0) { toFill->bbs[bbs] = &(toFill->atoms[i]); bbs++; } i++; } else if(strstr(linetype, "ENDMDL") != NULL || strstr(linetype, "END") != NULL || strstr(linetype, "TER") != NULL) { break; } } /* get that last average */ toFill->cm[res-1].x = avgx/nresatoms; toFill->cm[res-1].y = avgy/nresatoms; toFill->cm[res-1].z = avgz/nresatoms; /* Begin test code */ if(cas != residues) { printf("Number of residues and CA coordinates differs by %d (!)\n",residues-cas); if(cas < residues) { corruption = corruption|CRP_MISSINGCA; } else if(cas > residues) { corruption = corruption|CRP_MULTICA; } } if(bbs < residues*4) { corruption = corruption|CRP_MISSINGBB; } else if(bbs > residues*4) { corruption = corruption|CRP_MULTIBB; } fclose(FPIN); toFill->corruption = corruption; /* if(corruption == 0) printf("File was clean!\n"); */ return(toFill); } /* }}} */ /************************************************************************/ /*! \brief Writes the sequence of residues from a pdb file. This function takes a pdbf structure and a filename, and writes out the amino acid sequence according to the atomic coordinates. The output is in fasta format. \param p is the pdbf structure with the sequence of interest \param fname is the file name to be written */ /************************************************************************/ void gk_writefastafrompdb(pdbf *pb, char *fname) { int i; FILE *FPOUT; FPOUT = gk_fopen(fname,"w",fname); fprintf(FPOUT,"> %s\n",fname); for(i=0; inresidues; i++) fprintf(FPOUT,"%c",pb->resSeq[i]); fprintf(FPOUT,"\n"); fclose(FPOUT); } /************************************************************************/ /*! \brief Writes all centers of mass in pdb-format to file fname. This function takes a pdbf structure and writes out the calculated mass center information to file fname as though each one was a c-alpha. \param p is the pdbf structure to write out \param fname is the file name to be written */ /************************************************************************/ void gk_writecentersofmass(pdbf *p, char *fname) { int i; FILE *FPIN; FPIN = gk_fopen(fname,"w",fname); for(i=0; inresidues; i++) { fprintf(FPIN,"%-6s%5d %4s%1c%3s %1c%4d%1c %8.3lf%8.3lf%8.3lf%6.2f%6.2f\n", "ATOM ",i,"CA",' ',p->threeresSeq[i],' ',i,' ',p->cm[i].x,p->cm[i].y,p->cm[i].z,1.0,-37.0); } fclose(FPIN); } /************************************************************************/ /*! \brief Writes all atoms in p in pdb-format to file fname. This function takes a pdbf structure and writes out all the atom information to file fname. \param p is the pdbf structure to write out \param fname is the file name to be written */ /************************************************************************/ void gk_writefullatom(pdbf *p, char *fname) { int i; FILE *FPIN; FPIN = gk_fopen(fname,"w",fname); for(i=0; inatoms; i++) { fprintf(FPIN,"%-6s%5d %4s%1c%3s %1c%4d%1c %8.3lf%8.3lf%8.3lf%6.2f%6.2f\n", "ATOM ",p->atoms[i].serial,p->atoms[i].name,p->atoms[i].altLoc,p->atoms[i].resname,p->atoms[i].chainid,p->atoms[i].rserial,p->atoms[i].icode,p->atoms[i].x,p->atoms[i].y,p->atoms[i].z,p->atoms[i].opcy,p->atoms[i].tmpt); } fclose(FPIN); } /************************************************************************/ /*! \brief Writes out all the backbone atoms of a structure in pdb format This function takes a pdbf structure p and writes only the backbone atoms to a filename fname. \param p is the pdb structure to write out. \param fname is the file name to be written. */ /************************************************************************/ void gk_writebackbone(pdbf *p, char *fname) { int i; FILE *FPIN; FPIN = gk_fopen(fname,"w",fname); for(i=0; inbbs; i++) { fprintf(FPIN,"%-6s%5d %4s%1c%3s %1c%4d%1c %8.3lf%8.3lf%8.3lf%6.2f%6.2f\n", "ATOM ",p->bbs[i]->serial,p->bbs[i]->name,p->bbs[i]->altLoc,p->bbs[i]->resname,p->bbs[i]->chainid,p->bbs[i]->rserial,p->bbs[i]->icode,p->bbs[i]->x,p->bbs[i]->y,p->bbs[i]->z,p->bbs[i]->opcy,p->bbs[i]->tmpt); } fclose(FPIN); } /************************************************************************/ /*! \brief Writes out all the alpha carbon atoms of a structure This function takes a pdbf structure p and writes only the alpha carbon atoms to a filename fname. \param p is the pdb structure to write out. \param fname is the file name to be written. */ /************************************************************************/ void gk_writealphacarbons(pdbf *p, char *fname) { int i; FILE *FPIN; FPIN = gk_fopen(fname,"w",fname); for(i=0; incas; i++) { fprintf(FPIN,"%-6s%5d %4s%1c%3s %1c%4d%1c %8.3lf%8.3lf%8.3lf%6.2f%6.2f\n", "ATOM ",p->cas[i]->serial,p->cas[i]->name,p->cas[i]->altLoc,p->cas[i]->resname,p->cas[i]->chainid,p->cas[i]->rserial,p->cas[i]->icode,p->cas[i]->x,p->cas[i]->y,p->cas[i]->z,p->cas[i]->opcy,p->cas[i]->tmpt); } fclose(FPIN); } /************************************************************************/ /*! \brief Decodes the corruption bitswitch and prints any problems Due to the totally unreliable nature of the pdb format, reading a pdb file stores a corruption bitswitch, and this function decodes that switch and prints the result on stdout. \param p is the pdb structure to write out. \param fname is the file name to be written. */ /************************************************************************/ void gk_showcorruption(pdbf *p) { int corruption = p->corruption; if(corruption&CRP_ALTLOCS) printf("Multiple coordinate sets for at least one atom\n"); if(corruption&CRP_MISSINGCA) printf("Missing coordiantes for at least one CA atom\n"); if(corruption&CRP_MISSINGBB) printf("Missing coordiantes for at least one backbone atom (N,CA,C,O)\n"); if(corruption&CRP_MULTICHAIN) printf("File contains coordinates for multiple chains\n"); if(corruption&CRP_MULTICA) printf("Multiple CA atoms found for the same residue (could be alternate locators)\n"); if(corruption&CRP_MULTICA) printf("Multiple copies of backbone atoms found for the same residue (could be alternate locators)\n"); } /* sscanf(line, "%6s%5d%*1c%4s%1c%3s%*1c%1c%4d%1c%*3c%8lf%8lf%8lf%6lf%6lf%*6c%4s%2s%2s\n", linetype,&aserial,aname,&altLoc,rname,&chainid,&rserial,&icode,&x,&y,&z,&opcy,&tmpt,segId,element,charge); printf(".%s.%s.%s.\n",segId,element,charge); printf("%-6s%5d%-1s%-4s%1c%3s%1s%1c%4d%1c%3s%8.3lf%8.3lf%8.3lf%6.2f%6.2f%6s%4s%2s%2s\n", linetype,aserial," ",aname,altLoc,rname," ",chainid,rserial,icode," ",x,y,z,opcy,tmpt," ",segId,element,charge); */ /* and we could probably get away with this using astral files, */ /* sscanf(line, "%6s%5d%*1c%4s%1c%3s%*1c%1c%4d%1c%*3c%8lf%8lf%8lf%6lf%6lf%*6c%6s\n", linetype,&aserial,aname,&altLoc,rname,&chainid,&rserial,&icode,&x,&y,&z,&opcy,&tmpt,element); printf("%-6s%5d%-1s%-4s%1c%3s%1s%1c%4d%1c%3s%8.3lf%8.3lf%8.3lf%6.2f%6.2f%6s%6s\n", linetype,aserial," ",aname,altLoc,rname," ",chainid,rserial,icode," ",x,y,z,opcy,tmpt," ",element); */ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/evaluate.c�����������������������������������0000644�0001751�0000144�00000006704�14552244506�024307� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file evaluate.c \brief Various routines to evaluate classification performance \author George \date 9/23/2008 \version\verbatim $Id: evaluate.c 13328 2012-12-31 14:57:40Z karypis $ \endverbatim */ #include "GKlib.h" /********************************************************************** * This function computes the max accuracy score of a ranked list, * given +1/-1 class list **********************************************************************/ float ComputeAccuracy(int n, gk_fkv_t *list) { int i, P, N, TP, FN = 0; float bAccuracy = 0.0; float acc; for (P=0, i=0;i bAccuracy) bAccuracy = acc; } return bAccuracy; } /***************************************************************************** * This function computes the ROC score of a ranked list, given a +1/-1 class * list. ******************************************************************************/ float ComputeROCn(int n, int maxN, gk_fkv_t *list) { int i, P, TP, FP, TPprev, FPprev, AUC; float prev; FP = TP = FPprev = TPprev = AUC = 0; prev = list[0].key -1; for (P=0, i=0; i 0 ? (float)(1.0*AUC/(P*FP)) : 0.0); } /***************************************************************************** * This function computes the median rate of false positive for each positive * instance. ******************************************************************************/ float ComputeMedianRFP(int n, gk_fkv_t *list) { int i, P, N, TP, FP; P = N = 0; for (i=0; invtxs = -1; } /*************************************************************************/ /*! Frees all the memory allocated for a graph. \param graph is the graph to be freed. */ /*************************************************************************/ void gk_graph_Free(gk_graph_t **graph) { if (*graph == NULL) return; gk_graph_FreeContents(*graph); gk_free((void **)graph, LTERM); } /*************************************************************************/ /*! Frees only the memory allocated for the graph's different fields and sets them to NULL. \param graph is the graph whose contents will be freed. */ /*************************************************************************/ void gk_graph_FreeContents(gk_graph_t *graph) { gk_free((void *)&graph->xadj, &graph->adjncy, &graph->iadjwgt, &graph->fadjwgt, &graph->ivwgts, &graph->fvwgts, &graph->ivsizes, &graph->fvsizes, &graph->vlabels, LTERM); } /**************************************************************************/ /*! Reads a sparse graph from the supplied file \param filename is the file that stores the data. \param format is the graph format. The supported values are: GK_GRAPH_FMT_METIS. \param isfewgts is 1 if the edge-weights should be read as floats \param isfvwgts is 1 if the vertex-weights should be read as floats \param isfvsizes is 1 if the vertex-sizes should be read as floats \returns the graph that was read. */ /**************************************************************************/ gk_graph_t *gk_graph_Read(char *filename, int format, int isfewgts, int isfvwgts, int isfvsizes) { ssize_t i, k, l; size_t nfields, nvtxs, nedges, fmt, ncon, lnlen; int32_t ival; float fval; int readsizes=0, readwgts=0, readvals=0, numbering=0; char *line=NULL, *head, *tail, fmtstr[256]; FILE *fpin=NULL; gk_graph_t *graph=NULL; if (!gk_fexists(filename)) gk_errexit(SIGERR, "File %s does not exist!\n", filename); if (format == GK_GRAPH_FMT_METIS) { fpin = gk_fopen(filename, "r", "gk_graph_Read: fpin"); do { if (gk_getline(&line, &lnlen, fpin) <= 0) gk_errexit(SIGERR, "Premature end of input file: file:%s\n", filename); } while (line[0] == '%'); fmt = ncon = 0; nfields = sscanf(line, "%zu %zu %zu %zu", &nvtxs, &nedges, &fmt, &ncon); if (nfields < 2) gk_errexit(SIGERR, "Header line must contain at least 2 integers (#vtxs and #edges).\n"); nedges *= 2; if (fmt > 111) gk_errexit(SIGERR, "Cannot read this type of file format [fmt=%zu]!\n", fmt); sprintf(fmtstr, "%03zu", fmt%1000); readsizes = (fmtstr[0] == '1'); readwgts = (fmtstr[1] == '1'); readvals = (fmtstr[2] == '1'); numbering = 1; ncon = (ncon == 0 ? 1 : ncon); } else { gk_errexit(SIGERR, "Unrecognized format: %d\n", format); } graph = gk_graph_Create(); graph->nvtxs = nvtxs; graph->xadj = gk_zmalloc(nvtxs+1, "gk_graph_Read: xadj"); graph->adjncy = gk_i32malloc(nedges, "gk_graph_Read: adjncy"); if (readvals) { if (isfewgts) graph->fadjwgt = gk_fmalloc(nedges, "gk_graph_Read: fadjwgt"); else graph->iadjwgt = gk_i32malloc(nedges, "gk_graph_Read: iadjwgt"); } if (readsizes) { if (isfvsizes) graph->fvsizes = gk_fmalloc(nvtxs, "gk_graph_Read: fvsizes"); else graph->ivsizes = gk_i32malloc(nvtxs, "gk_graph_Read: ivsizes"); } if (readwgts) { if (isfvwgts) graph->fvwgts = gk_fmalloc(nvtxs*ncon, "gk_graph_Read: fvwgts"); else graph->ivwgts = gk_i32malloc(nvtxs*ncon, "gk_graph_Read: ivwgts"); } /*---------------------------------------------------------------------- * Read the sparse graph file *---------------------------------------------------------------------*/ numbering = (numbering ? - 1 : 0); for (graph->xadj[0]=0, k=0, i=0; ifvsizes[i] = (float)strtod(head, &tail); #else graph->fvsizes[i] = strtof(head, &tail); #endif if (tail == head) gk_errexit(SIGERR, "The line for vertex %zd does not have size information\n", i+1); if (graph->fvsizes[i] < 0) gk_errexit(SIGERR, "The size for vertex %zd must be >= 0\n", i+1); } else { graph->ivsizes[i] = strtol(head, &tail, 0); if (tail == head) gk_errexit(SIGERR, "The line for vertex %zd does not have size information\n", i+1); if (graph->ivsizes[i] < 0) gk_errexit(SIGERR, "The size for vertex %zd must be >= 0\n", i+1); } head = tail; } /* Read vertex weights */ if (readwgts) { for (l=0; lfvwgts[i*ncon+l] = (float)strtod(head, &tail); #else graph->fvwgts[i*ncon+l] = strtof(head, &tail); #endif if (tail == head) gk_errexit(SIGERR, "The line for vertex %zd does not have enough weights " "for the %d constraints.\n", i+1, ncon); if (graph->fvwgts[i*ncon+l] < 0) gk_errexit(SIGERR, "The weight vertex %zd and constraint %zd must be >= 0\n", i+1, l); } else { graph->ivwgts[i*ncon+l] = strtol(head, &tail, 0); if (tail == head) gk_errexit(SIGERR, "The line for vertex %zd does not have enough weights " "for the %d constraints.\n", i+1, ncon); if (graph->ivwgts[i*ncon+l] < 0) gk_errexit(SIGERR, "The weight vertex %zd and constraint %zd must be >= 0\n", i+1, l); } head = tail; } } /* Read the rest of the row */ while (1) { ival = (int)strtol(head, &tail, 0); if (tail == head) break; head = tail; if ((graph->adjncy[k] = ival + numbering) < 0) gk_errexit(SIGERR, "Error: Invalid column number %d at row %zd.\n", ival, i); if (readvals) { if (isfewgts) { #ifdef __MSC__ fval = (float)strtod(head, &tail); #else fval = strtof(head, &tail); #endif if (tail == head) gk_errexit(SIGERR, "Value could not be found for edge! Vertex:%zd, NNZ:%zd\n", i, k); graph->fadjwgt[k] = fval; } else { ival = strtol(head, &tail, 0); if (tail == head) gk_errexit(SIGERR, "Value could not be found for edge! Vertex:%zd, NNZ:%zd\n", i, k); graph->iadjwgt[k] = ival; } head = tail; } k++; } graph->xadj[i+1] = k; } if (k != nedges) gk_errexit(SIGERR, "gk_graph_Read: Something wrong with the number of edges in " "the input file. nedges=%zd, Actualnedges=%zd.\n", nedges, k); gk_fclose(fpin); gk_free((void **)&line, LTERM); return graph; } /**************************************************************************/ /*! Writes a graph into a file. \param graph is the graph to be written, \param filename is the name of the output file. \param format is one of GK_GRAPH_FMT_METIS specifying the format of the output file. */ /**************************************************************************/ void gk_graph_Write(gk_graph_t *graph, char *filename, int format) { ssize_t i, j; int hasvwgts, hasvsizes, hasewgts; FILE *fpout; if (format != GK_GRAPH_FMT_METIS) gk_errexit(SIGERR, "Unknown file format. %d\n", format); if (filename) fpout = gk_fopen(filename, "w", "gk_graph_Write: fpout"); else fpout = stdout; hasewgts = (graph->iadjwgt || graph->fadjwgt); hasvwgts = (graph->ivwgts || graph->fvwgts); hasvsizes = (graph->ivsizes || graph->fvsizes); /* write the header line */ fprintf(fpout, "%d %zd", graph->nvtxs, graph->xadj[graph->nvtxs]/2); if (hasvwgts || hasvsizes || hasewgts) fprintf(fpout, " %d%d%d", hasvsizes, hasvwgts, hasewgts); fprintf(fpout, "\n"); for (i=0; invtxs; i++) { if (hasvsizes) { if (graph->ivsizes) fprintf(fpout, " %d", graph->ivsizes[i]); else fprintf(fpout, " %f", graph->fvsizes[i]); } if (hasvwgts) { if (graph->ivwgts) fprintf(fpout, " %d", graph->ivwgts[i]); else fprintf(fpout, " %f", graph->fvwgts[i]); } for (j=graph->xadj[i]; jxadj[i+1]; j++) { fprintf(fpout, " %d", graph->adjncy[j]+1); if (hasewgts) { if (graph->iadjwgt) fprintf(fpout, " %d", graph->iadjwgt[j]); else fprintf(fpout, " %f", graph->fadjwgt[j]); } } fprintf(fpout, "\n"); } if (filename) gk_fclose(fpout); } /*************************************************************************/ /*! Returns a copy of a graph. \param graph is the graph to be duplicated. \returns the newly created copy of the graph. */ /**************************************************************************/ gk_graph_t *gk_graph_Dup(gk_graph_t *graph) { gk_graph_t *ngraph; ngraph = gk_graph_Create(); ngraph->nvtxs = graph->nvtxs; /* copy the adjacency structure */ if (graph->xadj) ngraph->xadj = gk_zcopy(graph->nvtxs+1, graph->xadj, gk_zmalloc(graph->nvtxs+1, "gk_graph_Dup: xadj")); if (graph->ivwgts) ngraph->ivwgts = gk_i32copy(graph->nvtxs, graph->ivwgts, gk_i32malloc(graph->nvtxs, "gk_graph_Dup: ivwgts")); if (graph->ivsizes) ngraph->ivsizes = gk_i32copy(graph->nvtxs, graph->ivsizes, gk_i32malloc(graph->nvtxs, "gk_graph_Dup: ivsizes")); if (graph->vlabels) ngraph->vlabels = gk_i32copy(graph->nvtxs, graph->vlabels, gk_i32malloc(graph->nvtxs, "gk_graph_Dup: ivlabels")); if (graph->fvwgts) ngraph->fvwgts = gk_fcopy(graph->nvtxs, graph->fvwgts, gk_fmalloc(graph->nvtxs, "gk_graph_Dup: fvwgts")); if (graph->fvsizes) ngraph->fvsizes = gk_fcopy(graph->nvtxs, graph->fvsizes, gk_fmalloc(graph->nvtxs, "gk_graph_Dup: fvsizes")); if (graph->adjncy) ngraph->adjncy = gk_i32copy(graph->xadj[graph->nvtxs], graph->adjncy, gk_i32malloc(graph->xadj[graph->nvtxs], "gk_graph_Dup: adjncy")); if (graph->iadjwgt) ngraph->iadjwgt = gk_i32copy(graph->xadj[graph->nvtxs], graph->iadjwgt, gk_i32malloc(graph->xadj[graph->nvtxs], "gk_graph_Dup: iadjwgt")); if (graph->fadjwgt) ngraph->fadjwgt = gk_fcopy(graph->xadj[graph->nvtxs], graph->fadjwgt, gk_fmalloc(graph->xadj[graph->nvtxs], "gk_graph_Dup: fadjwgt")); return ngraph; } /*************************************************************************/ /*! Returns a subgraph containing a set of consecutive vertices. \param graph is the original graph. \param vstart is the starting vertex. \param nvtxs is the number of vertices from vstart to extract. \returns the newly created subgraph. */ /**************************************************************************/ gk_graph_t *gk_graph_ExtractSubgraph(gk_graph_t *graph, int vstart, int nvtxs) { ssize_t i; gk_graph_t *ngraph; if (vstart+nvtxs > graph->nvtxs) return NULL; ngraph = gk_graph_Create(); ngraph->nvtxs = nvtxs; /* copy the adjancy structure */ if (graph->xadj) ngraph->xadj = gk_zcopy(nvtxs+1, graph->xadj+vstart, gk_zmalloc(nvtxs+1, "gk_graph_ExtractSubgraph: xadj")); for (i=nvtxs; i>=0; i--) ngraph->xadj[i] -= ngraph->xadj[0]; ASSERT(ngraph->xadj[0] == 0); if (graph->ivwgts) ngraph->ivwgts = gk_i32copy(nvtxs, graph->ivwgts+vstart, gk_i32malloc(nvtxs, "gk_graph_ExtractSubgraph: ivwgts")); if (graph->ivsizes) ngraph->ivsizes = gk_i32copy(nvtxs, graph->ivsizes+vstart, gk_i32malloc(nvtxs, "gk_graph_ExtractSubgraph: ivsizes")); if (graph->vlabels) ngraph->vlabels = gk_i32copy(nvtxs, graph->vlabels+vstart, gk_i32malloc(nvtxs, "gk_graph_ExtractSubgraph: vlabels")); if (graph->fvwgts) ngraph->fvwgts = gk_fcopy(nvtxs, graph->fvwgts+vstart, gk_fmalloc(nvtxs, "gk_graph_ExtractSubgraph: fvwgts")); if (graph->fvsizes) ngraph->fvsizes = gk_fcopy(nvtxs, graph->fvsizes+vstart, gk_fmalloc(nvtxs, "gk_graph_ExtractSubgraph: fvsizes")); ASSERT(ngraph->xadj[nvtxs] == graph->xadj[vstart+nvtxs]-graph->xadj[vstart]); if (graph->adjncy) ngraph->adjncy = gk_i32copy(graph->xadj[vstart+nvtxs]-graph->xadj[vstart], graph->adjncy+graph->xadj[vstart], gk_i32malloc(graph->xadj[vstart+nvtxs]-graph->xadj[vstart], "gk_graph_ExtractSubgraph: adjncy")); if (graph->iadjwgt) ngraph->iadjwgt = gk_i32copy(graph->xadj[vstart+nvtxs]-graph->xadj[vstart], graph->iadjwgt+graph->xadj[vstart], gk_i32malloc(graph->xadj[vstart+nvtxs]-graph->xadj[vstart], "gk_graph_ExtractSubgraph: iadjwgt")); if (graph->fadjwgt) ngraph->fadjwgt = gk_fcopy(graph->xadj[vstart+nvtxs]-graph->xadj[vstart], graph->fadjwgt+graph->xadj[vstart], gk_fmalloc(graph->xadj[vstart+nvtxs]-graph->xadj[vstart], "gk_graph_ExtractSubgraph: fadjwgt")); return ngraph; } /*************************************************************************/ /*! Returns a graph that has been reordered according to the permutation. \param[IN] graph is the graph to be re-ordered. \param[IN] perm is the new ordering of the graph's vertices \param[IN] iperm is the original ordering of the re-ordered graph's vertices \returns the newly created copy of the graph. \note Either perm or iperm can be NULL but not both. */ /**************************************************************************/ gk_graph_t *gk_graph_Reorder(gk_graph_t *graph, int32_t *perm, int32_t *iperm) { ssize_t j, jj, *xadj; int i, k, u, v, nvtxs; int freeperm=0, freeiperm=0; int32_t *adjncy; gk_graph_t *ngraph; if (perm == NULL && iperm == NULL) return NULL; ngraph = gk_graph_Create(); ngraph->nvtxs = nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; /* allocate memory for the different structures that are present in graph */ if (graph->xadj) ngraph->xadj = gk_zmalloc(nvtxs+1, "gk_graph_Reorder: xadj"); if (graph->ivwgts) ngraph->ivwgts = gk_i32malloc(nvtxs, "gk_graph_Reorder: ivwgts"); if (graph->ivsizes) ngraph->ivsizes = gk_i32malloc(nvtxs, "gk_graph_Reorder: ivsizes"); if (graph->vlabels) ngraph->vlabels = gk_i32malloc(nvtxs, "gk_graph_Reorder: ivlabels"); if (graph->fvwgts) ngraph->fvwgts = gk_fmalloc(nvtxs, "gk_graph_Reorder: fvwgts"); if (graph->fvsizes) ngraph->fvsizes = gk_fmalloc(nvtxs, "gk_graph_Reorder: fvsizes"); if (graph->adjncy) ngraph->adjncy = gk_i32malloc(graph->xadj[nvtxs], "gk_graph_Reorder: adjncy"); if (graph->iadjwgt) ngraph->iadjwgt = gk_i32malloc(graph->xadj[nvtxs], "gk_graph_Reorder: iadjwgt"); if (graph->fadjwgt) ngraph->fadjwgt = gk_fmalloc(graph->xadj[nvtxs], "gk_graph_Reorder: fadjwgt"); /* create perm/iperm if not provided */ if (perm == NULL) { freeperm = 1; perm = gk_i32malloc(nvtxs, "gk_graph_Reorder: perm"); for (i=0; ixadj[0] = jj = 0; for (v=0; vadjncy[jj] = perm[adjncy[j]]; if (graph->iadjwgt) ngraph->iadjwgt[jj] = graph->iadjwgt[j]; if (graph->fadjwgt) ngraph->fadjwgt[jj] = graph->fadjwgt[j]; } if (graph->ivwgts) ngraph->ivwgts[v] = graph->ivwgts[u]; if (graph->fvwgts) ngraph->fvwgts[v] = graph->fvwgts[u]; if (graph->ivsizes) ngraph->ivsizes[v] = graph->ivsizes[u]; if (graph->fvsizes) ngraph->fvsizes[v] = graph->fvsizes[u]; if (graph->vlabels) ngraph->vlabels[v] = graph->vlabels[u]; ngraph->xadj[v+1] = jj; } /* free memory */ if (freeperm) gk_free((void **)&perm, LTERM); if (freeiperm) gk_free((void **)&iperm, LTERM); return ngraph; } /*************************************************************************/ /*! This function finds the connected components in a graph. \param graph is the graph structure \param cptr is the ptr structure of the CSR representation of the components. The length of this vector must be graph->nvtxs+1. \param cind is the indices structure of the CSR representation of the components. The length of this vector must be graph->nvtxs. \returns the number of components that it found. \note The cptr and cind parameters can be NULL, in which case only the number of connected components is returned. */ /*************************************************************************/ int gk_graph_FindComponents(gk_graph_t *graph, int32_t *cptr, int32_t *cind) { ssize_t i, ii, j, jj, k, nvtxs, first, last, ntodo, ncmps; ssize_t *xadj; int32_t *adjncy, *pos, *todo; int32_t mustfree_ccsr=0, mustfree_where=0; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; /* Deal with NULL supplied cptr/cind vectors */ if (cptr == NULL) { cptr = gk_i32malloc(nvtxs+1, "gk_graph_FindComponents: cptr"); cind = gk_i32malloc(nvtxs, "gk_graph_FindComponents: cind"); mustfree_ccsr = 1; } /* The list of vertices that have not been touched yet. The valid entries are from [0..ntodo). */ todo = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_FindComponents: todo")); /* For a vertex that has not been visited, pos[i] is the position in the todo list that this vertex is stored. If a vertex has been visited, pos[i] = -1. */ pos = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_FindComponents: pos")); /* Find the connected componends */ ncmps = -1; ntodo = nvtxs; /* All vertices have not been visited */ first = last = 0; /* Point to the first and last vertices that have been touched but not explored. These vertices are stored in cind[first]...cind[last-1]. */ while (ntodo > 0) { if (first == last) { /* Find another starting vertex */ cptr[++ncmps] = first; /* Mark the end of the current CC */ ASSERT(pos[todo[0]] != -1); i = todo[0]; cind[last++] = i; pos[i] = -1; } i = cind[first++]; /* Get the first visited but unexplored vertex */ /* Remove i from the todo list and put the last item in the todo list at the position that i was so that the todo list will be consequtive. The pos[] array is updated accordingly to keep track the location of the vertices in the todo[] list. */ k = pos[i]; j = todo[k] = todo[--ntodo]; pos[j] = k; for (j=xadj[i]; jnvtxs <= 0) return; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; /* This array will function like pos + touched of the CC method */ pos = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_ComputeBFSOrdering: pos")); /* This array ([C]losed[O]pen[T]odo => cot) serves three purposes. Positions from [0...first) is the current iperm[] vector of the explored vertices; Positions from [first...last) is the OPEN list (i.e., visited vertices); Positions from [last...nvtxs) is the todo list. */ cot = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_ComputeBFSOrdering: cot")); /* put v at the front of the todo list */ pos[0] = cot[0] = v; pos[v] = cot[v] = 0; /* Find the connected componends induced by the partition */ first = last = 0; while (first < nvtxs) { if (first == last) { /* Find another starting vertex */ k = cot[last]; ASSERT(pos[k] != -1); pos[k] = -1; /* mark node as being visited */ last++; } i = cot[first++]; /* the ++ advances the explored vertices */ for (j=xadj[i]; jnvtxs <= 0) return; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; /* the degree of the vertices in the closed list */ degrees = gk_i32smalloc(nvtxs, 0, "gk_graph_ComputeBestFOrdering: degrees"); /* the minimum vertex ID of an open vertex to the closed list */ minIDs = gk_i32smalloc(nvtxs, nvtxs+1, "gk_graph_ComputeBestFOrdering: minIDs"); /* the open list */ open = gk_i32malloc(nvtxs, "gk_graph_ComputeBestFOrdering: open"); /* if perm[i] >= 0, then perm[i] is the order of vertex i; otherwise perm[i] == -1. */ perm = gk_i32smalloc(nvtxs, -1, "gk_graph_ComputeBestFOrdering: perm"); /* create the queue and put everything in it */ queue = gk_i32pqCreate(nvtxs); for (i=0; invtxs <= 0) return; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; /* the degree of the vertices in the closed list */ degrees = gk_i32smalloc(nvtxs, 0, "gk_graph_ComputeBestFOrdering: degrees"); /* the weighted degree of the vertices in the closed list for type==3 */ wdegrees = gk_i32smalloc(nvtxs, 0, "gk_graph_ComputeBestFOrdering: wdegrees"); /* the sum of differences for type==4 */ sod = gk_i32smalloc(nvtxs, 0, "gk_graph_ComputeBestFOrdering: sod"); /* the encountering level of a vertex type==5 */ level = gk_i32smalloc(nvtxs, 0, "gk_graph_ComputeBestFOrdering: level"); /* The open+todo list of vertices. The vertices from [0..nopen] are the open vertices. The vertices from [nopen..ntodo) are the todo vertices. */ ot = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_FindComponents: ot")); /* For a vertex that has not been explored, pos[i] is the position in the ot list. */ pos = gk_i32incset(nvtxs, 0, gk_i32malloc(nvtxs, "gk_graph_FindComponents: pos")); /* if perm[i] >= 0, then perm[i] is the order of vertex i; otherwise perm[i] == -1. */ perm = gk_i32smalloc(nvtxs, -1, "gk_graph_ComputeBestFOrdering: perm"); /* create the queue and put the starting vertex in it */ queue = gk_i32pqCreate(nvtxs); gk_i32pqInsert(queue, v, 1); /* put v at the front of the open list */ pos[0] = ot[0] = v; pos[v] = ot[v] = 0; nopen = 1; ntodo = nvtxs; /* start processing the nodes */ for (i=0; i= nopen) gk_errexit(SIGERR, "The position of v is not in open list. pos[%d]=%d is >=%d.\n", v, pos[v], nopen); /* remove v from the open list and re-arrange the todo part of the list */ ot[pos[v]] = ot[nopen-1]; pos[ot[nopen-1]] = pos[v]; if (ntodo > nopen) { ot[nopen-1] = ot[ntodo-1]; pos[ot[ntodo-1]] = nopen-1; } nopen--; ntodo--; for (j=xadj[v]; jnvtxs <= 0) return; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; inqueue = gk_i32smalloc(nvtxs, 0, "gk_graph_SingleSourceShortestPaths: inqueue"); /* determine if you will be computing using int32_t or float and proceed from there */ if (graph->iadjwgt != NULL) { gk_i32pq_t *queue; int32_t *adjwgt; int32_t *sps; adjwgt = graph->iadjwgt; queue = gk_i32pqCreate(nvtxs); gk_i32pqInsert(queue, v, 0); inqueue[v] = 1; sps = gk_i32smalloc(nvtxs, -1, "gk_graph_SingleSourceShortestPaths: sps"); sps[v] = 0; /* start processing the nodes */ while ((v = gk_i32pqGetTop(queue)) != -1) { inqueue[v] = 2; /* relax the adjacent edges */ for (i=xadj[v]; ifadjwgt; queue = gk_fpqCreate(nvtxs); gk_fpqInsert(queue, v, 0); inqueue[v] = 1; sps = gk_fsmalloc(nvtxs, -1, "gk_graph_SingleSourceShortestPaths: sps"); sps[v] = 0; /* start processing the nodes */ while ((v = gk_fpqGetTop(queue)) != -1) { inqueue[v] = 2; /* relax the adjacent edges */ for (i=xadj[v]; irowptr) gk_errexit(SIGERR, "Row-based view of the graphrix does not exists.\n"); n = graph->nrows; ptr = graph->rowptr; ind = graph->rowind; val = graph->rowval; break; case GK_CSR_COL: if (!graph->colptr) gk_errexit(SIGERR, "Column-based view of the graphrix does not exists.\n"); n = graph->ncols; ptr = graph->colptr; ind = graph->colind; val = graph->colval; break; default: gk_errexit(SIGERR, "Invalid index type of %d.\n", what); return; } #pragma omp parallel if (n > 100) { ssize_t i, j, k; gk_ikv_t *cand; float *tval; #pragma omp single for (i=0; i ptr[i] && ind[j] < ind[j-1]) k = 1; /* an inversion */ cand[j-ptr[i]].val = j-ptr[i]; cand[j-ptr[i]].key = ind[j]; tval[j-ptr[i]] = val[j]; } if (k) { gk_ikvsorti(ptr[i+1]-ptr[i], cand); for (j=ptr[i]; jnrows = nrows; ngraph->ncols = graph->ncols; for (nnz=0, i=0; irowptr[rind[i]+1]-graph->rowptr[rind[i]]; ngraph->rowptr = gk_zmalloc(ngraph->nrows+1, "gk_graph_ExtractPartition: rowptr"); ngraph->rowind = gk_imalloc(nnz, "gk_graph_ExtractPartition: rowind"); ngraph->rowval = gk_fmalloc(nnz, "gk_graph_ExtractPartition: rowval"); ngraph->rowptr[0] = 0; for (nnz=0, j=0, ii=0; iirowptr[i+1]-graph->rowptr[i], graph->rowind+graph->rowptr[i], ngraph->rowind+nnz); gk_fcopy(graph->rowptr[i+1]-graph->rowptr[i], graph->rowval+graph->rowptr[i], ngraph->rowval+nnz); nnz += graph->rowptr[i+1]-graph->rowptr[i]; ngraph->rowptr[++j] = nnz; } ASSERT(j == ngraph->nrows); return ngraph; } /*************************************************************************/ /*! Returns a subgraphrix corresponding to a specified partitioning of rows. \param graph is the original graphrix. \param part is the partitioning vector of the rows. \param pid is the partition ID that will be extracted. \returns the row structure of the newly created subgraphrix. */ /**************************************************************************/ gk_graph_t *gk_graph_ExtractPartition(gk_graph_t *graph, int *part, int pid) { ssize_t i, j, nnz; gk_graph_t *ngraph; ngraph = gk_graph_Create(); ngraph->nrows = 0; ngraph->ncols = graph->ncols; for (nnz=0, i=0; inrows; i++) { if (part[i] == pid) { ngraph->nrows++; nnz += graph->rowptr[i+1]-graph->rowptr[i]; } } ngraph->rowptr = gk_zmalloc(ngraph->nrows+1, "gk_graph_ExtractPartition: rowptr"); ngraph->rowind = gk_imalloc(nnz, "gk_graph_ExtractPartition: rowind"); ngraph->rowval = gk_fmalloc(nnz, "gk_graph_ExtractPartition: rowval"); ngraph->rowptr[0] = 0; for (nnz=0, j=0, i=0; inrows; i++) { if (part[i] == pid) { gk_icopy(graph->rowptr[i+1]-graph->rowptr[i], graph->rowind+graph->rowptr[i], ngraph->rowind+nnz); gk_fcopy(graph->rowptr[i+1]-graph->rowptr[i], graph->rowval+graph->rowptr[i], ngraph->rowval+nnz); nnz += graph->rowptr[i+1]-graph->rowptr[i]; ngraph->rowptr[++j] = nnz; } } ASSERT(j == ngraph->nrows); return ngraph; } /*************************************************************************/ /*! Splits the graphrix into multiple sub-graphrices based on the provided color array. \param graph is the original graphrix. \param color is an array of size equal to the number of non-zeros in the graphrix (row-wise structure). The graphrix is split into as many parts as the number of colors. For meaningfull results, the colors should be numbered consecutively starting from 0. \returns an array of graphrices for each supplied color number. */ /**************************************************************************/ gk_graph_t **gk_graph_Split(gk_graph_t *graph, int *color) { ssize_t i, j; int nrows, ncolors; ssize_t *rowptr; int *rowind; float *rowval; gk_graph_t **sgraphs; nrows = graph->nrows; rowptr = graph->rowptr; rowind = graph->rowind; rowval = graph->rowval; ncolors = gk_imax(rowptr[nrows], color)+1; sgraphs = (gk_graph_t **)gk_malloc(sizeof(gk_graph_t *)*ncolors, "gk_graph_Split: sgraphs"); for (i=0; inrows = graph->nrows; sgraphs[i]->ncols = graph->ncols; sgraphs[i]->rowptr = gk_zsmalloc(nrows+1, 0, "gk_graph_Split: sgraphs[i]->rowptr"); } for (i=0; irowptr[i]++; } for (i=0; irowptr); for (i=0; irowind = gk_imalloc(sgraphs[i]->rowptr[nrows], "gk_graph_Split: sgraphs[i]->rowind"); sgraphs[i]->rowval = gk_fmalloc(sgraphs[i]->rowptr[nrows], "gk_graph_Split: sgraphs[i]->rowval"); } for (i=0; irowind[sgraphs[color[j]]->rowptr[i]] = rowind[j]; sgraphs[color[j]]->rowval[sgraphs[color[j]]->rowptr[i]] = rowval[j]; sgraphs[color[j]]->rowptr[i]++; } } for (i=0; irowptr); return sgraphs; } /*************************************************************************/ /*! Prunes certain rows/columns of the graphrix. The prunning takes place by analyzing the row structure of the graphrix. The prunning takes place by removing rows/columns but it does not affect the numbering of the remaining rows/columns. \param graph the graphrix to be prunned, \param what indicates if the rows (GK_CSR_ROW) or the columns (GK_CSR_COL) of the graphrix will be prunned, \param minf is the minimum number of rows (columns) that a column (row) must be present in order to be kept, \param maxf is the maximum number of rows (columns) that a column (row) must be present at in order to be kept. \returns the prunned graphrix consisting only of its row-based structure. The input graphrix is not modified. */ /**************************************************************************/ gk_graph_t *gk_graph_Prune(gk_graph_t *graph, int what, int minf, int maxf) { ssize_t i, j, nnz; int nrows, ncols; ssize_t *rowptr, *nrowptr; int *rowind, *nrowind, *collen; float *rowval, *nrowval; gk_graph_t *ngraph; ngraph = gk_graph_Create(); nrows = ngraph->nrows = graph->nrows; ncols = ngraph->ncols = graph->ncols; rowptr = graph->rowptr; rowind = graph->rowind; rowval = graph->rowval; nrowptr = ngraph->rowptr = gk_zmalloc(nrows+1, "gk_graph_Prune: nrowptr"); nrowind = ngraph->rowind = gk_imalloc(rowptr[nrows], "gk_graph_Prune: nrowind"); nrowval = ngraph->rowval = gk_fmalloc(rowptr[nrows], "gk_graph_Prune: nrowval"); switch (what) { case GK_CSR_COL: collen = gk_ismalloc(ncols, 0, "gk_graph_Prune: collen"); for (i=0; i= minf && collen[i] <= maxf ? 1 : 0); nrowptr[0] = 0; for (nnz=0, i=0; i= minf && rowptr[i+1]-rowptr[i] <= maxf) { for (j=rowptr[i]; jrowval) { n = graph->nrows; ptr = graph->rowptr; val = graph->rowval; #pragma omp parallel if (ptr[n] > OMPMINOPS) { #pragma omp for private(j,sum) schedule(static) for (i=0; i 0 */ } if (sum > 0) { if (norm == 2) sum=1.0/sqrt(sum); else if (norm == 1) sum=1.0/sum; for (j=ptr[i]; jcolval) { n = graph->ncols; ptr = graph->colptr; val = graph->colval; #pragma omp parallel if (ptr[n] > OMPMINOPS) { #pragma omp for private(j,sum) schedule(static) for (i=0; i 0) { if (norm == 2) sum=1.0/sqrt(sum); else if (norm == 1) sum=1.0/sum; for (j=ptr[i]; j middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (gk_optind - last_nonopt); last_nonopt = gk_optind; } /*************************************************************************/ /* Initialize the internal data when the first call is made. */ /*************************************************************************/ static char *gk_getopt_initialize (int argc, char **argv, char *optstring) { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = gk_optind; nextchar = NULL; posixly_correct = getenv("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; return optstring; } /*************************************************************************/ /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `gk_optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns -1. Then `gk_optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `gk_opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `gk_optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `gk_optarg', otherwise `gk_optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. LONGOPTS is a vector of `struct gk_option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ /*************************************************************************/ static int gk_getopt_internal(int argc, char **argv, char *optstring, struct gk_option *longopts, int *longind, int long_only) { int print_errors = gk_opterr; if (optstring[0] == ':') print_errors = 0; if (argc < 1) return -1; gk_optarg = NULL; if (gk_optind == 0 || !gk_getopt_initialized) { if (gk_optind == 0) gk_optind = 1; /* Don't scan ARGV[0], the program name. */ optstring = gk_getopt_initialize (argc, argv, optstring); gk_getopt_initialized = 1; } /* Test whether ARGV[gk_optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ # define NONOPTION_P (argv[gk_optind][0] != '-' || argv[gk_optind][1] == '\0') if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ if (last_nonopt > gk_optind) last_nonopt = gk_optind; if (first_nonopt > gk_optind) first_nonopt = gk_optind; if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != gk_optind) exchange ((char **) argv); else if (last_nonopt != gk_optind) first_nonopt = gk_optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (gk_optind < argc && NONOPTION_P) gk_optind++; last_nonopt = gk_optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (gk_optind != argc && !strcmp (argv[gk_optind], "--")) { gk_optind++; if (first_nonopt != last_nonopt && last_nonopt != gk_optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = gk_optind; last_nonopt = argc; gk_optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (gk_optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) gk_optind = first_nonopt; return -1; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) { if (ordering == REQUIRE_ORDER) return -1; gk_optarg = argv[gk_optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[gk_optind] + 1 + (longopts != NULL && argv[gk_optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[gk_optind][1] == '-' || (long_only && (argv[gk_optind][2] || !strchr(optstring, argv[gk_optind][1]))))) { char *nameend; struct gk_option *p; struct gk_option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = -1; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) { if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) /* Second or later nonexact match found. */ ambig = 1; } } if (ambig && !exact) { if (print_errors) fprintf(stderr, "%s: option `%s' is ambiguous\n", argv[0], argv[gk_optind]); nextchar += strlen (nextchar); gk_optind++; gk_optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; gk_optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) gk_optarg = nameend + 1; else { if (print_errors) { if (argv[gk_optind - 1][1] == '-') /* --option */ fprintf(stderr, "%s: option `--%s' doesn't allow an argument\n", argv[0], pfound->name); else /* +option or -option */ fprintf(stderr, "%s: option `%c%s' doesn't allow an argument\n", argv[0], argv[gk_optind - 1][0], pfound->name); } nextchar += strlen (nextchar); gk_optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { if (gk_optind < argc) gk_optarg = argv[gk_optind++]; else { if (print_errors) fprintf(stderr, "%s: option `%s' requires an argument\n", argv[0], argv[gk_optind - 1]); nextchar += strlen (nextchar); gk_optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[gk_optind][1] == '-' || strchr(optstring, *nextchar) == NULL) { if (print_errors) { if (argv[gk_optind][1] == '-') /* --option */ fprintf(stderr, "%s: unrecognized option `--%s'\n", argv[0], nextchar); else /* +option or -option */ fprintf(stderr, "%s: unrecognized option `%c%s'\n", argv[0], argv[gk_optind][0], nextchar); } nextchar = (char *) ""; gk_optind++; gk_optopt = 0; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = strchr(optstring, c); /* Increment `gk_optind' when we start to process its last character. */ if (*nextchar == '\0') ++gk_optind; if (temp == NULL || c == ':') { if (print_errors) { if (posixly_correct) /* 1003.2 specifies the format of this message. */ fprintf(stderr, "%s: illegal option -- %c\n", argv[0], c); else fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c); } gk_optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { char *nameend; struct gk_option *p; struct gk_option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; /* This is an option that requires an argument. */ if (*nextchar != '\0') { gk_optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ gk_optind++; } else if (gk_optind == argc) { if (print_errors) { /* 1003.2 specifies the format of this message. */ fprintf(stderr, "%s: option requires an argument -- %c\n", argv[0], c); } gk_optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; return c; } else /* We already incremented `gk_optind' once; increment it again when taking next ARGV-elt as argument. */ gk_optarg = argv[gk_optind++]; /* gk_optarg is now the argument, see if it's in the table of longopts. */ for (nextchar = nameend = gk_optarg; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) { if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } } if (ambig && !exact) { if (print_errors) fprintf(stderr, "%s: option `-W %s' is ambiguous\n", argv[0], argv[gk_optind]); nextchar += strlen (nextchar); gk_optind++; return '?'; } if (pfound != NULL) { option_index = indfound; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) gk_optarg = nameend + 1; else { if (print_errors) fprintf(stderr, "%s: option `-W %s' doesn't allow an argument\n", argv[0], pfound->name); nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (gk_optind < argc) gk_optarg = argv[gk_optind++]; else { if (print_errors) fprintf(stderr, "%s: option `%s' requires an argument\n", argv[0], argv[gk_optind - 1]); nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { gk_optarg = nextchar; gk_optind++; } else gk_optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { gk_optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ gk_optind++; } else if (gk_optind == argc) { if (print_errors) { /* 1003.2 specifies the format of this message. */ fprintf(stderr, "%s: option requires an argument -- %c\n", argv[0], c); } gk_optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `gk_optind' once; increment it again when taking next ARGV-elt as argument. */ gk_optarg = argv[gk_optind++]; nextchar = NULL; } } return c; } } /*************************************************************************/ /*! \brief Parse command-line arguments The gk_getopt() function gets the next option argument from the argument list specified by the \c argv and \c argc arguments. Normally these values come directly from the arguments received by main(). \param argc is the number of command line arguments passed to main(). \param argv is an array of strings storing the above command line arguments. \param options is a string that specifies the option characters that are valid for this program. An option character in this string can be followed by a colon (`:') to indicate that it takes a required argument. If an option character is followed by two colons (`::'), its argument is optional; this is a GNU extension. \return It returns the option character for the next command line option. When no more option arguments are available, it returns -1. There may still be more non-option arguments; you must compare the external variable #gk_optind against the \c argc parameter to check this. \return If the option has an argument, gk_getopt() returns the argument by storing it in the variable #gk_optarg. You don't ordinarily need to copy the #gk_optarg string, since it is a pointer into the original \c argv array, not into a static area that might be overwritten. \return If gk_getopt() finds an option character in \c argv that was not included in options, or a missing option argument, it returns `?' and sets the external variable #gk_optopt to the actual option character. If the first character of options is a colon (`:'), then gk_getopt() returns `:' instead of `?' to indicate a missing option argument. In addition, if the external variable #gk_opterr is nonzero (which is the default), gk_getopt() prints an error message. This variable is set by gk_getopt() to point at the value of the option argument, for those options that accept arguments. gk_getopt() has three ways to deal with options that follow non-options \c argv elements. The special argument `--' forces in all cases the end of option scanning. - The default is to permute the contents of \c argv while scanning it so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. - If the options argument string begins with a hyphen (`-'), this is treated specially. It permits arguments that are not options to be returned as if they were associated with option character `\\1'. - POSIX demands the following behavior: The first non-option stops option processing. This mode is selected by either setting the environment variable POSIXLY_CORRECT or beginning the options argument string with a plus sign (`+'). */ /*************************************************************************/ int gk_getopt(int argc, char **argv, char *options) { return gk_getopt_internal(argc, argv, options, NULL, NULL, 0); } /*************************************************************************/ /*! \brief Parse command-line arguments with long options This function accepts GNU-style long options as well as single-character options. \param argc is the number of command line arguments passed to main(). \param argv is an array of strings storing the above command line arguments. \param options describes the short options to accept, just as it does in gk_getopt(). \param long_options describes the long options to accept. See the defintion of ::gk_option for more information. \param opt_index this is a returned variable. For any long option, gk_getopt_long() tells you the index in the array \c long_options of the options definition, by storing it into *opt_index. You can get the name of the option with longopts[*opt_index].name. So you can distinguish among long options either by the values in their val fields or by their indices. You can also distinguish in this way among long options that set flags. \return When gk_getopt_long() encounters a short option, it does the same thing that gk_getopt() would do: it returns the character code for the option, and stores the options argument (if it has one) in #gk_optarg. \return When gk_getopt_long() encounters a long option, it takes actions based on the flag and val fields of the definition of that option. \return If flag is a null pointer, then gk_getopt_long() returns the contents of val to indicate which option it found. You should arrange distinct values in the val field for options with different meanings, so you can decode these values after gk_getopt_long() returns. If the long option is equivalent to a short option, you can use the short option's character code in val. \return If flag is not a null pointer, that means this option should just set a flag in the program. The flag is a variable of type int that you define. Put the address of the flag in the flag field. Put in the val field the value you would like this option to store in the flag. In this case, gk_getopt_long() returns 0. \return When a long option has an argument, gk_getopt_long() puts the argument value in the variable #gk_optarg before returning. When the option has no argument, the value in #gk_optarg is a null pointer. This is how you can tell whether an optional argument was supplied. \return When gk_getopt_long() has no more options to handle, it returns -1, and leaves in the variable #gk_optind the index in argv of the next remaining argument. */ /*************************************************************************/ int gk_getopt_long( int argc, char **argv, char *options, struct gk_option *long_options, int *opt_index) { return gk_getopt_internal (argc, argv, options, long_options, opt_index, 0); } /*************************************************************************/ /*! \brief Parse command-line arguments with only long options Like gk_getopt_long(), but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option instead. */ /*************************************************************************/ int gk_getopt_long_only(int argc, char **argv, char *options, struct gk_option *long_options, int *opt_index) { return gk_getopt_internal(argc, argv, options, long_options, opt_index, 1); } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_mkblas.h0000644000175100001440000001353114552244506024434 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file gk_mkblas.h \brief Templates for BLAS-like routines \date Started 3/28/07 \author George \version\verbatim $Id: gk_mkblas.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim */ #ifndef _GK_MKBLAS_H_ #define _GK_MKBLAS_H_ #define GK_MKBLAS(PRFX, TYPE, OUTTYPE) \ /*************************************************************************/\ /*! The macro for gk_?incset()-class of routines */\ /*************************************************************************/\ TYPE *PRFX ## incset(size_t n, TYPE baseval, TYPE *x)\ {\ size_t i;\ \ for (i=0; i x[max] ? i : max);\ \ return x[max];\ }\ \ \ /*************************************************************************/\ /*! The macro for gk_?min()-class of routines */\ /*************************************************************************/\ TYPE PRFX ## min(size_t n, TYPE *x)\ {\ size_t i, min=0;\ \ if (n <= 0) return (TYPE) 0;\ \ for (i=1; i x[max] ? i : max);\ \ return max;\ }\ \ \ /*************************************************************************/\ /*! The macro for gk_?argmin()-class of routines */\ /*************************************************************************/\ size_t PRFX ## argmin(size_t n, TYPE *x)\ {\ size_t i, min=0;\ \ for (i=1; i 0 ? (OUTTYPE)sqrt((double)partial) : (OUTTYPE)0);\ }\ \ \ /*************************************************************************/\ /*! The macro for gk_?dot()-class of routines */\ /**************************************************************************/\ OUTTYPE PRFX ## dot(size_t n, TYPE *x, size_t incx, TYPE *y, size_t incy)\ {\ size_t i;\ OUTTYPE partial = 0.0;\ \ for (i=0; igk_seq_t variable \param A pointer to gk_seq_t itself \returns null */ /***********************************************************************/ void gk_seq_init(gk_seq_t *seq) { seq->len = 0; seq->sequence = NULL; seq->pssm = NULL; seq->psfm = NULL; seq->name = NULL; } /***********************************************************************/ /*! \brief This function creates the localizations for the various sequences \param string i.e amino acids, nucleotides, sequences \returns gk_i2cc2i_t variable */ /*********************************************************************/ gk_i2cc2i_t *gk_i2cc2i_create_common(char *alphabet) { int nsymbols; gk_idx_t i; gk_i2cc2i_t *t; nsymbols = strlen(alphabet); t = gk_malloc(sizeof(gk_i2cc2i_t),"gk_i2c_create_common"); t->n = nsymbols; t->i2c = gk_cmalloc(256, "gk_i2c_create_common"); t->c2i = gk_imalloc(256, "gk_i2c_create_common"); gk_cset(256, -1, t->i2c); gk_iset(256, -1, t->c2i); for(i=0;ii2c[i] = alphabet[i]; t->c2i[(int)alphabet[i]] = i; } return t; } /*********************************************************************/ /*! \brief This function reads a pssm in the format of gkmod pssm \param file_name is the name of the pssm file \returns gk_seq_t */ /********************************************************************/ gk_seq_t *gk_seq_ReadGKMODPSSM(char *filename) { gk_seq_t *seq; gk_idx_t i, j, ii; size_t ntokens, nbytes, len; FILE *fpin; gk_Tokens_t tokens; static char *AAORDER = "ARNDCQEGHILKMFPSTWYVBZX*"; static int PSSMWIDTH = 20; char *header, line[MAXLINELEN]; gk_i2cc2i_t *converter; header = gk_cmalloc(PSSMWIDTH, "gk_seq_ReadGKMODPSSM: header"); converter = gk_i2cc2i_create_common(AAORDER); gk_getfilestats(filename, &len, &ntokens, NULL, &nbytes); len --; seq = gk_malloc(sizeof(gk_seq_t),"gk_seq_ReadGKMODPSSM"); gk_seq_init(seq); seq->len = len; seq->sequence = gk_imalloc(len, "gk_seq_ReadGKMODPSSM"); seq->pssm = gk_iAllocMatrix(len, PSSMWIDTH, 0, "gk_seq_ReadGKMODPSSM"); seq->psfm = gk_iAllocMatrix(len, PSSMWIDTH, 0, "gk_seq_ReadGKMODPSSM"); seq->nsymbols = PSSMWIDTH; seq->name = gk_getbasename(filename); fpin = gk_fopen(filename,"r","gk_seq_ReadGKMODPSSM"); /* Read the header line */ if (fgets(line, MAXLINELEN-1, fpin) == NULL) errexit("Unexpected end of file: %s\n", filename); gk_strtoupper(line); gk_strtokenize(line, " \t\n", &tokens); for (i=0; isequence[i] = converter->c2i[(int)tokens.list[1][0]]; for (j=0; jpssm[i][converter->c2i[(int)header[j]]] = atoi(tokens.list[2+j]); seq->psfm[i][converter->c2i[(int)header[j]]] = atoi(tokens.list[2+PSSMWIDTH+j]); } gk_freetokenslist(&tokens); i++; } seq->len = i; /* Reset the length if certain characters were skipped */ gk_free((void **)&header, LTERM); gk_fclose(fpin); return seq; } /**************************************************************************/ /*! \brief This function frees the memory allocated to the seq structure. \param gk_seq_t \returns nothing */ /**************************************************************************/ void gk_seq_free(gk_seq_t *seq) { gk_iFreeMatrix(&seq->pssm, seq->len, seq->nsymbols); gk_iFreeMatrix(&seq->psfm, seq->len, seq->nsymbols); gk_free((void **)&seq->name, &seq->sequence, LTERM); //gk_free((void **)&seq, LTERM); gk_free((void **) &seq, LTERM); } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/b64.c0000644000175100001440000000704214552244506023070 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file b64.c \brief This file contains some simple 8bit-to-6bit encoding/deconding routines Most of these routines are outdated and should be converted using glibc's equivalent routines. \date Started 2/22/05 \author George \version\verbatim $Id: b64.c 10711 2011-08-31 22:23:04Z karypis $ \endverbatim \verbatim $Copyright$ $License$ \endverbatim */ #include "GKlib.h" #define B64OFFSET 48 /* This is the '0' number */ /****************************************************************************** * Encode 3 '8-bit' binary bytes as 4 '6-bit' characters *******************************************************************************/ void encodeblock(unsigned char *in, unsigned char *out) { out[0] = (in[0] >> 2); out[1] = (((in[0] & 0x03) << 4) | (in[1] >> 4)); out[2] = (((in[1] & 0x0f) << 2) | (in[2] >> 6)); out[3] = (in[2] & 0x3f); out[0] += B64OFFSET; out[1] += B64OFFSET; out[2] += B64OFFSET; out[3] += B64OFFSET; // printf("%c %c %c %c %2x %2x %2x %2x %2x %2x %2x\n", out[0], out[1], out[2], out[3], out[0], out[1], out[2], out[3], in[0], in[1], in[2]); } /****************************************************************************** * Decode 4 '6-bit' characters into 3 '8-bit' binary bytes *******************************************************************************/ void decodeblock(unsigned char *in, unsigned char *out) { in[0] -= B64OFFSET; in[1] -= B64OFFSET; in[2] -= B64OFFSET; in[3] -= B64OFFSET; out[0] = (in[0] << 2 | in[1] >> 4); out[1] = (in[1] << 4 | in[2] >> 2); out[2] = (in[2] << 6 | in[3]); } /****************************************************************************** * This function encodes an input array of bytes into a base64 encoding. Memory * for the output array is assumed to have been allocated by the calling program * and be sufficiently large. The output string is NULL terminated. *******************************************************************************/ void GKEncodeBase64(int nbytes, unsigned char *inbuffer, unsigned char *outbuffer) { int i, j; if (nbytes%3 != 0) gk_errexit(SIGERR, "GKEncodeBase64: Input buffer size should be a multiple of 3! (%d)\n", nbytes); for (j=0, i=0; i 1000 #pragma once #endif #include "ms_stdint.h" // 7.8 Format conversion of integer types typedef struct { intmax_t quot; intmax_t rem; } imaxdiv_t; // 7.8.1 Macros for format specifiers // The fprintf macros for signed integers are: #define PRId8 "d" #define PRIi8 "i" #define PRIdLEAST8 "d" #define PRIiLEAST8 "i" #define PRIdFAST8 "d" #define PRIiFAST8 "i" #define PRId16 "hd" #define PRIi16 "hi" #define PRIdLEAST16 "hd" #define PRIiLEAST16 "hi" #define PRIdFAST16 "hd" #define PRIiFAST16 "hi" #define PRId32 "I32d" #define PRIi32 "I32i" #define PRIdLEAST32 "I32d" #define PRIiLEAST32 "I32i" #define PRIdFAST32 "I32d" #define PRIiFAST32 "I32i" #define PRId64 "I64d" #define PRIi64 "I64i" #define PRIdLEAST64 "I64d" #define PRIiLEAST64 "I64i" #define PRIdFAST64 "I64d" #define PRIiFAST64 "I64i" #define PRIdMAX "I64d" #define PRIiMAX "I64i" #define PRIdPTR "Id" #define PRIiPTR "Ii" // The fprintf macros for unsigned integers are: #define PRIo8 "o" #define PRIu8 "u" #define PRIx8 "x" #define PRIX8 "X" #define PRIoLEAST8 "o" #define PRIuLEAST8 "u" #define PRIxLEAST8 "x" #define PRIXLEAST8 "X" #define PRIoFAST8 "o" #define PRIuFAST8 "u" #define PRIxFAST8 "x" #define PRIXFAST8 "X" #define PRIo16 "ho" #define PRIu16 "hu" #define PRIx16 "hx" #define PRIX16 "hX" #define PRIoLEAST16 "ho" #define PRIuLEAST16 "hu" #define PRIxLEAST16 "hx" #define PRIXLEAST16 "hX" #define PRIoFAST16 "ho" #define PRIuFAST16 "hu" #define PRIxFAST16 "hx" #define PRIXFAST16 "hX" #define PRIo32 "I32o" #define PRIu32 "I32u" #define PRIx32 "I32x" #define PRIX32 "I32X" #define PRIoLEAST32 "I32o" #define PRIuLEAST32 "I32u" #define PRIxLEAST32 "I32x" #define PRIXLEAST32 "I32X" #define PRIoFAST32 "I32o" #define PRIuFAST32 "I32u" #define PRIxFAST32 "I32x" #define PRIXFAST32 "I32X" #define PRIo64 "I64o" #define PRIu64 "I64u" #define PRIx64 "I64x" #define PRIX64 "I64X" #define PRIoLEAST64 "I64o" #define PRIuLEAST64 "I64u" #define PRIxLEAST64 "I64x" #define PRIXLEAST64 "I64X" #define PRIoFAST64 "I64o" #define PRIuFAST64 "I64u" #define PRIxFAST64 "I64x" #define PRIXFAST64 "I64X" #define PRIoMAX "I64o" #define PRIuMAX "I64u" #define PRIxMAX "I64x" #define PRIXMAX "I64X" #define PRIoPTR "Io" #define PRIuPTR "Iu" #define PRIxPTR "Ix" #define PRIXPTR "IX" // The fscanf macros for signed integers are: #define SCNd8 "d" #define SCNi8 "i" #define SCNdLEAST8 "d" #define SCNiLEAST8 "i" #define SCNdFAST8 "d" #define SCNiFAST8 "i" #define SCNd16 "hd" #define SCNi16 "hi" #define SCNdLEAST16 "hd" #define SCNiLEAST16 "hi" #define SCNdFAST16 "hd" #define SCNiFAST16 "hi" #define SCNd32 "ld" #define SCNi32 "li" #define SCNdLEAST32 "ld" #define SCNiLEAST32 "li" #define SCNdFAST32 "ld" #define SCNiFAST32 "li" #define SCNd64 "I64d" #define SCNi64 "I64i" #define SCNdLEAST64 "I64d" #define SCNiLEAST64 "I64i" #define SCNdFAST64 "I64d" #define SCNiFAST64 "I64i" #define SCNdMAX "I64d" #define SCNiMAX "I64i" #ifdef _WIN64 // [ # define SCNdPTR "I64d" # define SCNiPTR "I64i" #else // _WIN64 ][ # define SCNdPTR "ld" # define SCNiPTR "li" #endif // _WIN64 ] // The fscanf macros for unsigned integers are: #define SCNo8 "o" #define SCNu8 "u" #define SCNx8 "x" #define SCNX8 "X" #define SCNoLEAST8 "o" #define SCNuLEAST8 "u" #define SCNxLEAST8 "x" #define SCNXLEAST8 "X" #define SCNoFAST8 "o" #define SCNuFAST8 "u" #define SCNxFAST8 "x" #define SCNXFAST8 "X" #define SCNo16 "ho" #define SCNu16 "hu" #define SCNx16 "hx" #define SCNX16 "hX" #define SCNoLEAST16 "ho" #define SCNuLEAST16 "hu" #define SCNxLEAST16 "hx" #define SCNXLEAST16 "hX" #define SCNoFAST16 "ho" #define SCNuFAST16 "hu" #define SCNxFAST16 "hx" #define SCNXFAST16 "hX" #define SCNo32 "lo" #define SCNu32 "lu" #define SCNx32 "lx" #define SCNX32 "lX" #define SCNoLEAST32 "lo" #define SCNuLEAST32 "lu" #define SCNxLEAST32 "lx" #define SCNXLEAST32 "lX" #define SCNoFAST32 "lo" #define SCNuFAST32 "lu" #define SCNxFAST32 "lx" #define SCNXFAST32 "lX" #define SCNo64 "I64o" #define SCNu64 "I64u" #define SCNx64 "I64x" #define SCNX64 "I64X" #define SCNoLEAST64 "I64o" #define SCNuLEAST64 "I64u" #define SCNxLEAST64 "I64x" #define SCNXLEAST64 "I64X" #define SCNoFAST64 "I64o" #define SCNuFAST64 "I64u" #define SCNxFAST64 "I64x" #define SCNXFAST64 "I64X" #define SCNoMAX "I64o" #define SCNuMAX "I64u" #define SCNxMAX "I64x" #define SCNXMAX "I64X" #ifdef _WIN64 // [ # define SCNoPTR "I64o" # define SCNuPTR "I64u" # define SCNxPTR "I64x" # define SCNXPTR "I64X" #else // _WIN64 ][ # define SCNoPTR "lo" # define SCNuPTR "lu" # define SCNxPTR "lx" # define SCNXPTR "lX" #endif // _WIN64 ] // 7.8.2 Functions for greatest-width integer types // 7.8.2.1 The imaxabs function #define imaxabs _abs64 // 7.8.2.2 The imaxdiv function // This is modified version of div() function from Microsoft's div.c found // in %MSVC.NET%\crt\src\div.c #ifdef STATIC_IMAXDIV // [ static #else // STATIC_IMAXDIV ][ _inline #endif // STATIC_IMAXDIV ] imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) { imaxdiv_t result; result.quot = numer / denom; result.rem = numer % denom; if (numer < 0 && result.rem > 0) { // did division wrong; must fix up ++result.quot; result.rem -= denom; } return result; } // 7.8.2.3 The strtoimax and strtoumax functions #define strtoimax _strtoi64 #define strtoumax _strtoui64 // 7.8.2.4 The wcstoimax and wcstoumax functions #define wcstoimax _wcstoi64 #define wcstoumax _wcstoui64 #endif // _MSC_INTTYPES_H_ ] Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/string.c0000644000175100001440000003740714552244506024013 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /************************************************************************/ /*! \file \brief Functions for manipulating strings. Various functions for manipulating strings. Some of these functions provide new functionality, whereas others are drop-in replacements of standard functions (but with enhanced functionality). \date Started 11/1/99 \author George \version $Id: string.c 10711 2011-08-31 22:23:04Z karypis $ */ /************************************************************************/ #include "GKlib.h" /************************************************************************/ /*! \brief Replaces certain characters in a string. This function takes a string and replaces all the characters in the \c fromlist with the corresponding characters from the \c tolist. That is, each occurence of fromlist[i] is replaced by tolist[i]. If the \c tolist is shorter than \c fromlist, then the corresponding characters are deleted. The modifications on \c str are done in place. It tries to provide a functionality similar to Perl's \b tr// function. \param str is the string whose characters will be replaced. \param fromlist is the set of characters to be replaced. \param tolist is the set of replacement characters . \returns A pointer to \c str itself. */ /************************************************************************/ char *gk_strchr_replace(char *str, char *fromlist, char *tolist) { gk_idx_t i, j, k; size_t len, fromlen, tolen; len = strlen(str); fromlen = strlen(fromlist); tolen = strlen(tolist); for (i=j=0; i s// regular-expression based substitution function. \param str is the input string on which the operation will be performed. \param pattern is the regular expression for the pattern to be matched for substitution. \param replacement is the replacement string, in which the possible captured pattern substrings are referred to as $1, $2, ..., $9. The entire matched pattern is refered to as $0. \param options is a string specified options for the substitution operation. Currently the "i" (case insensitive) and "g" (global substitution) are supported. \param new_str is a reference to a pointer that will store a pointer to the newly created string that results from the substitutions. This string is allocated via gk_malloc() and needs to be freed using gk_free(). The string is returned even if no substitutions were performed. \returns If successful, it returns 1 + the number of substitutions that were performed. Thus, if no substitutions were performed, the returned value will be 1. Otherwise it returns 0. In case of error, a meaningful error message is returned in newstr, which also needs to be freed afterwards. */ /************************************************************************/ int gk_strstr_replace(char *str, char *pattern, char *replacement, char *options, char **new_str) { gk_idx_t i; int j, rc, flags, global, nmatches; size_t len, rlen, nlen, offset, noffset; regex_t re; regmatch_t matches[10]; /* Parse the options */ flags = REG_EXTENDED; if (strchr(options, 'i') != NULL) flags = flags | REG_ICASE; global = (strchr(options, 'g') != NULL ? 1 : 0); /* Compile the regex */ if ((rc = regcomp(&re, pattern, flags)) != 0) { len = regerror(rc, &re, NULL, 0); *new_str = gk_cmalloc(len, "gk_strstr_replace: new_str"); regerror(rc, &re, *new_str, len); return 0; } /* Prepare the output string */ len = strlen(str); nlen = 2*len; noffset = 0; *new_str = gk_cmalloc(nlen+1, "gk_strstr_replace: new_str"); /* Get into the matching-replacing loop */ rlen = strlen(replacement); offset = 0; nmatches = 0; do { rc = regexec(&re, str+offset, 10, matches, 0); if (rc == REG_ESPACE) { gk_free((void **)new_str, LTERM); *new_str = gk_strdup("regexec ran out of memory."); regfree(&re); return 0; } else if (rc == REG_NOMATCH) { if (nlen-noffset < len-offset) { nlen += (len-offset) - (nlen-noffset); *new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str"); } strcpy(*new_str+noffset, str+offset); noffset += (len-offset); break; } else { /* A match was found! */ nmatches++; /* Copy the left unmatched portion of the string */ if (matches[0].rm_so > 0) { if (nlen-noffset < matches[0].rm_so) { nlen += matches[0].rm_so - (nlen-noffset); *new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str"); } strncpy(*new_str+noffset, str+offset, matches[0].rm_so); noffset += matches[0].rm_so; } /* Go and append the replacement string */ for (i=0; i 9) { gk_free((void **)new_str, LTERM); *new_str = gk_strdup("Error in captured subexpression specification."); regfree(&re); return 0; } if (nlen-noffset < matches[j].rm_eo-matches[j].rm_so) { nlen += nlen + (matches[j].rm_eo-matches[j].rm_so); *new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str"); } strncpy(*new_str+noffset, str+offset+matches[j].rm_so, matches[j].rm_eo); noffset += matches[j].rm_eo-matches[j].rm_so; } else { gk_free((void **)new_str, LTERM); *new_str = gk_strdup("Error in replacement string. Missing subexpression number folloing '$'."); regfree(&re); return 0; } break; default: if (nlen-noffset < 1) { nlen += nlen + 1; *new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str"); } (*new_str)[noffset++] = replacement[i]; } } /* Update the offset of str for the next match */ offset += matches[0].rm_eo; if (!global) { /* Copy the right portion of the string if no 'g' option */ if (nlen-noffset < len-offset) { nlen += (len-offset) - (nlen-noffset); *new_str = (char *)gk_realloc(*new_str, (nlen+1)*sizeof(char), "gk_strstr_replace: new_str"); } strcpy(*new_str+noffset, str+offset); noffset += (len-offset); } } } while (global); (*new_str)[noffset] = '\0'; regfree(&re); return nmatches + 1; } /************************************************************************/ /*! \brief Prunes characters from the end of the string. This function removes any trailing characters that are included in the \c rmlist. The trimming stops at the last character (i.e., first character from the end) that is not in \c rmlist. This function can be used to removed trailing spaces, newlines, etc. This is a distructive operation as it modifies the string. \param str is the string that will be trimmed. \param rmlist contains the set of characters that will be removed. \returns A pointer to \c str itself. \sa gk_strhprune() */ /*************************************************************************/ char *gk_strtprune(char *str, char *rmlist) { gk_idx_t i, j; size_t len; len = strlen(rmlist); for (i=strlen(str)-1; i>=0; i--) { for (j=0; j0) { /* If something needs to be removed */ for (j=0; str[i]; i++, j++) str[j] = str[i]; str[j] = '\0'; } return str; } /************************************************************************/ /*! \brief Converts a string to upper case. This function converts a string to upper case. This operation modifies the string itself. \param str is the string whose case will be changed. \returns A pointer to \c str itself. \sa gk_strtolower() */ /*************************************************************************/ char *gk_strtoupper(char *str) { int i; for (i=0; str[i]!='\0'; str[i]=toupper(str[i]), i++); return str; } /************************************************************************/ /*! \brief Converts a string to lower case. This function converts a string to lower case. This operation modifies the string itself. \param str is the string whose case will be changed. \returns A pointer to \c str itself. \sa gk_strtoupper() */ /*************************************************************************/ char *gk_strtolower(char *str) { int i; for (i=0; str[i]!='\0'; str[i]=tolower(str[i]), i++); return str; } /************************************************************************/ /*! \brief Duplicates a string This function is a replacement for C's standard strdup() function. The key differences between the two are that gk_strdup(): - uses the dynamic memory allocation routines of \e GKlib. - it correctly handles NULL input strings. The string that is returned must be freed by gk_free(). \param orgstr is the string that will be duplicated. \returns A pointer to the newly created string. \sa gk_free() */ /*************************************************************************/ char *gk_strdup(char *orgstr) { int len; char *str=NULL; if (orgstr != NULL) { len = strlen(orgstr)+1; str = gk_malloc(len*sizeof(char), "gk_strdup: str"); strcpy(str, orgstr); } return str; } /************************************************************************/ /*! \brief Case insensitive string comparison. This function compares two strings for equality by ignoring the case of the strings. \warning This function is \b not equivalent to a case-insensitive strcmp() function, as it does not return ordering information. \todo Remove the above warning. \param s1 is the first string to be compared. \param s2 is the second string to be compared. \retval 1 if the strings are identical, \retval 0 otherwise. */ /*************************************************************************/ int gk_strcasecmp(char *s1, char *s2) { int i=0; if (strlen(s1) != strlen(s2)) return 0; while (s1[i] != '\0') { if (tolower(s1[i]) != tolower(s2[i])) return 0; i++; } return 1; } /************************************************************************/ /*! \brief Compare two strings in revere order This function is similar to strcmp but it performs the comparison as if the two strings were reversed. \param s1 is the first string to be compared. \param s2 is the second string to be compared. \retval -1, 0, 1, if the s1 < s2, s1 == s2, or s1 > s2. */ /*************************************************************************/ int gk_strrcmp(char *s1, char *s2) { int i1 = strlen(s1)-1; int i2 = strlen(s2)-1; while ((i1 >= 0) && (i2 >= 0)) { if (s1[i1] != s2[i2]) return (s1[i1] - s2[i2]); i1--; i2--; } /* i1 == -1 and/or i2 == -1 */ if (i1 < i2) return -1; if (i1 > i2) return 1; return 0; } /************************************************************************/ /*! \brief Converts a time_t time into a string This function takes a time_t-specified time and returns a string-formated representation of the corresponding time. The format of the string is mm/dd/yyyy hh:mm:ss, in which the hours are in military time. \param time is the time to be converted. \return It returns a pointer to a statically allocated string that is over-written in successive calls of this function. If the conversion failed, it returns NULL. */ /*************************************************************************/ char *gk_time2str(time_t time) { static char datestr[128]; struct tm *tm; tm = localtime(&time); if (strftime(datestr, 128, "%m/%d/%Y %H:%M:%S", tm) == 0) return NULL; else return datestr; } #if !defined(WIN32) && !defined(__MINGW32__) /************************************************************************/ /*! \brief Converts a date/time string into its equivalent time_t value This function takes date and/or time specification and converts it in the equivalent time_t representation. The conversion is done using the strptime() function. The format that gk_str2time() understands is mm/dd/yyyy hh:mm:ss, in which the hours are in military time. \param str is the date/time string to be converted. \return If the conversion was successful it returns the time, otherwise it returns -1. */ /*************************************************************************/ time_t gk_str2time(char *str) { struct tm time; time_t rtime; memset(&time, '\0', sizeof(time)); if (strptime(str, "%m/%d/%Y %H:%M:%S", &time) == NULL) return -1; rtime = mktime(&time); return (rtime < 0 ? 0 : rtime); } #endif /************************************************************************* * This function returns the ID of a particular string based on the * supplied StringMap array **************************************************************************/ int gk_GetStringID(gk_StringMap_t *strmap, char *key) { int i; for (i=0; strmap[i].name; i++) { if (gk_strcasecmp(key, strmap[i].name)) return strmap[i].id; } return -1; } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gkregex.h0000644000175100001440000005250414552244506024141 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* Definitions for data structures and routines for the regular expression library. Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003,2005,2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef _REGEX_H #define _REGEX_H 1 #include /* Allow the use in C++ code. */ #ifdef __cplusplus extern "C" { #endif /* The following two types have to be signed and unsigned integer type wide enough to hold a value of a pointer. For most ANSI compilers ptrdiff_t and size_t should be likely OK. Still size of these two types is 2 for Microsoft C. Ugh... */ typedef long int s_reg_t; typedef unsigned long int active_reg_t; /* The following bits are used to determine the regexp syntax we recognize. The set/not-set meanings are chosen so that Emacs syntax remains the value 0. The bits are given in alphabetical order, and the definitions shifted by one from the previous bit; thus, when we add or remove a bit, only one other definition need change. */ typedef unsigned long int reg_syntax_t; /* If this bit is not set, then \ inside a bracket expression is literal. If set, then such a \ quotes the following character. */ #define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) /* If this bit is not set, then + and ? are operators, and \+ and \? are literals. If set, then \+ and \? are operators and + and ? are literals. */ #define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) /* If this bit is set, then character classes are supported. They are: [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. If not set, then character classes are not supported. */ #define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) /* If this bit is set, then ^ and $ are always anchors (outside bracket expressions, of course). If this bit is not set, then it depends: ^ is an anchor if it is at the beginning of a regular expression or after an open-group or an alternation operator; $ is an anchor if it is at the end of a regular expression, or before a close-group or an alternation operator. This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because POSIX draft 11.2 says that * etc. in leading positions is undefined. We already implemented a previous draft which made those constructs invalid, though, so we haven't changed the code back. */ #define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) /* If this bit is set, then special characters are always special regardless of where they are in the pattern. If this bit is not set, then special characters are special only in some contexts; otherwise they are ordinary. Specifically, * + ? and intervals are only special when not after the beginning, open-group, or alternation operator. */ #define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) /* If this bit is set, then *, +, ?, and { cannot be first in an re or immediately after an alternation or begin-group operator. */ #define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) /* If this bit is set, then . matches newline. If not set, then it doesn't. */ #define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) /* If this bit is set, then . doesn't match NUL. If not set, then it does. */ #define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) /* If this bit is set, nonmatching lists [^...] do not match newline. If not set, they do. */ #define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) /* If this bit is set, either \{...\} or {...} defines an interval, depending on RE_NO_BK_BRACES. If not set, \{, \}, {, and } are literals. */ #define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) /* If this bit is set, +, ? and | aren't recognized as operators. If not set, they are. */ #define RE_LIMITED_OPS (RE_INTERVALS << 1) /* If this bit is set, newline is an alternation operator. If not set, newline is literal. */ #define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) /* If this bit is set, then `{...}' defines an interval, and \{ and \} are literals. If not set, then `\{...\}' defines an interval. */ #define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) /* If this bit is set, (...) defines a group, and \( and \) are literals. If not set, \(...\) defines a group, and ( and ) are literals. */ #define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) /* If this bit is set, then \ matches . If not set, then \ is a back-reference. */ #define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) /* If this bit is set, then | is an alternation operator, and \| is literal. If not set, then \| is an alternation operator, and | is literal. */ #define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) /* If this bit is set, then an ending range point collating higher than the starting range point, as in [z-a], is invalid. If not set, then when ending range point collates higher than the starting range point, the range is ignored. */ #define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) /* If this bit is set, then an unmatched ) is ordinary. If not set, then an unmatched ) is invalid. */ #define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) /* If this bit is set, succeed as soon as we match the whole pattern, without further backtracking. */ #define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1) /* If this bit is set, do not process the GNU regex operators. If not set, then the GNU regex operators are recognized. */ #define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1) /* If this bit is set, turn on internal regex debugging. If not set, and debugging was on, turn it off. This only works if regex.c is compiled -DDEBUG. We define this bit always, so that all that's needed to turn on debugging is to recompile regex.c; the calling code can always have this bit set, and it won't affect anything in the normal case. */ #define RE_DEBUG (RE_NO_GNU_OPS << 1) /* If this bit is set, a syntactically invalid interval is treated as a string of ordinary characters. For example, the ERE 'a{1' is treated as 'a\{1'. */ #define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) /* If this bit is set, then ignore case when matching. If not set, then case is significant. */ #define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1) /* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only for ^, because it is difficult to scan the regex backwards to find whether ^ should be special. */ #define RE_CARET_ANCHORS_HERE (RE_ICASE << 1) /* If this bit is set, then \{ cannot be first in an bre or immediately after an alternation or begin-group operator. */ #define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1) /* If this bit is set, then no_sub will be set to 1 during re_compile_pattern. */ #define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) /* This global variable defines the particular regexp syntax to use (for some interfaces). When a regexp is compiled, the syntax used is stored in the pattern buffer, so changing this does not affect already-compiled regexps. */ extern reg_syntax_t re_syntax_options; /* Define combinations of the above bits for the standard possibilities. (The [[[ comments delimit what gets put into the Texinfo file, so don't delete them!) */ /* [[[begin syntaxes]]] */ #define RE_SYNTAX_EMACS 0 #define RE_SYNTAX_AWK \ (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ | RE_NO_BK_PARENS | RE_NO_BK_REFS \ | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) #define RE_SYNTAX_GNU_AWK \ ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \ & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \ | RE_CONTEXT_INVALID_OPS )) #define RE_SYNTAX_POSIX_AWK \ (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ | RE_INTERVALS | RE_NO_GNU_OPS) #define RE_SYNTAX_GREP \ (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ | RE_NEWLINE_ALT) #define RE_SYNTAX_EGREP \ (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ | RE_NO_BK_VBAR) #define RE_SYNTAX_POSIX_EGREP \ (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \ | RE_INVALID_INTERVAL_ORD) /* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ #define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC #define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC /* Syntax bits common to both basic and extended POSIX regex syntax. */ #define _RE_SYNTAX_POSIX_COMMON \ (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ | RE_INTERVALS | RE_NO_EMPTY_RANGES) #define RE_SYNTAX_POSIX_BASIC \ (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP) /* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this isn't minimal, since other operators, such as \`, aren't disabled. */ #define RE_SYNTAX_POSIX_MINIMAL_BASIC \ (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) #define RE_SYNTAX_POSIX_EXTENDED \ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD) /* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is removed and RE_NO_BK_REFS is added. */ #define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ | RE_NO_BK_PARENS | RE_NO_BK_REFS \ | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) /* [[[end syntaxes]]] */ /* Maximum number of duplicates an interval can allow. Some systems (erroneously) define this in other header files, but we want our value, so remove any previous define. */ #ifdef RE_DUP_MAX # undef RE_DUP_MAX #endif /* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */ #define RE_DUP_MAX (0x7fff) /* POSIX `cflags' bits (i.e., information for `regcomp'). */ /* If this bit is set, then use extended regular expression syntax. If not set, then use basic regular expression syntax. */ #define REG_EXTENDED 1 /* If this bit is set, then ignore case when matching. If not set, then case is significant. */ #define REG_ICASE (REG_EXTENDED << 1) /* If this bit is set, then anchors do not match at newline characters in the string. If not set, then anchors do match at newlines. */ #define REG_NEWLINE (REG_ICASE << 1) /* If this bit is set, then report only success or fail in regexec. If not set, then returns differ between not matching and errors. */ #define REG_NOSUB (REG_NEWLINE << 1) /* POSIX `eflags' bits (i.e., information for regexec). */ /* If this bit is set, then the beginning-of-line operator doesn't match the beginning of the string (presumably because it's not the beginning of a line). If not set, then the beginning-of-line operator does match the beginning of the string. */ #define REG_NOTBOL 1 /* Like REG_NOTBOL, except for the end-of-line. */ #define REG_NOTEOL (1 << 1) /* Use PMATCH[0] to delimit the start and end of the search in the buffer. */ #define REG_STARTEND (1 << 2) /* If any error codes are removed, changed, or added, update the `re_error_msg' table in regex.c. */ typedef enum { #ifdef _XOPEN_SOURCE REG_ENOSYS = -1, /* This will never happen for this implementation. */ #endif REG_NOERROR = 0, /* Success. */ REG_NOMATCH, /* Didn't find a match (for regexec). */ /* POSIX regcomp return error codes. (In the order listed in the standard.) */ REG_BADPAT, /* Invalid pattern. */ REG_ECOLLATE, /* Inalid collating element. */ REG_ECTYPE, /* Invalid character class name. */ REG_EESCAPE, /* Trailing backslash. */ REG_ESUBREG, /* Invalid back reference. */ REG_EBRACK, /* Unmatched left bracket. */ REG_EPAREN, /* Parenthesis imbalance. */ REG_EBRACE, /* Unmatched \{. */ REG_BADBR, /* Invalid contents of \{\}. */ REG_ERANGE, /* Invalid range end. */ REG_ESPACE, /* Ran out of memory. */ REG_BADRPT, /* No preceding re for repetition op. */ /* Error codes we've added. */ REG_EEND, /* Premature end. */ REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ } reg_errcode_t; /* This data structure represents a compiled pattern. Before calling the pattern compiler, the fields `buffer', `allocated', `fastmap', `translate', and `no_sub' can be set. After the pattern has been compiled, the `re_nsub' field is available. All other fields are private to the regex routines. */ #ifndef RE_TRANSLATE_TYPE # define RE_TRANSLATE_TYPE unsigned char * #endif struct re_pattern_buffer { /* Space that holds the compiled pattern. It is declared as `unsigned char *' because its elements are sometimes used as array indexes. */ unsigned char *buffer; /* Number of bytes to which `buffer' points. */ unsigned long int allocated; /* Number of bytes actually used in `buffer'. */ unsigned long int used; /* Syntax setting with which the pattern was compiled. */ reg_syntax_t syntax; /* Pointer to a fastmap, if any, otherwise zero. re_search uses the fastmap, if there is one, to skip over impossible starting points for matches. */ char *fastmap; /* Either a translate table to apply to all characters before comparing them, or zero for no translation. The translation is applied to a pattern when it is compiled and to a string when it is matched. */ RE_TRANSLATE_TYPE translate; /* Number of subexpressions found by the compiler. */ size_t re_nsub; /* Zero if this pattern cannot match the empty string, one else. Well, in truth it's used only in `re_search_2', to see whether or not we should use the fastmap, so we don't set this absolutely perfectly; see `re_compile_fastmap' (the `duplicate' case). */ unsigned can_be_null : 1; /* If REGS_UNALLOCATED, allocate space in the `regs' structure for `max (RE_NREGS, re_nsub + 1)' groups. If REGS_REALLOCATE, reallocate space if necessary. If REGS_FIXED, use what's there. */ #define REGS_UNALLOCATED 0 #define REGS_REALLOCATE 1 #define REGS_FIXED 2 unsigned regs_allocated : 2; /* Set to zero when `regex_compile' compiles a pattern; set to one by `re_compile_fastmap' if it updates the fastmap. */ unsigned fastmap_accurate : 1; /* If set, `re_match_2' does not return information about subexpressions. */ unsigned no_sub : 1; /* If set, a beginning-of-line anchor doesn't match at the beginning of the string. */ unsigned not_bol : 1; /* Similarly for an end-of-line anchor. */ unsigned not_eol : 1; /* If true, an anchor at a newline matches. */ unsigned newline_anchor : 1; }; typedef struct re_pattern_buffer regex_t; /* Type for byte offsets within the string. POSIX mandates this. */ typedef int regoff_t; /* This is the structure we store register match data in. See regex.texinfo for a full description of what registers match. */ struct re_registers { unsigned num_regs; regoff_t *start; regoff_t *end; }; /* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, `re_match_2' returns information about at least this many registers the first time a `regs' structure is passed. */ #ifndef RE_NREGS # define RE_NREGS 30 #endif /* POSIX specification for registers. Aside from the different names than `re_registers', POSIX uses an array of structures, instead of a structure of arrays. */ typedef struct { regoff_t rm_so; /* Byte offset from string's start to substring's start. */ regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ } regmatch_t; /* Declarations for routines. */ /* Sets the current default syntax to SYNTAX, and return the old syntax. You can also simply assign to the `re_syntax_options' variable. */ extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax); /* Compile the regular expression PATTERN, with length LENGTH and syntax given by the global `re_syntax_options', into the buffer BUFFER. Return NULL if successful, and an error string if not. */ extern const char *re_compile_pattern (const char *__pattern, size_t __length, struct re_pattern_buffer *__buffer); /* Compile a fastmap for the compiled pattern in BUFFER; used to accelerate searches. Return 0 if successful and -2 if was an internal error. */ extern int re_compile_fastmap (struct re_pattern_buffer *__buffer); /* Search in the string STRING (with length LENGTH) for the pattern compiled into BUFFER. Start searching at position START, for RANGE characters. Return the starting position of the match, -1 for no match, or -2 for an internal error. Also return register information in REGS (if REGS and BUFFER->no_sub are nonzero). */ extern int re_search (struct re_pattern_buffer *__buffer, const char *__string, int __length, int __start, int __range, struct re_registers *__regs); /* Like `re_search', but search in the concatenation of STRING1 and STRING2. Also, stop searching at index START + STOP. */ extern int re_search_2 (struct re_pattern_buffer *__buffer, const char *__string1, int __length1, const char *__string2, int __length2, int __start, int __range, struct re_registers *__regs, int __stop); /* Like `re_search', but return how many characters in STRING the regexp in BUFFER matched, starting at position START. */ extern int re_match (struct re_pattern_buffer *__buffer, const char *__string, int __length, int __start, struct re_registers *__regs); /* Relates to `re_match' as `re_search_2' relates to `re_search'. */ extern int re_match_2 (struct re_pattern_buffer *__buffer, const char *__string1, int __length1, const char *__string2, int __length2, int __start, struct re_registers *__regs, int __stop); /* Set REGS to hold NUM_REGS registers, storing them in STARTS and ENDS. Subsequent matches using BUFFER and REGS will use this memory for recording register information. STARTS and ENDS must be allocated with malloc, and must each be at least `NUM_REGS * sizeof (regoff_t)' bytes long. If NUM_REGS == 0, then subsequent matches should allocate their own register data. Unless this function is called, the first search or match using PATTERN_BUFFER will allocate its own register data, without freeing the old data. */ extern void re_set_registers (struct re_pattern_buffer *__buffer, struct re_registers *__regs, unsigned int __num_regs, regoff_t *__starts, regoff_t *__ends); #if defined _REGEX_RE_COMP || defined _LIBC # ifndef _CRAY /* 4.2 bsd compatibility. */ extern char *re_comp (const char *); extern int re_exec (const char *); # endif #endif /* GCC 2.95 and later have "__restrict"; C99 compilers have "restrict", and "configure" may have defined "restrict". */ #ifndef __restrict # if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)) # if defined restrict || 199901L <= __STDC_VERSION__ # define __restrict restrict # else # define __restrict # endif # endif #endif /* gcc 3.1 and up support the [restrict] syntax. */ #ifndef __restrict_arr # if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) \ && !defined __GNUG__ # define __restrict_arr __restrict # else # define __restrict_arr # endif #endif /* POSIX compatibility. */ extern int regcomp (regex_t *__restrict __preg, const char *__restrict __pattern, int __cflags); extern int regexec (const regex_t *__restrict __preg, const char *__restrict __string, size_t __nmatch, regmatch_t __pmatch[__restrict_arr], int __eflags); extern size_t regerror (int __errcode, const regex_t *__restrict __preg, char *__restrict __errbuf, size_t __errbuf_size); extern void regfree (regex_t *__preg); #ifdef __cplusplus } #endif /* C++ */ #endif /* regex.h */ Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_externs.h0000644000175100001440000000232414552244506024651 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file gk_externs.h \brief This file contains definitions of external variables created by GKlib \date Started 3/27/2007 \author George \version\verbatim $Id: gk_externs.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim */ #ifndef _GK_EXTERNS_H_ #define _GK_EXTERNS_H_ /************************************************************************* * Extern variable definition. Hopefully, the __thread makes them thread-safe. **************************************************************************/ #ifndef _GK_ERROR_C_ /* declared in error.c */ extern __thread int gk_cur_jbufs; extern __thread jmp_buf gk_jbufs[]; extern __thread jmp_buf gk_jbuf; #endif #endif Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/0000755000175100001440000000000014576343415023153 5ustar hornikusersMatrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/srefine.c0000644000175100001440000001246614552244506024756 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * srefine.c * * This file contains code for the separator refinement algortihms * * Started 8/1/97 * George * * $Id: srefine.c 10515 2011-07-08 15:46:18Z karypis $ * */ #include "metislib.h" /*************************************************************************/ /*! This function is the entry point of the separator refinement. It does not perform any refinement on graph, but it starts by first projecting it to the next level finer graph and proceeds from there. */ /*************************************************************************/ void Refine2WayNode(ctrl_t *ctrl, graph_t *orggraph, graph_t *graph) { IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->UncoarsenTmr)); if (graph == orggraph) { Compute2WayNodePartitionParams(ctrl, graph); } else { do { graph = graph->finer; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ProjectTmr)); Project2WayNodePartition(ctrl, graph); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ProjectTmr)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->RefTmr)); FM_2WayNodeBalance(ctrl, graph); ASSERT(CheckNodePartitionParams(graph)); switch (ctrl->rtype) { case METIS_RTYPE_SEP2SIDED: FM_2WayNodeRefine2Sided(ctrl, graph, ctrl->niter); break; case METIS_RTYPE_SEP1SIDED: FM_2WayNodeRefine1Sided(ctrl, graph, ctrl->niter); break; default: gk_errexit(SIGERR, "Unknown rtype of %d\n", ctrl->rtype); } IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->RefTmr)); } while (graph != orggraph); } IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->UncoarsenTmr)); } /*************************************************************************/ /*! This function allocates memory for 2-way node-based refinement */ /**************************************************************************/ void Allocate2WayNodePartitionMemory(ctrl_t *ctrl, graph_t *graph) { idx_t nvtxs; nvtxs = graph->nvtxs; graph->pwgts = imalloc(3, "Allocate2WayNodePartitionMemory: pwgts"); graph->where = imalloc(nvtxs, "Allocate2WayNodePartitionMemory: where"); graph->bndptr = imalloc(nvtxs, "Allocate2WayNodePartitionMemory: bndptr"); graph->bndind = imalloc(nvtxs, "Allocate2WayNodePartitionMemory: bndind"); graph->nrinfo = (nrinfo_t *)gk_malloc(nvtxs*sizeof(nrinfo_t), "Allocate2WayNodePartitionMemory: nrinfo"); } /*************************************************************************/ /*! This function computes the edegrees[] to the left & right sides */ /*************************************************************************/ void Compute2WayNodePartitionParams(ctrl_t *ctrl, graph_t *graph) { idx_t i, j, nvtxs, nbnd; idx_t *xadj, *adjncy, *vwgt; idx_t *where, *pwgts, *bndind, *bndptr, *edegrees; nrinfo_t *rinfo; idx_t me, other; nvtxs = graph->nvtxs; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; where = graph->where; rinfo = graph->nrinfo; pwgts = iset(3, 0, graph->pwgts); bndind = graph->bndind; bndptr = iset(nvtxs, -1, graph->bndptr); /*------------------------------------------------------------ / Compute now the separator external degrees /------------------------------------------------------------*/ nbnd = 0; for (i=0; i=0 && me <= 2); if (me == 2) { /* If it is on the separator do some computations */ BNDInsert(nbnd, bndind, bndptr, i); edegrees = rinfo[i].edegrees; edegrees[0] = edegrees[1] = 0; for (j=xadj[i]; jmincut = pwgts[2]; graph->nbnd = nbnd; } /*************************************************************************/ /*! This function projects the node-based bisection */ /*************************************************************************/ void Project2WayNodePartition(ctrl_t *ctrl, graph_t *graph) { idx_t i, nvtxs; idx_t *cmap, *where, *cwhere; graph_t *cgraph; cgraph = graph->coarser; cwhere = cgraph->where; nvtxs = graph->nvtxs; cmap = graph->cmap; Allocate2WayNodePartitionMemory(ctrl, graph); where = graph->where; /* Project the partition */ for (i=0; i= 0 && where[i] <= 2, ("%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"\n", i, cmap[i], where[i], cwhere[cmap[i]])); } FreeGraph(&graph->coarser); graph->coarser = NULL; Compute2WayNodePartitionParams(ctrl, graph); } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/metislib.h0000644000175100001440000000230414552244506025126 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * metis.h * * This file includes all necessary header files * * Started 8/27/94 * George * * $Id: metislib.h 10655 2011-08-02 17:38:11Z benjamin $ */ #ifndef _LIBMETIS_METISLIB_H_ #define _LIBMETIS_METISLIB_H_ #include "GKlib.h" #if defined(ENABLE_OPENMP) #include #endif #include "metis.h" #include "rename.h" #include "gklib_defs.h" #include "defs.h" #include "struct.h" #include "macros.h" #include "proto.h" #if defined(COMPILER_MSC) #if defined(rint) #undef rint #endif #define rint(x) ((idx_t)((x)+0.5)) /* MSC does not have rint() function */ #endif #endif Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/util.c0000644000175100001440000000672714552244506024303 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * util.c * * This function contains various utility routines * * Started 9/28/95 * George * * $Id: util.c 10495 2011-07-06 16:04:45Z karypis $ */ #include "metislib.h" /*************************************************************************/ /*! This function initializes the random number generator */ /*************************************************************************/ void InitRandom(idx_t seed) { isrand((seed == -1 ? 4321 : seed)); } /*************************************************************************/ /*! Returns the highest weight index of x[i]*y[i] */ /*************************************************************************/ idx_t iargmax_nrm(size_t n, idx_t *x, real_t *y) { idx_t i, max=0; for (i=1; i x[max]*y[max] ? i : max); return max; } /*************************************************************************/ /*! These functions return the index of the maximum element in a vector */ /*************************************************************************/ idx_t iargmax_strd(size_t n, idx_t *x, idx_t incx) { size_t i, max=0; n *= incx; for (i=incx; i x[max] ? i : max); return max/incx; } /*************************************************************************/ /*! These functions return the index of the almost maximum element in a vector */ /*************************************************************************/ idx_t rargmax2(size_t n, real_t *x) { size_t i, max1, max2; if (x[0] > x[1]) { max1 = 0; max2 = 1; } else { max1 = 1; max2 = 0; } for (i=2; i x[max1]) { max2 = max1; max1 = i; } else if (x[i] > x[max2]) max2 = i; } return max2; } /*************************************************************************/ /*! These functions return the index of the second largest elements in the vector formed by x.y where '.' is element-wise multiplication */ /*************************************************************************/ idx_t iargmax2_nrm(size_t n, idx_t *x, real_t *y) { size_t i, max1, max2; if (x[0]*y[0] > x[1]*y[1]) { max1 = 0; max2 = 1; } else { max1 = 1; max2 = 0; } for (i=2; i x[max1]*y[max1]) { max2 = max1; max1 = i; } else if (x[i]*y[i] > x[max2]*y[max2]) max2 = i; } return max2; } /*************************************************************************/ /*! converts a signal code into a Metis return code */ /*************************************************************************/ int metis_rcode(int sigrval) { switch (sigrval) { case 0: return METIS_OK; break; case SIGMEM: return METIS_ERROR_MEMORY; break; default: return METIS_ERROR; break; } } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/kwayrefine.c0000644000175100001440000005033414552244506025463 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file \brief Driving routines for multilevel k-way refinement \date Started 7/28/1997 \author George \author Copyright 1997-2009, Regents of the University of Minnesota \version $Id: kwayrefine.c 10737 2011-09-13 13:37:25Z karypis $ */ #include "metislib.h" /*************************************************************************/ /*! This function is the entry point of cut-based refinement */ /*************************************************************************/ void RefineKWay(ctrl_t *ctrl, graph_t *orggraph, graph_t *graph) { idx_t i, nlevels, contig=ctrl->contig; graph_t *ptr; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->UncoarsenTmr)); /* Determine how many levels are there */ for (ptr=graph, nlevels=0; ptr!=orggraph; ptr=ptr->finer, nlevels++); /* Compute the parameters of the coarsest graph */ ComputeKWayPartitionParams(ctrl, graph); /* Try to minimize the sub-domain connectivity */ if (ctrl->minconn) EliminateSubDomainEdges(ctrl, graph); /* Deal with contiguity constraints at the beginning */ if (contig && FindPartitionInducedComponents(graph, graph->where, NULL, NULL) > ctrl->nparts) { EliminateComponents(ctrl, graph); ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE); Greedy_KWayOptimize(ctrl, graph, 5, 0, OMODE_BALANCE); ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE); Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 0, OMODE_REFINE); ctrl->contig = 0; } /* Refine each successively finer graph */ for (i=0; ;i++) { if (ctrl->minconn && i == nlevels/2) EliminateSubDomainEdges(ctrl, graph); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->RefTmr)); if (2*i >= nlevels && !IsBalanced(ctrl, graph, .02)) { ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE); Greedy_KWayOptimize(ctrl, graph, 1, 0, OMODE_BALANCE); ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE); } Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 5.0, OMODE_REFINE); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->RefTmr)); /* Deal with contiguity constraints in the middle */ if (contig && i == nlevels/2) { if (FindPartitionInducedComponents(graph, graph->where, NULL, NULL) > ctrl->nparts) { EliminateComponents(ctrl, graph); if (!IsBalanced(ctrl, graph, .02)) { ctrl->contig = 1; ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE); Greedy_KWayOptimize(ctrl, graph, 5, 0, OMODE_BALANCE); ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE); Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 0, OMODE_REFINE); ctrl->contig = 0; } } } if (graph == orggraph) break; graph = graph->finer; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ProjectTmr)); ASSERT(graph->vwgt != NULL); ProjectKWayPartition(ctrl, graph); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ProjectTmr)); } /* Deal with contiguity requirement at the end */ ctrl->contig = contig; if (contig && FindPartitionInducedComponents(graph, graph->where, NULL, NULL) > ctrl->nparts) EliminateComponents(ctrl, graph); if (!IsBalanced(ctrl, graph, 0.0)) { ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE); Greedy_KWayOptimize(ctrl, graph, 10, 0, OMODE_BALANCE); ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE); Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 0, OMODE_REFINE); } if (ctrl->contig) ASSERT(FindPartitionInducedComponents(graph, graph->where, NULL, NULL) == ctrl->nparts); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->UncoarsenTmr)); } /*************************************************************************/ /*! This function allocates memory for the k-way cut-based refinement */ /*************************************************************************/ void AllocateKWayPartitionMemory(ctrl_t *ctrl, graph_t *graph) { graph->pwgts = imalloc(ctrl->nparts*graph->ncon, "AllocateKWayPartitionMemory: pwgts"); graph->where = imalloc(graph->nvtxs, "AllocateKWayPartitionMemory: where"); graph->bndptr = imalloc(graph->nvtxs, "AllocateKWayPartitionMemory: bndptr"); graph->bndind = imalloc(graph->nvtxs, "AllocateKWayPartitionMemory: bndind"); switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: graph->ckrinfo = (ckrinfo_t *)gk_malloc(graph->nvtxs*sizeof(ckrinfo_t), "AllocateKWayPartitionMemory: ckrinfo"); break; case METIS_OBJTYPE_VOL: graph->vkrinfo = (vkrinfo_t *)gk_malloc(graph->nvtxs*sizeof(vkrinfo_t), "AllocateKWayVolPartitionMemory: vkrinfo"); /* This is to let the cut-based -minconn and -contig large-scale graph changes to go through */ graph->ckrinfo = (ckrinfo_t *)graph->vkrinfo; break; default: gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); } } /*************************************************************************/ /*! This function computes the initial id/ed for cut-based partitioning */ /**************************************************************************/ void ComputeKWayPartitionParams(ctrl_t *ctrl, graph_t *graph) { idx_t i, j, k, nvtxs, ncon, nparts, nbnd, mincut, me, other; idx_t *xadj, *vwgt, *adjncy, *adjwgt, *pwgts, *where, *bndind, *bndptr; nparts = ctrl->nparts; nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; pwgts = iset(nparts*ncon, 0, graph->pwgts); bndind = graph->bndind; bndptr = iset(nvtxs, -1, graph->bndptr); nbnd = mincut = 0; /* Compute pwgts */ if (ncon == 1) { for (i=0; i= 0 && where[i] < nparts); pwgts[where[i]] += vwgt[i]; } } else { for (i=0; iobjtype) { case METIS_OBJTYPE_CUT: { ckrinfo_t *myrinfo; cnbr_t *mynbrs; memset(graph->ckrinfo, 0, sizeof(ckrinfo_t)*nvtxs); cnbrpoolReset(ctrl); for (i=0; ickrinfo+i; for (j=xadj[i]; jid += adjwgt[j]; else myrinfo->ed += adjwgt[j]; } /* Time to compute the particular external degrees */ if (myrinfo->ed > 0) { mincut += myrinfo->ed; myrinfo->inbr = cnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1); mynbrs = ctrl->cnbrpool + myrinfo->inbr; for (j=xadj[i]; jnnbrs; k++) { if (mynbrs[k].pid == other) { mynbrs[k].ed += adjwgt[j]; break; } } if (k == myrinfo->nnbrs) { mynbrs[k].pid = other; mynbrs[k].ed = adjwgt[j]; myrinfo->nnbrs++; } } } ASSERT(myrinfo->nnbrs <= xadj[i+1]-xadj[i]); /* Only ed-id>=0 nodes are considered to be in the boundary */ if (myrinfo->ed-myrinfo->id >= 0) BNDInsert(nbnd, bndind, bndptr, i); } else { myrinfo->inbr = -1; } } graph->mincut = mincut/2; graph->nbnd = nbnd; } ASSERT(CheckBnd2(graph)); break; case METIS_OBJTYPE_VOL: { vkrinfo_t *myrinfo; vnbr_t *mynbrs; memset(graph->vkrinfo, 0, sizeof(vkrinfo_t)*nvtxs); vnbrpoolReset(ctrl); /* Compute now the id/ed degrees */ for (i=0; ivkrinfo+i; for (j=xadj[i]; jnid++; else myrinfo->ned++; } /* Time to compute the particular external degrees */ if (myrinfo->ned > 0) { mincut += myrinfo->ned; myrinfo->inbr = vnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1); mynbrs = ctrl->vnbrpool + myrinfo->inbr; for (j=xadj[i]; jnnbrs; k++) { if (mynbrs[k].pid == other) { mynbrs[k].ned++; break; } } if (k == myrinfo->nnbrs) { mynbrs[k].gv = 0; mynbrs[k].pid = other; mynbrs[k].ned = 1; myrinfo->nnbrs++; } } } ASSERT(myrinfo->nnbrs <= xadj[i+1]-xadj[i]); } else { myrinfo->inbr = -1; } } graph->mincut = mincut/2; ComputeKWayVolGains(ctrl, graph); } ASSERT(graph->minvol == ComputeVolume(graph, graph->where)); break; default: gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); } } /*************************************************************************/ /*! This function projects a partition, and at the same time computes the parameters for refinement. */ /*************************************************************************/ void ProjectKWayPartition(ctrl_t *ctrl, graph_t *graph) { idx_t i, j, k, nvtxs, nbnd, nparts, me, other, istart, iend, tid, ted; idx_t *xadj, *adjncy, *adjwgt; idx_t *cmap, *where, *bndptr, *bndind, *cwhere, *htable; graph_t *cgraph; WCOREPUSH; nparts = ctrl->nparts; cgraph = graph->coarser; cwhere = cgraph->where; nvtxs = graph->nvtxs; cmap = graph->cmap; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; AllocateKWayPartitionMemory(ctrl, graph); where = graph->where; bndind = graph->bndind; bndptr = iset(nvtxs, -1, graph->bndptr); htable = iset(nparts, -1, iwspacemalloc(ctrl, nparts)); /* Compute the required info for refinement */ switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: ASSERT(CheckBnd2(cgraph)); { ckrinfo_t *myrinfo; cnbr_t *mynbrs; /* go through and project partition and compute id/ed for the nodes */ for (i=0; ickrinfo[k].ed; /* For optimization */ } memset(graph->ckrinfo, 0, sizeof(ckrinfo_t)*nvtxs); cnbrpoolReset(ctrl); for (nbnd=0, i=0; ickrinfo+i; if (cmap[i] == 0) { /* Interior node. Note that cmap[i] = crinfo[cmap[i]].ed */ for (tid=0, j=istart; jid = tid; myrinfo->inbr = -1; } else { /* Potentially an interface node */ myrinfo->inbr = cnbrpoolGetNext(ctrl, iend-istart+1); mynbrs = ctrl->cnbrpool + myrinfo->inbr; me = where[i]; for (tid=0, ted=0, j=istart; jnnbrs; mynbrs[myrinfo->nnbrs].pid = other; mynbrs[myrinfo->nnbrs++].ed = adjwgt[j]; } else { mynbrs[k].ed += adjwgt[j]; } } } myrinfo->id = tid; myrinfo->ed = ted; /* Remove space for edegrees if it was interior */ if (ted == 0) { ctrl->nbrpoolcpos -= iend-istart+1; myrinfo->inbr = -1; } else { if (ted-tid >= 0) BNDInsert(nbnd, bndind, bndptr, i); for (j=0; jnnbrs; j++) htable[mynbrs[j].pid] = -1; } } } graph->nbnd = nbnd; } ASSERT(CheckBnd2(graph)); break; case METIS_OBJTYPE_VOL: { vkrinfo_t *myrinfo; vnbr_t *mynbrs; ASSERT(cgraph->minvol == ComputeVolume(cgraph, cgraph->where)); /* go through and project partition and compute id/ed for the nodes */ for (i=0; ivkrinfo[k].ned; /* For optimization */ } memset(graph->vkrinfo, 0, sizeof(vkrinfo_t)*nvtxs); vnbrpoolReset(ctrl); for (i=0; ivkrinfo+i; if (cmap[i] == 0) { /* Note that cmap[i] = crinfo[cmap[i]].ed */ myrinfo->nid = iend-istart; myrinfo->inbr = -1; } else { /* Potentially an interface node */ myrinfo->inbr = vnbrpoolGetNext(ctrl, iend-istart+1); mynbrs = ctrl->vnbrpool + myrinfo->inbr; me = where[i]; for (tid=0, ted=0, j=istart; jnnbrs; mynbrs[myrinfo->nnbrs].gv = 0; mynbrs[myrinfo->nnbrs].pid = other; mynbrs[myrinfo->nnbrs++].ned = 1; } else { mynbrs[k].ned++; } } } myrinfo->nid = tid; myrinfo->ned = ted; /* Remove space for edegrees if it was interior */ if (ted == 0) { ctrl->nbrpoolcpos -= iend-istart+1; myrinfo->inbr = -1; } else { for (j=0; jnnbrs; j++) htable[mynbrs[j].pid] = -1; } } } ComputeKWayVolGains(ctrl, graph); ASSERT(graph->minvol == ComputeVolume(graph, graph->where)); } break; default: gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); } graph->mincut = cgraph->mincut; icopy(nparts*graph->ncon, cgraph->pwgts, graph->pwgts); FreeGraph(&graph->coarser); graph->coarser = NULL; WCOREPOP; } /*************************************************************************/ /*! This function computes the boundary definition for balancing. */ /*************************************************************************/ void ComputeKWayBoundary(ctrl_t *ctrl, graph_t *graph, idx_t bndtype) { idx_t i, nvtxs, nbnd; idx_t *bndind, *bndptr; nvtxs = graph->nvtxs; bndind = graph->bndind; bndptr = iset(nvtxs, -1, graph->bndptr); nbnd = 0; switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: /* Compute the boundary */ if (bndtype == BNDTYPE_REFINE) { for (i=0; ickrinfo[i].ed-graph->ckrinfo[i].id >= 0) BNDInsert(nbnd, bndind, bndptr, i); } } else { /* BNDTYPE_BALANCE */ for (i=0; ickrinfo[i].ed > 0) BNDInsert(nbnd, bndind, bndptr, i); } } break; case METIS_OBJTYPE_VOL: /* Compute the boundary */ if (bndtype == BNDTYPE_REFINE) { for (i=0; ivkrinfo[i].gv >= 0) BNDInsert(nbnd, bndind, bndptr, i); } } else { /* BNDTYPE_BALANCE */ for (i=0; ivkrinfo[i].ned > 0) BNDInsert(nbnd, bndind, bndptr, i); } } break; default: gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); } graph->nbnd = nbnd; } /*************************************************************************/ /*! This function computes the initial gains in the communication volume */ /*************************************************************************/ void ComputeKWayVolGains(ctrl_t *ctrl, graph_t *graph) { idx_t i, ii, j, k, nvtxs, nparts, me, other; idx_t *xadj, *vsize, *adjncy, *where, *bndind, *bndptr, *ophtable; vkrinfo_t *myrinfo, *orinfo; vnbr_t *mynbrs, *onbrs; WCOREPUSH; nparts = ctrl->nparts; nvtxs = graph->nvtxs; xadj = graph->xadj; vsize = graph->vsize; adjncy = graph->adjncy; where = graph->where; bndind = graph->bndind; bndptr = iset(nvtxs, -1, graph->bndptr); ophtable = iset(nparts, -1, iwspacemalloc(ctrl, nparts)); /* Compute the volume gains */ graph->minvol = graph->nbnd = 0; for (i=0; ivkrinfo+i; myrinfo->gv = IDX_MIN; if (myrinfo->nnbrs > 0) { me = where[i]; mynbrs = ctrl->vnbrpool + myrinfo->inbr; graph->minvol += myrinfo->nnbrs*vsize[i]; for (j=xadj[i]; jvkrinfo+ii; onbrs = ctrl->vnbrpool + orinfo->inbr; for (k=0; knnbrs; k++) ophtable[onbrs[k].pid] = k; ophtable[other] = 1; /* this is to simplify coding */ if (me == other) { /* Find which domains 'i' is connected to but 'ii' is not and update their gain */ for (k=0; knnbrs; k++) { if (ophtable[mynbrs[k].pid] == -1) mynbrs[k].gv -= vsize[ii]; } } else { ASSERT(ophtable[me] != -1); if (onbrs[ophtable[me]].ned == 1) { /* I'm the only connection of 'ii' in 'me' */ /* Increase the gains for all the common domains between 'i' and 'ii' */ for (k=0; knnbrs; k++) { if (ophtable[mynbrs[k].pid] != -1) mynbrs[k].gv += vsize[ii]; } } else { /* Find which domains 'i' is connected to and 'ii' is not and update their gain */ for (k=0; knnbrs; k++) { if (ophtable[mynbrs[k].pid] == -1) mynbrs[k].gv -= vsize[ii]; } } } /* Reset the marker vector */ for (k=0; knnbrs; k++) ophtable[onbrs[k].pid] = -1; ophtable[other] = -1; } /* Compute the max vgain */ for (k=0; knnbrs; k++) { if (mynbrs[k].gv > myrinfo->gv) myrinfo->gv = mynbrs[k].gv; } /* Add the extra gain due to id == 0 */ if (myrinfo->ned > 0 && myrinfo->nid == 0) myrinfo->gv += vsize[i]; } if (myrinfo->gv >= 0) BNDInsert(graph->nbnd, bndind, bndptr, i); } WCOREPOP; } /*************************************************************************/ /*! This function checks if the partition weights are within the balance contraints */ /*************************************************************************/ int IsBalanced(ctrl_t *ctrl, graph_t *graph, real_t ffactor) { return (ComputeLoadImbalanceDiff(graph, ctrl->nparts, ctrl->pijbm, ctrl->ubfactors) <= ffactor); } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/kmetis.c0000644000175100001440000001721514552244506024614 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file \brief The top-level routines for multilevel k-way partitioning that minimizes the edge cut. \date Started 7/28/1997 \author George \author Copyright 1997-2011, Regents of the University of Minnesota \version\verbatim $Id: kmetis.c 13905 2013-03-25 13:21:20Z karypis $ \endverbatim */ #include "metislib.h" /*************************************************************************/ /*! This function is the entry point for MCKMETIS */ /*************************************************************************/ int METIS_PartGraphKway(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt, idx_t *nparts, real_t *tpwgts, real_t *ubvec, idx_t *options, idx_t *objval, idx_t *part) { int sigrval=0, renumber=0; graph_t *graph; ctrl_t *ctrl; /* set up malloc cleaning code and signal catchers */ if (!gk_malloc_init()) return METIS_ERROR_MEMORY; gk_sigtrap(); if ((sigrval = gk_sigcatch()) != 0) goto SIGTHROW; /* set up the run parameters */ ctrl = SetupCtrl(METIS_OP_KMETIS, options, *ncon, *nparts, tpwgts, ubvec); if (!ctrl) { gk_siguntrap(); return METIS_ERROR_INPUT; } /* if required, change the numbering to 0 */ if (ctrl->numflag == 1) { Change2CNumbering(*nvtxs, xadj, adjncy); renumber = 1; } /* set up the graph */ graph = SetupGraph(ctrl, *nvtxs, *ncon, xadj, adjncy, vwgt, vsize, adjwgt); /* set up multipliers for making balance computations easier */ SetupKWayBalMultipliers(ctrl, graph); /* set various run parameters that depend on the graph */ ctrl->CoarsenTo = gk_max((*nvtxs)/(20*gk_log2(*nparts)), 30*(*nparts)); ctrl->nIparts = (ctrl->CoarsenTo == 30*(*nparts) ? 4 : 5); /* take care contiguity requests for disconnected graphs */ if (ctrl->contig && !IsConnected(graph, 0)) gk_errexit(SIGERR, "METIS Error: A contiguous partition is requested for a non-contiguous input graph.\n"); /* allocate workspace memory */ AllocateWorkSpace(ctrl, graph); /* start the partitioning */ IFSET(ctrl->dbglvl, METIS_DBG_TIME, InitTimers(ctrl)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->TotalTmr)); *objval = MlevelKWayPartitioning(ctrl, graph, part); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->TotalTmr)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, PrintTimers(ctrl)); /* clean up */ FreeCtrl(&ctrl); SIGTHROW: /* if required, change the numbering back to 1 */ if (renumber) Change2FNumbering(*nvtxs, xadj, adjncy, part); gk_siguntrap(); gk_malloc_cleanup(0); return metis_rcode(sigrval); } /*************************************************************************/ /*! This function computes a k-way partitioning of a graph that minimizes the specified objective function. \param ctrl is the control structure \param graph is the graph to be partitioned \param part is the vector that on return will store the partitioning \returns the objective value of the partitoning. The partitioning itself is stored in the part vector. */ /*************************************************************************/ idx_t MlevelKWayPartitioning(ctrl_t *ctrl, graph_t *graph, idx_t *part) { idx_t i, objval=0, curobj=0, bestobj=0; real_t curbal=0.0, bestbal=0.0; graph_t *cgraph; for (i=0; incuts; i++) { cgraph = CoarsenGraph(ctrl, graph); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->InitPartTmr)); AllocateKWayPartitionMemory(ctrl, cgraph); /* Release the work space */ FreeWorkSpace(ctrl); /* Compute the initial partitioning */ InitKWayPartitioning(ctrl, cgraph); /* Re-allocate the work space */ AllocateWorkSpace(ctrl, graph); AllocateRefinementWorkSpace(ctrl, 2*cgraph->nedges); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr)); IFSET(ctrl->dbglvl, METIS_DBG_IPART, printf("Initial %"PRIDX"-way partitioning cut: %"PRIDX"\n", ctrl->nparts, objval)); RefineKWay(ctrl, graph, cgraph); switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: curobj = graph->mincut; break; case METIS_OBJTYPE_VOL: curobj = graph->minvol; break; default: gk_errexit(SIGERR, "Unknown objtype: %d\n", ctrl->objtype); } curbal = ComputeLoadImbalanceDiff(graph, ctrl->nparts, ctrl->pijbm, ctrl->ubfactors); if (i == 0 || (curbal <= 0.0005 && bestobj > curobj) || (bestbal > 0.0005 && curbal < bestbal)) { icopy(graph->nvtxs, graph->where, part); bestobj = curobj; bestbal = curbal; } FreeRData(graph); if (bestobj == 0) break; } FreeGraph(&graph); return bestobj; } /*************************************************************************/ /*! This function computes the initial k-way partitioning using PMETIS */ /*************************************************************************/ void InitKWayPartitioning(ctrl_t *ctrl, graph_t *graph) { idx_t i, options[METIS_NOPTIONS], curobj=0; #ifdef XXX idx_t ntrials, bestobj=0; #endif idx_t *bestwhere=NULL; real_t *ubvec=NULL; int status; METIS_SetDefaultOptions(options); options[METIS_OPTION_NITER] = 10; options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT; options[METIS_OPTION_NO2HOP] = ctrl->no2hop; ubvec = rmalloc(graph->ncon, "InitKWayPartitioning: ubvec"); for (i=0; incon; i++) ubvec[i] = (real_t)pow(ctrl->ubfactors[i], 1.0/log(ctrl->nparts)); switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: case METIS_OBJTYPE_VOL: options[METIS_OPTION_NCUTS] = ctrl->nIparts; status = METIS_PartGraphRecursive(&graph->nvtxs, &graph->ncon, graph->xadj, graph->adjncy, graph->vwgt, graph->vsize, graph->adjwgt, &ctrl->nparts, ctrl->tpwgts, ubvec, options, &curobj, graph->where); if (status != METIS_OK) gk_errexit(SIGERR, "Failed during initial partitioning\n"); break; #ifdef XXX /* This does not seem to help */ case METIS_OBJTYPE_VOL: bestwhere = imalloc(graph->nvtxs, "InitKWayPartitioning: bestwhere"); options[METIS_OPTION_NCUTS] = 2; ntrials = (ctrl->nIparts+1)/2; for (i=0; invtxs, &graph->ncon, graph->xadj, graph->adjncy, graph->vwgt, graph->vsize, graph->adjwgt, &ctrl->nparts, ctrl->tpwgts, ubvec, options, &curobj, graph->where); if (status != METIS_OK) gk_errexit(SIGERR, "Failed during initial partitioning\n"); curobj = ComputeVolume(graph, graph->where); if (i == 0 || bestobj > curobj) { bestobj = curobj; if (i < ntrials-1) icopy(graph->nvtxs, graph->where, bestwhere); } if (bestobj == 0) break; } if (bestobj != curobj) icopy(graph->nvtxs, bestwhere, graph->where); break; #endif default: gk_errexit(SIGERR, "Unknown objtype: %d\n", ctrl->objtype); } gk_free((void **)&ubvec, &bestwhere, LTERM); } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/gklib_rename.h0000644000175100001440000001074314552244506025743 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file * Copyright 1997, Regents of the University of Minnesota * * This file contains header files * * Started 10/2/97 * George * * $Id: gklib_rename.h 10395 2011-06-23 23:28:06Z karypis $ * */ #ifndef _LIBMETIS_GKLIB_RENAME_H_ #define _LIBMETIS_GKLIB_RENAME_H_ /* gklib.c - generated from the .o files using the ./utils/listundescapedsumbols.csh */ #define iAllocMatrix libmetis__iAllocMatrix #define iFreeMatrix libmetis__iFreeMatrix #define iSetMatrix libmetis__iSetMatrix #define iargmax libmetis__iargmax #define iargmax_n libmetis__iargmax_n #define iargmin libmetis__iargmin #define iarray2csr libmetis__iarray2csr #define iaxpy libmetis__iaxpy #define icopy libmetis__icopy #define idot libmetis__idot #define iincset libmetis__iincset #define ikvAllocMatrix libmetis__ikvAllocMatrix #define ikvFreeMatrix libmetis__ikvFreeMatrix #define ikvSetMatrix libmetis__ikvSetMatrix #define ikvcopy libmetis__ikvcopy #define ikvmalloc libmetis__ikvmalloc #define ikvrealloc libmetis__ikvrealloc #define ikvset libmetis__ikvset #define ikvsmalloc libmetis__ikvsmalloc #define ikvsortd libmetis__ikvsortd #define ikvsorti libmetis__ikvsorti #define ikvsortii libmetis__ikvsortii #define imalloc libmetis__imalloc #define imax libmetis__imax #define imin libmetis__imin #define inorm2 libmetis__inorm2 #define ipqCheckHeap libmetis__ipqCheckHeap #define ipqCreate libmetis__ipqCreate #define ipqDelete libmetis__ipqDelete #define ipqDestroy libmetis__ipqDestroy #define ipqFree libmetis__ipqFree #define ipqGetTop libmetis__ipqGetTop #define ipqInit libmetis__ipqInit #define ipqInsert libmetis__ipqInsert #define ipqLength libmetis__ipqLength #define ipqReset libmetis__ipqReset #define ipqSeeKey libmetis__ipqSeeKey #define ipqSeeTopKey libmetis__ipqSeeTopKey #define ipqSeeTopVal libmetis__ipqSeeTopVal #define ipqUpdate libmetis__ipqUpdate #define isrand libmetis__isrand #define irand libmetis__irand #define irandArrayPermute libmetis__irandArrayPermute #define irandArrayPermuteFine libmetis__irandArrayPermuteFine #define irandInRange libmetis__irandInRange #define irealloc libmetis__irealloc #define iscale libmetis__iscale #define iset libmetis__iset #define ismalloc libmetis__ismalloc #define isortd libmetis__isortd #define isorti libmetis__isorti #define isrand libmetis__isrand #define isum libmetis__isum #define rAllocMatrix libmetis__rAllocMatrix #define rFreeMatrix libmetis__rFreeMatrix #define rSetMatrix libmetis__rSetMatrix #define rargmax libmetis__rargmax #define rargmax_n libmetis__rargmax_n #define rargmin libmetis__rargmin #define raxpy libmetis__raxpy #define rcopy libmetis__rcopy #define rdot libmetis__rdot #define rincset libmetis__rincset #define rkvAllocMatrix libmetis__rkvAllocMatrix #define rkvFreeMatrix libmetis__rkvFreeMatrix #define rkvSetMatrix libmetis__rkvSetMatrix #define rkvcopy libmetis__rkvcopy #define rkvmalloc libmetis__rkvmalloc #define rkvrealloc libmetis__rkvrealloc #define rkvset libmetis__rkvset #define rkvsmalloc libmetis__rkvsmalloc #define rkvsortd libmetis__rkvsortd #define rkvsorti libmetis__rkvsorti #define rmalloc libmetis__rmalloc #define rmax libmetis__rmax #define rmin libmetis__rmin #define rnorm2 libmetis__rnorm2 #define rpqCheckHeap libmetis__rpqCheckHeap #define rpqCreate libmetis__rpqCreate #define rpqDelete libmetis__rpqDelete #define rpqDestroy libmetis__rpqDestroy #define rpqFree libmetis__rpqFree #define rpqGetTop libmetis__rpqGetTop #define rpqInit libmetis__rpqInit #define rpqInsert libmetis__rpqInsert #define rpqLength libmetis__rpqLength #define rpqReset libmetis__rpqReset #define rpqSeeKey libmetis__rpqSeeKey #define rpqSeeTopKey libmetis__rpqSeeTopKey #define rpqSeeTopVal libmetis__rpqSeeTopVal #define rpqUpdate libmetis__rpqUpdate #define rrealloc libmetis__rrealloc #define rscale libmetis__rscale #define rset libmetis__rset #define rsmalloc libmetis__rsmalloc #define rsortd libmetis__rsortd #define rsorti libmetis__rsorti #define rsum libmetis__rsum #define uvwsorti libmetis__uvwsorti #endif Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/pmetis.c0000644000175100001440000003112714552244506024617 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /** \file \brief This file contains the top level routines for the multilevel recursive bisection algorithm PMETIS. \date Started 7/24/1997 \author George \author Copyright 1997-2009, Regents of the University of Minnesota \version\verbatim $Id: pmetis.c 10513 2011-07-07 22:06:03Z karypis $ \endverbatim */ #include "metislib.h" /*************************************************************************/ /*! \ingroup api \brief Recursive partitioning routine. This function computes a partitioning of a graph based on multilevel recursive bisection. It can be used to partition a graph into \e k parts. The objective of the partitioning is to minimize the edgecut subject to one or more balancing constraints. \param[in] nvtxs is the number of vertices in the graph. \param[in] ncon is the number of balancing constraints. For the standard partitioning problem in which each vertex is either unweighted or has a single weight, ncon should be 1. \param[in] xadj is an array of size nvtxs+1 used to specify the starting positions of the adjacency structure of the vertices in the adjncy array. \param[in] adjncy is an array of size to the sum of the degrees of the graph that stores for each vertex the set of vertices that is adjancent to. \param[in] vwgt is an array of size nvtxs*ncon that stores the weights of the vertices for each constraint. The ncon weights for the ith vertex are stored in the ncon consecutive locations starting at vwgt[i*ncon]. When ncon==1, a NULL value can be passed indicating that all the vertices in the graph have the same weight. \param[in] adjwgt is an array of size equal to adjncy, specifying the weight for each edge (i.e., adjwgt[j] corresponds to the weight of the edge stored in adjncy[j]). A NULL value can be passed indicating that all the edges in the graph have the same weight. \param[in] nparts is the number of desired partitions. \param[in] tpwgts is an array of size nparts*ncon that specifies the desired weight for each part and constraint. The \e{target partition weight} for the ith part and jth constraint is specified at tpwgts[i*ncon+j] (the numbering of i and j starts from 0). For each constraint, the sum of the tpwgts[] entries must be 1.0 (i.e., \f$ \sum_i tpwgts[i*ncon+j] = 1.0 \f$). A NULL value can be passed indicating that the graph should be equally divided among the parts. \param[in] ubvec is an array of size ncon that specifies the allowed load imbalance tolerance for each constraint. For the ith part and jth constraint the allowed weight is the ubvec[j]*tpwgts[i*ncon+j] fraction of the jth's constraint total weight. The load imbalances must be greater than 1.0. A NULL value can be passed indicating that the load imbalance tolerance for each constraint should be 1.001 (for ncon==1) or 1.01 (for ncon>1). \params[in] options is the array for passing additional parameters in order to customize the behaviour of the partitioning algorithm. \params[out] edgecut stores the cut of the partitioning. \params[out] part is an array of size nvtxs used to store the computed partitioning. The partition number for the ith vertex is stored in part[i]. Based on the numflag parameter, the numbering of the parts starts from either 0 or 1. \returns \retval METIS_OK indicates that the function returned normally. \retval METIS_ERROR_INPUT indicates an input error. \retval METIS_ERROR_MEMORY indicates that it could not allocate the required memory. */ /*************************************************************************/ int METIS_PartGraphRecursive(idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt, idx_t *nparts, real_t *tpwgts, real_t *ubvec, idx_t *options, idx_t *objval, idx_t *part) { int sigrval=0, renumber=0; graph_t *graph; ctrl_t *ctrl; /* set up malloc cleaning code and signal catchers */ if (!gk_malloc_init()) return METIS_ERROR_MEMORY; gk_sigtrap(); if ((sigrval = gk_sigcatch()) != 0) goto SIGTHROW; /* set up the run parameters */ ctrl = SetupCtrl(METIS_OP_PMETIS, options, *ncon, *nparts, tpwgts, ubvec); if (!ctrl) { gk_siguntrap(); return METIS_ERROR_INPUT; } /* if required, change the numbering to 0 */ if (ctrl->numflag == 1) { Change2CNumbering(*nvtxs, xadj, adjncy); renumber = 1; } /* set up the graph */ graph = SetupGraph(ctrl, *nvtxs, *ncon, xadj, adjncy, vwgt, vsize, adjwgt); /* allocate workspace memory */ AllocateWorkSpace(ctrl, graph); /* start the partitioning */ IFSET(ctrl->dbglvl, METIS_DBG_TIME, InitTimers(ctrl)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->TotalTmr)); *objval = MlevelRecursiveBisection(ctrl, graph, *nparts, part, ctrl->tpwgts, 0); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->TotalTmr)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, PrintTimers(ctrl)); /* clean up */ FreeCtrl(&ctrl); SIGTHROW: /* if required, change the numbering back to 1 */ if (renumber) Change2FNumbering(*nvtxs, xadj, adjncy, part); gk_siguntrap(); gk_malloc_cleanup(0); return metis_rcode(sigrval); } /*************************************************************************/ /*! This function is the top-level driver of the recursive bisection routine. */ /*************************************************************************/ idx_t MlevelRecursiveBisection(ctrl_t *ctrl, graph_t *graph, idx_t nparts, idx_t *part, real_t *tpwgts, idx_t fpart) { idx_t i, nvtxs, ncon, objval; idx_t *label, *where; graph_t *lgraph, *rgraph; real_t wsum, *tpwgts2; if ((nvtxs = graph->nvtxs) == 0) { printf("\t***Cannot bisect a graph with 0 vertices!\n" "\t***You are trying to partition a graph into too many parts!\n"); return 0; } ncon = graph->ncon; /* determine the weights of the two partitions as a function of the weight of the target partition weights */ WCOREPUSH; tpwgts2 = rwspacemalloc(ctrl, 2*ncon); for (i=0; i>1), tpwgts+i, ncon); tpwgts2[ncon+i] = 1.0 - tpwgts2[i]; } /* perform the bisection */ objval = MultilevelBisect(ctrl, graph, tpwgts2); WCOREPOP; label = graph->label; where = graph->where; for (i=0; i 2) SplitGraphPart(ctrl, graph, &lgraph, &rgraph); /* Free the memory of the top level graph */ FreeGraph(&graph); /* Scale the fractions in the tpwgts according to the true weight */ for (i=0; i>1), tpwgts+i, ncon); rscale((nparts>>1), 1.0/wsum, tpwgts+i, ncon); rscale(nparts-(nparts>>1), 1.0/(1.0-wsum), tpwgts+(nparts>>1)*ncon+i, ncon); } /* Do the recursive call */ if (nparts > 3) { objval += MlevelRecursiveBisection(ctrl, lgraph, (nparts>>1), part, tpwgts, fpart); objval += MlevelRecursiveBisection(ctrl, rgraph, nparts-(nparts>>1), part, tpwgts+(nparts>>1)*ncon, fpart+(nparts>>1)); } else if (nparts == 3) { FreeGraph(&lgraph); objval += MlevelRecursiveBisection(ctrl, rgraph, nparts-(nparts>>1), part, tpwgts+(nparts>>1)*ncon, fpart+(nparts>>1)); } return objval; } /*************************************************************************/ /*! This function performs a multilevel bisection */ /*************************************************************************/ idx_t MultilevelBisect(ctrl_t *ctrl, graph_t *graph, real_t *tpwgts) { idx_t i, niparts, bestobj=0, curobj=0, *bestwhere=NULL; graph_t *cgraph; real_t bestbal=0.0, curbal=0.0; Setup2WayBalMultipliers(ctrl, graph, tpwgts); WCOREPUSH; if (ctrl->ncuts > 1) bestwhere = iwspacemalloc(ctrl, graph->nvtxs); for (i=0; incuts; i++) { cgraph = CoarsenGraph(ctrl, graph); niparts = (cgraph->nvtxs <= ctrl->CoarsenTo ? SMALLNIPARTS : LARGENIPARTS); Init2WayPartition(ctrl, cgraph, tpwgts, niparts); Refine2Way(ctrl, graph, cgraph, tpwgts); curobj = graph->mincut; curbal = ComputeLoadImbalanceDiff(graph, 2, ctrl->pijbm, ctrl->ubfactors); if (i == 0 || (curbal <= 0.0005 && bestobj > curobj) || (bestbal > 0.0005 && curbal < bestbal)) { bestobj = curobj; bestbal = curbal; if (i < ctrl->ncuts-1) icopy(graph->nvtxs, graph->where, bestwhere); } if (bestobj == 0) break; if (i < ctrl->ncuts-1) FreeRData(graph); } if (bestobj != curobj) { icopy(graph->nvtxs, bestwhere, graph->where); Compute2WayPartitionParams(ctrl, graph); } WCOREPOP; return bestobj; } /*************************************************************************/ /*! This function splits a graph into two based on its bisection */ /*************************************************************************/ void SplitGraphPart(ctrl_t *ctrl, graph_t *graph, graph_t **r_lgraph, graph_t **r_rgraph) { idx_t i, j, k, l, istart, iend, mypart, nvtxs, ncon, snvtxs[2], snedges[2]; idx_t *xadj, *vwgt, *adjncy, *adjwgt, *label, *where, *bndptr; idx_t *sxadj[2], *svwgt[2], *sadjncy[2], *sadjwgt[2], *slabel[2]; idx_t *rename; idx_t *auxadjncy, *auxadjwgt; graph_t *lgraph, *rgraph; WCOREPUSH; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->SplitTmr)); nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; label = graph->label; where = graph->where; bndptr = graph->bndptr; ASSERT(bndptr != NULL); rename = iwspacemalloc(ctrl, nvtxs); snvtxs[0] = snvtxs[1] = snedges[0] = snedges[1] = 0; for (i=0; ixadj; svwgt[0] = lgraph->vwgt; sadjncy[0] = lgraph->adjncy; sadjwgt[0] = lgraph->adjwgt; slabel[0] = lgraph->label; rgraph = SetupSplitGraph(graph, snvtxs[1], snedges[1]); sxadj[1] = rgraph->xadj; svwgt[1] = rgraph->vwgt; sadjncy[1] = rgraph->adjncy; sadjwgt[1] = rgraph->adjwgt; slabel[1] = rgraph->label; snvtxs[0] = snvtxs[1] = snedges[0] = snedges[1] = 0; sxadj[0][0] = sxadj[1][0] = 0; for (i=0; inedges = snedges[0]; rgraph->nedges = snedges[1]; SetupGraph_tvwgt(lgraph); SetupGraph_tvwgt(rgraph); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->SplitTmr)); *r_lgraph = lgraph; *r_rgraph = rgraph; WCOREPOP; } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/auxapi.c0000644000175100001440000000322514552244506024603 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /** \file \brief This file contains various helper API routines for using METIS. \date Started 5/12/2011 \author George \author Copyright 1997-2009, Regents of the University of Minnesota \version\verbatim $Id: auxapi.c 10409 2011-06-25 16:58:34Z karypis $ \endverbatim */ #include "metislib.h" /*************************************************************************/ /*! This function free memory that was allocated by METIS and retuned to the application. \param ptr points to the memory that was previously allocated by METIS. */ /*************************************************************************/ int METIS_Free(void *ptr) { if (ptr != NULL) free(ptr); return METIS_OK; } /*************************************************************************/ /*! This function sets the default values for the options. \param options points to an array of size at least METIS_NOPTIONS. */ /*************************************************************************/ int METIS_SetDefaultOptions(idx_t *options) { iset(METIS_NOPTIONS, -1, options); return METIS_OK; } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/mmd.c0000644000175100001440000005235714552244506024103 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * mmd.c * * ************************************************************** * The following C function was developed from a FORTRAN subroutine * in SPARSPAK written by Eleanor Chu, Alan George, Joseph Liu * and Esmond Ng. * * The FORTRAN-to-C transformation and modifications such as dynamic * memory allocation and deallocation were performed by Chunguang * Sun. * ************************************************************** * * Taken from SMMS, George 12/13/94 * * The meaning of invperm, and perm vectors is different from that * in genqmd_ of SparsPak * * $Id: mmd.c 5993 2009-01-07 02:09:57Z karypis $ */ #include "metislib.h" /************************************************************************* * genmmd -- multiple minimum external degree * purpose -- this routine implements the minimum degree * algorithm. it makes use of the implicit representation * of elimination graphs by quotient graphs, and the notion * of indistinguishable nodes. It also implements the modifications * by multiple elimination and minimum external degree. * Caution -- the adjacency vector adjncy will be destroyed. * Input parameters -- * neqns -- number of equations. * (xadj, adjncy) -- the adjacency structure. * delta -- tolerance value for multiple elimination. * maxint -- maximum machine representable (short) integer * (any smaller estimate will do) for marking nodes. * Output parameters -- * perm -- the minimum degree ordering. * invp -- the inverse of perm. * *ncsub -- an upper bound on the number of nonzero subscripts * for the compressed storage scheme. * Working parameters -- * head -- vector for head of degree lists. * invp -- used temporarily for degree forward link. * perm -- used temporarily for degree backward link. * qsize -- vector for size of supernodes. * list -- vector for temporary linked lists. * marker -- a temporary marker vector. * Subroutines used -- mmdelm, mmdint, mmdnum, mmdupd. **************************************************************************/ void genmmd(idx_t neqns, idx_t *xadj, idx_t *adjncy, idx_t *invp, idx_t *perm, idx_t delta, idx_t *head, idx_t *qsize, idx_t *list, idx_t *marker, idx_t maxint, idx_t *ncsub) { idx_t ehead, i, mdeg, mdlmt, mdeg_node, nextmd, num, tag; if (neqns <= 0) return; /* Adjust from C to Fortran */ xadj--; adjncy--; invp--; perm--; head--; qsize--; list--; marker--; /* initialization for the minimum degree algorithm. */ *ncsub = 0; mmdint(neqns, xadj, adjncy, head, invp, perm, qsize, list, marker); /* 'num' counts the number of ordered nodes plus 1. */ num = 1; /* eliminate all isolated nodes. */ nextmd = head[1]; while (nextmd > 0) { mdeg_node = nextmd; nextmd = invp[mdeg_node]; marker[mdeg_node] = maxint; invp[mdeg_node] = -num; num = num + 1; } /* search for node of the minimum degree. 'mdeg' is the current */ /* minimum degree; 'tag' is used to facilitate marking nodes. */ if (num > neqns) goto n1000; tag = 1; head[1] = 0; mdeg = 2; /* infinite loop here ! */ while (1) { while (head[mdeg] <= 0) mdeg++; /* use value of 'delta' to set up 'mdlmt', which governs */ /* when a degree update is to be performed. */ mdlmt = mdeg + delta; ehead = 0; n500: mdeg_node = head[mdeg]; while (mdeg_node <= 0) { mdeg++; if (mdeg > mdlmt) goto n900; mdeg_node = head[mdeg]; }; /* remove 'mdeg_node' from the degree structure. */ nextmd = invp[mdeg_node]; head[mdeg] = nextmd; if (nextmd > 0) perm[nextmd] = -mdeg; invp[mdeg_node] = -num; *ncsub += mdeg + qsize[mdeg_node] - 2; if ((num+qsize[mdeg_node]) > neqns) goto n1000; /* eliminate 'mdeg_node' and perform quotient graph */ /* transformation. reset 'tag' value if necessary. */ tag++; if (tag >= maxint) { tag = 1; for (i = 1; i <= neqns; i++) if (marker[i] < maxint) marker[i] = 0; }; mmdelm(mdeg_node, xadj, adjncy, head, invp, perm, qsize, list, marker, maxint, tag); num += qsize[mdeg_node]; list[mdeg_node] = ehead; ehead = mdeg_node; if (delta >= 0) goto n500; n900: /* update degrees of the nodes involved in the */ /* minimum degree nodes elimination. */ if (num > neqns) goto n1000; mmdupd( ehead, neqns, xadj, adjncy, delta, &mdeg, head, invp, perm, qsize, list, marker, maxint, &tag); }; /* end of -- while ( 1 ) -- */ n1000: mmdnum( neqns, perm, invp, qsize ); /* Adjust from Fortran back to C*/ xadj++; adjncy++; invp++; perm++; head++; qsize++; list++; marker++; } /************************************************************************** * mmdelm ...... multiple minimum degree elimination * Purpose -- This routine eliminates the node mdeg_node of minimum degree * from the adjacency structure, which is stored in the quotient * graph format. It also transforms the quotient graph representation * of the elimination graph. * Input parameters -- * mdeg_node -- node of minimum degree. * maxint -- estimate of maximum representable (short) integer. * tag -- tag value. * Updated parameters -- * (xadj, adjncy) -- updated adjacency structure. * (head, forward, backward) -- degree doubly linked structure. * qsize -- size of supernode. * marker -- marker vector. * list -- temporary linked list of eliminated nabors. ***************************************************************************/ void mmdelm(idx_t mdeg_node, idx_t *xadj, idx_t *adjncy, idx_t *head, idx_t *forward, idx_t *backward, idx_t *qsize, idx_t *list, idx_t *marker, idx_t maxint, idx_t tag) { idx_t element, i, istop, istart, j, jstop, jstart, link, nabor, node, npv, nqnbrs, nxnode, pvnode, rlmt, rloc, rnode, xqnbr; /* find the reachable set of 'mdeg_node' and */ /* place it in the data structure. */ marker[mdeg_node] = tag; istart = xadj[mdeg_node]; istop = xadj[mdeg_node+1] - 1; /* 'element' points to the beginning of the list of */ /* eliminated nabors of 'mdeg_node', and 'rloc' gives the */ /* storage location for the next reachable node. */ element = 0; rloc = istart; rlmt = istop; for ( i = istart; i <= istop; i++ ) { nabor = adjncy[i]; if ( nabor == 0 ) break; if ( marker[nabor] < tag ) { marker[nabor] = tag; if ( forward[nabor] < 0 ) { list[nabor] = element; element = nabor; } else { adjncy[rloc] = nabor; rloc++; }; }; /* end of -- if -- */ }; /* end of -- for -- */ /* merge with reachable nodes from generalized elements. */ while ( element > 0 ) { adjncy[rlmt] = -element; link = element; n400: jstart = xadj[link]; jstop = xadj[link+1] - 1; for ( j = jstart; j <= jstop; j++ ) { node = adjncy[j]; link = -node; if ( node < 0 ) goto n400; if ( node == 0 ) break; if ((marker[node]=0)) { marker[node] = tag; /*use storage from eliminated nodes if necessary.*/ while ( rloc >= rlmt ) { link = -adjncy[rlmt]; rloc = xadj[link]; rlmt = xadj[link+1] - 1; }; adjncy[rloc] = node; rloc++; }; }; /* end of -- for ( j = jstart; -- */ element = list[element]; }; /* end of -- while ( element > 0 ) -- */ if ( rloc <= rlmt ) adjncy[rloc] = 0; /* for each node in the reachable set, do the following. */ link = mdeg_node; n1100: istart = xadj[link]; istop = xadj[link+1] - 1; for ( i = istart; i <= istop; i++ ) { rnode = adjncy[i]; link = -rnode; if ( rnode < 0 ) goto n1100; if ( rnode == 0 ) return; /* 'rnode' is in the degree list structure. */ pvnode = backward[rnode]; if (( pvnode != 0 ) && ( pvnode != (-maxint) )) { /* then remove 'rnode' from the structure. */ nxnode = forward[rnode]; if ( nxnode > 0 ) backward[nxnode] = pvnode; if ( pvnode > 0 ) forward[pvnode] = nxnode; npv = -pvnode; if ( pvnode < 0 ) head[npv] = nxnode; }; /* purge inactive quotient nabors of 'rnode'. */ jstart = xadj[rnode]; jstop = xadj[rnode+1] - 1; xqnbr = jstart; for ( j = jstart; j <= jstop; j++ ) { nabor = adjncy[j]; if ( nabor == 0 ) break; if ( marker[nabor] < tag ) { adjncy[xqnbr] = nabor; xqnbr++; }; }; /* no active nabor after the purging. */ nqnbrs = xqnbr - jstart; if ( nqnbrs <= 0 ) { /* merge 'rnode' with 'mdeg_node'. */ qsize[mdeg_node] += qsize[rnode]; qsize[rnode] = 0; marker[rnode] = maxint; forward[rnode] = -mdeg_node; backward[rnode] = -maxint; } else { /* flag 'rnode' for degree update, and */ /* add 'mdeg_node' as a nabor of 'rnode'. */ forward[rnode] = nqnbrs + 1; backward[rnode] = 0; adjncy[xqnbr] = mdeg_node; xqnbr++; if ( xqnbr <= jstop ) adjncy[xqnbr] = 0; }; }; /* end of -- for ( i = istart; -- */ return; } /*************************************************************************** * mmdint ---- mult minimum degree initialization * purpose -- this routine performs initialization for the * multiple elimination version of the minimum degree algorithm. * input parameters -- * neqns -- number of equations. * (xadj, adjncy) -- adjacency structure. * output parameters -- * (head, dfrow, backward) -- degree doubly linked structure. * qsize -- size of supernode ( initialized to one). * list -- linked list. * marker -- marker vector. ****************************************************************************/ idx_t mmdint(idx_t neqns, idx_t *xadj, idx_t *adjncy, idx_t *head, idx_t *forward, idx_t *backward, idx_t *qsize, idx_t *list, idx_t *marker) { idx_t fnode, ndeg, node; for ( node = 1; node <= neqns; node++ ) { head[node] = 0; qsize[node] = 1; marker[node] = 0; list[node] = 0; }; /* initialize the degree doubly linked lists. */ for ( node = 1; node <= neqns; node++ ) { ndeg = xadj[node+1] - xadj[node]/* + 1*/; /* george */ if (ndeg == 0) ndeg = 1; fnode = head[ndeg]; forward[node] = fnode; head[ndeg] = node; if ( fnode > 0 ) backward[fnode] = node; backward[node] = -ndeg; }; return 0; } /**************************************************************************** * mmdnum --- multi minimum degree numbering * purpose -- this routine performs the final step in producing * the permutation and inverse permutation vectors in the * multiple elimination version of the minimum degree * ordering algorithm. * input parameters -- * neqns -- number of equations. * qsize -- size of supernodes at elimination. * updated parameters -- * invp -- inverse permutation vector. on input, * if qsize[node] = 0, then node has been merged * into the node -invp[node]; otherwise, * -invp[node] is its inverse labelling. * output parameters -- * perm -- the permutation vector. ****************************************************************************/ void mmdnum(idx_t neqns, idx_t *perm, idx_t *invp, idx_t *qsize) { idx_t father, nextf, node, nqsize, num, root; for ( node = 1; node <= neqns; node++ ) { nqsize = qsize[node]; if ( nqsize <= 0 ) perm[node] = invp[node]; if ( nqsize > 0 ) perm[node] = -invp[node]; }; /* for each node which has been merged, do the following. */ for ( node = 1; node <= neqns; node++ ) { if ( perm[node] <= 0 ) { /* trace the merged tree until one which has not */ /* been merged, call it root. */ father = node; while ( perm[father] <= 0 ) father = - perm[father]; /* number node after root. */ root = father; num = perm[root] + 1; invp[node] = -num; perm[root] = num; /* shorten the merged tree. */ father = node; nextf = - perm[father]; while ( nextf > 0 ) { perm[father] = -root; father = nextf; nextf = -perm[father]; }; }; /* end of -- if ( perm[node] <= 0 ) -- */ }; /* end of -- for ( node = 1; -- */ /* ready to compute perm. */ for ( node = 1; node <= neqns; node++ ) { num = -invp[node]; invp[node] = num; perm[num] = node; }; return; } /**************************************************************************** * mmdupd ---- multiple minimum degree update * purpose -- this routine updates the degrees of nodes after a * multiple elimination step. * input parameters -- * ehead -- the beginning of the list of eliminated nodes * (i.e., newly formed elements). * neqns -- number of equations. * (xadj, adjncy) -- adjacency structure. * delta -- tolerance value for multiple elimination. * maxint -- maximum machine representable (short) integer. * updated parameters -- * mdeg -- new minimum degree after degree update. * (head, forward, backward) -- degree doubly linked structure. * qsize -- size of supernode. * list -- marker vector for degree update. * *tag -- tag value. ****************************************************************************/ void mmdupd(idx_t ehead, idx_t neqns, idx_t *xadj, idx_t *adjncy, idx_t delta, idx_t *mdeg, idx_t *head, idx_t *forward, idx_t *backward, idx_t *qsize, idx_t *list, idx_t *marker, idx_t maxint, idx_t *tag) { idx_t deg, deg0, element, enode, fnode, i, iq2, istop, istart, j, jstop, jstart, link, mdeg0, mtag, nabor, node, q2head, qxhead; mdeg0 = *mdeg + delta; element = ehead; n100: if ( element <= 0 ) return; /* for each of the newly formed element, do the following. */ /* reset tag value if necessary. */ mtag = *tag + mdeg0; if ( mtag >= maxint ) { *tag = 1; for ( i = 1; i <= neqns; i++ ) if ( marker[i] < maxint ) marker[i] = 0; mtag = *tag + mdeg0; }; /* create two linked lists from nodes associated with 'element': */ /* one with two nabors (q2head) in the adjacency structure, and the*/ /* other with more than two nabors (qxhead). also compute 'deg0',*/ /* number of nodes in this element. */ q2head = 0; qxhead = 0; deg0 = 0; link =element; n400: istart = xadj[link]; istop = xadj[link+1] - 1; for ( i = istart; i <= istop; i++ ) { enode = adjncy[i]; link = -enode; if ( enode < 0 ) goto n400; if ( enode == 0 ) break; if ( qsize[enode] != 0 ) { deg0 += qsize[enode]; marker[enode] = mtag; /*'enode' requires a degree update*/ if ( backward[enode] == 0 ) { /* place either in qxhead or q2head list. */ if ( forward[enode] != 2 ) { list[enode] = qxhead; qxhead = enode; } else { list[enode] = q2head; q2head = enode; }; }; }; /* enf of -- if ( qsize[enode] != 0 ) -- */ }; /* end of -- for ( i = istart; -- */ /* for each node in q2 list, do the following. */ enode = q2head; iq2 = 1; n900: if ( enode <= 0 ) goto n1500; if ( backward[enode] != 0 ) goto n2200; (*tag)++; deg = deg0; /* identify the other adjacent element nabor. */ istart = xadj[enode]; nabor = adjncy[istart]; if ( nabor == element ) nabor = adjncy[istart+1]; link = nabor; if ( forward[nabor] >= 0 ) { /* nabor is uneliminated, increase degree count. */ deg += qsize[nabor]; goto n2100; }; /* the nabor is eliminated. for each node in the 2nd element */ /* do the following. */ n1000: istart = xadj[link]; istop = xadj[link+1] - 1; for ( i = istart; i <= istop; i++ ) { node = adjncy[i]; link = -node; if ( node != enode ) { if ( node < 0 ) goto n1000; if ( node == 0 ) goto n2100; if ( qsize[node] != 0 ) { if ( marker[node] < *tag ) { /* 'node' is not yet considered. */ marker[node] = *tag; deg += qsize[node]; } else { if ( backward[node] == 0 ) { if ( forward[node] == 2 ) { /* 'node' is indistinguishable from 'enode'.*/ /* merge them into a new supernode. */ qsize[enode] += qsize[node]; qsize[node] = 0; marker[node] = maxint; forward[node] = -enode; backward[node] = -maxint; } else { /* 'node' is outmacthed by 'enode' */ if (backward[node]==0) backward[node] = -maxint; }; }; /* end of -- if ( backward[node] == 0 ) -- */ }; /* end of -- if ( marker[node] < *tag ) -- */ }; /* end of -- if ( qsize[node] != 0 ) -- */ }; /* end of -- if ( node != enode ) -- */ }; /* end of -- for ( i = istart; -- */ goto n2100; n1500: /* for each 'enode' in the 'qx' list, do the following. */ enode = qxhead; iq2 = 0; n1600: if ( enode <= 0 ) goto n2300; if ( backward[enode] != 0 ) goto n2200; (*tag)++; deg = deg0; /*for each unmarked nabor of 'enode', do the following.*/ istart = xadj[enode]; istop = xadj[enode+1] - 1; for ( i = istart; i <= istop; i++ ) { nabor = adjncy[i]; if ( nabor == 0 ) break; if ( marker[nabor] < *tag ) { marker[nabor] = *tag; link = nabor; if ( forward[nabor] >= 0 ) /*if uneliminated, include it in deg count.*/ deg += qsize[nabor]; else { n1700: /* if eliminated, include unmarked nodes in this*/ /* element into the degree count. */ jstart = xadj[link]; jstop = xadj[link+1] - 1; for ( j = jstart; j <= jstop; j++ ) { node = adjncy[j]; link = -node; if ( node < 0 ) goto n1700; if ( node == 0 ) break; if ( marker[node] < *tag ) { marker[node] = *tag; deg += qsize[node]; }; }; /* end of -- for ( j = jstart; -- */ }; /* end of -- if ( forward[nabor] >= 0 ) -- */ }; /* end of -- if ( marker[nabor] < *tag ) -- */ }; /* end of -- for ( i = istart; -- */ n2100: /* update external degree of 'enode' in degree structure, */ /* and '*mdeg' if necessary. */ deg = deg - qsize[enode] + 1; fnode = head[deg]; forward[enode] = fnode; backward[enode] = -deg; if ( fnode > 0 ) backward[fnode] = enode; head[deg] = enode; if ( deg < *mdeg ) *mdeg = deg; n2200: /* get next enode in current element. */ enode = list[enode]; if ( iq2 == 1 ) goto n900; goto n1600; n2300: /* get next element in the list. */ *tag = mtag; element = list[element]; goto n100; } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/coarsen.c0000644000175100001440000010102614552244506024744 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file \brief Functions for computing matchings during graph coarsening \date Started 7/23/97 \author George \author Copyright 1997-2011, Regents of the University of Minnesota \version\verbatim $Id: coarsen.c 13936 2013-03-30 03:59:09Z karypis $ \endverbatim */ #include "metislib.h" #define UNMATCHEDFOR2HOP 0.10 /* The fraction of unmatched vertices that triggers 2-hop */ /*************************************************************************/ /*! This function takes a graph and creates a sequence of coarser graphs. It implements the coarsening phase of the multilevel paradigm. */ /*************************************************************************/ graph_t *CoarsenGraph(ctrl_t *ctrl, graph_t *graph) { idx_t i, eqewgts; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->CoarsenTmr)); /* determine if the weights on the edges are all the same */ for (eqewgts=1, i=1; inedges; i++) { if (graph->adjwgt[0] != graph->adjwgt[i]) { eqewgts = 0; break; } } /* set the maximum allowed coarsest vertex weight */ for (i=0; incon; i++) ctrl->maxvwgt[i] = 1.5*graph->tvwgt[i]/ctrl->CoarsenTo; do { IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, PrintCGraphStats(ctrl, graph)); /* allocate memory for cmap, if it has not already been done due to multiple cuts */ if (graph->cmap == NULL) graph->cmap = imalloc(graph->nvtxs, "CoarsenGraph: graph->cmap"); /* determine which matching scheme you will use */ switch (ctrl->ctype) { case METIS_CTYPE_RM: Match_RM(ctrl, graph); break; case METIS_CTYPE_SHEM: if (eqewgts || graph->nedges == 0) Match_RM(ctrl, graph); else Match_SHEM(ctrl, graph); break; default: gk_errexit(SIGERR, "Unknown ctype: %d\n", ctrl->ctype); } graph = graph->coarser; eqewgts = 0; ASSERT(CheckGraph(graph, 0, 1)); } while (graph->nvtxs > ctrl->CoarsenTo && graph->nvtxs < COARSEN_FRACTION*graph->finer->nvtxs && graph->nedges > graph->nvtxs/2); IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, PrintCGraphStats(ctrl, graph)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->CoarsenTmr)); return graph; } /*************************************************************************/ /*! This function takes a graph and creates a sequence of nlevels coarser graphs, where nlevels is an input parameter. */ /*************************************************************************/ graph_t *CoarsenGraphNlevels(ctrl_t *ctrl, graph_t *graph, idx_t nlevels) { idx_t i, eqewgts, level; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->CoarsenTmr)); /* determine if the weights on the edges are all the same */ for (eqewgts=1, i=1; inedges; i++) { if (graph->adjwgt[0] != graph->adjwgt[i]) { eqewgts = 0; break; } } /* set the maximum allowed coarsest vertex weight */ for (i=0; incon; i++) ctrl->maxvwgt[i] = 1.5*graph->tvwgt[i]/ctrl->CoarsenTo; for (level=0; leveldbglvl, METIS_DBG_COARSEN, PrintCGraphStats(ctrl, graph)); /* allocate memory for cmap, if it has not already been done due to multiple cuts */ if (graph->cmap == NULL) graph->cmap = imalloc(graph->nvtxs, "CoarsenGraph: graph->cmap"); /* determine which matching scheme you will use */ switch (ctrl->ctype) { case METIS_CTYPE_RM: Match_RM(ctrl, graph); break; case METIS_CTYPE_SHEM: if (eqewgts || graph->nedges == 0) Match_RM(ctrl, graph); else Match_SHEM(ctrl, graph); break; default: gk_errexit(SIGERR, "Unknown ctype: %d\n", ctrl->ctype); } graph = graph->coarser; eqewgts = 0; ASSERT(CheckGraph(graph, 0, 1)); if (graph->nvtxs < ctrl->CoarsenTo || graph->nvtxs > COARSEN_FRACTION*graph->finer->nvtxs || graph->nedges < graph->nvtxs/2) break; } IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, PrintCGraphStats(ctrl, graph)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->CoarsenTmr)); return graph; } /*************************************************************************/ /*! This function finds a matching by randomly selecting one of the unmatched adjacent vertices. */ /**************************************************************************/ idx_t Match_RM(ctrl_t *ctrl, graph_t *graph) { idx_t i, pi, j, k, nvtxs, ncon, cnvtxs, maxidx, last_unmatched; idx_t *xadj, *vwgt, *adjncy, *maxvwgt; idx_t *match, *cmap, *perm; size_t nunmatched=0; WCOREPUSH; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->MatchTmr)); nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; cmap = graph->cmap; maxvwgt = ctrl->maxvwgt; match = iset(nvtxs, UNMATCHED, iwspacemalloc(ctrl, nvtxs)); perm = iwspacemalloc(ctrl, nvtxs); irandArrayPermute(nvtxs, perm, nvtxs/8, 1); for (cnvtxs=0, last_unmatched=0, pi=0; pimaxvwgt requirements */ if (xadj[i] == xadj[i+1]) { last_unmatched = gk_max(pi, last_unmatched)+1; for (; last_unmatchedno2hop && nunmatched > UNMATCHEDFOR2HOP*nvtxs) cnvtxs = Match_2Hop(ctrl, graph, perm, match, cnvtxs, nunmatched); /* match the final unmatched vertices with themselves and reorder the vertices of the coarse graph for memory-friendly contraction */ for (cnvtxs=0, i=0; idbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->MatchTmr)); CreateCoarseGraph(ctrl, graph, cnvtxs, match); WCOREPOP; return cnvtxs; } /**************************************************************************/ /*! This function finds a matching using the HEM heuristic. The vertices are visited based on increasing degree to ensure that all vertices are given a chance to match with something. */ /**************************************************************************/ idx_t Match_SHEM(ctrl_t *ctrl, graph_t *graph) { idx_t i, pi, j, k, nvtxs, ncon, cnvtxs, maxidx, maxwgt, last_unmatched, avgdegree; idx_t *xadj, *vwgt, *adjncy, *adjwgt, *maxvwgt; idx_t *match, *cmap, *degrees, *perm, *tperm; size_t nunmatched=0; WCOREPUSH; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->MatchTmr)); nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; cmap = graph->cmap; maxvwgt = ctrl->maxvwgt; match = iset(nvtxs, UNMATCHED, iwspacemalloc(ctrl, nvtxs)); perm = iwspacemalloc(ctrl, nvtxs); tperm = iwspacemalloc(ctrl, nvtxs); degrees = iwspacemalloc(ctrl, nvtxs); irandArrayPermute(nvtxs, tperm, nvtxs/8, 1); avgdegree = 0.7*(xadj[nvtxs]/nvtxs); for (i=0; i avgdegree ? avgdegree : xadj[i+1]-xadj[i]); BucketSortKeysInc(ctrl, nvtxs, avgdegree, degrees, tperm, perm); for (cnvtxs=0, last_unmatched=0, pi=0; pimaxvwgt requirements */ if (xadj[i] == xadj[i+1]) { last_unmatched = gk_max(pi, last_unmatched)+1; for (; last_unmatchedinvtvwgt, vwgt+i*ncon, vwgt+maxidx*ncon, vwgt+k*ncon)))) { maxidx = k; maxwgt = adjwgt[j]; } } /* If it did not match, record for a 2-hop matching. */ if (maxidx == i && ivecaxpylez(ncon, 2, vwgt+i*ncon, vwgt+i*ncon, maxvwgt)) { nunmatched++; maxidx = UNMATCHED; } } } } if (maxidx != UNMATCHED) { cmap[i] = cmap[maxidx] = cnvtxs++; match[i] = maxidx; match[maxidx] = i; } } } //printf("nunmatched: %zu\n", nunmatched); /* see if a 2-hop matching is required/allowed */ if (!ctrl->no2hop && nunmatched > UNMATCHEDFOR2HOP*nvtxs) cnvtxs = Match_2Hop(ctrl, graph, perm, match, cnvtxs, nunmatched); /* match the final unmatched vertices with themselves and reorder the vertices of the coarse graph for memory-friendly contraction */ for (cnvtxs=0, i=0; idbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->MatchTmr)); CreateCoarseGraph(ctrl, graph, cnvtxs, match); WCOREPOP; return cnvtxs; } /*************************************************************************/ /*! This function matches the unmatched vertices using a 2-hop matching that involves vertices that are two hops away from each other. */ /**************************************************************************/ idx_t Match_2Hop(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match, idx_t cnvtxs, size_t nunmatched) { cnvtxs = Match_2HopAny(ctrl, graph, perm, match, cnvtxs, &nunmatched, 2); cnvtxs = Match_2HopAll(ctrl, graph, perm, match, cnvtxs, &nunmatched, 64); if (nunmatched > 1.5*UNMATCHEDFOR2HOP*graph->nvtxs) cnvtxs = Match_2HopAny(ctrl, graph, perm, match, cnvtxs, &nunmatched, 3); if (nunmatched > 2.0*UNMATCHEDFOR2HOP*graph->nvtxs) cnvtxs = Match_2HopAny(ctrl, graph, perm, match, cnvtxs, &nunmatched, graph->nvtxs); return cnvtxs; } /*************************************************************************/ /*! This function matches the unmatched vertices whose degree is less than maxdegree using a 2-hop matching that involves vertices that are two hops away from each other. The requirement of the 2-hop matching is a simple non-empty overlap between the adjancency lists of the vertices. */ /**************************************************************************/ idx_t Match_2HopAny(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match, idx_t cnvtxs, size_t *r_nunmatched, size_t maxdegree) { idx_t i, pi, j, jj, nvtxs; idx_t *xadj, *adjncy, *colptr, *rowind; idx_t *cmap; size_t nunmatched; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux3Tmr)); nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; cmap = graph->cmap; nunmatched = *r_nunmatched; /*IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, printf("IN: nunmatched: %zu\t", * nunmatched)); */ /* create the inverted index */ WCOREPUSH; colptr = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs+1)); for (i=0; ij; jj--) { if (match[rowind[jj]] == UNMATCHED) { cmap[rowind[j]] = cmap[rowind[jj]] = cnvtxs++; match[rowind[j]] = rowind[jj]; match[rowind[jj]] = rowind[j]; nunmatched -= 2; break; } } } } } WCOREPOP; /* IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, printf("OUT: nunmatched: %zu\n", nunmatched)); */ IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux3Tmr)); *r_nunmatched = nunmatched; return cnvtxs; } /*************************************************************************/ /*! This function matches the unmatched vertices whose degree is less than maxdegree using a 2-hop matching that involves vertices that are two hops away from each other. The requirement of the 2-hop matching is that of identical adjacency lists. */ /**************************************************************************/ idx_t Match_2HopAll(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match, idx_t cnvtxs, size_t *r_nunmatched, size_t maxdegree) { idx_t i, pi, pk, j, jj, k, nvtxs, mask, idegree; idx_t *xadj, *adjncy; idx_t *cmap, *mark; ikv_t *keys; size_t nunmatched, ncand; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux3Tmr)); nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; cmap = graph->cmap; nunmatched = *r_nunmatched; mask = IDX_MAX/maxdegree; /*IFSET(ctrl->dbglvl, METIS_DBG_COARSEN, printf("IN: nunmatched: %zu\t", nunmatched)); */ WCOREPUSH; /* collapse vertices with identical adjancency lists */ keys = ikvwspacemalloc(ctrl, nunmatched); for (ncand=0, pi=0; pi 1 && idegree < maxdegree) { for (k=0, j=xadj[i]; jdbglvl, METIS_DBG_COARSEN, printf("OUT: ncand: %zu, nunmatched: %zu\n", ncand, nunmatched)); */ IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux3Tmr)); *r_nunmatched = nunmatched; return cnvtxs; } /*************************************************************************/ /*! This function prints various stats for each graph during coarsening */ /*************************************************************************/ void PrintCGraphStats(ctrl_t *ctrl, graph_t *graph) { idx_t i; printf("%10"PRIDX" %10"PRIDX" %10"PRIDX" [%"PRIDX"] [", graph->nvtxs, graph->nedges, isum(graph->nedges, graph->adjwgt, 1), ctrl->CoarsenTo); for (i=0; incon; i++) printf(" %8"PRIDX":%8"PRIDX, ctrl->maxvwgt[i], graph->tvwgt[i]); printf(" ]\n"); } /*************************************************************************/ /*! This function creates the coarser graph. It uses a simple hash-table for identifying the adjacent vertices that get collapsed to the same node. The hash-table can have conflicts, which are handled via a linear scan. */ /*************************************************************************/ void CreateCoarseGraph(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs, idx_t *match) { idx_t j, jj, k, kk, m, istart, iend, nvtxs, nedges, ncon, cnedges, v, u, mask, dovsize; idx_t *xadj, *vwgt, *vsize, *adjncy, *adjwgt; idx_t *cmap, *htable; idx_t *cxadj, *cvwgt, *cvsize, *cadjncy, *cadjwgt; graph_t *cgraph; dovsize = (ctrl->objtype == METIS_OBJTYPE_VOL ? 1 : 0); /* Check if the mask-version of the code is a good choice */ mask = HTLENGTH; if (cnvtxs < 2*mask || graph->nedges/graph->nvtxs > mask/20) { CreateCoarseGraphNoMask(ctrl, graph, cnvtxs, match); return; } nvtxs = graph->nvtxs; xadj = graph->xadj; for (v=0; v (mask>>3)) { CreateCoarseGraphNoMask(ctrl, graph, cnvtxs, match); return; } } WCOREPUSH; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ContractTmr)); ncon = graph->ncon; vwgt = graph->vwgt; vsize = graph->vsize; adjncy = graph->adjncy; adjwgt = graph->adjwgt; cmap = graph->cmap; /* Initialize the coarser graph */ cgraph = SetupCoarseGraph(graph, cnvtxs, dovsize); cxadj = cgraph->xadj; cvwgt = cgraph->vwgt; cvsize = cgraph->vsize; cadjncy = cgraph->adjncy; cadjwgt = cgraph->adjwgt; htable = iset(gk_min(cnvtxs+1, mask+1), -1, iwspacemalloc(ctrl, mask+1)); cxadj[0] = cnvtxs = cnedges = 0; for (v=0; v= 0 && cadjncy[jj] != cnvtxs) { for (jj=0; jj= 0 && jj < nedges && cadjncy[jj] == cnvtxs) { cadjncy[jj] = cadjncy[--nedges]; cadjwgt[jj] = cadjwgt[nedges]; } } /* Zero out the htable */ for (j=0; jnedges = cnedges; for (j=0; jtvwgt[j] = isum(cgraph->nvtxs, cgraph->vwgt+j, ncon); cgraph->invtvwgt[j] = 1.0/(cgraph->tvwgt[j] > 0 ? cgraph->tvwgt[j] : 1); } ReAdjustMemory(ctrl, graph, cgraph); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ContractTmr)); WCOREPOP; } /*************************************************************************/ /*! This function creates the coarser graph. It uses a full-size array (htable) for identifying the adjacent vertices that get collapsed to the same node. */ /*************************************************************************/ void CreateCoarseGraphNoMask(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs, idx_t *match) { idx_t j, k, m, istart, iend, nvtxs, nedges, ncon, cnedges, v, u, dovsize; idx_t *xadj, *vwgt, *vsize, *adjncy, *adjwgt; idx_t *cmap, *htable; idx_t *cxadj, *cvwgt, *cvsize, *cadjncy, *cadjwgt; graph_t *cgraph; WCOREPUSH; dovsize = (ctrl->objtype == METIS_OBJTYPE_VOL ? 1 : 0); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ContractTmr)); nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; vwgt = graph->vwgt; vsize = graph->vsize; adjncy = graph->adjncy; adjwgt = graph->adjwgt; cmap = graph->cmap; /* Initialize the coarser graph */ cgraph = SetupCoarseGraph(graph, cnvtxs, dovsize); cxadj = cgraph->xadj; cvwgt = cgraph->vwgt; cvsize = cgraph->vsize; cadjncy = cgraph->adjncy; cadjwgt = cgraph->adjwgt; htable = iset(cnvtxs, -1, iwspacemalloc(ctrl, cnvtxs)); cxadj[0] = cnvtxs = cnedges = 0; for (v=0; vnedges = cnedges; for (j=0; jtvwgt[j] = isum(cgraph->nvtxs, cgraph->vwgt+j, ncon); cgraph->invtvwgt[j] = 1.0/(cgraph->tvwgt[j] > 0 ? cgraph->tvwgt[j] : 1); } ReAdjustMemory(ctrl, graph, cgraph); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ContractTmr)); WCOREPOP; } /*************************************************************************/ /*! This function creates the coarser graph. It uses a simple hash-table for identifying the adjacent vertices that get collapsed to the same node. The hash-table can have conflicts, which are handled via a linear scan. It relies on the perm[] array to visit the vertices in increasing cnvtxs order. */ /*************************************************************************/ void CreateCoarseGraphPerm(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs, idx_t *match, idx_t *perm) { idx_t i, j, jj, k, kk, m, istart, iend, nvtxs, nedges, ncon, cnedges, v, u, mask, dovsize; idx_t *xadj, *vwgt, *vsize, *adjncy, *adjwgt; idx_t *cmap, *htable; idx_t *cxadj, *cvwgt, *cvsize, *cadjncy, *cadjwgt; graph_t *cgraph; WCOREPUSH; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ContractTmr)); dovsize = (ctrl->objtype == METIS_OBJTYPE_VOL ? 1 : 0); mask = HTLENGTH; nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; vwgt = graph->vwgt; vsize = graph->vsize; adjncy = graph->adjncy; adjwgt = graph->adjwgt; cmap = graph->cmap; /* Initialize the coarser graph */ cgraph = SetupCoarseGraph(graph, cnvtxs, dovsize); cxadj = cgraph->xadj; cvwgt = cgraph->vwgt; cvsize = cgraph->vsize; cadjncy = cgraph->adjncy; cadjwgt = cgraph->adjwgt; htable = iset(mask+1, -1, iwspacemalloc(ctrl, mask+1)); cxadj[0] = cnvtxs = cnedges = 0; for (i=0; i= 0 && cadjncy[jj] != cnvtxs) { for (jj=0; jj= 0 && cadjncy[jj] == cnvtxs) { /* This 2nd check is needed for non-adjacent matchings */ cadjncy[jj] = cadjncy[--nedges]; cadjwgt[jj] = cadjwgt[nedges]; } } for (j=0; jnedges = cnedges; for (i=0; itvwgt[i] = isum(cgraph->nvtxs, cgraph->vwgt+i, ncon); cgraph->invtvwgt[i] = 1.0/(cgraph->tvwgt[i] > 0 ? cgraph->tvwgt[i] : 1); } ReAdjustMemory(ctrl, graph, cgraph); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ContractTmr)); WCOREPOP; } /*************************************************************************/ /*! Setup the various arrays for the coarse graph */ /*************************************************************************/ graph_t *SetupCoarseGraph(graph_t *graph, idx_t cnvtxs, idx_t dovsize) { graph_t *cgraph; cgraph = CreateGraph(); cgraph->nvtxs = cnvtxs; cgraph->ncon = graph->ncon; cgraph->finer = graph; graph->coarser = cgraph; /* Allocate memory for the coarser graph */ cgraph->xadj = imalloc(cnvtxs+1, "SetupCoarseGraph: xadj"); cgraph->adjncy = imalloc(graph->nedges, "SetupCoarseGraph: adjncy"); cgraph->adjwgt = imalloc(graph->nedges, "SetupCoarseGraph: adjwgt"); cgraph->vwgt = imalloc(cgraph->ncon*cnvtxs, "SetupCoarseGraph: vwgt"); cgraph->tvwgt = imalloc(cgraph->ncon, "SetupCoarseGraph: tvwgt"); cgraph->invtvwgt = rmalloc(cgraph->ncon, "SetupCoarseGraph: invtvwgt"); if (dovsize) cgraph->vsize = imalloc(cnvtxs, "SetupCoarseGraph: vsize"); return cgraph; } /*************************************************************************/ /*! This function re-adjusts the amount of memory that was allocated if it will lead to significant savings */ /*************************************************************************/ void ReAdjustMemory(ctrl_t *ctrl, graph_t *graph, graph_t *cgraph) { if (cgraph->nedges > 10000 && cgraph->nedges < 0.9*graph->nedges) { cgraph->adjncy = irealloc(cgraph->adjncy, cgraph->nedges, "ReAdjustMemory: adjncy"); cgraph->adjwgt = irealloc(cgraph->adjwgt, cgraph->nedges, "ReAdjustMemory: adjwgt"); } } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/frename.c0000644000175100001440000000762314552244506024737 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * Frename.c * * THis file contains some renaming routines to deal with different Fortran compilers * * Started 9/15/97 * George * */ #include "metislib.h" #define FRENAME(name, dargs, cargs, name1, name2, name3, name4) \ int name1 dargs { return name cargs; } \ int name2 dargs { return name cargs; } \ int name3 dargs { return name cargs; } \ int name4 dargs { return name cargs; } FRENAME( METIS_PartGraphRecursive, (idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt, idx_t *nparts, real_t *tpwgts, real_t *ubvec, idx_t *options, idx_t *edgecut, idx_t *part), (nvtxs, ncon, xadj, adjncy, vwgt, vsize, adjwgt, nparts, tpwgts, ubvec, options, edgecut, part), METIS_PARTGRAPHRECURSIVE, metis_partgraphrecursive, metis_partgraphrecursive_, metis_partgraphrecursive__ ) FRENAME( METIS_PartGraphKway, (idx_t *nvtxs, idx_t *ncon, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt, idx_t *nparts, real_t *tpwgts, real_t *ubvec, idx_t *options, idx_t *edgecut, idx_t *part), (nvtxs, ncon, xadj, adjncy, vwgt, vsize, adjwgt, nparts, tpwgts, ubvec, options, edgecut, part), METIS_PARTGRAPHKWAY, metis_partgraphkway, metis_partgraphkway_, metis_partgraphkway__ ) FRENAME( METIS_MeshToDual, (idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *ncommon, idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy), (ne, nn, eptr, eind, ncommon, numflag, r_xadj, r_adjncy), METIS_MESHTODUAL, metis_meshtodual, metis_meshtodual_, metis_meshtodual__ ) FRENAME( METIS_MeshToNodal, (idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy), (ne, nn, eptr, eind, numflag, r_xadj, r_adjncy), METIS_MESHTONODAL, metis_meshtonodal, metis_meshtonodal_, metis_meshtonodal__ ) FRENAME( METIS_PartMeshNodal, (idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *vwgt, idx_t *vsize, idx_t *nparts, real_t *tpwgts, idx_t *options, idx_t *objval, idx_t *epart, idx_t *npart), (ne, nn, eptr, eind, vwgt, vsize, nparts, tpwgts, options, objval, epart, npart), METIS_PARTMESHNODAL, metis_partmeshnodal, metis_partmeshnodal_, metis_partmeshnodal__ ) FRENAME( METIS_PartMeshDual, (idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *vwgt, idx_t *vsize, idx_t *ncommon, idx_t *nparts, real_t *tpwgts, idx_t *options, idx_t *objval, idx_t *epart, idx_t *npart), (ne, nn, eptr, eind, vwgt, vsize, ncommon, nparts, tpwgts, options, objval, epart, npart), METIS_PARTMESHDUAL, metis_partmeshdual, metis_partmeshdual_, metis_partmeshdual__ ) FRENAME( METIS_NodeND, (idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *options, idx_t *perm, idx_t *iperm), (nvtxs, xadj, adjncy, vwgt, options, perm, iperm), METIS_NODEND, metis_nodend, metis_nodend_, metis_nodend__ ) FRENAME( METIS_Free, (void *ptr), (ptr), METIS_FREE, metis_free, metis_free_, metis_free__ ) FRENAME( METIS_SetDefaultOptions, (idx_t *options), (options), METIS_SETDEFAULTOPTIONS, metis_setdefaultoptions, metis_setdefaultoptions_, metis_setdefaultoptions__ ) Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/stdheaders.h0000644000175100001440000000202614552244506025445 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * stdheaders.h * * This file includes all necessary header files * * Started 8/27/94 * George * * $Id: stdheaders.h 5993 2009-01-07 02:09:57Z karypis $ */ #ifndef _LIBMETIS_STDHEADERS_H_ #define _LIBMETIS_STDHEADERS_H_ #include #ifdef __STDC__ #include #else #include #endif #include #include #include #include #include #endif Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/struct.h0000644000175100001440000002246314552244506024652 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * struct.h * * This file contains data structures for ILU routines. * * Started 9/26/95 * George * * $Id: struct.h 13900 2013-03-24 15:27:07Z karypis $ */ #ifndef _LIBMETIS_STRUCT_H_ #define _LIBMETIS_STRUCT_H_ /*************************************************************************/ /*! This data structure stores cut-based k-way refinement info about an adjacent subdomain for a given vertex. */ /*************************************************************************/ typedef struct cnbr_t { idx_t pid; /*!< The partition ID */ idx_t ed; /*!< The sum of the weights of the adjacent edges that are incident on pid */ } cnbr_t; /*************************************************************************/ /*! The following data structure stores holds information on degrees for k-way partition */ /*************************************************************************/ typedef struct ckrinfo_t { idx_t id; /*!< The internal degree of a vertex (sum of weights) */ idx_t ed; /*!< The total external degree of a vertex */ idx_t nnbrs; /*!< The number of neighboring subdomains */ idx_t inbr; /*!< The index in the cnbr_t array where the nnbrs list of neighbors is stored */ } ckrinfo_t; /*************************************************************************/ /*! This data structure stores volume-based k-way refinement info about an adjacent subdomain for a given vertex. */ /*************************************************************************/ typedef struct vnbr_t { idx_t pid; /*!< The partition ID */ idx_t ned; /*!< The number of the adjacent edges that are incident on pid */ idx_t gv; /*!< The gain in volume achieved by moving the vertex to pid */ } vnbr_t; /*************************************************************************/ /*! The following data structure holds information on degrees for k-way vol-based partition */ /*************************************************************************/ typedef struct vkrinfo_t { idx_t nid; /*!< The internal degree of a vertex (count of edges) */ idx_t ned; /*!< The total external degree of a vertex (count of edges) */ idx_t gv; /*!< The volume gain of moving that vertex */ idx_t nnbrs; /*!< The number of neighboring subdomains */ idx_t inbr; /*!< The index in the vnbr_t array where the nnbrs list of neighbors is stored */ } vkrinfo_t; /*************************************************************************/ /*! The following data structure holds information on degrees for k-way partition */ /*************************************************************************/ typedef struct nrinfo_t { idx_t edegrees[2]; } nrinfo_t; /*************************************************************************/ /*! This data structure holds a graph */ /*************************************************************************/ typedef struct graph_t { idx_t nvtxs, nedges; /* The # of vertices and edges in the graph */ idx_t ncon; /* The # of constrains */ idx_t *xadj; /* Pointers to the locally stored vertices */ idx_t *vwgt; /* Vertex weights */ idx_t *vsize; /* Vertex sizes for min-volume formulation */ idx_t *adjncy; /* Array that stores the adjacency lists of nvtxs */ idx_t *adjwgt; /* Array that stores the weights of the adjacency lists */ idx_t *tvwgt; /* The sum of the vertex weights in the graph */ real_t *invtvwgt; /* The inverse of the sum of the vertex weights in the graph */ /* These are to keep track control if the corresponding fields correspond to application or library memory */ int free_xadj, free_vwgt, free_vsize, free_adjncy, free_adjwgt; idx_t *label; idx_t *cmap; /* Partition parameters */ idx_t mincut, minvol; idx_t *where, *pwgts; idx_t nbnd; idx_t *bndptr, *bndind; /* Bisection refinement parameters */ idx_t *id, *ed; /* K-way refinement parameters */ ckrinfo_t *ckrinfo; /*!< The per-vertex cut-based refinement info */ vkrinfo_t *vkrinfo; /*!< The per-vertex volume-based refinement info */ /* Node refinement information */ nrinfo_t *nrinfo; struct graph_t *coarser, *finer; } graph_t; /*************************************************************************/ /*! This data structure holds a mesh */ /*************************************************************************/ typedef struct mesh_t { idx_t ne, nn; /*!< The # of elements and nodes in the mesh */ idx_t ncon; /*!< The number of element balancing constraints (element weights) */ idx_t *eptr, *eind; /*!< The CSR-structure storing the nodes in the elements */ idx_t *ewgt; /*!< The weights of the elements */ } mesh_t; /*************************************************************************/ /*! The following structure stores information used by Metis */ /*************************************************************************/ typedef struct ctrl_t { moptype_et optype; /* Type of operation */ mobjtype_et objtype; /* Type of refinement objective */ mdbglvl_et dbglvl; /* Controls the debuging output of the program */ mctype_et ctype; /* The type of coarsening */ miptype_et iptype; /* The type of initial partitioning */ mrtype_et rtype; /* The type of refinement */ idx_t CoarsenTo; /* The # of vertices in the coarsest graph */ idx_t nIparts; /* The number of initial partitions to compute */ idx_t no2hop; /* Indicates if 2-hop matching will be used */ idx_t minconn; /* Indicates if the subdomain connectivity will be minimized */ idx_t contig; /* Indicates if contigous partitions are required */ idx_t nseps; /* The number of separators to be found during multiple bisections */ idx_t ufactor; /* The user-supplied load imbalance factor */ idx_t compress; /* If the graph will be compressed prior to ordering */ idx_t ccorder; /* If connected components will be ordered separately */ idx_t seed; /* The seed for the random number generator */ idx_t ncuts; /* The number of different partitionings to compute */ idx_t niter; /* The number of iterations during each refinement */ idx_t numflag; /* The user-supplied numflag for the graph */ idx_t *maxvwgt; /* The maximum allowed weight for a vertex */ idx_t ncon; /*!< The number of balancing constraints */ idx_t nparts; /*!< The number of partitions */ real_t pfactor; /* .1*(user-supplied prunning factor) */ real_t *ubfactors; /*!< The per-constraint ubfactors */ real_t *tpwgts; /*!< The target partition weights */ real_t *pijbm; /*!< The nparts*ncon multiplies for the ith partition and jth constraint for obtaining the balance */ real_t cfactor; /*!< The achieved compression factor */ /* Various Timers */ double TotalTmr, InitPartTmr, MatchTmr, ContractTmr, CoarsenTmr, UncoarsenTmr, RefTmr, ProjectTmr, SplitTmr, Aux1Tmr, Aux2Tmr, Aux3Tmr; /* Workspace information */ gk_mcore_t *mcore; /*!< The persistent memory core for within function mallocs/frees */ /* These are for use by the k-way refinement routines */ size_t nbrpoolsize; /*!< The number of {c,v}nbr_t entries that have been allocated */ size_t nbrpoolcpos; /*!< The position of the first free entry in the array */ size_t nbrpoolreallocs; /*!< The number of times the pool was resized */ cnbr_t *cnbrpool; /*!< The pool of cnbr_t entries to be used during refinement. The size and current position of the pool is controlled by nnbrs & cnbrs */ vnbr_t *vnbrpool; /*!< The pool of vnbr_t entries to be used during refinement. The size and current position of the pool is controlled by nnbrs & cnbrs */ /* The subdomain graph, in sparse format */ idx_t *maxnads; /* The maximum allocated number of adjacent domains */ idx_t *nads; /* The number of adjacent domains */ idx_t **adids; /* The IDs of the adjacent domains */ idx_t **adwgts; /* The edge-weight to the adjacent domains */ idx_t *pvec1, *pvec2; /* Auxiliar nparts-size vectors for efficiency */ } ctrl_t; #endif Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/compress.c0000644000175100001440000001507114552244506025151 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * compress.c * * This file contains code for compressing nodes with identical adjacency * structure and for prunning dense columns * * Started 9/17/97 * George */ #include "metislib.h" /*************************************************************************/ /*! This function compresses a graph by merging identical vertices The compression should lead to at least 10% reduction. The compressed graph that is generated has its adjwgts set to 1. \returns 1 if compression was performed, otherwise it returns 0. */ /**************************************************************************/ graph_t *CompressGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *cptr, idx_t *cind) { idx_t i, ii, iii, j, jj, k, l, cnvtxs, cnedges; idx_t *cxadj, *cadjncy, *cvwgt, *mark, *map; ikv_t *keys; graph_t *graph=NULL; mark = ismalloc(nvtxs, -1, "CompressGraph: mark"); map = ismalloc(nvtxs, -1, "CompressGraph: map"); keys = ikvmalloc(nvtxs, "CompressGraph: keys"); /* Compute a key for each adjacency list */ for (i=0; idbglvl, METIS_DBG_INFO, printf(" Compression: reduction in # of vertices: %"PRIDX".\n", nvtxs-cnvtxs)); if (cnvtxs < COMPRESSION_FRACTION*nvtxs) { /* Sufficient compression is possible, so go ahead and create the compressed graph */ graph = CreateGraph(); cnedges = 0; for (i=0; ixadj = imalloc(cnvtxs+1, "CompressGraph: xadj"); cvwgt = graph->vwgt = ismalloc(cnvtxs, 0, "CompressGraph: vwgt"); cadjncy = graph->adjncy = imalloc(cnedges, "CompressGraph: adjncy"); graph->adjwgt = ismalloc(cnedges, 1, "CompressGraph: adjwgt"); /* Now go and compress the graph */ iset(nvtxs, -1, mark); l = cxadj[0] = 0; for (i=0; invtxs = cnvtxs; graph->nedges = l; graph->ncon = 1; SetupGraph_tvwgt(graph); SetupGraph_label(graph); } gk_free((void **)&keys, &map, &mark, LTERM); return graph; } /*************************************************************************/ /*! This function prunes all the vertices in a graph with degree greater than factor*average. \returns the number of vertices that were prunned. */ /*************************************************************************/ graph_t *PruneGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *iperm, real_t factor) { idx_t i, j, k, l, nlarge, pnvtxs, pnedges; idx_t *pxadj, *padjncy, *pvwgt; idx_t *perm; graph_t *graph=NULL; perm = imalloc(nvtxs, "PruneGraph: perm"); factor = factor*xadj[nvtxs]/nvtxs; pnvtxs = pnedges = nlarge = 0; for (i=0; idbglvl, METIS_DBG_INFO, printf(" Pruned %"PRIDX" of %"PRIDX" vertices.\n", nlarge, nvtxs)); if (nlarge > 0 && nlarge < nvtxs) { /* Prunning is possible, so go ahead and create the prunned graph */ graph = CreateGraph(); /* Allocate memory for the prunned graph*/ pxadj = graph->xadj = imalloc(pnvtxs+1, "PruneGraph: xadj"); pvwgt = graph->vwgt = imalloc(pnvtxs, "PruneGraph: vwgt"); padjncy = graph->adjncy = imalloc(pnedges, "PruneGraph: adjncy"); graph->adjwgt = ismalloc(pnedges, 1, "PruneGraph: adjwgt"); pxadj[0] = pnedges = l = 0; for (i=0; invtxs = pnvtxs; graph->nedges = pnedges; graph->ncon = 1; SetupGraph_tvwgt(graph); SetupGraph_label(graph); } else if (nlarge > 0 && nlarge == nvtxs) { IFSET(ctrl->dbglvl, METIS_DBG_INFO, printf(" Pruning is ignored as it removes all vertices.\n")); nlarge = 0; } gk_free((void **)&perm, LTERM); return graph; } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/fortran.c0000644000175100001440000000761514552244506024776 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * fortran.c * * This file contains code for the fortran to C interface * * Started 8/19/97 * George * */ #include "metislib.h" /*************************************************************************/ /*! This function changes the numbering to start from 0 instead of 1 */ /*************************************************************************/ void Change2CNumbering(idx_t nvtxs, idx_t *xadj, idx_t *adjncy) { idx_t i; for (i=0; i<=nvtxs; i++) xadj[i]--; for (i=0; ioptype) { case METIS_OP_PMETIS: coresize = 3*(graph->nvtxs+1)*sizeof(idx_t) + 5*(ctrl->nparts+1)*graph->ncon*sizeof(idx_t) + 5*(ctrl->nparts+1)*graph->ncon*sizeof(real_t); break; default: coresize = 4*(graph->nvtxs+1)*sizeof(idx_t) + 5*(ctrl->nparts+1)*graph->ncon*sizeof(idx_t) + 5*(ctrl->nparts+1)*graph->ncon*sizeof(real_t); } /*coresize = 0;*/ ctrl->mcore = gk_mcoreCreate(coresize); ctrl->nbrpoolsize = 0; ctrl->nbrpoolcpos = 0; } /*************************************************************************/ /*! This function allocates refinement-specific memory for the workspace */ /*************************************************************************/ void AllocateRefinementWorkSpace(ctrl_t *ctrl, idx_t nbrpoolsize) { ctrl->nbrpoolsize = nbrpoolsize; ctrl->nbrpoolcpos = 0; ctrl->nbrpoolreallocs = 0; switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: ctrl->cnbrpool = (cnbr_t *)gk_malloc(ctrl->nbrpoolsize*sizeof(cnbr_t), "AllocateRefinementWorkSpace: cnbrpool"); break; case METIS_OBJTYPE_VOL: ctrl->vnbrpool = (vnbr_t *)gk_malloc(ctrl->nbrpoolsize*sizeof(vnbr_t), "AllocateRefinementWorkSpace: vnbrpool"); break; default: gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); } /* Allocate the memory for the sparse subdomain graph */ if (ctrl->minconn) { ctrl->pvec1 = imalloc(ctrl->nparts+1, "AllocateRefinementWorkSpace: pvec1"); ctrl->pvec2 = imalloc(ctrl->nparts+1, "AllocateRefinementWorkSpace: pvec2"); ctrl->maxnads = ismalloc(ctrl->nparts, INIT_MAXNAD, "AllocateRefinementWorkSpace: maxnads"); ctrl->nads = imalloc(ctrl->nparts, "AllocateRefinementWorkSpace: nads"); ctrl->adids = iAllocMatrix(ctrl->nparts, INIT_MAXNAD, 0, "AllocateRefinementWorkSpace: adids"); ctrl->adwgts = iAllocMatrix(ctrl->nparts, INIT_MAXNAD, 0, "AllocateRefinementWorkSpace: adwgts"); } } /*************************************************************************/ /*! This function frees the workspace */ /*************************************************************************/ void FreeWorkSpace(ctrl_t *ctrl) { gk_mcoreDestroy(&ctrl->mcore, ctrl->dbglvl&METIS_DBG_INFO); #ifndef NDEBUG IFSET(ctrl->dbglvl, METIS_DBG_INFO, printf(" nbrpool statistics\n" " nbrpoolsize: %12zu nbrpoolcpos: %12zu\n" " nbrpoolreallocs: %12zu\n\n", ctrl->nbrpoolsize, ctrl->nbrpoolcpos, ctrl->nbrpoolreallocs)); #endif gk_free((void **)&ctrl->cnbrpool, &ctrl->vnbrpool, LTERM); ctrl->nbrpoolsize = 0; ctrl->nbrpoolcpos = 0; if (ctrl->minconn) { iFreeMatrix(&(ctrl->adids), ctrl->nparts, INIT_MAXNAD); iFreeMatrix(&(ctrl->adwgts), ctrl->nparts, INIT_MAXNAD); gk_free((void **)&ctrl->pvec1, &ctrl->pvec2, &ctrl->maxnads, &ctrl->nads, LTERM); } } /*************************************************************************/ /*! This function allocate space from the workspace/heap */ /*************************************************************************/ void *wspacemalloc(ctrl_t *ctrl, size_t nbytes) { return gk_mcoreMalloc(ctrl->mcore, nbytes); } /*************************************************************************/ /*! This function sets a marker in the stack of malloc ops to be used subsequently for freeing purposes */ /*************************************************************************/ void wspacepush(ctrl_t *ctrl) { gk_mcorePush(ctrl->mcore); } /*************************************************************************/ /*! This function frees all mops since the last push */ /*************************************************************************/ void wspacepop(ctrl_t *ctrl) { gk_mcorePop(ctrl->mcore); } /*************************************************************************/ /*! This function allocate space from the core */ /*************************************************************************/ idx_t *iwspacemalloc(ctrl_t *ctrl, idx_t n) { return (idx_t *)wspacemalloc(ctrl, n*sizeof(idx_t)); } /*************************************************************************/ /*! This function allocate space from the core */ /*************************************************************************/ real_t *rwspacemalloc(ctrl_t *ctrl, idx_t n) { return (real_t *)wspacemalloc(ctrl, n*sizeof(real_t)); } /*************************************************************************/ /*! This function allocate space from the core */ /*************************************************************************/ ikv_t *ikvwspacemalloc(ctrl_t *ctrl, idx_t n) { return (ikv_t *)wspacemalloc(ctrl, n*sizeof(ikv_t)); } /*************************************************************************/ /*! This function resets the cnbrpool */ /*************************************************************************/ void cnbrpoolReset(ctrl_t *ctrl) { ctrl->nbrpoolcpos = 0; } /*************************************************************************/ /*! This function gets the next free index from cnbrpool */ /*************************************************************************/ idx_t cnbrpoolGetNext(ctrl_t *ctrl, idx_t nnbrs) { ctrl->nbrpoolcpos += nnbrs; if (ctrl->nbrpoolcpos > ctrl->nbrpoolsize) { ctrl->nbrpoolsize += gk_max(10*nnbrs, ctrl->nbrpoolsize/2); ctrl->cnbrpool = (cnbr_t *)gk_realloc(ctrl->cnbrpool, ctrl->nbrpoolsize*sizeof(cnbr_t), "cnbrpoolGet: cnbrpool"); ctrl->nbrpoolreallocs++; } return ctrl->nbrpoolcpos - nnbrs; } /*************************************************************************/ /*! This function resets the vnbrpool */ /*************************************************************************/ void vnbrpoolReset(ctrl_t *ctrl) { ctrl->nbrpoolcpos = 0; } /*************************************************************************/ /*! This function gets the next free index from vnbrpool */ /*************************************************************************/ idx_t vnbrpoolGetNext(ctrl_t *ctrl, idx_t nnbrs) { ctrl->nbrpoolcpos += nnbrs; if (ctrl->nbrpoolcpos > ctrl->nbrpoolsize) { ctrl->nbrpoolsize += gk_max(10*nnbrs, ctrl->nbrpoolsize/2); ctrl->vnbrpool = (vnbr_t *)gk_realloc(ctrl->vnbrpool, ctrl->nbrpoolsize*sizeof(vnbr_t), "vnbrpoolGet: vnbrpool"); ctrl->nbrpoolreallocs++; } return ctrl->nbrpoolcpos - nnbrs; } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/kwayfm.c0000644000175100001440000017474714552244506024634 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file \brief Routines for k-way refinement \date Started 7/28/97 \author George \author Copyright 1997-2009, Regents of the University of Minnesota \version $Id: kwayfm.c 10567 2011-07-13 16:17:07Z karypis $ */ #include "metislib.h" /*************************************************************************/ /* Top-level routine for k-way partitioning refinement. This routine just calls the appropriate refinement routine based on the objectives and constraints. */ /*************************************************************************/ void Greedy_KWayOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter, real_t ffactor, idx_t omode) { switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: if (graph->ncon == 1) Greedy_KWayCutOptimize(ctrl, graph, niter, ffactor, omode); else Greedy_McKWayCutOptimize(ctrl, graph, niter, ffactor, omode); break; case METIS_OBJTYPE_VOL: if (graph->ncon == 1) Greedy_KWayVolOptimize(ctrl, graph, niter, ffactor, omode); else Greedy_McKWayVolOptimize(ctrl, graph, niter, ffactor, omode); break; default: gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); } } /*************************************************************************/ /*! K-way partitioning optimization in which the vertices are visited in decreasing ed/sqrt(nnbrs)-id order. Note this is just an approximation, as the ed is often split across different subdomains and the sqrt(nnbrs) is just a crude approximation. \param graph is the graph that is being refined. \param niter is the number of refinement iterations. \param ffactor is the \em fudge-factor for allowing positive gain moves to violate the max-pwgt constraint. \param omode is the type of optimization that will performed among OMODE_REFINE and OMODE_BALANCE */ /**************************************************************************/ void Greedy_KWayCutOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter, real_t ffactor, idx_t omode) { /* Common variables to all types of kway-refinement/balancing routines */ idx_t i, ii, iii, j, k, pass, nvtxs, nparts, gain; idx_t from, me, to, oldcut, vwgt; idx_t *xadj, *adjncy, *adjwgt; idx_t *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt, *itpwgts; idx_t nmoved, nupd, *vstatus, *updptr, *updind; idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL; idx_t *bfslvl=NULL, *bfsind=NULL, *bfsmrk=NULL; idx_t bndtype = (omode == OMODE_REFINE ? BNDTYPE_REFINE : BNDTYPE_BALANCE); /* Edgecut-specific/different variables */ idx_t nbnd, oldnnbrs; rpq_t *queue; real_t rgain; ckrinfo_t *myrinfo; cnbr_t *mynbrs; WCOREPUSH; /* Link the graph fields */ nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; bndind = graph->bndind; bndptr = graph->bndptr; where = graph->where; pwgts = graph->pwgts; nparts = ctrl->nparts; /* Setup the weight intervals of the various subdomains */ minwgt = iwspacemalloc(ctrl, nparts); maxwgt = iwspacemalloc(ctrl, nparts); itpwgts = iwspacemalloc(ctrl, nparts); for (i=0; itpwgts[i]*graph->tvwgt[0]; maxwgt[i] = ctrl->tpwgts[i]*graph->tvwgt[0]*ctrl->ubfactors[0]; minwgt[i] = ctrl->tpwgts[i]*graph->tvwgt[0]*(1.0/ctrl->ubfactors[0]); } perm = iwspacemalloc(ctrl, nvtxs); /* This stores the valid target subdomains. It is used when ctrl->minconn to control the subdomains to which moves are allowed to be made. When ctrl->minconn is false, the default values of 2 allow all moves to go through and it does not interfere with the zero-gain move selection. */ safetos = iset(nparts, 2, iwspacemalloc(ctrl, nparts)); if (ctrl->minconn) { ComputeSubDomainGraph(ctrl, graph); nads = ctrl->nads; adids = ctrl->adids; doms = iset(nparts, 0, ctrl->pvec1); } /* Setup updptr, updind like boundary info to keep track of the vertices whose vstatus's need to be reset at the end of the inner iteration */ vstatus = iset(nvtxs, VPQSTATUS_NOTPRESENT, iwspacemalloc(ctrl, nvtxs)); updptr = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs)); updind = iwspacemalloc(ctrl, nvtxs); if (ctrl->contig) { /* The arrays that will be used for limited check of articulation points */ bfslvl = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); bfsind = iwspacemalloc(ctrl, nvtxs); bfsmrk = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); } if (ctrl->dbglvl&METIS_DBG_REFINE) { printf("%s: [%6"PRIDX" %6"PRIDX"]-[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL"," " Nv-Nb[%6"PRIDX" %6"PRIDX"], Cut: %6"PRIDX, (omode == OMODE_REFINE ? "GRC" : "GBC"), pwgts[iargmin(nparts, pwgts)], imax(nparts, pwgts), minwgt[0], maxwgt[0], ComputeLoadImbalance(graph, nparts, ctrl->pijbm), graph->nvtxs, graph->nbnd, graph->mincut); if (ctrl->minconn) printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1)); printf("\n"); } queue = rpqCreate(nvtxs); /*===================================================================== * The top-level refinement loop *======================================================================*/ for (pass=0; passmincut); if (omode == OMODE_BALANCE) { /* Check to see if things are out of balance, given the tolerance */ for (i=0; i maxwgt[i]) break; } if (i == nparts) /* Things are balanced. Return right away */ break; } oldcut = graph->mincut; nbnd = graph->nbnd; nupd = 0; if (ctrl->minconn) maxndoms = imax(nparts, nads); /* Insert the boundary vertices in the priority queue */ irandArrayPermute(nbnd, perm, nbnd/4, 1); for (ii=0; iickrinfo[i].nnbrs > 0 ? 1.0*graph->ckrinfo[i].ed/sqrt(graph->ckrinfo[i].nnbrs) : 0.0) - graph->ckrinfo[i].id; rpqInsert(queue, i, rgain); vstatus[i] = VPQSTATUS_PRESENT; ListInsert(nupd, updind, updptr, i); } /* Start extracting vertices from the queue and try to move them */ for (nmoved=0, iii=0;;iii++) { if ((i = rpqGetTop(queue)) == -1) break; vstatus[i] = VPQSTATUS_EXTRACTED; myrinfo = graph->ckrinfo+i; mynbrs = ctrl->cnbrpool + myrinfo->inbr; from = where[i]; vwgt = graph->vwgt[i]; /* Prevent moves that make 'from' domain underbalanced */ if (omode == OMODE_REFINE) { if (myrinfo->id > 0 && pwgts[from]-vwgt < minwgt[from]) continue; } else { /* OMODE_BALANCE */ if (pwgts[from]-vwgt < minwgt[from]) continue; } if (ctrl->contig && IsArticulationNode(i, xadj, adjncy, where, bfslvl, bfsind, bfsmrk)) continue; if (ctrl->minconn) SelectSafeTargetSubdomains(myrinfo, mynbrs, nads, adids, maxndoms, safetos, doms); /* Find the most promising subdomain to move to */ if (omode == OMODE_REFINE) { for (k=myrinfo->nnbrs-1; k>=0; k--) { if (!safetos[to=mynbrs[k].pid]) continue; gain = mynbrs[k].ed-myrinfo->id; if (gain >= 0 && pwgts[to]+vwgt <= maxwgt[to]+ffactor*gain) break; } if (k < 0) continue; /* break out if you did not find a candidate */ for (j=k-1; j>=0; j--) { if (!safetos[to=mynbrs[j].pid]) continue; gain = mynbrs[j].ed-myrinfo->id; if ((mynbrs[j].ed > mynbrs[k].ed && pwgts[to]+vwgt <= maxwgt[to]+ffactor*gain) || (mynbrs[j].ed == mynbrs[k].ed && itpwgts[mynbrs[k].pid]*pwgts[to] < itpwgts[to]*pwgts[mynbrs[k].pid])) k = j; } to = mynbrs[k].pid; gain = mynbrs[k].ed-myrinfo->id; if (!(gain > 0 || (gain == 0 && (pwgts[from] >= maxwgt[from] || itpwgts[to]*pwgts[from] > itpwgts[from]*(pwgts[to]+vwgt) || (iii%2 == 0 && safetos[to] == 2) ) ) ) ) continue; } else { /* OMODE_BALANCE */ for (k=myrinfo->nnbrs-1; k>=0; k--) { if (!safetos[to=mynbrs[k].pid]) continue; if (pwgts[to]+vwgt <= maxwgt[to] || itpwgts[from]*(pwgts[to]+vwgt) <= itpwgts[to]*pwgts[from]) break; } if (k < 0) continue; /* break out if you did not find a candidate */ for (j=k-1; j>=0; j--) { if (!safetos[to=mynbrs[j].pid]) continue; if (itpwgts[mynbrs[k].pid]*pwgts[to] < itpwgts[to]*pwgts[mynbrs[k].pid]) k = j; } to = mynbrs[k].pid; if (pwgts[from] < maxwgt[from] && pwgts[to] > minwgt[to] && mynbrs[k].ed-myrinfo->id < 0) continue; } /*===================================================================== * If we got here, we can now move the vertex from 'from' to 'to' *======================================================================*/ graph->mincut -= mynbrs[k].ed-myrinfo->id; nmoved++; IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, printf("\t\tMoving %6"PRIDX" to %3"PRIDX". Gain: %4"PRIDX". Cut: %6"PRIDX"\n", i, to, mynbrs[k].ed-myrinfo->id, graph->mincut)); /* Update the subdomain connectivity information */ if (ctrl->minconn) { /* take care of i's move itself */ UpdateEdgeSubDomainGraph(ctrl, from, to, myrinfo->id-mynbrs[k].ed, &maxndoms); /* take care of the adjancent vertices */ for (j=xadj[i]; jckrinfo+ii; oldnnbrs = myrinfo->nnbrs; UpdateAdjacentVertexInfoAndBND(ctrl, ii, xadj[ii+1]-xadj[ii], me, from, to, myrinfo, adjwgt[j], nbnd, bndptr, bndind, bndtype); UpdateQueueInfo(queue, vstatus, ii, me, from, to, myrinfo, oldnnbrs, nupd, updptr, updind, bndtype); ASSERT(myrinfo->nnbrs <= xadj[ii+1]-xadj[ii]); } } graph->nbnd = nbnd; /* Reset the vstatus and associated data structures */ for (i=0; idbglvl&METIS_DBG_REFINE) { printf("\t[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL", Nb: %6"PRIDX"." " Nmoves: %5"PRIDX", Cut: %6"PRIDX", Vol: %6"PRIDX, pwgts[iargmin(nparts, pwgts)], imax(nparts, pwgts), ComputeLoadImbalance(graph, nparts, ctrl->pijbm), graph->nbnd, nmoved, graph->mincut, ComputeVolume(graph, where)); if (ctrl->minconn) printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1)); printf("\n"); } if (nmoved == 0 || (omode == OMODE_REFINE && graph->mincut == oldcut)) break; } rpqDestroy(queue); WCOREPOP; } /*************************************************************************/ /*! K-way refinement that minimizes the communication volume. This is a greedy routine and the vertices are visited in decreasing gv order. \param graph is the graph that is being refined. \param niter is the number of refinement iterations. \param ffactor is the \em fudge-factor for allowing positive gain moves to violate the max-pwgt constraint. */ /**************************************************************************/ void Greedy_KWayVolOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter, real_t ffactor, idx_t omode) { /* Common variables to all types of kway-refinement/balancing routines */ idx_t i, ii, iii, j, k, pass, nvtxs, nparts, gain; idx_t from, me, to, oldcut, vwgt; idx_t *xadj, *adjncy; idx_t *where, *pwgts, *perm, *bndind, *minwgt, *maxwgt, *itpwgts; idx_t nmoved, nupd, *vstatus, *updptr, *updind; idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL; idx_t *bfslvl=NULL, *bfsind=NULL, *bfsmrk=NULL; idx_t bndtype = (omode == OMODE_REFINE ? BNDTYPE_REFINE : BNDTYPE_BALANCE); /* Volume-specific/different variables */ ipq_t *queue; idx_t oldvol, xgain; idx_t *vmarker, *pmarker, *modind; vkrinfo_t *myrinfo; vnbr_t *mynbrs; WCOREPUSH; /* Link the graph fields */ nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; bndind = graph->bndind; where = graph->where; pwgts = graph->pwgts; nparts = ctrl->nparts; /* Setup the weight intervals of the various subdomains */ minwgt = iwspacemalloc(ctrl, nparts); maxwgt = iwspacemalloc(ctrl, nparts); itpwgts = iwspacemalloc(ctrl, nparts); for (i=0; itpwgts[i]*graph->tvwgt[0]; maxwgt[i] = ctrl->tpwgts[i]*graph->tvwgt[0]*ctrl->ubfactors[0]; minwgt[i] = ctrl->tpwgts[i]*graph->tvwgt[0]*(1.0/ctrl->ubfactors[0]); } perm = iwspacemalloc(ctrl, nvtxs); /* This stores the valid target subdomains. It is used when ctrl->minconn to control the subdomains to which moves are allowed to be made. When ctrl->minconn is false, the default values of 2 allow all moves to go through and it does not interfere with the zero-gain move selection. */ safetos = iset(nparts, 2, iwspacemalloc(ctrl, nparts)); if (ctrl->minconn) { ComputeSubDomainGraph(ctrl, graph); nads = ctrl->nads; adids = ctrl->adids; doms = iset(nparts, 0, ctrl->pvec1); } /* Setup updptr, updind like boundary info to keep track of the vertices whose vstatus's need to be reset at the end of the inner iteration */ vstatus = iset(nvtxs, VPQSTATUS_NOTPRESENT, iwspacemalloc(ctrl, nvtxs)); updptr = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs)); updind = iwspacemalloc(ctrl, nvtxs); if (ctrl->contig) { /* The arrays that will be used for limited check of articulation points */ bfslvl = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); bfsind = iwspacemalloc(ctrl, nvtxs); bfsmrk = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); } /* Vol-refinement specific working arrays */ modind = iwspacemalloc(ctrl, nvtxs); vmarker = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); pmarker = iset(nparts, -1, iwspacemalloc(ctrl, nparts)); if (ctrl->dbglvl&METIS_DBG_REFINE) { printf("%s: [%6"PRIDX" %6"PRIDX"]-[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL ", Nv-Nb[%6"PRIDX" %6"PRIDX"], Cut: %5"PRIDX", Vol: %5"PRIDX, (omode == OMODE_REFINE ? "GRV" : "GBV"), pwgts[iargmin(nparts, pwgts)], imax(nparts, pwgts), minwgt[0], maxwgt[0], ComputeLoadImbalance(graph, nparts, ctrl->pijbm), graph->nvtxs, graph->nbnd, graph->mincut, graph->minvol); if (ctrl->minconn) printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1)); printf("\n"); } queue = ipqCreate(nvtxs); /*===================================================================== * The top-level refinement loop *======================================================================*/ for (pass=0; passminvol); if (omode == OMODE_BALANCE) { /* Check to see if things are out of balance, given the tolerance */ for (i=0; i maxwgt[i]) break; } if (i == nparts) /* Things are balanced. Return right away */ break; } oldcut = graph->mincut; oldvol = graph->minvol; nupd = 0; if (ctrl->minconn) maxndoms = imax(nparts, nads); /* Insert the boundary vertices in the priority queue */ irandArrayPermute(graph->nbnd, perm, graph->nbnd/4, 1); for (ii=0; iinbnd; ii++) { i = bndind[perm[ii]]; ipqInsert(queue, i, graph->vkrinfo[i].gv); vstatus[i] = VPQSTATUS_PRESENT; ListInsert(nupd, updind, updptr, i); } /* Start extracting vertices from the queue and try to move them */ for (nmoved=0, iii=0;;iii++) { if ((i = ipqGetTop(queue)) == -1) break; vstatus[i] = VPQSTATUS_EXTRACTED; myrinfo = graph->vkrinfo+i; mynbrs = ctrl->vnbrpool + myrinfo->inbr; from = where[i]; vwgt = graph->vwgt[i]; /* Prevent moves that make 'from' domain underbalanced */ if (omode == OMODE_REFINE) { if (myrinfo->nid > 0 && pwgts[from]-vwgt < minwgt[from]) continue; } else { /* OMODE_BALANCE */ if (pwgts[from]-vwgt < minwgt[from]) continue; } if (ctrl->contig && IsArticulationNode(i, xadj, adjncy, where, bfslvl, bfsind, bfsmrk)) continue; if (ctrl->minconn) SelectSafeTargetSubdomains(myrinfo, mynbrs, nads, adids, maxndoms, safetos, doms); xgain = (myrinfo->nid == 0 && myrinfo->ned > 0 ? graph->vsize[i] : 0); /* Find the most promising subdomain to move to */ if (omode == OMODE_REFINE) { for (k=myrinfo->nnbrs-1; k>=0; k--) { if (!safetos[to=mynbrs[k].pid]) continue; gain = mynbrs[k].gv + xgain; if (gain >= 0 && pwgts[to]+vwgt <= maxwgt[to]+ffactor*gain) break; } if (k < 0) continue; /* break out if you did not find a candidate */ for (j=k-1; j>=0; j--) { if (!safetos[to=mynbrs[j].pid]) continue; gain = mynbrs[j].gv + xgain; if ((mynbrs[j].gv > mynbrs[k].gv && pwgts[to]+vwgt <= maxwgt[to]+ffactor*gain) || (mynbrs[j].gv == mynbrs[k].gv && mynbrs[j].ned > mynbrs[k].ned && pwgts[to]+vwgt <= maxwgt[to]) || (mynbrs[j].gv == mynbrs[k].gv && mynbrs[j].ned == mynbrs[k].ned && itpwgts[mynbrs[k].pid]*pwgts[to] < itpwgts[to]*pwgts[mynbrs[k].pid]) ) k = j; } to = mynbrs[k].pid; ASSERT(xgain+mynbrs[k].gv >= 0); j = 0; if (xgain+mynbrs[k].gv > 0 || mynbrs[k].ned-myrinfo->nid > 0) j = 1; else if (mynbrs[k].ned-myrinfo->nid == 0) { if ((iii%2 == 0 && safetos[to] == 2) || pwgts[from] >= maxwgt[from] || itpwgts[from]*(pwgts[to]+vwgt) < itpwgts[to]*pwgts[from]) j = 1; } if (j == 0) continue; } else { /* OMODE_BALANCE */ for (k=myrinfo->nnbrs-1; k>=0; k--) { if (!safetos[to=mynbrs[k].pid]) continue; if (pwgts[to]+vwgt <= maxwgt[to] || itpwgts[from]*(pwgts[to]+vwgt) <= itpwgts[to]*pwgts[from]) break; } if (k < 0) continue; /* break out if you did not find a candidate */ for (j=k-1; j>=0; j--) { if (!safetos[to=mynbrs[j].pid]) continue; if (itpwgts[mynbrs[k].pid]*pwgts[to] < itpwgts[to]*pwgts[mynbrs[k].pid]) k = j; } to = mynbrs[k].pid; if (pwgts[from] < maxwgt[from] && pwgts[to] > minwgt[to] && (xgain+mynbrs[k].gv < 0 || (xgain+mynbrs[k].gv == 0 && mynbrs[k].ned-myrinfo->nid < 0)) ) continue; } /*===================================================================== * If we got here, we can now move the vertex from 'from' to 'to' *======================================================================*/ INC_DEC(pwgts[to], pwgts[from], vwgt); graph->mincut -= mynbrs[k].ned-myrinfo->nid; graph->minvol -= (xgain+mynbrs[k].gv); where[i] = to; nmoved++; IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, printf("\t\tMoving %6"PRIDX" from %3"PRIDX" to %3"PRIDX". " "Gain: [%4"PRIDX" %4"PRIDX"]. Cut: %6"PRIDX", Vol: %6"PRIDX"\n", i, from, to, xgain+mynbrs[k].gv, mynbrs[k].ned-myrinfo->nid, graph->mincut, graph->minvol)); /* Update the subdomain connectivity information */ if (ctrl->minconn) { /* take care of i's move itself */ UpdateEdgeSubDomainGraph(ctrl, from, to, myrinfo->nid-mynbrs[k].ned, &maxndoms); /* take care of the adjancent vertices */ for (j=xadj[i]; jdbglvl&METIS_DBG_REFINE) { printf("\t[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL", Nb: %6"PRIDX"." " Nmoves: %5"PRIDX", Cut: %6"PRIDX", Vol: %6"PRIDX, pwgts[iargmin(nparts, pwgts)], imax(nparts, pwgts), ComputeLoadImbalance(graph, nparts, ctrl->pijbm), graph->nbnd, nmoved, graph->mincut, graph->minvol); if (ctrl->minconn) printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1)); printf("\n"); } if (nmoved == 0 || (omode == OMODE_REFINE && graph->minvol == oldvol && graph->mincut == oldcut)) break; } ipqDestroy(queue); WCOREPOP; } /*************************************************************************/ /*! K-way partitioning optimization in which the vertices are visited in decreasing ed/sqrt(nnbrs)-id order. Note this is just an approximation, as the ed is often split across different subdomains and the sqrt(nnbrs) is just a crude approximation. \param graph is the graph that is being refined. \param niter is the number of refinement iterations. \param ffactor is the \em fudge-factor for allowing positive gain moves to violate the max-pwgt constraint. \param omode is the type of optimization that will performed among OMODE_REFINE and OMODE_BALANCE */ /**************************************************************************/ void Greedy_McKWayCutOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter, real_t ffactor, idx_t omode) { /* Common variables to all types of kway-refinement/balancing routines */ idx_t i, ii, iii, j, k, pass, nvtxs, ncon, nparts, gain; idx_t from, me, to, cto, oldcut; idx_t *xadj, *vwgt, *adjncy, *adjwgt; idx_t *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt; idx_t nmoved, nupd, *vstatus, *updptr, *updind; idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL; idx_t *bfslvl=NULL, *bfsind=NULL, *bfsmrk=NULL; idx_t bndtype = (omode == OMODE_REFINE ? BNDTYPE_REFINE : BNDTYPE_BALANCE); real_t *ubfactors, *pijbm; real_t origbal; /* Edgecut-specific/different variables */ idx_t nbnd, oldnnbrs; rpq_t *queue; real_t rgain; ckrinfo_t *myrinfo; cnbr_t *mynbrs; WCOREPUSH; /* Link the graph fields */ nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; bndind = graph->bndind; bndptr = graph->bndptr; where = graph->where; pwgts = graph->pwgts; nparts = ctrl->nparts; pijbm = ctrl->pijbm; /* Determine the ubfactors. The method used is different based on omode. When OMODE_BALANCE, the ubfactors are those supplied by the user. When OMODE_REFINE, the ubfactors are the max of the current partition and the user-specified ones. */ ubfactors = rwspacemalloc(ctrl, ncon); ComputeLoadImbalanceVec(graph, nparts, pijbm, ubfactors); origbal = rvecmaxdiff(ncon, ubfactors, ctrl->ubfactors); if (omode == OMODE_BALANCE) { rcopy(ncon, ctrl->ubfactors, ubfactors); } else { for (i=0; i ctrl->ubfactors[i] ? ubfactors[i] : ctrl->ubfactors[i]); } /* Setup the weight intervals of the various subdomains */ minwgt = iwspacemalloc(ctrl, nparts*ncon); maxwgt = iwspacemalloc(ctrl, nparts*ncon); for (i=0; itpwgts[i*ncon+j]*graph->tvwgt[j]*ubfactors[j]; /*minwgt[i*ncon+j] = ctrl->tpwgts[i*ncon+j]*graph->tvwgt[j]*(.9/ubfactors[j]);*/ minwgt[i*ncon+j] = ctrl->tpwgts[i*ncon+j]*graph->tvwgt[j]*.2; } } perm = iwspacemalloc(ctrl, nvtxs); /* This stores the valid target subdomains. It is used when ctrl->minconn to control the subdomains to which moves are allowed to be made. When ctrl->minconn is false, the default values of 2 allow all moves to go through and it does not interfere with the zero-gain move selection. */ safetos = iset(nparts, 2, iwspacemalloc(ctrl, nparts)); if (ctrl->minconn) { ComputeSubDomainGraph(ctrl, graph); nads = ctrl->nads; adids = ctrl->adids; doms = iset(nparts, 0, ctrl->pvec1); } /* Setup updptr, updind like boundary info to keep track of the vertices whose vstatus's need to be reset at the end of the inner iteration */ vstatus = iset(nvtxs, VPQSTATUS_NOTPRESENT, iwspacemalloc(ctrl, nvtxs)); updptr = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs)); updind = iwspacemalloc(ctrl, nvtxs); if (ctrl->contig) { /* The arrays that will be used for limited check of articulation points */ bfslvl = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); bfsind = iwspacemalloc(ctrl, nvtxs); bfsmrk = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); } if (ctrl->dbglvl&METIS_DBG_REFINE) { printf("%s: [%6"PRIDX" %6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL"(%.3"PRREAL")," " Nv-Nb[%6"PRIDX" %6"PRIDX"], Cut: %6"PRIDX", (%"PRIDX")", (omode == OMODE_REFINE ? "GRC" : "GBC"), imin(nparts*ncon, pwgts), imax(nparts*ncon, pwgts), imax(nparts*ncon, maxwgt), ComputeLoadImbalance(graph, nparts, pijbm), origbal, graph->nvtxs, graph->nbnd, graph->mincut, niter); if (ctrl->minconn) printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1)); printf("\n"); } queue = rpqCreate(nvtxs); /*===================================================================== * The top-level refinement loop *======================================================================*/ for (pass=0; passmincut); /* In balancing mode, exit as soon as balance is reached */ if (omode == OMODE_BALANCE && IsBalanced(ctrl, graph, 0)) break; oldcut = graph->mincut; nbnd = graph->nbnd; nupd = 0; if (ctrl->minconn) maxndoms = imax(nparts, nads); /* Insert the boundary vertices in the priority queue */ irandArrayPermute(nbnd, perm, nbnd/4, 1); for (ii=0; iickrinfo[i].nnbrs > 0 ? 1.0*graph->ckrinfo[i].ed/sqrt(graph->ckrinfo[i].nnbrs) : 0.0) - graph->ckrinfo[i].id; rpqInsert(queue, i, rgain); vstatus[i] = VPQSTATUS_PRESENT; ListInsert(nupd, updind, updptr, i); } /* Start extracting vertices from the queue and try to move them */ for (nmoved=0, iii=0;;iii++) { if ((i = rpqGetTop(queue)) == -1) break; vstatus[i] = VPQSTATUS_EXTRACTED; myrinfo = graph->ckrinfo+i; mynbrs = ctrl->cnbrpool + myrinfo->inbr; from = where[i]; /* Prevent moves that make 'from' domain underbalanced */ if (omode == OMODE_REFINE) { if (myrinfo->id > 0 && !ivecaxpygez(ncon, -1, vwgt+i*ncon, pwgts+from*ncon, minwgt+from*ncon)) continue; } else { /* OMODE_BALANCE */ if (!ivecaxpygez(ncon, -1, vwgt+i*ncon, pwgts+from*ncon, minwgt+from*ncon)) continue; } if (ctrl->contig && IsArticulationNode(i, xadj, adjncy, where, bfslvl, bfsind, bfsmrk)) continue; if (ctrl->minconn) SelectSafeTargetSubdomains(myrinfo, mynbrs, nads, adids, maxndoms, safetos, doms); /* Find the most promising subdomain to move to */ if (omode == OMODE_REFINE) { for (k=myrinfo->nnbrs-1; k>=0; k--) { if (!safetos[to=mynbrs[k].pid]) continue; gain = mynbrs[k].ed-myrinfo->id; if (gain >= 0 && ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon)) break; } if (k < 0) continue; /* break out if you did not find a candidate */ cto = to; for (j=k-1; j>=0; j--) { if (!safetos[to=mynbrs[j].pid]) continue; if ((mynbrs[j].ed > mynbrs[k].ed && ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon)) || (mynbrs[j].ed == mynbrs[k].ed && BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, 1, pwgts+cto*ncon, pijbm+cto*ncon, 1, pwgts+to*ncon, pijbm+to*ncon))) { k = j; cto = to; } } to = cto; gain = mynbrs[k].ed-myrinfo->id; if (!(gain > 0 || (gain == 0 && (BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, -1, pwgts+from*ncon, pijbm+from*ncon, +1, pwgts+to*ncon, pijbm+to*ncon) || (iii%2 == 0 && safetos[to] == 2) ) ) ) ) continue; } else { /* OMODE_BALANCE */ for (k=myrinfo->nnbrs-1; k>=0; k--) { if (!safetos[to=mynbrs[k].pid]) continue; if (ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon) || BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, -1, pwgts+from*ncon, pijbm+from*ncon, +1, pwgts+to*ncon, pijbm+to*ncon)) break; } if (k < 0) continue; /* break out if you did not find a candidate */ cto = to; for (j=k-1; j>=0; j--) { if (!safetos[to=mynbrs[j].pid]) continue; if (BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, 1, pwgts+cto*ncon, pijbm+cto*ncon, 1, pwgts+to*ncon, pijbm+to*ncon)) { k = j; cto = to; } } to = cto; if (mynbrs[k].ed-myrinfo->id < 0 && !BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, -1, pwgts+from*ncon, pijbm+from*ncon, +1, pwgts+to*ncon, pijbm+to*ncon)) continue; } /*===================================================================== * If we got here, we can now move the vertex from 'from' to 'to' *======================================================================*/ graph->mincut -= mynbrs[k].ed-myrinfo->id; nmoved++; IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, printf("\t\tMoving %6"PRIDX" to %3"PRIDX". Gain: %4"PRIDX". Cut: %6"PRIDX"\n", i, to, mynbrs[k].ed-myrinfo->id, graph->mincut)); /* Update the subdomain connectivity information */ if (ctrl->minconn) { /* take care of i's move itself */ UpdateEdgeSubDomainGraph(ctrl, from, to, myrinfo->id-mynbrs[k].ed, &maxndoms); /* take care of the adjancent vertices */ for (j=xadj[i]; jckrinfo+ii; oldnnbrs = myrinfo->nnbrs; UpdateAdjacentVertexInfoAndBND(ctrl, ii, xadj[ii+1]-xadj[ii], me, from, to, myrinfo, adjwgt[j], nbnd, bndptr, bndind, bndtype); UpdateQueueInfo(queue, vstatus, ii, me, from, to, myrinfo, oldnnbrs, nupd, updptr, updind, bndtype); ASSERT(myrinfo->nnbrs <= xadj[ii+1]-xadj[ii]); } } graph->nbnd = nbnd; /* Reset the vstatus and associated data structures */ for (i=0; idbglvl&METIS_DBG_REFINE) { printf("\t[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL", Nb: %6"PRIDX"." " Nmoves: %5"PRIDX", Cut: %6"PRIDX", Vol: %6"PRIDX, imin(nparts*ncon, pwgts), imax(nparts*ncon, pwgts), ComputeLoadImbalance(graph, nparts, pijbm), graph->nbnd, nmoved, graph->mincut, ComputeVolume(graph, where)); if (ctrl->minconn) printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1)); printf("\n"); } if (nmoved == 0 || (omode == OMODE_REFINE && graph->mincut == oldcut)) break; } rpqDestroy(queue); WCOREPOP; } /*************************************************************************/ /*! K-way refinement that minimizes the communication volume. This is a greedy routine and the vertices are visited in decreasing gv order. \param graph is the graph that is being refined. \param niter is the number of refinement iterations. \param ffactor is the \em fudge-factor for allowing positive gain moves to violate the max-pwgt constraint. */ /**************************************************************************/ void Greedy_McKWayVolOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter, real_t ffactor, idx_t omode) { /* Common variables to all types of kway-refinement/balancing routines */ idx_t i, ii, iii, j, k, pass, nvtxs, ncon, nparts, gain; idx_t from, me, to, cto, oldcut; idx_t *xadj, *vwgt, *adjncy; idx_t *where, *pwgts, *perm, *bndind, *minwgt, *maxwgt; idx_t nmoved, nupd, *vstatus, *updptr, *updind; idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL; idx_t *bfslvl=NULL, *bfsind=NULL, *bfsmrk=NULL; idx_t bndtype = (omode == OMODE_REFINE ? BNDTYPE_REFINE : BNDTYPE_BALANCE); real_t *ubfactors, *pijbm; real_t origbal; /* Volume-specific/different variables */ ipq_t *queue; idx_t oldvol, xgain; idx_t *vmarker, *pmarker, *modind; vkrinfo_t *myrinfo; vnbr_t *mynbrs; WCOREPUSH; /* Link the graph fields */ nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; bndind = graph->bndind; where = graph->where; pwgts = graph->pwgts; nparts = ctrl->nparts; pijbm = ctrl->pijbm; /* Determine the ubfactors. The method used is different based on omode. When OMODE_BALANCE, the ubfactors are those supplied by the user. When OMODE_REFINE, the ubfactors are the max of the current partition and the user-specified ones. */ ubfactors = rwspacemalloc(ctrl, ncon); ComputeLoadImbalanceVec(graph, nparts, pijbm, ubfactors); origbal = rvecmaxdiff(ncon, ubfactors, ctrl->ubfactors); if (omode == OMODE_BALANCE) { rcopy(ncon, ctrl->ubfactors, ubfactors); } else { for (i=0; i ctrl->ubfactors[i] ? ubfactors[i] : ctrl->ubfactors[i]); } /* Setup the weight intervals of the various subdomains */ minwgt = iwspacemalloc(ctrl, nparts*ncon); maxwgt = iwspacemalloc(ctrl, nparts*ncon); for (i=0; itpwgts[i*ncon+j]*graph->tvwgt[j]*ubfactors[j]; /*minwgt[i*ncon+j] = ctrl->tpwgts[i*ncon+j]*graph->tvwgt[j]*(.9/ubfactors[j]); */ minwgt[i*ncon+j] = ctrl->tpwgts[i*ncon+j]*graph->tvwgt[j]*.2; } } perm = iwspacemalloc(ctrl, nvtxs); /* This stores the valid target subdomains. It is used when ctrl->minconn to control the subdomains to which moves are allowed to be made. When ctrl->minconn is false, the default values of 2 allow all moves to go through and it does not interfere with the zero-gain move selection. */ safetos = iset(nparts, 2, iwspacemalloc(ctrl, nparts)); if (ctrl->minconn) { ComputeSubDomainGraph(ctrl, graph); nads = ctrl->nads; adids = ctrl->adids; doms = iset(nparts, 0, ctrl->pvec1); } /* Setup updptr, updind like boundary info to keep track of the vertices whose vstatus's need to be reset at the end of the inner iteration */ vstatus = iset(nvtxs, VPQSTATUS_NOTPRESENT, iwspacemalloc(ctrl, nvtxs)); updptr = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs)); updind = iwspacemalloc(ctrl, nvtxs); if (ctrl->contig) { /* The arrays that will be used for limited check of articulation points */ bfslvl = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); bfsind = iwspacemalloc(ctrl, nvtxs); bfsmrk = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); } /* Vol-refinement specific working arrays */ modind = iwspacemalloc(ctrl, nvtxs); vmarker = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); pmarker = iset(nparts, -1, iwspacemalloc(ctrl, nparts)); if (ctrl->dbglvl&METIS_DBG_REFINE) { printf("%s: [%6"PRIDX" %6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL"(%.3"PRREAL")," ", Nv-Nb[%6"PRIDX" %6"PRIDX"], Cut: %5"PRIDX", Vol: %5"PRIDX", (%"PRIDX")", (omode == OMODE_REFINE ? "GRV" : "GBV"), imin(nparts*ncon, pwgts), imax(nparts*ncon, pwgts), imax(nparts*ncon, maxwgt), ComputeLoadImbalance(graph, nparts, pijbm), origbal, graph->nvtxs, graph->nbnd, graph->mincut, graph->minvol, niter); if (ctrl->minconn) printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1)); printf("\n"); } queue = ipqCreate(nvtxs); /*===================================================================== * The top-level refinement loop *======================================================================*/ for (pass=0; passminvol); /* In balancing mode, exit as soon as balance is reached */ if (omode == OMODE_BALANCE && IsBalanced(ctrl, graph, 0)) break; oldcut = graph->mincut; oldvol = graph->minvol; nupd = 0; if (ctrl->minconn) maxndoms = imax(nparts, nads); /* Insert the boundary vertices in the priority queue */ irandArrayPermute(graph->nbnd, perm, graph->nbnd/4, 1); for (ii=0; iinbnd; ii++) { i = bndind[perm[ii]]; ipqInsert(queue, i, graph->vkrinfo[i].gv); vstatus[i] = VPQSTATUS_PRESENT; ListInsert(nupd, updind, updptr, i); } /* Start extracting vertices from the queue and try to move them */ for (nmoved=0, iii=0;;iii++) { if ((i = ipqGetTop(queue)) == -1) break; vstatus[i] = VPQSTATUS_EXTRACTED; myrinfo = graph->vkrinfo+i; mynbrs = ctrl->vnbrpool + myrinfo->inbr; from = where[i]; /* Prevent moves that make 'from' domain underbalanced */ if (omode == OMODE_REFINE) { if (myrinfo->nid > 0 && !ivecaxpygez(ncon, -1, vwgt+i*ncon, pwgts+from*ncon, minwgt+from*ncon)) continue; } else { /* OMODE_BALANCE */ if (!ivecaxpygez(ncon, -1, vwgt+i*ncon, pwgts+from*ncon, minwgt+from*ncon)) continue; } if (ctrl->contig && IsArticulationNode(i, xadj, adjncy, where, bfslvl, bfsind, bfsmrk)) continue; if (ctrl->minconn) SelectSafeTargetSubdomains(myrinfo, mynbrs, nads, adids, maxndoms, safetos, doms); xgain = (myrinfo->nid == 0 && myrinfo->ned > 0 ? graph->vsize[i] : 0); /* Find the most promising subdomain to move to */ if (omode == OMODE_REFINE) { for (k=myrinfo->nnbrs-1; k>=0; k--) { if (!safetos[to=mynbrs[k].pid]) continue; gain = mynbrs[k].gv + xgain; if (gain >= 0 && ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon)) break; } if (k < 0) continue; /* break out if you did not find a candidate */ cto = to; for (j=k-1; j>=0; j--) { if (!safetos[to=mynbrs[j].pid]) continue; gain = mynbrs[j].gv + xgain; if ((mynbrs[j].gv > mynbrs[k].gv && ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon)) || (mynbrs[j].gv == mynbrs[k].gv && mynbrs[j].ned > mynbrs[k].ned && ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon)) || (mynbrs[j].gv == mynbrs[k].gv && mynbrs[j].ned == mynbrs[k].ned && BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, 1, pwgts+cto*ncon, pijbm+cto*ncon, 1, pwgts+to*ncon, pijbm+to*ncon))) { k = j; cto = to; } } to = cto; j = 0; if (xgain+mynbrs[k].gv > 0 || mynbrs[k].ned-myrinfo->nid > 0) j = 1; else if (mynbrs[k].ned-myrinfo->nid == 0) { if ((iii%2 == 0 && safetos[to] == 2) || BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, -1, pwgts+from*ncon, pijbm+from*ncon, +1, pwgts+to*ncon, pijbm+to*ncon)) j = 1; } if (j == 0) continue; } else { /* OMODE_BALANCE */ for (k=myrinfo->nnbrs-1; k>=0; k--) { if (!safetos[to=mynbrs[k].pid]) continue; if (ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon) || BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, -1, pwgts+from*ncon, pijbm+from*ncon, +1, pwgts+to*ncon, pijbm+to*ncon)) break; } if (k < 0) continue; /* break out if you did not find a candidate */ cto = to; for (j=k-1; j>=0; j--) { if (!safetos[to=mynbrs[j].pid]) continue; if (BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, 1, pwgts+cto*ncon, pijbm+cto*ncon, 1, pwgts+to*ncon, pijbm+to*ncon)) { k = j; cto = to; } } to = cto; if ((xgain+mynbrs[k].gv < 0 || (xgain+mynbrs[k].gv == 0 && mynbrs[k].ned-myrinfo->nid < 0)) && !BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors, -1, pwgts+from*ncon, pijbm+from*ncon, +1, pwgts+to*ncon, pijbm+to*ncon)) continue; } /*===================================================================== * If we got here, we can now move the vertex from 'from' to 'to' *======================================================================*/ graph->mincut -= mynbrs[k].ned-myrinfo->nid; graph->minvol -= (xgain+mynbrs[k].gv); where[i] = to; nmoved++; IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, printf("\t\tMoving %6"PRIDX" from %3"PRIDX" to %3"PRIDX". " "Gain: [%4"PRIDX" %4"PRIDX"]. Cut: %6"PRIDX", Vol: %6"PRIDX"\n", i, from, to, xgain+mynbrs[k].gv, mynbrs[k].ned-myrinfo->nid, graph->mincut, graph->minvol)); /* Update the subdomain connectivity information */ if (ctrl->minconn) { /* take care of i's move itself */ UpdateEdgeSubDomainGraph(ctrl, from, to, myrinfo->nid-mynbrs[k].ned, &maxndoms); /* take care of the adjancent vertices */ for (j=xadj[i]; jdbglvl&METIS_DBG_REFINE) { printf("\t[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL", Nb: %6"PRIDX"." " Nmoves: %5"PRIDX", Cut: %6"PRIDX", Vol: %6"PRIDX, imin(nparts*ncon, pwgts), imax(nparts*ncon, pwgts), ComputeLoadImbalance(graph, nparts, pijbm), graph->nbnd, nmoved, graph->mincut, graph->minvol); if (ctrl->minconn) printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1)); printf("\n"); } if (nmoved == 0 || (omode == OMODE_REFINE && graph->minvol == oldvol && graph->mincut == oldcut)) break; } ipqDestroy(queue); WCOREPOP; } /*************************************************************************/ /*! This function performs an approximate articulation vertex test. It assumes that the bfslvl, bfsind, and bfsmrk arrays are initialized appropriately. */ /*************************************************************************/ idx_t IsArticulationNode(idx_t i, idx_t *xadj, idx_t *adjncy, idx_t *where, idx_t *bfslvl, idx_t *bfsind, idx_t *bfsmrk) { idx_t ii, j, k=0, head, tail, nhits, tnhits, from, BFSDEPTH=5; from = where[i]; /* Determine if the vertex is safe to move from a contiguity standpoint */ for (tnhits=0, j=xadj[i]; jxadj; adjncy = graph->adjncy; vsize = graph->vsize; where = graph->where; myrinfo = graph->vkrinfo+v; mynbrs = ctrl->vnbrpool + myrinfo->inbr; /*====================================================================== * Remove the contributions on the gain made by 'v'. *=====================================================================*/ for (k=0; knnbrs; k++) pmarker[mynbrs[k].pid] = k; pmarker[from] = k; myidx = pmarker[to]; /* Keep track of the index in mynbrs of the 'to' domain */ for (j=xadj[v]; jvkrinfo+ii; onbrs = ctrl->vnbrpool + orinfo->inbr; if (other == from) { for (k=0; knnbrs; k++) { if (pmarker[onbrs[k].pid] == -1) onbrs[k].gv += vsize[v]; } } else { ASSERT(pmarker[other] != -1); if (mynbrs[pmarker[other]].ned > 1) { for (k=0; knnbrs; k++) { if (pmarker[onbrs[k].pid] == -1) onbrs[k].gv += vsize[v]; } } else { /* There is only one connection */ for (k=0; knnbrs; k++) { if (pmarker[onbrs[k].pid] != -1) onbrs[k].gv -= vsize[v]; } } } } for (k=0; knnbrs; k++) pmarker[mynbrs[k].pid] = -1; pmarker[from] = -1; /*====================================================================== * Update the id/ed of vertex 'v' *=====================================================================*/ if (myidx == -1) { myidx = myrinfo->nnbrs++; ASSERT(myidx < xadj[v+1]-xadj[v]); mynbrs[myidx].ned = 0; } myrinfo->ned += myrinfo->nid-mynbrs[myidx].ned; SWAP(myrinfo->nid, mynbrs[myidx].ned, j); if (mynbrs[myidx].ned == 0) mynbrs[myidx] = mynbrs[--myrinfo->nnbrs]; else mynbrs[myidx].pid = from; /*====================================================================== * Update the degrees of adjacent vertices and their volume gains *=====================================================================*/ vmarker[v] = 1; modind[0] = v; nmod = 1; for (j=xadj[v]; jvkrinfo+ii; if (myrinfo->inbr == -1) myrinfo->inbr = vnbrpoolGetNext(ctrl, xadj[ii+1]-xadj[ii]+1); mynbrs = ctrl->vnbrpool + myrinfo->inbr; if (me == from) { INC_DEC(myrinfo->ned, myrinfo->nid, 1); } else if (me == to) { INC_DEC(myrinfo->nid, myrinfo->ned, 1); } /* Remove the edgeweight from the 'pid == from' entry of the vertex */ if (me != from) { for (k=0; knnbrs; k++) { if (mynbrs[k].pid == from) { if (mynbrs[k].ned == 1) { mynbrs[k] = mynbrs[--myrinfo->nnbrs]; vmarker[ii] = 1; /* You do a complete .gv calculation */ /* All vertices adjacent to 'ii' need to be updated */ for (jj=xadj[ii]; jjvkrinfo+u; onbrs = ctrl->vnbrpool + orinfo->inbr; for (kk=0; kknnbrs; kk++) { if (onbrs[kk].pid == from) { onbrs[kk].gv -= vsize[ii]; if (!vmarker[u]) { /* Need to update boundary etc */ vmarker[u] = 2; modind[nmod++] = u; } break; } } } } else { mynbrs[k].ned--; /* Update the gv due to single 'ii' connection to 'from' */ if (mynbrs[k].ned == 1) { /* find the vertex 'u' that 'ii' was connected into 'from' */ for (jj=xadj[ii]; jjvkrinfo+u; onbrs = ctrl->vnbrpool + orinfo->inbr; /* The following is correct because domains in common between ii and u will lead to a reduction over the previous gain, whereas domains only in u but not in ii, will lead to no change as opposed to the earlier increase */ for (kk=0; kknnbrs; kk++) onbrs[kk].gv += vsize[ii]; if (!vmarker[u]) { /* Need to update boundary etc */ vmarker[u] = 2; modind[nmod++] = u; } break; } } } } break; } } } /* Add the edgeweight to the 'pid == to' entry of the vertex */ if (me != to) { for (k=0; knnbrs; k++) { if (mynbrs[k].pid == to) { mynbrs[k].ned++; /* Update the gv due to non-single 'ii' connection to 'to' */ if (mynbrs[k].ned == 2) { /* find the vertex 'u' that 'ii' was connected into 'to' */ for (jj=xadj[ii]; jjvkrinfo+u; onbrs = ctrl->vnbrpool + orinfo->inbr; for (kk=0; kknnbrs; kk++) onbrs[kk].gv -= vsize[ii]; if (!vmarker[u]) { /* Need to update boundary etc */ vmarker[u] = 2; modind[nmod++] = u; } break; } } } break; } } if (k == myrinfo->nnbrs) { mynbrs[myrinfo->nnbrs].pid = to; mynbrs[myrinfo->nnbrs++].ned = 1; vmarker[ii] = 1; /* You do a complete .gv calculation */ /* All vertices adjacent to 'ii' need to be updated */ for (jj=xadj[ii]; jjvkrinfo+u; onbrs = ctrl->vnbrpool + orinfo->inbr; for (kk=0; kknnbrs; kk++) { if (onbrs[kk].pid == to) { onbrs[kk].gv += vsize[ii]; if (!vmarker[u]) { /* Need to update boundary etc */ vmarker[u] = 2; modind[nmod++] = u; } break; } } } } } ASSERT(myrinfo->nnbrs <= xadj[ii+1]-xadj[ii]); } /*====================================================================== * Add the contributions on the volume gain due to 'v' *=====================================================================*/ myrinfo = graph->vkrinfo+v; mynbrs = ctrl->vnbrpool + myrinfo->inbr; for (k=0; knnbrs; k++) pmarker[mynbrs[k].pid] = k; pmarker[to] = k; for (j=xadj[v]; jvkrinfo+ii; onbrs = ctrl->vnbrpool + orinfo->inbr; if (other == to) { for (k=0; knnbrs; k++) { if (pmarker[onbrs[k].pid] == -1) onbrs[k].gv -= vsize[v]; } } else { ASSERT(pmarker[other] != -1); if (mynbrs[pmarker[other]].ned > 1) { for (k=0; knnbrs; k++) { if (pmarker[onbrs[k].pid] == -1) onbrs[k].gv -= vsize[v]; } } else { /* There is only one connection */ for (k=0; knnbrs; k++) { if (pmarker[onbrs[k].pid] != -1) onbrs[k].gv += vsize[v]; } } } } for (k=0; knnbrs; k++) pmarker[mynbrs[k].pid] = -1; pmarker[to] = -1; /*====================================================================== * Recompute the volume information of the 'hard' nodes, and update the * max volume gain for all the modified vertices and the priority queue *=====================================================================*/ for (iii=0; iiivkrinfo+i; mynbrs = ctrl->vnbrpool + myrinfo->inbr; if (vmarker[i] == 1) { /* Only complete gain updates go through */ for (k=0; knnbrs; k++) mynbrs[k].gv = 0; for (j=xadj[i]; jvkrinfo+ii; onbrs = ctrl->vnbrpool + orinfo->inbr; for (kk=0; kknnbrs; kk++) pmarker[onbrs[kk].pid] = kk; pmarker[other] = 1; if (me == other) { /* Find which domains 'i' is connected and 'ii' is not and update their gain */ for (k=0; knnbrs; k++) { if (pmarker[mynbrs[k].pid] == -1) mynbrs[k].gv -= vsize[ii]; } } else { ASSERT(pmarker[me] != -1); /* I'm the only connection of 'ii' in 'me' */ if (onbrs[pmarker[me]].ned == 1) { /* Increase the gains for all the common domains between 'i' and 'ii' */ for (k=0; knnbrs; k++) { if (pmarker[mynbrs[k].pid] != -1) mynbrs[k].gv += vsize[ii]; } } else { /* Find which domains 'i' is connected and 'ii' is not and update their gain */ for (k=0; knnbrs; k++) { if (pmarker[mynbrs[k].pid] == -1) mynbrs[k].gv -= vsize[ii]; } } } for (kk=0; kknnbrs; kk++) pmarker[onbrs[kk].pid] = -1; pmarker[other] = -1; } } /* Compute the overall gv for that node */ myrinfo->gv = IDX_MIN; for (k=0; knnbrs; k++) { if (mynbrs[k].gv > myrinfo->gv) myrinfo->gv = mynbrs[k].gv; } /* Add the xtra gain due to id == 0 */ if (myrinfo->ned > 0 && myrinfo->nid == 0) myrinfo->gv += vsize[i]; /*====================================================================== * Maintain a consistent boundary *=====================================================================*/ if (bndtype == BNDTYPE_REFINE) { if (myrinfo->gv >= 0 && graph->bndptr[i] == -1) BNDInsert(graph->nbnd, graph->bndind, graph->bndptr, i); if (myrinfo->gv < 0 && graph->bndptr[i] != -1) BNDDelete(graph->nbnd, graph->bndind, graph->bndptr, i); } else { if (myrinfo->ned > 0 && graph->bndptr[i] == -1) BNDInsert(graph->nbnd, graph->bndind, graph->bndptr, i); if (myrinfo->ned == 0 && graph->bndptr[i] != -1) BNDDelete(graph->nbnd, graph->bndind, graph->bndptr, i); } /*====================================================================== * Update the priority queue appropriately (if allowed) *=====================================================================*/ if (queue != NULL) { if (vstatus[i] != VPQSTATUS_EXTRACTED) { if (graph->bndptr[i] != -1) { /* In-boundary vertex */ if (vstatus[i] == VPQSTATUS_PRESENT) { ipqUpdate(queue, i, myrinfo->gv); } else { ipqInsert(queue, i, myrinfo->gv); vstatus[i] = VPQSTATUS_PRESENT; ListInsert(*r_nupd, updind, updptr, i); } } else { /* Off-boundary vertex */ if (vstatus[i] == VPQSTATUS_PRESENT) { ipqDelete(queue, i); vstatus[i] = VPQSTATUS_NOTPRESENT; ListDelete(*r_nupd, updind, updptr, i); } } } } vmarker[i] = 0; } } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/options.c0000644000175100001440000004423014552244506025010 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /** \file \brief This file contains various routines for dealing with options and ctrl_t. \date Started 5/12/2011 \author George \author Copyright 1997-2011, Regents of the University of Minnesota \version\verbatim $Id: options.c 13901 2013-03-24 16:17:03Z karypis $ \endverbatim */ #include "metislib.h" /*************************************************************************/ /*! This function creates and sets the run parameters (ctrl_t) */ /*************************************************************************/ ctrl_t *SetupCtrl(moptype_et optype, idx_t *options, idx_t ncon, idx_t nparts, real_t *tpwgts, real_t *ubvec) { idx_t i, j; ctrl_t *ctrl; ctrl = (ctrl_t *)gk_malloc(sizeof(ctrl_t), "SetupCtrl: ctrl"); memset((void *)ctrl, 0, sizeof(ctrl_t)); switch (optype) { case METIS_OP_PMETIS: ctrl->objtype = GETOPTION(options, METIS_OPTION_OBJTYPE, METIS_OBJTYPE_CUT); ctrl->rtype = METIS_RTYPE_FM; ctrl->ncuts = GETOPTION(options, METIS_OPTION_NCUTS, 1); ctrl->niter = GETOPTION(options, METIS_OPTION_NITER, 10); if (ncon == 1) { ctrl->iptype = GETOPTION(options, METIS_OPTION_IPTYPE, METIS_IPTYPE_GROW); ctrl->ufactor = GETOPTION(options, METIS_OPTION_UFACTOR, PMETIS_DEFAULT_UFACTOR); ctrl->CoarsenTo = 20; } else { ctrl->iptype = GETOPTION(options, METIS_OPTION_IPTYPE, METIS_IPTYPE_RANDOM); ctrl->ufactor = GETOPTION(options, METIS_OPTION_UFACTOR, MCPMETIS_DEFAULT_UFACTOR); ctrl->CoarsenTo = 100; } break; case METIS_OP_KMETIS: ctrl->objtype = GETOPTION(options, METIS_OPTION_OBJTYPE, METIS_OBJTYPE_CUT); ctrl->iptype = METIS_IPTYPE_METISRB; ctrl->rtype = METIS_RTYPE_GREEDY; ctrl->ncuts = GETOPTION(options, METIS_OPTION_NCUTS, 1); ctrl->niter = GETOPTION(options, METIS_OPTION_NITER, 10); ctrl->ufactor = GETOPTION(options, METIS_OPTION_UFACTOR, KMETIS_DEFAULT_UFACTOR); ctrl->minconn = GETOPTION(options, METIS_OPTION_MINCONN, 0); ctrl->contig = GETOPTION(options, METIS_OPTION_CONTIG, 0); break; case METIS_OP_OMETIS: ctrl->objtype = GETOPTION(options, METIS_OPTION_OBJTYPE, METIS_OBJTYPE_NODE); ctrl->rtype = GETOPTION(options, METIS_OPTION_RTYPE, METIS_RTYPE_SEP1SIDED); ctrl->iptype = GETOPTION(options, METIS_OPTION_IPTYPE, METIS_IPTYPE_EDGE); ctrl->nseps = GETOPTION(options, METIS_OPTION_NSEPS, 1); ctrl->niter = GETOPTION(options, METIS_OPTION_NITER, 10); ctrl->ufactor = GETOPTION(options, METIS_OPTION_UFACTOR, OMETIS_DEFAULT_UFACTOR); ctrl->compress = GETOPTION(options, METIS_OPTION_COMPRESS, 1); ctrl->ccorder = GETOPTION(options, METIS_OPTION_CCORDER, 0); ctrl->pfactor = 0.1*GETOPTION(options, METIS_OPTION_PFACTOR, 0); ctrl->CoarsenTo = 100; break; default: gk_errexit(SIGERR, "Unknown optype of %d\n", optype); } /* common options */ ctrl->ctype = GETOPTION(options, METIS_OPTION_CTYPE, METIS_CTYPE_SHEM); ctrl->no2hop = GETOPTION(options, METIS_OPTION_NO2HOP, 0); ctrl->seed = GETOPTION(options, METIS_OPTION_SEED, -1); ctrl->dbglvl = GETOPTION(options, METIS_OPTION_DBGLVL, 0); ctrl->numflag = GETOPTION(options, METIS_OPTION_NUMBERING, 0); /* set non-option information */ ctrl->optype = optype; ctrl->ncon = ncon; ctrl->nparts = nparts; ctrl->maxvwgt = ismalloc(ncon, 0, "SetupCtrl: maxvwgt"); /* setup the target partition weights */ if (ctrl->optype != METIS_OP_OMETIS) { ctrl->tpwgts = rmalloc(nparts*ncon, "SetupCtrl: ctrl->tpwgts"); if (tpwgts) { rcopy(nparts*ncon, tpwgts, ctrl->tpwgts); } else { for (i=0; itpwgts[i*ncon+j] = 1.0/nparts; } } } else { /* METIS_OP_OMETIS */ /* this is required to allow the pijbm to be defined properly for the edge-based refinement during initial partitioning */ ctrl->tpwgts = rsmalloc(2, .5, "SetupCtrl: ctrl->tpwgts"); } /* setup the ubfactors */ ctrl->ubfactors = rsmalloc(ctrl->ncon, I2RUBFACTOR(ctrl->ufactor), "SetupCtrl: ubfactors"); if (ubvec) rcopy(ctrl->ncon, ubvec, ctrl->ubfactors); for (i=0; incon; i++) ctrl->ubfactors[i] += 0.0000499; /* Allocate memory for balance multipliers. Note that for PMETIS/OMETIS routines the memory allocated is more than required as balance multipliers for 2 parts is sufficient. */ ctrl->pijbm = rmalloc(nparts*ncon, "SetupCtrl: ctrl->pijbm"); InitRandom(ctrl->seed); IFSET(ctrl->dbglvl, METIS_DBG_INFO, PrintCtrl(ctrl)); if (!CheckParams(ctrl)) { FreeCtrl(&ctrl); return NULL; } else { return ctrl; } } /*************************************************************************/ /*! Computes the per-partition/constraint balance multipliers */ /*************************************************************************/ void SetupKWayBalMultipliers(ctrl_t *ctrl, graph_t *graph) { idx_t i, j; for (i=0; inparts; i++) { for (j=0; jncon; j++) ctrl->pijbm[i*graph->ncon+j] = graph->invtvwgt[j]/ctrl->tpwgts[i*graph->ncon+j]; } } /*************************************************************************/ /*! Computes the per-partition/constraint balance multipliers */ /*************************************************************************/ void Setup2WayBalMultipliers(ctrl_t *ctrl, graph_t *graph, real_t *tpwgts) { idx_t i, j; for (i=0; i<2; i++) { for (j=0; jncon; j++) ctrl->pijbm[i*graph->ncon+j] = graph->invtvwgt[j]/tpwgts[i*graph->ncon+j]; } } /*************************************************************************/ /*! This function prints the various control fields */ /*************************************************************************/ void PrintCtrl(ctrl_t *ctrl) { idx_t i, j, modnum; printf(" Runtime parameters:\n"); printf(" Objective type: "); switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: printf("METIS_OBJTYPE_CUT\n"); break; case METIS_OBJTYPE_VOL: printf("METIS_OBJTYPE_VOL\n"); break; case METIS_OBJTYPE_NODE: printf("METIS_OBJTYPE_NODE\n"); break; default: printf("Unknown!\n"); } printf(" Coarsening type: "); switch (ctrl->ctype) { case METIS_CTYPE_RM: printf("METIS_CTYPE_RM\n"); break; case METIS_CTYPE_SHEM: printf("METIS_CTYPE_SHEM\n"); break; default: printf("Unknown!\n"); } printf(" Initial partitioning type: "); switch (ctrl->iptype) { case METIS_IPTYPE_GROW: printf("METIS_IPTYPE_GROW\n"); break; case METIS_IPTYPE_RANDOM: printf("METIS_IPTYPE_RANDOM\n"); break; case METIS_IPTYPE_EDGE: printf("METIS_IPTYPE_EDGE\n"); break; case METIS_IPTYPE_NODE: printf("METIS_IPTYPE_NODE\n"); break; case METIS_IPTYPE_METISRB: printf("METIS_IPTYPE_METISRB\n"); break; default: printf("Unknown!\n"); } printf(" Refinement type: "); switch (ctrl->rtype) { case METIS_RTYPE_FM: printf("METIS_RTYPE_FM\n"); break; case METIS_RTYPE_GREEDY: printf("METIS_RTYPE_GREEDY\n"); break; case METIS_RTYPE_SEP2SIDED: printf("METIS_RTYPE_SEP2SIDED\n"); break; case METIS_RTYPE_SEP1SIDED: printf("METIS_RTYPE_SEP1SIDED\n"); break; default: printf("Unknown!\n"); } printf(" Perform a 2-hop matching: %s\n", (ctrl->no2hop ? "Yes" : "No")); printf(" Number of balancing constraints: %"PRIDX"\n", ctrl->ncon); printf(" Number of refinement iterations: %"PRIDX"\n", ctrl->niter); printf(" Random number seed: %"PRIDX"\n", ctrl->seed); if (ctrl->optype == METIS_OP_OMETIS) { printf(" Number of separators: %"PRIDX"\n", ctrl->nseps); printf(" Compress graph prior to ordering: %s\n", (ctrl->compress ? "Yes" : "No")); printf(" Detect & order connected components separately: %s\n", (ctrl->ccorder ? "Yes" : "No")); printf(" Prunning factor for high degree vertices: %"PRREAL"\n", ctrl->pfactor); } else { printf(" Number of partitions: %"PRIDX"\n", ctrl->nparts); printf(" Number of cuts: %"PRIDX"\n", ctrl->ncuts); printf(" User-supplied ufactor: %"PRIDX"\n", ctrl->ufactor); if (ctrl->optype == METIS_OP_KMETIS) { printf(" Minimize connectivity: %s\n", (ctrl->minconn ? "Yes" : "No")); printf(" Create contigous partitions: %s\n", (ctrl->contig ? "Yes" : "No")); } modnum = (ctrl->ncon==1 ? 5 : (ctrl->ncon==2 ? 3 : (ctrl->ncon==3 ? 2 : 1))); printf(" Target partition weights: "); for (i=0; inparts; i++) { if (i%modnum == 0) printf("\n "); printf("%4"PRIDX"=[", i); for (j=0; jncon; j++) printf("%s%.2e", (j==0 ? "" : " "), (double)ctrl->tpwgts[i*ctrl->ncon+j]); printf("]"); } printf("\n"); } printf(" Allowed maximum load imbalance: "); for (i=0; incon; i++) printf("%.3"PRREAL" ", ctrl->ubfactors[i]); printf("\n"); printf("\n"); } /*************************************************************************/ /*! This function checks the validity of user-supplied parameters */ /*************************************************************************/ int CheckParams(ctrl_t *ctrl) { idx_t i, j; real_t sum; mdbglvl_et dbglvl=METIS_DBG_INFO; switch (ctrl->optype) { case METIS_OP_PMETIS: if (ctrl->objtype != METIS_OBJTYPE_CUT) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect objective type.\n")); return 0; } if (ctrl->ctype != METIS_CTYPE_RM && ctrl->ctype != METIS_CTYPE_SHEM) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect coarsening scheme.\n")); return 0; } if (ctrl->iptype != METIS_IPTYPE_GROW && ctrl->iptype != METIS_IPTYPE_RANDOM) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect initial partitioning scheme.\n")); return 0; } if (ctrl->rtype != METIS_RTYPE_FM) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect refinement scheme.\n")); return 0; } if (ctrl->ncuts <= 0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ncuts.\n")); return 0; } if (ctrl->niter <= 0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect niter.\n")); return 0; } if (ctrl->ufactor <= 0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ufactor.\n")); return 0; } if (ctrl->numflag != 0 && ctrl->numflag != 1) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect numflag.\n")); return 0; } if (ctrl->nparts <= 0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect nparts.\n")); return 0; } if (ctrl->ncon <= 0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ncon.\n")); return 0; } for (i=0; incon; i++) { sum = rsum(ctrl->nparts, ctrl->tpwgts+i, ctrl->ncon); if (sum < 0.99 || sum > 1.01) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect sum of %"PRREAL" for tpwgts for constraint %"PRIDX".\n", sum, i)); return 0; } } for (i=0; incon; i++) { for (j=0; jnparts; j++) { if (ctrl->tpwgts[j*ctrl->ncon+i] <= 0.0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect tpwgts for partition %"PRIDX" and constraint %"PRIDX".\n", j, i)); return 0; } } } for (i=0; incon; i++) { if (ctrl->ubfactors[i] <= 1.0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ubfactor for constraint %"PRIDX".\n", i)); return 0; } } break; case METIS_OP_KMETIS: if (ctrl->objtype != METIS_OBJTYPE_CUT && ctrl->objtype != METIS_OBJTYPE_VOL) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect objective type.\n")); return 0; } if (ctrl->ctype != METIS_CTYPE_RM && ctrl->ctype != METIS_CTYPE_SHEM) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect coarsening scheme.\n")); return 0; } if (ctrl->iptype != METIS_IPTYPE_METISRB) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect initial partitioning scheme.\n")); return 0; } if (ctrl->rtype != METIS_RTYPE_GREEDY) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect refinement scheme.\n")); return 0; } if (ctrl->ncuts <= 0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ncuts.\n")); return 0; } if (ctrl->niter <= 0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect niter.\n")); return 0; } if (ctrl->ufactor <= 0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ufactor.\n")); return 0; } if (ctrl->numflag != 0 && ctrl->numflag != 1) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect numflag.\n")); return 0; } if (ctrl->nparts <= 0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect nparts.\n")); return 0; } if (ctrl->ncon <= 0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ncon.\n")); return 0; } if (ctrl->contig != 0 && ctrl->contig != 1) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect contig.\n")); return 0; } if (ctrl->minconn != 0 && ctrl->minconn != 1) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect minconn.\n")); return 0; } for (i=0; incon; i++) { sum = rsum(ctrl->nparts, ctrl->tpwgts+i, ctrl->ncon); if (sum < 0.99 || sum > 1.01) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect sum of %"PRREAL" for tpwgts for constraint %"PRIDX".\n", sum, i)); return 0; } } for (i=0; incon; i++) { for (j=0; jnparts; j++) { if (ctrl->tpwgts[j*ctrl->ncon+i] <= 0.0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect tpwgts for partition %"PRIDX" and constraint %"PRIDX".\n", j, i)); return 0; } } } for (i=0; incon; i++) { if (ctrl->ubfactors[i] <= 1.0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ubfactor for constraint %"PRIDX".\n", i)); return 0; } } break; case METIS_OP_OMETIS: if (ctrl->objtype != METIS_OBJTYPE_NODE) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect objective type.\n")); return 0; } if (ctrl->ctype != METIS_CTYPE_RM && ctrl->ctype != METIS_CTYPE_SHEM) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect coarsening scheme.\n")); return 0; } if (ctrl->iptype != METIS_IPTYPE_EDGE && ctrl->iptype != METIS_IPTYPE_NODE) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect initial partitioning scheme.\n")); return 0; } if (ctrl->rtype != METIS_RTYPE_SEP1SIDED && ctrl->rtype != METIS_RTYPE_SEP2SIDED) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect refinement scheme.\n")); return 0; } if (ctrl->nseps <= 0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect nseps.\n")); return 0; } if (ctrl->niter <= 0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect niter.\n")); return 0; } if (ctrl->ufactor <= 0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ufactor.\n")); return 0; } if (ctrl->numflag != 0 && ctrl->numflag != 1) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect numflag.\n")); return 0; } if (ctrl->nparts != 3) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect nparts.\n")); return 0; } if (ctrl->ncon != 1) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ncon.\n")); return 0; } if (ctrl->compress != 0 && ctrl->compress != 1) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect compress.\n")); return 0; } if (ctrl->ccorder != 0 && ctrl->ccorder != 1) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ccorder.\n")); return 0; } if (ctrl->pfactor < 0.0 ) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect pfactor.\n")); return 0; } for (i=0; incon; i++) { if (ctrl->ubfactors[i] <= 1.0) { IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect ubfactor for constraint %"PRIDX".\n", i)); return 0; } } break; default: IFSET(dbglvl, METIS_DBG_INFO, printf("Input Error: Incorrect optype\n")); return 0; } return 1; } /*************************************************************************/ /*! This function frees the memory associated with a ctrl_t */ /*************************************************************************/ void FreeCtrl(ctrl_t **r_ctrl) { ctrl_t *ctrl = *r_ctrl; FreeWorkSpace(ctrl); gk_free((void **)&ctrl->tpwgts, &ctrl->pijbm, &ctrl->ubfactors, &ctrl->maxvwgt, &ctrl, LTERM); *r_ctrl = NULL; } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/bucketsort.c0000644000175100001440000000300614552244506025476 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * bucketsort.c * * This file contains code that implement a variety of counting sorting * algorithms * * Started 7/25/97 * George * */ #include "metislib.h" /************************************************************************* * This function uses simple counting sort to return a permutation array * corresponding to the sorted order. The keys are arsumed to start from * 0 and they are positive. This sorting is used during matching. **************************************************************************/ void BucketSortKeysInc(ctrl_t *ctrl, idx_t n, idx_t max, idx_t *keys, idx_t *tperm, idx_t *perm) { idx_t i, ii; idx_t *counts; WCOREPUSH; counts = iset(max+2, 0, iwspacemalloc(ctrl, max+2)); for (i=0; i (b)) GK_MKPQUEUE(ipq, ipq_t, ikv_t, idx_t, idx_t, ikvmalloc, IDX_MAX, key_gt) GK_MKPQUEUE(rpq, rpq_t, rkv_t, real_t, idx_t, rkvmalloc, REAL_MAX, key_gt) #undef key_gt /*************************************************************************/ /*! Random number generation routines */ /*************************************************************************/ GK_MKRANDOM(i, idx_t, idx_t) /*************************************************************************/ /*! Utility routines */ /*************************************************************************/ GK_MKARRAY2CSR(i, idx_t) /*************************************************************************/ /*! Sorting routines */ /*************************************************************************/ void isorti(size_t n, idx_t *base) { #define i_lt(a, b) ((*a) < (*b)) GK_MKQSORT(idx_t, base, n, i_lt); #undef i_lt } void isortd(size_t n, idx_t *base) { #define i_gt(a, b) ((*a) > (*b)) GK_MKQSORT(idx_t, base, n, i_gt); #undef i_gt } void rsorti(size_t n, real_t *base) { #define r_lt(a, b) ((*a) < (*b)) GK_MKQSORT(real_t, base, n, r_lt); #undef r_lt } void rsortd(size_t n, real_t *base) { #define r_gt(a, b) ((*a) > (*b)) GK_MKQSORT(real_t, base, n, r_gt); #undef r_gt } void ikvsorti(size_t n, ikv_t *base) { #define ikey_lt(a, b) ((a)->key < (b)->key) GK_MKQSORT(ikv_t, base, n, ikey_lt); #undef ikey_lt } /* Sorts based both on key and val */ void ikvsortii(size_t n, ikv_t *base) { #define ikeyval_lt(a, b) ((a)->key < (b)->key || ((a)->key == (b)->key && (a)->val < (b)->val)) GK_MKQSORT(ikv_t, base, n, ikeyval_lt); #undef ikeyval_lt } void ikvsortd(size_t n, ikv_t *base) { #define ikey_gt(a, b) ((a)->key > (b)->key) GK_MKQSORT(ikv_t, base, n, ikey_gt); #undef ikey_gt } void rkvsorti(size_t n, rkv_t *base) { #define rkey_lt(a, b) ((a)->key < (b)->key) GK_MKQSORT(rkv_t, base, n, rkey_lt); #undef rkey_lt } void rkvsortd(size_t n, rkv_t *base) { #define rkey_gt(a, b) ((a)->key > (b)->key) GK_MKQSORT(rkv_t, base, n, rkey_gt); #undef rkey_gt } void uvwsorti(size_t n, uvw_t *base) { #define uvwkey_lt(a, b) ((a)->u < (b)->u || ((a)->u == (b)->u && (a)->v < (b)->v)) GK_MKQSORT(uvw_t, base, n, uvwkey_lt); #undef uvwkey_lt } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/contig.c0000644000175100001440000005233614552244506024606 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file \brief Functions that deal with eliminating disconnected partitions \date Started 7/15/98 \author George \author Copyright 1997-2009, Regents of the University of Minnesota \version $Id: contig.c 10513 2011-07-07 22:06:03Z karypis $ */ #include "metislib.h" /*************************************************************************/ /*! This function finds the connected components induced by the partitioning vector. \param graph is the graph structure \param where is the partitioning vector. If this is NULL, then the entire graph is treated to belong into a single partition. \param cptr is the ptr structure of the CSR representation of the components. The length of this vector must be graph->nvtxs+1. \param cind is the indices structure of the CSR representation of the components. The length of this vector must be graph->nvtxs. \returns the number of components that it found. \note The cptr and cind parameters can be NULL, in which case only the number of connected components is returned. */ /*************************************************************************/ idx_t FindPartitionInducedComponents(graph_t *graph, idx_t *where, idx_t *cptr, idx_t *cind) { idx_t i, j, k, me=0, nvtxs, first, last, nleft, ncmps; idx_t *xadj, *adjncy; idx_t *touched, *perm, *todo; idx_t mustfree_ccsr=0, mustfree_where=0; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; /* Deal with NULL supplied cptr/cind vectors */ if (cptr == NULL) { cptr = imalloc(nvtxs+1, "FindPartitionInducedComponents: cptr"); cind = imalloc(nvtxs, "FindPartitionInducedComponents: cind"); mustfree_ccsr = 1; } /* Deal with NULL supplied where vector */ if (where == NULL) { where = ismalloc(nvtxs, 0, "FindPartitionInducedComponents: where"); mustfree_where = 1; } /* Allocate memory required for the BFS traversal */ perm = iincset(nvtxs, 0, imalloc(nvtxs, "FindPartitionInducedComponents: perm")); todo = iincset(nvtxs, 0, imalloc(nvtxs, "FindPartitionInducedComponents: todo")); touched = ismalloc(nvtxs, 0, "FindPartitionInducedComponents: touched"); /* Find the connected componends induced by the partition */ ncmps = -1; first = last = 0; nleft = nvtxs; while (nleft > 0) { if (first == last) { /* Find another starting vertex */ cptr[++ncmps] = first; ASSERT(touched[todo[0]] == 0); i = todo[0]; cind[last++] = i; touched[i] = 1; me = where[i]; } i = cind[first++]; k = perm[i]; j = todo[k] = todo[--nleft]; perm[j] = k; for (j=xadj[i]; jnvtxs; xadj = graph->xadj; adjncy = graph->adjncy; /* Allocate memory required for the BFS traversal */ perm = iincset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); iincset(nvtxs, 0, bfsperm); /* this array will also store the vertices still to be processed */ /* Find the connected componends induced by the partition */ first = last = 0; while (first < nvtxs) { if (first == last) { /* Find another starting vertex */ k = bfsperm[last]; ASSERT(perm[k] != -1); perm[k] = -1; /* mark node as being visited */ last++; } i = bfsperm[first++]; for (j=xadj[i]; jnvtxs; xadj = graph->xadj; adjncy = graph->adjncy; where = graph->where; touched = ismalloc(nvtxs, 0, "IsConnected: touched"); queue = imalloc(nvtxs, "IsConnected: queue"); cptr = imalloc(nvtxs+1, "IsConnected: cptr"); nleft = 0; for (i=0; i 1 && report) { printf("The graph has %"PRIDX" connected components in partition %"PRIDX":\t", ncmps, pid); for (i=0; ivwgt[queue[j]]; printf("[%5"PRIDX" %5"PRIDX"] ", cptr[i+1]-cptr[i], wgt); /* if (cptr[i+1]-cptr[i] == 1) printf("[%"PRIDX" %"PRIDX"] ", queue[cptr[i]], xadj[queue[cptr[i]]+1]-xadj[queue[cptr[i]]]); */ } printf("\n"); } gk_free((void **)&touched, &queue, &cptr, LTERM); return (ncmps == 1 ? 1 : 0); } /*************************************************************************/ /*! This function identifies the number of connected components in a graph that result after removing the vertices that belong to the vertex separator (i.e., graph->where[i] == 2). The connected component memberships are returned in the CSR-style pair of arrays cptr, cind. */ /**************************************************************************/ idx_t FindSepInducedComponents(ctrl_t *ctrl, graph_t *graph, idx_t *cptr, idx_t *cind) { idx_t i, j, k, nvtxs, first, last, nleft, ncmps; idx_t *xadj, *adjncy, *where, *touched, *queue; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; where = graph->where; touched = ismalloc(nvtxs, 0, "IsConnected: queue"); for (i=0; inbnd; i++) touched[graph->bndind[i]] = 1; queue = cind; nleft = 0; for (i=0; iwhere and tries to push them around to remove some of them. */ /*************************************************************************/ void EliminateComponents(ctrl_t *ctrl, graph_t *graph) { idx_t i, ii, j, jj, me, nparts, nvtxs, ncon, ncmps, ncand, target; idx_t *xadj, *adjncy, *vwgt, *adjwgt, *where, *pwgts; idx_t *cptr, *cind, *cpvec, *pcptr, *pcind, *cwhere; idx_t cid, bestcid, *cwgt, *bestcwgt; idx_t ntodo, oldntodo, *todo; rkv_t *cand; idx_t *vmarker=NULL, *pmarker=NULL, *modind=NULL; /* volume specific work arrays */ WCOREPUSH; nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; adjncy = graph->adjncy; vwgt = graph->vwgt; adjwgt = (ctrl->objtype == METIS_OBJTYPE_VOL ? NULL : graph->adjwgt); where = graph->where; pwgts = graph->pwgts; nparts = ctrl->nparts; cptr = iwspacemalloc(ctrl, nvtxs+1); cind = iwspacemalloc(ctrl, nvtxs); ncmps = FindPartitionInducedComponents(graph, where, cptr, cind); IFSET(ctrl->dbglvl, METIS_DBG_CONTIGINFO, printf("I found %"PRIDX" components, for this %"PRIDX"-way partition\n", ncmps, nparts)); /* There are more components than partitions */ if (ncmps > nparts) { cwgt = iwspacemalloc(ctrl, ncon); bestcwgt = iwspacemalloc(ctrl, ncon); cpvec = iwspacemalloc(ctrl, nparts); pcptr = iset(nparts+1, 0, iwspacemalloc(ctrl, nparts+1)); pcind = iwspacemalloc(ctrl, ncmps); cwhere = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs)); todo = iwspacemalloc(ctrl, ncmps); cand = (rkv_t *)wspacemalloc(ctrl, nparts*sizeof(rkv_t)); if (ctrl->objtype == METIS_OBJTYPE_VOL) { /* Vol-refinement specific working arrays */ modind = iwspacemalloc(ctrl, nvtxs); vmarker = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); pmarker = iset(nparts, -1, iwspacemalloc(ctrl, nparts)); } /* Get a CSR representation of the components-2-partitions mapping */ for (i=0; i 0) { oldntodo = ntodo; for (i=0; idbglvl, METIS_DBG_CONTIGINFO, printf("Trying to move %"PRIDX" [%"PRIDX"] from %"PRIDX"\n", cid, isum(ncon, cwgt, 1), me)); /* Determine the connectivity */ iset(nparts, 0, cpvec); for (j=cptr[cid]; j 0) { cand[ncand].key = cpvec[j]; cand[ncand++].val = j; } } if (ncand == 0) continue; rkvsortd(ncand, cand); /* Limit the moves to only the top candidates, which are defined as those with connectivity at least 50% of the best. This applies only when ncon=1, as for multi-constraint, balancing will be hard. */ if (ncon == 1) { for (j=1; jubfactors, 1, pwgts+target*ncon, ctrl->pijbm+target*ncon, 1, pwgts+cand[j].val*ncon, ctrl->pijbm+cand[j].val*ncon)) target = cand[j].val; } IFSET(ctrl->dbglvl, METIS_DBG_CONTIGINFO, printf("\tMoving it to %"PRIDX" [%"PRIDX"] [%"PRIDX"]\n", target, cpvec[target], ncand)); /* Note that as a result of a previous movement, a connected component may now will like to stay to its original partition */ if (target != me) { switch (ctrl->objtype) { case METIS_OBJTYPE_CUT: MoveGroupContigForCut(ctrl, graph, target, cid, cptr, cind); break; case METIS_OBJTYPE_VOL: MoveGroupContigForVol(ctrl, graph, target, cid, cptr, cind, vmarker, pmarker, modind); break; default: gk_errexit(SIGERR, "Unknown objtype %d\n", ctrl->objtype); } } /* Update the cwhere vector */ for (j=cptr[cid]; jdbglvl, METIS_DBG_CONTIGINFO, printf("Stopped at ntodo: %"PRIDX"\n", ntodo)); break; } } for (i=0; ixadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; bndptr = graph->bndptr; bndind = graph->bndind; nbnd = graph->nbnd; for (iii=ptr[gid]; iiickrinfo+i; if (myrinfo->inbr == -1) { myrinfo->inbr = cnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1); myrinfo->nnbrs = 0; } mynbrs = ctrl->cnbrpool + myrinfo->inbr; /* find the location of 'to' in myrinfo or create it if it is not there */ for (k=0; knnbrs; k++) { if (mynbrs[k].pid == to) break; } if (k == myrinfo->nnbrs) { mynbrs[k].pid = to; mynbrs[k].ed = 0; myrinfo->nnbrs++; } graph->mincut -= mynbrs[k].ed-myrinfo->id; /* Update ID/ED and BND related information for the moved vertex */ iaxpy(graph->ncon, 1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+to*graph->ncon, 1); iaxpy(graph->ncon, -1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+from*graph->ncon, 1); UpdateMovedVertexInfoAndBND(i, from, k, to, myrinfo, mynbrs, where, nbnd, bndptr, bndind, BNDTYPE_REFINE); /* Update the degrees of adjacent vertices */ for (j=xadj[i]; jckrinfo+ii; UpdateAdjacentVertexInfoAndBND(ctrl, ii, xadj[ii+1]-xadj[ii], me, from, to, myrinfo, adjwgt[j], nbnd, bndptr, bndind, BNDTYPE_REFINE); } ASSERT(CheckRInfo(ctrl, graph->ckrinfo+i)); } graph->nbnd = nbnd; } /*************************************************************************/ /*! This function moves a collection of vertices and updates their rinfo */ /*************************************************************************/ void MoveGroupContigForVol(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t gid, idx_t *ptr, idx_t *ind, idx_t *vmarker, idx_t *pmarker, idx_t *modind) { idx_t i, ii, iii, j, k, l, from, other, xgain; idx_t *xadj, *vsize, *adjncy, *where; vkrinfo_t *myrinfo, *orinfo; vnbr_t *mynbrs, *onbrs; xadj = graph->xadj; vsize = graph->vsize; adjncy = graph->adjncy; where = graph->where; for (iii=ptr[gid]; iiivkrinfo+i; if (myrinfo->inbr == -1) { myrinfo->inbr = vnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1); myrinfo->nnbrs = 0; } mynbrs = ctrl->vnbrpool + myrinfo->inbr; xgain = (myrinfo->nid == 0 && myrinfo->ned > 0 ? vsize[i] : 0); /* find the location of 'to' in myrinfo or create it if it is not there */ for (k=0; knnbrs; k++) { if (mynbrs[k].pid == to) break; } if (k == myrinfo->nnbrs) { if (myrinfo->nid > 0) xgain -= vsize[i]; /* determine the volume gain resulting from that move */ for (j=xadj[i]; jvkrinfo+ii; onbrs = ctrl->vnbrpool + orinfo->inbr; ASSERT(other != to) if (from == other) { /* Same subdomain vertex: Decrease the gain if 'to' is a new neighbor. */ for (l=0; lnnbrs; l++) { if (onbrs[l].pid == to) break; } if (l == orinfo->nnbrs) xgain -= vsize[ii]; } else { /* Remote vertex: increase if 'to' is a new subdomain */ for (l=0; lnnbrs; l++) { if (onbrs[l].pid == to) break; } if (l == orinfo->nnbrs) xgain -= vsize[ii]; /* Remote vertex: decrease if i is the only connection to 'from' */ for (l=0; lnnbrs; l++) { if (onbrs[l].pid == from && onbrs[l].ned == 1) { xgain += vsize[ii]; break; } } } } graph->minvol -= xgain; graph->mincut -= -myrinfo->nid; } else { graph->minvol -= (xgain + mynbrs[k].gv); graph->mincut -= mynbrs[k].ned-myrinfo->nid; } /* Update where and pwgts */ where[i] = to; iaxpy(graph->ncon, 1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+to*graph->ncon, 1); iaxpy(graph->ncon, -1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+from*graph->ncon, 1); /* Update the id/ed/gains/bnd of potentially affected nodes */ KWayVolUpdate(ctrl, graph, i, from, to, NULL, NULL, NULL, NULL, NULL, BNDTYPE_REFINE, vmarker, pmarker, modind); /*CheckKWayVolPartitionParams(ctrl, graph);*/ } ASSERT(ComputeCut(graph, where) == graph->mincut); ASSERTP(ComputeVolume(graph, where) == graph->minvol, ("%"PRIDX" %"PRIDX"\n", ComputeVolume(graph, where), graph->minvol)); } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/debug.c0000644000175100001440000003140014575233601024375 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * debug.c * * This file contains code that performs self debuging * * Started 7/24/97 * George * */ #include "metislib.h" /*************************************************************************/ /*! This function computes the total edgecut */ /*************************************************************************/ idx_t ComputeCut(graph_t *graph, idx_t *where) { idx_t i, j, cut; if (graph->adjwgt == NULL) { for (cut=0, i=0; invtxs; i++) { for (j=graph->xadj[i]; jxadj[i+1]; j++) if (where[i] != where[graph->adjncy[j]]) cut++; } } else { for (cut=0, i=0; invtxs; i++) { for (j=graph->xadj[i]; jxadj[i+1]; j++) if (where[i] != where[graph->adjncy[j]]) cut += graph->adjwgt[j]; } } return cut/2; } /*************************************************************************/ /*! This function computes the total volume */ /*************************************************************************/ idx_t ComputeVolume(graph_t *graph, idx_t *where) { idx_t i, j, k, nvtxs, nparts, totalv; idx_t *xadj, *adjncy, *vsize, *marker; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; vsize = graph->vsize; nparts = where[iargmax(nvtxs, where)]+1; marker = ismalloc(nparts, -1, "ComputeVolume: marker"); totalv = 0; for (i=0; iadjwgt == NULL) { for (i=0; invtxs; i++) { for (j=graph->xadj[i]; jxadj[i+1]; j++) if (where[i] != where[graph->adjncy[j]]) cuts[where[i]]++; } } else { for (i=0; invtxs; i++) { for (j=graph->xadj[i]; jxadj[i+1]; j++) if (where[i] != where[graph->adjncy[j]]) cuts[where[i]] += graph->adjwgt[j]; } } maxcut = cuts[iargmax(nparts, cuts)]; #ifndef NDEBUG printf("%zu => %"PRIDX"\n", iargmax(nparts, cuts), maxcut); #endif gk_free((void **)&cuts, LTERM); return maxcut; } /*************************************************************************/ /*! This function checks whether or not the boundary information is correct */ /*************************************************************************/ idx_t CheckBnd(graph_t *graph) { #ifndef NDEBUG idx_t i, j, nvtxs, nbnd; idx_t *xadj, *adjncy, *where, *bndptr, *bndind; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; where = graph->where; bndptr = graph->bndptr; bndind = graph->bndind; for (nbnd=0, i=0; inbnd, ("%"PRIDX" %"PRIDX"\n", nbnd, graph->nbnd)); #endif return 1; } /*************************************************************************/ /*! This function checks whether or not the boundary information is correct */ /*************************************************************************/ idx_t CheckBnd2(graph_t *graph) { #ifndef NDEBUG idx_t i, j, nvtxs, nbnd, id, ed; idx_t *xadj, *adjncy, *where, *bndptr, *bndind; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; where = graph->where; bndptr = graph->bndptr; bndind = graph->bndind; for (nbnd=0, i=0; iadjwgt[j]; else id += graph->adjwgt[j]; } if (ed - id >= 0 && xadj[i] < xadj[i+1]) { nbnd++; ASSERTP(bndptr[i] != -1, ("%"PRIDX" %"PRIDX" %"PRIDX"\n", i, id, ed)); ASSERT(bndind[bndptr[i]] == i); } } ASSERTP(nbnd == graph->nbnd, ("%"PRIDX" %"PRIDX"\n", nbnd, graph->nbnd)); #endif return 1; } /*************************************************************************/ /*! This function checks whether or not the boundary information is correct */ /*************************************************************************/ idx_t CheckNodeBnd(graph_t *graph, idx_t onbnd) { #ifndef NDEBUG idx_t i, j, nvtxs, nbnd; idx_t *xadj, *adjncy, *where, *bndptr, *bndind; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; where = graph->where; bndptr = graph->bndptr; bndind = graph->bndind; for (nbnd=0, i=0; icnbrpool + rinfo->inbr; for (i=0; innbrs; i++) { for (j=i+1; jnnbrs; j++) ASSERTP(nbrs[i].pid != nbrs[j].pid, ("%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"\n", i, j, nbrs[i].pid, nbrs[j].pid)); } #endif return 1; } /*************************************************************************/ /*! This function checks the correctness of the NodeFM data structures */ /*************************************************************************/ idx_t CheckNodePartitionParams(graph_t *graph) { idx_t i, j, nvtxs, me, other; idx_t *xadj, *adjncy, *vwgt, *where; idx_t edegrees[2], pwgts[3]; nvtxs = graph->nvtxs; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; where = graph->where; /*------------------------------------------------------------ / Compute now the separator external degrees /------------------------------------------------------------*/ pwgts[0] = pwgts[1] = pwgts[2] = 0; for (i=0; inrinfo[i].edegrees[0] || edegrees[1] != graph->nrinfo[i].edegrees[1]) { printf("Something wrong with edegrees: %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"\n", i, edegrees[0], edegrees[1], graph->nrinfo[i].edegrees[0], graph->nrinfo[i].edegrees[1]); return 0; } } } if (pwgts[0] != graph->pwgts[0] || pwgts[1] != graph->pwgts[1] || pwgts[2] != graph->pwgts[2]) { printf("Something wrong with part-weights: %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"\n", pwgts[0], pwgts[1], pwgts[2], graph->pwgts[0], graph->pwgts[1], graph->pwgts[2]); return 0; } return 1; } /*************************************************************************/ /*! This function checks if the separator is indeed a separator */ /*************************************************************************/ idx_t IsSeparable(graph_t *graph) { #ifndef NDEBUG idx_t i, j, nvtxs, other; idx_t *xadj, *adjncy, *where; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; where = graph->where; for (i=0; ivrinfo structure */ /*************************************************************************/ void CheckKWayVolPartitionParams(ctrl_t *ctrl, graph_t *graph) { idx_t i, ii, j, k, kk, nvtxs, me, other, pid; idx_t *xadj, *vsize, *adjncy, *where; vkrinfo_t *rinfo, *myrinfo, *orinfo, tmprinfo; vnbr_t *mynbrs, *onbrs, *tmpnbrs; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; vsize = graph->vsize; adjncy = graph->adjncy; where = graph->where; rinfo = graph->vkrinfo; tmpnbrs = (vnbr_t *)wspacemalloc(ctrl, ctrl->nparts*sizeof(vnbr_t)); /*------------------------------------------------------------ / Compute now the iv/ev degrees /------------------------------------------------------------*/ for (i=0; ivnbrpool + myrinfo->inbr; for (k=0; knnbrs; k++) tmpnbrs[k] = mynbrs[k]; tmprinfo.nnbrs = myrinfo->nnbrs; tmprinfo.nid = myrinfo->nid; tmprinfo.ned = myrinfo->ned; myrinfo = &tmprinfo; mynbrs = tmpnbrs; for (k=0; knnbrs; k++) mynbrs[k].gv = 0; for (j=xadj[i]; jvnbrpool + orinfo->inbr; if (me == other) { /* Find which domains 'i' is connected and 'ii' is not and update their gain */ for (k=0; knnbrs; k++) { pid = mynbrs[k].pid; for (kk=0; kknnbrs; kk++) { if (onbrs[kk].pid == pid) break; } if (kk == orinfo->nnbrs) mynbrs[k].gv -= vsize[ii]; } } else { /* Find the orinfo[me].ed and see if I'm the only connection */ for (k=0; knnbrs; k++) { if (onbrs[k].pid == me) break; } if (onbrs[k].ned == 1) { /* I'm the only connection of 'ii' in 'me' */ for (k=0; knnbrs; k++) { if (mynbrs[k].pid == other) { mynbrs[k].gv += vsize[ii]; break; } } /* Increase the gains for all the common domains between 'i' and 'ii' */ for (k=0; knnbrs; k++) { if ((pid = mynbrs[k].pid) == other) continue; for (kk=0; kknnbrs; kk++) { if (onbrs[kk].pid == pid) { mynbrs[k].gv += vsize[ii]; break; } } } } else { /* Find which domains 'i' is connected and 'ii' is not and update their gain */ for (k=0; knnbrs; k++) { if ((pid = mynbrs[k].pid) == other) continue; for (kk=0; kknnbrs; kk++) { if (onbrs[kk].pid == pid) break; } if (kk == orinfo->nnbrs) mynbrs[k].gv -= vsize[ii]; } } } } myrinfo = rinfo+i; mynbrs = ctrl->vnbrpool + myrinfo->inbr; for (k=0; knnbrs; k++) { pid = mynbrs[k].pid; for (kk=0; kk 0); /* assign it first to the domain with most things in common */ rpart[i] = nbrdom[iargmax(nnbrs, nbrwgt)]; /* if overweight, assign it to the light domain */ if (pwgts[rpart[i]] > itpwgts[rpart[i]]) { for (j=0; jnumflag == 1) { Change2CNumbering(*nvtxs, xadj, adjncy); renumber = 1; } IFSET(ctrl->dbglvl, METIS_DBG_TIME, InitTimers(ctrl)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->TotalTmr)); /* prune the dense columns */ if (ctrl->pfactor > 0.0) { piperm = imalloc(*nvtxs, "OMETIS: piperm"); graph = PruneGraph(ctrl, *nvtxs, xadj, adjncy, vwgt, piperm, ctrl->pfactor); if (graph == NULL) { /* if there was no prunning, cleanup the pfactor */ gk_free((void **)&piperm, LTERM); ctrl->pfactor = 0.0; } else { nnvtxs = graph->nvtxs; ctrl->compress = 0; /* disable compression if prunning took place */ } } /* compress the graph; note that compression only happens if not prunning has taken place. */ if (ctrl->compress) { cptr = imalloc(*nvtxs+1, "OMETIS: cptr"); cind = imalloc(*nvtxs, "OMETIS: cind"); graph = CompressGraph(ctrl, *nvtxs, xadj, adjncy, vwgt, cptr, cind); if (graph == NULL) { /* if there was no compression, cleanup the compress flag */ gk_free((void **)&cptr, &cind, LTERM); ctrl->compress = 0; } else { nnvtxs = graph->nvtxs; ctrl->cfactor = 1.0*(*nvtxs)/nnvtxs; if (ctrl->cfactor > 1.5 && ctrl->nseps == 1) ctrl->nseps = 2; //ctrl->nseps = (idx_t)(ctrl->cfactor*ctrl->nseps); } } /* if no prunning and no compression, setup the graph in the normal way. */ if (ctrl->pfactor == 0.0 && ctrl->compress == 0) graph = SetupGraph(ctrl, *nvtxs, 1, xadj, adjncy, vwgt, NULL, NULL); ASSERT(CheckGraph(graph, ctrl->numflag, 1)); /* allocate workspace memory */ AllocateWorkSpace(ctrl, graph); /* do the nested dissection ordering */ if (ctrl->ccorder) MlevelNestedDissectionCC(ctrl, graph, iperm, graph->nvtxs); else MlevelNestedDissection(ctrl, graph, iperm, graph->nvtxs); if (ctrl->pfactor > 0.0) { /* Order any prunned vertices */ icopy(nnvtxs, iperm, perm); /* Use perm as an auxiliary array */ for (i=0; icompress) { /* Uncompress the ordering */ /* construct perm from iperm */ for (i=0; idbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->TotalTmr)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, PrintTimers(ctrl)); /* clean up */ FreeCtrl(&ctrl); SIGTHROW: /* if required, change the numbering back to 1 */ if (renumber) Change2FNumberingOrder(*nvtxs, xadj, adjncy, perm, iperm); gk_siguntrap(); gk_malloc_cleanup(0); return metis_rcode(sigrval); } /*************************************************************************/ /*! This is the driver for the recursive tri-section of a graph into the left, separator, and right partitions. The graphs correspond to the left and right parts are further tri-sected in a recursive fashion. The nodes in the separator are ordered at the end of the left & right nodes. */ /*************************************************************************/ void MlevelNestedDissection(ctrl_t *ctrl, graph_t *graph, idx_t *order, idx_t lastvtx) { idx_t i, nbnd; idx_t *label, *bndind; graph_t *lgraph, *rgraph; MlevelNodeBisectionMultiple(ctrl, graph); IFSET(ctrl->dbglvl, METIS_DBG_SEPINFO, printf("Nvtxs: %6"PRIDX", [%6"PRIDX" %6"PRIDX" %6"PRIDX"]\n", graph->nvtxs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2])); /* Order the nodes in the separator */ nbnd = graph->nbnd; bndind = graph->bndind; label = graph->label; for (i=0; invtxs, which will not be defined upon return from MlevelNestedDissection. */ if (lgraph->nvtxs > MMDSWITCH && lgraph->nedges > 0) MlevelNestedDissection(ctrl, lgraph, order, lastvtx-rgraph->nvtxs); else { MMDOrder(ctrl, lgraph, order, lastvtx-rgraph->nvtxs); FreeGraph(&lgraph); } if (rgraph->nvtxs > MMDSWITCH && rgraph->nedges > 0) MlevelNestedDissection(ctrl, rgraph, order, lastvtx); else { MMDOrder(ctrl, rgraph, order, lastvtx); FreeGraph(&rgraph); } } /*************************************************************************/ /*! This routine is similar to its non 'CC' counterpart. The difference is that after each tri-section, the connected components of the original graph that result after removing the separator vertises are ordered independently (i.e., this may lead to more than just the left and the right subgraphs). */ /*************************************************************************/ void MlevelNestedDissectionCC(ctrl_t *ctrl, graph_t *graph, idx_t *order, idx_t lastvtx) { idx_t i, nvtxs, nbnd, ncmps, rnvtxs, snvtxs; idx_t *label, *bndind; idx_t *cptr, *cind; graph_t **sgraphs; nvtxs = graph->nvtxs; MlevelNodeBisectionMultiple(ctrl, graph); IFSET(ctrl->dbglvl, METIS_DBG_SEPINFO, printf("Nvtxs: %6"PRIDX", [%6"PRIDX" %6"PRIDX" %6"PRIDX"]\n", graph->nvtxs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2])); /* Order the nodes in the separator */ nbnd = graph->nbnd; bndind = graph->bndind; label = graph->label; for (i=0; idbglvl&METIS_DBG_INFO) { if (ncmps > 2) printf(" Bisection resulted in %"PRIDX" connected components\n", ncmps); } sgraphs = SplitGraphOrderCC(ctrl, graph, ncmps, cptr, cind); WCOREPOP; /* Free the memory of the top level graph */ FreeGraph(&graph); /* Go and process the subgraphs */ for (rnvtxs=i=0; invtxs; if (sgraphs[i]->nvtxs > MMDSWITCH && sgraphs[i]->nedges > 0) { MlevelNestedDissectionCC(ctrl, sgraphs[i], order, lastvtx-rnvtxs); } else { MMDOrder(ctrl, sgraphs[i], order, lastvtx-rnvtxs); FreeGraph(&sgraphs[i]); } rnvtxs += snvtxs; } gk_free((void **)&sgraphs, LTERM); } /*************************************************************************/ /*! This function performs multilevel node bisection (i.e., tri-section). It performs multiple bisections and selects the best. */ /*************************************************************************/ void MlevelNodeBisectionMultiple(ctrl_t *ctrl, graph_t *graph) { idx_t i, mincut; idx_t *bestwhere; /* if the graph is small, just find a single vertex separator */ if (ctrl->nseps == 1 || graph->nvtxs < (ctrl->compress ? 1000 : 2000)) { MlevelNodeBisectionL2(ctrl, graph, LARGENIPARTS); return; } WCOREPUSH; bestwhere = iwspacemalloc(ctrl, graph->nvtxs); mincut = graph->tvwgt[0]; for (i=0; inseps; i++) { MlevelNodeBisectionL2(ctrl, graph, LARGENIPARTS); if (i == 0 || graph->mincut < mincut) { mincut = graph->mincut; if (i < ctrl->nseps-1) icopy(graph->nvtxs, graph->where, bestwhere); } if (mincut == 0) break; if (i < ctrl->nseps-1) FreeRData(graph); } if (mincut != graph->mincut) { icopy(graph->nvtxs, bestwhere, graph->where); Compute2WayNodePartitionParams(ctrl, graph); } WCOREPOP; } /*************************************************************************/ /*! This function performs multilevel node bisection (i.e., tri-section). It performs multiple bisections and selects the best. */ /*************************************************************************/ void MlevelNodeBisectionL2(ctrl_t *ctrl, graph_t *graph, idx_t niparts) { idx_t i, mincut, nruns=5; graph_t *cgraph; idx_t *bestwhere; /* if the graph is small, just find a single vertex separator */ if (graph->nvtxs < 5000) { MlevelNodeBisectionL1(ctrl, graph, niparts); return; } WCOREPUSH; ctrl->CoarsenTo = gk_max(100, graph->nvtxs/30); cgraph = CoarsenGraphNlevels(ctrl, graph, 4); bestwhere = iwspacemalloc(ctrl, cgraph->nvtxs); mincut = graph->tvwgt[0]; for (i=0; imincut < mincut) { mincut = cgraph->mincut; if (i < nruns-1) icopy(cgraph->nvtxs, cgraph->where, bestwhere); } if (mincut == 0) break; if (i < nruns-1) FreeRData(cgraph); } if (mincut != cgraph->mincut) icopy(cgraph->nvtxs, bestwhere, cgraph->where); WCOREPOP; Refine2WayNode(ctrl, graph, cgraph); } /*************************************************************************/ /*! The top-level routine of the actual multilevel node bisection */ /*************************************************************************/ void MlevelNodeBisectionL1(ctrl_t *ctrl, graph_t *graph, idx_t niparts) { graph_t *cgraph; ctrl->CoarsenTo = graph->nvtxs/8; if (ctrl->CoarsenTo > 100) ctrl->CoarsenTo = 100; else if (ctrl->CoarsenTo < 40) ctrl->CoarsenTo = 40; cgraph = CoarsenGraph(ctrl, graph); niparts = gk_max(1, (cgraph->nvtxs <= ctrl->CoarsenTo ? niparts/2: niparts)); /*niparts = (cgraph->nvtxs <= ctrl->CoarsenTo ? SMALLNIPARTS : LARGENIPARTS);*/ InitSeparator(ctrl, cgraph, niparts); Refine2WayNode(ctrl, graph, cgraph); } /*************************************************************************/ /*! This function takes a graph and a tri-section (left, right, separator) and splits it into two graphs. This function relies on the fact that adjwgt is all equal to 1. */ /*************************************************************************/ void SplitGraphOrder(ctrl_t *ctrl, graph_t *graph, graph_t **r_lgraph, graph_t **r_rgraph) { idx_t i, ii, j, k, l, istart, iend, mypart, nvtxs, snvtxs[3], snedges[3]; idx_t *xadj, *vwgt, *adjncy, *label, *where, *bndptr, *bndind; idx_t *sxadj[2], *svwgt[2], *sadjncy[2], *sadjwgt[2], *slabel[2]; idx_t *rename; idx_t *auxadjncy; graph_t *lgraph, *rgraph; WCOREPUSH; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->SplitTmr)); nvtxs = graph->nvtxs; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; label = graph->label; where = graph->where; bndptr = graph->bndptr; bndind = graph->bndind; ASSERT(bndptr != NULL); rename = iwspacemalloc(ctrl, nvtxs); snvtxs[0] = snvtxs[1] = snvtxs[2] = snedges[0] = snedges[1] = snedges[2] = 0; for (i=0; ixadj; svwgt[0] = lgraph->vwgt; sadjncy[0] = lgraph->adjncy; sadjwgt[0] = lgraph->adjwgt; slabel[0] = lgraph->label; rgraph = SetupSplitGraph(graph, snvtxs[1], snedges[1]); sxadj[1] = rgraph->xadj; svwgt[1] = rgraph->vwgt; sadjncy[1] = rgraph->adjncy; sadjwgt[1] = rgraph->adjwgt; slabel[1] = rgraph->label; /* Go and use bndptr to also mark the boundary nodes in the two partitions */ for (ii=0; iinbnd; ii++) { i = bndind[ii]; for (j=xadj[i]; jnvtxs = snvtxs[0]; lgraph->nedges = snedges[0]; rgraph->nvtxs = snvtxs[1]; rgraph->nedges = snedges[1]; SetupGraph_tvwgt(lgraph); SetupGraph_tvwgt(rgraph); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->SplitTmr)); *r_lgraph = lgraph; *r_rgraph = rgraph; WCOREPOP; } /*************************************************************************/ /*! This function takes a graph and generates a set of graphs, each of which is a connected component in the original graph. This function relies on the fact that adjwgt is all equal to 1. \param ctrl stores run state info. \param graph is the graph to be split. \param ncmps is the number of connected components. \param cptr is an array of size ncmps+1 that marks the start and end locations of the vertices in cind that make up the respective components (i.e., cptr, cind is in CSR format). \param cind is an array of size equal to the number of vertices in the original graph and stores the vertices that belong to each connected component. \returns an array of subgraphs corresponding to the extracted subgraphs. */ /*************************************************************************/ graph_t **SplitGraphOrderCC(ctrl_t *ctrl, graph_t *graph, idx_t ncmps, idx_t *cptr, idx_t *cind) { idx_t i, ii, iii, j, k, l, istart, iend, nvtxs, snvtxs, snedges; idx_t *xadj, *vwgt, *adjncy, *label, *where, *bndptr, *bndind; idx_t *sxadj, *svwgt, *sadjncy, *sadjwgt, *slabel; idx_t *rename; idx_t *auxadjncy; graph_t **sgraphs; WCOREPUSH; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->SplitTmr)); nvtxs = graph->nvtxs; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; label = graph->label; where = graph->where; bndptr = graph->bndptr; bndind = graph->bndind; ASSERT(bndptr != NULL); /* Go and use bndptr to also mark the boundary nodes in the two partitions */ for (ii=0; iinbnd; ii++) { i = bndind[ii]; for (j=xadj[i]; jxadj; svwgt = sgraphs[iii]->vwgt; sadjncy = sgraphs[iii]->adjncy; sadjwgt = sgraphs[iii]->adjwgt; slabel = sgraphs[iii]->label; snvtxs = snedges = sxadj[0] = 0; for (ii=cptr[iii]; iinvtxs = snvtxs; sgraphs[iii]->nedges = snedges; SetupGraph_tvwgt(sgraphs[iii]); } IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->SplitTmr)); WCOREPOP; return sgraphs; } /*************************************************************************/ /*! This function uses MMD to order the graph. The vertices are numbered from lastvtx downwards. */ /*************************************************************************/ void MMDOrder(ctrl_t *ctrl, graph_t *graph, idx_t *order, idx_t lastvtx) { idx_t i, k, nvtxs, nofsub, firstvtx; idx_t *xadj, *adjncy, *label; idx_t *perm, *iperm, *head, *qsize, *list, *marker; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; /* Relabel the vertices so that it starts from 1 */ k = xadj[nvtxs]; for (i=0; ilabel; firstvtx = lastvtx-nvtxs; for (i=0; invtxs; ncon = graph->ncon; xadj = graph->xadj; adjncy = graph->adjncy; vwgt = graph->vwgt; vsize = graph->vsize; adjwgt = graph->adjwgt; if (vwgt == NULL) { vwgt = graph->vwgt = ismalloc(nvtxs, 1, "vwgt"); mustfree = 1; } if (adjwgt == NULL) { adjwgt = graph->adjwgt = ismalloc(xadj[nvtxs], 1, "adjwgt"); mustfree += 2; } printf("%"PRIDX"-way Cut: %5"PRIDX", Vol: %5"PRIDX", ", nparts, ComputeCut(graph, where), ComputeVolume(graph, where)); /* Compute balance information */ kpwgts = ismalloc(ncon*nparts, 0, "ComputePartitionInfo: kpwgts"); for (i=0; ivwgt = NULL; } if (mustfree == 2 || mustfree == 3) { gk_free((void **)&adjwgt, LTERM); graph->adjwgt = NULL; } gk_free((void **)&kpwgts, &padjncy, &padjwgt, &padjcut, LTERM); } /************************************************************************* * This function computes the balance of the partitioning **************************************************************************/ void ComputePartitionBalance(graph_t *graph, idx_t nparts, idx_t *where, real_t *ubvec) { idx_t i, j, nvtxs, ncon; idx_t *kpwgts, *vwgt; nvtxs = graph->nvtxs; ncon = graph->ncon; vwgt = graph->vwgt; kpwgts = ismalloc(nparts, 0, "ComputePartitionInfo: kpwgts"); if (vwgt == NULL) { for (i=0; invtxs; i++) kpwgts[where[i]] += vwgt[i*ncon+j]; ubvec[j] = 1.0*nparts*kpwgts[iargmax(nparts, kpwgts)]/(1.0*isum(nparts, kpwgts, 1)); } } gk_free((void **)&kpwgts, LTERM); } /************************************************************************* * This function computes the balance of the element partitioning **************************************************************************/ real_t ComputeElementBalance(idx_t ne, idx_t nparts, idx_t *where) { idx_t i; idx_t *kpwgts; real_t balance; kpwgts = ismalloc(nparts, 0, "ComputeElementBalance: kpwgts"); for (i=0; i=0; n--) { if (x[n] > y[n]) return 0; } return 1; } /*************************************************************************/ /*! This function compares two vectors x & y and returns true if \forall i, x[i] >= y[i]. */ /**************************************************************************/ int rvecge(idx_t n, real_t *x, real_t *y) { for (n--; n>=0; n--) { if (x[n] < y[n]) return 0; } return 1; } /*************************************************************************/ /*! This function compares vectors x1+x2 against y and returns true if \forall i, x1[i]+x2[i] <= y[i]. */ /**************************************************************************/ int rvecsumle(idx_t n, real_t *x1, real_t *x2, real_t *y) { for (n--; n>=0; n--) { if (x1[n]+x2[n] > y[n]) return 0; } return 1; } /*************************************************************************/ /*! This function returns max_i(x[i]-y[i]) */ /**************************************************************************/ real_t rvecmaxdiff(idx_t n, real_t *x, real_t *y) { real_t max; max = x[0]-y[0]; for (n--; n>0; n--) { if (max < x[n]-y[n]) max = x[n]-y[n]; } return max; } /*************************************************************************/ /*! This function returns true if \forall i, x[i] <= z[i]. */ /**************************************************************************/ int ivecle(idx_t n, idx_t *x, idx_t *z) { for (n--; n>=0; n--) { if (x[n] > z[n]) return 0; } return 1; } /*************************************************************************/ /*! This function returns true if \forall i, x[i] >= z[i]. */ /**************************************************************************/ int ivecge(idx_t n, idx_t *x, idx_t *z) { for (n--; n>=0; n--) { if (x[n] < z[n]) return 0; } return 1; } /*************************************************************************/ /*! This function returns true if \forall i, a*x[i]+y[i] <= z[i]. */ /**************************************************************************/ int ivecaxpylez(idx_t n, idx_t a, idx_t *x, idx_t *y, idx_t *z) { for (n--; n>=0; n--) { if (a*x[n]+y[n] > z[n]) return 0; } return 1; } /*************************************************************************/ /*! This function returns true if \forall i, a*x[i]+y[i] >= z[i]. */ /**************************************************************************/ int ivecaxpygez(idx_t n, idx_t a, idx_t *x, idx_t *y, idx_t *z) { for (n--; n>=0; n--) { if (a*x[n]+y[n] < z[n]) return 0; } return 1; } /*************************************************************************/ /*! This function checks if v+u2 provides a better balance in the weight vector that v+u1 */ /*************************************************************************/ int BetterVBalance(idx_t ncon, real_t *invtvwgt, idx_t *v_vwgt, idx_t *u1_vwgt, idx_t *u2_vwgt) { idx_t i; real_t sum1=0.0, sum2=0.0, diff1=0.0, diff2=0.0; for (i=0; i= 0); } /*************************************************************************/ /*! This function takes two ubfactor-centered load imbalance vectors x & y, and returns true if y is better balanced than x. */ /*************************************************************************/ int BetterBalance2Way(idx_t n, real_t *x, real_t *y) { real_t nrm1=0.0, nrm2=0.0; for (--n; n>=0; n--) { if (x[n] > 0) nrm1 += x[n]*x[n]; if (y[n] > 0) nrm2 += y[n]*y[n]; } return nrm2 < nrm1; } /*************************************************************************/ /*! Given a vertex and two weights, this function returns 1, if the second partition will be more balanced than the first after the weighted additional of that vertex. The balance determination takes into account the ideal target weights of the two partitions. */ /*************************************************************************/ int BetterBalanceKWay(idx_t ncon, idx_t *vwgt, real_t *ubvec, idx_t a1, idx_t *pt1, real_t *bm1, idx_t a2, idx_t *pt2, real_t *bm2) { idx_t i; real_t tmp, nrm1=0.0, nrm2=0.0, max1=0.0, max2=0.0; for (i=0; i max1 ? tmp : max1); tmp = bm2[i]*(pt2[i]+a2*vwgt[i]) - ubvec[i]; //printf("%+.4f ", (float)tmp); nrm2 += tmp*tmp; max2 = (tmp > max2 ? tmp : max2); //printf("%4d %4d %4d %4d %4d %4d %4d %.2f\n", // (int)vwgt[i], // (int)a1, (int)pt1[i], (int)tpt1[i], // (int)a2, (int)pt2[i], (int)tpt2[i], ubvec[i]); } //printf(" %.3f %.3f %.3f %.3f\n", (float)max1, (float)nrm1, (float)max2, (float)nrm2); if (max2 < max1) return 1; if (max2 == max1 && nrm2 < nrm1) return 1; return 0; } /*************************************************************************/ /*! Computes the maximum load imbalance of a partitioning solution over all the constraints. */ /**************************************************************************/ real_t ComputeLoadImbalance(graph_t *graph, idx_t nparts, real_t *pijbm) { idx_t i, j, ncon, *pwgts; real_t max, cur; ncon = graph->ncon; pwgts = graph->pwgts; max = 1.0; for (i=0; i max) max = cur; } } return max; } /*************************************************************************/ /*! Computes the maximum load imbalance difference of a partitioning solution over all the constraints. The difference is defined with respect to the allowed maximum unbalance for the respective constraint. */ /**************************************************************************/ real_t ComputeLoadImbalanceDiff(graph_t *graph, idx_t nparts, real_t *pijbm, real_t *ubvec) { idx_t i, j, ncon, *pwgts; real_t max, cur; ncon = graph->ncon; pwgts = graph->pwgts; max = -1.0; for (i=0; i max) max = cur; } } return max; } /*************************************************************************/ /*! Computes the difference between load imbalance of each constraint across the partitions minus the desired upper bound on the load imabalnce. It also returns the maximum load imbalance across the partitions & constraints. */ /**************************************************************************/ real_t ComputeLoadImbalanceDiffVec(graph_t *graph, idx_t nparts, real_t *pijbm, real_t *ubfactors, real_t *diffvec) { idx_t i, j, ncon, *pwgts; real_t cur, max; ncon = graph->ncon; pwgts = graph->pwgts; for (max=-1.0, i=0; i diffvec[i]) diffvec[i] = cur; } if (max < diffvec[i]) max = diffvec[i]; } return max; } /*************************************************************************/ /*! Computes the load imbalance of each constraint across the partitions. */ /**************************************************************************/ void ComputeLoadImbalanceVec(graph_t *graph, idx_t nparts, real_t *pijbm, real_t *lbvec) { idx_t i, j, ncon, *pwgts; real_t cur; ncon = graph->ncon; pwgts = graph->pwgts; for (i=0; i lbvec[i]) lbvec[i] = cur; } } } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/rename.h0000644000175100001440000003015514552244506024572 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * rename.h * * This file contains header files * * Started 10/2/97 * George * * $Id: rename.h 13933 2013-03-29 22:20:46Z karypis $ * */ #ifndef _LIBMETIS_RENAME_H_ #define _LIBMETIS_RENAME_H_ /* balance.c */ #define Balance2Way libmetis__Balance2Way #define Bnd2WayBalance libmetis__Bnd2WayBalance #define General2WayBalance libmetis__General2WayBalance #define McGeneral2WayBalance libmetis__McGeneral2WayBalance /* bucketsort.c */ #define BucketSortKeysInc libmetis__BucketSortKeysInc /* checkgraph.c */ #define CheckGraph libmetis__CheckGraph #define CheckInputGraphWeights libmetis__CheckInputGraphWeights #define FixGraph libmetis__FixGraph /* coarsen.c */ #define CoarsenGraph libmetis__CoarsenGraph #define Match_RM libmetis__Match_RM #define Match_SHEM libmetis__Match_SHEM #define Match_2Hop libmetis__Match_2Hop #define Match_2HopAny libmetis__Match_2HopAny #define Match_2HopAll libmetis__Match_2HopAll #define PrintCGraphStats libmetis__PrintCGraphStats #define CreateCoarseGraph libmetis__CreateCoarseGraph #define CreateCoarseGraphNoMask libmetis__CreateCoarseGraphNoMask #define CreateCoarseGraphPerm libmetis__CreateCoarseGraphPerm #define SetupCoarseGraph libmetis__SetupCoarseGraph #define ReAdjustMemory libmetis__ReAdjustMemory /* compress.c */ #define CompressGraph libmetis__CompressGraph #define PruneGraph libmetis__PruneGraph /* contig.c */ #define FindPartitionInducedComponents libmetis__FindPartitionInducedComponents #define IsConnected libmetis__IsConnected #define IsConnectedSubdomain libmetis__IsConnectedSubdomain #define FindSepInducedComponents libmetis__FindSepInducedComponents #define EliminateComponents libmetis__EliminateComponents #define MoveGroupContigForCut libmetis__MoveGroupContigForCut #define MoveGroupContigForVol libmetis__MoveGroupContigForVol /* debug.c */ #define ComputeCut libmetis__ComputeCut #define ComputeVolume libmetis__ComputeVolume #define ComputeMaxCut libmetis__ComputeMaxCut #define CheckBnd libmetis__CheckBnd #define CheckBnd2 libmetis__CheckBnd2 #define CheckNodeBnd libmetis__CheckNodeBnd #define CheckRInfo libmetis__CheckRInfo #define CheckNodePartitionParams libmetis__CheckNodePartitionParams #define IsSeparable libmetis__IsSeparable #define CheckKWayVolPartitionParams libmetis__CheckKWayVolPartitionParams /* fm.c */ #define FM_2WayRefine libmetis__FM_2WayRefine #define FM_2WayCutRefine libmetis__FM_2WayCutRefine #define FM_Mc2WayCutRefine libmetis__FM_Mc2WayCutRefine #define SelectQueue libmetis__SelectQueue #define Print2WayRefineStats libmetis__Print2WayRefineStats /* fortran.c */ #define Change2CNumbering libmetis__Change2CNumbering #define Change2FNumbering libmetis__Change2FNumbering #define Change2FNumbering2 libmetis__Change2FNumbering2 #define Change2FNumberingOrder libmetis__Change2FNumberingOrder #define ChangeMesh2CNumbering libmetis__ChangeMesh2CNumbering #define ChangeMesh2FNumbering libmetis__ChangeMesh2FNumbering #define ChangeMesh2FNumbering2 libmetis__ChangeMesh2FNumbering2 /* graph.c */ #define SetupGraph libmetis__SetupGraph #define SetupGraph_adjrsum libmetis__SetupGraph_adjrsum #define SetupGraph_tvwgt libmetis__SetupGraph_tvwgt #define SetupGraph_label libmetis__SetupGraph_label #define SetupSplitGraph libmetis__SetupSplitGraph #define CreateGraph libmetis__CreateGraph #define InitGraph libmetis__InitGraph #define FreeRData libmetis__FreeRData #define FreeGraph libmetis__FreeGraph /* initpart.c */ #define Init2WayPartition libmetis__Init2WayPartition #define InitSeparator libmetis__InitSeparator #define RandomBisection libmetis__RandomBisection #define GrowBisection libmetis__GrowBisection #define McRandomBisection libmetis__McRandomBisection #define McGrowBisection libmetis__McGrowBisection #define GrowBisectionNode libmetis__GrowBisectionNode /* kmetis.c */ #define MlevelKWayPartitioning libmetis__MlevelKWayPartitioning #define InitKWayPartitioning libmetis__InitKWayPartitioning /* kwayfm.c */ #define Greedy_KWayOptimize libmetis__Greedy_KWayOptimize #define Greedy_KWayCutOptimize libmetis__Greedy_KWayCutOptimize #define Greedy_KWayVolOptimize libmetis__Greedy_KWayVolOptimize #define Greedy_McKWayCutOptimize libmetis__Greedy_McKWayCutOptimize #define Greedy_McKWayVolOptimize libmetis__Greedy_McKWayVolOptimize #define IsArticulationNode libmetis__IsArticulationNode #define KWayVolUpdate libmetis__KWayVolUpdate /* kwayrefine.c */ #define RefineKWay libmetis__RefineKWay #define AllocateKWayPartitionMemory libmetis__AllocateKWayPartitionMemory #define ComputeKWayPartitionParams libmetis__ComputeKWayPartitionParams #define ProjectKWayPartition libmetis__ProjectKWayPartition #define ComputeKWayBoundary libmetis__ComputeKWayBoundary #define ComputeKWayVolGains libmetis__ComputeKWayVolGains #define IsBalanced libmetis__IsBalanced /* mcutil */ #define rvecle libmetis__rvecle #define rvecge libmetis__rvecge #define rvecsumle libmetis__rvecsumle #define rvecmaxdiff libmetis__rvecmaxdiff #define ivecle libmetis__ivecle #define ivecge libmetis__ivecge #define ivecaxpylez libmetis__ivecaxpylez #define ivecaxpygez libmetis__ivecaxpygez #define BetterVBalance libmetis__BetterVBalance #define BetterBalance2Way libmetis__BetterBalance2Way #define BetterBalanceKWay libmetis__BetterBalanceKWay #define ComputeLoadImbalance libmetis__ComputeLoadImbalance #define ComputeLoadImbalanceDiff libmetis__ComputeLoadImbalanceDiff #define ComputeLoadImbalanceDiffVec libmetis__ComputeLoadImbalanceDiffVec #define ComputeLoadImbalanceVec libmetis__ComputeLoadImbalanceVec /* mesh.c */ #define CreateGraphDual libmetis__CreateGraphDual #define FindCommonElements libmetis__FindCommonElements #define CreateGraphNodal libmetis__CreateGraphNodal #define FindCommonNodes libmetis__FindCommonNodes #define CreateMesh libmetis__CreateMesh #define InitMesh libmetis__InitMesh #define FreeMesh libmetis__FreeMesh /* meshpart.c */ #define InduceRowPartFromColumnPart libmetis__InduceRowPartFromColumnPart /* minconn.c */ #define ComputeSubDomainGraph libmetis__ComputeSubDomainGraph #define UpdateEdgeSubDomainGraph libmetis__UpdateEdgeSubDomainGraph #define PrintSubDomainGraph libmetis__PrintSubDomainGraph #define EliminateSubDomainEdges libmetis__EliminateSubDomainEdges #define MoveGroupMinConnForCut libmetis__MoveGroupMinConnForCut #define MoveGroupMinConnForVol libmetis__MoveGroupMinConnForVol /* mincover.c */ #define MinCover libmetis__MinCover #define MinCover_Augment libmetis__MinCover_Augment #define MinCover_Decompose libmetis__MinCover_Decompose #define MinCover_ColDFS libmetis__MinCover_ColDFS #define MinCover_RowDFS libmetis__MinCover_RowDFS /* mmd.c */ #define genmmd libmetis__genmmd #define mmdelm libmetis__mmdelm #define mmdint libmetis__mmdint #define mmdnum libmetis__mmdnum #define mmdupd libmetis__mmdupd /* ometis.c */ #define MlevelNestedDissection libmetis__MlevelNestedDissection #define MlevelNestedDissectionCC libmetis__MlevelNestedDissectionCC #define MlevelNodeBisectionMultiple libmetis__MlevelNodeBisectionMultiple #define MlevelNodeBisectionL2 libmetis__MlevelNodeBisectionL2 #define MlevelNodeBisectionL1 libmetis__MlevelNodeBisectionL1 #define SplitGraphOrder libmetis__SplitGraphOrder #define SplitGraphOrderCC libmetis__SplitGraphOrderCC #define MMDOrder libmetis__MMDOrder /* options.c */ #define SetupCtrl libmetis__SetupCtrl #define SetupKWayBalMultipliers libmetis__SetupKWayBalMultipliers #define Setup2WayBalMultipliers libmetis__Setup2WayBalMultipliers #define PrintCtrl libmetis__PrintCtrl #define FreeCtrl libmetis__FreeCtrl #define CheckParams libmetis__CheckParams /* parmetis.c */ #define MlevelNestedDissectionP libmetis__MlevelNestedDissectionP #define FM_2WayNodeRefine1SidedP libmetis__FM_2WayNodeRefine1SidedP #define FM_2WayNodeRefine2SidedP libmetis__FM_2WayNodeRefine2SidedP /* pmetis.c */ #define MlevelRecursiveBisection libmetis__MlevelRecursiveBisection #define MultilevelBisect libmetis__MultilevelBisect #define SplitGraphPart libmetis__SplitGraphPart /* refine.c */ #define Refine2Way libmetis__Refine2Way #define Allocate2WayPartitionMemory libmetis__Allocate2WayPartitionMemory #define Compute2WayPartitionParams libmetis__Compute2WayPartitionParams #define Project2WayPartition libmetis__Project2WayPartition /* separator.c */ #define ConstructSeparator libmetis__ConstructSeparator #define ConstructMinCoverSeparator libmetis__ConstructMinCoverSeparator /* sfm.c */ #define FM_2WayNodeRefine2Sided libmetis__FM_2WayNodeRefine2Sided #define FM_2WayNodeRefine1Sided libmetis__FM_2WayNodeRefine1Sided #define FM_2WayNodeBalance libmetis__FM_2WayNodeBalance /* srefine.c */ #define Refine2WayNode libmetis__Refine2WayNode #define Allocate2WayNodePartitionMemory libmetis__Allocate2WayNodePartitionMemory #define Compute2WayNodePartitionParams libmetis__Compute2WayNodePartitionParams #define Project2WayNodePartition libmetis__Project2WayNodePartition /* stat.c */ #define ComputePartitionInfoBipartite libmetis__ComputePartitionInfoBipartite #define ComputePartitionBalance libmetis__ComputePartitionBalance #define ComputeElementBalance libmetis__ComputeElementBalance /* timing.c */ #define InitTimers libmetis__InitTimers #define PrintTimers libmetis__PrintTimers /* util.c */ #define iargmax_strd libmetis__iargmax_strd #define iargmax_nrm libmetis__iargmax_nrm #define iargmax2_nrm libmetis__iargmax2_nrm #define rargmax2 libmetis__rargmax2 #define InitRandom libmetis__InitRandom #define metis_rcode libmetis__metis_rcode /* wspace.c */ #define AllocateWorkSpace libmetis__AllocateWorkSpace #define AllocateRefinementWorkSpace libmetis__AllocateRefinementWorkSpace #define FreeWorkSpace libmetis__FreeWorkSpace #define wspacemalloc libmetis__wspacemalloc #define wspacepush libmetis__wspacepush #define wspacepop libmetis__wspacepop #define iwspacemalloc libmetis__iwspacemalloc #define rwspacemalloc libmetis__rwspacemalloc #define ikvwspacemalloc libmetis__ikvwspacemalloc #define cnbrpoolReset libmetis__cnbrpoolReset #define cnbrpoolGetNext libmetis__cnbrpoolGetNext #define vnbrpoolReset libmetis__vnbrpoolReset #define vnbrpoolGetNext libmetis__vnbrpoolGetNext #endif Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/gklib_defs.h0000644000175100001440000000422014552244506025406 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file \brief Data structures and prototypes for GKlib integration \date Started 12/23/2008 \author George \version\verbatim $Id: gklib_defs.h 10395 2011-06-23 23:28:06Z karypis $ \endverbatim */ #ifndef _LIBMETIS_GKLIB_H_ #define _LIBMETIS_GKLIB_H_ #include "gklib_rename.h" /*************************************************************************/ /*! Stores a weighted edge */ /*************************************************************************/ typedef struct { idx_t u, v, w; /*!< Edge (u,v) with weight w */ } uvw_t; /************************************************************************* * Define various data structure using GKlib's templates. **************************************************************************/ GK_MKKEYVALUE_T(ikv_t, idx_t, idx_t) GK_MKKEYVALUE_T(rkv_t, real_t, idx_t) GK_MKPQUEUE_T(ipq_t, ikv_t) GK_MKPQUEUE_T(rpq_t, rkv_t) /* gklib.c */ GK_MKBLAS_PROTO(i, idx_t, idx_t) GK_MKBLAS_PROTO(r, real_t, real_t) GK_MKALLOC_PROTO(i, idx_t) GK_MKALLOC_PROTO(r, real_t) GK_MKALLOC_PROTO(ikv, ikv_t) GK_MKALLOC_PROTO(rkv, rkv_t) GK_MKPQUEUE_PROTO(ipq, ipq_t, idx_t, idx_t) GK_MKPQUEUE_PROTO(rpq, rpq_t, real_t, idx_t) GK_MKRANDOM_PROTO(i, idx_t, idx_t) GK_MKARRAY2CSR_PROTO(i, idx_t) void isorti(size_t n, idx_t *base); void isortd(size_t n, idx_t *base); void rsorti(size_t n, real_t *base); void rsortd(size_t n, real_t *base); void ikvsorti(size_t n, ikv_t *base); void ikvsortii(size_t n, ikv_t *base); void ikvsortd(size_t n, ikv_t *base); void rkvsorti(size_t n, rkv_t *base); void rkvsortd(size_t n, rkv_t *base); void uvwsorti(size_t n, uvw_t *base); #endif Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/initpart.c0000644000175100001440000004401114552244506025144 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * initpart.c * * This file contains code that performs the initial partition of the * coarsest graph * * Started 7/23/97 * George * */ #include "metislib.h" /*************************************************************************/ /*! This function computes the initial bisection of the coarsest graph */ /*************************************************************************/ void Init2WayPartition(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { mdbglvl_et dbglvl; ASSERT(graph->tvwgt[0] >= 0); dbglvl = ctrl->dbglvl; IFSET(ctrl->dbglvl, METIS_DBG_REFINE, ctrl->dbglvl -= METIS_DBG_REFINE); IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, ctrl->dbglvl -= METIS_DBG_MOVEINFO); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->InitPartTmr)); switch (ctrl->iptype) { case METIS_IPTYPE_RANDOM: if (graph->ncon == 1) RandomBisection(ctrl, graph, ntpwgts, niparts); else McRandomBisection(ctrl, graph, ntpwgts, niparts); break; case METIS_IPTYPE_GROW: if (graph->nedges == 0) if (graph->ncon == 1) RandomBisection(ctrl, graph, ntpwgts, niparts); else McRandomBisection(ctrl, graph, ntpwgts, niparts); else if (graph->ncon == 1) GrowBisection(ctrl, graph, ntpwgts, niparts); else McGrowBisection(ctrl, graph, ntpwgts, niparts); break; default: gk_errexit(SIGERR, "Unknown initial partition type: %d\n", ctrl->iptype); } IFSET(ctrl->dbglvl, METIS_DBG_IPART, printf("Initial Cut: %"PRIDX"\n", graph->mincut)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr)); ctrl->dbglvl = dbglvl; } /*************************************************************************/ /*! This function computes the initial separator of the coarsest graph */ /*************************************************************************/ void InitSeparator(ctrl_t *ctrl, graph_t *graph, idx_t niparts) { real_t ntpwgts[2] = {0.5, 0.5}; mdbglvl_et dbglvl; dbglvl = ctrl->dbglvl; IFSET(ctrl->dbglvl, METIS_DBG_REFINE, ctrl->dbglvl -= METIS_DBG_REFINE); IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, ctrl->dbglvl -= METIS_DBG_MOVEINFO); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->InitPartTmr)); /* this is required for the cut-based part of the refinement */ Setup2WayBalMultipliers(ctrl, graph, ntpwgts); switch (ctrl->iptype) { case METIS_IPTYPE_EDGE: if (graph->nedges == 0) RandomBisection(ctrl, graph, ntpwgts, niparts); else GrowBisection(ctrl, graph, ntpwgts, niparts); Compute2WayPartitionParams(ctrl, graph); ConstructSeparator(ctrl, graph); break; case METIS_IPTYPE_NODE: GrowBisectionNode(ctrl, graph, ntpwgts, niparts); break; default: gk_errexit(SIGERR, "Unkown iptype of %"PRIDX"\n", ctrl->iptype); } IFSET(ctrl->dbglvl, METIS_DBG_IPART, printf("Initial Sep: %"PRIDX"\n", graph->mincut)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr)); ctrl->dbglvl = dbglvl; } /*************************************************************************/ /*! This function computes a bisection of a graph by randomly assigning the vertices followed by a bisection refinement. The resulting partition is returned in graph->where. */ /*************************************************************************/ void RandomBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { idx_t i, ii, nvtxs, pwgts[2], zeromaxpwgt, bestcut=0, inbfs; idx_t *vwgt, *where; idx_t *perm, *bestwhere; WCOREPUSH; nvtxs = graph->nvtxs; vwgt = graph->vwgt; Allocate2WayPartitionMemory(ctrl, graph); where = graph->where; bestwhere = iwspacemalloc(ctrl, nvtxs); perm = iwspacemalloc(ctrl, nvtxs); zeromaxpwgt = ctrl->ubfactors[0]*graph->tvwgt[0]*ntpwgts[0]; for (inbfs=0; inbfs 0) { irandArrayPermute(nvtxs, perm, nvtxs/2, 1); pwgts[1] = graph->tvwgt[0]; pwgts[0] = 0; for (ii=0; ii zeromaxpwgt) break; } } } /* Do some partition refinement */ Compute2WayPartitionParams(ctrl, graph); /* printf("IPART: %3"PRIDX" [%5"PRIDX" %5"PRIDX"] [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->nvtxs, pwgts[0], pwgts[1], graph->pwgts[0], graph->pwgts[1], graph->mincut); */ Balance2Way(ctrl, graph, ntpwgts); /* printf("BPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0], graph->pwgts[1], graph->mincut); */ FM_2WayRefine(ctrl, graph, ntpwgts, 4); /* printf("RPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0], graph->pwgts[1], graph->mincut); */ if (inbfs==0 || bestcut > graph->mincut) { bestcut = graph->mincut; icopy(nvtxs, where, bestwhere); if (bestcut == 0) break; } } graph->mincut = bestcut; icopy(nvtxs, bestwhere, where); WCOREPOP; } /*************************************************************************/ /*! This function takes a graph and produces a bisection by using a region growing algorithm. The resulting bisection is refined using FM. The resulting partition is returned in graph->where. */ /*************************************************************************/ void GrowBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { idx_t i, j, k, nvtxs, drain, nleft, first, last, pwgts[2], oneminpwgt, onemaxpwgt, bestcut=0, inbfs; idx_t *xadj, *vwgt, *adjncy, *where; idx_t *queue, *touched, *bestwhere; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; Allocate2WayPartitionMemory(ctrl, graph); where = graph->where; bestwhere = iwspacemalloc(ctrl, nvtxs); queue = iwspacemalloc(ctrl, nvtxs); touched = iwspacemalloc(ctrl, nvtxs); onemaxpwgt = ctrl->ubfactors[0]*graph->tvwgt[0]*ntpwgts[1]; oneminpwgt = (1.0/ctrl->ubfactors[0])*graph->tvwgt[0]*ntpwgts[1]; for (inbfs=0; inbfstvwgt[0]; pwgts[0] = 0; queue[0] = irandInRange(nvtxs); touched[queue[0]] = 1; first = 0; last = 1; nleft = nvtxs-1; drain = 0; /* Start the BFS from queue to get a partition */ for (;;) { if (first == last) { /* Empty. Disconnected graph! */ if (nleft == 0 || drain) break; k = irandInRange(nleft); for (i=0; i 0 && pwgts[1]-vwgt[i] < oneminpwgt) { drain = 1; continue; } where[i] = 0; INC_DEC(pwgts[0], pwgts[1], vwgt[i]); if (pwgts[1] <= onemaxpwgt) break; drain = 0; for (j=xadj[i]; jnvtxs, pwgts[0], pwgts[1], graph->pwgts[0], graph->pwgts[1], graph->mincut); */ Balance2Way(ctrl, graph, ntpwgts); /* printf("BPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0], graph->pwgts[1], graph->mincut); */ FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); /* printf("RPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0], graph->pwgts[1], graph->mincut); */ if (inbfs == 0 || bestcut > graph->mincut) { bestcut = graph->mincut; icopy(nvtxs, where, bestwhere); if (bestcut == 0) break; } } graph->mincut = bestcut; icopy(nvtxs, bestwhere, where); WCOREPOP; } /*************************************************************************/ /*! This function takes a multi-constraint graph and computes a bisection by randomly assigning the vertices and then refining it. The resulting partition is returned in graph->where. */ /**************************************************************************/ void McRandomBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { idx_t i, ii, nvtxs, ncon, bestcut=0, inbfs, qnum; idx_t *bestwhere, *where, *perm, *counts; idx_t *vwgt; WCOREPUSH; nvtxs = graph->nvtxs; ncon = graph->ncon; vwgt = graph->vwgt; Allocate2WayPartitionMemory(ctrl, graph); where = graph->where; bestwhere = iwspacemalloc(ctrl, nvtxs); perm = iwspacemalloc(ctrl, nvtxs); counts = iwspacemalloc(ctrl, ncon); for (inbfs=0; inbfs<2*niparts; inbfs++) { irandArrayPermute(nvtxs, perm, nvtxs/2, 1); iset(ncon, 0, counts); /* partition by spliting the queues randomly */ for (ii=0; iiniter); Balance2Way(ctrl, graph, ntpwgts); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); Balance2Way(ctrl, graph, ntpwgts); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); if (inbfs == 0 || bestcut >= graph->mincut) { bestcut = graph->mincut; icopy(nvtxs, where, bestwhere); if (bestcut == 0) break; } } graph->mincut = bestcut; icopy(nvtxs, bestwhere, where); WCOREPOP; } /*************************************************************************/ /*! This function takes a multi-constraint graph and produces a bisection by using a region growing algorithm. The resulting partition is returned in graph->where. */ /*************************************************************************/ void McGrowBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { idx_t nvtxs, bestcut=0, inbfs; idx_t *bestwhere, *where; WCOREPUSH; nvtxs = graph->nvtxs; Allocate2WayPartitionMemory(ctrl, graph); where = graph->where; bestwhere = iwspacemalloc(ctrl, nvtxs); for (inbfs=0; inbfs<2*niparts; inbfs++) { iset(nvtxs, 1, where); where[irandInRange(nvtxs)] = 0; Compute2WayPartitionParams(ctrl, graph); Balance2Way(ctrl, graph, ntpwgts); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); Balance2Way(ctrl, graph, ntpwgts); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); if (inbfs == 0 || bestcut >= graph->mincut) { bestcut = graph->mincut; icopy(nvtxs, where, bestwhere); if (bestcut == 0) break; } } graph->mincut = bestcut; icopy(nvtxs, bestwhere, where); WCOREPOP; } /*************************************************************************/ /* This function takes a graph and produces a tri-section into left, right, and separator using a region growing algorithm. The resulting separator is refined using node FM. The resulting partition is returned in graph->where. */ /**************************************************************************/ void GrowBisectionNode(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { idx_t i, j, k, nvtxs, drain, nleft, first, last, pwgts[2], oneminpwgt, onemaxpwgt, bestcut=0, inbfs; idx_t *xadj, *vwgt, *adjncy, *where, *bndind; idx_t *queue, *touched, *bestwhere; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; bestwhere = iwspacemalloc(ctrl, nvtxs); queue = iwspacemalloc(ctrl, nvtxs); touched = iwspacemalloc(ctrl, nvtxs); onemaxpwgt = ctrl->ubfactors[0]*graph->tvwgt[0]*0.5; oneminpwgt = (1.0/ctrl->ubfactors[0])*graph->tvwgt[0]*0.5; /* Allocate refinement memory. Allocate sufficient memory for both edge and node */ graph->pwgts = imalloc(3, "GrowBisectionNode: pwgts"); graph->where = imalloc(nvtxs, "GrowBisectionNode: where"); graph->bndptr = imalloc(nvtxs, "GrowBisectionNode: bndptr"); graph->bndind = imalloc(nvtxs, "GrowBisectionNode: bndind"); graph->id = imalloc(nvtxs, "GrowBisectionNode: id"); graph->ed = imalloc(nvtxs, "GrowBisectionNode: ed"); graph->nrinfo = (nrinfo_t *)gk_malloc(nvtxs*sizeof(nrinfo_t), "GrowBisectionNode: nrinfo"); where = graph->where; bndind = graph->bndind; for (inbfs=0; inbfstvwgt[0]; pwgts[0] = 0; queue[0] = irandInRange(nvtxs); touched[queue[0]] = 1; first = 0; last = 1; nleft = nvtxs-1; drain = 0; /* Start the BFS from queue to get a partition */ for (;;) { if (first == last) { /* Empty. Disconnected graph! */ if (nleft == 0 || drain) break; k = irandInRange(nleft); for (i=0; inbnd; i++) { j = bndind[i]; if (xadj[j+1]-xadj[j] > 0) /* ignore islands */ where[j] = 2; } Compute2WayNodePartitionParams(ctrl, graph); FM_2WayNodeRefine2Sided(ctrl, graph, 1); FM_2WayNodeRefine1Sided(ctrl, graph, 4); /* printf("ISep: [%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"] %"PRIDX"\n", inbfs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2], bestcut); */ if (inbfs == 0 || bestcut > graph->mincut) { bestcut = graph->mincut; icopy(nvtxs, where, bestwhere); } } graph->mincut = bestcut; icopy(nvtxs, bestwhere, where); WCOREPOP; } /*************************************************************************/ /* This function takes a graph and produces a tri-section into left, right, and separator using a region growing algorithm. The resulting separator is refined using node FM. The resulting partition is returned in graph->where. */ /**************************************************************************/ void GrowBisectionNode2(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { idx_t i, j, nvtxs, bestcut=0, inbfs; idx_t *xadj, *where, *bndind, *bestwhere; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; /* Allocate refinement memory. Allocate sufficient memory for both edge and node */ graph->pwgts = imalloc(3, "GrowBisectionNode: pwgts"); graph->where = imalloc(nvtxs, "GrowBisectionNode: where"); graph->bndptr = imalloc(nvtxs, "GrowBisectionNode: bndptr"); graph->bndind = imalloc(nvtxs, "GrowBisectionNode: bndind"); graph->id = imalloc(nvtxs, "GrowBisectionNode: id"); graph->ed = imalloc(nvtxs, "GrowBisectionNode: ed"); graph->nrinfo = (nrinfo_t *)gk_malloc(nvtxs*sizeof(nrinfo_t), "GrowBisectionNode: nrinfo"); bestwhere = iwspacemalloc(ctrl, nvtxs); where = graph->where; bndind = graph->bndind; for (inbfs=0; inbfs 0) where[irandInRange(nvtxs)] = 0; Compute2WayPartitionParams(ctrl, graph); General2WayBalance(ctrl, graph, ntpwgts); FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter); /* Construct and refine the vertex separator */ for (i=0; inbnd; i++) { j = bndind[i]; if (xadj[j+1]-xadj[j] > 0) /* ignore islands */ where[j] = 2; } Compute2WayNodePartitionParams(ctrl, graph); FM_2WayNodeRefine2Sided(ctrl, graph, 4); /* printf("ISep: [%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"] %"PRIDX"\n", inbfs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2], bestcut); */ if (inbfs == 0 || bestcut > graph->mincut) { bestcut = graph->mincut; icopy(nvtxs, where, bestwhere); } } graph->mincut = bestcut; icopy(nvtxs, bestwhere, where); WCOREPOP; } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/separator.c0000644000175100001440000001251314552244506025314 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * separator.c * * This file contains code for separator extraction * * Started 8/1/97 * George * * $Id: separator.c 10481 2011-07-05 18:01:23Z karypis $ * */ #include "metislib.h" /************************************************************************* * This function takes a bisection and constructs a minimum weight vertex * separator out of it. It uses the node-based separator refinement for it. **************************************************************************/ void ConstructSeparator(ctrl_t *ctrl, graph_t *graph) { idx_t i, j, nvtxs, nbnd; idx_t *xadj, *where, *bndind; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; nbnd = graph->nbnd; bndind = graph->bndind; where = icopy(nvtxs, graph->where, iwspacemalloc(ctrl, nvtxs)); /* Put the nodes in the boundary into the separator */ for (i=0; i 0) /* Ignore islands */ where[j] = 2; } FreeRData(graph); Allocate2WayNodePartitionMemory(ctrl, graph); icopy(nvtxs, where, graph->where); WCOREPOP; ASSERT(IsSeparable(graph)); Compute2WayNodePartitionParams(ctrl, graph); ASSERT(CheckNodePartitionParams(graph)); FM_2WayNodeRefine2Sided(ctrl, graph, 1); FM_2WayNodeRefine1Sided(ctrl, graph, 4); ASSERT(IsSeparable(graph)); } /************************************************************************* * This function takes a bisection and constructs a minimum weight vertex * separator out of it. It uses an unweighted minimum-cover algorithm * followed by node-based separator refinement. **************************************************************************/ void ConstructMinCoverSeparator(ctrl_t *ctrl, graph_t *graph) { idx_t i, ii, j, jj, k, l, nvtxs, nbnd, bnvtxs[3], bnedges[2], csize; idx_t *xadj, *adjncy, *bxadj, *badjncy; idx_t *where, *bndind, *vmap, *ivmap, *cover; #ifndef NDEBUG idx_t *bndptr; #endif WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; nbnd = graph->nbnd; bndind = graph->bndind; #ifndef NDEBUG bndptr = graph->bndptr; #endif where = graph->where; vmap = iwspacemalloc(ctrl, nvtxs); ivmap = iwspacemalloc(ctrl, nbnd); cover = iwspacemalloc(ctrl, nbnd); if (nbnd > 0) { /* Go through the boundary and determine the sizes of the bipartite graph */ bnvtxs[0] = bnvtxs[1] = bnedges[0] = bnedges[1] = 0; for (i=0; i 0) { bnvtxs[k]++; bnedges[k] += xadj[j+1]-xadj[j]; } } bnvtxs[2] = bnvtxs[0]+bnvtxs[1]; bnvtxs[1] = bnvtxs[0]; bnvtxs[0] = 0; bxadj = iwspacemalloc(ctrl, bnvtxs[2]+1); badjncy = iwspacemalloc(ctrl, bnedges[0]+bnedges[1]+1); /* Construct the ivmap and vmap */ ASSERT(iset(nvtxs, -1, vmap) == vmap); for (i=0; i 0) { vmap[j] = bnvtxs[k]; ivmap[bnvtxs[k]++] = j; } } /* OK, go through and put the vertices of each part starting from 0 */ bnvtxs[1] = bnvtxs[0]; bnvtxs[0] = 0; bxadj[0] = l = 0; for (k=0; k<2; k++) { for (ii=0; iibndptr[jj])); badjncy[l++] = vmap[jj]; } } bxadj[++bnvtxs[k]] = l; } } } ASSERT(l <= bnedges[0]+bnedges[1]); MinCover(bxadj, badjncy, bnvtxs[0], bnvtxs[1], cover, &csize); IFSET(ctrl->dbglvl, METIS_DBG_SEPINFO, printf("Nvtxs: %6"PRIDX", [%5"PRIDX" %5"PRIDX"], Cut: %6"PRIDX", SS: [%6"PRIDX" %6"PRIDX"], Cover: %6"PRIDX"\n", nvtxs, graph->pwgts[0], graph->pwgts[1], graph->mincut, bnvtxs[0], bnvtxs[1]-bnvtxs[0], csize)); for (i=0; idbglvl, METIS_DBG_SEPINFO, printf("Nvtxs: %6"PRIDX", [%5"PRIDX" %5"PRIDX"], Cut: %6"PRIDX", SS: [%6"PRIDX" %6"PRIDX"], Cover: %6"PRIDX"\n", nvtxs, graph->pwgts[0], graph->pwgts[1], graph->mincut, (idx_t)0, (idx_t)0, (idx_t)0)); } /* Prepare to refine the vertex separator */ icopy(nvtxs, graph->where, vmap); FreeRData(graph); Allocate2WayNodePartitionMemory(ctrl, graph); icopy(nvtxs, vmap, graph->where); WCOREPOP; Compute2WayNodePartitionParams(ctrl, graph); ASSERT(CheckNodePartitionParams(graph)); FM_2WayNodeRefine1Sided(ctrl, graph, ctrl->niter); ASSERT(IsSeparable(graph)); } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/mincover.c0000644000175100001440000001722114552244506025137 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * mincover.c * * This file implements the minimum cover algorithm * * Started 8/1/97 * George * * $Id: mincover.c 9942 2011-05-17 22:09:52Z karypis $ */ #include "metislib.h" /************************************************************************* * Constants used by mincover algorithm **************************************************************************/ #define INCOL 10 #define INROW 20 #define VC 1 #define SC 2 #define HC 3 #define VR 4 #define SR 5 #define HR 6 /************************************************************************* * This function returns the min-cover of a bipartite graph. * The algorithm used is due to Hopcroft and Karp as modified by Duff etal * adj: the adjacency list of the bipartite graph * asize: the number of vertices in the first part of the bipartite graph * bsize-asize: the number of vertices in the second part * 0..(asize-1) > A vertices * asize..bsize > B vertices * * Returns: * cover : the actual cover (array) * csize : the size of the cover **************************************************************************/ void MinCover(idx_t *xadj, idx_t *adjncy, idx_t asize, idx_t bsize, idx_t *cover, idx_t *csize) { idx_t i, j; idx_t *mate, *queue, *flag, *level, *lst; idx_t fptr, rptr, lstptr; idx_t row, maxlevel, col; mate = ismalloc(bsize, -1, "MinCover: mate"); flag = imalloc(bsize, "MinCover: flag"); level = imalloc(bsize, "MinCover: level"); queue = imalloc(bsize, "MinCover: queue"); lst = imalloc(bsize, "MinCover: lst"); /* Get a cheap matching */ for (i=0; invtxs = nvtxs; graph->nedges = xadj[nvtxs]; graph->ncon = ncon; graph->xadj = xadj; graph->free_xadj = 0; graph->adjncy = adjncy; graph->free_adjncy = 0; /* setup the vertex weights */ if (vwgt) { graph->vwgt = vwgt; graph->free_vwgt = 0; } else { vwgt = graph->vwgt = ismalloc(ncon*nvtxs, 1, "SetupGraph: vwgt"); } graph->tvwgt = imalloc(ncon, "SetupGraph: tvwgts"); graph->invtvwgt = rmalloc(ncon, "SetupGraph: invtvwgts"); for (i=0; itvwgt[i] = isum(nvtxs, vwgt+i, ncon); graph->invtvwgt[i] = 1.0/(graph->tvwgt[i] > 0 ? graph->tvwgt[i] : 1); } if (ctrl->objtype == METIS_OBJTYPE_VOL) { /* Setup the vsize */ if (vsize) { graph->vsize = vsize; graph->free_vsize = 0; } else { vsize = graph->vsize = ismalloc(nvtxs, 1, "SetupGraph: vsize"); } /* Allocate memory for edge weights and initialize them to the sum of the vsize */ adjwgt = graph->adjwgt = imalloc(graph->nedges, "SetupGraph: adjwgt"); for (i=0; iadjwgt = adjwgt; graph->free_adjwgt = 0; } else { adjwgt = graph->adjwgt = ismalloc(graph->nedges, 1, "SetupGraph: adjwgt"); } } /* setup various derived info */ SetupGraph_tvwgt(graph); if (ctrl->optype == METIS_OP_PMETIS || ctrl->optype == METIS_OP_OMETIS) SetupGraph_label(graph); ASSERT(CheckGraph(graph, ctrl->numflag, 1)); return graph; } /*************************************************************************/ /*! Set's up the tvwgt/invtvwgt info */ /*************************************************************************/ void SetupGraph_tvwgt(graph_t *graph) { idx_t i; if (graph->tvwgt == NULL) graph->tvwgt = imalloc(graph->ncon, "SetupGraph_tvwgt: tvwgt"); if (graph->invtvwgt == NULL) graph->invtvwgt = rmalloc(graph->ncon, "SetupGraph_tvwgt: invtvwgt"); for (i=0; incon; i++) { graph->tvwgt[i] = isum(graph->nvtxs, graph->vwgt+i, graph->ncon); graph->invtvwgt[i] = 1.0/(graph->tvwgt[i] > 0 ? graph->tvwgt[i] : 1); } } /*************************************************************************/ /*! Set's up the label info */ /*************************************************************************/ void SetupGraph_label(graph_t *graph) { idx_t i; if (graph->label == NULL) graph->label = imalloc(graph->nvtxs, "SetupGraph_label: label"); for (i=0; invtxs; i++) graph->label[i] = i; } /*************************************************************************/ /*! Setup the various arrays for the splitted graph */ /*************************************************************************/ graph_t *SetupSplitGraph(graph_t *graph, idx_t snvtxs, idx_t snedges) { graph_t *sgraph; sgraph = CreateGraph(); sgraph->nvtxs = snvtxs; sgraph->nedges = snedges; sgraph->ncon = graph->ncon; /* Allocate memory for the splitted graph */ sgraph->xadj = imalloc(snvtxs+1, "SetupSplitGraph: xadj"); sgraph->vwgt = imalloc(sgraph->ncon*snvtxs, "SetupSplitGraph: vwgt"); sgraph->adjncy = imalloc(snedges, "SetupSplitGraph: adjncy"); sgraph->adjwgt = imalloc(snedges, "SetupSplitGraph: adjwgt"); sgraph->label = imalloc(snvtxs, "SetupSplitGraph: label"); sgraph->tvwgt = imalloc(sgraph->ncon, "SetupSplitGraph: tvwgt"); sgraph->invtvwgt = rmalloc(sgraph->ncon, "SetupSplitGraph: invtvwgt"); if (graph->vsize) sgraph->vsize = imalloc(snvtxs, "SetupSplitGraph: vsize"); return sgraph; } /*************************************************************************/ /*! This function creates and initializes a graph_t data structure */ /*************************************************************************/ graph_t *CreateGraph(void) { graph_t *graph; graph = (graph_t *)gk_malloc(sizeof(graph_t), "CreateGraph: graph"); InitGraph(graph); return graph; } /*************************************************************************/ /*! This function initializes a graph_t data structure */ /*************************************************************************/ void InitGraph(graph_t *graph) { memset((void *)graph, 0, sizeof(graph_t)); /* graph size constants */ graph->nvtxs = -1; graph->nedges = -1; graph->ncon = -1; graph->mincut = -1; graph->minvol = -1; graph->nbnd = -1; /* memory for the graph structure */ graph->xadj = NULL; graph->vwgt = NULL; graph->vsize = NULL; graph->adjncy = NULL; graph->adjwgt = NULL; graph->label = NULL; graph->cmap = NULL; graph->tvwgt = NULL; graph->invtvwgt = NULL; /* by default these are set to true, but the can be explicitly changed afterwards */ graph->free_xadj = 1; graph->free_vwgt = 1; graph->free_vsize = 1; graph->free_adjncy = 1; graph->free_adjwgt = 1; /* memory for the partition/refinement structure */ graph->where = NULL; graph->pwgts = NULL; graph->id = NULL; graph->ed = NULL; graph->bndptr = NULL; graph->bndind = NULL; graph->nrinfo = NULL; graph->ckrinfo = NULL; graph->vkrinfo = NULL; /* linked-list structure */ graph->coarser = NULL; graph->finer = NULL; } /*************************************************************************/ /*! This function frees the refinement/partition memory stored in a graph */ /*************************************************************************/ void FreeRData(graph_t *graph) { /* The following is for the -minconn and -contig to work properly in the vol-refinement routines */ if ((void *)graph->ckrinfo == (void *)graph->vkrinfo) graph->ckrinfo = NULL; /* free partition/refinement structure */ gk_free((void **)&graph->where, &graph->pwgts, &graph->id, &graph->ed, &graph->bndptr, &graph->bndind, &graph->nrinfo, &graph->ckrinfo, &graph->vkrinfo, LTERM); } /*************************************************************************/ /*! This function deallocates any memory stored in a graph */ /*************************************************************************/ void FreeGraph(graph_t **r_graph) { graph_t *graph; graph = *r_graph; /* free graph structure */ if (graph->free_xadj) gk_free((void **)&graph->xadj, LTERM); if (graph->free_vwgt) gk_free((void **)&graph->vwgt, LTERM); if (graph->free_vsize) gk_free((void **)&graph->vsize, LTERM); if (graph->free_adjncy) gk_free((void **)&graph->adjncy, LTERM); if (graph->free_adjwgt) gk_free((void **)&graph->adjwgt, LTERM); /* free partition/refinement structure */ FreeRData(graph); gk_free((void **)&graph->tvwgt, &graph->invtvwgt, &graph->label, &graph->cmap, &graph, LTERM); *r_graph = NULL; } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/refine.c0000644000175100001440000001422114552244506024562 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* \file \brief This file contains the driving routines for multilevel refinement \date Started 7/24/1997 \author George \author Copyright 1997-2009, Regents of the University of Minnesota \version\verbatim $Id: refine.c 10513 2011-07-07 22:06:03Z karypis $ \endverbatim */ #include "metislib.h" /*************************************************************************/ /*! This function is the entry point of refinement */ /*************************************************************************/ void Refine2Way(ctrl_t *ctrl, graph_t *orggraph, graph_t *graph, real_t *tpwgts) { IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->UncoarsenTmr)); /* Compute the parameters of the coarsest graph */ Compute2WayPartitionParams(ctrl, graph); for (;;) { ASSERT(CheckBnd(graph)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->RefTmr)); Balance2Way(ctrl, graph, tpwgts); FM_2WayRefine(ctrl, graph, tpwgts, ctrl->niter); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->RefTmr)); if (graph == orggraph) break; graph = graph->finer; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ProjectTmr)); Project2WayPartition(ctrl, graph); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ProjectTmr)); } IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->UncoarsenTmr)); } /*************************************************************************/ /*! This function allocates memory for 2-way edge refinement */ /*************************************************************************/ void Allocate2WayPartitionMemory(ctrl_t *ctrl, graph_t *graph) { idx_t nvtxs, ncon; nvtxs = graph->nvtxs; ncon = graph->ncon; graph->pwgts = imalloc(2*ncon, "Allocate2WayPartitionMemory: pwgts"); graph->where = imalloc(nvtxs, "Allocate2WayPartitionMemory: where"); graph->bndptr = imalloc(nvtxs, "Allocate2WayPartitionMemory: bndptr"); graph->bndind = imalloc(nvtxs, "Allocate2WayPartitionMemory: bndind"); graph->id = imalloc(nvtxs, "Allocate2WayPartitionMemory: id"); graph->ed = imalloc(nvtxs, "Allocate2WayPartitionMemory: ed"); } /*************************************************************************/ /*! This function computes the initial id/ed */ /*************************************************************************/ void Compute2WayPartitionParams(ctrl_t *ctrl, graph_t *graph) { idx_t i, j, nvtxs, ncon, nbnd, mincut, istart, iend, tid, ted, me; idx_t *xadj, *vwgt, *adjncy, *adjwgt, *pwgts; idx_t *where, *bndptr, *bndind, *id, *ed; nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; id = graph->id; ed = graph->ed; pwgts = iset(2*ncon, 0, graph->pwgts); bndptr = iset(nvtxs, -1, graph->bndptr); bndind = graph->bndind; /* Compute pwgts */ if (ncon == 1) { for (i=0; i= 0 && where[i] <= 1); pwgts[where[i]] += vwgt[i]; } ASSERT(pwgts[0]+pwgts[1] == graph->tvwgt[0]); } else { for (i=0; i 0 || istart == iend) { BNDInsert(nbnd, bndind, bndptr, i); mincut += ted; } } graph->mincut = mincut/2; graph->nbnd = nbnd; } /*************************************************************************/ /*! Projects a partition and computes the refinement params. */ /*************************************************************************/ void Project2WayPartition(ctrl_t *ctrl, graph_t *graph) { idx_t i, j, istart, iend, nvtxs, nbnd, me, tid, ted; idx_t *xadj, *adjncy, *adjwgt; idx_t *cmap, *where, *bndptr, *bndind; idx_t *cwhere, *cbndptr; idx_t *id, *ed; graph_t *cgraph; Allocate2WayPartitionMemory(ctrl, graph); cgraph = graph->coarser; cwhere = cgraph->where; cbndptr = cgraph->bndptr; nvtxs = graph->nvtxs; cmap = graph->cmap; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; id = graph->id; ed = graph->ed; bndptr = iset(nvtxs, -1, graph->bndptr); bndind = graph->bndind; /* Project the partition and record which of these nodes came from the coarser boundary */ for (i=0; i 0 || istart == iend) BNDInsert(nbnd, bndind, bndptr, i); } graph->mincut = cgraph->mincut; graph->nbnd = nbnd; /* copy pwgts */ icopy(2*graph->ncon, cgraph->pwgts, graph->pwgts); FreeGraph(&graph->coarser); graph->coarser = NULL; } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/parmetis.c0000644000175100001440000005551214552244506025146 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * parmetis.c * * This file contains top level routines that are used by ParMETIS * * Started 10/14/97 * George * * $Id: parmetis.c 10481 2011-07-05 18:01:23Z karypis $ * */ #include "metislib.h" /*************************************************************************/ /*! This function is the entry point for the node ND code for ParMETIS. The difference between this routine and the standard METIS_NodeND are the following - It performs at least log2(npes) levels of nested dissection. - It stores the size of the log2(npes) top-level separators in the sizes array. */ /*************************************************************************/ int METIS_NodeNDP(idx_t nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t npes, idx_t *options, idx_t *perm, idx_t *iperm, idx_t *sizes) { idx_t i, ii, j, l, nnvtxs=0; graph_t *graph; ctrl_t *ctrl; idx_t *cptr, *cind; ctrl = SetupCtrl(METIS_OP_OMETIS, options, 1, 3, NULL, NULL); if (!ctrl) return METIS_ERROR_INPUT; IFSET(ctrl->dbglvl, METIS_DBG_TIME, InitTimers(ctrl)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->TotalTmr)); /* compress the graph; not that compression only happens if not prunning has taken place. */ if (ctrl->compress) { cptr = imalloc(nvtxs+1, "OMETIS: cptr"); cind = imalloc(nvtxs, "OMETIS: cind"); graph = CompressGraph(ctrl, nvtxs, xadj, adjncy, vwgt, cptr, cind); if (graph == NULL) { /* if there was no compression, cleanup the compress flag */ gk_free((void **)&cptr, &cind, LTERM); ctrl->compress = 0; } else { nnvtxs = graph->nvtxs; } } /* if no compression, setup the graph in the normal way. */ if (ctrl->compress == 0) graph = SetupGraph(ctrl, nvtxs, 1, xadj, adjncy, vwgt, NULL, NULL); /* allocate workspace memory */ AllocateWorkSpace(ctrl, graph); /* do the nested dissection ordering */ iset(2*npes-1, 0, sizes); MlevelNestedDissectionP(ctrl, graph, iperm, graph->nvtxs, npes, 0, sizes); /* Uncompress the ordering */ if (ctrl->compress) { /* construct perm from iperm */ for (i=0; idbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->TotalTmr)); IFSET(ctrl->dbglvl, METIS_DBG_TIME, PrintTimers(ctrl)); /* clean up */ FreeCtrl(&ctrl); return METIS_OK; } /*************************************************************************/ /*! This function is similar to MlevelNestedDissection with the difference that it also records separator sizes for the top log2(npes) levels */ /**************************************************************************/ void MlevelNestedDissectionP(ctrl_t *ctrl, graph_t *graph, idx_t *order, idx_t lastvtx, idx_t npes, idx_t cpos, idx_t *sizes) { idx_t i, nvtxs, nbnd; idx_t *label, *bndind; graph_t *lgraph, *rgraph; nvtxs = graph->nvtxs; if (nvtxs == 0) { FreeGraph(&graph); return; } MlevelNodeBisectionMultiple(ctrl, graph); IFSET(ctrl->dbglvl, METIS_DBG_SEPINFO, printf("Nvtxs: %6"PRIDX", [%6"PRIDX" %6"PRIDX" %6"PRIDX"]\n", graph->nvtxs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2])); if (cpos < npes-1) { sizes[2*npes-2-cpos] = graph->pwgts[2]; sizes[2*npes-2-(2*cpos+1)] = graph->pwgts[1]; sizes[2*npes-2-(2*cpos+2)] = graph->pwgts[0]; } /* Order the nodes in the separator */ nbnd = graph->nbnd; bndind = graph->bndind; label = graph->label; for (i=0; invtxs > MMDSWITCH || 2*cpos+2 < npes-1) && lgraph->nedges > 0) MlevelNestedDissectionP(ctrl, lgraph, order, lastvtx-rgraph->nvtxs, npes, 2*cpos+2, sizes); else { MMDOrder(ctrl, lgraph, order, lastvtx-rgraph->nvtxs); FreeGraph(&lgraph); } if ((rgraph->nvtxs > MMDSWITCH || 2*cpos+1 < npes-1) && rgraph->nedges > 0) MlevelNestedDissectionP(ctrl, rgraph, order, lastvtx, npes, 2*cpos+1, sizes); else { MMDOrder(ctrl, rgraph, order, lastvtx); FreeGraph(&rgraph); } } /*************************************************************************/ /*! This function bisects a graph by computing a vertex separator */ /**************************************************************************/ int METIS_ComputeVertexSeparator(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *options, idx_t *r_sepsize, idx_t *part) { graph_t *graph; ctrl_t *ctrl; if ((ctrl = SetupCtrl(METIS_OP_OMETIS, options, 1, 3, NULL, NULL)) == NULL) return METIS_ERROR_INPUT; InitRandom(ctrl->seed); graph = SetupGraph(ctrl, *nvtxs, 1, xadj, adjncy, vwgt, NULL, NULL); AllocateWorkSpace(ctrl, graph); /*============================================================ * Perform the bisection *============================================================*/ ctrl->CoarsenTo = 100; MlevelNodeBisectionMultiple(ctrl, graph); *r_sepsize = graph->pwgts[2]; icopy(*nvtxs, graph->where, part); FreeGraph(&graph); FreeCtrl(&ctrl); return METIS_OK; } /*************************************************************************/ /*! This function is the entry point of a node-based separator refinement of the nodes with an hmarker[] of 0. */ /*************************************************************************/ int METIS_NodeRefine(idx_t nvtxs, idx_t *xadj, idx_t *vwgt, idx_t *adjncy, idx_t *where, idx_t *hmarker, real_t ubfactor) { graph_t *graph; ctrl_t *ctrl; /* set up the run time parameters */ ctrl = SetupCtrl(METIS_OP_OMETIS, NULL, 1, 3, NULL, NULL); if (!ctrl) return METIS_ERROR_INPUT; /* set up the graph */ graph = SetupGraph(ctrl, nvtxs, 1, xadj, adjncy, vwgt, NULL, NULL); /* allocate workspace memory */ AllocateWorkSpace(ctrl, graph); /* set up the memory and the input partition */ Allocate2WayNodePartitionMemory(ctrl, graph); icopy(nvtxs, where, graph->where); Compute2WayNodePartitionParams(ctrl, graph); FM_2WayNodeRefine1SidedP(ctrl, graph, hmarker, ubfactor, 10); /* FM_2WayNodeRefine2SidedP(ctrl, graph, hmarker, ubfactor, 10); */ icopy(nvtxs, graph->where, where); FreeGraph(&graph); FreeCtrl(&ctrl); return METIS_OK; } /*************************************************************************/ /*! This function performs a node-based 1-sided FM refinement that moves only nodes whose hmarker[] == -1. It is used by Parmetis. */ /*************************************************************************/ void FM_2WayNodeRefine1SidedP(ctrl_t *ctrl, graph_t *graph, idx_t *hmarker, real_t ubfactor, idx_t npasses) { idx_t i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, nmind, nbad, qsize; idx_t *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr; idx_t *mptr, *mind, *swaps, *inqueue; rpq_t *queue; nrinfo_t *rinfo; idx_t higain, oldgain, mincut, initcut, mincutorder; idx_t pass, from, to, limit; idx_t badmaxpwgt, mindiff, newdiff; WCOREPUSH; ASSERT(graph->mincut == graph->pwgts[2]); nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; vwgt = graph->vwgt; bndind = graph->bndind; bndptr = graph->bndptr; where = graph->where; pwgts = graph->pwgts; rinfo = graph->nrinfo; queue = rpqCreate(nvtxs); inqueue = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs)); swaps = iwspacemalloc(ctrl, nvtxs); mptr = iwspacemalloc(ctrl, nvtxs+1); mind = iwspacemalloc(ctrl, 2*nvtxs); badmaxpwgt = (idx_t)(ubfactor*gk_max(pwgts[0], pwgts[1])); IFSET(ctrl->dbglvl, METIS_DBG_REFINE, printf("Partitions-N1: [%6"PRIDX" %6"PRIDX"] Nv-Nb[%6"PRIDX" %6"PRIDX"] " "MaxPwgt[%6"PRIDX"]. ISep: %6"PRIDX"\n", pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, badmaxpwgt, graph->mincut)); to = (pwgts[0] < pwgts[1] ? 1 : 0); for (pass=0; passmincut; nbnd = graph->nbnd; /* use the swaps array in place of the traditional perm array to save memory */ irandArrayPermute(nbnd, swaps, nbnd, 1); for (ii=0; ii= 2*nvtxs-1) break; inqueue[higain] = -1; if (pwgts[to]+vwgt[higain] > badmaxpwgt) { /* Skip this vertex */ if (nbad++ > limit) break; else { nswaps--; continue; } } pwgts[2] -= (vwgt[higain]-rinfo[higain].edegrees[from]); newdiff = abs(pwgts[to]+vwgt[higain] - (pwgts[from]-rinfo[higain].edegrees[from])); if (pwgts[2] < mincut || (pwgts[2] == mincut && newdiff < mindiff)) { mincut = pwgts[2]; mincutorder = nswaps; mindiff = newdiff; nbad = 0; } else { if (nbad++ > limit) { pwgts[2] += (vwgt[higain]-rinfo[higain].edegrees[from]); break; /* No further improvement, break out */ } } BNDDelete(nbnd, bndind, bndptr, higain); pwgts[to] += vwgt[higain]; where[higain] = to; swaps[nswaps] = higain; /********************************************************** * Update the degrees of the affected nodes ***********************************************************/ for (j=xadj[higain]; jdbglvl, METIS_DBG_MOVEINFO, printf("Moved %6"PRIDX" to %3"PRIDX", Gain: %5"PRIDX" [%5"PRIDX"] \t[%5"PRIDX" %5"PRIDX" %5"PRIDX"] [%3"PRIDX" %2"PRIDX"]\n", higain, to, (vwgt[higain]-rinfo[higain].edegrees[from]), vwgt[higain], pwgts[0], pwgts[1], pwgts[2], nswaps, limit)); } /**************************************************************** * Roll back computation *****************************************************************/ for (nswaps--; nswaps>mincutorder; nswaps--) { higain = swaps[nswaps]; ASSERT(CheckNodePartitionParams(graph)); ASSERT(where[higain] == to); INC_DEC(pwgts[2], pwgts[to], vwgt[higain]); where[higain] = 2; BNDInsert(nbnd, bndind, bndptr, higain); edegrees = rinfo[higain].edegrees; edegrees[0] = edegrees[1] = 0; for (j=xadj[higain]; jdbglvl, METIS_DBG_REFINE, printf("\tMinimum sep: %6"PRIDX" at %5"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX", QSIZE: %6"PRIDX"\n", mincut, mincutorder, pwgts[0], pwgts[1], nbnd, qsize)); graph->mincut = mincut; graph->nbnd = nbnd; if (pass%2 == 1 && (mincutorder == -1 || mincut >= initcut)) break; } rpqDestroy(queue); WCOREPOP; } /*************************************************************************/ /*! This function performs a node-based (two-sided) FM refinement that moves only nodes whose hmarker[] == -1. It is used by Parmetis. */ /*************************************************************************/ void FM_2WayNodeRefine2SidedP(ctrl_t *ctrl, graph_t *graph, idx_t *hmarker, real_t ubfactor, idx_t npasses) { idx_t i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, nmind; idx_t *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr; idx_t *mptr, *mind, *moved, *swaps; rpq_t *queues[2]; nrinfo_t *rinfo; idx_t higain, oldgain, mincut, initcut, mincutorder; idx_t pass, to, other, limit; idx_t badmaxpwgt, mindiff, newdiff; idx_t u[2], g[2]; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; vwgt = graph->vwgt; bndind = graph->bndind; bndptr = graph->bndptr; where = graph->where; pwgts = graph->pwgts; rinfo = graph->nrinfo; queues[0] = rpqCreate(nvtxs); queues[1] = rpqCreate(nvtxs); moved = iwspacemalloc(ctrl, nvtxs); swaps = iwspacemalloc(ctrl, nvtxs); mptr = iwspacemalloc(ctrl, nvtxs+1); mind = iwspacemalloc(ctrl, 2*nvtxs); IFSET(ctrl->dbglvl, METIS_DBG_REFINE, printf("Partitions: [%6"PRIDX" %6"PRIDX"] Nv-Nb[%6"PRIDX" %6"PRIDX"]. ISep: %6"PRIDX"\n", pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, graph->mincut)); badmaxpwgt = (idx_t)(ubfactor*gk_max(pwgts[0], pwgts[1])); for (pass=0; passmincut; nbnd = graph->nbnd; /* use the swaps array in place of the traditional perm array to save memory */ irandArrayPermute(nbnd, swaps, nbnd, 1); for (ii=0; ii g[1] ? 0 : (g[0] < g[1] ? 1 : pass%2)); if (pwgts[to]+vwgt[u[to]] > badmaxpwgt) to = (to+1)%2; } else if (u[0] == -1 && u[1] == -1) { break; } else if (u[0] != -1 && pwgts[0]+vwgt[u[0]] <= badmaxpwgt) { to = 0; } else if (u[1] != -1 && pwgts[1]+vwgt[u[1]] <= badmaxpwgt) { to = 1; } else break; other = (to+1)%2; higain = rpqGetTop(queues[to]); /* Delete its matching entry in the other queue */ if (moved[higain] == -5) rpqDelete(queues[other], higain); ASSERT(bndptr[higain] != -1); /* The following check is to ensure we break out if there is a posibility of over-running the mind array. */ if (nmind + xadj[higain+1]-xadj[higain] >= 2*nvtxs-1) break; pwgts[2] -= (vwgt[higain]-rinfo[higain].edegrees[other]); newdiff = abs(pwgts[to]+vwgt[higain] - (pwgts[other]-rinfo[higain].edegrees[other])); if (pwgts[2] < mincut || (pwgts[2] == mincut && newdiff < mindiff)) { mincut = pwgts[2]; mincutorder = nswaps; mindiff = newdiff; } else { if (nswaps - mincutorder > limit) { pwgts[2] += (vwgt[higain]-rinfo[higain].edegrees[other]); break; /* No further improvement, break out */ } } BNDDelete(nbnd, bndind, bndptr, higain); pwgts[to] += vwgt[higain]; where[higain] = to; moved[higain] = nswaps; swaps[nswaps] = higain; /********************************************************** * Update the degrees of the affected nodes ***********************************************************/ for (j=xadj[higain]; jdbglvl, METIS_DBG_MOVEINFO, printf("Moved %6"PRIDX" to %3"PRIDX", Gain: %5"PRIDX" [%5"PRIDX"] " "[%4"PRIDX" %4"PRIDX"] \t[%5"PRIDX" %5"PRIDX" %5"PRIDX"]\n", higain, to, g[to], g[other], vwgt[u[to]], vwgt[u[other]], pwgts[0], pwgts[1], pwgts[2])); } /**************************************************************** * Roll back computation *****************************************************************/ for (nswaps--; nswaps>mincutorder; nswaps--) { higain = swaps[nswaps]; ASSERT(CheckNodePartitionParams(graph)); to = where[higain]; other = (to+1)%2; INC_DEC(pwgts[2], pwgts[to], vwgt[higain]); where[higain] = 2; BNDInsert(nbnd, bndind, bndptr, higain); edegrees = rinfo[higain].edegrees; edegrees[0] = edegrees[1] = 0; for (j=xadj[higain]; jdbglvl, METIS_DBG_REFINE, printf("\tMinimum sep: %6"PRIDX" at %5"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", mincut, mincutorder, pwgts[0], pwgts[1], nbnd)); graph->mincut = mincut; graph->nbnd = nbnd; if (mincutorder == -1 || mincut >= initcut) break; } rpqDestroy(queues[0]); rpqDestroy(queues[1]); WCOREPOP; } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/fm.c0000644000175100001440000004575514552244506023734 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file \brief Functions for the edge-based FM refinement \date Started 7/23/97 \author George \author Copyright 1997-2011, Regents of the University of Minnesota \version\verbatim $Id: fm.c 10187 2011-06-13 13:46:57Z karypis $ \endverbatim */ #include "metislib.h" /************************************************************************* * This function performs an edge-based FM refinement **************************************************************************/ void FM_2WayRefine(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niter) { if (graph->ncon == 1) FM_2WayCutRefine(ctrl, graph, ntpwgts, niter); else FM_Mc2WayCutRefine(ctrl, graph, ntpwgts, niter); } /*************************************************************************/ /*! This function performs a cut-focused FM refinement */ /*************************************************************************/ void FM_2WayCutRefine(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niter) { idx_t i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, pass, limit, tmp; idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *id, *ed, *bndptr, *bndind, *pwgts; idx_t *moved, *swaps, *perm; rpq_t *queues[2]; idx_t higain, mincut, mindiff, origdiff, initcut, newcut, mincutorder, avgvwgt; idx_t tpwgts[2]; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; id = graph->id; ed = graph->ed; pwgts = graph->pwgts; bndptr = graph->bndptr; bndind = graph->bndind; moved = iwspacemalloc(ctrl, nvtxs); swaps = iwspacemalloc(ctrl, nvtxs); perm = iwspacemalloc(ctrl, nvtxs); tpwgts[0] = graph->tvwgt[0]*ntpwgts[0]; tpwgts[1] = graph->tvwgt[0]-tpwgts[0]; limit = gk_min(gk_max(0.01*nvtxs, 15), 100); avgvwgt = gk_min((pwgts[0]+pwgts[1])/20, 2*(pwgts[0]+pwgts[1])/nvtxs); queues[0] = rpqCreate(nvtxs); queues[1] = rpqCreate(nvtxs); IFSET(ctrl->dbglvl, METIS_DBG_REFINE, Print2WayRefineStats(ctrl, graph, ntpwgts, 0, -2)); origdiff = iabs(tpwgts[0]-pwgts[0]); iset(nvtxs, -1, moved); for (pass=0; passmincut; mindiff = iabs(tpwgts[0]-pwgts[0]); ASSERT(ComputeCut(graph, where) == graph->mincut); ASSERT(CheckBnd(graph)); /* Insert boundary nodes in the priority queues */ nbnd = graph->nbnd; irandArrayPermute(nbnd, perm, nbnd, 1); for (ii=0; ii 0 || id[bndind[i]] == 0); ASSERT(bndptr[bndind[i]] != -1); rpqInsert(queues[where[bndind[i]]], bndind[i], ed[bndind[i]]-id[bndind[i]]); } for (nswaps=0; nswaps limit) { /* We hit the limit, undo last move */ newcut += (ed[higain]-id[higain]); INC_DEC(pwgts[from], pwgts[to], vwgt[higain]); break; } where[higain] = to; moved[higain] = nswaps; swaps[nswaps] = higain; IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, printf("Moved %6"PRIDX" from %"PRIDX". [%3"PRIDX" %3"PRIDX"] %5"PRIDX" [%4"PRIDX" %4"PRIDX"]\n", higain, from, ed[higain]-id[higain], vwgt[higain], newcut, pwgts[0], pwgts[1])); /************************************************************** * Update the id[i]/ed[i] values of the affected nodes ***************************************************************/ SWAP(id[higain], ed[higain], tmp); if (ed[higain] == 0 && xadj[higain] < xadj[higain+1]) BNDDelete(nbnd, bndind, bndptr, higain); for (j=xadj[higain]; j 0) { /* It will now become a boundary vertex */ BNDInsert(nbnd, bndind, bndptr, k); if (moved[k] == -1) rpqInsert(queues[where[k]], k, ed[k]-id[k]); } } } } /**************************************************************** * Roll back computations *****************************************************************/ for (i=0; imincutorder; nswaps--) { higain = swaps[nswaps]; to = where[higain] = (where[higain]+1)%2; SWAP(id[higain], ed[higain], tmp); if (ed[higain] == 0 && bndptr[higain] != -1 && xadj[higain] < xadj[higain+1]) BNDDelete(nbnd, bndind, bndptr, higain); else if (ed[higain] > 0 && bndptr[higain] == -1) BNDInsert(nbnd, bndind, bndptr, higain); INC_DEC(pwgts[to], pwgts[(to+1)%2], vwgt[higain]); for (j=xadj[higain]; j 0) BNDInsert(nbnd, bndind, bndptr, k); } } graph->mincut = mincut; graph->nbnd = nbnd; IFSET(ctrl->dbglvl, METIS_DBG_REFINE, Print2WayRefineStats(ctrl, graph, ntpwgts, 0, mincutorder)); if (mincutorder <= 0 || mincut == initcut) break; } rpqDestroy(queues[0]); rpqDestroy(queues[1]); WCOREPOP; } /*************************************************************************/ /*! This function performs a cut-focused multi-constraint FM refinement */ /*************************************************************************/ void FM_Mc2WayCutRefine(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niter) { idx_t i, ii, j, k, l, kwgt, nvtxs, ncon, nbnd, nswaps, from, to, pass, limit, tmp, cnum; idx_t *xadj, *adjncy, *vwgt, *adjwgt, *pwgts, *where, *id, *ed, *bndptr, *bndind; idx_t *moved, *swaps, *perm, *qnum; idx_t higain, mincut, initcut, newcut, mincutorder; real_t *invtvwgt, *ubfactors, *minbalv, *newbalv; real_t origbal, minbal, newbal, rgain, ffactor; rpq_t **queues; WCOREPUSH; nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; invtvwgt = graph->invtvwgt; where = graph->where; id = graph->id; ed = graph->ed; pwgts = graph->pwgts; bndptr = graph->bndptr; bndind = graph->bndind; moved = iwspacemalloc(ctrl, nvtxs); swaps = iwspacemalloc(ctrl, nvtxs); perm = iwspacemalloc(ctrl, nvtxs); qnum = iwspacemalloc(ctrl, nvtxs); ubfactors = rwspacemalloc(ctrl, ncon); newbalv = rwspacemalloc(ctrl, ncon); minbalv = rwspacemalloc(ctrl, ncon); limit = gk_min(gk_max(0.01*nvtxs, 25), 150); /* Determine a fudge factor to allow the refinement routines to get out of tight balancing constraints. */ ffactor = .5/gk_max(20, nvtxs); /* Initialize the queues */ queues = (rpq_t **)wspacemalloc(ctrl, 2*ncon*sizeof(rpq_t *)); for (i=0; i<2*ncon; i++) queues[i] = rpqCreate(nvtxs); for (i=0; ipijbm, ctrl->ubfactors, ubfactors); for (i=0; i 0 ? ctrl->ubfactors[i]+ubfactors[i] : ctrl->ubfactors[i]); IFSET(ctrl->dbglvl, METIS_DBG_REFINE, Print2WayRefineStats(ctrl, graph, ntpwgts, origbal, -2)); iset(nvtxs, -1, moved); for (pass=0; passmincut; minbal = ComputeLoadImbalanceDiffVec(graph, 2, ctrl->pijbm, ubfactors, minbalv); ASSERT(ComputeCut(graph, where) == graph->mincut); ASSERT(CheckBnd(graph)); /* Insert boundary nodes in the priority queues */ nbnd = graph->nbnd; irandArrayPermute(nbnd, perm, nbnd/5, 1); for (ii=0; ii 0 || id[i] == 0); ASSERT(bndptr[i] != -1); //rgain = 1.0*(ed[i]-id[i])/sqrt(vwgt[i*ncon+qnum[i]]+1); //rgain = (ed[i]-id[i] > 0 ? 1.0*(ed[i]-id[i])/sqrt(vwgt[i*ncon+qnum[i]]+1) : ed[i]-id[i]); rgain = ed[i]-id[i]; rpqInsert(queues[2*qnum[i]+where[i]], i, rgain); } for (nswaps=0; nswapspijbm, ubfactors, queues, &from, &cnum); to = (from+1)%2; if (from == -1 || (higain = rpqGetTop(queues[2*cnum+from])) == -1) break; ASSERT(bndptr[higain] != -1); newcut -= (ed[higain]-id[higain]); iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1); iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+from*ncon, 1); newbal = ComputeLoadImbalanceDiffVec(graph, 2, ctrl->pijbm, ubfactors, newbalv); if ((newcut < mincut && newbal <= ffactor) || (newcut == mincut && (newbal < minbal || (newbal == minbal && BetterBalance2Way(ncon, minbalv, newbalv))))) { mincut = newcut; minbal = newbal; mincutorder = nswaps; rcopy(ncon, newbalv, minbalv); } else if (nswaps-mincutorder > limit) { /* We hit the limit, undo last move */ newcut += (ed[higain]-id[higain]); iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+from*ncon, 1); iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1); break; } where[higain] = to; moved[higain] = nswaps; swaps[nswaps] = higain; if (ctrl->dbglvl&METIS_DBG_MOVEINFO) { printf("Moved%6"PRIDX" from %"PRIDX"(%"PRIDX") Gain:%5"PRIDX", " "Cut:%5"PRIDX", NPwgts:", higain, from, cnum, ed[higain]-id[higain], newcut); for (l=0; lpijbm), newbal); } /************************************************************** * Update the id[i]/ed[i] values of the affected nodes ***************************************************************/ SWAP(id[higain], ed[higain], tmp); if (ed[higain] == 0 && xadj[higain] < xadj[higain+1]) BNDDelete(nbnd, bndind, bndptr, higain); for (j=xadj[higain]; j 0 ? // 1.0*(ed[k]-id[k])/sqrt(vwgt[k*ncon+qnum[k]]+1) : ed[k]-id[k]); rgain = ed[k]-id[k]; rpqUpdate(queues[2*qnum[k]+where[k]], k, rgain); } } } else { if (ed[k] > 0) { /* It will now become a boundary vertex */ BNDInsert(nbnd, bndind, bndptr, k); if (moved[k] == -1) { //rgain = 1.0*(ed[k]-id[k])/sqrt(vwgt[k*ncon+qnum[k]]+1); //rgain = (ed[k]-id[k] > 0 ? // 1.0*(ed[k]-id[k])/sqrt(vwgt[k*ncon+qnum[k]]+1) : ed[k]-id[k]); rgain = ed[k]-id[k]; rpqInsert(queues[2*qnum[k]+where[k]], k, rgain); } } } } } /**************************************************************** * Roll back computations *****************************************************************/ for (i=0; imincutorder; nswaps--) { higain = swaps[nswaps]; to = where[higain] = (where[higain]+1)%2; SWAP(id[higain], ed[higain], tmp); if (ed[higain] == 0 && bndptr[higain] != -1 && xadj[higain] < xadj[higain+1]) BNDDelete(nbnd, bndind, bndptr, higain); else if (ed[higain] > 0 && bndptr[higain] == -1) BNDInsert(nbnd, bndind, bndptr, higain); iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1); iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+((to+1)%2)*ncon, 1); for (j=xadj[higain]; j 0) BNDInsert(nbnd, bndind, bndptr, k); } } graph->mincut = mincut; graph->nbnd = nbnd; IFSET(ctrl->dbglvl, METIS_DBG_REFINE, Print2WayRefineStats(ctrl, graph, ntpwgts, minbal, mincutorder)); if (mincutorder <= 0 || mincut == initcut) break; } for (i=0; i<2*ncon; i++) rpqDestroy(queues[i]); WCOREPOP; } /*************************************************************************/ /*! This function selects the partition number and the queue from which we will move vertices out. */ /*************************************************************************/ void SelectQueue(graph_t *graph, real_t *pijbm, real_t *ubfactors, rpq_t **queues, idx_t *from, idx_t *cnum) { idx_t ncon, i, part; real_t max, tmp; ncon = graph->ncon; *from = -1; *cnum = -1; /* First determine the side and the queue, irrespective of the presence of nodes. The side & queue is determined based on the most violated balancing constraint. */ for (max=0.0, part=0; part<2; part++) { for (i=0; ipwgts[part*ncon+i]*pijbm[part*ncon+i] - ubfactors[i]; /* the '=' in the test bellow is to ensure that under tight constraints the partition that is at the max is selected */ if (tmp >= max) { max = tmp; *from = part; *cnum = i; } } } if (*from != -1) { /* in case the desired queue is empty, select a queue from the same side */ if (rpqLength(queues[2*(*cnum)+(*from)]) == 0) { for (i=0; i 0) { max = graph->pwgts[(*from)*ncon+i]*pijbm[(*from)*ncon+i] - ubfactors[i]; *cnum = i; break; } } for (i++; ipwgts[(*from)*ncon+i]*pijbm[(*from)*ncon+i] - ubfactors[i]; if (tmp > max && rpqLength(queues[2*i+(*from)]) > 0) { max = tmp; *cnum = i; } } } /* printf("Selected1 %"PRIDX"(%"PRIDX") -> %"PRIDX" [%5"PRREAL"]\n", *from, *cnum, rpqLength(queues[2*(*cnum)+(*from)]), max); */ } else { /* the partitioning does not violate balancing constraints, in which case select a queue based on cut criteria */ for (part=0; part<2; part++) { for (i=0; i 0 && (*from == -1 || rpqSeeTopKey(queues[2*i+part]) > max)) { max = rpqSeeTopKey(queues[2*i+part]); *from = part; *cnum = i; } } } /* printf("Selected2 %"PRIDX"(%"PRIDX") -> %"PRIDX"\n", *from, *cnum, rpqLength(queues[2*(*cnum)+(*from)]), max); */ } } /*************************************************************************/ /*! Prints statistics about the refinement */ /*************************************************************************/ void Print2WayRefineStats(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, real_t deltabal, idx_t mincutorder) { int i; if (mincutorder == -2) { printf("Parts: "); printf("Nv-Nb[%5"PRIDX" %5"PRIDX"] ICut: %6"PRIDX, graph->nvtxs, graph->nbnd, graph->mincut); printf(" ["); for (i=0; incon; i++) printf("(%.3"PRREAL" %.3"PRREAL" T:%.3"PRREAL" %.3"PRREAL")", graph->pwgts[i]*graph->invtvwgt[i], graph->pwgts[graph->ncon+i]*graph->invtvwgt[i], ntpwgts[i], ntpwgts[graph->ncon+i]); printf("] LB: %.3"PRREAL"(%+.3"PRREAL")\n", ComputeLoadImbalance(graph, 2, ctrl->pijbm), deltabal); } else { printf("\tMincut: %6"PRIDX" at %5"PRIDX" NBND %6"PRIDX" NPwgts: [", graph->mincut, mincutorder, graph->nbnd); for (i=0; incon; i++) printf("(%.3"PRREAL" %.3"PRREAL")", graph->pwgts[i]*graph->invtvwgt[i], graph->pwgts[graph->ncon+i]*graph->invtvwgt[i]); printf("] LB: %.3"PRREAL"(%+.3"PRREAL")\n", ComputeLoadImbalance(graph, 2, ctrl->pijbm), deltabal); } } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/checkgraph.c0000644000175100001440000001731214552244506025415 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * checkgraph.c * * This file contains routines related to I/O * * Started 8/28/94 * George * */ #include "metislib.h" /*************************************************************************/ /*! This function checks if a graph is valid. A valid graph must satisfy the following constraints: - It should contain no self-edges. - It should be undirected; i.e., (u,v) and (v,u) should be present. - The adjacency list should not contain multiple edges to the same other vertex. \param graph is the graph to be checked, whose numbering starts from 0. \param numflag is 0 if error reporting will be done using 0 as the numbering, or 1 if the reporting should be done using 1. \param verbose is 1 the identified errors will be displayed, or 0, if it should run silently. */ /*************************************************************************/ int CheckGraph(graph_t *graph, int numflag, int verbose) { idx_t i, j, k, l; idx_t nvtxs, err=0; idx_t minedge, maxedge, minewgt, maxewgt; idx_t *xadj, *adjncy, *adjwgt, *htable; numflag = (numflag == 0 ? 0 : 1); /* make sure that numflag is 0 or 1 */ nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; ASSERT(adjwgt != NULL); htable = ismalloc(nvtxs, 0, "htable"); minedge = maxedge = adjncy[0]; minewgt = maxewgt = adjwgt[0]; for (i=0; i maxedge) ? k : maxedge; minewgt = (adjwgt[j] < minewgt) ? adjwgt[j] : minewgt; maxewgt = (adjwgt[j] > maxewgt) ? adjwgt[j] : maxewgt; if (i == k) { if (verbose) printf("Vertex %"PRIDX" contains a self-loop " "(i.e., diagonal entry in the matrix)!\n", i+numflag); err++; } else { for (l=xadj[k]; l 0 && verbose) { printf("A total of %"PRIDX" errors exist in the input file. " "Correct them, and run again!\n", err); } gk_free((void **)&htable, LTERM); return (err == 0 ? 1 : 0); } /*************************************************************************/ /*! This function performs a quick check of the weights of the graph */ /*************************************************************************/ int CheckInputGraphWeights(idx_t nvtxs, idx_t ncon, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt) { idx_t i; if (ncon <= 0) { printf("Input Error: ncon must be >= 1.\n"); return 0; } if (vwgt) { for (i=ncon*nvtxs; i>=0; i--) { if (vwgt[i] < 0) { printf("Input Error: negative vertex weight(s).\n"); return 0; } } } if (vsize) { for (i=nvtxs; i>=0; i--) { if (vsize[i] < 0) { printf("Input Error: negative vertex sizes(s).\n"); return 0; } } } if (adjwgt) { for (i=xadj[nvtxs]-1; i>=0; i--) { if (adjwgt[i] < 0) { printf("Input Error: non-positive edge weight(s).\n"); return 0; } } } return 1; } /*************************************************************************/ /*! This function creates a graph whose topology is consistent with Metis' requirements that: - There are no self-edges. - It is undirected; i.e., (u,v) and (v,u) should be present and of the same weight. - The adjacency list should not contain multiple edges to the same other vertex. Any of the above errors are fixed by performing the following operations: - Self-edges are removed. - The undirected graph is formed by the union of edges. - One of the duplicate edges is selected. The routine does not change the provided vertex weights. */ /*************************************************************************/ graph_t *FixGraph(graph_t *graph) { idx_t i, j, k, l, nvtxs, nedges; idx_t *xadj, *adjncy, *adjwgt; idx_t *nxadj, *nadjncy, *nadjwgt; graph_t *ngraph; uvw_t *edges; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; ASSERT(adjwgt != NULL); ngraph = CreateGraph(); ngraph->nvtxs = nvtxs; /* deal with vertex weights/sizes */ ngraph->ncon = graph->ncon; ngraph->vwgt = icopy(nvtxs*graph->ncon, graph->vwgt, imalloc(nvtxs*graph->ncon, "FixGraph: vwgt")); ngraph->vsize = ismalloc(nvtxs, 1, "FixGraph: vsize"); if (graph->vsize) icopy(nvtxs, graph->vsize, ngraph->vsize); /* fix graph by sorting the "superset" of edges */ edges = (uvw_t *)gk_malloc(sizeof(uvw_t)*2*xadj[nvtxs], "FixGraph: edges"); for (nedges=0, i=0; i adjncy[j]) { edges[nedges].u = adjncy[j]; edges[nedges].v = i; edges[nedges].w = adjwgt[j]; nedges++; } } } uvwsorti(nedges, edges); /* keep the unique subset */ for (k=0, i=1; ixadj = ismalloc(nvtxs+1, 0, "FixGraph: nxadj"); nadjncy = ngraph->adjncy = imalloc(2*nedges, "FixGraph: nadjncy"); nadjwgt = ngraph->adjwgt = imalloc(2*nedges, "FixGraph: nadjwgt"); /* create the adjacency list of the fixed graph from the upper-triangular part of the adjacency matrix */ for (k=0; ked += myrinfo->id-mynbrs[k].ed; \ SWAP(myrinfo->id, mynbrs[k].ed, j); \ if (mynbrs[k].ed == 0) \ mynbrs[k] = mynbrs[--myrinfo->nnbrs]; \ else \ mynbrs[k].pid = from; \ \ /* Update the boundary information. Both deletion and addition is \ allowed as this routine can be used for moving arbitrary nodes. */ \ if (bndtype == BNDTYPE_REFINE) { \ if (bndptr[i] != -1 && myrinfo->ed - myrinfo->id < 0) \ BNDDelete(nbnd, bndind, bndptr, i); \ if (bndptr[i] == -1 && myrinfo->ed - myrinfo->id >= 0) \ BNDInsert(nbnd, bndind, bndptr, i); \ } \ else { \ if (bndptr[i] != -1 && myrinfo->ed <= 0) \ BNDDelete(nbnd, bndind, bndptr, i); \ if (bndptr[i] == -1 && myrinfo->ed > 0) \ BNDInsert(nbnd, bndind, bndptr, i); \ } \ } while(0) #define UpdateAdjacentVertexInfoAndBND(ctrl, vid, adjlen, me, from, to, \ myrinfo, ewgt, nbnd, bndptr, bndind, bndtype) \ do { \ idx_t k; \ cnbr_t *mynbrs; \ \ if (myrinfo->inbr == -1) { \ myrinfo->inbr = cnbrpoolGetNext(ctrl, adjlen+1); \ myrinfo->nnbrs = 0; \ } \ ASSERT(CheckRInfo(ctrl, myrinfo)); \ \ mynbrs = ctrl->cnbrpool + myrinfo->inbr; \ \ /* Update global ID/ED and boundary */ \ if (me == from) { \ INC_DEC(myrinfo->ed, myrinfo->id, (ewgt)); \ if (bndtype == BNDTYPE_REFINE) { \ if (myrinfo->ed-myrinfo->id >= 0 && bndptr[(vid)] == -1) \ BNDInsert(nbnd, bndind, bndptr, (vid)); \ } \ else { \ if (myrinfo->ed > 0 && bndptr[(vid)] == -1) \ BNDInsert(nbnd, bndind, bndptr, (vid)); \ } \ } \ else if (me == to) { \ INC_DEC(myrinfo->id, myrinfo->ed, (ewgt)); \ if (bndtype == BNDTYPE_REFINE) { \ if (myrinfo->ed-myrinfo->id < 0 && bndptr[(vid)] != -1) \ BNDDelete(nbnd, bndind, bndptr, (vid)); \ } \ else { \ if (myrinfo->ed <= 0 && bndptr[(vid)] != -1) \ BNDDelete(nbnd, bndind, bndptr, (vid)); \ } \ } \ \ /* Remove contribution from the .ed of 'from' */ \ if (me != from) { \ for (k=0; knnbrs; k++) { \ if (mynbrs[k].pid == from) { \ if (mynbrs[k].ed == (ewgt)) \ mynbrs[k] = mynbrs[--myrinfo->nnbrs]; \ else \ mynbrs[k].ed -= (ewgt); \ break; \ } \ } \ } \ \ /* Add contribution to the .ed of 'to' */ \ if (me != to) { \ for (k=0; knnbrs; k++) { \ if (mynbrs[k].pid == to) { \ mynbrs[k].ed += (ewgt); \ break; \ } \ } \ if (k == myrinfo->nnbrs) { \ mynbrs[k].pid = to; \ mynbrs[k].ed = (ewgt); \ myrinfo->nnbrs++; \ } \ } \ \ ASSERT(CheckRInfo(ctrl, myrinfo));\ } while(0) #define UpdateQueueInfo(queue, vstatus, vid, me, from, to, myrinfo, oldnnbrs, \ nupd, updptr, updind, bndtype) \ do { \ real_t rgain; \ \ if (me == to || me == from || oldnnbrs != myrinfo->nnbrs) { \ rgain = (myrinfo->nnbrs > 0 ? \ 1.0*myrinfo->ed/sqrt(myrinfo->nnbrs) : 0.0) - myrinfo->id; \ \ if (bndtype == BNDTYPE_REFINE) { \ if (vstatus[(vid)] == VPQSTATUS_PRESENT) { \ if (myrinfo->ed-myrinfo->id >= 0) \ rpqUpdate(queue, (vid), rgain); \ else { \ rpqDelete(queue, (vid)); \ vstatus[(vid)] = VPQSTATUS_NOTPRESENT; \ ListDelete(nupd, updind, updptr, (vid)); \ } \ } \ else if (vstatus[(vid)] == VPQSTATUS_NOTPRESENT && myrinfo->ed-myrinfo->id >= 0) { \ rpqInsert(queue, (vid), rgain); \ vstatus[(vid)] = VPQSTATUS_PRESENT; \ ListInsert(nupd, updind, updptr, (vid)); \ } \ } \ else { \ if (vstatus[(vid)] == VPQSTATUS_PRESENT) { \ if (myrinfo->ed > 0) \ rpqUpdate(queue, (vid), rgain); \ else { \ rpqDelete(queue, (vid)); \ vstatus[(vid)] = VPQSTATUS_NOTPRESENT; \ ListDelete(nupd, updind, updptr, (vid)); \ } \ } \ else if (vstatus[(vid)] == VPQSTATUS_NOTPRESENT && myrinfo->ed > 0) { \ rpqInsert(queue, (vid), rgain); \ vstatus[(vid)] = VPQSTATUS_PRESENT; \ ListInsert(nupd, updind, updptr, (vid)); \ } \ } \ } \ } while(0) /*************************************************************************/ /*! This macro determines the set of subdomains that a vertex can move to without increasins the maxndoms. */ /*************************************************************************/ #define SelectSafeTargetSubdomains(myrinfo, mynbrs, nads, adids, maxndoms, safetos, vtmp) \ do { \ idx_t j, k, l, nadd, to; \ for (j=0; jnnbrs; j++) { \ safetos[to = mynbrs[j].pid] = 0; \ \ /* uncompress the connectivity info for the 'to' subdomain */ \ for (k=0; knnbrs; k++) { \ if (k == j) \ continue; \ \ l = mynbrs[k].pid; \ if (vtmp[l] == 0) { \ if (nads[l] > maxndoms-1) { \ nadd = maxndoms; \ break; \ } \ nadd++; \ } \ } \ if (nads[to]+nadd <= maxndoms) \ safetos[to] = 1; \ if (nadd == 0) \ safetos[to] = 2; \ \ /* cleanup the connectivity info due to the 'to' subdomain */ \ for (k=0; knvtxs; where = graph->where; nparts = ctrl->nparts; vadids = ctrl->pvec1; vadwgts = iset(nparts, 0, ctrl->pvec2); pptr = iwspacemalloc(ctrl, nparts+1); pind = iwspacemalloc(ctrl, nvtxs); iarray2csr(nvtxs, nparts, where, pptr, pind); for (pid=0; pidobjtype) { case METIS_OBJTYPE_CUT: { ckrinfo_t *rinfo; cnbr_t *nbrs; rinfo = graph->ckrinfo; for (nads=0, ii=pptr[pid]; ii 0) { nnbrs = rinfo[i].nnbrs; nbrs = ctrl->cnbrpool + rinfo[i].inbr; for (j=0; jvkrinfo; for (nads=0, ii=pptr[pid]; ii 0) { nnbrs = rinfo[i].nnbrs; nbrs = ctrl->vnbrpool + rinfo[i].inbr; for (j=0; jobjtype); } /* See if you have enough memory to store the adjacent info for that subdomain */ if (ctrl->maxnads[pid] < nads) { ctrl->maxnads[pid] = 2*nads; ctrl->adids[pid] = irealloc(ctrl->adids[pid], ctrl->maxnads[pid], "ComputeSubDomainGraph: adids[pid]"); ctrl->adwgts[pid] = irealloc(ctrl->adwgts[pid], ctrl->maxnads[pid], "ComputeSubDomainGraph: adids[pid]"); } ctrl->nads[pid] = nads; for (j=0; jadids[pid][j] = vadids[j]; ctrl->adwgts[pid][j] = vadwgts[vadids[j]]; vadwgts[vadids[j]] = 0; } } WCOREPOP; } /*************************************************************************/ /*! This function updates the weight of an edge in the subdomain graph by adding to it the value of ewgt. The update can either increase or decrease the weight of the subdomain edge based on the value of ewgt. \param u is the ID of one of the incident subdomains to the edge \param v is the ID of the other incident subdomains to the edge \param ewgt is the weight to be added to the subdomain edge \param nparts is the number of subdomains \param r_maxndoms is the maximum number of adjacent subdomains and is updated as necessary. The update is skipped if a NULL value is supplied. */ /*************************************************************************/ void UpdateEdgeSubDomainGraph(ctrl_t *ctrl, idx_t u, idx_t v, idx_t ewgt, idx_t *r_maxndoms) { idx_t i, j, nads; if (ewgt == 0) return; for (i=0; i<2; i++) { nads = ctrl->nads[u]; /* Find the edge */ for (j=0; jadids[u][j] == v) { ctrl->adwgts[u][j] += ewgt; break; } } if (j == nads) { /* Deal with the case in which the edge was not found */ ASSERT(ewgt > 0); if (ctrl->maxnads[u] == nads) { ctrl->maxnads[u] = 2*(nads+1); ctrl->adids[u] = irealloc(ctrl->adids[u], ctrl->maxnads[u], "IncreaseEdgeSubDomainGraph: adids[pid]"); ctrl->adwgts[u] = irealloc(ctrl->adwgts[u], ctrl->maxnads[u], "IncreaseEdgeSubDomainGraph: adids[pid]"); } ctrl->adids[u][nads] = v; ctrl->adwgts[u][nads] = ewgt; nads++; if (r_maxndoms != NULL && nads > *r_maxndoms) { printf("You just increased the maxndoms: %"PRIDX" %"PRIDX"\n", nads, *r_maxndoms); *r_maxndoms = nads; } } else { /* See if the updated edge becomes 0 */ ASSERT(ctrl->adwgts[u][j] >= 0); if (ctrl->adwgts[u][j] == 0) { ctrl->adids[u][j] = ctrl->adids[u][nads-1]; ctrl->adwgts[u][j] = ctrl->adwgts[u][nads-1]; nads--; if (r_maxndoms != NULL && nads+1 == *r_maxndoms) *r_maxndoms = ctrl->nads[iargmax(ctrl->nparts, ctrl->nads)]; } } ctrl->nads[u] = nads; SWAP(u, v, j); } } /*************************************************************************/ /*! This function computes the subdomain graph */ /*************************************************************************/ void EliminateSubDomainEdges(ctrl_t *ctrl, graph_t *graph) { idx_t i, ii, j, k, ncon, nparts, scheme, pid_from, pid_to, me, other, nvtxs, total, max, avg, totalout, nind=0, ncand=0, ncand2, target, target2, nadd, bestnadd=0; idx_t min, move, *cpwgt; idx_t *xadj, *adjncy, *vwgt, *adjwgt, *pwgts, *where, *maxpwgt, *mypmat, *otherpmat, *kpmat, *ind; idx_t *nads, **adids, **adwgts; ikv_t *cand, *cand2; ipq_t queue; real_t *tpwgts, badfactor=1.4; idx_t *pptr, *pind; idx_t *vmarker=NULL, *pmarker=NULL, *modind=NULL; /* volume specific work arrays */ WCOREPUSH; nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; adjncy = graph->adjncy; vwgt = graph->vwgt; adjwgt = (ctrl->objtype == METIS_OBJTYPE_VOL ? NULL : graph->adjwgt); where = graph->where; pwgts = graph->pwgts; /* We assume that this is properly initialized */ nparts = ctrl->nparts; tpwgts = ctrl->tpwgts; cpwgt = iwspacemalloc(ctrl, ncon); maxpwgt = iwspacemalloc(ctrl, nparts*ncon); ind = iwspacemalloc(ctrl, nvtxs); otherpmat = iset(nparts, 0, iwspacemalloc(ctrl, nparts)); cand = ikvwspacemalloc(ctrl, nparts); cand2 = ikvwspacemalloc(ctrl, nparts); pptr = iwspacemalloc(ctrl, nparts+1); pind = iwspacemalloc(ctrl, nvtxs); iarray2csr(nvtxs, nparts, where, pptr, pind); if (ctrl->objtype == METIS_OBJTYPE_VOL) { /* Vol-refinement specific working arrays */ modind = iwspacemalloc(ctrl, nvtxs); vmarker = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs)); pmarker = iset(nparts, -1, iwspacemalloc(ctrl, nparts)); } /* Compute the pmat matrix and ndoms */ ComputeSubDomainGraph(ctrl, graph); nads = ctrl->nads; adids = ctrl->adids; adwgts = ctrl->adwgts; mypmat = iset(nparts, 0, ctrl->pvec1); kpmat = iset(nparts, 0, ctrl->pvec2); /* Compute the maximum allowed weight for each domain */ for (i=0; itvwgt[j]*ctrl->ubfactors[j]; } ipqInit(&queue, nparts); /* Get into the loop eliminating subdomain connections */ while (1) { total = isum(nparts, nads, 1); avg = total/nparts; max = nads[iargmax(nparts, nads)]; #ifndef NDEBUG IFSET(ctrl->dbglvl, METIS_DBG_CONNINFO, printf("Adjacent Subdomain Stats: Total: %3"PRIDX", " "Max: %3"PRIDX"[%zu], Avg: %3"PRIDX"\n", total, max, iargmax(nparts, nads), avg)); #endif if (max < badfactor*avg) break; /* Add the subdomains that you will try to reduce their connectivity */ ipqReset(&queue); for (i=0; i= avg + (max-avg)/2) ipqInsert(&queue, i, nads[i]); } move = 0; while ((me = ipqGetTop(&queue)) != -1) { totalout = isum(nads[me], adwgts[me], 1); for (ncand2=0, i=0; idbglvl, METIS_DBG_CONNINFO, printf("Me: %"PRIDX", Degree: %4"PRIDX", TotalOut: %"PRIDX",\n", me, nads[me], totalout)); /* Sort the connections according to their cut */ ikvsorti(ncand2, cand2); /* Two schemes are used for eliminating subdomain edges. The first, tries to eliminate subdomain edges by moving remote groups of vertices to subdomains that 'me' is already connected to. The second, tries to eliminate subdomain edges by moving entire sets of my vertices that connect to the 'other' subdomain to a subdomain that I'm already connected to. These two schemes are applied in sequence. */ target = target2 = -1; for (scheme=0; scheme<2; scheme++) { for (min=0; min 0); } ikvsortd(ncand, cand); IFSET(ctrl->dbglvl, METIS_DBG_CONNINFO, printf("\tMinOut: %4"PRIDX", to: %3"PRIDX", TtlWgt: %5"PRIDX"[#:%"PRIDX"]\n", mypmat[other], other, isum(ncon, cpwgt, 1), nind)); /* Go through and select the first domain that is common with 'me', and does not increase the nads[target] higher than nads[me], subject to the maxpwgt constraint. Traversal is done from the mostly connected to the least. */ for (i=0; i 0) { /* Check if balance will go off */ if (!ivecaxpylez(ncon, 1, cpwgt, pwgts+k*ncon, maxpwgt+k*ncon)) continue; /* get a dense vector out of k's connectivity */ for (j=0; j 0 && kpmat[j] == 0 && nads[j]+1 >= nads[me]) break; } /* There were no bad second level effects. See if you can find a subdomain to move to. */ if (j == nparts) { for (nadd=0, j=0; j 0 && kpmat[j] == 0) nadd++; } IFSET(ctrl->dbglvl, METIS_DBG_CONNINFO, printf("\t\tto=%"PRIDX", nadd=%"PRIDX", %"PRIDX"\n", k, nadd, nads[k])); if (nads[k]+nadd < nads[me]) { if (target2 == -1 || nads[target2]+bestnadd > nads[k]+nadd || (nads[target2]+bestnadd == nads[k]+nadd && bestnadd > nadd)) { target2 = k; bestnadd = nadd; } } if (nadd == 0) target = k; } /* reset kpmat for the next iteration */ for (j=0; jdbglvl, METIS_DBG_CONNINFO, printf("\t\tScheme: %"PRIDX". Moving to %"PRIDX"\n", scheme, target)); move = 1; break; } } if (target != -1) break; /* A move was found. No need to try the other scheme */ } /* reset the mypmat for next iteration */ for (i=0; iobjtype) { case METIS_OBJTYPE_CUT: MoveGroupMinConnForCut(ctrl, graph, target, nind, ind); break; case METIS_OBJTYPE_VOL: MoveGroupMinConnForVol(ctrl, graph, target, nind, ind, vmarker, pmarker, modind); break; default: gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype); } /* Update the csr representation of the partitioning vector */ iarray2csr(nvtxs, nparts, where, pptr, pind); } } if (move == 0) break; } ipqFree(&queue); WCOREPOP; } /*************************************************************************/ /*! This function moves a collection of vertices and updates their rinfo */ /*************************************************************************/ void MoveGroupMinConnForCut(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t nind, idx_t *ind) { idx_t i, ii, j, k, nbnd, from, me; idx_t *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind; ckrinfo_t *myrinfo; cnbr_t *mynbrs; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; bndptr = graph->bndptr; bndind = graph->bndind; nbnd = graph->nbnd; while (--nind>=0) { i = ind[nind]; from = where[i]; myrinfo = graph->ckrinfo+i; if (myrinfo->inbr == -1) { myrinfo->inbr = cnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1); myrinfo->nnbrs = 0; } mynbrs = ctrl->cnbrpool + myrinfo->inbr; /* find the location of 'to' in myrinfo or create it if it is not there */ for (k=0; knnbrs; k++) { if (mynbrs[k].pid == to) break; } if (k == myrinfo->nnbrs) { ASSERT(k < xadj[i+1]-xadj[i]); mynbrs[k].pid = to; mynbrs[k].ed = 0; myrinfo->nnbrs++; } /* Update pwgts */ iaxpy(graph->ncon, 1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+to*graph->ncon, 1); iaxpy(graph->ncon, -1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+from*graph->ncon, 1); /* Update mincut */ graph->mincut -= mynbrs[k].ed-myrinfo->id; /* Update subdomain connectivity graph to reflect the move of 'i' */ UpdateEdgeSubDomainGraph(ctrl, from, to, myrinfo->id-mynbrs[k].ed, NULL); /* Update ID/ED and BND related information for the moved vertex */ UpdateMovedVertexInfoAndBND(i, from, k, to, myrinfo, mynbrs, where, nbnd, bndptr, bndind, BNDTYPE_REFINE); /* Update the degrees of adjacent vertices */ for (j=xadj[i]; jckrinfo+ii; UpdateAdjacentVertexInfoAndBND(ctrl, ii, xadj[ii+1]-xadj[ii], me, from, to, myrinfo, adjwgt[j], nbnd, bndptr, bndind, BNDTYPE_REFINE); /* Update subdomain graph to reflect the move of 'i' for domains other than 'from' and 'to' */ if (me != from && me != to) { UpdateEdgeSubDomainGraph(ctrl, from, me, -adjwgt[j], NULL); UpdateEdgeSubDomainGraph(ctrl, to, me, adjwgt[j], NULL); } } } ASSERT(ComputeCut(graph, where) == graph->mincut); graph->nbnd = nbnd; } /*************************************************************************/ /*! This function moves a collection of vertices and updates their rinfo */ /*************************************************************************/ void MoveGroupMinConnForVol(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t nind, idx_t *ind, idx_t *vmarker, idx_t *pmarker, idx_t *modind) { idx_t i, ii, j, k, l, from, me, other, xgain, ewgt; idx_t *xadj, *vsize, *adjncy, *where; vkrinfo_t *myrinfo, *orinfo; vnbr_t *mynbrs, *onbrs; xadj = graph->xadj; vsize = graph->vsize; adjncy = graph->adjncy; where = graph->where; while (--nind>=0) { i = ind[nind]; from = where[i]; myrinfo = graph->vkrinfo+i; if (myrinfo->inbr == -1) { myrinfo->inbr = vnbrpoolGetNext(ctrl, xadj[i+1]-xadj[i]+1); myrinfo->nnbrs = 0; } mynbrs = ctrl->vnbrpool + myrinfo->inbr; xgain = (myrinfo->nid == 0 && myrinfo->ned > 0 ? vsize[i] : 0); //printf("Moving %"PRIDX" from %"PRIDX" to %"PRIDX" [vsize: %"PRIDX"] [xgain: %"PRIDX"]\n", // i, from, to, vsize[i], xgain); /* find the location of 'to' in myrinfo or create it if it is not there */ for (k=0; knnbrs; k++) { if (mynbrs[k].pid == to) break; } if (k == myrinfo->nnbrs) { //printf("Missing neighbor\n"); if (myrinfo->nid > 0) xgain -= vsize[i]; /* determine the volume gain resulting from that move */ for (j=xadj[i]; jvkrinfo+ii; onbrs = ctrl->vnbrpool + orinfo->inbr; ASSERT(other != to) //printf(" %8d %8d %3d\n", (int)ii, (int)vsize[ii], (int)other); if (from == other) { /* Same subdomain vertex: Decrease the gain if 'to' is a new neighbor. */ for (l=0; lnnbrs; l++) { if (onbrs[l].pid == to) break; } if (l == orinfo->nnbrs) xgain -= vsize[ii]; } else { /* Remote vertex: increase if 'to' is a new subdomain */ for (l=0; lnnbrs; l++) { if (onbrs[l].pid == to) break; } if (l == orinfo->nnbrs) xgain -= vsize[ii]; /* Remote vertex: decrease if i is the only connection to 'from' */ for (l=0; lnnbrs; l++) { if (onbrs[l].pid == from && onbrs[l].ned == 1) { xgain += vsize[ii]; break; } } } } graph->minvol -= xgain; graph->mincut -= -myrinfo->nid; ewgt = myrinfo->nid; } else { graph->minvol -= (xgain + mynbrs[k].gv); graph->mincut -= mynbrs[k].ned-myrinfo->nid; ewgt = myrinfo->nid-mynbrs[k].ned; } /* Update where and pwgts */ where[i] = to; iaxpy(graph->ncon, 1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+to*graph->ncon, 1); iaxpy(graph->ncon, -1, graph->vwgt+i*graph->ncon, 1, graph->pwgts+from*graph->ncon, 1); /* Update subdomain connectivity graph to reflect the move of 'i' */ UpdateEdgeSubDomainGraph(ctrl, from, to, ewgt, NULL); /* Update the subdomain connectivity of the adjacent vertices */ for (j=xadj[i]; jmincut); ASSERTP(ComputeVolume(graph, where) == graph->minvol, ("%"PRIDX" %"PRIDX"\n", ComputeVolume(graph, where), graph->minvol)); } /*************************************************************************/ /*! This function computes the subdomain graph. For deubuging purposes. */ /*************************************************************************/ void PrintSubDomainGraph(graph_t *graph, idx_t nparts, idx_t *where) { idx_t i, j, k, me, nvtxs, total, max; idx_t *xadj, *adjncy, *adjwgt, *pmat; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; pmat = ismalloc(nparts*nparts, 0, "ComputeSubDomainGraph: pmat"); for (i=0; i 0) k++; } total += k; if (k > max) max = k; /* printf("%2"PRIDX" -> %2"PRIDX" ", i, k); for (j=0; j 0) printf("[%2"PRIDX" %4"PRIDX"] ", j, pmat[i*nparts+j]); } printf("\n"); */ } printf("Total adjacent subdomains: %"PRIDX", Max: %"PRIDX"\n", total, max); gk_free((void **)&pmat, LTERM); } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/defs.h0000644000175100001440000000501514552244506024241 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * defs.h * * This file contains constant definitions * * Started 8/27/94 * George * * $Id: defs.h 13933 2013-03-29 22:20:46Z karypis $ * */ #ifndef _LIBMETIS_DEFS_H_ #define _LIBMETIS_DEFS_H_ #define METISTITLE "METIS 5.0 Copyright 1998-13, Regents of the University of Minnesota\n" #define MAXLINE 1280000 #define LTERM (void **) 0 /* List terminator for gk_free() */ #define HTLENGTH ((1<<11)-1) #define INIT_MAXNAD 200 /* Initial number of maximum number of adjacent domains. This number will be adjusted as required. */ /* Types of boundaries */ #define BNDTYPE_REFINE 1 /* Used for k-way refinement-purposes */ #define BNDTYPE_BALANCE 2 /* Used for k-way balancing purposes */ /* Mode of optimization */ #define OMODE_REFINE 1 /* Optimize the objective function */ #define OMODE_BALANCE 2 /* Balance the subdomains */ /* Types of vertex statues in the priority queue */ #define VPQSTATUS_PRESENT 1 /* The vertex is in the queue */ #define VPQSTATUS_EXTRACTED 2 /* The vertex has been extracted from the queue */ #define VPQSTATUS_NOTPRESENT 3 /* The vertex is not present in the queue and has not been extracted before */ #define UNMATCHED -1 #define LARGENIPARTS 7 /* Number of random initial partitions */ #define SMALLNIPARTS 5 /* Number of random initial partitions */ #define COARSEN_FRACTION 0.85 /* Node reduction between succesive coarsening levels */ #define COMPRESSION_FRACTION 0.85 #define MMDSWITCH 120 /* Default ufactors for the various operational modes */ #define PMETIS_DEFAULT_UFACTOR 1 #define MCPMETIS_DEFAULT_UFACTOR 10 #define KMETIS_DEFAULT_UFACTOR 30 #define OMETIS_DEFAULT_UFACTOR 200 #endif Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/sfm.c0000644000175100001440000005015614552244506024106 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * sfm.c * * This file contains code that implementes an FM-based separator refinement * * Started 8/1/97 * George * * $Id: sfm.c 10874 2011-10-17 23:13:00Z karypis $ * */ #include "metislib.h" /*************************************************************************/ /*! This function performs a node-based FM refinement */ /**************************************************************************/ void FM_2WayNodeRefine2Sided(ctrl_t *ctrl, graph_t *graph, idx_t niter) { idx_t i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, nmind; idx_t *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr; idx_t *mptr, *mind, *moved, *swaps; rpq_t *queues[2]; nrinfo_t *rinfo; idx_t higain, oldgain, mincut, initcut, mincutorder; idx_t pass, to, other, limit; idx_t badmaxpwgt, mindiff, newdiff; idx_t u[2], g[2]; real_t mult; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; vwgt = graph->vwgt; bndind = graph->bndind; bndptr = graph->bndptr; where = graph->where; pwgts = graph->pwgts; rinfo = graph->nrinfo; queues[0] = rpqCreate(nvtxs); queues[1] = rpqCreate(nvtxs); moved = iwspacemalloc(ctrl, nvtxs); swaps = iwspacemalloc(ctrl, nvtxs); mptr = iwspacemalloc(ctrl, nvtxs+1); mind = iwspacemalloc(ctrl, 2*nvtxs); mult = 0.5*ctrl->ubfactors[0]; badmaxpwgt = (idx_t)(mult*(pwgts[0]+pwgts[1]+pwgts[2])); IFSET(ctrl->dbglvl, METIS_DBG_REFINE, printf("Partitions-N2: [%6"PRIDX" %6"PRIDX"] Nv-Nb[%6"PRIDX" %6"PRIDX"]. ISep: %6"PRIDX"\n", pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, graph->mincut)); for (pass=0; passmincut; nbnd = graph->nbnd; /* use the swaps array in place of the traditional perm array to save memory */ irandArrayPermute(nbnd, swaps, nbnd, 1); for (ii=0; iicompress ? gk_min(5*nbnd, 400) : gk_min(2*nbnd, 300)); /****************************************************** * Get into the FM loop *******************************************************/ mptr[0] = nmind = 0; mindiff = iabs(pwgts[0]-pwgts[1]); to = (pwgts[0] < pwgts[1] ? 0 : 1); for (nswaps=0; nswaps g[1] ? 0 : (g[0] < g[1] ? 1 : pass%2)); if (pwgts[to]+vwgt[u[to]] > badmaxpwgt) to = (to+1)%2; } else if (u[0] == -1 && u[1] == -1) { break; } else if (u[0] != -1 && pwgts[0]+vwgt[u[0]] <= badmaxpwgt) { to = 0; } else if (u[1] != -1 && pwgts[1]+vwgt[u[1]] <= badmaxpwgt) { to = 1; } else break; other = (to+1)%2; higain = rpqGetTop(queues[to]); if (moved[higain] == -1) /* Delete if it was in the separator originally */ rpqDelete(queues[other], higain); ASSERT(bndptr[higain] != -1); /* The following check is to ensure we break out if there is a posibility of over-running the mind array. */ if (nmind + xadj[higain+1]-xadj[higain] >= 2*nvtxs-1) break; pwgts[2] -= (vwgt[higain]-rinfo[higain].edegrees[other]); newdiff = iabs(pwgts[to]+vwgt[higain] - (pwgts[other]-rinfo[higain].edegrees[other])); if (pwgts[2] < mincut || (pwgts[2] == mincut && newdiff < mindiff)) { mincut = pwgts[2]; mincutorder = nswaps; mindiff = newdiff; } else { if (nswaps - mincutorder > 2*limit || (nswaps - mincutorder > limit && pwgts[2] > 1.10*mincut)) { pwgts[2] += (vwgt[higain]-rinfo[higain].edegrees[other]); break; /* No further improvement, break out */ } } BNDDelete(nbnd, bndind, bndptr, higain); pwgts[to] += vwgt[higain]; where[higain] = to; moved[higain] = nswaps; swaps[nswaps] = higain; /********************************************************** * Update the degrees of the affected nodes ***********************************************************/ for (j=xadj[higain]; jdbglvl, METIS_DBG_MOVEINFO, printf("Moved %6"PRIDX" to %3"PRIDX", Gain: %5"PRIDX" [%5"PRIDX"] [%4"PRIDX" %4"PRIDX"] \t[%5"PRIDX" %5"PRIDX" %5"PRIDX"]\n", higain, to, g[to], g[other], vwgt[u[to]], vwgt[u[other]], pwgts[0], pwgts[1], pwgts[2])); } /**************************************************************** * Roll back computation *****************************************************************/ for (nswaps--; nswaps>mincutorder; nswaps--) { higain = swaps[nswaps]; ASSERT(CheckNodePartitionParams(graph)); to = where[higain]; other = (to+1)%2; INC_DEC(pwgts[2], pwgts[to], vwgt[higain]); where[higain] = 2; BNDInsert(nbnd, bndind, bndptr, higain); edegrees = rinfo[higain].edegrees; edegrees[0] = edegrees[1] = 0; for (j=xadj[higain]; jdbglvl, METIS_DBG_REFINE, printf("\tMinimum sep: %6"PRIDX" at %5"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", mincut, mincutorder, pwgts[0], pwgts[1], nbnd)); graph->mincut = mincut; graph->nbnd = nbnd; if (mincutorder == -1 || mincut >= initcut) break; } rpqDestroy(queues[0]); rpqDestroy(queues[1]); WCOREPOP; } /*************************************************************************/ /*! This function performs a node-based FM refinement. Each refinement iteration is split into two sub-iterations. In each sub-iteration only moves to one of the left/right partitions is allowed; hence, it is one-sided. */ /**************************************************************************/ void FM_2WayNodeRefine1Sided(ctrl_t *ctrl, graph_t *graph, idx_t niter) { idx_t i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, nmind, iend; idx_t *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr; idx_t *mptr, *mind, *swaps; rpq_t *queue; nrinfo_t *rinfo; idx_t higain, mincut, initcut, mincutorder; idx_t pass, to, other, limit; idx_t badmaxpwgt, mindiff, newdiff; real_t mult; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; vwgt = graph->vwgt; bndind = graph->bndind; bndptr = graph->bndptr; where = graph->where; pwgts = graph->pwgts; rinfo = graph->nrinfo; queue = rpqCreate(nvtxs); swaps = iwspacemalloc(ctrl, nvtxs); mptr = iwspacemalloc(ctrl, nvtxs+1); mind = iwspacemalloc(ctrl, 2*nvtxs); mult = 0.5*ctrl->ubfactors[0]; badmaxpwgt = (idx_t)(mult*(pwgts[0]+pwgts[1]+pwgts[2])); IFSET(ctrl->dbglvl, METIS_DBG_REFINE, printf("Partitions-N1: [%6"PRIDX" %6"PRIDX"] Nv-Nb[%6"PRIDX" %6"PRIDX"]. ISep: %6"PRIDX"\n", pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, graph->mincut)); to = (pwgts[0] < pwgts[1] ? 1 : 0); for (pass=0; pass<2*niter; pass++) { /* the 2*niter is for the two sides */ other = to; to = (to+1)%2; rpqReset(queue); mincutorder = -1; initcut = mincut = graph->mincut; nbnd = graph->nbnd; /* use the swaps array in place of the traditional perm array to save memory */ irandArrayPermute(nbnd, swaps, nbnd, 1); for (ii=0; iicompress ? gk_min(5*nbnd, 500) : gk_min(3*nbnd, 300)); /****************************************************** * Get into the FM loop *******************************************************/ IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux3Tmr)); mptr[0] = nmind = 0; mindiff = iabs(pwgts[0]-pwgts[1]); for (nswaps=0; nswaps= 2*nvtxs-1) break; if (pwgts[to]+vwgt[higain] > badmaxpwgt) break; /* No point going any further. Balance will be bad */ pwgts[2] -= (vwgt[higain]-rinfo[higain].edegrees[other]); newdiff = iabs(pwgts[to]+vwgt[higain] - (pwgts[other]-rinfo[higain].edegrees[other])); if (pwgts[2] < mincut || (pwgts[2] == mincut && newdiff < mindiff)) { mincut = pwgts[2]; mincutorder = nswaps; mindiff = newdiff; } else { if (nswaps - mincutorder > 3*limit || (nswaps - mincutorder > limit && pwgts[2] > 1.10*mincut)) { pwgts[2] += (vwgt[higain]-rinfo[higain].edegrees[other]); break; /* No further improvement, break out */ } } BNDDelete(nbnd, bndind, bndptr, higain); pwgts[to] += vwgt[higain]; where[higain] = to; swaps[nswaps] = higain; /********************************************************** * Update the degrees of the affected nodes ***********************************************************/ IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux1Tmr)); for (j=xadj[higain]; jdbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux1Tmr)); IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, printf("Moved %6"PRIDX" to %3"PRIDX", Gain: %5"PRIDX" [%5"PRIDX"] \t[%5"PRIDX" %5"PRIDX" %5"PRIDX"] [%3"PRIDX" %2"PRIDX"]\n", higain, to, (vwgt[higain]-rinfo[higain].edegrees[other]), vwgt[higain], pwgts[0], pwgts[1], pwgts[2], nswaps, limit)); } IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux3Tmr)); /**************************************************************** * Roll back computation *****************************************************************/ IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->Aux2Tmr)); for (nswaps--; nswaps>mincutorder; nswaps--) { higain = swaps[nswaps]; ASSERT(CheckNodePartitionParams(graph)); ASSERT(where[higain] == to); INC_DEC(pwgts[2], pwgts[to], vwgt[higain]); where[higain] = 2; BNDInsert(nbnd, bndind, bndptr, higain); edegrees = rinfo[higain].edegrees; edegrees[0] = edegrees[1] = 0; for (j=xadj[higain]; jdbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->Aux2Tmr)); ASSERT(mincut == pwgts[2]); IFSET(ctrl->dbglvl, METIS_DBG_REFINE, printf("\tMinimum sep: %6"PRIDX" at %5"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", mincut, mincutorder, pwgts[0], pwgts[1], nbnd)); graph->mincut = mincut; graph->nbnd = nbnd; if (pass%2 == 1 && (mincutorder == -1 || mincut >= initcut)) break; } rpqDestroy(queue); WCOREPOP; } /*************************************************************************/ /*! This function balances the left/right partitions of a separator tri-section */ /*************************************************************************/ void FM_2WayNodeBalance(ctrl_t *ctrl, graph_t *graph) { idx_t i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, gain; idx_t badmaxpwgt, higain, oldgain, to, other; idx_t *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr; idx_t *perm, *moved; rpq_t *queue; nrinfo_t *rinfo; real_t mult; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; vwgt = graph->vwgt; bndind = graph->bndind; bndptr = graph->bndptr; where = graph->where; pwgts = graph->pwgts; rinfo = graph->nrinfo; mult = 0.5*ctrl->ubfactors[0]; badmaxpwgt = (idx_t)(mult*(pwgts[0]+pwgts[1])); if (gk_max(pwgts[0], pwgts[1]) < badmaxpwgt) return; if (iabs(pwgts[0]-pwgts[1]) < 3*graph->tvwgt[0]/nvtxs) return; WCOREPUSH; to = (pwgts[0] < pwgts[1] ? 0 : 1); other = (to+1)%2; queue = rpqCreate(nvtxs); perm = iwspacemalloc(ctrl, nvtxs); moved = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs)); IFSET(ctrl->dbglvl, METIS_DBG_REFINE, printf("Partitions: [%6"PRIDX" %6"PRIDX"] Nv-Nb[%6"PRIDX" %6"PRIDX"]. ISep: %6"PRIDX" [B]\n", pwgts[0], pwgts[1], graph->nvtxs, graph->nbnd, graph->mincut)); nbnd = graph->nbnd; irandArrayPermute(nbnd, perm, nbnd, 1); for (ii=0; ii pwgts[other]) break; /* break if balance is achieved and no +ve or zero gain */ if (gain < 0 && pwgts[other] < badmaxpwgt) break; /* skip this vertex if it will violate balance on the other side */ if (pwgts[to]+vwgt[higain] > badmaxpwgt) continue; ASSERT(bndptr[higain] != -1); pwgts[2] -= gain; BNDDelete(nbnd, bndind, bndptr, higain); pwgts[to] += vwgt[higain]; where[higain] = to; IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, printf("Moved %6"PRIDX" to %3"PRIDX", Gain: %3"PRIDX", \t[%5"PRIDX" %5"PRIDX" %5"PRIDX"]\n", higain, to, vwgt[higain]-rinfo[higain].edegrees[other], pwgts[0], pwgts[1], pwgts[2])); /********************************************************** * Update the degrees of the affected nodes ***********************************************************/ for (j=xadj[higain]; jdbglvl, METIS_DBG_REFINE, printf("\tBalanced sep: %6"PRIDX" at %4"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", pwgts[2], nswaps, pwgts[0], pwgts[1], nbnd)); graph->mincut = pwgts[2]; graph->nbnd = nbnd; rpqDestroy(queue); WCOREPOP; } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/balance.c0000644000175100001440000004110714552244506024702 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /*! \file \brief Functions for the edge-based balancing \date Started 7/23/97 \author George \author Copyright 1997-2011, Regents of the University of Minnesota \version\verbatim $Id: balance.c 10187 2011-06-13 13:46:57Z karypis $ \endverbatim */ #include "metislib.h" /************************************************************************* * This function is the entry poidx_t of the bisection balancing algorithms. **************************************************************************/ void Balance2Way(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts) { if (ComputeLoadImbalanceDiff(graph, 2, ctrl->pijbm, ctrl->ubfactors) <= 0) return; if (graph->ncon == 1) { /* return right away if the balance is OK */ if (iabs(ntpwgts[0]*graph->tvwgt[0]-graph->pwgts[0]) < 3*graph->tvwgt[0]/graph->nvtxs) return; if (graph->nbnd > 0) Bnd2WayBalance(ctrl, graph, ntpwgts); else General2WayBalance(ctrl, graph, ntpwgts); } else { McGeneral2WayBalance(ctrl, graph, ntpwgts); } } /************************************************************************* * This function balances two partitions by moving boundary nodes * from the domain that is overweight to the one that is underweight. **************************************************************************/ void Bnd2WayBalance(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts) { idx_t i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, tmp; idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *id, *ed, *bndptr, *bndind, *pwgts; idx_t *moved, *perm; rpq_t *queue; idx_t higain, mincut, mindiff; idx_t tpwgts[2]; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; id = graph->id; ed = graph->ed; pwgts = graph->pwgts; bndptr = graph->bndptr; bndind = graph->bndind; moved = iwspacemalloc(ctrl, nvtxs); perm = iwspacemalloc(ctrl, nvtxs); /* Determine from which domain you will be moving data */ tpwgts[0] = graph->tvwgt[0]*ntpwgts[0]; tpwgts[1] = graph->tvwgt[0] - tpwgts[0]; mindiff = iabs(tpwgts[0]-pwgts[0]); from = (pwgts[0] < tpwgts[0] ? 1 : 0); to = (from+1)%2; IFSET(ctrl->dbglvl, METIS_DBG_REFINE, printf("Partitions: [%6"PRIDX" %6"PRIDX"] T[%6"PRIDX" %6"PRIDX"], Nv-Nb[%6"PRIDX" %6"PRIDX"]. ICut: %6"PRIDX" [B]\n", pwgts[0], pwgts[1], tpwgts[0], tpwgts[1], graph->nvtxs, graph->nbnd, graph->mincut)); queue = rpqCreate(nvtxs); iset(nvtxs, -1, moved); ASSERT(ComputeCut(graph, where) == graph->mincut); ASSERT(CheckBnd(graph)); /* Insert the boundary nodes of the proper partition whose size is OK in the priority queue */ nbnd = graph->nbnd; irandArrayPermute(nbnd, perm, nbnd/5, 1); for (ii=0; ii 0 || id[bndind[i]] == 0); ASSERT(bndptr[bndind[i]] != -1); if (where[bndind[i]] == from && vwgt[bndind[i]] <= mindiff) rpqInsert(queue, bndind[i], ed[bndind[i]]-id[bndind[i]]); } mincut = graph->mincut; for (nswaps=0; nswaps tpwgts[to]) break; mincut -= (ed[higain]-id[higain]); INC_DEC(pwgts[to], pwgts[from], vwgt[higain]); where[higain] = to; moved[higain] = nswaps; IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, printf("Moved %6"PRIDX" from %"PRIDX". [%3"PRIDX" %3"PRIDX"] %5"PRIDX" [%4"PRIDX" %4"PRIDX"]\n", higain, from, ed[higain]-id[higain], vwgt[higain], mincut, pwgts[0], pwgts[1])); /************************************************************** * Update the id[i]/ed[i] values of the affected nodes ***************************************************************/ SWAP(id[higain], ed[higain], tmp); if (ed[higain] == 0 && xadj[higain] < xadj[higain+1]) BNDDelete(nbnd, bndind, bndptr, higain); for (j=xadj[higain]; j 0) { /* It will now become a boundary vertex */ BNDInsert(nbnd, bndind, bndptr, k); if (moved[k] == -1 && where[k] == from && vwgt[k] <= mindiff) rpqInsert(queue, k, ed[k]-id[k]); } } } } IFSET(ctrl->dbglvl, METIS_DBG_REFINE, printf("\tMinimum cut: %6"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", mincut, pwgts[0], pwgts[1], nbnd)); graph->mincut = mincut; graph->nbnd = nbnd; rpqDestroy(queue); WCOREPOP; } /************************************************************************* * This function balances two partitions by moving the highest gain * (including negative gain) vertices to the other domain. * It is used only when tha unbalance is due to non contigous * subdomains. That is, the are no boundary vertices. * It moves vertices from the domain that is overweight to the one that * is underweight. **************************************************************************/ void General2WayBalance(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts) { idx_t i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, tmp; idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *id, *ed, *bndptr, *bndind, *pwgts; idx_t *moved, *perm; rpq_t *queue; idx_t higain, mincut, mindiff; idx_t tpwgts[2]; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; id = graph->id; ed = graph->ed; pwgts = graph->pwgts; bndptr = graph->bndptr; bndind = graph->bndind; moved = iwspacemalloc(ctrl, nvtxs); perm = iwspacemalloc(ctrl, nvtxs); /* Determine from which domain you will be moving data */ tpwgts[0] = graph->tvwgt[0]*ntpwgts[0]; tpwgts[1] = graph->tvwgt[0] - tpwgts[0]; mindiff = iabs(tpwgts[0]-pwgts[0]); from = (pwgts[0] < tpwgts[0] ? 1 : 0); to = (from+1)%2; IFSET(ctrl->dbglvl, METIS_DBG_REFINE, printf("Partitions: [%6"PRIDX" %6"PRIDX"] T[%6"PRIDX" %6"PRIDX"], Nv-Nb[%6"PRIDX" %6"PRIDX"]. ICut: %6"PRIDX" [B]\n", pwgts[0], pwgts[1], tpwgts[0], tpwgts[1], graph->nvtxs, graph->nbnd, graph->mincut)); queue = rpqCreate(nvtxs); iset(nvtxs, -1, moved); ASSERT(ComputeCut(graph, where) == graph->mincut); ASSERT(CheckBnd(graph)); /* Insert the nodes of the proper partition whose size is OK in the priority queue */ irandArrayPermute(nvtxs, perm, nvtxs/5, 1); for (ii=0; iimincut; nbnd = graph->nbnd; for (nswaps=0; nswaps tpwgts[to]) break; mincut -= (ed[higain]-id[higain]); INC_DEC(pwgts[to], pwgts[from], vwgt[higain]); where[higain] = to; moved[higain] = nswaps; IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, printf("Moved %6"PRIDX" from %"PRIDX". [%3"PRIDX" %3"PRIDX"] %5"PRIDX" [%4"PRIDX" %4"PRIDX"]\n", higain, from, ed[higain]-id[higain], vwgt[higain], mincut, pwgts[0], pwgts[1])); /************************************************************** * Update the id[i]/ed[i] values of the affected nodes ***************************************************************/ SWAP(id[higain], ed[higain], tmp); if (ed[higain] == 0 && bndptr[higain] != -1 && xadj[higain] < xadj[higain+1]) BNDDelete(nbnd, bndind, bndptr, higain); if (ed[higain] > 0 && bndptr[higain] == -1) BNDInsert(nbnd, bndind, bndptr, higain); for (j=xadj[higain]; j 0 && bndptr[k] == -1) BNDInsert(nbnd, bndind, bndptr, k); } } IFSET(ctrl->dbglvl, METIS_DBG_REFINE, printf("\tMinimum cut: %6"PRIDX", PWGTS: [%6"PRIDX" %6"PRIDX"], NBND: %6"PRIDX"\n", mincut, pwgts[0], pwgts[1], nbnd)); graph->mincut = mincut; graph->nbnd = nbnd; rpqDestroy(queue); WCOREPOP; } /************************************************************************* * This function performs an edge-based FM refinement **************************************************************************/ void McGeneral2WayBalance(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts) { idx_t i, ii, j, k, l, kwgt, nvtxs, ncon, nbnd, nswaps, from, to, limit, tmp, cnum; idx_t *xadj, *adjncy, *vwgt, *adjwgt, *where, *pwgts, *id, *ed, *bndptr, *bndind; idx_t *moved, *swaps, *perm, *qnum, *qsizes; idx_t higain, mincut, newcut, mincutorder; real_t *invtvwgt, *minbalv, *newbalv, minbal, newbal; rpq_t **queues; WCOREPUSH; nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; invtvwgt = graph->invtvwgt; where = graph->where; id = graph->id; ed = graph->ed; pwgts = graph->pwgts; bndptr = graph->bndptr; bndind = graph->bndind; moved = iwspacemalloc(ctrl, nvtxs); swaps = iwspacemalloc(ctrl, nvtxs); perm = iwspacemalloc(ctrl, nvtxs); qnum = iwspacemalloc(ctrl, nvtxs); newbalv = rwspacemalloc(ctrl, ncon); minbalv = rwspacemalloc(ctrl, ncon); qsizes = iwspacemalloc(ctrl, 2*ncon); limit = gk_min(gk_max(0.01*nvtxs, 15), 100); /* Initialize the queues */ queues = (rpq_t **)wspacemalloc(ctrl, 2*ncon*sizeof(rpq_t *)); for (i=0; i<2*ncon; i++) { queues[i] = rpqCreate(nvtxs); qsizes[i] = 0; } for (i=0; i qsizes[2*j+from] && vwgt[i*ncon+qnum[i]]*invtvwgt[qnum[i]] < 1.3*vwgt[i*ncon+j]*invtvwgt[j]) { qsizes[2*qnum[i]+from]--; qsizes[2*j+from]++; qnum[i] = j; } } } } } minbal = ComputeLoadImbalanceDiffVec(graph, 2, ctrl->pijbm, ctrl->ubfactors, minbalv); ASSERT(minbal > 0.0); newcut = mincut = graph->mincut; mincutorder = -1; if (ctrl->dbglvl&METIS_DBG_REFINE) { printf("Parts: ["); for (l=0; lnvtxs, graph->nbnd, graph->mincut, minbal); } iset(nvtxs, -1, moved); ASSERT(ComputeCut(graph, where) == graph->mincut); ASSERT(CheckBnd(graph)); /* Insert all nodes in the priority queues */ nbnd = graph->nbnd; irandArrayPermute(nvtxs, perm, nvtxs/10, 1); for (ii=0; iipijbm, ctrl->ubfactors, queues, &from, &cnum); to = (from+1)%2; if (from == -1 || (higain = rpqGetTop(queues[2*cnum+from])) == -1) break; newcut -= (ed[higain]-id[higain]); iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1); iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+from*ncon, 1); newbal = ComputeLoadImbalanceDiffVec(graph, 2, ctrl->pijbm, ctrl->ubfactors, newbalv); if (newbal < minbal || (newbal == minbal && (newcut < mincut || (newcut == mincut && BetterBalance2Way(ncon, minbalv, newbalv))))) { mincut = newcut; minbal = newbal; mincutorder = nswaps; rcopy(ncon, newbalv, minbalv); } else if (nswaps-mincutorder > limit) { /* We hit the limit, undo last move */ newcut += (ed[higain]-id[higain]); iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+from*ncon, 1); iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1); break; } where[higain] = to; moved[higain] = nswaps; swaps[nswaps] = higain; if (ctrl->dbglvl&METIS_DBG_MOVEINFO) { printf("Moved %6"PRIDX" from %"PRIDX"(%"PRIDX"). Gain: %5"PRIDX", " "Cut: %5"PRIDX", NPwgts: ", higain, from, cnum, ed[higain]-id[higain], newcut); for (l=0; l 0 && bndptr[higain] == -1) BNDInsert(nbnd, bndind, bndptr, higain); for (j=xadj[higain]; j 0 && bndptr[k] == -1) BNDInsert(nbnd, bndind, bndptr, k); } } /**************************************************************** * Roll back computations *****************************************************************/ for (nswaps--; nswaps>mincutorder; nswaps--) { higain = swaps[nswaps]; to = where[higain] = (where[higain]+1)%2; SWAP(id[higain], ed[higain], tmp); if (ed[higain] == 0 && bndptr[higain] != -1 && xadj[higain] < xadj[higain+1]) BNDDelete(nbnd, bndind, bndptr, higain); else if (ed[higain] > 0 && bndptr[higain] == -1) BNDInsert(nbnd, bndind, bndptr, higain); iaxpy(ncon, 1, vwgt+higain*ncon, 1, pwgts+to*ncon, 1); iaxpy(ncon, -1, vwgt+higain*ncon, 1, pwgts+((to+1)%2)*ncon, 1); for (j=xadj[higain]; j 0) BNDInsert(nbnd, bndind, bndptr, k); } } if (ctrl->dbglvl&METIS_DBG_REFINE) { printf("\tMincut: %6"PRIDX" at %5"PRIDX", NBND: %6"PRIDX", NPwgts: [", mincut, mincutorder, nbnd); for (l=0; lpijbm)); } graph->mincut = mincut; graph->nbnd = nbnd; for (i=0; i<2*ncon; i++) rpqDestroy(queues[i]); WCOREPOP; } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/timing.c0000644000175100001440000000553614552244506024612 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * timing.c * * This file contains routines that deal with timing Metis * * Started 7/24/97 * George * * $Id: timing.c 13936 2013-03-30 03:59:09Z karypis $ * */ #include "metislib.h" /************************************************************************* * This function clears the timers **************************************************************************/ void InitTimers(ctrl_t *ctrl) { gk_clearcputimer(ctrl->TotalTmr); gk_clearcputimer(ctrl->InitPartTmr); gk_clearcputimer(ctrl->MatchTmr); gk_clearcputimer(ctrl->ContractTmr); gk_clearcputimer(ctrl->CoarsenTmr); gk_clearcputimer(ctrl->UncoarsenTmr); gk_clearcputimer(ctrl->RefTmr); gk_clearcputimer(ctrl->ProjectTmr); gk_clearcputimer(ctrl->SplitTmr); gk_clearcputimer(ctrl->Aux1Tmr); gk_clearcputimer(ctrl->Aux2Tmr); gk_clearcputimer(ctrl->Aux3Tmr); } /************************************************************************* * This function prints the various timers **************************************************************************/ void PrintTimers(ctrl_t *ctrl) { printf("\nTiming Information -------------------------------------------------"); printf("\n Multilevel: \t\t %7.3"PRREAL"", gk_getcputimer(ctrl->TotalTmr)); printf("\n Coarsening: \t\t %7.3"PRREAL"", gk_getcputimer(ctrl->CoarsenTmr)); printf("\n Matching: \t\t\t %7.3"PRREAL"", gk_getcputimer(ctrl->MatchTmr)); printf("\n Contract: \t\t\t %7.3"PRREAL"", gk_getcputimer(ctrl->ContractTmr)); printf("\n Initial Partition: \t %7.3"PRREAL"", gk_getcputimer(ctrl->InitPartTmr)); printf("\n Uncoarsening: \t\t %7.3"PRREAL"", gk_getcputimer(ctrl->UncoarsenTmr)); printf("\n Refinement: \t\t\t %7.3"PRREAL"", gk_getcputimer(ctrl->RefTmr)); printf("\n Projection: \t\t\t %7.3"PRREAL"", gk_getcputimer(ctrl->ProjectTmr)); printf("\n Splitting: \t\t %7.3"PRREAL"", gk_getcputimer(ctrl->SplitTmr)); /* printf("\n Aux1Tmr: \t\t %7.3"PRREAL"", gk_getcputimer(ctrl->Aux1Tmr)); printf("\n Aux2Tmr: \t\t %7.3"PRREAL"", gk_getcputimer(ctrl->Aux2Tmr)); printf("\n Aux3Tmr: \t\t %7.3"PRREAL"", gk_getcputimer(ctrl->Aux3Tmr)); */ printf("\n********************************************************************\n"); } Matrix/src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/mesh.c0000644000175100001440000003164314552244506024255 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ /* * Copyright 1997, Regents of the University of Minnesota * * mesh.c * * This file contains routines for converting 3D and 4D finite element * meshes into dual or nodal graphs * * Started 8/18/97 * George * * $Id: mesh.c 13804 2013-03-04 23:49:08Z karypis $ * */ #include "metislib.h" /*****************************************************************************/ /*! This function creates a graph corresponding to the dual of a finite element mesh. \param ne is the number of elements in the mesh. \param nn is the number of nodes in the mesh. \param eptr is an array of size ne+1 used to mark the start and end locations in the nind array. \param eind is an array that stores for each element the set of node IDs (indices) that it is made off. The length of this array is equal to the total number of nodes over all the mesh elements. \param ncommon is the minimum number of nodes that two elements must share in order to be connected via an edge in the dual graph. \param numflag is either 0 or 1 indicating if the numbering of the nodes starts from 0 or 1, respectively. The same numbering is used for the returned graph as well. \param r_xadj indicates where the adjacency list of each vertex is stored in r_adjncy. The memory for this array is allocated by this routine. It can be freed by calling METIS_free(). \param r_adjncy stores the adjacency list of each vertex in the generated dual graph. The memory for this array is allocated by this routine. It can be freed by calling METIS_free(). */ /*****************************************************************************/ int METIS_MeshToDual(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *ncommon, idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy) { int sigrval=0, renumber=0; /* set up malloc cleaning code and signal catchers */ if (!gk_malloc_init()) return METIS_ERROR_MEMORY; gk_sigtrap(); if ((sigrval = gk_sigcatch()) != 0) goto SIGTHROW; /* renumber the mesh */ if (*numflag == 1) { ChangeMesh2CNumbering(*ne, eptr, eind); renumber = 1; } /* create dual graph */ *r_xadj = *r_adjncy = NULL; CreateGraphDual(*ne, *nn, eptr, eind, *ncommon, r_xadj, r_adjncy); SIGTHROW: if (renumber) ChangeMesh2FNumbering(*ne, eptr, eind, *ne, *r_xadj, *r_adjncy); gk_siguntrap(); gk_malloc_cleanup(0); if (sigrval != 0) { if (*r_xadj != NULL) free(*r_xadj); if (*r_adjncy != NULL) free(*r_adjncy); *r_xadj = *r_adjncy = NULL; } return metis_rcode(sigrval); } /*****************************************************************************/ /*! This function creates a graph corresponding to (almost) the nodal of a finite element mesh. In the nodal graph, each node is connected to the nodes corresponding to the union of nodes present in all the elements in which that node belongs. \param ne is the number of elements in the mesh. \param nn is the number of nodes in the mesh. \param eptr is an array of size ne+1 used to mark the start and end locations in the nind array. \param eind is an array that stores for each element the set of node IDs (indices) that it is made off. The length of this array is equal to the total number of nodes over all the mesh elements. \param numflag is either 0 or 1 indicating if the numbering of the nodes starts from 0 or 1, respectively. The same numbering is used for the returned graph as well. \param r_xadj indicates where the adjacency list of each vertex is stored in r_adjncy. The memory for this array is allocated by this routine. It can be freed by calling METIS_free(). \param r_adjncy stores the adjacency list of each vertex in the generated dual graph. The memory for this array is allocated by this routine. It can be freed by calling METIS_free(). */ /*****************************************************************************/ int METIS_MeshToNodal(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, idx_t *numflag, idx_t **r_xadj, idx_t **r_adjncy) { int sigrval=0, renumber=0; /* set up malloc cleaning code and signal catchers */ if (!gk_malloc_init()) return METIS_ERROR_MEMORY; gk_sigtrap(); if ((sigrval = gk_sigcatch()) != 0) goto SIGTHROW; /* renumber the mesh */ if (*numflag == 1) { ChangeMesh2CNumbering(*ne, eptr, eind); renumber = 1; } /* create nodal graph */ *r_xadj = *r_adjncy = NULL; CreateGraphNodal(*ne, *nn, eptr, eind, r_xadj, r_adjncy); SIGTHROW: if (renumber) ChangeMesh2FNumbering(*ne, eptr, eind, *nn, *r_xadj, *r_adjncy); gk_siguntrap(); gk_malloc_cleanup(0); if (sigrval != 0) { if (*r_xadj != NULL) free(*r_xadj); if (*r_adjncy != NULL) free(*r_adjncy); *r_xadj = *r_adjncy = NULL; } return metis_rcode(sigrval); } /*****************************************************************************/ /*! This function creates the dual of a finite element mesh */ /*****************************************************************************/ void CreateGraphDual(idx_t ne, idx_t nn, idx_t *eptr, idx_t *eind, idx_t ncommon, idx_t **r_xadj, idx_t **r_adjncy) { idx_t i, j, nnbrs; idx_t *nptr, *nind; idx_t *xadj, *adjncy; idx_t *marker, *nbrs; if (ncommon < 1) { printf(" Increased ncommon to 1, as it was initially %"PRIDX"\n", ncommon); ncommon = 1; } /* construct the node-element list first */ nptr = ismalloc(nn+1, 0, "CreateGraphDual: nptr"); nind = imalloc(eptr[ne], "CreateGraphDual: nind"); for (i=0; i= ncommon || overlap >= elen-1 || overlap >= eptr[l+1]-eptr[l]-1) nbrs[j++] = l; marker[l] = 0; } return j; } /*****************************************************************************/ /*! This function creates the (almost) nodal of a finite element mesh */ /*****************************************************************************/ void CreateGraphNodal(idx_t ne, idx_t nn, idx_t *eptr, idx_t *eind, idx_t **r_xadj, idx_t **r_adjncy) { idx_t i, j, nnbrs; idx_t *nptr, *nind; idx_t *xadj, *adjncy; idx_t *marker, *nbrs; /* construct the node-element list first */ nptr = ismalloc(nn+1, 0, "CreateGraphNodal: nptr"); nind = imalloc(eptr[ne], "CreateGraphNodal: nind"); for (i=0; ieptr, &mesh->eind, &mesh->ewgt, &mesh, LTERM); *r_mesh = NULL; } Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/0000755000175100001440000000000014576344041017615 5ustar hornikusersMatrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_norm.c0000644000175100001440000000076414552026002022747 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_l_norm.c: int64_t version of cholmod_norm //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_norm.c" Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_submatrix.c0000644000175100001440000000100314552026002023775 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_l_submatrix.c: int64_t version of cholmod_submatrix //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_submatrix.c" Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_norm.c0000644000175100001440000001513214552026002022427 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_norm: compute norm of a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // r = norm (A), compute the infinity-norm, 1-norm, or 2-norm of a sparse or // dense matrix. Can compute the 2-norm only for a dense column vector. // Returns -1 if an error occurs. // // Pattern, real, complex, and zomplex sparse matrices, with any dtype, are // supported. #include "cholmod_internal.h" #ifndef NGPL #ifndef NMATRIXOPS //------------------------------------------------------------------------------ // t_cholmod_norm_worker template //------------------------------------------------------------------------------ #define PATTERN #include "t_cholmod_norm_worker.c" #define DOUBLE #define REAL #include "t_cholmod_norm_worker.c" #define COMPLEX #include "t_cholmod_norm_worker.c" #define ZOMPLEX #include "t_cholmod_norm_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_norm_worker.c" #define COMPLEX #include "t_cholmod_norm_worker.c" #define ZOMPLEX #include "t_cholmod_norm_worker.c" //------------------------------------------------------------------------------ // cholmod_norm_dense //------------------------------------------------------------------------------ double CHOLMOD(norm_dense) // returns norm (X) ( // input: cholmod_dense *X, // matrix to compute the norm of int norm, // type of norm: 0: inf. norm, 1: 1-norm, 2: 2-norm cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (EMPTY) ; RETURN_IF_NULL (X, EMPTY) ; RETURN_IF_XTYPE_INVALID (X, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, EMPTY) ; Common->status = CHOLMOD_OK ; if (norm < 0 || norm > 2 || (norm == 2 && X->ncol > 1)) { ERROR (CHOLMOD_INVALID, "invalid norm") ; return (EMPTY) ; } //-------------------------------------------------------------------------- // allocate workspace, if needed //-------------------------------------------------------------------------- double *W = NULL ; bool use_workspace = (norm == 0 && X->ncol > 4) ; if (use_workspace) { CHOLMOD(alloc_work) (0, 0, X->nrow, CHOLMOD_DOUBLE, Common) ; W = (double *) (Common->Xwork) ; if (Common->status < CHOLMOD_OK) { // oops, no workspace use_workspace = FALSE ; W = NULL ; } } //-------------------------------------------------------------------------- // compute the norm //-------------------------------------------------------------------------- double xnorm = 0 ; switch ((X->xtype + X->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: xnorm = rs_cholmod_norm_dense_worker (X, norm, W) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: xnorm = cs_cholmod_norm_dense_worker (X, norm, W) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: xnorm = zs_cholmod_norm_dense_worker (X, norm, W) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: xnorm = rd_cholmod_norm_dense_worker (X, norm, W) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: xnorm = cd_cholmod_norm_dense_worker (X, norm, W) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: xnorm = zd_cholmod_norm_dense_worker (X, norm, W) ; break ; } return (xnorm) ; } //------------------------------------------------------------------------------ // cholmod_norm_sparse //------------------------------------------------------------------------------ double CHOLMOD(norm_sparse) // returns norm (A) ( // input: cholmod_sparse *A, // matrix to compute the norm of int norm, // type of norm: 0: inf. norm, 1: 1-norm cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (EMPTY) ; RETURN_IF_NULL (A, EMPTY) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, EMPTY) ; Common->status = CHOLMOD_OK ; if (norm < 0 || norm > 1) { ERROR (CHOLMOD_INVALID, "invalid norm") ; return (EMPTY) ; } if (A->stype && A->nrow != A->ncol) { ERROR (CHOLMOD_INVALID, "matrix invalid") ; return (EMPTY) ; } //-------------------------------------------------------------------------- // allocate workspace, if needed //-------------------------------------------------------------------------- double *W = NULL ; if (A->stype || norm == 0) { CHOLMOD(alloc_work) (0, 0, A->nrow, CHOLMOD_DOUBLE, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (EMPTY) ; } W = (double *) (Common->Xwork) ; DEBUG (for (Int i = 0 ; i < A->nrow ; i++) ASSERT (W [i] == 0)) ; } //-------------------------------------------------------------------------- // compute the norm //-------------------------------------------------------------------------- double anorm = 0 ; switch ((A->xtype + A->dtype) % 8) { default: anorm = p_cholmod_norm_sparse_worker (A, norm, W) ; break ; case CHOLMOD_SINGLE + CHOLMOD_REAL: anorm = rs_cholmod_norm_sparse_worker (A, norm, W) ; break ; case CHOLMOD_SINGLE + CHOLMOD_COMPLEX: anorm = cs_cholmod_norm_sparse_worker (A, norm, W) ; break ; case CHOLMOD_SINGLE + CHOLMOD_ZOMPLEX: anorm = zs_cholmod_norm_sparse_worker (A, norm, W) ; break ; case CHOLMOD_DOUBLE + CHOLMOD_REAL: anorm = rd_cholmod_norm_sparse_worker (A, norm, W) ; break ; case CHOLMOD_DOUBLE + CHOLMOD_COMPLEX: anorm = cd_cholmod_norm_sparse_worker (A, norm, W) ; break ; case CHOLMOD_DOUBLE + CHOLMOD_ZOMPLEX: anorm = zd_cholmod_norm_sparse_worker (A, norm, W) ; break ; } return (anorm) ; } #endif #endif Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_sdmult.c0000644000175100001440000000077214552026002023303 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_l_sdmult.c: int64_t version of cholmod_sdmult //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_sdmult.c" Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_horzcat.c0000644000175100001440000000077514552026002023450 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_l_horzcat.c: int64_t version of cholmod_horzcat //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_horzcat.c" Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_horzcat.c0000644000175100001440000001473014552026002023131 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_horzcat: horizontal concatenation, C=[A B] //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // Horizontal concatenation, C = [A , B] in MATLAB notation. // // A and B can be up/lo/unsym; C is unsymmetric and packed. // A and B must have the same number of rows. // C is sorted if both A and B are sorted. // // workspace: Iwork (max (A->nrow, A->ncol, B->nrow, B->ncol)). // allocates temporary copies of A and B if they are symmetric. // // A and B must have the same xtype and dtype, unless mode is 0. #include "cholmod_internal.h" #ifndef NGPL #ifndef NMATRIXOPS //------------------------------------------------------------------------------ // t_cholmod_horzcat_worker template //------------------------------------------------------------------------------ #define PATTERN #include "t_cholmod_horzcat_worker.c" #define DOUBLE #define REAL #include "t_cholmod_horzcat_worker.c" #define COMPLEX #include "t_cholmod_horzcat_worker.c" #define ZOMPLEX #include "t_cholmod_horzcat_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_horzcat_worker.c" #define COMPLEX #include "t_cholmod_horzcat_worker.c" #define ZOMPLEX #include "t_cholmod_horzcat_worker.c" //------------------------------------------------------------------------------ // cholmod_horzcat //------------------------------------------------------------------------------ cholmod_sparse *CHOLMOD(horzcat) // return C = [A B] ( // input: cholmod_sparse *A, // left matrix to concatenate cholmod_sparse *B, // right matrix to concatenate int mode, // 2: numerical (conj) if A and/or B are symmetric // 1: numerical (non-conj.) if A and/or B are symmetric // 0: pattern cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- cholmod_sparse *C = NULL, *A2 = NULL, *B2 = NULL ; RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_NULL (A, NULL) ; RETURN_IF_NULL (B, NULL) ; mode = RANGE (mode, 0, 2) ; if (A->xtype == CHOLMOD_PATTERN || B->xtype == CHOLMOD_PATTERN) { mode = 0 ; } bool values = (mode != 0) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, NULL) ; RETURN_IF_XTYPE_INVALID (B, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, NULL) ; if (A->nrow != B->nrow) { // A and B must have the same number of rows ERROR (CHOLMOD_INVALID, "A and B must have same # rows") ; return (NULL) ; } if (mode != 0 && (A->xtype != B->xtype || A->dtype != B->dtype)) { // A and B must have the same xtype and dtype if mode is 0 ERROR (CHOLMOD_INVALID, "A and B must have same xtype and dtype") ; return (NULL) ; } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- Int ancol = A->ncol ; Int bncol = B->ncol ; Int nrow = A->nrow ; CHOLMOD(allocate_work) (0, MAX3 (nrow, ancol, bncol), 0, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (NULL) ; } //-------------------------------------------------------------------------- // convert A and/or B if necessary //-------------------------------------------------------------------------- // convert A to unsymmetric, if necessary if (A->stype != 0) { // workspace: Iwork (max (A->nrow,A->ncol)) A2 = CHOLMOD(copy) (A, 0, mode, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (NULL) ; } A = A2 ; } // convert B to unsymmetric, if necessary if (B->stype != 0) { // workspace: Iwork (max (B->nrow,B->ncol)) B2 = CHOLMOD(copy) (B, 0, mode, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory CHOLMOD(free_sparse) (&A2, Common) ; return (NULL) ; } B = B2 ; } //-------------------------------------------------------------------------- // allocate C //-------------------------------------------------------------------------- Int anz = CHOLMOD(nnz) (A, Common) ; Int bnz = CHOLMOD(nnz) (B, Common) ; Int ncol = ancol + bncol ; Int nz = anz + bnz ; C = CHOLMOD(allocate_sparse) (nrow, ncol, nz, A->sorted && B->sorted, TRUE, 0, (values ? A->xtype : CHOLMOD_PATTERN) + A->dtype, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory CHOLMOD(free_sparse) (&A2, Common) ; CHOLMOD(free_sparse) (&B2, Common) ; return (NULL) ; } //-------------------------------------------------------------------------- // C = [A , B] //-------------------------------------------------------------------------- switch ((C->xtype + C->dtype) % 8) { default: p_cholmod_horzcat_worker (C, A, B) ; break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_horzcat_worker (C, A, B) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_horzcat_worker (C, A, B) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_horzcat_worker (C, A, B) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_horzcat_worker (C, A, B) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_horzcat_worker (C, A, B) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_horzcat_worker (C, A, B) ; break ; } //-------------------------------------------------------------------------- // free the unsymmetric copies of A and B, and return C //-------------------------------------------------------------------------- CHOLMOD(free_sparse) (&A2, Common) ; CHOLMOD(free_sparse) (&B2, Common) ; return (C) ; } #endif #endif Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_symmetry.c0000644000175100001440000004545614552026002023361 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_symmetry: determine symmetry status of a matrix //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // Determines if a sparse matrix is rectangular, unsymmetric, symmetric, // skew-symmetric, or Hermitian. It does so by looking at its numerical values // of both upper and lower triangular parts of a CHOLMOD "unsymmetric" // matrix, where A->stype == 0. The transpose of A is NOT constructed. // // If not unsymmetric, it also determines if the matrix has a diagonal whose // entries are all real and positive (and thus a candidate for sparse Cholesky // if A->stype is changed to a nonzero value). // // Note that a Matrix Market "general" matrix is either rectangular or // unsymmetric. // // The row indices in the column of each matrix MUST be sorted for this function // to work properly (A->sorted must be true). This routine returns EMPTY if // A->stype is not zero, or if A->sorted is false. The exception to this rule // is if A is rectangular. // // If option == 0, then this routine returns immediately when it finds a // non-positive diagonal entry (or one with nonzero imaginary part). If the // matrix is not a candidate for sparse Cholesky, it returns the value // CHOLMOD_MM_UNSYMMETRIC, even if the matrix might in fact be symmetric or // Hermitian. // // This routine is useful inside the MATLAB backslash, which must look at an // arbitrary matrix (A->stype == 0) and determine if it is a candidate for // sparse Cholesky. In that case, option should be 0. // // This routine is also useful when writing a MATLAB matrix to a file in // Rutherford/Boeing or Matrix Market format. Those formats require a // determination as to the symmetry of the matrix, and thus this routine should // not return upon encountering the first non-positive diagonal. In this case, // option should be 1. // // If option is 2, this function can be used to compute the numerical and // pattern symmetry, where 0 is a completely unsymmetric matrix, and 1 is a // perfectly symmetric matrix. This option is used when computing the following // statistics for the matrices in the SuiteSparse Matrix Collection. // // numerical symmetry: number of matched offdiagonal nonzeros over // the total number of offdiagonal entries. A real entry A(i,j), i ~= j, // is matched if A (j,i) == A (i,j), but this is only counted if both // A(j,i) and A(i,j) are nonzero. This does not depend on Z. // (If A is complex, then the above test is modified; A (i,j) is matched // if conj (A (j,i)) == A (i,j)). // // Then numeric symmetry = xmatched / nzoffdiag, or 1 if nzoffdiag = 0. // // pattern symmetry: number of matched offdiagonal entries over the // total number of offdiagonal entries. An entry A(i,j), i ~= j, is // matched if A (j,i) is also an entry. // // Then pattern symmetry = pmatched / nzoffdiag, or 1 if nzoffdiag = 0. // // The symmetry of a matrix with no offdiagonal entries is equal to 1. // // A workspace of size ncol integers is allocated; EMPTY is returned if this // allocation fails. // // Summary of return values: // // EMPTY (-1) out of memory, stype not zero, A not sorted // CHOLMOD_MM_RECTANGULAR 1 A is rectangular // CHOLMOD_MM_UNSYMMETRIC 2 A is unsymmetric // CHOLMOD_MM_SYMMETRIC 3 A is symmetric, but with non-pos. diagonal // CHOLMOD_MM_HERMITIAN 4 A is Hermitian, but with non-pos. diagonal // CHOLMOD_MM_SKEW_SYMMETRIC 5 A is skew symmetric // CHOLMOD_MM_SYMMETRIC_POSDIAG 6 A is symmetric with positive diagonal // CHOLMOD_MM_HERMITIAN_POSDIAG 7 A is Hermitian with positive diagonal // // See also the spsym mexFunction, which is a MATLAB interface for this code. // // If the matrix is a candidate for sparse Cholesky, it will return a result // CHOLMOD_MM_SYMMETRIC_POSDIAG if real, or CHOLMOD_MM_HERMITIAN_POSDIAG if // complex. Otherwise, it will return a value less than this. This is true // regardless of the value of the option parameter. #include "cholmod_internal.h" #ifndef NGPL #ifndef NMATRIXOPS //------------------------------------------------------------------------------ // get_value: get the pth value in the matrix //------------------------------------------------------------------------------ static void get_value ( cholmod_sparse *A, // sparse matrix to query Int p, // get the pth entry of A int xtype, // A->xtype: pattern, real, complex, or zomplex int dtype, // A->dtype: single or double double *x, // the real part of A(i,j) double *z // the imaginary part of A(i,j) ) { switch (xtype) { case CHOLMOD_PATTERN: (*x) = 1 ; (*z) = 0 ; break ; case CHOLMOD_REAL: if (dtype == CHOLMOD_DOUBLE) { double *Ax = A->x ; (*x) = Ax [p] ; } else { float *Ax = A->x ; (*x) = (double) Ax [p] ; } (*z) = 0 ; break ; case CHOLMOD_COMPLEX: if (dtype == CHOLMOD_DOUBLE) { double *Ax = A->x ; (*x) = Ax [2*p] ; (*z) = Ax [2*p+1] ; } else { float *Ax = A->x ; (*x) = (double) Ax [2*p] ; (*z) = (double) Ax [2*p+1] ; } break ; case CHOLMOD_ZOMPLEX: if (dtype == CHOLMOD_DOUBLE) { double *Ax = A->x ; double *Az = A->z ; (*x) = Ax [p] ; (*z) = Az [p] ; } else { float *Ax = A->x ; float *Az = A->z ; (*x) = (double) Ax [p] ; (*z) = (double) Az [p] ; } break ; } } //------------------------------------------------------------------------------ // cholmod_symmetry //------------------------------------------------------------------------------ // Determine the symmetry of a matrix, and check its diagonal. // // option 0: Do not count # of matched pairs. Quick return if the // the matrix has a zero, negative, or imaginary diagonal entry. // // option 1: Do not count # of matched pairs. Do not return quickly if // the matrix has a zero, negative, or imaginary diagonal entry. // The result 1 to 7 is accurately computed: // // EMPTY (-1): out of memory, stype not zero, // A not sorted // CHOLMOD_MM_RECTANGULAR 1 A is rectangular // CHOLMOD_MM_UNSYMMETRIC 2 A is unsymmetric // CHOLMOD_MM_SYMMETRIC 3 A is symmetric, with non-pos. diagonal // CHOLMOD_MM_HERMITIAN 4 A is Hermitian, with non-pos. diagonal // CHOLMOD_MM_SKEW_SYMMETRIC 5 A is skew symmetric // CHOLMOD_MM_SYMMETRIC_POSDIAG 6 is symmetric with positive diagonal // CHOLMOD_MM_HERMITIAN_POSDIAG 7 A is Hermitian with positive diagonal // // The routine returns as soon as the above is determined (that is, it // can return as soon as it determines the matrix is unsymmetric). // // option 2: All of the above, but also compute the number of matched off- // diagonal entries (of two types). xmatched is the number of nonzero // entries for which A(i,j) = conj(A(j,i)). pmatched is the number of // entries (i,j) for which A(i,j) and A(j,i) are both in the pattern of A // (the value doesn't matter). nzoffdiag is the total number of // off-diagonal entries in the pattern. nzdiag is the number of diagonal // entries in the pattern. // // With option 0 or 1, or if the matrix is rectangular, xmatched, pmatched, // nzoffdiag, and nzdiag are not computed. // // Note that a matched pair, A(i,j) and A(j,i) for i != j, is counted twice // (once per entry). int CHOLMOD(symmetry) ( // input: cholmod_sparse *A, int option, // option 0, 1, or 2 (see above) // output: Int *p_xmatched, // # of matched numerical entries Int *p_pmatched, // # of matched entries in pattern Int *p_nzoffdiag, // # of off diagonal entries Int *p_nzdiag, // # of diagonal entries cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (EMPTY) ; RETURN_IF_NULL (A, EMPTY) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, EMPTY) ; Common->status = CHOLMOD_OK ; ASSERT (CHOLMOD(dump_sparse) (A, "cholmod_symmetry", Common) >= 0) ; if (p_xmatched == NULL || p_pmatched == NULL || p_nzoffdiag == NULL || p_nzdiag == NULL) { // option 2 is not performed if any output parameter is NULL option = MAX (option, 1) ; } //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Ap = A->p ; Int *Ai = A->i ; Int *Anz = A->nz ; bool packed = A->packed ; Int ncol = A->ncol ; Int nrow = A->nrow ; int xtype = A->xtype ; int dtype = A->dtype ; //-------------------------------------------------------------------------- // check if rectangular, unsorted, or stype is not zero //-------------------------------------------------------------------------- if (nrow != ncol) { // matrix is rectangular return (CHOLMOD_MM_RECTANGULAR) ; } if (!(A->sorted) || A->stype != 0) { // this function cannot determine the type or symmetry return (EMPTY) ; } //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- // this function requires uninitialized Int workspace of size ncol CHOLMOD(allocate_work) (0, ncol, 0, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (EMPTY) ; } Int *munch = Common->Iwork ; // the munch array is size ncol //-------------------------------------------------------------------------- // determine symmetry of a square matrix //-------------------------------------------------------------------------- // a complex or zomplex matrix is Hermitian until proven otherwise bool is_hermitian = (xtype >= CHOLMOD_COMPLEX) ; // any matrix is symmetric until proven otherwise bool is_symmetric = true ; // a non-pattern matrix is skew-symmetric until proven otherwise bool is_skew = (xtype != CHOLMOD_PATTERN) ; // a matrix has positive diagonal entries until proven otherwise bool posdiag = true ; // munch pointers start at the top of each column for (Int j = 0 ; j < ncol ; j++) { munch [j] = Ap [j] ; } Int xmatched = 0 ; Int pmatched = 0 ; Int nzdiag = 0 ; for (Int j = 0 ; j < ncol ; j++) // examine each column of A { //---------------------------------------------------------------------- // look at the entire munch column j //---------------------------------------------------------------------- // start at the munch point of column j, and go to end of the column Int p = munch [j] ; Int pend = (packed) ? (Ap [j+1]) : (Ap [j] + Anz [j]) ; for ( ; p < pend ; p++) { // get the row index of A(i,j) Int i = Ai [p] ; if (i < j) { //-------------------------------------------------------------- // A(i,j) in triu(A), but matching A(j,i) not in tril(A) //-------------------------------------------------------------- // entry A(i,j) is unmatched; it appears in the upper triangular // part, but not the lower triangular part. The matrix is // unsymmetric. is_hermitian = false ; is_symmetric = false ; is_skew = false ; } else if (i == j) { //-------------------------------------------------------------- // the diagonal A(j,j) is present; check its value //-------------------------------------------------------------- double aij_real, aij_imag ; get_value (A, p, xtype, dtype, &aij_real, &aij_imag) ; if (aij_real != 0. || aij_imag != 0.) { // diagonal is nonzero; matrix is not skew-symmetric nzdiag++ ; is_skew = false ; } if (aij_real <= 0. || aij_imag != 0.) { // diagonal negative or imaginary; not chol candidate posdiag = false ; } if (aij_imag != 0.) { // imaginary part is present; not Hermitian is_hermitian = false ; } } else // i > j { //-------------------------------------------------------------- // consider column i, up to and including row j //-------------------------------------------------------------- // munch the entry at top of column i up to and incl row j Int piend = (packed) ? (Ap [i+1]) : (Ap [i] + Anz [i]) ; bool found = false ; for ( ; munch [i] < piend ; munch [i]++) { Int i2 = Ai [munch [i]] ; if (i2 < j) { //------------------------------------------------------ // A(i2,i) in triu(A) but A(i,i2) not in tril(A) //------------------------------------------------------ // the matrix is unsymmetric is_hermitian = false ; is_symmetric = false ; is_skew = false ; } else if (i2 == j) { //------------------------------------------------------ // both A(i,j) and A(j,i) exist in the matrix //------------------------------------------------------ // this is one more matching entry in the pattern pmatched += 2 ; found = true ; // get the value of A(i,j) double aij_real, aij_imag ; get_value (A, p, xtype, dtype, &aij_real, &aij_imag) ; // get the value of A(j,i) at the munch [i] position double aji_real, aji_imag ; Int p2 = munch [i] ; get_value (A, p2, xtype, dtype, &aji_real, &aji_imag) ; // compare A(i,j) with A(j,i) if (aij_real != aji_real || aij_imag != aji_imag) { // the matrix cannot be symmetric is_symmetric = false ; } if (aij_real != -aji_real || aij_imag != aji_imag) { // the matrix cannot be skew-symmetric is_skew = false ; } if (aij_real != aji_real || aij_imag != -aji_imag) { // the matrix cannot be Hermitian is_hermitian = false ; } else { // A(i,j) and A(j,i) are numerically matched xmatched += 2 ; } } else // i2 > j { //------------------------------------------------------ // entry A(i2,i) is not munched; consider it later //------------------------------------------------------ break ; } } if (!found) { // A(i,j) in tril(A) but A(j,i) not in triu(A). // The matrix is unsymmetric. is_hermitian = false ; is_symmetric = false ; is_skew = false ; } } if (option < 2 && !(is_symmetric || is_skew || is_hermitian)) { // matrix is unsymmetric; terminate the test return (CHOLMOD_MM_UNSYMMETRIC) ; } } //---------------------------------------------------------------------- // quick return if not Cholesky candidate //---------------------------------------------------------------------- if (option < 1 && (!posdiag || nzdiag <= j)) { // Diagonal entry not present, or present but negative or with // nonzero imaginary part. Quick return for option 0. return (CHOLMOD_MM_UNSYMMETRIC) ; } } //-------------------------------------------------------------------------- // return the results //-------------------------------------------------------------------------- if (nzdiag < ncol) { // not all diagonal entries are present posdiag = false ; } if (option >= 2) { *p_xmatched = xmatched ; *p_pmatched = pmatched ; *p_nzoffdiag = CHOLMOD(nnz) (A, Common) - nzdiag ; *p_nzdiag = nzdiag ; } int result = CHOLMOD_MM_UNSYMMETRIC ; if (is_hermitian) { // complex Hermitian matrix, with either pos. or non-pos. diagonal result = posdiag ? CHOLMOD_MM_HERMITIAN_POSDIAG : CHOLMOD_MM_HERMITIAN ; } else if (is_symmetric) { // real or complex symmetric matrix, with pos. or non-pos. diagonal result = posdiag ? CHOLMOD_MM_SYMMETRIC_POSDIAG : CHOLMOD_MM_SYMMETRIC ; } else if (is_skew) { // real or complex skew-symmetric matrix result = CHOLMOD_MM_SKEW_SYMMETRIC ; } return (result) ; } #endif #endif Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_ssmult.c0000644000175100001440000002567114552026002023014 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_ssmult: sparse-times-sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // C = A*B. Multiply two sparse matrices. // // A and B can be packed or unpacked, sorted or unsorted, and of any stype. If // A or B are symmetric, an internal unsymmetric copy is made first, however. // For the complex case, if A and/or B are symmetric with just their lower or // upper part stored, they are assumed to be Hermitian when converted. // // C is computed as if A and B are unsymmetric, and then if the stype input // parameter requests a symmetric form (upper or lower) the matrix is converted // into that form. // // C is returned as packed, and either unsorted or sorted, depending on the // "sorted" input parameter. If C is returned sorted, then either C = (B'*A')' // or C = (A*B)'' is computed, depending on the number of nonzeros in A, B, and // C. // // workspace: // if C unsorted: Flag (A->nrow), W (A->nrow) if values // if C sorted: Flag (B->ncol), W (B->ncol) if values // Iwork (max (A->ncol, A->nrow, B->nrow, B->ncol)) // allocates temporary copies for A, B, and C, if required. // // Matrices of any xtype and dtype supported, but the xtype and dtype of // A and B must match (unless mode is zero). #include "cholmod_internal.h" #ifndef NGPL #ifndef NMATRIXOPS //------------------------------------------------------------------------------ // t_cholmod_ssmult_worker template //------------------------------------------------------------------------------ #define PATTERN #include "t_cholmod_ssmult_worker.c" #define DOUBLE #define REAL #include "t_cholmod_ssmult_worker.c" #define COMPLEX #include "t_cholmod_ssmult_worker.c" #define ZOMPLEX #include "t_cholmod_ssmult_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_ssmult_worker.c" #define COMPLEX #include "t_cholmod_ssmult_worker.c" #define ZOMPLEX #include "t_cholmod_ssmult_worker.c" //------------------------------------------------------------------------------ // cholmod_ssmult //------------------------------------------------------------------------------ cholmod_sparse *CHOLMOD(ssmult) // return C=A*B ( // input: cholmod_sparse *A, // left matrix to multiply cholmod_sparse *B, // right matrix to multiply int stype, // requested stype of C int mode, // 2: numerical (conj) if A and/or B are symmetric // 1: numerical (non-conj.) if A and/or B are symmetric // 0: pattern int sorted, // if TRUE then return C with sorted columns cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- cholmod_sparse *C = NULL, *A2 = NULL, *B2 = NULL ; RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_NULL (A, NULL) ; RETURN_IF_NULL (B, NULL) ; mode = RANGE (mode, 0, 2) ; if (A->xtype == CHOLMOD_PATTERN || B->xtype == CHOLMOD_PATTERN) { mode = 0 ; } RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, NULL) ; RETURN_IF_XTYPE_INVALID (B, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, NULL) ; if (A->ncol != B->nrow) { // inner dimensions must agree ERROR (CHOLMOD_INVALID, "A and B inner dimensions must match") ; return (NULL) ; } bool values = (mode != 0) ; if (values && (A->xtype != B->xtype || A->dtype != B->dtype)) { // A and B must have the same numerical type if mode != 0 ERROR (CHOLMOD_INVALID, "A and B must have the same xtype and dtype") ; return (NULL) ; } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- if (A->nrow <= 1) { // C will be implicitly sorted, so no need to sort it here sorted = FALSE ; } size_t n1 ; if (sorted) { n1 = MAX (A->nrow, B->ncol) ; } else { n1 = A->nrow ; } size_t n2 = (size_t) MAX4 (A->ncol, A->nrow, B->nrow, B->ncol) ; size_t nw = ((A->xtype >= CHOLMOD_COMPLEX) ? 2 : 1) * (values ? n1 : 0) ; CHOLMOD(alloc_work) (n1, n2, nw, A->dtype, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (NULL) ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, nw, A->dtype, Common)) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- // convert A to unsymmetric, if necessary A2 = NULL ; B2 = NULL ; if (A->stype) { // workspace: Iwork (max (A->nrow,A->ncol)) A2 = CHOLMOD(copy) (A, 0, mode, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, nw, A->dtype, Common)) ; return (NULL) ; } A = A2 ; } // convert B to unsymmetric, if necessary if (B->stype) { // workspace: Iwork (max (B->nrow,B->ncol)) B2 = CHOLMOD(copy) (B, 0, mode, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory CHOLMOD(free_sparse) (&A2, Common) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, nw, A->dtype, Common)) ; return (NULL) ; } B = B2 ; } ASSERT (CHOLMOD(dump_sparse) (A, "A", Common) >= 0) ; ASSERT (CHOLMOD(dump_sparse) (B, "B", Common) >= 0) ; // get the A matrix Int *Ap = A->p ; Int *Anz = A->nz ; Int *Ai = A->i ; bool apacked = A->packed ; // get the B matrix Int *Bp = B->p ; Int *Bnz = B->nz ; Int *Bi = B->i ; bool bpacked = B->packed ; // get the size of C Int nrow = A->nrow ; Int ncol = B->ncol ; // get workspace Int *Flag = Common->Flag ; // size nrow, Flag [0..nrow-1] < mark on input //-------------------------------------------------------------------------- // count the number of entries in the result C //-------------------------------------------------------------------------- int ok = TRUE ; size_t cnz = 0 ; size_t cnzmax = SIZE_MAX - A->nrow ; for (Int j = 0 ; ok && (j < ncol) ; j++) { // clear the Flag array CLEAR_FLAG (Common) ; Int mark = Common->mark ; // for each nonzero B(k,j) in column j, do: Int pb = Bp [j] ; Int pbend = (bpacked) ? (Bp [j+1]) : (pb + Bnz [j]) ; for ( ; pb < pbend ; pb++) { // B(k,j) is nonzero Int k = Bi [pb] ; // add the nonzero pattern of A(:,k) to the pattern of C(:,j) Int pa = Ap [k] ; Int paend = (apacked) ? (Ap [k+1]) : (pa + Anz [k]) ; for ( ; pa < paend ; pa++) { Int i = Ai [pa] ; if (Flag [i] != mark) { Flag [i] = mark ; cnz++ ; } } } ok = (cnz < cnzmax) ; } CLEAR_FLAG (Common) ; ASSERT (check_flag (Common)) ; //-------------------------------------------------------------------------- // allocate C //-------------------------------------------------------------------------- C = CHOLMOD(allocate_sparse) (nrow, ncol, ok ? cnz : SIZE_MAX, FALSE, TRUE, 0, (values ? A->xtype : CHOLMOD_PATTERN) + A->dtype, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory CHOLMOD(free_sparse) (&A2, Common) ; CHOLMOD(free_sparse) (&B2, Common) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, nw, A->dtype, Common)) ; return (NULL) ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, nw, A->dtype, Common)) ; //-------------------------------------------------------------------------- // C = A*B //-------------------------------------------------------------------------- switch ((C->xtype + C->dtype) % 8) { default: p_cholmod_ssmult_worker (C, A, B, Common) ; break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_ssmult_worker (C, A, B, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_ssmult_worker (C, A, B, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_ssmult_worker (C, A, B, Common) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_ssmult_worker (C, A, B, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_ssmult_worker (C, A, B, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_ssmult_worker (C, A, B, Common) ; break ; } //-------------------------------------------------------------------------- // clear workspace and free temporary matrices //-------------------------------------------------------------------------- CHOLMOD(free_sparse) (&A2, Common) ; CHOLMOD(free_sparse) (&B2, Common) ; CLEAR_FLAG (Common) ; ASSERT (check_flag (Common)) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, nw, A->dtype, Common)) ; //-------------------------------------------------------------------------- // convert C to a symmetric upper/lower matrix if requested //-------------------------------------------------------------------------- // convert C in place, which cannot fail since no memory is allocated if (stype > 0) { // C = triu (C), in place (void) CHOLMOD(band_inplace) (0, ncol, values, C, Common) ; C->stype = 1 ; } else if (stype < 0) { // C = tril (C), in place (void) CHOLMOD(band_inplace) (-nrow, 0, values, C, Common) ; C->stype = -1 ; } ASSERT (Common->status >= CHOLMOD_OK) ; //-------------------------------------------------------------------------- // sort C, if requested //-------------------------------------------------------------------------- if (sorted) { // this cannot fail (no workspace; sort is done in-place) CHOLMOD(sort) (C, Common) ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_sparse) (C, "ssmult", Common) >= 0) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, nw, A->dtype, Common)) ; return (C) ; } #endif #endif Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_scale.c0000644000175100001440000001274514552026002022552 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_scale: scale a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // scale a matrix: A = diag(s)*A, A*diag(s), s*A, or diag(s)*A*diag(s) // // A can be of any type (packed/unpacked, upper/lower/unsymmetric). // The symmetry of A is ignored; all entries in the matrix are modified. // // If A is m-by-n unsymmetric but scaled symmtrically, the result is // A = diag (s (1:m)) * A * diag (s (1:n)). // // Note: diag(s) should be interpretted as spdiags(s,0,n,n) where n=length(s). // // Row or column scaling of a symmetric matrix still results in a symmetric // matrix, since entries are still ignored by other routines. // For example, when row-scaling a symmetric matrix where just the upper // triangular part is stored (and lower triangular entries ignored) // A = diag(s)*triu(A) is performed, where the result A is also // symmetric-upper. This has the effect of modifying the implicit lower // triangular part. In MATLAB notation: // // U = diag(s)*triu(A) ; // L = tril (U',-1) // A = L + U ; // // The scale parameter determines the kind of scaling to perform: // // CHOLMOD_SCALAR: s[0]*A // CHOLMOD_ROW: diag(s)*A // CHOLMOD_COL: A*diag(s) // CHOLMOD_SYM: diag(s)*A*diag(s) // // The size of S depends on the scale parameter: // // CHOLMOD_SCALAR: size 1 // CHOLMOD_ROW: size nrow-by-1 or 1-by-nrow // CHOLMOD_COL: size ncol-by-1 or 1-by-ncol // CHOLMOD_SYM: size max(nrow,ncol)-by-1, or 1-by-max(nrow,ncol) // // workspace: none // // Real, complex, and zomplex matrices are supported, of any dtype. // The xtype and dtype of A and S must match. #include "cholmod_internal.h" #ifndef NGPL #ifndef NMATRIXOPS //------------------------------------------------------------------------------ // t_cholmod_scale_worker //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_scale_worker.c" #define COMPLEX #include "t_cholmod_scale_worker.c" #define ZOMPLEX #include "t_cholmod_scale_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_scale_worker.c" #define COMPLEX #include "t_cholmod_scale_worker.c" #define ZOMPLEX #include "t_cholmod_scale_worker.c" //------------------------------------------------------------------------------ // cholmod_scale //------------------------------------------------------------------------------ int CHOLMOD(scale) ( // input: cholmod_dense *S, // scale factors (scalar or vector) int scale, // type of scaling to compute // input/output: cholmod_sparse *A, // matrix to scale cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (S, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (S, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ; if (A->xtype != S->xtype || A->dtype != S->dtype) { ERROR (CHOLMOD_INVALID, "xtype and dtype of A and S must match") ; return (FALSE) ; } Int ncol = A->ncol ; Int nrow = A->nrow ; Int sncol = S->ncol ; Int snrow = S->nrow ; bool ok ; if (scale == CHOLMOD_SCALAR) { ok = (snrow == 1 && sncol == 1) ; } else if (scale == CHOLMOD_ROW) { ok = (snrow == nrow && sncol == 1) || (snrow == 1 && sncol == nrow) ; } else if (scale == CHOLMOD_COL) { ok = (snrow == ncol && sncol == 1) || (snrow == 1 && sncol == ncol) ; } else if (scale == CHOLMOD_SYM) { Int nn = MAX (nrow, ncol) ; ok = (snrow == nn && sncol == 1) || (snrow == 1 && sncol == nn) ; } else { // scale invalid ERROR (CHOLMOD_INVALID, "invalid scaling option") ; return (FALSE) ; } if (!ok) { // S is wrong size ERROR (CHOLMOD_INVALID, "invalid scale factors") ; return (FALSE) ; } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // scale the matrix //-------------------------------------------------------------------------- switch ((A->xtype + A->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_scale_worker (S, scale, A) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_scale_worker (S, scale, A) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_scale_worker (S, scale, A) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_scale_worker (S, scale, A) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_scale_worker (S, scale, A) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_scale_worker (S, scale, A) ; break ; } ASSERT (CHOLMOD(dump_sparse) (A, "A scaled", Common) >= 0) ; return (TRUE) ; } #endif #endif Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_horzcat_worker.c0000644000175100001440000000472214552026002025045 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/t_cholmod_horzcat_worker //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_horzcat_worker) ( cholmod_sparse *C, // output matrix cholmod_sparse *A, // left matrix to concatenate cholmod_sparse *B // right matrix to concatenate ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Ap = A->p ; Int *Anz = A->nz ; Int *Ai = A->i ; #ifndef PATTERN Real *Ax = A->x ; #ifdef ZOMPLEX Real *Az = A->z ; #endif #endif bool apacked = A->packed ; Int ancol = A->ncol ; Int *Bp = B->p ; Int *Bnz = B->nz ; Int *Bi = B->i ; #ifndef PATTERN Real *Bx = B->x ; #ifdef ZOMPLEX Real *Bz = B->z ; #endif #endif bool bpacked = B->packed ; Int bncol = B->ncol ; Int *Cp = C->p ; Int *Ci = C->i ; #ifndef PATTERN Real *Cx = C->x ; #ifdef ZOMPLEX Real *Cz = C->z ; #endif #endif Int ncol = C->ncol ; //-------------------------------------------------------------------------- // C = [A , B] //-------------------------------------------------------------------------- Int pc = 0 ; // copy A as the first A->ncol columns of C for (Int j = 0 ; j < ancol ; j++) { // A(:,j) is the jth column of C Int p = Ap [j] ; Int pend = (apacked) ? (Ap [j+1]) : (p + Anz [j]) ; Cp [j] = pc ; for ( ; p < pend ; p++) { Ci [pc] = Ai [p] ; ASSIGN (Cx, Cz, pc, Ax, Az, p) ; pc++ ; } } // copy B as the next B->ncol columns of C for (Int j = 0 ; j < bncol ; j++) { // B(:,j) is the (ancol+j)th column of C Int p = Bp [j] ; Int pend = (bpacked) ? (Bp [j+1]) : (p + Bnz [j]) ; Cp [ancol + j] = pc ; for ( ; p < pend ; p++) { Ci [pc] = Bi [p] ; ASSIGN (Cx, Cz, pc, Bx, Bz, p) ; pc++ ; } } Cp [ncol] = pc ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_submatrix_worker.c0000644000175100001440000000670314552026002025412 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/t_cholmod_submatrix_worker //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_submatrix_worker) ( cholmod_sparse *C, cholmod_sparse *A, Int nr, Int nc, Int *cset, // set of column indices, duplicates OK Int *Head, Int *Rnext ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Ap = A->p ; Int *Ai = A->i ; Int *Anz = A->nz ; #ifndef PATTERN Real *Ax = A->x ; #ifdef ZOMPLEX Real *Az = A->z ; #endif #endif bool packed = A->packed ; Int *Cp = C->p ; Int *Ci = C->i ; #ifndef PATTERN Real *Cx = C->x ; #ifdef ZOMPLEX Real *Cz = C->z ; #endif #endif Int cncol = C->ncol ; //-------------------------------------------------------------------------- // C = A (rset, cset) //-------------------------------------------------------------------------- Int pc = 0 ; if (nr < 0) { //---------------------------------------------------------------------- // C = A (:,cset), where cset is not empty //---------------------------------------------------------------------- for (Int cj = 0 ; cj < cncol ; cj++) { // construct column cj of C, which is column j of A PRINT1 (("construct cj = j = "ID"\n", cj)) ; Int j = cset [cj] ; Cp [cj] = pc ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Ci [pc] = Ai [p] ; ASSIGN (Cx, Cz, pc, Ax, Az, p) ; pc++ ; ASSERT (pc <= C->nzmax) ; } } } else { //---------------------------------------------------------------------- // C = A (rset,cset), where rset is not empty but cset might be empty //---------------------------------------------------------------------- for (Int cj = 0 ; cj < cncol ; cj++) { // construct column cj of C, which is column j of A PRINT1 (("construct cj = "ID"\n", cj)) ; Int j = (nc < 0) ? cj : (cset [cj]) ; PRINT1 (("cj = "ID"\n", j)) ; Cp [cj] = pc ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { // row (Ai [p]) of A becomes multiple rows (ci) of C PRINT2 (("i: "ID" becomes: ", Ai [p])) ; for (Int ci = Head [Ai [p]] ; ci != EMPTY ; ci = Rnext [ci]) { PRINT3 ((""ID" ", ci)) ; Ci [pc] = ci ; ASSIGN (Cx, Cz, pc, Ax, Az, p) ; pc++ ; ASSERT (pc <= C->nzmax) ; } PRINT2 (("\n")) ; } } } // finalize the last column of C Cp [cncol] = pc ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_vertcat.c0000644000175100001440000000077514552026002023446 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_l_vertcat.c: int64_t version of cholmod_vertcat //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_vertcat.c" Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_vertcat_worker.c0000644000175100001440000000443114552026002025040 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/t_cholmod_vertcat_worker //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_vertcat_worker) ( cholmod_sparse *C, // output matrix cholmod_sparse *A, // top matrix to concatenate cholmod_sparse *B // bottom matrix to concatenate ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Ap = A->p ; Int *Anz = A->nz ; Int *Ai = A->i ; #ifndef PATTERN Real *Ax = A->x ; #ifdef ZOMPLEX Real *Az = A->z ; #endif #endif bool apacked = A->packed ; Int anrow = A->nrow ; Int *Bp = B->p ; Int *Bnz = B->nz ; Int *Bi = B->i ; #ifndef PATTERN Real *Bx = B->x ; #ifdef ZOMPLEX Real *Bz = B->z ; #endif #endif bool bpacked = B->packed ; Int *Cp = C->p ; Int *Ci = C->i ; #ifndef PATTERN Real *Cx = C->x ; #ifdef ZOMPLEX Real *Cz = C->z ; #endif #endif Int ncol = C->ncol ; //-------------------------------------------------------------------------- // C = [A ; B] //-------------------------------------------------------------------------- Int pc = 0 ; for (Int j = 0 ; j < ncol ; j++) { // append A(:,j) as the first part of C(:,j) Int p = Ap [j] ; Int pend = (apacked) ? (Ap [j+1]) : (p + Anz [j]) ; Cp [j] = pc ; for ( ; p < pend ; p++) { Ci [pc] = Ai [p] ; ASSIGN (Cx, Cz, pc, Ax, Az, p) ; pc++ ; } // append B(:,j) as the second part of C(:,j) p = Bp [j] ; pend = (bpacked) ? (Bp [j+1]) : (p + Bnz [j]) ; for ( ; p < pend ; p++) { Ci [pc] = Bi [p] + anrow ; ASSIGN (Cx, Cz, pc, Bx, Bz, p) ; pc++ ; } } Cp [ncol] = pc ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_ssmult_worker.c0000644000175100001440000000671014552026002024721 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/t_cholmod_ssmult_worker: sparse-times-sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_ssmult_worker) ( cholmod_sparse *C, cholmod_sparse *A, cholmod_sparse *B, cholmod_common *Common ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Ap = A->p ; Int *Anz = A->nz ; Int *Ai = A->i ; #ifndef PATTERN Real *Ax = A->x ; #ifdef ZOMPLEX Real *Az = A->z ; #endif #endif bool apacked = A->packed ; Int *Bp = B->p ; Int *Bnz = B->nz ; Int *Bi = B->i ; #ifndef PATTERN Real *Bx = B->x ; #ifdef ZOMPLEX Real *Bz = B->z ; #endif #endif bool bpacked = B->packed ; // get the size of C #ifdef ZOMPLEX Int nrow = A->nrow ; #endif Int ncol = B->ncol ; // get workspace #ifndef PATTERN Real *Wx = Common->Xwork ; // size nrow, unused if C is pattern #ifdef ZOMPLEX Real *Wz = Wx + nrow ; // only used for the zomplex case #endif #endif Int *Flag = Common->Flag ; // size nrow, Flag [0..nrow-1] < mark on input Int *Cp = C->p ; Int *Ci = C->i ; #ifndef PATTERN Real *Cx = C->x ; #ifdef ZOMPLEX Real *Cz = C->z ; #endif #endif //-------------------------------------------------------------------------- // C = A*B //-------------------------------------------------------------------------- Int pc = 0 ; for (Int j = 0 ; j < ncol ; j++) { // clear the Flag array CLEAR_FLAG (Common) ; Int mark = Common->mark ; // start column j of C Cp [j] = pc ; // for each nonzero B(k,j) in column j, do: Int pb = Bp [j] ; Int pbend = (bpacked) ? (Bp [j+1]) : (pb + Bnz [j]) ; for ( ; pb < pbend ; pb++) { // B(k,j) is nonzero Int k = Bi [pb] ; // b = Bx [pb] ; #ifndef PATTERN Real bx [2] ; #ifdef ZOMPLEX Real bz [1] ; #endif #endif ASSIGN (bx, bz, 0, Bx, Bz, pb) ; // add the nonzero pattern of A(:,k) to the pattern of C(:,j) // and scatter the values into W Int pa = Ap [k] ; Int paend = (apacked) ? (Ap [k+1]) : (pa + Anz [k]) ; for ( ; pa < paend ; pa++) { Int i = Ai [pa] ; if (Flag [i] != mark) { Flag [i] = mark ; Ci [pc++] = i ; } // W (i) += Ax [pa] * b ; MULTADD (Wx, Wz, i, Ax, Az, pa, bx, bz, 0) ; } } // gather the values into C(:,j) #ifndef PATTERN for (Int p = Cp [j] ; p < pc ; p++) { Int i = Ci [p] ; // Cx [p] = W (i) ; ASSIGN (Cx, Cz, p, Wx, Wz, i) ; // W (i) = 0 ; CLEAR (Wx, Wz, i) ; } #endif } Cp [ncol] = pc ; ASSERT (MAX (1,pc) == C->nzmax) ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_symmetry.c0000644000175100001440000000100014552026002023645 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_l_symmetry.c: int64_t version of cholmod_symmetry //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_symmetry.c" Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_norm_worker.c0000644000175100001440000002141114552026002024340 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/t_cholmod_norm_worker: compute norm of a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // The intermediate values and the final result are always computed in // double, even if the matrix is single precision. #include "cholmod_template.h" //------------------------------------------------------------------------------ // t_cholmod_norm_dense_worker //------------------------------------------------------------------------------ #ifndef PATTERN static double TEMPLATE (cholmod_norm_dense_worker) // return norm ( // input: cholmod_dense *X, // matrix to compute the norm of int norm, // type of norm: 0: inf. norm, 1: 1-norm, 2: 2-norm double *W // optional size-ncol workspace, always double ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int ncol = X->ncol ; Int nrow = X->nrow ; Int d = X->d ; Real *Xx = X->x ; #ifdef ZOMPLEX Real *Xz = X->z ; #endif double xnorm = 0 ; //-------------------------------------------------------------------------- // compute the norm //-------------------------------------------------------------------------- if (W != NULL) { //---------------------------------------------------------------------- // infinity-norm = max row sum, using stride-1 access of X //---------------------------------------------------------------------- DEBUG (for (Int i = 0 ; i < nrow ; i++) ASSERT (W [i] == 0)) ; // this is faster than stride-d, but requires O(nrow) workspace for (Int j = 0 ; j < ncol ; j++) { for (Int i = 0 ; i < nrow ; i++) { W [i] += ABS (Xx, Xz, i+j*d) ; } } for (Int i = 0 ; i < nrow ; i++) { double s = W [i] ; if ((isnan (s) || s > xnorm) && !isnan (xnorm)) { xnorm = s ; } W [i] = 0 ; } } else if (norm == 0) { //---------------------------------------------------------------------- // infinity-norm = max row sum, using stride-d access of X //---------------------------------------------------------------------- for (Int i = 0 ; i < nrow ; i++) { double s = 0 ; for (Int j = 0 ; j < ncol ; j++) { s += ABS (Xx, Xz, i+j*d) ; } if ((isnan (s) || s > xnorm) && !isnan (xnorm)) { xnorm = s ; } } } else if (norm == 1) { //---------------------------------------------------------------------- // 1-norm = max column sum //---------------------------------------------------------------------- for (Int j = 0 ; j < ncol ; j++) { double s = 0 ; for (Int i = 0 ; i < nrow ; i++) { s += ABS (Xx, Xz, i+j*d) ; } if ((isnan (s) || s > xnorm) && !isnan (xnorm)) { xnorm = s ; } } } else { //---------------------------------------------------------------------- // 2-norm = sqrt (sum (X.^2)) //---------------------------------------------------------------------- for (Int i = 0 ; i < nrow ; i++) { double s = ABS (Xx, Xz, i) ; xnorm += s*s ; } xnorm = sqrt (xnorm) ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (xnorm) ; } #endif //------------------------------------------------------------------------------ // t_cholmod_norm_sparse_worker //------------------------------------------------------------------------------ static double TEMPLATE (cholmod_norm_sparse_worker) // return norm ( // input: cholmod_sparse *A, // matrix to compute the norm of int norm, // type of norm: 0: inf. norm, 1: 1-norm, 2: 2-norm double *W // optional size-ncol workspace, always double ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Ap = A->p ; Int *Ai = A->i ; Int *Anz = A->nz ; #ifndef PATTERN Real *Ax = A->x ; #ifdef ZOMPLEX Real *Az = A->z ; #endif #endif Int ncol = A->ncol ; Int nrow = A->nrow ; bool packed = A->packed ; double anorm = 0 ; if (A->stype > 0) { //---------------------------------------------------------------------- // A is symmetric with upper triangular part stored //---------------------------------------------------------------------- // infinity-norm = 1-norm = max row/col sum for (Int j = 0 ; j < ncol ; j++) { Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; double s = ABS (Ax, Az, p) ; if (i == j) { W [i] += s ; } else if (i < j) { W [i] += s ; W [j] += s ; } } } } else if (A->stype < 0) { //---------------------------------------------------------------------- // A is symmetric with lower triangular part stored //---------------------------------------------------------------------- // infinity-norm = 1-norm = max row/col sum for (Int j = 0 ; j < ncol ; j++) { Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; double s = ABS (Ax, Az, p) ; if (i == j) { W [i] += s ; } else if (i > j) { W [i] += s ; W [j] += s ; } } } } else if (norm == 0) { //---------------------------------------------------------------------- // A is unsymmetric, compute the infinity-norm //---------------------------------------------------------------------- // infinity-norm = max row sum for (Int j = 0 ; j < ncol ; j++) { Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { W [Ai [p]] += ABS (Ax, Az, p) ; } } } else { //---------------------------------------------------------------------- // A is unsymmetric, compute the 1-norm //---------------------------------------------------------------------- // 1-norm = max column sum for (Int j = 0 ; j < ncol ; j++) { Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; double s ; #ifdef PATTERN { s = pend - p ; } #else { s = 0 ; for ( ; p < pend ; p++) { s += ABS (Ax, Az, p) ; } } #endif if ((isnan (s) || s > anorm) && !isnan (anorm)) { anorm = s ; } } } //-------------------------------------------------------------------------- // compute the max row sum //-------------------------------------------------------------------------- if (A->stype || norm == 0) { for (Int i = 0 ; i < nrow ; i++) { double s = W [i] ; if ((isnan (s) || s > anorm) && !isnan (anorm)) { anorm = s ; } W [i] = 0 ; } } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (anorm) ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_drop.c0000644000175100001440000000076414552026002022740 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_l_drop.c: int64_t version of cholmod_drop //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_drop.c" Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_ssmult.c0000644000175100001440000000077214552026002023322 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_l_ssmult.c: int64_t version of cholmod_ssmult //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_ssmult.c" Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_vertcat.c0000644000175100001440000001475114552026002023132 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_vertcat: vertical concatenation: C=[A;B] //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // Vertical concatenation, C = [A ; B] in MATLAB notation. // // A and B can be up/lo/unsym; C is unsymmetric and packed. // A and B must have the same number of columns. // C is sorted if both A and B are sorted. // // workspace: Iwork (max (A->nrow, A->ncol, B->nrow, B->ncol)). // allocates temporary copies of A and B if they are symmetric. // // A and B must have the same xtype and dtype, unless mode is 0. #include "cholmod_internal.h" #ifndef NGPL #ifndef NMATRIXOPS //------------------------------------------------------------------------------ // t_cholmod_vertcat_worker template //------------------------------------------------------------------------------ #define PATTERN #include "t_cholmod_vertcat_worker.c" #define DOUBLE #define REAL #include "t_cholmod_vertcat_worker.c" #define COMPLEX #include "t_cholmod_vertcat_worker.c" #define ZOMPLEX #include "t_cholmod_vertcat_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_vertcat_worker.c" #define COMPLEX #include "t_cholmod_vertcat_worker.c" #define ZOMPLEX #include "t_cholmod_vertcat_worker.c" //------------------------------------------------------------------------------ // cholmod_vertcat //------------------------------------------------------------------------------ cholmod_sparse *CHOLMOD(vertcat) ( // input: cholmod_sparse *A, // top matrix to concatenate cholmod_sparse *B, // bottom matrix to concatenate int mode, // 2: numerical (conj) if A and/or B are symmetric // 1: numerical (non-conj.) if A and/or B are symmetric // 0: pattern cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- cholmod_sparse *C = NULL, *A2 = NULL, *B2 = NULL ; RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_NULL (A, NULL) ; RETURN_IF_NULL (B, NULL) ; mode = RANGE (mode, 0, 2) ; if (A->xtype == CHOLMOD_PATTERN || B->xtype == CHOLMOD_PATTERN) { mode = 0 ; } bool values = (mode != 0) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, NULL) ; RETURN_IF_XTYPE_INVALID (B, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, NULL) ; if (A->ncol != B->ncol) { // A and B must have the same number of columns ERROR (CHOLMOD_INVALID, "A and B must have same # of columns") ; return (NULL) ; } if (mode != 0 && (A->xtype != B->xtype || A->dtype != B->dtype)) { // A and B must have the same xtype and dtype if mode is 0 ERROR (CHOLMOD_INVALID, "A and B must have same xtype and dtype") ; return (NULL) ; } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- Int anrow = A->nrow ; Int bnrow = B->nrow ; Int ncol = A->ncol ; CHOLMOD(allocate_work) (0, MAX3 (anrow, bnrow, ncol), 0, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (NULL) ; } //-------------------------------------------------------------------------- // convert A and/or B if necessary //-------------------------------------------------------------------------- // convert A to unsymmetric, if necessary A2 = NULL ; if (A->stype != 0) { // workspace: Iwork (max (A->nrow,A->ncol)) A2 = CHOLMOD(copy) (A, 0, mode, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (NULL) ; } A = A2 ; } // convert B to unsymmetric, if necessary B2 = NULL ; if (B->stype != 0) { // workspace: Iwork (max (B->nrow,B->ncol)) B2 = CHOLMOD(copy) (B, 0, mode, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory CHOLMOD(free_sparse) (&A2, Common) ; return (NULL) ; } B = B2 ; } //-------------------------------------------------------------------------- // allocate C //-------------------------------------------------------------------------- Int anz = CHOLMOD(nnz) (A, Common) ; Int bnz = CHOLMOD(nnz) (B, Common) ; Int nrow = anrow + bnrow ; Int nz = anz + bnz ; C = CHOLMOD(allocate_sparse) (nrow, ncol, nz, A->sorted && B->sorted, TRUE, 0, (values ? A->xtype : CHOLMOD_PATTERN) + A->dtype, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory CHOLMOD(free_sparse) (&A2, Common) ; CHOLMOD(free_sparse) (&B2, Common) ; return (NULL) ; } //-------------------------------------------------------------------------- // C = [A ; B] //-------------------------------------------------------------------------- switch ((C->xtype + C->dtype) % 8) { default: p_cholmod_vertcat_worker (C, A, B) ; break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_vertcat_worker (C, A, B) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_vertcat_worker (C, A, B) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_vertcat_worker (C, A, B) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_vertcat_worker (C, A, B) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_vertcat_worker (C, A, B) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_vertcat_worker (C, A, B) ; break ; } //-------------------------------------------------------------------------- // free the unsymmetric copies of A and B, and return C //-------------------------------------------------------------------------- CHOLMOD(free_sparse) (&A2, Common) ; CHOLMOD(free_sparse) (&B2, Common) ; return (C) ; } #endif #endif Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_sdmult.c0000644000175100001440000001370214552026002022765 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_sdmult: sparse-times-dense matrix //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // Sparse matrix times dense matrix: // Y = alpha*(A*X) + beta*Y or Y = alpha*(A'*X) + beta*Y, // where A is sparse and X and Y are dense. // // when using A, X has A->ncol columns and Y has A->nrow rows // when using A', X has A->nrow columns and Y has A->ncol rows // // workspace: none in Common. Temporary workspace of size 4*(X->nrow) is used // if A is stored in symmetric form and X has four columns or more. If the // workspace is not available, a slower method is used instead that requires // no workspace. // // transpose = 0: use A // otherwise, use A' (complex conjugate transpose) // // transpose is ignored if the matrix is symmetric or Hermitian. // (the array transpose A.' is not supported). // // Supports real, complex, and zomplex matrices, but the xtypes and dtypes of // A, X, and Y must all match. #include "cholmod_internal.h" #ifndef NGPL #ifndef NMATRIXOPS //------------------------------------------------------------------------------ // t_cholmod_sdmult_worker //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_sdmult_worker.c" #define COMPLEX #include "t_cholmod_sdmult_worker.c" #define ZOMPLEX #include "t_cholmod_sdmult_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_sdmult_worker.c" #define COMPLEX #include "t_cholmod_sdmult_worker.c" #define ZOMPLEX #include "t_cholmod_sdmult_worker.c" //------------------------------------------------------------------------------ // cholmod_sdmult //------------------------------------------------------------------------------ int CHOLMOD(sdmult) ( // input: cholmod_sparse *A, // sparse matrix to multiply int transpose, // use A if 0, otherwise use A' double alpha [2], // scale factor for A double beta [2], // scale factor for Y cholmod_dense *X, // dense matrix to multiply // input/output: cholmod_dense *Y, // resulting dense matrix cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (X, FALSE) ; RETURN_IF_NULL (Y, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (X, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (Y, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ; size_t ny = transpose ? A->ncol : A->nrow ; // required length of Y size_t nx = transpose ? A->nrow : A->ncol ; // required length of X if (X->nrow != nx || X->ncol != Y->ncol || Y->nrow != ny) { // X and/or Y have the wrong dimension ERROR (CHOLMOD_INVALID, "X and/or Y have wrong dimensions") ; return (FALSE) ; } if (A->xtype != X->xtype || A->xtype != Y->xtype || A->dtype != X->dtype || A->dtype != Y->dtype) { ERROR (CHOLMOD_INVALID, "A, X, and Y must have same xtype and dtype") ; return (FALSE) ; } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate workspace, if required //-------------------------------------------------------------------------- void *w = NULL ; size_t e = (A->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * ((A->xtype == CHOLMOD_REAL) ? 1 : 2) ; if (A->stype && X->ncol >= 4) { w = CHOLMOD(malloc) (4*nx, ex, Common) ; } if (Common->status < CHOLMOD_OK) { return (FALSE) ; // out of memory } //-------------------------------------------------------------------------- // Y = alpha*op(A)*X + beta*Y via template routine //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_sparse) (A, "A", Common) >= 0) ; DEBUG (CHOLMOD(dump_dense) (X, "X", Common)) ; DEBUG (if ((beta [0] != 0) || ((beta [1] != 0) && A->xtype != CHOLMOD_REAL)) CHOLMOD(dump_dense) (Y, "Y", Common)) ; float s_alpha [2] ; s_alpha [0] = (float) alpha [0] ; s_alpha [1] = (float) alpha [1] ; float s_beta [2] ; s_beta [0] = (float) beta [0] ; s_beta [1] = (float) beta [1] ; switch ((A->xtype + A->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_sdmult_worker (A, transpose, s_alpha, s_beta, X, Y, w) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_sdmult_worker (A, transpose, s_alpha, s_beta, X, Y, w) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_sdmult_worker (A, transpose, s_alpha, s_beta, X, Y, w) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_sdmult_worker (A, transpose, alpha, beta, X, Y, w) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_sdmult_worker (A, transpose, alpha, beta, X, Y, w) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_sdmult_worker (A, transpose, alpha, beta, X, Y, w) ; break ; } //-------------------------------------------------------------------------- // free workspace //-------------------------------------------------------------------------- CHOLMOD(free) (4*nx, ex, w, Common) ; DEBUG (CHOLMOD(dump_dense) (Y, "Y", Common)) ; return (TRUE) ; } #endif #endif Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_scale.c0000644000175100001440000000076714552026002023066 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_l_scale.c: int64_t version of cholmod_scale //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_scale.c" Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_drop.c0000644000175100001440000000715414552026002022425 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_drop: drop small entries from a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // Drop small entries from A, and entries in the ignored part of A if A // is symmetric. None of the matrix operations drop small numerical entries // from a matrix, except for this one. NaN's and Inf's are kept. // // workspace: none // // Supports any xtype (pattern, real, complex, zomplex) and any dtype // (single or double). #include "cholmod_internal.h" #ifndef NGPL #ifndef NMATRIXOPS //------------------------------------------------------------------------------ // t_cholmod_drop_worker //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_drop_worker.c" #define COMPLEX #include "t_cholmod_drop_worker.c" #define ZOMPLEX #include "t_cholmod_drop_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_drop_worker.c" #define COMPLEX #include "t_cholmod_drop_worker.c" #define ZOMPLEX #include "t_cholmod_drop_worker.c" //------------------------------------------------------------------------------ // cholmod_drop //------------------------------------------------------------------------------ int CHOLMOD(drop) ( // input: double tol, // keep entries with absolute value > tol // input/output: cholmod_sparse *A, // matrix to drop entries from cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; Common->status = CHOLMOD_OK ; ASSERT (CHOLMOD(dump_sparse) (A, "A predrop", Common) >= 0) ; //-------------------------------------------------------------------------- // drop small entries from A //-------------------------------------------------------------------------- switch ((A->xtype + A->dtype) % 8) { default: // pattern only: just drop entries outside the lower/upper part, // if A is symmetric if (A->stype > 0) { CHOLMOD(band_inplace) (0, A->ncol, 0, A, Common) ; } else if (A->stype < 0) { CHOLMOD(band_inplace) (-(A->nrow), 0, 0, A, Common) ; } break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_drop_worker (tol, A, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_drop_worker (tol, A, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_drop_worker (tol, A, Common) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_drop_worker (tol, A, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_drop_worker (tol, A, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_drop_worker (tol, A, Common) ; break ; } ASSERT (CHOLMOD(dump_sparse) (A, "A dropped", Common) >= 0) ; return (TRUE) ; } #endif #endif Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_drop_worker.c0000644000175100001440000001215614552026002024337 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/t_cholmod_drop_worker: drop small entries //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #include "cholmod_template.h" //------------------------------------------------------------------------------ // IF_DROP: macro to determine if A(i,j) is dropped //------------------------------------------------------------------------------ #ifdef REAL #define IF_DROP(Ax,Az,p,tol) \ double ax = (double) Ax [p] ; \ if (tol_is_zero ? (ax == 0) : (fabs (ax) <= tol)) #elif defined ( COMPLEX ) #define IF_DROP(Ax,Az,p,tol) \ double ax = (double) Ax [2*(p) ] ; \ double az = (double) Ax [2*(p)+1] ; \ if (tol_is_zero ? (ax == 0 && az == 0) : \ (SuiteSparse_config_hypot (ax, az) <= tol)) #elif defined ( ZOMPLEX ) #define IF_DROP(Ax,Az,p,tol) \ double ax = (double) Ax [p] ; \ double az = (double) Az [p] ; \ if (tol_is_zero ? (ax == 0 && az == 0) : \ (SuiteSparse_config_hypot (ax, az) <= tol)) #endif //------------------------------------------------------------------------------ // t_cholmod_drop_worker //------------------------------------------------------------------------------ static void TEMPLATE (cholmod_drop_worker) ( // input: double tol, // keep entries with absolute value > tol // input/output: cholmod_sparse *A, // matrix to drop entries from cholmod_common *Common ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Ap = A->p ; Int *Ai = A->i ; Real *Ax = A->x ; #ifdef ZOMPLEX Real *Az = A->z ; #endif Int *Anz = A->nz ; bool packed = A->packed ; Int ncol = A->ncol ; Int nz = 0 ; bool tol_is_zero = (tol == 0.) ; //-------------------------------------------------------------------------- // drop small numerical entries from A, and entries in ignored part //-------------------------------------------------------------------------- if (A->stype > 0) { //---------------------------------------------------------------------- // A is symmetric, with just upper triangular part stored //---------------------------------------------------------------------- for (Int j = 0 ; j < ncol ; j++) { Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; Ap [j] = nz ; for ( ; p < pend ; p++) { Int i = Ai [p] ; if (i > j) continue ; IF_DROP (Ax, Az, p, tol) continue ; // keep this entry Ai [nz] = i ; ASSIGN (Ax, Az, nz, Ax, Az, p) ; nz++ ; } } } else if (A->stype < 0) { //---------------------------------------------------------------------- // A is symmetric, with just lower triangular part stored //---------------------------------------------------------------------- for (Int j = 0 ; j < ncol ; j++) { Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; Ap [j] = nz ; for ( ; p < pend ; p++) { Int i = Ai [p] ; if (i < j) continue ; IF_DROP (Ax, Az, p, tol) continue ; // keep this entry Ai [nz] = i ; ASSIGN (Ax, Az, nz, Ax, Az, p) ; nz++ ; } } } else { //---------------------------------------------------------------------- // both parts of A present, just drop small entries //---------------------------------------------------------------------- for (Int j = 0 ; j < ncol ; j++) { Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; Ap [j] = nz ; for ( ; p < pend ; p++) { Int i = Ai [p] ; IF_DROP (Ax, Az, p, tol) continue ; // keep this entry Ai [nz] = i ; ASSIGN (Ax, Az, nz, Ax, Az, p) ; nz++ ; } } } // finalize the last column of A Ap [ncol] = nz ; // reduce A->i and A->x in size ASSERT (MAX (1,nz) <= A->nzmax) ; CHOLMOD(reallocate_sparse) (nz, A, Common) ; ASSERT (Common->status >= CHOLMOD_OK) ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX #undef IF_DROP Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_scale_worker.c0000644000175100001440000001131214552026002024453 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/t_cholmod_scale_worker: scale a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_scale_worker) ( // input: cholmod_dense *S, // scale factors (scalar or vector) int scale, // type of scaling to compute // input/output: cholmod_sparse *A // matrix to scale ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Ap = A->p ; Int *Anz = A->nz ; Int *Ai = A->i ; Real *Ax = A->x ; #ifdef ZOMPLEX Real *Az = A->z ; #endif bool packed = A->packed ; Int ncol = A->ncol ; Real *Sx = S->x ; #ifdef ZOMPLEX Real *Sz = S->z ; #endif //-------------------------------------------------------------------------- // scale the matrix //-------------------------------------------------------------------------- if (scale == CHOLMOD_ROW) { //---------------------------------------------------------------------- // A = diag(s)*A, row scaling //---------------------------------------------------------------------- for (Int j = 0 ; j < ncol ; j++) { Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; // t = S (i) * A (i,j) Real tx [2] ; #ifdef ZOMPLEX Real tz [1] ; #endif MULT (tx, tz, 0, Sx, Sz, i, Ax, Az, p) ; // A (i,j) = t ASSIGN (Ax, Az, p, tx, tz, 0) ; } } } else if (scale == CHOLMOD_COL) { //---------------------------------------------------------------------- // A = A*diag(s), column scaling //---------------------------------------------------------------------- for (Int j = 0 ; j < ncol ; j++) { // s = S (j) Real sx [2] ; #ifdef ZOMPLEX Real sz [1] ; #endif ASSIGN (sx, sz, 0, Sx, Sz, j) ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { // t = A (i,j) * s Real tx [2] ; #ifdef ZOMPLEX Real tz [1] ; #endif MULT (tx, tz, 0, Ax, Az, p, sx, sz, 0) ; // A (i,j) = t ASSIGN (Ax, Az, p, tx, tz, 0) ; } } } else if (scale == CHOLMOD_SYM) { //---------------------------------------------------------------------- // A = diag(s)*A*diag(s), symmetric scaling //---------------------------------------------------------------------- for (Int j = 0 ; j < ncol ; j++) { // s = S (j) Real sx [2] ; #ifdef ZOMPLEX Real sz [1] ; #endif ASSIGN (sx, sz, 0, Sx, Sz, j) ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; // t = A (i,j) * S (i) Real tx [2] ; #ifdef ZOMPLEX Real tz [1] ; #endif MULT (tx, tz, 0, Ax, Az, p, Sx, Sz, i) ; // A (i,j) = s * t MULT (Ax, Az, p, sx, sz, 0, tx, tz, 0) ; } } } else if (scale == CHOLMOD_SCALAR) { //---------------------------------------------------------------------- // A = s[0] * A, scalar scaling //---------------------------------------------------------------------- // s = S (0) Real sx [2] ; #ifdef ZOMPLEX Real sz [1] ; #endif ASSIGN (sx, sz, 0, Sx, Sz, 0) ; for (Int j = 0 ; j < ncol ; j++) { Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { // t = s * A (i,j) Real tx [2] ; #ifdef ZOMPLEX Real tz [1] ; #endif MULT (tx, tz, 0, sx, sz, 0, Ax, Az, p) ; // A (i,j) = t ASSIGN (Ax, Az, p, tx, tz, 0) ; } } } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_sdmult_worker.c0000644000175100001440000006171014552026002024703 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/t_cholmod_sdmult_worker //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #include "cholmod_template.h" //------------------------------------------------------------------------------ // ADVANCE macro //------------------------------------------------------------------------------ #ifdef REAL #define ADVANCE(x,z,d) x += d #elif defined (COMPLEX) #define ADVANCE(x,z,d) x += 2*d #else #define ADVANCE(x,z,d) x += d ; z += d #endif //------------------------------------------------------------------------------ // t_cholmod_sdmult_worker //------------------------------------------------------------------------------ static void TEMPLATE (cholmod_sdmult_worker) ( // input: cholmod_sparse *A, // sparse matrix to multiply int transpose, // use A if 0, or A' otherwise Real alpha [2], // scale factor for A Real beta [2], // scale factor for Y cholmod_dense *X, // dense matrix to multiply // input/output: cholmod_dense *Y, // resulting dense matrix // workspace Real *W // size 4*nx if needed, twice that for c/zomplex case ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Real yx [8], xx [8], ax [2] ; #ifdef ZOMPLEX Real yz [4], xz [4], az [1] ; Real betaz [1], alphaz [1] ; betaz [0] = beta [1] ; alphaz [0] = alpha [1] ; #endif size_t ny = transpose ? A->ncol : A->nrow ; // required length of Y #ifdef ZOMPLEX size_t nx = transpose ? A->nrow : A->ncol ; // required length of X #endif Int ncol = A->ncol ; Int *Ap = A->p ; Int *Anz = A->nz ; Int *Ai = A->i ; Real *Ax = A->x ; #ifdef ZOMPLEX Real *Az = A->z ; #endif bool packed = A->packed ; Real *Xx = X->x ; #ifdef ZOMPLEX Real *Xz = X->z ; #endif Real *Yx = Y->x ; #ifdef ZOMPLEX Real *Yz = Y->z ; #endif Int kcol = X->ncol ; size_t dy = Y->d ; size_t dx = X->d ; Real *w = W ; #ifdef ZOMPLEX Real *Wz = (W) ? W + 4*nx : W ; #endif //-------------------------------------------------------------------------- // Y = beta * Y //-------------------------------------------------------------------------- if (ENTRY_IS_ZERO (beta, betaz, 0)) { for (Int k = 0 ; k < kcol ; k++) { for (Int i = 0 ; i < ((Int) ny) ; i++) { // y [i] = 0 CLEAR (Yx, Yz, i) ; } // y += dy ADVANCE (Yx,Yz,dy) ; } } else if (!ENTRY_IS_ONE (beta, betaz, 0)) { for (Int k = 0 ; k < kcol ; k++) { for (Int i = 0 ; i < ((Int) ny) ; i++) { // y [i] *= beta [0] MULT (Yx,Yz,i, Yx,Yz,i, beta,betaz, 0) ; } // y += dy ADVANCE (Yx,Yz,dy) ; } } if (ENTRY_IS_ZERO (alpha, alphaz, 0)) { // nothing else to do return ; } //-------------------------------------------------------------------------- // Y += alpha * op(A) * X, where op(A)=A or A' //-------------------------------------------------------------------------- Yx = Y->x ; #ifdef ZOMPLEX Yz = Y->z ; #endif Int k = 0 ; if (A->stype == 0) { if (transpose) { //------------------------------------------------------------------ // Y += alpha * A' * x, unsymmetric case //------------------------------------------------------------------ if (kcol % 4 == 1) { for (Int j = 0 ; j < ncol ; j++) { // yj = 0 CLEAR (yx, yz, 0) ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { // yj += conj(Ax [p]) * x [Ai [p]] Int i = Ai [p] ; ASSIGN_CONJ (ax,az,0, Ax,Az,p) ; MULTADD (yx,yz,0, ax,az,0, Xx,Xz,i) ; } // y [j] += alpha [0] * yj MULTADD (Yx,Yz,j, alpha,alphaz,0, yx,yz,0) ; } // y += dy // x += dx ADVANCE (Yx,Yz,dy) ; ADVANCE (Xx,Xz,dx) ; k++ ; } else if (kcol % 4 == 2) { for (Int j = 0 ; j < ncol ; j++) { // yj0 = 0 // yj1 = 0 CLEAR (yx,yz,0) ; CLEAR (yx,yz,1) ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; // aij = conj (Ax [p]) ASSIGN_CONJ (ax,az,0, Ax,Az,p) ; // yj0 += aij * x [i ] // yj1 += aij * x [i+dx] MULTADD (yx,yz,0, ax,az,0, Xx,Xz,i) ; MULTADD (yx,yz,1, ax,az,0, Xx,Xz,i+dx) ; } // y [j ] += alpha [0] * yj0 // y [j+dy] += alpha [0] * yj1 MULTADD (Yx,Yz,j, alpha,alphaz,0, yx,yz,0) ; MULTADD (Yx,Yz,j+dy, alpha,alphaz,0, yx,yz,1) ; } // y += 2*dy // x += 2*dx ADVANCE (Yx,Yz,2*dy) ; ADVANCE (Xx,Xz,2*dx) ; k += 2 ; } else if (kcol % 4 == 3) { for (Int j = 0 ; j < ncol ; j++) { // yj0 = 0 // yj1 = 0 // yj2 = 0 CLEAR (yx,yz,0) ; CLEAR (yx,yz,1) ; CLEAR (yx,yz,2) ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; // aij = conj (Ax [p]) ASSIGN_CONJ (ax,az,0, Ax,Az,p) ; // yj0 += aij * x [i ] // yj1 += aij * x [i+ dx] // yj2 += aij * x [i+2*dx] MULTADD (yx,yz,0, ax,az,0, Xx,Xz,i) ; MULTADD (yx,yz,1, ax,az,0, Xx,Xz,i+dx) ; MULTADD (yx,yz,2, ax,az,0, Xx,Xz,i+2*dx) ; } // y [j ] += alpha [0] * yj0 // y [j+ dy] += alpha [0] * yj1 // y [j+2*dy] += alpha [0] * yj2 MULTADD (Yx,Yz,j, alpha,alphaz,0, yx,yz,0) ; MULTADD (Yx,Yz,j+dy, alpha,alphaz,0, yx,yz,1) ; MULTADD (Yx,Yz,j+2*dy, alpha,alphaz,0, yx,yz,2) ; } // y += 3*dy // x += 3*dx ADVANCE (Yx,Yz,3*dy) ; ADVANCE (Xx,Xz,3*dx) ; k += 3 ; } for ( ; k < kcol ; k += 4) { for (Int j = 0 ; j < ncol ; j++) { // yj0 = 0 // yj1 = 0 // yj2 = 0 // yj3 = 0 CLEAR (yx,yz,0) ; CLEAR (yx,yz,1) ; CLEAR (yx,yz,2) ; CLEAR (yx,yz,3) ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; // aij = conj(Ax [p]) ASSIGN_CONJ (ax,az,0, Ax,Az,p) ; // yj0 += aij * x [i ] // yj1 += aij * x [i+ dx] // yj2 += aij * x [i+2*dx] // yj3 += aij * x [i+3*dx] MULTADD (yx,yz,0, ax,az,0, Xx,Xz,i) ; MULTADD (yx,yz,1, ax,az,0, Xx,Xz,i+dx) ; MULTADD (yx,yz,2, ax,az,0, Xx,Xz,i+2*dx) ; MULTADD (yx,yz,3, ax,az,0, Xx,Xz,i+3*dx) ; } // y [j ] += alpha [0] * yj0 // y [j+ dy] += alpha [0] * yj1 // y [j+2*dy] += alpha [0] * yj2 // y [j+3*dy] += alpha [0] * yj3 MULTADD (Yx,Yz,j, alpha,alphaz,0, yx,yz,0) ; MULTADD (Yx,Yz,j+dy, alpha,alphaz,0, yx,yz,1) ; MULTADD (Yx,Yz,j+2*dy, alpha,alphaz,0, yx,yz,2) ; MULTADD (Yx,Yz,j+3*dy, alpha,alphaz,0, yx,yz,3) ; } // y += 4*dy // x += 4*dx ADVANCE (Yx,Yz,4*dy) ; ADVANCE (Xx,Xz,4*dx) ; } } else { //------------------------------------------------------------------ // Y += alpha * A * x, unsymmetric case //------------------------------------------------------------------ if (kcol % 4 == 1) { for (Int j = 0 ; j < ncol ; j++) { // xj = alpha [0] * x [j] MULT (xx,xz,0, alpha,alphaz,0, Xx,Xz,j) ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { // y [Ai [p]] += Ax [p] * xj Int i = Ai [p] ; MULTADD (Yx,Yz,i, Ax,Az,p, xx,xz,0) ; } } // y += dy // x += dx ADVANCE (Yx,Yz,dy) ; ADVANCE (Xx,Xz,dx) ; k++ ; } else if (kcol % 4 == 2) { for (Int j = 0 ; j < ncol ; j++) { // xj0 = alpha [0] * x [j ] // xj1 = alpha [0] * x [j+dx] MULT (xx,xz,0, alpha,alphaz,0, Xx,Xz,j) ; MULT (xx,xz,1, alpha,alphaz,0, Xx,Xz,j+dx) ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; // aij = Ax [p] ASSIGN (ax,az,0, Ax,Az,p) ; // y [i ] += aij * xj0 // y [i+dy] += aij * xj1 MULTADD (Yx,Yz,i, ax,az,0, xx,xz,0) ; MULTADD (Yx,Yz,i+dy, ax,az,0, xx,xz,1) ; } } // y += 2*dy // x += 2*dx ADVANCE (Yx,Yz,2*dy) ; ADVANCE (Xx,Xz,2*dx) ; k += 2 ; } else if (kcol % 4 == 3) { for (Int j = 0 ; j < ncol ; j++) { // xj0 = alpha [0] * x [j ] // xj1 = alpha [0] * x [j+ dx] // xj2 = alpha [0] * x [j+2*dx] MULT (xx,xz,0, alpha,alphaz,0, Xx,Xz,j) ; MULT (xx,xz,1, alpha,alphaz,0, Xx,Xz,j+dx) ; MULT (xx,xz,2, alpha,alphaz,0, Xx,Xz,j+2*dx) ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; // aij = Ax [p] ASSIGN (ax,az,0, Ax,Az,p) ; // y [i ] += aij * xj0 // y [i+ dy] += aij * xj1 // y [i+2*dy] += aij * xj2 MULTADD (Yx,Yz,i, ax,az,0, xx,xz,0) ; MULTADD (Yx,Yz,i+dy, ax,az,0, xx,xz,1) ; MULTADD (Yx,Yz,i+2*dy, ax,az,0, xx,xz,2) ; } } // y += 3*dy // x += 3*dx ADVANCE (Yx,Yz,3*dy) ; ADVANCE (Xx,Xz,3*dx) ; k += 3 ; } for ( ; k < kcol ; k += 4) { for (Int j = 0 ; j < ncol ; j++) { // xj0 = alpha [0] * x [j ] // xj1 = alpha [0] * x [j+ dx] // xj2 = alpha [0] * x [j+2*dx] // xj3 = alpha [0] * x [j+3*dx] MULT (xx,xz,0, alpha,alphaz,0, Xx,Xz,j) ; MULT (xx,xz,1, alpha,alphaz,0, Xx,Xz,j+dx) ; MULT (xx,xz,2, alpha,alphaz,0, Xx,Xz,j+2*dx) ; MULT (xx,xz,3, alpha,alphaz,0, Xx,Xz,j+3*dx) ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; // aij = Ax [p] ASSIGN (ax,az,0, Ax,Az,p) ; // y [i ] += aij * xj0 // y [i+ dy] += aij * xj1 // y [i+2*dy] += aij * xj2 // y [i+3*dy] += aij * xj3 MULTADD (Yx,Yz,i, ax,az,0, xx,xz,0) ; MULTADD (Yx,Yz,i+dy, ax,az,0, xx,xz,1) ; MULTADD (Yx,Yz,i+2*dy, ax,az,0, xx,xz,2) ; MULTADD (Yx,Yz,i+3*dy, ax,az,0, xx,xz,3) ; } } // y += 4*dy // x += 4*dx ADVANCE (Yx,Yz,4*dy) ; ADVANCE (Xx,Xz,4*dx) ; } } } else { //---------------------------------------------------------------------- // Y += alpha * A * x, symmetric case (upper/lower) //---------------------------------------------------------------------- // Only the upper/lower triangular part and the diagonal of A is used. // Since both x and y are written to in the innermost loop, this code // can experience cache bank conflicts if x is used directly. Thus, a // copy is made of x, four columns at a time, if x has four or more // columns. if (kcol % 4 == 1) { for (Int j = 0 ; j < ncol ; j++) { // yj = 0 CLEAR (yx,yz,0) ; // xj = alpha [0] * x [j] MULT (xx,xz,0, alpha,alphaz,0, Xx,Xz,j) ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; if (i == j) { // y [i] += Ax [p] * xj MULTADD (Yx,Yz,i, Ax,Az,p, xx,xz,0) ; } else if ((A->stype > 0 && i < j) || (A->stype < 0 && i > j)) { // aij = Ax [p] ASSIGN (ax,az,0, Ax,Az,p) ; // y [i] += aij * xj // yj += aij * x [i] MULTADD (Yx,Yz,i, ax,az,0, xx,xz,0) ; MULTADDCONJ (yx,yz,0, ax,az,0, Xx,Xz,i) ; } } // y [j] += alpha [0] * yj MULTADD (Yx,Yz,j, alpha,alphaz,0, yx,yz,0) ; } // y += dy // x += dx ADVANCE (Yx,Yz,dy) ; ADVANCE (Xx,Xz,dx) ; k++ ; } else if (kcol % 4 == 2) { for (Int j = 0 ; j < ncol ; j++) { // yj0 = 0 // yj1 = 0 CLEAR (yx,yz,0) ; CLEAR (yx,yz,1) ; // xj0 = alpha [0] * x [j ] // xj1 = alpha [0] * x [j+dx] MULT (xx,xz,0, alpha,alphaz,0, Xx,Xz,j) ; MULT (xx,xz,1, alpha,alphaz,0, Xx,Xz,j+dx) ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; if (i == j) { // aij = Ax [p] ASSIGN (ax,az,0, Ax,Az,p) ; // y [i ] += aij * xj0 // y [i+dy] += aij * xj1 MULTADD (Yx,Yz,i, ax,az,0, xx,xz,0) ; MULTADD (Yx,Yz,i+dy, ax,az,0, xx,xz,1) ; } else if ((A->stype > 0 && i < j) || (A->stype < 0 && i > j)) { // aij = Ax [p] ASSIGN (ax,az,0, Ax,Az,p) ; // y [i ] += aij * xj0 // y [i+dy] += aij * xj1 // yj0 += aij * x [i ] // yj1 += aij * x [i+dx] MULTADD (Yx,Yz,i, ax,az,0, xx,xz,0) ; MULTADD (Yx,Yz,i+dy, ax,az,0, xx,xz,1) ; MULTADDCONJ (yx,yz,0, ax,az,0, Xx,Xz,i) ; MULTADDCONJ (yx,yz,1, ax,az,0, Xx,Xz,i+dx) ; } } // y [j ] += alpha [0] * yj0 // y [j+dy] += alpha [0] * yj1 MULTADD (Yx,Yz,j, alpha,alphaz,0, yx,yz,0) ; MULTADD (Yx,Yz,j+dy, alpha,alphaz,0, yx,yz,1) ; } // y += 2*dy // x += 2*dx ADVANCE (Yx,Yz,2*dy) ; ADVANCE (Xx,Xz,2*dx) ; k += 2 ; } else if (kcol % 4 == 3) { for (Int j = 0 ; j < ncol ; j++) { // yj0 = 0 // yj1 = 0 // yj2 = 0 CLEAR (yx,yz,0) ; CLEAR (yx,yz,1) ; CLEAR (yx,yz,2) ; // xj0 = alpha [0] * x [j ] // xj1 = alpha [0] * x [j+ dx] // xj2 = alpha [0] * x [j+2*dx] MULT (xx,xz,0, alpha,alphaz,0, Xx,Xz,j) ; MULT (xx,xz,1, alpha,alphaz,0, Xx,Xz,j+dx) ; MULT (xx,xz,2, alpha,alphaz,0, Xx,Xz,j+2*dx) ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; if (i == j) { // aij = Ax [p] ASSIGN (ax,az,0, Ax,Az,p) ; // y [i ] += aij * xj0 // y [i+ dy] += aij * xj1 // y [i+2*dy] += aij * xj2 MULTADD (Yx,Yz,i, ax,az,0, xx,xz,0) ; MULTADD (Yx,Yz,i+dy, ax,az,0, xx,xz,1) ; MULTADD (Yx,Yz,i+2*dy, ax,az,0, xx,xz,2) ; } else if ((A->stype > 0 && i < j) || (A->stype < 0 && i > j)) { // aij = Ax [p] ASSIGN (ax,az,0, Ax,Az,p) ; // y [i ] += aij * xj0 // y [i+ dy] += aij * xj1 // y [i+2*dy] += aij * xj2 // yj0 += aij * x [i ] // yj1 += aij * x [i+ dx] // yj2 += aij * x [i+2*dx] MULTADD (Yx,Yz,i, ax,az,0, xx,xz,0) ; MULTADD (Yx,Yz,i+dy, ax,az,0, xx,xz,1) ; MULTADD (Yx,Yz,i+2*dy, ax,az,0, xx,xz,2) ; MULTADDCONJ (yx,yz,0, ax,az,0, Xx,Xz,i) ; MULTADDCONJ (yx,yz,1, ax,az,0, Xx,Xz,i+dx) ; MULTADDCONJ (yx,yz,2, ax,az,0, Xx,Xz,i+2*dx) ; } } // y [j ] += alpha [0] * yj0 // y [j+ dy] += alpha [0] * yj1 // y [j+2*dy] += alpha [0] * yj2 MULTADD (Yx,Yz,j, alpha,alphaz,0, yx,yz,0) ; MULTADD (Yx,Yz,j+dy, alpha,alphaz,0, yx,yz,1) ; MULTADD (Yx,Yz,j+2*dy, alpha,alphaz,0, yx,yz,2) ; } // y += 3*dy // x += 3*dx ADVANCE (Yx,Yz,3*dy) ; ADVANCE (Xx,Xz,3*dx) ; k += 3 ; } // copy four columns of X into W, and put in row form for ( ; k < kcol ; k += 4) { for (Int j = 0 ; j < ncol ; j++) { // w [4*j ] = x [j ] // w [4*j+1] = x [j+ dx] // w [4*j+2] = x [j+2*dx] // w [4*j+3] = x [j+3*dx] ASSIGN (w,Wz,4*j , Xx,Xz,j ) ; ASSIGN (w,Wz,4*j+1, Xx,Xz,j+dx ) ; ASSIGN (w,Wz,4*j+2, Xx,Xz,j+2*dx) ; ASSIGN (w,Wz,4*j+3, Xx,Xz,j+3*dx) ; } for (Int j = 0 ; j < ncol ; j++) { // yj0 = 0 // yj1 = 0 // yj2 = 0 // yj3 = 0 CLEAR (yx,yz,0) ; CLEAR (yx,yz,1) ; CLEAR (yx,yz,2) ; CLEAR (yx,yz,3) ; // xj0 = alpha [0] * w [4*j ] // xj1 = alpha [0] * w [4*j+1] // xj2 = alpha [0] * w [4*j+2] // xj3 = alpha [0] * w [4*j+3] MULT (xx,xz,0, alpha,alphaz,0, w,Wz,4*j) ; MULT (xx,xz,1, alpha,alphaz,0, w,Wz,4*j+1) ; MULT (xx,xz,2, alpha,alphaz,0, w,Wz,4*j+2) ; MULT (xx,xz,3, alpha,alphaz,0, w,Wz,4*j+3) ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; if (i == j) { // aij = Ax [p] ASSIGN (ax,az,0, Ax,Az,p) ; // y [i ] += aij * xj0 // y [i+ dy] += aij * xj1 // y [i+2*dy] += aij * xj2 // y [i+3*dy] += aij * xj3 MULTADD (Yx,Yz,i , ax,az,0, xx,xz,0) ; MULTADD (Yx,Yz,i+dy , ax,az,0, xx,xz,1) ; MULTADD (Yx,Yz,i+2*dy, ax,az,0, xx,xz,2) ; MULTADD (Yx,Yz,i+3*dy, ax,az,0, xx,xz,3) ; } else if ((A->stype > 0 && i < j) || (A->stype < 0 && i > j)) { // aij = Ax [p] ASSIGN (ax,az,0, Ax,Az,p) ; // y [i ] += aij * xj0 // y [i+ dy] += aij * xj1 // y [i+2*dy] += aij * xj2 // y [i+3*dy] += aij * xj3 // yj0 += aij * w [4*i ] // yj1 += aij * w [4*i+1] // yj2 += aij * w [4*i+2] // yj3 += aij * w [4*i+3] MULTADD (Yx,Yz,i, ax,az,0, xx,xz,0) ; MULTADD (Yx,Yz,i+dy, ax,az,0, xx,xz,1) ; MULTADD (Yx,Yz,i+2*dy, ax,az,0, xx,xz,2) ; MULTADD (Yx,Yz,i+3*dy, ax,az,0, xx,xz,3) ; MULTADDCONJ (yx,yz,0, ax,az,0, w,Wz,4*i) ; MULTADDCONJ (yx,yz,1, ax,az,0, w,Wz,4*i+1) ; MULTADDCONJ (yx,yz,2, ax,az,0, w,Wz,4*i+2) ; MULTADDCONJ (yx,yz,3, ax,az,0, w,Wz,4*i+3) ; } } // y [j ] += alpha [0] * yj0 // y [j+ dy] += alpha [0] * yj1 // y [j+2*dy] += alpha [0] * yj2 // y [j+3*dy] += alpha [0] * yj3 MULTADD (Yx,Yz,j , alpha,alphaz,0, yx,yz,0) ; MULTADD (Yx,Yz,j+dy , alpha,alphaz,0, yx,yz,1) ; MULTADD (Yx,Yz,j+2*dy, alpha,alphaz,0, yx,yz,2) ; MULTADD (Yx,Yz,j+3*dy, alpha,alphaz,0, yx,yz,3) ; } // y += 4*dy // x += 4*dx ADVANCE (Yx,Yz,4*dy) ; ADVANCE (Xx,Xz,4*dx) ; } } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX #undef ADVANCE Matrix/src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_submatrix.c0000644000175100001440000003455514552026002023504 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/MatrixOps/cholmod_submatrix: extract submatrix from a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // C = A (rset,cset), where C becomes length(rset)-by-length(cset) in // dimension. rset and cset can have duplicate entries. A can be symmetric; // C is returned as unsymmetric. C is packed. If the sorted flag is TRUE on // input, or rset is sorted and A is sorted, then C is sorted; otherwise C is // unsorted. // // A NULL rset or cset means "[ ]" in MATLAB notation. // If the length of rset or cset is negative, it denotes ":" in MATLAB notation. // // For permuting a matrix, this routine is an alternative to cholmod_ptranspose // (which permutes and transposes a matrix and can work on symmetric matrices). // // The time taken by this routine is O(A->nrow) if the Common workspace needs // to be initialized, plus O(C->nrow + C->ncol + nnz (A (:,cset))). Thus, if C // is small and the workspace is not initialized, the time can be dominated by // the call to cholmod_allocate_work. However, once the workspace is // allocated, subsequent calls take less time. // // workspace: Iwork (max (A->nrow + length (rset), length (cset))). // allocates temporary copy of C if it is to be returned sorted. // // Matrices of any xtype and dtype are supported. #include "cholmod_internal.h" #ifndef NGPL #ifndef NMATRIXOPS //------------------------------------------------------------------------------ // t_cholmod_submatrix_worker //------------------------------------------------------------------------------ #define PATTERN #include "t_cholmod_submatrix_worker.c" #define DOUBLE #define REAL #include "t_cholmod_submatrix_worker.c" #define COMPLEX #include "t_cholmod_submatrix_worker.c" #define ZOMPLEX #include "t_cholmod_submatrix_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_submatrix_worker.c" #define COMPLEX #include "t_cholmod_submatrix_worker.c" #define ZOMPLEX #include "t_cholmod_submatrix_worker.c" //------------------------------------------------------------------------------ // check_subset //------------------------------------------------------------------------------ // Check the rset or cset, and return TRUE if valid, FALSE if invalid static int check_subset (Int *set, Int len, Int n) { Int k ; if (set == NULL) { return (TRUE) ; } for (k = 0 ; k < len ; k++) { if (set [k] < 0 || set [k] >= n) { return (FALSE) ; } } return (TRUE) ; } //------------------------------------------------------------------------------ // cholmod_submatrix //------------------------------------------------------------------------------ cholmod_sparse *CHOLMOD(submatrix) // return C = A (rset,cset) ( // input: cholmod_sparse *A, // matrix to subreference Int *rset, // set of row indices, duplicates OK int64_t rsize, // size of rset, or -1 for ":" Int *cset, // set of column indices, duplicates OK int64_t csize, // size of cset, or -1 for ":" int mode, // 2: numerical (conj) if A is symmetric, // 1: numerical (non-conj.) if A is symmetric // 0: pattern int sorted, // if TRUE then return C with sorted columns cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- cholmod_sparse *C = NULL, *A2 = NULL ; RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_NULL (A, NULL) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, NULL) ; mode = RANGE (mode, 0, 2) ; if (A->xtype == CHOLMOD_PATTERN) { mode = 0 ; } bool values = (mode != 0) ; if (rsize > Int_max || csize > Int_max) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (NULL) ; } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // get problem size //-------------------------------------------------------------------------- Int ancol = A->ncol ; Int anrow = A->nrow ; Int nr = (Int) rsize ; Int nc = (Int) csize ; if (rset == NULL) { // nr = 0 denotes rset = [ ], nr < 0 denotes rset = 0:anrow-1 nr = (nr < 0) ? (-1) : 0 ; } if (cset == NULL) { // nr = 0 denotes cset = [ ], nr < 0 denotes cset = 0:ancol-1 nc = (nc < 0) ? (-1) : 0 ; } Int cnrow = (nr < 0) ? anrow : nr ; // negative rset means rset = 0:anrow-1 Int cncol = (nc < 0) ? ancol : nc ; // negative cset means cset = 0:ancol-1 //-------------------------------------------------------------------------- // check for quick return //-------------------------------------------------------------------------- if (nr < 0 && nc < 0) { //---------------------------------------------------------------------- // C = A (:,:), use cholmod_copy instead //---------------------------------------------------------------------- // workspace: Iwork (max (C->nrow,C->ncol)) PRINT1 (("submatrix C = A (:,:)\n")) ; C = CHOLMOD(copy) (A, 0, mode, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (NULL) ; } return (C) ; } //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- PRINT1 (("submatrix nr "ID" nc "ID" Cnrow "ID" Cncol "ID"" " Anrow "ID" Ancol "ID"\n", nr, nc, cnrow, cncol, anrow, ancol)) ; // s = MAX3 (anrow+MAX(0,nr), cncol, cnrow) ; int ok = TRUE ; size_t nr_size = (size_t) MAX (0, nr) ; size_t s = CHOLMOD(add_size_t) (A->nrow, MAX (0, nr_size), &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (NULL) ; } s = MAX3 (s, ((size_t) cncol), ((size_t) cnrow)) ; CHOLMOD(allocate_work) (anrow, s, 0, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (NULL) ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; //-------------------------------------------------------------------------- // check rset and cset //-------------------------------------------------------------------------- PRINT1 (("nr "ID" nc "ID"\n", nr, nc)) ; PRINT1 (("anrow "ID" ancol "ID"\n", anrow, ancol)) ; PRINT1 (("cnrow "ID" cncol "ID"\n", cnrow, cncol)) ; DEBUG (for (Int i = 0 ; i < nr ; i++) PRINT2 (("rset ["ID"] = "ID"\n", i, rset [i]))); DEBUG (for (Int i = 0 ; i < nc ; i++) PRINT2 (("cset ["ID"] = "ID"\n", i, cset [i]))); if (!check_subset (rset, nr, anrow)) { ERROR (CHOLMOD_INVALID, "invalid rset") ; return (NULL) ; } if (!check_subset (cset, nc, ancol)) { ERROR (CHOLMOD_INVALID, "invalid cset") ; return (NULL) ; } //-------------------------------------------------------------------------- // convert A if necessary //-------------------------------------------------------------------------- // convert A to unsymmetric, if necessary if (A->stype != 0) { // workspace: Iwork (max (A->nrow,A->ncol)) A2 = CHOLMOD(copy) (A, 0, mode, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (NULL) ; } A = A2 ; } ASSERT (A->stype == 0) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Ap = A->p ; Int *Anz = A->nz ; Int *Ai = A->i ; bool packed = A->packed ; //-------------------------------------------------------------------------- // get workspace //-------------------------------------------------------------------------- Int *Head = Common->Head ; // size anrow Int *Iwork = Common->Iwork ; Int *Rlen = Iwork ; // size anrow Int *Rnext = Iwork + anrow ; // size nr, not used if nr < 0 //-------------------------------------------------------------------------- // construct inverse of rset and compute nnz (C) //-------------------------------------------------------------------------- // C is sorted if A and rset are sorted, or if C has one row or less bool csorted = A->sorted || (cnrow <= 1) ; Int nnz = 0 ; if (nr < 0) { // C = A (:,cset) where cset = [ ] or cset is not empty ASSERT (IMPLIES (cncol > 0, cset != NULL)) ; for (Int cj = 0 ; cj < cncol ; cj++) { // construct column cj of C, which is column j of A Int j = cset [cj] ; nnz += (packed) ? (Ap [j+1] - Ap [j]) : MAX (0, Anz [j]) ; } } else { // C = A (rset,cset), where rset is not empty but cset might be empty // create link lists in reverse order to preserve natural order Int ilast = anrow ; for (Int ci = nr-1 ; ci >= 0 ; ci--) { // row i of A becomes row ci of C; add ci to ith link list Int i = rset [ci] ; Int head = Head [i] ; Rlen [i] = (head == EMPTY) ? 1 : (Rlen [i] + 1) ; Rnext [ci] = head ; Head [i] = ci ; if (i > ilast) { // row indices in columns of C will not be sorted csorted = FALSE ; } ilast = i ; } #ifndef NDEBUG for (Int i = 0 ; i < anrow ; i++) { Int k = 0 ; Int rlen = (Head [i] != EMPTY) ? Rlen [i] : -1 ; PRINT1 (("Row "ID" Rlen "ID": ", i, rlen)) ; for (Int ci = Head [i] ; ci != EMPTY ; ci = Rnext [ci]) { k++ ; PRINT2 ((""ID" ", ci)) ; } PRINT1 (("\n")) ; ASSERT (IMPLIES (Head [i] != EMPTY, k == Rlen [i])) ; } #endif // count entries in C for (Int cj = 0 ; cj < cncol ; cj++) { // count rows in column cj of C, which is column j of A Int j = (nc < 0) ? cj : (cset [cj]) ; Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { // row i of A becomes multiple rows (ci) of C Int i = Ai [p] ; ASSERT (i >= 0 && i < anrow) ; if (Head [i] != EMPTY) { nnz += Rlen [i] ; } } } } PRINT1 (("nnz (C) "ID"\n", nnz)) ; // rset and cset are now valid DEBUG (CHOLMOD(dump_subset) (rset, rsize, anrow, "rset", Common)) ; DEBUG (CHOLMOD(dump_subset) (cset, csize, ancol, "cset", Common)) ; //-------------------------------------------------------------------------- // allocate C //-------------------------------------------------------------------------- C = CHOLMOD(allocate_sparse) (cnrow, cncol, nnz, csorted, TRUE, 0, (values ? A->xtype : CHOLMOD_PATTERN) + A->dtype, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory for (Int i = 0 ; i < anrow ; i++) { Head [i] = EMPTY ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; CHOLMOD(free_sparse) (&A2, Common) ; return (NULL) ; } //-------------------------------------------------------------------------- // C = A (rset,cset) //-------------------------------------------------------------------------- if (nnz == 0) { // C has no entries Int *Cp = C->p ; for (Int cj = 0 ; cj <= cncol ; cj++) { Cp [cj] = 0 ; } } else { switch ((C->xtype + C->dtype) % 8) { default: p_cholmod_submatrix_worker (C, A, nr, nc, cset, Head, Rnext) ; break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_submatrix_worker (C, A, nr, nc, cset, Head, Rnext) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_submatrix_worker (C, A, nr, nc, cset, Head, Rnext) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_submatrix_worker (C, A, nr, nc, cset, Head, Rnext) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_submatrix_worker (C, A, nr, nc, cset, Head, Rnext) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_submatrix_worker (C, A, nr, nc, cset, Head, Rnext) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_submatrix_worker (C, A, nr, nc, cset, Head, Rnext) ; break ; } } //-------------------------------------------------------------------------- // clear workspace //-------------------------------------------------------------------------- for (Int ci = 0 ; ci < nr ; ci++) { Head [rset [ci]] = EMPTY ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; //-------------------------------------------------------------------------- // sort C, if requested //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_sparse) (C , "C before sort", Common) >= 0) ; if (sorted && !csorted) { CHOLMOD(sort) (C, Common) ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- CHOLMOD(free_sparse) (&A2, Common) ; ASSERT (CHOLMOD(dump_sparse) (C , "Final C", Common) >= 0) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; return (C) ; } #endif #endif Matrix/src/SuiteSparse/CHOLMOD/Utility/0000755000175100001440000000000014576344041017332 5ustar hornikusersMatrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_sym.c0000644000175100001440000001701414552026002024423 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_transpose_sym: symmetric permuted transpose //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // C = A' or A(p,p)' if A is symmetric. The output matrix C must already be // allocated, with enough space, and with the correct xtype (the same as A, // or CHOLMOD_PATTERN if only the pattern of C is to be computed. The dtype // of C and A must also match. A must be symmetric; and C is constructed as // symmetric with the C->stype = -(A->stype). C->packed must be true. // // For a method that creates C itself, see cholmod_ptranspose instead. // // workspace: at most 2*nrow #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ return (FALSE) ; \ } //------------------------------------------------------------------------------ // t_cholmod_transpose_sym_worker template //------------------------------------------------------------------------------ #define PATTERN #include "t_cholmod_transpose_sym_worker.c" #define DOUBLE #define REAL #include "t_cholmod_transpose_sym_worker.c" #define COMPLEX #include "t_cholmod_transpose_sym_worker.c" #define COMPLEX #define NCONJUGATE #include "t_cholmod_transpose_sym_worker.c" #define ZOMPLEX #include "t_cholmod_transpose_sym_worker.c" #define ZOMPLEX #define NCONJUGATE #include "t_cholmod_transpose_sym_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_transpose_sym_worker.c" #define COMPLEX #include "t_cholmod_transpose_sym_worker.c" #define COMPLEX #define NCONJUGATE #include "t_cholmod_transpose_sym_worker.c" #define ZOMPLEX #include "t_cholmod_transpose_sym_worker.c" #define ZOMPLEX #define NCONJUGATE #include "t_cholmod_transpose_sym_worker.c" //------------------------------------------------------------------------------ int CHOLMOD(transpose_sym) ( // input: cholmod_sparse *A, // input matrix int mode, // 2: numerical (conj) // 1: numerical (non-conj.) // <= 0: pattern (with diag) Int *Perm, // permutation for C=A(p,p)', or NULL // input/output: cholmod_sparse *C, // output matrix, must be allocated on input cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_SPARSE_MATRIX_INVALID (A, FALSE) ; RETURN_IF_NULL (C, FALSE) ; Common->status = CHOLMOD_OK ; mode = RANGE (mode, 0, 2) ; if (A->xtype == CHOLMOD_PATTERN || C->xtype == CHOLMOD_PATTERN) { // A or C is pattern: C must be pattern, so mode can only be zero mode = 0 ; } Int n = A->ncol ; if (A->stype == 0 || n != A->nrow) { ERROR (CHOLMOD_INVALID, "A must be symmetric") ; return (FALSE) ; } if ((C->xtype != ((mode == 0) ? CHOLMOD_PATTERN : A->xtype)) || (C->dtype != A->dtype) || (n != C->ncol) || (n != C->nrow) || (!C->packed)) { ERROR (CHOLMOD_INVALID, "C is invalid") ; return (FALSE) ; } ASSERT (CHOLMOD(dump_sparse) (A, "transpose_sym:A", Common) >= 0) ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- CHOLMOD(allocate_work) (0, ((Perm == NULL) ? 1: 2) * A->ncol, 0, Common) ; RETURN_IF_ERROR ; Int *Wi = (Int *) Common->Iwork ; // size n integers Int *Pinv = NULL ; memset (Wi, 0, n * sizeof (Int)) ; //-------------------------------------------------------------------------- // compute Pinv and make sure Perm is valid //-------------------------------------------------------------------------- if (Perm != NULL) { Pinv = Wi + n ; // size n CHOLMOD(set_empty) (Pinv, n) ; for (Int k = 0 ; k < n ; k++) { Int i = Perm [k] ; if ((i < 0 || i > n) || (Pinv [i] >= 0)) { ERROR (CHOLMOD_INVALID, "invalid permutation") ; return (FALSE) ; } Pinv [i] = k ; } } //-------------------------------------------------------------------------- // count the # of entries in each column of C //-------------------------------------------------------------------------- Int *Ap = (Int *) A->p ; Int *Ai = (Int *) A->i ; Int *Anz = (Int *) A->nz ; #include "t_cholmod_transpose_sym_template.c" //-------------------------------------------------------------------------- // compute the column pointers of C //-------------------------------------------------------------------------- if (CHOLMOD(cumsum) (C->p, Wi, n) > C->nzmax) { ERROR (CHOLMOD_INVALID, "C->nzmax is too small") ; return (FALSE) ; } memcpy (Wi, C->p, n * sizeof (Int)) ; //-------------------------------------------------------------------------- // compute the pattern and values of C //-------------------------------------------------------------------------- bool conj = (mode == 2) ; switch ((C->xtype + C->dtype) % 8) { default: p_cholmod_transpose_sym_worker (C, A, Pinv, Wi) ; break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_transpose_sym_worker (C, A, Pinv, Wi) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: if (conj) { cs_cholmod_transpose_sym_worker (C, A, Pinv, Wi) ; } else { cs_t_cholmod_transpose_sym_worker (C, A, Pinv, Wi) ; } break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: if (conj) { zs_cholmod_transpose_sym_worker (C, A, Pinv, Wi) ; } else { zs_t_cholmod_transpose_sym_worker (C, A, Pinv, Wi) ; } break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_transpose_sym_worker (C, A, Pinv, Wi) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: if (conj) { cd_cholmod_transpose_sym_worker (C, A, Pinv, Wi) ; } else { cd_t_cholmod_transpose_sym_worker (C, A, Pinv, Wi) ; } break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: if (conj) { zd_cholmod_transpose_sym_worker (C, A, Pinv, Wi) ; } else { zd_t_cholmod_transpose_sym_worker (C, A, Pinv, Wi) ; } break ; } //-------------------------------------------------------------------------- // finalize C and return result //-------------------------------------------------------------------------- C->sorted = (Perm == NULL) ; C->stype = - SIGN (A->stype) ; ASSERT (CHOLMOD(dump_sparse) (C, "transpose_sym:C", Common) >= 0) ; return (TRUE) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_transpose_unsym.c0000644000175100001440000000077614552026002024452 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_transpose_unsym: unsymmetric permuted transpose //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_transpose_unsym.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_xtype.c0000644000175100001440000000075714552026002022351 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_xtype.c: change xtype and/or dtype //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_change_xdtype.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_sort.c0000644000175100001440000000074014552026002022472 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_sort: sort a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_sort.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_dense_to_sparse_worker.c0000644000175100001440000000671414552026002026270 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_dense_to_sparse_worker: dense to sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_dense_to_sparse_worker) ( cholmod_sparse *C, // output sparse matrix, already allocated cholmod_dense *X // input dense matrix ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- ASSERT (X->nrow == C->nrow) ; ASSERT (X->ncol == C->ncol) ; ASSERT (X->d >= X->nrow) ; ASSERT (X->dtype == C->dtype) ; ASSERT (C->packed) ; ASSERT (C->sorted) ; ASSERT (C->stype == 0) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Real *Xx = (Real *) X->x ; #ifdef ZOMPLEX Real *Xz = (Real *) X->z ; #endif Int nrow = X->nrow ; Int ncol = X->ncol ; Int d = X->d ; Int *Cp = (Int *) C->p ; Int *Ci = (Int *) C->i ; Real *Cx = (Real *) C->x ; #ifdef ZOMPLEX Real *Cz = (Real *) C->z ; #endif bool pattern = (C->xtype == CHOLMOD_PATTERN) ; //-------------------------------------------------------------------------- // copy the dense matrix into the sparse matrix C //-------------------------------------------------------------------------- Int p = 0 ; if (pattern) { //---------------------------------------------------------------------- // copy just the pattern of the nonzeros of X into C //---------------------------------------------------------------------- for (Int j = 0, jx = 0 ; j < ncol ; j++, jx += d) { // log the start of C(:,j) Cp [j] = p ; // find the pattern of nonzeros in X(:,j) for (Int i = 0, q = jx ; i < nrow ; i++, q++) { if (ENTRY_IS_NONZERO (Xx, Xz, q)) { Ci [p++] = i ; } } } } else { //---------------------------------------------------------------------- // copy the pattern and values of nonzeros in X into C //---------------------------------------------------------------------- ASSERT (C->xtype == X->xtype) ; for (Int j = 0, jx = 0 ; j < ncol ; j++, jx += d) { // log the start of C(:,j) Cp [j] = p ; // find the pattern and values of nonzeros in X(:,j) for (Int i = 0, q = jx ; i < nrow ; i++, q++) { if (ENTRY_IS_NONZERO (Xx, Xz, q)) { ASSIGN (Cx, Cz, p, Xx, Xz, q) ; Ci [p++] = i ; } } } } //-------------------------------------------------------------------------- // log the end of the last column of C //-------------------------------------------------------------------------- Cp [ncol] = p ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_divcomplex.c0000644000175100001440000000136714552026002023350 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_divcomplex: complex divide //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" // Compute c = a/b int cholmod_divcomplex ( // input: double ar, double ai, // a (real, imaginary) double br, double bi, // b (real, imaginary) double *cr, double *ci // c (real, imaginary) ) { return (SuiteSparse_config_divcomplex (ar, ai, br, bi, cr, ci)) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_reallocate_triplet.c0000644000175100001440000000351014552026002025367 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_reallocate_triplet: reallocate triplet matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Change the max # of nonzeros that can be held in a triplet matrix T. #include "cholmod_internal.h" int CHOLMOD(reallocate_triplet) ( // input: size_t nznew, // new max # of nonzeros the triplet matrix can hold // input/output: cholmod_triplet *T, // triplet matrix to reallocate cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (T, FALSE) ; RETURN_IF_XTYPE_IS_INVALID (T->xtype, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // reallocate the triplet matrix //-------------------------------------------------------------------------- nznew = MAX (1, nznew) ; // ensure T can hold at least 1 entry int nint = 2 ; // reallocate both T->i and T->j CHOLMOD(realloc_multiple) (nznew, nint, T->xtype + T->dtype, &(T->i), &(T->j), &(T->x), &(T->z), &(T->nzmax), Common) ; //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (Common->status == CHOLMOD_OK) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_reallocate_factor.c0000644000175100001440000000365614552026002025175 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_reallocate_factor: reallocate a factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Change the max # of nonzeros that can be held in a factor L. // The factor must be simplicial. #include "cholmod_internal.h" int CHOLMOD(reallocate_factor) ( // input: size_t nznew, // new max # of nonzeros the factor matrix can hold // input/output: cholmod_factor *L, // factor to reallocate cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (L, FALSE) ; RETURN_IF_XTYPE_IS_INVALID (L->xtype, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; if (L->is_super) { ERROR (CHOLMOD_INVALID, "L invalid") ; return (FALSE) ; } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // reallocate the sparse matrix //-------------------------------------------------------------------------- nznew = MAX (1, nznew) ; // ensure L can hold at least 1 entry int nint = 1 ; // reallocate just L->i CHOLMOD(realloc_multiple) (nznew, nint, L->xtype + L->dtype, &(L->i), NULL, &(L->x), &(L->z), &(L->nzmax), Common) ; //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (Common->status == CHOLMOD_OK) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_score_comp.c0000644000175100001440000000075614552026002023643 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_score_comp: for sorting supernodes //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_score_comp.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_start.c0000644000175100001440000000075114552026002022327 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_start: start CHOLMOD (int32 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_start.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_set_empty.c0000644000175100001440000000116414552026002023525 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_set_empty: set an Int array to EMPTY //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" void CHOLMOD(set_empty) ( Int *S, // Int array of size n size_t n ) { for (size_t k = 0 ; k < n ; k++) { S [k] = EMPTY ; } } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_copy_triplet.c0000644000175100001440000000076114552026002024223 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_copy_triplet: copy a triplet matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_copy_triplet.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_sym_template.c0000644000175100001440000000733614552026002026324 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_transpose_sym_template: //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // C = A' or A(p,p)', either symbolic or numeric phase //------------------------------------------------------------------------------ // The including file must define or undef NUMERIC. // define NUMERIC: if computing values and pattern of C, undefine it if // computing just the column counts of C. //------------------------------------------------------------------------------ { if (Pinv == NULL) { //---------------------------------------------------------------------- // C = A', unpermuted transpose //---------------------------------------------------------------------- if (A->stype < 0) { //------------------------------------------------------------------ // C = A', A is symmetric lower, C will be symmetric upper //------------------------------------------------------------------ if (A->packed) { // A is packed #define PACKED #define LO #include "t_cholmod_transpose_sym_unpermuted.c" } else { // A is unpacked #define LO #include "t_cholmod_transpose_sym_unpermuted.c" } } else { //------------------------------------------------------------------ // C = A', A is symmetric upper, C will be symmetric lower //------------------------------------------------------------------ if (A->packed) { // A is packed #define PACKED #include "t_cholmod_transpose_sym_unpermuted.c" } else { // A is unpacked #include "t_cholmod_transpose_sym_unpermuted.c" } } } else { //---------------------------------------------------------------------- // C = A(p,p)', permuted transpose //---------------------------------------------------------------------- if (A->stype < 0) { //------------------------------------------------------------------ // C = A(p,p)', A is symmetric lower, C will be symmetric upper //------------------------------------------------------------------ if (A->packed) { // A is packed #define PACKED #define LO #include "t_cholmod_transpose_sym_permuted.c" } else { // A is unpacked #define LO #include "t_cholmod_transpose_sym_permuted.c" } } else { //------------------------------------------------------------------ // C = A(p,p)', A is symmetric upper, C will be symmetric lower //------------------------------------------------------------------ if (A->packed) { // A is packed #define PACKED #include "t_cholmod_transpose_sym_permuted.c" } else { // A is unpacked #include "t_cholmod_transpose_sym_permuted.c" } } } } #undef NUMERIC Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_allocate_triplet.c0000644000175100001440000000100114552026002024506 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_allocate_triplet: allocate triplet matrix (int32) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_allocate_triplet.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_ensure_dense.c0000644000175100001440000000100014552026002024150 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_ensure_dense: ensure dense matrix has a given size //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_ensure_dense.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_xtype.c0000644000175100001440000000076114552026002022657 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_xtype.c: change xtype and/or dtype //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_change_xdtype.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_free.c0000644000175100001440000000073614552026002022116 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_free: free (int32 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_free.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_reallocate_column.c0000644000175100001440000001723614552026002025213 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_reallocate_column: reallocate a column of a factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Expand the space for a single column L(:,j) of a simplicial factor. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status != CHOLMOD_OK) \ { \ /* out of memory; change L to simplicial symbolic */ \ CHOLMOD(change_factor) (CHOLMOD_PATTERN + L->dtype, L->is_ll, \ /* make L simplicial: */ FALSE, \ /* make L packed */ TRUE, \ /* make L monotonic: */ TRUE, L, Common) ; \ ERROR (CHOLMOD_OUT_OF_MEMORY, "out of memory") ; \ return (FALSE) ; \ } //------------------------------------------------------------------------------ // t_cholmod_reallocate_column_worker template //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_reallocate_column_worker.c" #define COMPLEX #include "t_cholmod_reallocate_column_worker.c" #define ZOMPLEX #include "t_cholmod_reallocate_column_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_reallocate_column_worker.c" #define COMPLEX #include "t_cholmod_reallocate_column_worker.c" #define ZOMPLEX #include "t_cholmod_reallocate_column_worker.c" //------------------------------------------------------------------------------ // cholmod_reallocate_column //------------------------------------------------------------------------------ int CHOLMOD(reallocate_column) ( // input: size_t j, // reallocate L(:,j) size_t need, // space in L(:,j) for this # of entries // input/output: cholmod_factor *L, // L factor modified, L(:,j) resized cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_FACTOR_INVALID (L, FALSE) ; Common->status = CHOLMOD_OK ; DEBUG (CHOLMOD(dump_factor) (L, "realloc col:L input", Common)) ; Int n = L->n ; if (L->xtype == CHOLMOD_PATTERN || L->is_super || j >= n) { ERROR (CHOLMOD_INVALID, "L not simplicial or j out of range") ; return (FALSE) ; } //-------------------------------------------------------------------------- // ensure need is in range 1:(n-j) and add slack space //-------------------------------------------------------------------------- need = MAX (need, 1) ; double slack = MAX (Common->grow1, 1.0) * ((double) need) + Common->grow2 ; slack = MIN (slack, (double) (n-j)) ; need = MAX (need, slack) ; need = MAX (need, 1) ; need = MIN (need, n-j) ; //-------------------------------------------------------------------------- // quick return if L(:,j) already big enough //-------------------------------------------------------------------------- Int *Lp = (Int *) L->p ; Int *Lnext = (Int *) L->next ; Int *Lprev = (Int *) L->prev ; size_t already_have = ((size_t) Lp [Lnext [j]] - (size_t) Lp [j]) ; if (already_have >= need) { return (TRUE) ; } //-------------------------------------------------------------------------- // check if enough space at the end of L->i, L->x, and L->z //-------------------------------------------------------------------------- Int tail = n ; Int new_nzmax_required = need + Lp [tail] ; if (new_nzmax_required > L->nzmax) { //---------------------------------------------------------------------- // out of space in L, so grow the entire factor to lnznew space //---------------------------------------------------------------------- double grow0 = Common->grow0 ; grow0 = (isnan (grow0) || grow0 < 1.2) ? 1.2 : grow0 ; double xnz = grow0 * (((double) L->nzmax) + ((double) need) + 1) ; size_t lnznew = (xnz > (double) SIZE_MAX) ? SIZE_MAX : (size_t) xnz ; CHOLMOD(reallocate_factor) (lnznew, L, Common) ; RETURN_IF_ERROR ; //---------------------------------------------------------------------- // count # of times any factor has been reallocated //---------------------------------------------------------------------- Common->nrealloc_factor++ ; //---------------------------------------------------------------------- // repack all columns so each column has some slack spce //---------------------------------------------------------------------- CHOLMOD(pack_factor) (L, Common) ; RETURN_IF_ERROR ; } //-------------------------------------------------------------------------- // move j to the end of the list //-------------------------------------------------------------------------- L->is_monotonic = FALSE ; // L is no longer monotonic Lnext [Lprev [j]] = Lnext [j] ; // remove j from is current place Lprev [Lnext [j]] = Lprev [j] ; Lnext [Lprev [tail]] = j ; // place it at the end of the list Lprev [j] = Lprev [tail] ; Lnext [j] = tail ; Lprev [tail] = j ; //-------------------------------------------------------------------------- // add space to L(:,j), now at the end of L //-------------------------------------------------------------------------- Int psrc = Lp [j] ; Int pdest = Lp [tail] ; Lp [j] = pdest ; Lp [tail] += need ; //-------------------------------------------------------------------------- // move L(:,j) to its new space at the end of L //-------------------------------------------------------------------------- switch ((L->xtype + L->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_reallocate_column_worker (L, j, pdest, psrc) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_reallocate_column_worker (L, j, pdest, psrc) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_reallocate_column_worker (L, j, pdest, psrc) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_reallocate_column_worker (L, j, pdest, psrc) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_reallocate_column_worker (L, j, pdest, psrc) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_reallocate_column_worker (L, j, pdest, psrc) ; break ; } //-------------------------------------------------------------------------- // count # of times any L(:,j) has been reallocated //-------------------------------------------------------------------------- Common->nrealloc_col++ ; //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- DEBUG (CHOLMOD(dump_factor) (L, "realloc col:L output", Common)) ; return (TRUE) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_copy_sparse.c0000644000175100001440000000075614552026002024041 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_copy_sparse: copy a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_copy_sparse.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_mult_size_t.c0000644000175100001440000000136714552026002024057 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_mult_size_t: multiply two size_t values //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" // multiply two size_t values and safely check for integer overflow size_t CHOLMOD(mult_size_t) (size_t a, size_t b, int *ok) { uint64_t x ; (*ok) = (*ok) && cholmod_mult_uint64_t (&x, (uint64_t) a, (uint64_t) b) ; return (((*ok) && x <= SIZE_MAX) ? ((size_t) x) : 0) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_eye.c0000644000175100001440000000073714552026002022273 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_eye: dense identity matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_eye.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_ptranspose.c0000644000175100001440000000075214552026002023704 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_ptranspose: permuted transpose //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_ptranspose.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_allocate_dense.c0000644000175100001440000000077514552026002024455 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_allocate_dense: allocate dense matrix (int64) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_allocate_dense.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_dbound.c0000644000175100001440000000126114552026002022442 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_dbound: bound diagonal of LDL (double, int32) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_BOUND_FUNCTION cholmod_dbound #define COMMON_BOUND (Common->dbound) #define COMMON_BOUNDS_HIT (Common->ndbounds_hit) #define Real double #define CHOLMOD_INT32 #include "t_cholmod_bound.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_free_triplet.c0000644000175100001440000000075714552026002024177 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_free_triplet: free triplet matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_free_triplet.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_spzeros.c0000644000175100001440000000240514552026002023220 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_spzeros: all-zero sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Create a sparse matrix with no entries, of any xtype or dtype. The A->stype // is zero (unsymmetric) but this can be modified by the caller to either +1 or // -1, and the matrix will still be valid. #include "cholmod_internal.h" cholmod_sparse *CHOLMOD(spzeros) // return a sparse matrix with no entries ( // input: size_t nrow, // # of rows size_t ncol, // # of columns size_t nzmax, // max # of entries the matrix can hold int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) { return (CHOLMOD(allocate_sparse) (nrow, ncol, nzmax, /* A is sorted: */ TRUE, /* A is packed: */ TRUE, /* A is unsymmetric: */ 0, xdtype, Common)) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_sbound.c0000644000175100001440000000126414552026002022777 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_sbound: bound diagonal of LDL (single, int64) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_BOUND_FUNCTION cholmod_l_sbound #define COMMON_BOUND (Common->sbound) #define COMMON_BOUNDS_HIT (Common->nsbounds_hit) #define Real float #define CHOLMOD_INT64 #include "t_cholmod_bound.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_2_worker.c0000644000175100001440000001035714552026002026115 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_change_factor_2_worker: change format of a factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" //------------------------------------------------------------------------------ // t_cholmod_change_factor_2_worker: changes a simplicial numeric factor //------------------------------------------------------------------------------ // The contents of the old L->(i,x,z) is copied/converted into Li2, Lx2, and // Lz2. static void TEMPLATE (cholmod_change_factor_2_worker) ( cholmod_factor *L, // factor to modify int to_packed, // if true: convert L to packed Int *Li2, // new space for L->i (if out_of_place is true) Real *Lx2, // new space for L->x (if out_of_place is true) Real *Lz2, // new space for L->z (if out_of_place is true) Int lnz, // max # of entries that Li2, Lx2, Lz2 can hold bool grow, // if true: add slack space to the new columns of L double grow1, // growth factor for each column double grow2, // growth factor for each column bool make_ll, // if true: convert LDL' to LL' bool out_of_place, // if true: convert L out-of-place using Li2, Lx2, Lz2 bool make_ldl, // if true: convert LL' to LDL' cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- ASSERT (!L->is_super) ; ASSERT (L->xtype != CHOLMOD_PATTERN) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int n = L->n ; Int *Lp = (Int *) L->p ; Int *Li = (Int *) L->i ; Real *Lx = (Real *) L->x ; #ifdef ZOMPLEX Real *Lz = (Real *) L->z ; #endif Int *Lnz = (Int *) L->nz ; //-------------------------------------------------------------------------- // initialize L->minor; will be set below to the min j where D(j,j) <= 0 //-------------------------------------------------------------------------- if (make_ll) { L->minor = n ; } //-------------------------------------------------------------------------- // convert the simplicial numeric L //-------------------------------------------------------------------------- if (out_of_place) { //---------------------------------------------------------------------- // L must be converted out of place //---------------------------------------------------------------------- // L is converted out-of-place, into the newly allocate space Li2, Lx2, // and Lz2. This occurs if L is to be packed and/or made monotonic, // but L is not already monotonic. ASSERT (Li2 != NULL) ; ASSERT (Lx2 != NULL) ; ASSERT (IMPLIES (L->xtype == CHOLMOD_ZOMPLEX, Lz2 != NULL)) ; #define OUT_OF_PLACE #include "t_cholmod_change_factor_2_template.c" } else if (to_packed) { //---------------------------------------------------------------------- // pack L, removing all slack space, in existing Li, Lx, and Lz space //---------------------------------------------------------------------- ASSERT (Li2 == NULL) ; ASSERT (Lx2 == NULL) ; ASSERT (Lz2 == NULL) ; #define TO_PACKED #include "t_cholmod_change_factor_2_template.c" } else { //---------------------------------------------------------------------- // in-place conversion of L: no entries are moved //---------------------------------------------------------------------- ASSERT (Li2 == NULL) ; ASSERT (Lx2 == NULL) ; ASSERT (Lz2 == NULL) ; #define IN_PLACE #include "t_cholmod_change_factor_2_template.c" } } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_sparse.c0000644000175100001440000001172614552026002024050 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_copy_sparse: copy a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Creates an exact copy of a sparse matrix. For making a copy with a change // of stype and/or copying the pattern of a numerical matrix, see cholmod_copy. // For changing the xtype and/or dtype, see cholmod_sparse_xtype. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_sparse) (&C, Common) ; \ return (NULL) ; \ } //------------------------------------------------------------------------------ // t_cholmod_copy_sparse_worker template //------------------------------------------------------------------------------ #define PATTERN #include "t_cholmod_copy_sparse_worker.c" #define DOUBLE #define REAL #include "t_cholmod_copy_sparse_worker.c" #define COMPLEX #include "t_cholmod_copy_sparse_worker.c" #define ZOMPLEX #include "t_cholmod_copy_sparse_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_copy_sparse_worker.c" #define COMPLEX #include "t_cholmod_copy_sparse_worker.c" #define ZOMPLEX #include "t_cholmod_copy_sparse_worker.c" cholmod_sparse *CHOLMOD(copy_sparse) // return new sparse matrix ( // input: cholmod_sparse *A, // sparse matrix to copy cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_SPARSE_MATRIX_INVALID (A, NULL) ; Common->status = CHOLMOD_OK ; ASSERT (CHOLMOD(dump_sparse) (A, "copy_sparse:A", Common) >= 0) ; //-------------------------------------------------------------------------- // allocate the copy C with the same characteristcs as A //-------------------------------------------------------------------------- cholmod_sparse *C = CHOLMOD(allocate_sparse) (A->nrow, A->ncol, A->nzmax, A->sorted, A->packed, A->stype, A->xtype + A->dtype, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // get the sizes of the entries //-------------------------------------------------------------------------- size_t ei = sizeof (Int) ; size_t e = (A->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * ((A->xtype == CHOLMOD_PATTERN) ? 0 : ((A->xtype == CHOLMOD_COMPLEX) ? 2 : 1)) ; size_t ez = e * ((A->xtype == CHOLMOD_ZOMPLEX) ? 1 : 0) ; //-------------------------------------------------------------------------- // copy the contents from A to C //-------------------------------------------------------------------------- size_t ncol = A->ncol ; // copy A->p (both packed and unpacked cases) memcpy (C->p, A->p, (ncol+1) * ei) ; if (A->packed) { // use memcpy when A is packed int64_t anz = CHOLMOD(nnz) (A, Common) ; if (A->i != NULL) memcpy (C->i, A->i, anz * ei) ; if (A->x != NULL) memcpy (C->x, A->x, anz * ex) ; if (A->z != NULL) memcpy (C->z, A->z, anz * ez) ; } else { // copy A->nz (for any xtype and dtype) if (A->nz != NULL) memcpy (C->nz, A->nz, ncol * ei) ; // use a template worker when A is unpacked to copy A->i, A->x, and A->z switch ((A->xtype + A->dtype) % 8) { default: p_cholmod_copy_sparse_worker (C, A) ; break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_copy_sparse_worker (C, A) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_copy_sparse_worker (C, A) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_copy_sparse_worker (C, A) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_copy_sparse_worker (C, A) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_copy_sparse_worker (C, A) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_copy_sparse_worker (C, A) ; break ; } } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_sparse) (C, "copy_sparse:C", Common) >= 0) ; return (C) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_reallocate_column.c0000644000175100001440000000100514552026002025166 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_reallocate_column: reallocate a column of a factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_reallocate_column.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_speye_worker.c0000644000175100001440000000314314552026002024231 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_speye_worker: sparse identity matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_speye_worker) ( cholmod_sparse *A ) { //-------------------------------------------------------------------------- // fill the matrix with all 1's on the diagonal //-------------------------------------------------------------------------- Int *Ap = (Int *) A->p ; Int *Ai = (Int *) A->i ; #ifndef PATTERN Real *Ax = (Real *) A->x ; #ifdef ZOMPLEX Real *Az = (Real *) A->z ; #endif #endif Int ncol = (Int) A->ncol ; Int nrow = (Int) A->nrow ; Int n = MIN (nrow, ncol) ; #ifndef PATTERN Real onex [2] = {1,0} ; #ifdef ZOMPLEX Real onez [1] = {0} ; #endif #endif for (Int k = 0 ; k < n ; k++) { // A(k,k) = 1 Ap [k] = k ; Ai [k] = k ; ASSIGN (Ax, Az, k, onex, onez, 0) ; } //-------------------------------------------------------------------------- // finish the rest of A->p for any remaining empty columns //-------------------------------------------------------------------------- for (Int k = n ; k <= ncol ; k++) { Ap [k] = n ; } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_free_dense.c0000644000175100001440000000371614552026002023620 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_free_dense: free dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" int CHOLMOD(free_dense) ( // input/output: cholmod_dense **X, // handle of dense matrix to free cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; if (X == NULL || (*X) == NULL) { // X is already freed; nothing to do return (TRUE) ; } //-------------------------------------------------------------------------- // get the sizes of the entries //-------------------------------------------------------------------------- size_t e = ((*X)->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * (((*X)->xtype == CHOLMOD_COMPLEX) ? 2 : 1) ; size_t ez = e * (((*X)->xtype == CHOLMOD_ZOMPLEX) ? 1 : 0) ; size_t nzmax = (*X)->nzmax ; //-------------------------------------------------------------------------- // free the two arrays //-------------------------------------------------------------------------- CHOLMOD(free) (nzmax, ex, (*X)->x, Common) ; CHOLMOD(free) (nzmax, ez, (*X)->z, Common) ; //-------------------------------------------------------------------------- // free the header and return result //-------------------------------------------------------------------------- (*X) = CHOLMOD(free) (1, sizeof (cholmod_dense), (*X), Common) ; return (TRUE) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_calloc.c0000644000175100001440000000111614552026002022423 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_calloc: calloc (int32 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_ALLOC_FUNCTION cholmod_calloc #define SUITESPARSE_ALLOC_FUNCTION SuiteSparse_calloc #define CHOLMOD_INT32 #include "t_cholmod_malloc.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_sparse_worker.c0000644000175100001440000000371614552026002025441 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_copy_sparse_worker: copy a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_copy_sparse_worker) ( cholmod_sparse *C, // output sparse matrix cholmod_sparse *A // sparse matrix to copy ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- // This worker is only used for the unpacked case ASSERT (!(A->packed)) ; //-------------------------------------------------------------------------- // get the A and C matrices //-------------------------------------------------------------------------- Int *Ap = (Int *) A->p ; Int *Anz = (Int *) A->nz ; Int *Ai = (Int *) A->i ; #ifndef PATTERN Real *Ax = (Real *) A->x ; #ifdef ZOMPLEX Real *Az = (Real *) A->z ; #endif #endif size_t ncol = A->ncol ; Int *Ci = (Int *) C->i ; #ifndef PATTERN Real *Cx = (Real *) C->x ; #ifdef ZOMPLEX Real *Cz = (Real *) C->z ; #endif #endif //-------------------------------------------------------------------------- // copy the contents from A to C //-------------------------------------------------------------------------- for (Int j = 0 ; j < ncol ; j++) { Int p = Ap [j] ; Int pend = p + Anz [j] ; for ( ; p < pend ; p++) { // C(i,j) = A (i,j) Ci [p] = Ai [p] ; ASSIGN (Cx, Cz, p, Ax, Az, p) ; } } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_band_worker.c0000644000175100001440000000651614552026002024017 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_band_worker: extract the band of a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_band_worker) ( cholmod_sparse *C, cholmod_sparse *A, int64_t k1, // keep entries in k1:k2 diagonals int64_t k2, bool ignore_diag // if true, exclude any diagonal entries ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int nrow = A->nrow ; Int ncol = A->ncol ; Int *Ap = (Int *) A->p ; Int *Anz = (Int *) A->nz ; Int *Ai = (Int *) A->i ; #ifndef PATTERN Real *Ax = (Real *) A->x ; #ifdef ZOMPLEX Real *Az = (Real *) A->z ; #endif #endif bool packed = A->packed ; Int *Cp = (Int *) C->p ; Int *Ci = (Int *) C->i ; #ifndef PATTERN Real *Cx = (Real *) C->x ; #ifdef ZOMPLEX Real *Cz = (Real *) C->z ; #endif #endif // columns outside of j1:j2 have no entries in diagonals k1:k2 Int j1 = MAX (k1, 0) ; Int j2 = MIN (k2+nrow, ncol) ; //-------------------------------------------------------------------------- // columns 0 to j1-1 are empty //-------------------------------------------------------------------------- memset (Cp, 0, j1 * sizeof (Int)) ; //-------------------------------------------------------------------------- // handle columns j1:j2-1 //-------------------------------------------------------------------------- Int cnz = 0 ; for (Int j = j1 ; j < j2 ; j++) { //---------------------------------------------------------------------- // get A(:,j) and log the start of C(:,j) //---------------------------------------------------------------------- // NOTE: C and A can be aliased Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; Cp [j] = cnz ; //---------------------------------------------------------------------- // extract entries in the band of A(:,j) //---------------------------------------------------------------------- for ( ; p < pend ; p++) { // A(i,j) is in the kth diagonal, where k = j-i Int i = Ai [p] ; Int k = j - i ; // check if k is in range k1:k2; if k is zero and diagonal is // ignored, then skip this entry if ((k >= k1) && (k <= k2) && !(k == 0 && ignore_diag)) { // C(i,j) = A(i,j) ASSIGN (Cx, Cz, cnz, Ax, Az, p) ; Ci [cnz++] = i ; } } } //-------------------------------------------------------------------------- // columns j2 to ncol-1 are empty //-------------------------------------------------------------------------- for (Int j = j2 ; j <= ncol ; j++) { Cp [j] = cnz ; } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_copy_dense.c0000644000175100001440000000075114552026002023322 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_copy_dense: copy a dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_copy_dense.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_band_nnz.c0000644000175100001440000000077114552026002022765 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_band_nnz: # of entries in a band of sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_band_nnz.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_hypot.c0000644000175100001440000000104614552026002022646 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_hypot: complex hypot //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" double cholmod_l_hypot (double x, double y) { return (SuiteSparse_config_hypot (x, y)) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_mult_size_t.c0000644000175100001440000000076214552026002023532 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_mult_size_t: multiply two size_t values //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_mult_size_t.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy.c0000644000175100001440000002677114552026002022501 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_copy: copy a sparse matrix (with change of stype) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Create a copy (C) of a sparse matrix A, with change of stype. // A has any xtype, dtype, and stype, and can be packed or unpacked. // C has the same xtype and dtype, but any stype (unless A is rectangular, // in which case C->stype must be zero). C is packed. // A->stype == 0: A is unsymmetric // A->stype < 0: A is symmetric with lower triangular part stored. Any entries // above the diagonal are ignored. // A->stype > 0: A is symmetric with upper triangular part stored. Any entries // below the diagonal are ignored. // C can be returned as numerical or pattern-only; and in the latter case, // the diagonal entries can be ignored. // In MATLAB: Using cholmod_copy: // --------- ---------------------------- // C = A ; A unsymmetric, C unsymmetric // C = tril (A) ; A unsymmetric, C sym lower // C = triu (A) ; A unsymmetric, C sym upper // U = triu (A) ; L = tril (U',-1) ; C = L+U ; A sym upper, C unsymmetric // C = triu (A)' ; A sym upper, C sym lower // C = triu (A) ; A sym upper, C sym upper // L = tril (A) ; U = triu (L',1) ; C = L+U ; A sym lower, C unsymmetric // C = tril (A) ; A sym lower, C sym lower // C = tril (A)' ; A sym lower, C sym upper // If A is complex or zomplex, then U' or L' above can be computed as an // array (non-conjugate) transpose, or a matrix (conjugate) transpose. // The mode parameter: // 2 numerical, with conjugate transpose // 1 numerical, with non-conjugate transpose // 0 pattern, keeping the diagonal // -1 pattern, remove the diagonal // -2 pattern, and add 50% + n extra space to C // as elbow room for AMD and CAMD, when converting // a symmetric matrix A to an unsymmetric matrix C // workspace: Iwork (max (nrow,ncol)) #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_sparse) (&C, Common) ; \ return (NULL) ; \ } //------------------------------------------------------------------------------ // t_cholmod_copy_worker template //------------------------------------------------------------------------------ #define PATTERN #include "t_cholmod_copy_worker.c" #define DOUBLE #define REAL #include "t_cholmod_copy_worker.c" #define COMPLEX #include "t_cholmod_copy_worker.c" #define COMPLEX #define NCONJUGATE #include "t_cholmod_copy_worker.c" #define ZOMPLEX #include "t_cholmod_copy_worker.c" #define ZOMPLEX #define NCONJUGATE #include "t_cholmod_copy_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_copy_worker.c" #define COMPLEX #include "t_cholmod_copy_worker.c" #define COMPLEX #define NCONJUGATE #include "t_cholmod_copy_worker.c" #define ZOMPLEX #include "t_cholmod_copy_worker.c" #define ZOMPLEX #define NCONJUGATE #include "t_cholmod_copy_worker.c" //------------------------------------------------------------------------------ cholmod_sparse *CHOLMOD(copy) ( // input: cholmod_sparse *A, // input matrix, not modified int stype, // stype of C int mode, // 2: numerical (conj) // 1: numerical (non-conj.) // 0: pattern (with diag) // -1: pattern (remove diag) // -2: pattern (remove diag; add ~50% extra space in C) cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_SPARSE_MATRIX_INVALID (A, NULL) ; Common->status = CHOLMOD_OK ; cholmod_sparse *C = NULL ; Int nrow = A->nrow ; Int ncol = A->ncol ; int astype = SIGN (A->stype) ; stype = SIGN (stype) ; if ((stype || astype) && nrow != ncol) { ERROR (CHOLMOD_INVALID, "matrix invalid") ; return (NULL) ; } //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- mode = RANGE (mode, -2, 2) ; bool ignore_diag = (mode < 0) ; bool up = (astype > 0) ; bool lo = (astype < 0) ; bool values = (mode > 0) && (A->xtype != CHOLMOD_PATTERN) ; bool conj = (mode == 2) ; //-------------------------------------------------------------------------- // copy the matrix //-------------------------------------------------------------------------- if (astype == stype) { //---------------------------------------------------------------------- // no change of stype, but possible remove of diagonal //---------------------------------------------------------------------- C = CHOLMOD(band) (A, -nrow, ncol, mode, Common) ; RETURN_IF_ERROR ; } else if (astype == 0) { //---------------------------------------------------------------------- // A is unsymmetric; C is symmetric upper or lower //---------------------------------------------------------------------- size_t nlo = (stype > 0) ? 0 : (-nrow) ; size_t nup = (stype > 0) ? ncol : 0 ; C = CHOLMOD(band) (A, nlo, nup, mode, Common) ; RETURN_IF_ERROR ; C->stype = stype ; } else if (astype == -stype) { //---------------------------------------------------------------------- // both A and C are symmetric, but opposite, so a transpose is needed //---------------------------------------------------------------------- C = CHOLMOD(transpose) (A, mode, Common) ; RETURN_IF_ERROR ; if (ignore_diag) { // remove diagonal, if requested CHOLMOD(band_inplace) (-nrow, ncol, -1, C, Common) ; RETURN_IF_ERROR ; } } else { //---------------------------------------------------------------------- // A is symmetric and C is unsymmetric //---------------------------------------------------------------------- Int *Ap = (Int *) A->p ; Int *Anz = (Int *) A->nz ; Int *Ai = (Int *) A->i ; bool packed = A->packed ; //---------------------------------------------------------------------- // allocate workspace //---------------------------------------------------------------------- ASSERT (nrow == ncol) ; CHOLMOD(allocate_work) (0, ncol, 0, Common) ; RETURN_IF_ERROR ; Int *Wj = (Int *) Common->Iwork ; //---------------------------------------------------------------------- // count entries in each column of C //---------------------------------------------------------------------- memset (Wj, 0, ncol * sizeof (Int)) ; size_t cnz = 0 ; for (Int j = 0 ; j < ncol ; j++) { Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; if (i == j) { // diagonal entry A(i,i) if (ignore_diag) continue ; Wj [j]++ ; cnz++ ; } else if ((up && i < j) || (lo && i > j)) { // A(i,j) is placed in both upper and lower part of C Wj [j]++ ; Wj [i]++ ; cnz += 2 ; } } } //---------------------------------------------------------------------- // allocate C //---------------------------------------------------------------------- size_t cnzmax = cnz + ((mode == -2) ? (cnz/2 + ncol) : 0) ; C = CHOLMOD(allocate_sparse) (nrow, ncol, cnzmax, /* C is sorted if A is sorted: */ A->sorted, /* C is packed: */ TRUE, /* C stype: */ 0, (values ? A->xtype : CHOLMOD_PATTERN) + A->dtype, Common) ; RETURN_IF_ERROR ; //---------------------------------------------------------------------- // Cp = cumsum of column counts (Wj), and then copy Cp back to Wj //---------------------------------------------------------------------- Int *Cp = C->p ; CHOLMOD(cumsum) (Cp, Wj, ncol) ; memcpy (Wj, Cp, ncol * sizeof (Int)) ; //---------------------------------------------------------------------- // construct C via the template function //---------------------------------------------------------------------- switch ((C->xtype + C->dtype) % 8) { default: p_cholmod_copy_worker (C, A, ignore_diag, Common) ; break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_copy_worker (C, A, ignore_diag, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: if (conj) { cs_cholmod_copy_worker (C, A, ignore_diag, Common) ; } else { cs_t_cholmod_copy_worker (C, A, ignore_diag, Common) ; } break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: if (conj) { zs_cholmod_copy_worker (C, A, ignore_diag, Common) ; } else { zs_t_cholmod_copy_worker (C, A, ignore_diag, Common) ; } break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_copy_worker (C, A, ignore_diag, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: if (conj) { cd_cholmod_copy_worker (C, A, ignore_diag, Common) ; } else { cd_t_cholmod_copy_worker (C, A, ignore_diag, Common) ; } break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: if (conj) { zd_cholmod_copy_worker (C, A, ignore_diag, Common) ; } else { zd_t_cholmod_copy_worker (C, A, ignore_diag, Common) ; } break ; } } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- DEBUG (size_t nnzdiag = CHOLMOD(dump_sparse) (C, "copy:C", Common)) ; ASSERT (IMPLIES (ignore_diag, nnzdiag == 0)) ; return (C) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_ptranspose.c0000644000175100001440000000751614552026002023721 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_ptranspose: permuted transpose //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // C = A' or A(p,p)' if A is symmetric. C = A', A(:,f)' or A(p,f)' if A is // unsymmetric. // // workspace: at most nrow+ncol #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_sparse) (&C, Common) ; \ return (NULL) ; \ } cholmod_sparse *CHOLMOD(ptranspose) ( // input: cholmod_sparse *A, // input matrix int mode, // 2: numerical (conj) // 1: numerical (non-conj.) // <= 0: pattern (with diag) Int *Perm, // permutation for C=A(p,f)' or C=A(p,p)', or NULL Int *fset, // a list of column indices in range 0:A->ncol-1 size_t fsize, // # of entries in fset cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_SPARSE_MATRIX_INVALID (A, NULL) ; Common->status = CHOLMOD_OK ; mode = RANGE (mode, -1, 2) ; //-------------------------------------------------------------------------- // count # of entries in C //-------------------------------------------------------------------------- Int cnz = 0 ; if ((A->stype == 0) && (fset != NULL)) { // C = A(p,f)' or A(:,f)' where A is unsymmetric and fset is present Int ncol = A->ncol ; if (A->packed) { Int *Ap = (Int *) A->p ; for (Int k = 0 ; k < fsize ; k++) { Int j = fset [k] ; if (j < 0 || j >= ncol) continue ; cnz += (Ap [j+1] - Ap [j]) ; } } else { Int *Anz = (Int *) A->nz ; for (Int k = 0 ; k < fsize ; k++) { Int j = fset [k] ; if (j < 0 || j >= ncol) continue ; cnz += Anz [j] ; } } } else { // C = A(p,p)' A is symmetric, or C=A' where A is any matrix cnz = CHOLMOD(nnz) (A, Common) ; } //-------------------------------------------------------------------------- // allocate C //-------------------------------------------------------------------------- cholmod_sparse *C = CHOLMOD(allocate_sparse) (A->ncol, A->nrow, cnz, /* C is sorted: */ TRUE, /* C is packed */ TRUE, /* C has the opposite stype as A: */ -(A->stype), ((mode > 0) ? A->xtype : CHOLMOD_PATTERN) + A->dtype, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // construct C //-------------------------------------------------------------------------- if (A->stype != 0) { // C = A (p,p)' or A' when A is symmetric (upper or lower) CHOLMOD(transpose_sym) (A, mode, Perm, C, Common) ; } else { // C = A (p,f)' or A(:,f)' when A is unsymmetric CHOLMOD(transpose_unsym) (A, mode, Perm, fset, fsize, C, Common) ; } RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (C) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_sym_unpermuted.c0000644000175100001440000000334214552026002026672 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_transpose_sym_unpermuted //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // C = A' where A and C are symmetric //------------------------------------------------------------------------------ // The including file must define or undef PACKED, NUMERIC, and LO. // define PACKED: if A->packed is true, undefine if A->packed is false // define LO: if A is symmetric lower, undefine it if A is upper // define NUMERIC: if computing values and pattern of C, undefine it if // computing just the column counts of C. //------------------------------------------------------------------------------ { for (Int j = 0 ; j < n ; j++) { Int pa = Ap [j] ; #ifdef PACKED Int paend = Ap [j+1] ; #else Int paend = pa + Anz [j] ; #endif for ( ; pa < paend ; pa++) { // get A(i,j) Int i = Ai [pa] ; #ifdef LO // A is symmetric lower, C is symmetric upper if (i < j) continue ; #else // A is symmetric upper, C is symmetric lower if (i > j) continue ; #endif // C(j,i) = conj (A(i,j)) #ifdef NUMERIC Int pc = #endif Wi [i]++ ; #ifdef NUMERIC ASSIGN_CONJ_OR_NCONJ (Cx, Cz, pc, Ax, Az, pa) ; Ci [pc] = j ; #endif } } } #undef PACKED #undef LO Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_transpose_sym.c0000644000175100001440000000077214552026002024416 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_transpose_sym: symmetric permuted transpose //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_transpose_sym.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_version.c0000644000175100001440000000251714552026002023204 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_version: CHOLMOD version //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" int CHOLMOD(version) // returns CHOLMOD_VERSION ( // if version is not NULL, then cholmod_version returns its contents as: // version [0] = CHOLMOD_MAIN_VERSION // version [1] = CHOLMOD_SUB_VERSION // version [2] = CHOLMOD_SUBSUB_VERSION int version [3] ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- if (version == NULL) { return (CHOLMOD_VERSION) ; } //-------------------------------------------------------------------------- // return the full version of CHOLMOD //-------------------------------------------------------------------------- version [0] = CHOLMOD_MAIN_VERSION ; version [1] = CHOLMOD_SUB_VERSION ; version [2] = CHOLMOD_SUBSUB_VERSION ; return (CHOLMOD_VERSION) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_dense_nnz.c0000644000175100001440000000076314552026002023160 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_dense_nnz: # of nonzeros in a dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_dense_nnz.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_dense_to_sparse.c0000644000175100001440000000100214552026002024650 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_dense_to_sparse: convert a dense matrix to sparse //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_dense_to_sparse.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_allocate_work.c0000644000175100001440000000131414552026002024327 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_allocate_work: alloc workspace (double, int64) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" int cholmod_l_allocate_work ( // input: size_t nrow, size_t iworksize, size_t xworksize, cholmod_common *Common ) { return (cholmod_l_alloc_work (nrow, iworksize, xworksize, CHOLMOD_DOUBLE, Common)) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_eye_worker.c0000644000175100001440000000224614552026002023671 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_eye_worker: dense identity matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_eye_worker) ( cholmod_dense *X ) { //-------------------------------------------------------------------------- // fill the matrix with all 1's on the diagonal //-------------------------------------------------------------------------- Real *Xx = (Real *) X->x ; #ifdef ZOMPLEX Real *Xz = (Real *) X->z ; #endif Int nrow = (Int) X->nrow ; Int ncol = (Int) X->ncol ; Int n = MIN (nrow, ncol) ; Real onex [2] = {1,0} ; #ifdef ZOMPLEX Real onez [1] = {0} ; #endif for (Int k = 0 ; k < n ; k++) { // X(k,k) = 1 ASSIGN (Xx, Xz, k + k*nrow, onex, onez, 0) ; } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_ones.c0000644000175100001440000000074214552026002022136 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_ones: dense matrix of all ones //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_ones.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_aat.c0000644000175100001440000000074514552026002021742 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_aat: compute AA' or A(:,f)*A(:,f)' //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_aat.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_spzeros.c0000644000175100001440000000074614552026002022703 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_spzeros: all-zero sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_spzeros.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_add_worker.c0000644000175100001440000001141314552026002023633 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_add_worker: C = alpha*A + beta*B //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" //------------------------------------------------------------------------------ // cholmod_add: C = alpha*A + beta*B //------------------------------------------------------------------------------ static void TEMPLATE (cholmod_add_worker) ( cholmod_sparse *C, cholmod_sparse *A, cholmod_sparse *B, double alpha [2], double beta [2], cholmod_common *Common ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- ASSERT (A->sorted) ; ASSERT (B->sorted) ; ASSERT (C->sorted) ; ASSERT (A->stype == B->stype) ; ASSERT (A->stype == C->stype) ; ASSERT (C->packed) ; bool upper = (A->stype > 0) ; bool lower = (A->stype < 0) ; Int *Ap = (Int *) A->p ; Int *Anz = (Int *) A->nz ; Int *Ai = (Int *) A->i ; bool apacked = A->packed ; size_t ncol = A->ncol ; Int *Bp = (Int *) B->p ; Int *Bnz = (Int *) B->nz ; Int *Bi = (Int *) B->i ; bool bpacked = B->packed ; Int *Cp = (Int *) C->p ; Int *Ci = (Int *) C->i ; #ifndef PATTERN Real *Ax = (Real *) A->x ; Real *Bx = (Real *) B->x ; Real *Cx = (Real *) C->x ; Real alphax [2], betax [2] ; alphax [0] = (Real) alpha [0] ; betax [0] = (Real) beta [0] ; alphax [1] = 0 ; betax [1] = 0 ; #endif #ifdef COMPLEX alphax [1] = (Real) alpha [1] ; betax [1] = (Real) beta [1] ; #endif #ifdef ZOMPLEX Real *Az = (Real *) A->z ; Real *Bz = (Real *) B->z ; Real *Cz = (Real *) C->z ; Real alphaz [1], betaz [1] ; alphaz [0] = (Real) alpha [1] ; betaz [0] = (Real) beta [1] ; #endif //-------------------------------------------------------------------------- // C = alpha*A + beta*B //-------------------------------------------------------------------------- Int cnz = 0 ; for (Int j = 0 ; j < ncol ; j++) { //---------------------------------------------------------------------- // log the start of the jth column of C //---------------------------------------------------------------------- Cp [j] = cnz ; //---------------------------------------------------------------------- // get A(:,j) and B(:,j) //---------------------------------------------------------------------- Int pa = Ap [j] ; Int paend = (apacked) ? (Ap [j+1]) : (pa + Anz [j]) ; Int pb = Bp [j] ; Int pbend = (bpacked) ? (Bp [j+1]) : (pb + Bnz [j]) ; //---------------------------------------------------------------------- // C(:,j) = alpha*A(:,j) + beta*B(:,j) //---------------------------------------------------------------------- while (pa < paend || pb < pbend) { // get A(i,j) Int iA = (pa < paend) ? Ai [pa] : Int_max ; // get B(i,j) Int iB = (pb < pbend) ? Bi [pb] : Int_max ; // skip if C(i,j) is in the ignored part of the matrix Int i = MIN (iA, iB) ; if ((upper && i > j) || (lower && i < j)) continue ; // compute C(i,j) ASSERT (cnz < C->nzmax) ; Ci [cnz] = i ; if (iA < iB) { // B(:,j) is not present, so C(i,j) = alpha*A(i,j) MULT (Cx, Cz, cnz, alphax, alphaz, 0, Ax, Az, pa) ; pa++ ; } else if (iA > iB) { // A(:,j) is not present, so C(i,j) = beta*B(i,j) MULT (Cx, Cz, cnz, betax, betaz, 0, Bx, Bz, pb) ; pb++ ; } else { // C(i,j) = alpha*A(i,j) + beta*B(i,j) MULT (Cx, Cz, cnz, alphax, alphaz, 0, Ax, Az, pa) ; MULTADD (Cx, Cz, cnz, betax, betaz, 0, Bx, Bz, pb) ; pa++ ; pb++ ; } cnz++ ; } } //-------------------------------------------------------------------------- // log the end of the last column of C //-------------------------------------------------------------------------- Cp [ncol] = cnz ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_mult_uint64_t.c0000644000175100001440000000465514552026002023716 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_mult_uint64_t: multiply two uint64_t values //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. This file is licensed the same as GraphBLAS (Apache-2.0). // SPDX-License-Identifier: Apache-2.0 //------------------------------------------------------------------------------ // c = a*b but check for overflow // If c=a*b is large, c = UINT64_MAX is set, and the function returns false. // "large" means that c=a*b might overflow; see details below. // Otherwise c = a*b < INT64_MAX is guaranteed to be returned, and the function // returns true. // Derived from GraphBLAS/Source/GB_uint64_multiply. #include "cholmod_internal.h" bool cholmod_mult_uint64_t // c = a*b, return true if ok ( uint64_t *c, const uint64_t a, const uint64_t b ) { if (a <= 1 || b <= 1) { (*c) = a*b ; return (true) ; } uint64_t a1 = a >> 30 ; // a1 = a / 2^30 uint64_t b1 = b >> 30 ; // b1 = b / 2^30 if (a1 > 0 && b1 > 0) { // c = a*b will likely overflow, since both a and b are >= 2^30 and // thus c >= 2^60. This is slightly pessimistic. (*c) = UINT64_MAX ; return (false) ; } // a = a1 * 2^30 + a0 uint64_t a0 = a & 0x3FFFFFFFL ; // b = b1 * 2^30 + b0 uint64_t b0 = b & 0x3FFFFFFFL ; // a*b = (a1*b1) * 2^60 + (a1*b0 + a0*b1) * 2^30 + a0*b0 // since either a1 or b1 are zero, a1*b1 is zero // a0, b0 are < 2^30 // a1, b1 are < 2^34 // a1*b0 < 2^64 // a0*b1 < 2^64 // a0*b0 < 2^60 // thus // a*b = (a1*b0 + a0*b1) * 2^30 + a0*b0 // < (2^64 + 2^64 ) * 2^30 + 2^60 // so it is safe to compute t0 and t1 without risk of overflow: uint64_t t0 = a1*b0 ; uint64_t t1 = a0*b1 ; // a*b = (t0 + t1) * 2^30 + a0*b0 if (t0 >= 0x40000000L || t1 >= 0x40000000L) { // t >= 2^31, so t * 2^30 might overflow. This is also slightly // pessimistic, but good enough for the usage of this function. (*c) = UINT64_MAX ; return (false) ; } // t = t0 + t1 < 2^30 + 2^30 < 2^31, so // c = a*b = t * 2^30 + a0*b0 < 2^61 + 2^60 < 2^62, no overflow possible uint64_t t = t0 + t1 ; (*c) = (t << 30) + a0*b0 ; return (true) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_triplet_to_sparse.c0000644000175100001440000001745014552026002025263 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_triplet_to_sparse: convert triplet to sparse //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" //------------------------------------------------------------------------------ // t_cholmod_triplet_to_sparse_worker template //------------------------------------------------------------------------------ #define PATTERN #include "t_cholmod_triplet_to_sparse_worker.c" #define DOUBLE #define REAL #include "t_cholmod_triplet_to_sparse_worker.c" #define COMPLEX #include "t_cholmod_triplet_to_sparse_worker.c" #define ZOMPLEX #include "t_cholmod_triplet_to_sparse_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_triplet_to_sparse_worker.c" #define COMPLEX #include "t_cholmod_triplet_to_sparse_worker.c" #define ZOMPLEX #include "t_cholmod_triplet_to_sparse_worker.c" //------------------------------------------------------------------------------ // cholmod_triplet_to_sparse: convert triplet matrix to sparse matrix //------------------------------------------------------------------------------ #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_sparse) (&A, Common) ; \ CHOLMOD(free_sparse) (&R, Common) ; \ return (NULL) ; \ } // Converts a triplet matrix T into a sparse matrix A. The nzmax parameter // can be used to add additional space in A for future entries. The # of // entries that can be held in A is max (nnz (A), nzmax), so pass in nzmax // as zero if you do not need any additional space for future growth. // workspace: Iwork (max (nrow,ncol)) cholmod_sparse *CHOLMOD(triplet_to_sparse) // return sparse matrix A ( // input: cholmod_triplet *T, // input triplet matrix size_t nzmax, // allocate space for max(nzmax,nnz(A)) entries cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_TRIPLET_MATRIX_INVALID (T, NULL) ; Common->status = CHOLMOD_OK ; cholmod_sparse *A = NULL ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- size_t nrow = T->nrow ; size_t ncol = T->ncol ; size_t nz = T->nnz ; Int *Ti = (Int *) T->i ; Int *Tj = (Int *) T->j ; int stype = T->stype ; //-------------------------------------------------------------------------- // allocate temporary matrix R to hold the transpose of A //-------------------------------------------------------------------------- // R is unpacked so that duplicates can be easily assembled in place. // Note that the stype of R is negated, to hold the transpose of A. cholmod_sparse *R = CHOLMOD(allocate_sparse) (ncol, nrow, nz, /* R is unsorted: */ FALSE, /* R is unpacked: */ FALSE, /* stype is flipped: */ -stype, T->xtype + T->dtype, Common) ; RETURN_IF_ERROR ; Int *Rp = (Int *) R->p ; Int *Rnz = (Int *) R->nz ; //-------------------------------------------------------------------------- // count entries in each column of R, imcluding duplicates //-------------------------------------------------------------------------- // Rnz [0..nrow-1] = 0 memset (Rnz, 0, nrow * sizeof (Int)) ; for (Int k = 0 ; k < nz ; k++) { // get the entry T(i,j), which becomes R(j,i) Int i = Ti [k] ; Int j = Tj [k] ; if (i < 0 || j < 0 || i >= nrow || j >= ncol) { ERROR (CHOLMOD_INVALID, "index out of range") ; break ; } if (stype > 0) { // A will be symmetric, and only its upper triangular part is // stored, so R must be lower triangular. Ensure that entries // in the upper triangular part of R are transposed to the lower // triangular part, by placing the entry T(i,j) in column // MIN(i,j) of R. Rnz [MIN (i,j)]++ ; } else if (stype < 0) { // See comment above; A is lower triangular so R must be upper. Rnz [MAX (i,j)]++ ; } else { // T and A are unsymmetric Rnz [i]++ ; } } RETURN_IF_ERROR ; // return if index out of range //-------------------------------------------------------------------------- // Rp = cumulative sum of the row counts, Rnz //-------------------------------------------------------------------------- CHOLMOD(cumsum) (Rp, Rnz, nrow) ; //-------------------------------------------------------------------------- // allocate Iwork workspace for the template work, of size MAX (nrow,ncol) //-------------------------------------------------------------------------- CHOLMOD(alloc_work) (0, MAX (nrow, ncol), 0, 0, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // R = T' using template worker //-------------------------------------------------------------------------- size_t anz = 0 ; switch ((T->xtype + T->dtype) % 8) { default: anz = p_cholmod_triplet_to_sparse_worker (T, R, Common) ; break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: anz = rs_cholmod_triplet_to_sparse_worker (T, R, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: anz = cs_cholmod_triplet_to_sparse_worker (T, R, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: anz = zs_cholmod_triplet_to_sparse_worker (T, R, Common) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: anz = rd_cholmod_triplet_to_sparse_worker (T, R, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: anz = cd_cholmod_triplet_to_sparse_worker (T, R, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: anz = zd_cholmod_triplet_to_sparse_worker (T, R, Common) ; break ; } //-------------------------------------------------------------------------- // allocate the final output matrix A //-------------------------------------------------------------------------- anz = MAX (anz, nzmax) ; A = CHOLMOD(allocate_sparse) (nrow, ncol, anz, TRUE, TRUE, stype, T->xtype + T->dtype, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // A = R' //-------------------------------------------------------------------------- // uses Iwork [0..ncol-1] workspace if (stype == 0) { // unsymmetric transpose CHOLMOD(transpose_unsym) (R, 1, NULL, NULL, 0, A, Common) ; } else { // symmetric array transpose (not conjugate tranpose if complex) CHOLMOD(transpose_sym) (R, 1, NULL, A, Common) ; } RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // free workspace and return result //-------------------------------------------------------------------------- CHOLMOD(free_sparse) (&R, Common) ; ASSERT (CHOLMOD(dump_sparse) (A, "triplet_to_sparse:A", Common) >= 0) ; return (A) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_free_factor.c0000644000175100001440000000076514552026002023771 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_free_factor: free a sparse factorization //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_free_factor.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_factor.c0000644000175100001440000001534714552026002024034 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_copy_factor: copy a factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Creates an exact copy of a sparse factorization object. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_factor) (&H, Common) ; \ return (NULL) ; \ } //------------------------------------------------------------------------------ // t_cholmod_copy_factor_worker template //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_copy_factor_worker.c" #define COMPLEX #include "t_cholmod_copy_factor_worker.c" #define ZOMPLEX #include "t_cholmod_copy_factor_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_copy_factor_worker.c" #define COMPLEX #include "t_cholmod_copy_factor_worker.c" #define ZOMPLEX #include "t_cholmod_copy_factor_worker.c" //------------------------------------------------------------------------------ cholmod_factor *CHOLMOD(copy_factor) // return a copy of the factor ( // input: cholmod_factor *L, // factor to copy (not modified) cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_FACTOR_INVALID (L, FALSE) ; Common->status = CHOLMOD_OK ; DEBUG (CHOLMOD(dump_factor) (L, "copy_factor:L", Common)) ; //-------------------------------------------------------------------------- // get inputs and sizes of entries //-------------------------------------------------------------------------- size_t n = L->n ; size_t ei = sizeof (Int) ; size_t e = (L->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * ((L->xtype == CHOLMOD_PATTERN) ? 0 : ((L->xtype == CHOLMOD_COMPLEX) ? 2 : 1)) ; //-------------------------------------------------------------------------- // allocate the new factor H, H->Perm, and H->ColCount //-------------------------------------------------------------------------- cholmod_factor *H = CHOLMOD(alloc_factor) (n, L->dtype, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // copy the symbolic contents (same for simplicial or supernodal) //-------------------------------------------------------------------------- memcpy (H->Perm, L->Perm, n * ei) ; memcpy (H->ColCount, L->ColCount, n * ei) ; H->ordering = L->ordering ; H->is_ll = L->is_ll ; //-------------------------------------------------------------------------- // copy the rest of the factor //-------------------------------------------------------------------------- if (L->is_super) { //---------------------------------------------------------------------- // L is a numerical supernodal factor; change H to supernodal //---------------------------------------------------------------------- H->xsize = L->xsize ; H->ssize = L->ssize ; H->nsuper = L->nsuper ; CHOLMOD(change_factor) (L->xtype + L->dtype, /* to LL': */ TRUE, /* to supernodal: */ TRUE, /* to packed: */ TRUE, /* to monotonic: */ TRUE, H, Common) ; RETURN_IF_ERROR ; //---------------------------------------------------------------------- // copy the supernodal contents //---------------------------------------------------------------------- H->maxcsize = L->maxcsize ; H->maxesize = L->maxesize ; memcpy (H->super, L->super, (L->nsuper + 1) * ei) ; memcpy (H->pi, L->pi, (L->nsuper + 1) * ei) ; memcpy (H->px, L->px, (L->nsuper + 1) * ei) ; memset (H->s, 0, ei) ; memcpy (H->s, L->s, (L->ssize) * ei) ; if (L->xtype == CHOLMOD_REAL || L->xtype == CHOLMOD_COMPLEX) { memcpy (H->x, L->x, (L->xsize) * ex) ; } } else if (L->xtype != CHOLMOD_PATTERN) { //---------------------------------------------------------------------- // L is a numerical simplicial factor; change H to the same //---------------------------------------------------------------------- H->nzmax = L->nzmax ; CHOLMOD(change_factor) (L->xtype + L->dtype, L->is_ll, /* to supernodal: */ FALSE, /* to packed: */ -1, /* to monotonic: */ TRUE, H, Common) ; RETURN_IF_ERROR ; //---------------------------------------------------------------------- // copy the simplicial contents //---------------------------------------------------------------------- H->xtype = L->xtype ; H->dtype = L->dtype ; memcpy (H->p, L->p, (n+1) * ei) ; memcpy (H->prev, L->prev, (n+2) * ei) ; memcpy (H->next, L->next, (n+2) * ei) ; memcpy (H->nz, L->nz, n * ei) ; switch ((L->xtype + L->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_copy_factor_worker (L, H) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_copy_factor_worker (L, H) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_copy_factor_worker (L, H) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_copy_factor_worker (L, H) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_copy_factor_worker (L, H) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_copy_factor_worker (L, H) ; break ; } } //-------------------------------------------------------------------------- // finalize the copy and return result //-------------------------------------------------------------------------- H->minor = L->minor ; H->is_monotonic = L->is_monotonic ; DEBUG (CHOLMOD(dump_factor) (H, "copy_factor:H", Common)) ; ASSERT (H->xtype == L->xtype && H->is_super == L->is_super) ; return (H) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sparse_to_triplet_worker.c0000644000175100001440000000716214552026002026653 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_sparse_to_triplet_worker //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_sparse_to_triplet_worker) ( cholmod_triplet *T, cholmod_sparse *A ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int ncol = A->ncol ; bool packed = (bool) A->packed ; Int *Ap = (Int *) A->p ; Int *Ai = (Int *) A->i ; #ifndef PATTERN Real *Ax = (Real *) A->x ; #ifdef ZOMPLEX Real *Az = (Real *) A->z ; #endif #endif Int *Anz = (Int *) A->nz ; Int *Ti = (Int *) T->i ; Int *Tj = (Int *) T->j ; #ifndef PATTERN Real *Tx = (Real *) T->x ; #ifdef ZOMPLEX Real *Tz = (Real *) T->z ; #endif #endif Int k = 0 ; //-------------------------------------------------------------------------- // copy entries from A into T //-------------------------------------------------------------------------- #define COPY_ENTRY(entry_test) \ if (entry_test) \ { \ Ti [k] = i ; \ Tj [k] = j ; \ /* Tx (k) = Ax (p) */ \ ASSIGN (Tx, Tz, k, Ax, Az, p) ; \ k++ ; \ } if (A->stype == 0) { //---------------------------------------------------------------------- // A is unsymmetric //---------------------------------------------------------------------- for (Int j = 0 ; j < ncol ; j++) { Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; COPY_ENTRY (true) ; } } } else if (A->stype > 0) { //---------------------------------------------------------------------- // A is symmetric, with just upper triangular part stored //---------------------------------------------------------------------- for (Int j = 0 ; j < ncol ; j++) { Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; COPY_ENTRY (i <= j) ; } } } else { //---------------------------------------------------------------------- // A is symmetric, with just lower triangular part stored //---------------------------------------------------------------------- for (Int j = 0 ; j < ncol ; j++) { Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; COPY_ENTRY (i >= j) ; } } } //-------------------------------------------------------------------------- // log the number of entries in T //-------------------------------------------------------------------------- T->nnz = k ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_free_work.c0000644000175100001440000000444214552026002023501 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_free_work: free workspace in Common (int32/64) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" int CHOLMOD(free_work) (cholmod_common *Common) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; //-------------------------------------------------------------------------- // free Flag and Head, of size nrow and nrow+1 Ints //-------------------------------------------------------------------------- size_t nrow = Common->nrow ; Common->Flag = CHOLMOD(free) (nrow, sizeof (Int), Common->Flag, Common) ; Common->Head = CHOLMOD(free) (nrow+1, sizeof (Int), Common->Head, Common) ; Common->nrow = 0 ; //-------------------------------------------------------------------------- // free Iwork, of size iworksize Ints //-------------------------------------------------------------------------- Common->Iwork = CHOLMOD(free) (Common->iworksize, sizeof (Int), Common->Iwork, Common) ; Common->iworksize = 0 ; //-------------------------------------------------------------------------- // free Xwork, of size xworkbytes //-------------------------------------------------------------------------- Common->Xwork = CHOLMOD(free) (Common->xworkbytes, sizeof (uint8_t), Common->Xwork, Common) ; Common->xworkbytes = 0 ; //-------------------------------------------------------------------------- // free GPU workspace //-------------------------------------------------------------------------- #ifdef CHOLMOD_HAS_CUDA CHOLMOD(gpu_deallocate) (Common) ; #endif //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (TRUE) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_calloc.c0000644000175100001440000000112214552026002022733 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_calloc: calloc (int64 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_ALLOC_FUNCTION cholmod_l_calloc #define SUITESPARSE_ALLOC_FUNCTION SuiteSparse_calloc #define CHOLMOD_INT64 #include "t_cholmod_malloc.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_add_size_t.c0000644000175100001440000000075314552026002023301 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_add_size_t: add two size_t values //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_add_size_t.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_pack_factor.c0000644000175100001440000000077114552026002023763 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_pack_factor: pack a simplicial factorization //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_pack_factor.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_copy_factor.c0000644000175100001440000000074714552026002024022 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_copy_factor: copy a factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_copy_factor.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_nnz.c0000644000175100001440000000074714552026002022004 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_nnz: # of entries in a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_nnz.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_dense_nnz.c0000644000175100001440000000076514552026002023475 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_dense_nnz: # of nonzeros in a dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_dense_nnz.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_defaults.c0000644000175100001440000000076614552026002023007 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_defaults: set CHOLMOD defaults (int32 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_defaults.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_pack_factor.c0000644000175100001440000000745014552026002023774 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_pack_factor: pack a simplicial factorization //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // The columns of simplicial factor L can have gaps between them, with empty // space. This method removes the empty space, leaving all the empty space at // the tail end of L->i and L->x. Each column of L is reduced in is size so // that it has at most Common->grow2 empty space at the end of each column. // L must be simplicial and numerical (not symbolic). If L is supernodal, or // symbolic, this method does nothing. // This method can be followed by a call to cholmod_reallocate_factor, to // reduce the size of L->i and L->x. Or, the space can be left to accomodate // future growth from updates/downdates. // The columns of L are not made to appear in monotonic order. For that, // use cholmod_change_factor which can both pack the columns and make them // monotonic. #include "cholmod_internal.h" //------------------------------------------------------------------------------ // t_cholmod_pack_factor_worker template //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_pack_factor_worker.c" #define COMPLEX #include "t_cholmod_pack_factor_worker.c" #define ZOMPLEX #include "t_cholmod_pack_factor_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_pack_factor_worker.c" #define COMPLEX #include "t_cholmod_pack_factor_worker.c" #define ZOMPLEX #include "t_cholmod_pack_factor_worker.c" //------------------------------------------------------------------------------ // cholmod_pack_factor //------------------------------------------------------------------------------ int CHOLMOD(pack_factor) ( // input/output: cholmod_factor *L, // factor to pack cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_FACTOR_INVALID (L, FALSE) ; Common->status = CHOLMOD_OK ; DEBUG (CHOLMOD(dump_factor) (L, "pack:L input", Common)) ; if (L->xtype == CHOLMOD_PATTERN || L->is_super) { // nothing to do return (TRUE) ; } //-------------------------------------------------------------------------- // pack //-------------------------------------------------------------------------- switch ((L->xtype + L->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_pack_factor_worker (L, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_pack_factor_worker (L, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_pack_factor_worker (L, Common) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_pack_factor_worker (L, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_pack_factor_worker (L, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_pack_factor_worker (L, Common) ; break ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- DEBUG (CHOLMOD(dump_factor) (L, "done pack", Common)) ; return (TRUE) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_aat.c0000644000175100001440000000074714552026002022257 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_aat: compute AA' or A(:,f)*A(:,f)' //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_aat.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_add.c0000644000175100001440000000073614552026002022240 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_add: C = alpha*A + beta*B //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_add.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_ones_worker.c0000644000175100001440000000212414552026002024046 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_ones_worker: dense matrix of all ones //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_ones_worker) ( cholmod_dense *X ) { //-------------------------------------------------------------------------- // fill the matrix with all 1's //-------------------------------------------------------------------------- Real *Xx = (Real *) X->x ; #ifdef ZOMPLEX Real *Xz = (Real *) X->z ; #endif size_t nzmax = X->nzmax ; Real onex [2] = {1,0} ; #ifdef ZOMPLEX Real onez [1] = {0} ; #endif for (Int k = 0 ; k < nzmax ; k++) { // X(k) = 1 ASSIGN (Xx, Xz, k, onex, onez, 0) ; } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_realloc.c0000644000175100001440000000075114552026002023126 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_realloc: realloc (int64 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_realloc.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_allocate_factor.c0000644000175100001440000000157314552026002024317 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_allocate_factor: allocate a simplicial factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // For backward compatibilty; L is returned as double precision. // Use cholmod_alloc_factor to allocate a single precision factor. #define CHOLMOD_INT32 #include "cholmod_internal.h" cholmod_factor *cholmod_allocate_factor // return the new factor L ( // input: size_t n, // L is factorization of an n-by-n matrix cholmod_common *Common ) { return (cholmod_alloc_factor (n, CHOLMOD_DOUBLE, Common)) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_alloc_work.c0000644000175100001440000001052214552026002023646 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_alloc_work: double/single int32/64 workspace //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Allocates and initializes CHOLMOD workspace in Common, or increases the size // of the workspace if already allocated. If the required workspace is already // allocated, no action is taken. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_work) (Common) ; \ return (FALSE) ; \ } #define RETURN_IF_ALLOC_NOT_ALLOWED \ if (Common->no_workspace_reallocate) \ { \ Common->status = CHOLMOD_INVALID ; \ return (FALSE) ; \ } int CHOLMOD(alloc_work) ( // input: size_t nrow, // # of rows in the matrix A size_t iworksize, // size of Iwork (# of integers, int32 or int64) size_t xworksize, // size of Xwork (in # of entries, double or single) int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate Flag (of size nrow Ints) and Head (of size nrow+1 Ints) //-------------------------------------------------------------------------- // ensure at least 1 entry allocated, and check for size_t overflow nrow = MAX (1, nrow) ; size_t nrow1 = nrow + 1 ; if (nrow1 < nrow) Common->status = CHOLMOD_TOO_LARGE ; RETURN_IF_ERROR ; if (nrow > Common->nrow) { RETURN_IF_ALLOC_NOT_ALLOWED ; Common->Flag = CHOLMOD(free) (Common->nrow, sizeof (Int), Common->Flag, Common) ; Common->Head = CHOLMOD(free) (Common->nrow+1, sizeof (Int), Common->Head, Common) ; Common->nrow = nrow ; Common->Flag = CHOLMOD(malloc) (nrow, sizeof (Int), Common) ; Common->Head = CHOLMOD(malloc) (nrow1, sizeof (Int), Common) ; RETURN_IF_ERROR ; // clear the Flag and Head workspace Common->mark = 0 ; CHOLMOD(set_empty) (Common->Flag, nrow) ; CHOLMOD(set_empty) (Common->Head, nrow+1) ; } //-------------------------------------------------------------------------- // allocate Iwork (of size iworksize Ints) //-------------------------------------------------------------------------- iworksize = MAX (1, iworksize) ; if (iworksize > Common->iworksize) { RETURN_IF_ALLOC_NOT_ALLOWED ; CHOLMOD(free) (Common->iworksize, sizeof (Int), Common->Iwork, Common) ; Common->iworksize = iworksize ; Common->Iwork = CHOLMOD(malloc) (iworksize, sizeof (Int), Common) ; RETURN_IF_ERROR ; } //-------------------------------------------------------------------------- // allocate Xwork (xworksize) and set it to 0 //-------------------------------------------------------------------------- // make sure xworksize is >= 2 xworksize = MAX (2, xworksize) ; size_t e = (dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; if (xworksize > Common->xworkbytes / e) { RETURN_IF_ALLOC_NOT_ALLOWED ; CHOLMOD(free) (Common->xworkbytes, sizeof (uint8_t), Common->Xwork, Common) ; Common->Xwork = CHOLMOD(malloc) (xworksize, e, Common) ; RETURN_IF_ERROR ; // clear the Xwork workspace Common->xworkbytes = xworksize * e ; memset (Common->Xwork, 0, Common->xworkbytes) ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (TRUE) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_error.c0000644000175100001440000000727614552026002022657 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_error: CHOLMOD error handling //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" //------------------------------------------------------------------------------ // MESSAGE macro: print a message using the given printf function pointer //------------------------------------------------------------------------------ #define MESSAGE(kind) \ { \ printf_function ("CHOLMOD " kind ":") ; \ if (message != NULL) printf_function (" %s.", message) ; \ if (file != NULL) printf_function (" file: %s", file) ; \ if (line > 0 ) printf_function (" line: %d", line) ; \ printf_function ("\n") ; \ fflush (stdout) ; \ fflush (stderr) ; \ } //------------------------------------------------------------------------------ // cholmod_error //------------------------------------------------------------------------------ int CHOLMOD(error) ( // input: int status, // Common->status const char *file, // source file where error occurred int line, // line number where error occurred const char *message, // error message to print cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; //-------------------------------------------------------------------------- // set the error status //-------------------------------------------------------------------------- Common->status = status ; //-------------------------------------------------------------------------- // handle the error, unless we're inside a CHOLMOD try/catch block //-------------------------------------------------------------------------- if (!(Common->try_catch)) { //---------------------------------------------------------------------- // print the error message, if permitted //---------------------------------------------------------------------- #ifndef NPRINT int (*printf_function) (const char *, ...) ; printf_function = SuiteSparse_config_printf_func_get ( ) ; if (printf_function != NULL) { if (status > 0 && Common->print > 1) { // print a warning message MESSAGE ("warning") ; } else if (Common->print > 0) { // print an error message MESSAGE ("error") ; } } #endif //---------------------------------------------------------------------- // call the user error handler, if present //---------------------------------------------------------------------- if (Common->error_handler != NULL) { Common->error_handler (status, file, line, message) ; } } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (TRUE) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_copy_factor.c0000644000175100001440000000074514552026002023505 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_copy_factor: copy a factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_copy_factor.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_maxrank.c0000644000175100001440000000076314552026002022636 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_maxrank: find valid value of Common->maxrank //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_maxrank.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_free.c0000644000175100001440000000074014552026002022424 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_free: free (int64 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_free.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_eye.c0000644000175100001440000000703214552026002022276 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_eye: dense identity matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Create a dense identity matrix, possibly rectangular, of any xtype or // dtype. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_dense) (&X, Common) ; \ return (NULL) ; \ } //------------------------------------------------------------------------------ // t_cholmod_eye_worker template //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_eye_worker.c" #define COMPLEX #include "t_cholmod_eye_worker.c" #define ZOMPLEX #include "t_cholmod_eye_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_eye_worker.c" #define COMPLEX #include "t_cholmod_eye_worker.c" #define ZOMPLEX #include "t_cholmod_eye_worker.c" //------------------------------------------------------------------------------ // cholmod_eye: create a dense identity matrix //------------------------------------------------------------------------------ cholmod_dense *CHOLMOD(eye) // return a dense identity matrix ( // input: size_t nrow, // # of rows size_t ncol, // # of columns int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (_REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate the matrix and set it to all zero //-------------------------------------------------------------------------- cholmod_dense *X = CHOLMOD(zeros) (nrow, ncol, xdtype, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // fill the matrix with all 1's on the diagonal //-------------------------------------------------------------------------- switch (xdtype % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_eye_worker (X) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_eye_worker (X) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_eye_worker (X) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_eye_worker (X) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_eye_worker (X) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_eye_worker (X) ; break ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_dense) (X, "eye:X", Common) >= 0) ; return (X) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_3_worker.c0000644000175100001440000001272314552026002026115 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_change_factor_3_worker: change format of a factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Converts a supernodal numeric L into a simplicial numeric L. The factor is // modified in place in Lx. // If to_packed is false, entries in Lx stay in the same position they had in // the supernode, and Li is created to hold the pattern of all those entries. // Gaps will naturally appear because of the unused space in each supernode. // // Consider the following example: // // Each supernode is lower trapezoidal, with a top part that is lower // triangular (with diagonal present) and a bottom part that is rectangular. // In this example below, nscol = 5, so the supernode represents 5 columns of // L, and nsrow = 8, which means that the first column of the supernode has 8 // entries, including the diagonal. // // x 1 2 3 4 // x x 2 3 4 // x x x 3 4 // x x x x 4 // x x x x x // x x x x x // x x x x x // x x x x x // // If the entries in the supernode are not moved, the first column will have a // single entry of slack space at the end of the space (the "1" above). The // 2nd column has 2 entries of slack space ("2"). The 3rd column has 3 entries // of slack space ("3"), and so on. The last column (5th) has no slack space // since it is followed by the next supenode. // If to_packed is true, the space is compressed and the unused entries above // the diagonal of each supernode are removed. That is, in this example, the // supernode takes up 40 entries in Lx in supernodal form. In the simplicial // form, there is no slack space, and the total space becomes 8 + 7 + 6 + 5 + 4 // = 30. The first column starts at position Lpx [s] in Lx for supernode s, // and is moved to the 'left', starting at position Lp [j] if the first column // is j = L->super [s]. Since space is being compacted, Lp [j] <= Lpx [s] // holds, and thus Lx can be compacted in place when to_packed is true. // // x // x x // x x x // x x x x // x x x x x // x x x x x // x x x x x // x x x x x // The factor is either real or complex (not pattern nor complex). Thus, // L->x is always non-NULL, and L->z is NULL and not used. Instead of Lz, // a blank appears in the macros that access the values of L below. #include "cholmod_template.h" //------------------------------------------------------------------------------ // t_cholmod_change_factor_3_worker: convert supernodal numeric L to simplicial //------------------------------------------------------------------------------ static void TEMPLATE (cholmod_change_factor_3_worker) ( cholmod_factor *L, // factor to modify int to_packed, // if true: convert L to packed int to_ll, // if true, convert to LL. if false: to LDL' cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- ASSERT (L->is_super) ; ASSERT (L->xtype == CHOLMOD_REAL || L->xtype == CHOLMOD_COMPLEX) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int n = L->n ; // L is n-by-n Int nsuper = L->nsuper ; // # of supernodes Int *Lpi = (Int *) L->pi ; // index into L->s for supernode pattern Int *Lpx = (Int *) L->px ; // index into L->x for supernode values Int *Ls = (Int *) L->s ; // pattern of supernodes Int *Super = (Int *) L->super ; // 1st column in each supernode // Lx holds supernode values on input; simplicial values on output: Real *Lx = (Real *) L->x ; // numerical values (real or complex) // the simplicial space is allocated but not initialized on input: Int *Lp = (Int *) L->p ; // simplicial col pointers Int *Li = (Int *) L->i ; // simplicial row indices Int *Lnz = (Int *) L->nz ; // simplicial column counts //---------------------------------------------------------------------- // convert supernodal LL' to simplicial LL' or LDL' (packed/unpacked) //---------------------------------------------------------------------- if (to_packed) { if (to_ll) { // convert to simplicial packed LL' #define TO_PACKED true #define TO_LL true #include "t_cholmod_change_factor_3_template.c" } else { // convert to simplicial packed LDL' #define TO_PACKED true #define TO_LL false #include "t_cholmod_change_factor_3_template.c" } } else { if (to_ll) { // convert to simplicial unpacked LL' #define TO_PACKED false #define TO_LL true #include "t_cholmod_change_factor_3_template.c" } else { // convert to simplicial unpacked LDL' #define TO_PACKED false #define TO_LL false #include "t_cholmod_change_factor_3_template.c" } } } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_factor_worker.c0000644000175100001440000000323714552026002025420 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_copy_factor_worker: copy a factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Columns are copied individually, to avoid copying uninitialized space #include "cholmod_template.h" static void TEMPLATE (cholmod_copy_factor_worker) ( cholmod_factor *L, // input factor to copy (not modified) cholmod_factor *H // output factor ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- size_t n = L->n ; Int *Lp = (Int *) L->p ; Int *Li = (Int *) L->i ; Int *Lnz = (Int *) L->nz ; Real *Lx = (Real *) L->x ; #ifdef ZOMPLEX Real *Lz = (Real *) L->z ; #endif Int *Hi = (Int *) H->i ; Real *Hx = (Real *) H->x ; #ifdef ZOMPLEX Real *Hz = (Real *) H->z ; #endif //-------------------------------------------------------------------------- // copy each column //-------------------------------------------------------------------------- for (Int j = 0 ; j < n ; j++) { Int p = Lp [j] ; Int pend = p + Lnz [j] ; for ( ; p < pend ; p++) { Hi [p] = Li [p] ; ASSIGN (Hx, Hz, p, Lx, Lz, p) ; } } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_memdebug.c0000644000175100001440000001117414552026002022760 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_memdebug: memory debugging //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" #ifndef NDEBUG #define CM_MEMTABLE_SIZE 10000 static void *memtable_p [CM_MEMTABLE_SIZE] ; static size_t memtable_s [CM_MEMTABLE_SIZE] ; static int nmemtable = 0 ; //------------------------------------------------------------------------------ // CM_memtable_dump: dump the memtable //------------------------------------------------------------------------------ void CM_memtable_dump (void) { printf ("\nmemtable dump: %d\n", nmemtable) ; for (int k = 0 ; k < nmemtable ; k++) { printf (" %4d: %12p : %ld\n", k, memtable_p [k], memtable_s [k]) ; } } //------------------------------------------------------------------------------ // CM_memtable_n: return # of items in the memtable //------------------------------------------------------------------------------ int CM_memtable_n (void) { return (nmemtable) ; } //------------------------------------------------------------------------------ // CM_memtable_clear: clear the memtable //------------------------------------------------------------------------------ void CM_memtable_clear (void) { nmemtable = 0 ; } //------------------------------------------------------------------------------ // CM_memtable_add: add a pointer to the memtable of malloc'd blocks //------------------------------------------------------------------------------ void CM_memtable_add (void *p, size_t size) { if (p == NULL) return ; bool fail = false ; #ifdef CM_MEMDUMP printf ("memtable add %p size %ld\n", p, size) ; #endif int n = nmemtable ; fail = (n > CM_MEMTABLE_SIZE) ; if (!fail) { for (int i = 0 ; i < n ; i++) { if (p == memtable_p [i]) { printf ("\nadd duplicate %p size %ld\n", p, size) ; CM_memtable_dump ( ) ; fail = true ; break ; } } } if (!fail && p != NULL) { memtable_p [n] = p ; memtable_s [n] = size ; nmemtable++ ; } ASSERT (!fail) ; #ifdef CM_MEMDUMP CM_memtable_dump ( ) ; #endif } //------------------------------------------------------------------------------ // CM_memtable_size: get the size of a malloc'd block //------------------------------------------------------------------------------ size_t CM_memtable_size (void *p) { size_t size = 0 ; if (p == NULL) return (0) ; bool found = false ; int n = nmemtable ; for (int i = 0 ; i < n ; i++) { if (p == memtable_p [i]) { size = memtable_s [i] ; found = true ; break ; } } if (!found) { printf ("\nFAIL: %p not found\n", p) ; CM_memtable_dump ( ) ; ASSERT (0) ; } return (size) ; } //------------------------------------------------------------------------------ // CM_memtable_find: test if a malloc'd block is in the table //------------------------------------------------------------------------------ bool CM_memtable_find (void *p) { bool found = false ; if (p == NULL) return (false) ; int n = nmemtable ; for (int i = 0 ; i < n ; i++) { if (p == memtable_p [i]) { found = true ; break ; } } return (found) ; } //------------------------------------------------------------------------------ // CM_memtable_remove: remove a pointer from the table of malloc'd blocks //------------------------------------------------------------------------------ void CM_memtable_remove (void *p) { if (p == NULL) return ; bool found = false ; #ifdef CM_MEMDUMP printf ("memtable remove %p ", p) ; #endif int n = nmemtable ; for (int i = 0 ; i < n ; i++) { if (p == memtable_p [i]) { // found p in the table; remove it memtable_p [i] = memtable_p [n-1] ; memtable_s [i] = memtable_s [n-1] ; nmemtable -- ; found = true ; break ; } } if (!found) { printf ("remove %p NOT FOUND\n", p) ; CM_memtable_dump ( ) ; } ASSERT (found) ; #ifdef CM_MEMDUMP CM_memtable_dump ( ) ; #endif } #endif Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_add_size_t.c0000644000175100001440000000075314552026002023614 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_add_size_t: add two size_t values //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_add_size_t.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_3_template.c0000644000175100001440000001041414552026002026412 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_change_factor_3_template //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ { Int p = 0 ; // current position in simplicial L for (Int s = 0 ; s < nsuper ; s++) { //------------------------------------------------------------------ // get the Supernode (0:nsrow-1, 0:nscol-1) //------------------------------------------------------------------ Int k1 = Super [s] ; // 1st column of supernode s Int k2 = Super [s+1] ; // k2-1 is last column of supernode s Int psi = Lpi [s] ; // Ls [psi:psend-1]: pattern of s Int psend = Lpi [s+1] ; Int psx = Lpx [s] ; // Lx [psx:..]: values of supernode s Int nsrow = psend - psi ; // # of rows in 1st column of s Int nscol = k2 - k1 ; // # of cols in the supernode //------------------------------------------------------------------ // convert the Supernode to the simplicial L (k1,k2-1) //------------------------------------------------------------------ for (Int jj = 0 ; jj < nscol ; jj++) { //-------------------------------------------------------------- // convert L(:,j) from Supernode (:,jj) //-------------------------------------------------------------- Int j = jj + k1 ; // L(:,j) is Supernode column jj Lnz [j] = nsrow - jj ; // # entries in L(:,j) //-------------------------------------------------------------- // log the start of L(:,j) in the simplicial form of L //-------------------------------------------------------------- Int ii = jj ; Int q = psx + jj + jj*nsrow ; Lp [j] = TO_PACKED ? p:q ; //-------------------------------------------------------------- // handle the diagonal for LDL' //-------------------------------------------------------------- Real ljj [1] ; if (!TO_LL) { // create the row index for L(j,j) Li [TO_PACKED ? p:q] = j ; // compute D(j,j) ASSIGN_REAL (ljj, 0, Lx, q) ; if (ljj [0] <= 0) { // not positive definite: values of L(:,j) not changed ASSIGN_REAL (Lx, TO_PACKED ? p:q, ljj, 0) ; CLEAR_IMAG (Lx, , TO_PACKED ? p:q) ; ljj [0] = 1 ; } else { // D(j,j) = L (j,j)^2 Real djj [1] ; djj [0] = ljj [0] * ljj [0] ; ASSIGN_REAL (Lx, TO_PACKED ? p:q, djj, 0) ; CLEAR_IMAG (Lx, , TO_PACKED ? p:q) ; } // advance to the first off-diagonal entry of L(:,j) ii++ ; p++ ; } //-------------------------------------------------------------- // convert the remainder of L(:,j) //-------------------------------------------------------------- for ( ; ii < nsrow ; ii++, p++) { // create the row index for L(i,j) q = psx + ii + jj*nsrow ; Li [TO_PACKED ? p:q] = Ls [psi + ii] ; // revise the numeric value of L(i,j) if (TO_LL) { // for LL': L(i,j) is unchanged; move to new position if (TO_PACKED) { ASSIGN (Lx, , p, Lx, , q) ; } } else { // for LDL': L(i,j) = L(i,j) / L(j,j) DIV_REAL (Lx, , TO_PACKED ? p:q, Lx, , q, ljj, 0) ; } } } } // log the end of the last column in L Lp [n] = TO_PACKED ? p : Lpx [nsuper] ; } #undef TO_PACKED #undef TO_LL Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_maxrank.c0000644000175100001440000000076514552026002023153 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_maxrank: find valid value of Common->maxrank //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_maxrank.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_alloc_work.c0000644000175100001440000000077614552026002023650 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_alloc_work: alloc workspace (double/single, int64) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_alloc_work.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_speye.c0000644000175100001440000000074214552026002022317 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_speye: sparse identity matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_speye.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_triplet.c0000644000175100001440000000530314552026002024230 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_copy_triplet: copy a triplet matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_triplet) (&C, Common) ; \ return (NULL) ; \ } cholmod_triplet *CHOLMOD(copy_triplet) // return new triplet matrix ( // input: cholmod_triplet *T, // triplet matrix to copy cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_TRIPLET_MATRIX_INVALID (T, NULL) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate the copy //-------------------------------------------------------------------------- cholmod_triplet *C = CHOLMOD(allocate_triplet) (T->nrow, T->ncol, T->nzmax, T->stype, T->xtype + T->dtype, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // get the sizes of the entries //-------------------------------------------------------------------------- size_t ei = sizeof (Int) ; size_t e = (T->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * ((T->xtype == CHOLMOD_PATTERN) ? 0 : ((T->xtype == CHOLMOD_COMPLEX) ? 2 : 1)) ; size_t ez = e * ((T->xtype == CHOLMOD_ZOMPLEX) ? 1 : 0) ; //-------------------------------------------------------------------------- // copy the contents from T to C //-------------------------------------------------------------------------- C->nnz = T->nnz ; if (T->i != NULL) memcpy (C->i, T->i, T->nnz * ei) ; if (T->j != NULL) memcpy (C->j, T->j, T->nnz * ei) ; if (T->x != NULL) memcpy (C->x, T->x, T->nnz * ex) ; if (T->z != NULL) memcpy (C->z, T->z, T->nnz * ez) ; //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_triplet) (C, "copy_triplet:C", Common)) ; return (C) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_eye.c0000644000175100001440000000073514552026002021756 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_eye: dense identity matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_eye.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose.c0000644000175100001440000000153414552026002023533 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_transpose: transpose a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" cholmod_sparse *CHOLMOD(transpose) ( // input: cholmod_sparse *A, // input matrix int mode, // 2: numerical (conj) // 1: numerical (non-conj.) // <= 0: pattern (with diag) cholmod_common *Common ) { return (CHOLMOD(ptranspose) (A, mode, /* Perm: */ NULL, /* fset: */ NULL, /* fsize: */ 0, Common)) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_finish.c0000644000175100001440000000175114552026002022776 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_finish: finish CHOLMOD (int32/int64 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" // cholmod_start or cholmod_l_start must be called once prior to calling any // other CHOLMOD method. It contains workspace that must be freed by // cholmod_finish or cholmod_l_finish (which is just another name for // cholmod_free_work or cholmod_l_free_work, respetively), int CHOLMOD(finish) (cholmod_common *Common) { #ifdef BLAS_DUMP if (Common->blas_dump != NULL) { fclose (Common->blas_dump) ; Common->blas_dump = NULL ; } #endif return (CHOLMOD(free_work) (Common)) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_allocate_dense.c0000644000175100001440000000077314552026002024140 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_allocate_dense: allocate dense matrix (int32) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_allocate_dense.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_free_dense.c0000644000175100001440000000075114552026002023604 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_free_dense: free dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_free_dense.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_free_work.c0000644000175100001440000000076614552026002023476 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_free_work: free workspace in Common (int64) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_free_work.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_aat_worker.c0000644000175100001440000001131214552026002023646 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_aat_worker: C = A*A' or A(:,f)*A*(:,f)' //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_aat_worker) ( cholmod_sparse *C, // output matrix cholmod_sparse *A, // input matrix, not modified cholmod_sparse *F, // input matrix, not modified, F = A' or A(:,f)' bool ignore_diag, // if true, ignore diagonal cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- ASSERT (A->stype == 0) ; ASSERT (C->stype == 0) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int n = A->nrow ; Int *Ap = (Int *) A->p ; Int *Anz = (Int *) A->nz ; Int *Ai = (Int *) A->i ; #ifndef PATTERN Real *Ax = (Real *) A->x ; #ifdef ZOMPLEX Real *Az = (Real *) A->z ; #endif #endif bool packed = A->packed ; Int *Fp = (Int *) F->p ; Int *Fi = (Int *) F->i ; #ifndef PATTERN Real *Fx = (Real *) F->x ; #ifdef ZOMPLEX Real *Fz = (Real *) F->z ; #endif #endif ASSERT (F->packed) ; Int *Cp = (Int *) C->p ; Int *Ci = (Int *) C->i ; #ifndef PATTERN Real *Cx = (Real *) C->x ; #ifdef ZOMPLEX Real *Cz = (Real *) C->z ; #endif #endif ASSERT (C->packed) ; //-------------------------------------------------------------------------- // get workspace //-------------------------------------------------------------------------- // W is all negative, because jmark in t_cholmod_aat is always negative. Int *W = Common->Iwork ; // size n, all < 0 #ifndef NDEBUG for (Int i = 0 ; i < n ; i++) { ASSERT (W [i] < 0) ; } #endif //-------------------------------------------------------------------------- // C = A*A' or A(:,f)*A(:,f)' //-------------------------------------------------------------------------- Int pc = 0 ; for (Int j = 0 ; j < n ; j++) { //---------------------------------------------------------------------- // log the start of C(:,j) //---------------------------------------------------------------------- Int pc_start = pc ; Cp [j] = pc ; //---------------------------------------------------------------------- // compute C(:,j) = A*F(:,j) //---------------------------------------------------------------------- for (Int pf = Fp [j] ; pf < Fp [j+1] ; pf++) { //------------------------------------------------------------------ // get the F(t,j) entry //------------------------------------------------------------------ Int t = Fi [pf] ; #ifndef PATTERN Real fx [2] = {0,0} ; #ifdef ZOMPLEX Real fz [1] = {0} ; #endif #endif ASSIGN (fx, fz, 0, Fx, Fz, pf) ; //------------------------------------------------------------------ // C(:,j) += A(:,t)*F(t,j) //------------------------------------------------------------------ Int p = Ap [t] ; Int pend = (packed) ? (Ap [t+1]) : (p + Anz [t]) ; for ( ; p < pend ; p++) { // get the A(i,t) entry Int i = Ai [p] ; if (ignore_diag && i == j) continue ; Int pi = W [i] ; if (pi < pc_start) { // C(i,j) is a new entry; log its position Ci [pc] = i ; W [i] = pc ; // C(i,j) = A(i,t) * F(t,j) MULT (Cx, Cz, pc, Ax, Az, p, fx, fz, 0) ; pc++ ; } else { // C(i,j) exists in C(:,j) at position pi // C(i,j) += A(i,t) * F(t,j) MULTADD (Cx, Cz, pi, Ax, Az, p, fx, fz, 0) ; } } } } //-------------------------------------------------------------------------- // log the end of the last column of C //-------------------------------------------------------------------------- Cp [n] = pc ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_reallocate_triplet.c0000644000175100001440000000077714552026002025060 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_reallocate_triplet: reallocate triplet matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_reallocate_triplet.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sort_worker.c0000644000175100001440000001666714552026002024112 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_sort_worker: sort all columns of a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" //------------------------------------------------------------------------------ // variants for each xtype: pattern, real, complex, and zomplex //------------------------------------------------------------------------------ #if defined ( PATTERN ) #define CM_PART(Ai,Ax,Az,n,seed) TEMPLATE(cm_part) (Ai, n, seed) #define CM_QSRT(Ai,Ax,Az,p,n,seed) TEMPLATE(cm_qsrt) (Ai+p, n, seed) #define CM_SWAP(a,b) \ { \ SWAP (Int, Ai, a, b) ; \ } #elif defined ( REAL ) #define CM_PART(Ai,Ax,Az,n,seed) TEMPLATE(cm_part) (Ai, Ax, n, seed) #define CM_QSRT(Ai,Ax,Az,p,n,seed) TEMPLATE(cm_qsrt) (Ai+p, Ax+p, n, seed) #define CM_SWAP(a,b) \ { \ SWAP (Int, Ai, a, b) ; \ SWAP (Real, Ax, a, b) ; \ } #elif defined ( COMPLEX ) #define CM_PART(Ai,Ax,Az,n,seed) TEMPLATE(cm_part) (Ai, Ax, n, seed) #define CM_QSRT(Ai,Ax,Az,p,n,seed) TEMPLATE(cm_qsrt) (Ai+p,Ax+2*p,n,seed) #define CM_SWAP(a,b) \ { \ SWAP (Int, Ai, a, b) ; \ SWAP (Real, Ax, 2*(a), 2*(b)) ; \ SWAP (Real, Ax, 2*(a)+1, 2*(b)+1) ; \ } #else #define CM_PART(Ai,Ax,Az,n,seed) TEMPLATE(cm_part) (Ai, Ax, Az, n, seed) #define CM_QSRT(Ai,Ax,Az,p,n,seed) TEMPLATE(cm_qsrt) (Ai+p,Ax+p,Az+p,n,seed) #define CM_SWAP(a,b) \ { \ SWAP (Int, Ai, a, b) ; \ SWAP (Real, Ax, a, b) ; \ SWAP (Real, Az, a, b) ; \ } #endif //------------------------------------------------------------------------------ // cm_part: use a pivot to partition an array //------------------------------------------------------------------------------ // C.A.R Hoare partition method, partitions an array in-place via a pivot. // k = partition (A, n) partitions A [0:n-1] such that all entries in // A [0:k] are <= all entries in A [k+1:n-1]. // Ai [0:n-1] is the sort key, and Ax,Az [0:n-1] are satelite data. static inline Int TEMPLATE (cm_part) ( Int *Ai, // Ai [0..n-1]: indices to sort #if !defined ( PATTERN ) Real *Ax, // Ax [0..n-1]: values of A(:,j) #endif #if defined ( ZOMPLEX ) Real *Az, // Az [0..n-1] #endif const Int n, // length of Ai, Ax, Az uint64_t *seed // random number seed, modified on output ) { // select a pivot at random Int p = ((n < CM_RAND_MAX) ? cm_rand15 (seed) : cm_rand (seed)) % n ; // get the pivot value Int pivot = Ai [p] ; // At the top of the while loop, A [left+1...right-1] is considered, and // entries outside this range are in their proper place and not touched. // Since the input specification of this function is to partition A // [0..n-1], left must start at -1 and right must start at n. Int left = -1 ; Int right = n ; // keep partitioning until the left and right sides meet while (true) { // loop invariant: A [0..left] < pivot and A [right..n-1] > pivot, // so the region to be considered is A [left+1 ... right-1]. // increment left until finding an entry A [left] >= pivot do { left++ ; } while (Ai [left] < pivot) ; // decrement right until finding an entry A [right] <= pivot do { right-- ; } while (pivot < Ai [right]) ; // now A [0..left-1] < pivot and A [right+1..n-1] > pivot, but // A [left] > pivot and A [right] < pivot, so these two entries // are out of place and must be swapped. // However, if the two sides have met, the partition is finished. if (left >= right) { // A has been partitioned into A [0:right] and A [right+1:n-1]. // k = right+1, so A is split into A [0:k-1] and A [k:n-1]. return (right + 1) ; } // since A [left] > pivot and A [right] < pivot, swap them CM_SWAP (left, right) ; // after the swap this condition holds: // A [0..left] < pivot and A [right..n-1] > pivot } } //------------------------------------------------------------------------------ // cm_qsrt: recursive single-threaded quicksort //------------------------------------------------------------------------------ static void TEMPLATE (cm_qsrt) // sort A [0:n-1] ( Int *Ai, // Ai [0..n-1]: indices to sort #if !defined ( PATTERN ) Real *Ax, // Ax [0..n-1]: values of A(:,j) #endif #if defined ( ZOMPLEX ) Real *Az, // Az [0..n-1] #endif const Int n, // length of Ai, Ax, Az uint64_t *seed // random number seed ) { if (n < 20) { // in-place insertion sort on A [0:n-1], where n is small for (Int k = 1 ; k < n ; k++) { for (Int j = k ; j > 0 && Ai [j] < Ai [j-1] ; j--) { // swap A [j-1] and A [j] CM_SWAP (j-1, j) ; } } } else { // partition A [0:n-1] into A [0:k-1] and A [k:n-1] Int k = CM_PART (Ai, Ax, Az, n, seed) ; // sort each partition CM_QSRT (Ai, Ax, Az, 0, k, seed) ; // sort A [0:k-1] CM_QSRT (Ai, Ax, Az, k, n-k, seed) ; // sort A [k+1:n-1] } } //------------------------------------------------------------------------------ // t_cholmod_sort_worker //------------------------------------------------------------------------------ static void TEMPLATE (cholmod_sort_worker) ( cholmod_sparse *A // matrix to sort in-place ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Ap = (Int *) A->p ; Int *Ai = (Int *) A->i ; Int *Anz = (Int *) A->nz ; #ifndef PATTERN Real *Ax = (Real *) A->x ; #ifdef ZOMPLEX Real *Az = (Real *) A->z ; #endif #endif Int ncol = A->ncol ; bool packed = A->packed ; uint64_t seed = 42 ; for (Int j = 0 ; j < ncol ; j++) { //---------------------------------------------------------------------- // sort A(:,j) according to its row indices //---------------------------------------------------------------------- Int pa = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (pa + Anz [j]) ; Int ilast = EMPTY ; for (Int p = pa ; p < pend ; p++) { Int i = Ai [p] ; if (i < ilast) { // sort Ai, Ax, Ax [pa:pend-1] according to row index Ai CM_QSRT (Ai, Ax, Az, pa, pend - pa, &seed) ; break ; } ilast = i ; } } A->sorted = TRUE ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX #undef CM_SWAP #undef CM_PART #undef CM_QSRT Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_allocate_sparse.c0000644000175100001440000001003714552026002024654 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_allocate_sparse: allocate a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Allocate a sparse matrix. The contents A->i, A->x, and A->z (if zomplex) // exist but are not initialized. A->p and A->nz (if unpacked) are set to // zero, giving a valid sparse matrix with no entries. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_sparse) (&A, Common) ; \ return (NULL) ; \ } cholmod_sparse *CHOLMOD(allocate_sparse) ( // input: size_t nrow, // # of rows size_t ncol, // # of columns size_t nzmax, // max # of entries the matrix can hold int sorted, // true if columns are sorted int packed, // true if A is be packed (A->nz NULL), false if unpacked int stype, // the stype of the matrix (unsym, tril, or triu) int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; Common->status = CHOLMOD_OK ; if (stype != 0 && nrow != ncol) { ERROR (CHOLMOD_INVALID, "rectangular matrix with stype != 0 invalid") ; return (NULL) ; } //-------------------------------------------------------------------------- // get the xtype and dtype //-------------------------------------------------------------------------- int xtype = xdtype & 3 ; // pattern, real, complex, or zomplex int dtype = xdtype & 4 ; // double or single //-------------------------------------------------------------------------- // allocate the header for A //-------------------------------------------------------------------------- cholmod_sparse *A = CHOLMOD(calloc) (1, sizeof (cholmod_sparse), Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // fill the header //-------------------------------------------------------------------------- A->nrow = nrow ; // # rows A->ncol = ncol ; // # columns A->stype = stype ; // symmetry type A->itype = ITYPE ; // integer type A->xtype = xtype ; // pattern, real, complex, or zomplex A->dtype = dtype ; // double or single A->packed = packed ; // packed or unpacked A->sorted = sorted ; // columns sorted or unsorted //-------------------------------------------------------------------------- // allocate and clear A->p and A->nz //-------------------------------------------------------------------------- A->p = CHOLMOD(calloc) (ncol+1, sizeof (Int), Common) ; if (!packed) { A->nz = CHOLMOD(calloc) (ncol, sizeof (Int), Common) ; } RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // reallocate the sparse matrix to change A->nzmax from 0 to nzmax //-------------------------------------------------------------------------- CHOLMOD(reallocate_sparse) (nzmax, A, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_sparse) (A, "allocate_sparse:A", Common) >= 0) ; return (A) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_version.c0000644000175100001440000000073714552026002022663 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_version: CHOLMOD version //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_version.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_hypot.c0000644000175100001440000000104214552026002022327 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_hypot: complex hypot //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" double cholmod_hypot (double x, double y) { return (SuiteSparse_config_hypot (x, y)) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_allocate_sparse.c0000644000175100001440000000077014552026002024334 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_allocate_sparse: allocate a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_allocate_sparse.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_xdtype_template.c0000644000175100001440000002154214552026002026233 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_change_xdtype_template: change xtype and/or dtype //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Changes the xtype and/or dtype of X and Z. // X and Z are arrays of size 0, nz, 2*nz, and are modified (in/out). #include "cholmod_internal.h" #define TRY(statement) \ { \ statement ; \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free) (nz, exout, X_output, Common) ; \ CHOLMOD(free) (nz, ezout, Z_output, Common) ; \ return (FALSE) ; \ } \ } //------------------------------------------------------------------------------ static int CHANGE_XDTYPE2 ( Int nz, // # of entries in X and/or Z int *input_xtype, // changed to output_xtype on output // CHOLMOD_PATTERN: X and Z are NULL on input // CHOLMOD_REAL: X is size nz, and Z is NULL on input // CHOLMOD_COMPLEX: X is size 2*nz, and Z is NULL on input // CHOLMOD_ZOMPLEX: X and Z are size nz on input int output_xtype, // CHOLMOD_PATTERN: X and Z are NULL on output // CHOLMOD_REAL: X is size nz, and Z is NULL on output // CHOLMOD_COMPLEX: X is size 2*nz, and Z is NULL on output // CHOLMOD_ZOMPLEX: X and Z are size nz on output int *input_dtype, // changed to output_dtype on output int output_dtype, // input/output: void **X, // &X on input, reallocated on output void **Z, // &Z on input, reallocated on output cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- Common->status = CHOLMOD_OK ; if (*input_xtype == output_xtype && sizeof (Real_IN) == sizeof (Real_OUT)) { // nothing to do return (TRUE) ; } //-------------------------------------------------------------------------- // get the entry sizes of the input and output //-------------------------------------------------------------------------- size_t ein = sizeof (Real_IN) ; size_t exin = ein * (((*input_xtype) == CHOLMOD_PATTERN) ? 0 : (((*input_xtype) == CHOLMOD_COMPLEX) ? 2 : 1)) ; size_t ezin = ein * (((*input_xtype) == CHOLMOD_ZOMPLEX) ? 1 : 0) ; size_t eout = sizeof (Real_OUT) ; size_t exout = eout * (((output_xtype) == CHOLMOD_PATTERN) ? 0 : (((output_xtype) == CHOLMOD_COMPLEX) ? 2 : 1)) ; size_t ezout = eout * (((output_xtype) == CHOLMOD_ZOMPLEX) ? 1 : 0) ; //-------------------------------------------------------------------------- // convert the array //-------------------------------------------------------------------------- Real_IN *X_input = (Real_IN *) *X ; Real_IN *Z_input = (Real_IN *) *Z ; Real_OUT *X_output = NULL ; Real_OUT *Z_output = NULL ; switch (output_xtype) { //---------------------------------------------------------------------- case CHOLMOD_PATTERN: // convert any xtype to pattern //---------------------------------------------------------------------- break ; //---------------------------------------------------------------------- case CHOLMOD_REAL: // convert any xtype to real //---------------------------------------------------------------------- TRY (X_output = CHOLMOD(malloc) (nz, exout, Common)) ; switch (*input_xtype) { case CHOLMOD_PATTERN: // pattern to real for (Int k = 0 ; k < nz ; k++) { X_output [k] = 1 ; } break ; case CHOLMOD_REAL: // real to real for (Int k = 0 ; k < nz ; k++) { X_output [k] = (Real_OUT) X_input [k] ; } break ; case CHOLMOD_COMPLEX: // complex to real for (Int k = 0 ; k < nz ; k++) { X_output [k] = (Real_OUT) X_input [2*k] ; } break ; case CHOLMOD_ZOMPLEX: // zomplex to real for (Int k = 0 ; k < nz ; k++) { X_output [k] = (Real_OUT) X_input [k] ; } break ; } break ; //---------------------------------------------------------------------- case CHOLMOD_COMPLEX: // convert any xtype to complex //---------------------------------------------------------------------- TRY (X_output = CHOLMOD(malloc) (nz, exout, Common)) ; switch (*input_xtype) { case CHOLMOD_PATTERN: // pattern to complex for (Int k = 0 ; k < nz ; k++) { X_output [2*k ] = 1 ; X_output [2*k+1] = 0 ; } break ; case CHOLMOD_REAL: // real to complex for (Int k = 0 ; k < nz ; k++) { X_output [2*k ] = (Real_OUT) X_input [k] ; X_output [2*k+1] = 0 ; } break ; case CHOLMOD_COMPLEX: // complex to complex for (Int k = 0 ; k < 2*nz ; k++) { X_output [k] = (Real_OUT) X_input [k] ; } break ; case CHOLMOD_ZOMPLEX: // zomplex to complex for (Int k = 0 ; k < nz ; k++) { X_output [2*k ] = (Real_OUT) X_input [k] ; X_output [2*k+1] = (Real_OUT) Z_input [k] ; } break ; } break ; //---------------------------------------------------------------------- case CHOLMOD_ZOMPLEX: // convert any xtype to zomplex //---------------------------------------------------------------------- TRY (X_output = CHOLMOD(malloc) (nz, exout, Common)) ; TRY (Z_output = CHOLMOD(malloc) (nz, ezout, Common)) ; switch (*input_xtype) { case CHOLMOD_PATTERN: // pattern to zomplex for (Int k = 0 ; k < nz ; k++) { X_output [k] = 1 ; Z_output [k] = 0 ; } break ; case CHOLMOD_REAL: // real to zomplex for (Int k = 0 ; k < nz ; k++) { X_output [k] = (Real_OUT) X_input [k] ; Z_output [k] = 0 ; } break ; case CHOLMOD_COMPLEX: // complex to zomplex for (Int k = 0 ; k < nz ; k++) { X_output [k] = (Real_OUT) X_input [2*k ] ; Z_output [k] = (Real_OUT) X_input [2*k+1] ; } break ; case CHOLMOD_ZOMPLEX: // zomplex to zomplex for (Int k = 0 ; k < nz ; k++) { X_output [k] = (Real_OUT) X_input [k] ; Z_output [k] = (Real_OUT) Z_input [k] ; } break ; } break ; } //-------------------------------------------------------------------------- // free the input arrays and return result //-------------------------------------------------------------------------- CHOLMOD(free) (nz, exin, X_input, Common) ; CHOLMOD(free) (nz, ezin, Z_input, Common) ; (*X) = X_output ; (*Z) = Z_output ; (*input_xtype) = output_xtype ; (*input_dtype) = output_dtype ; return (TRUE) ; } #undef CHANGE_XDTYPE2 #undef Real_IN #undef Real_OUT Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_malloc.c0000644000175100001440000000112214552026002022745 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_malloc: malloc (int64 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_ALLOC_FUNCTION cholmod_l_malloc #define SUITESPARSE_ALLOC_FUNCTION SuiteSparse_malloc #define CHOLMOD_INT64 #include "t_cholmod_malloc.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_score_comp.c0000644000175100001440000000075414552026002023326 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_score_comp: for sorting supernodes //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_score_comp.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_add.c0000644000175100001440000002127614552026002022252 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_add: C = alpha*A + beta*B //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // The C matrix is returned as packed and sorted. A and B must have the same // xtype, unless one of them is pattern, in which case only the patterns of A // and B are used, and C has xtype of pattern. A, B, and C must all have the // same dtype. If A->stype and B->stype differ, then C is computed as // unsymmetric (stype of 0). #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_sparse) (&C, Common) ; \ CHOLMOD(free_sparse) (&A2, Common) ; \ CHOLMOD(free_sparse) (&B2, Common) ; \ return (NULL) ; \ } //------------------------------------------------------------------------------ // t_cholmod_add_worker template //------------------------------------------------------------------------------ #define PATTERN #include "t_cholmod_add_worker.c" #define DOUBLE #define REAL #include "t_cholmod_add_worker.c" #define COMPLEX #include "t_cholmod_add_worker.c" #define ZOMPLEX #include "t_cholmod_add_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_add_worker.c" #define COMPLEX #include "t_cholmod_add_worker.c" #define ZOMPLEX #include "t_cholmod_add_worker.c" //------------------------------------------------------------------------------ // cholmod_add: C = alpha*A + beta*B //------------------------------------------------------------------------------ cholmod_sparse *CHOLMOD(add) // return C = alpha*A + beta*B ( // input: cholmod_sparse *A, // input matrix cholmod_sparse *B, // input matrix double alpha [2], // scale factor for A (two entries used if complex) double beta [2], // scale factor for B (two entries used if complex) int mode, // 2: numerical (conj) if A and/or B are symmetric, // 1: numerical (non-conj.) if A and/or B are symmetric. // 0: pattern int sorted, // ignored; C is now always returned as sorted cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs and determine the xtype and dtype of C //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_SPARSE_MATRIX_INVALID (A, NULL) ; RETURN_IF_SPARSE_MATRIX_INVALID (B, NULL) ; Common->status = CHOLMOD_OK ; cholmod_sparse *A2 = NULL, *B2 = NULL, *C = NULL ; if (A->nrow != B->nrow || A->ncol != B->ncol) { ERROR (CHOLMOD_INVALID, "A and B dimensions do not match") ; return (NULL) ; } mode = RANGE (mode, 0, 2) ; int axtype = A->xtype ; int bxtype = B->xtype ; if (mode == 0 || axtype == CHOLMOD_PATTERN || bxtype == CHOLMOD_PATTERN) { // treat A and B as if they are pattern-only matrices; C is pattern mode = 0 ; axtype = CHOLMOD_PATTERN ; bxtype = CHOLMOD_PATTERN ; } if (axtype != bxtype) { ERROR (CHOLMOD_INVALID, "A and B xtypes do not match") ; return (NULL) ; } if (mode != 0 && A->dtype != B->dtype) { ERROR (CHOLMOD_INVALID, "A and B dtypes do not match") ; return (NULL) ; } int xtype = axtype ; int dtype = A->dtype ; ASSERT (CHOLMOD(dump_sparse) (A, "add:A", Common) >= 0) ; ASSERT (CHOLMOD(dump_sparse) (B, "add:B", Common) >= 0) ; //-------------------------------------------------------------------------- // get the sizes of the entries of C, A, and B //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- // convert/sort A and/or B, if needed //-------------------------------------------------------------------------- if (A->stype == B->stype) { //---------------------------------------------------------------------- // A and B have the same stype, but make sure they are both sorted //---------------------------------------------------------------------- // A2 = sorted copy of A, if A is not sorted, with same stype as A if (!A->sorted) { A2 = CHOLMOD(copy) (A, A->stype, mode, Common) ; RETURN_IF_ERROR ; CHOLMOD(sort) (A2, Common) ; RETURN_IF_ERROR ; A = A2 ; } // B2 = sorted copy of B, if B is not sorted, with same stype as B if (!B->sorted) { B2 = CHOLMOD(copy) (B, B->stype, mode, Common) ; RETURN_IF_ERROR ; CHOLMOD(sort) (B2, Common) ; RETURN_IF_ERROR ; B = B2 ; } } else { //---------------------------------------------------------------------- // the stype of A and B differ, so make both unsymmetric and sorted //---------------------------------------------------------------------- if (!(A->stype == 0 && A->sorted)) { // A2 = sorted unsymmetric copy of A with stype of zero A2 = CHOLMOD(copy) (A, 0, mode, Common) ; RETURN_IF_ERROR ; if (!A2->sorted) { CHOLMOD(sort) (A2, Common) ; RETURN_IF_ERROR ; } A = A2 ; } if (!(B->stype == 0 && B->sorted)) { // B2 = sorted unsymmetric copy of A with stype of zero B2 = CHOLMOD(copy) (B, 0, mode, Common) ; RETURN_IF_ERROR ; if (!B2->sorted) { CHOLMOD(sort) (B2, Common) ; RETURN_IF_ERROR ; } B = B2 ; } } // C, A, and B now all have the same stype, and are sorted ASSERT (A->stype == B->stype) ; ASSERT (A->sorted) ; ASSERT (B->sorted) ; //-------------------------------------------------------------------------- // allocate C //-------------------------------------------------------------------------- size_t nzmax = CHOLMOD(nnz) (A, Common) + CHOLMOD(nnz) (B, Common) ; C = CHOLMOD(allocate_sparse) (A->nrow, A->ncol, nzmax, /* C is sorted: */ TRUE, /* C is packed: */ TRUE, A->stype, xtype + dtype, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // C = alpha*A + beta*B //-------------------------------------------------------------------------- switch ((xtype + dtype) % 8) { default: p_cholmod_add_worker (C, A, B, alpha, beta, Common) ; break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_add_worker (C, A, B, alpha, beta, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_add_worker (C, A, B, alpha, beta, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_add_worker (C, A, B, alpha, beta, Common) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_add_worker (C, A, B, alpha, beta, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_add_worker (C, A, B, alpha, beta, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_add_worker (C, A, B, alpha, beta, Common) ; break ; } //-------------------------------------------------------------------------- // free temporary copies of A and B, if created //-------------------------------------------------------------------------- CHOLMOD(free_sparse) (&A2, Common) ; CHOLMOD(free_sparse) (&B2, Common) ; //-------------------------------------------------------------------------- // compact the space of C //-------------------------------------------------------------------------- size_t cnz = CHOLMOD(nnz) (C, Common) ; CHOLMOD(reallocate_sparse) (cnz, C, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_sparse) (C, "add:C", Common) >= 0) ; return (C) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_factor_to_sparse.c0000644000175100001440000000100114552026002024514 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_factor_to_sparse: convert factor to sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_factor_to_sparse.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_clear_flag.c0000644000175100001440000000361514552026002023576 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_clear_flag: clear Common->Flag //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" // cholmod_clear_flag increments Common->mark to ensure // Common->Flag [0..Common->nrow-1] < mark holds. If incrementing // Common->mark results in integer overflow, Flag is set to EMPTY and // Common->mark is set to zero. int64_t CHOLMOD(clear_flag) // returns the new Common->mark ( cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (EMPTY) ; //-------------------------------------------------------------------------- // increment the mark //-------------------------------------------------------------------------- Common->mark++ ; //-------------------------------------------------------------------------- // check for int32 or int64 overflow //-------------------------------------------------------------------------- bool overflow = (Common->mark <= 0) ; #if defined ( CHOLMOD_INT32 ) overflow = overflow || (Common->mark > INT32_MAX) ; #endif if (overflow) { Common->mark = 0 ; CHOLMOD(set_empty) (Common->Flag, Common->nrow) ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (check_flag (Common)) ; return (Common->mark) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_zeros.c0000644000175100001440000000075514552026002022340 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_zeros: allocate an all-zero dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_zeros.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_free_triplet.c0000644000175100001440000000420614552026002024200 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_free_triplet: free triplet matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" int CHOLMOD(free_triplet) ( // input/output: cholmod_triplet **T, // handle of triplet matrix to free cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; if (T == NULL || (*T) == NULL) { // T is already freed; nothing to do return (TRUE) ; } //-------------------------------------------------------------------------- // get the sizes of the entries //-------------------------------------------------------------------------- size_t ei = sizeof (Int) ; size_t e = ((*T)->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * (((*T)->xtype == CHOLMOD_PATTERN) ? 0 : (((*T)->xtype == CHOLMOD_COMPLEX) ? 2 : 1)) ; size_t ez = e * (((*T)->xtype == CHOLMOD_ZOMPLEX) ? 1 : 0) ; size_t nz = (*T)->nzmax ; //-------------------------------------------------------------------------- // free the four arrays //-------------------------------------------------------------------------- CHOLMOD(free) (nz, ei, (*T)->i, Common) ; CHOLMOD(free) (nz, ei, (*T)->j, Common) ; CHOLMOD(free) (nz, ex, (*T)->x, Common) ; CHOLMOD(free) (nz, ez, (*T)->z, Common) ; //-------------------------------------------------------------------------- // free the header and return result //-------------------------------------------------------------------------- (*T) = CHOLMOD(free) (1, sizeof (cholmod_triplet), (*T), Common) ; return (TRUE) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_copy_dense.c0000644000175100001440000000075314552026002023637 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_copy_dense: copy a dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_copy_dense.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_alloc_work.c0000644000175100001440000000077414552026002023333 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_alloc_work: alloc workspace (double/single, int32) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_alloc_work.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_alloc_factor.c0000644000175100001440000000076614552026002023630 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_alloc_factor: allocate a simplicial factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_alloc_factor.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_reallocate_column.c0000644000175100001440000000100314552026002024651 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_reallocate_column: reallocate a column of a factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_reallocate_column.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_free_sparse.c0000644000175100001440000000075414552026002024006 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_free_sparse: free sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_free_sparse.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_copy_dense2.c0000644000175100001440000000075514552026002023723 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_copy_dense2: copy a dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_copy_dense2.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_unsym_template.c0000644000175100001440000000433414552026002026662 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_transpose_unsym_template //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // C = A', C = A(:,f)', C = A(p,:)', or C = A(p,f)'; A and C are unsymmetric //------------------------------------------------------------------------------ // The including file must define or undef PACKED, NUMERIC, and FSET // define PACKED: if A->packed is true, undefine if A->packed is false // define NUMERIC: if computing values and pattern of C, undefine it if // computing just the column counts of C. //------------------------------------------------------------------------------ { #undef N #ifdef FSET #define N nf #else #define N ncol #endif for (Int k = 0 ; k < N ; k++) { //---------------------------------------------------------------------- // get the fset, if present //---------------------------------------------------------------------- #ifdef FSET Int j = fset [k] ; #else Int j = k ; #endif //---------------------------------------------------------------------- // get A(:,k) //---------------------------------------------------------------------- Int p = Ap [j] ; #ifdef PACKED Int pend = Ap [j+1] ; #else Int pend = p + Anz [j] ; #endif //---------------------------------------------------------------------- // scan entries in A(:,k) //---------------------------------------------------------------------- for ( ; p < pend ; p++) { // get A(i,j) and count it or get its place in C #ifdef NUMERIC Int pc = #endif Wi [Ai [p]]++ ; #ifdef NUMERIC // C(j,i) = conj (A(i,j)) ASSIGN_CONJ_OR_NCONJ (Cx, Cz, pc, Ax, Az, p) ; Ci [pc] = j ; #endif } } } #undef FSET #undef PACKED Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_worker.c0000644000175100001440000001152014552026002024054 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_copy_worker: copy sparse matrix (change of stype) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // A is symmetric upper or lower, and C is unsymmetric. Both are square. #include "cholmod_template.h" static void TEMPLATE (cholmod_copy_worker) ( cholmod_sparse *C, // output matrix cholmod_sparse *A, // input matrix, not modified bool ignore_diag, // if true, ignore diagonal cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- Int n = A->ncol ; ASSERT (A->stype != 0) ; ASSERT (C->stype == 0) ; ASSERT (n == A->ncol) ; ASSERT (n == C->nrow) ; ASSERT (n == C->ncol) ; ASSERT (C->packed) ; ASSERT (C->sorted == A->sorted) ; ASSERT (C->dtype == A->dtype) ; ASSERT (C->xtype == A->xtype || C->xtype == CHOLMOD_PATTERN) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Wj = (Int *) Common->Iwork ; // size n integer workspace Int *Ap = (Int *) A->p ; Int *Anz = (Int *) A->nz ; Int *Ai = (Int *) A->i ; #ifndef PATTERN Real *Ax = (Real *) A->x ; #ifdef ZOMPLEX Real *Az = (Real *) A->z ; #endif #endif bool packed = A->packed ; Int *Ci = (Int *) C->i ; #ifndef PATTERN Real *Cx = (Real *) C->x ; #ifdef ZOMPLEX Real *Cz = (Real *) C->z ; #endif #endif bool keep_diag = !ignore_diag ; //-------------------------------------------------------------------------- // create an unsymmetric matrix C from a symmetric matrix A //-------------------------------------------------------------------------- // place A(i,j) in C(:,k) #define ASSIGN_CIJ(i,j) \ { \ Int q = Wj [j]++ ; \ ASSIGN (Cx, Cz, q, Ax, Az, p) ; \ Ci [q] = i ; \ } // place conj(A(i,j)) or A(i,j) in C(:,k) #define ASSIGN_CIJ_CONJ_OR_NCONJ(i,j) \ { \ Int q = Wj [i]++ ; \ ASSIGN_CONJ_OR_NCONJ (Cx, Cz, q, Ax, Az, p) ; \ Ci [q] = j ; \ } if (A->stype > 0) { //---------------------------------------------------------------------- // A is symmetric upper //---------------------------------------------------------------------- for (Int j = 0 ; j < n ; j++) { Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { // get A(i,j) Int i = Ai [p] ; // skip entries in strictly lower part if (i > j) continue ; if (i == j) { // place diagonal entry A(i,i) in C(:,i) if (keep_diag) ASSIGN_CIJ (i,i) ; } else { // place A(i,j) in C(:,j) and conj(A(i,j)) in C(:,i) ASSIGN_CIJ (i,j) ; ASSIGN_CIJ_CONJ_OR_NCONJ (i,j) ; } } } } else // A->stype < 0 { //---------------------------------------------------------------------- // A is symmetric lower //---------------------------------------------------------------------- for (Int j = 0 ; j < n ; j++) { Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { // get A(i,j) Int i = Ai [p] ; // skip entries in strictly upper part if (i < j) continue ; if (i == j) { // place diagonal entry A(i,i) in C(:,i) if (keep_diag) ASSIGN_CIJ (i,i) ; } else { // place A(i,j) in C(:,j) and conj(A(i,j)) in C(:,i) ASSIGN_CIJ (i,j) ; ASSIGN_CIJ_CONJ_OR_NCONJ (i,j) ; } } } } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX #undef NCONJUGATE Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_start.c0000644000175100001440000000075314552026002022644 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_start: start CHOLMOD (int64 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_start.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_transpose_unsym.c0000644000175100001440000000100014552026002024742 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_transpose_unsym: unsymmetric permuted transpose //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_transpose_unsym.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_allocate_work.c0000644000175100001440000000130614552026002024015 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_allocate_work: alloc workspace (double, int32) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" int cholmod_allocate_work ( // input: size_t nrow, size_t iworksize, size_t xworksize, cholmod_common *Common ) { return (cholmod_alloc_work (nrow, iworksize, xworksize, CHOLMOD_DOUBLE, Common)) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_spzeros.c0000644000175100001440000000075014552026002023211 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_spzeros: all-zero sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_spzeros.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_free_sparse.c0000644000175100001440000000435414552026002024016 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_free_sparse: free sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" int CHOLMOD(free_sparse) ( // input/output: cholmod_sparse **A, // handle of sparse matrix to free cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; if (A == NULL || (*A) == NULL) { // A is already freed; nothing to do return (TRUE) ; } //-------------------------------------------------------------------------- // get the sizes of the entries //-------------------------------------------------------------------------- size_t ei = sizeof (Int) ; size_t e = ((*A)->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * (((*A)->xtype == CHOLMOD_PATTERN) ? 0 : (((*A)->xtype == CHOLMOD_COMPLEX) ? 2 : 1)) ; size_t ez = e * (((*A)->xtype == CHOLMOD_ZOMPLEX) ? 1 : 0) ; size_t nzmax = (*A)->nzmax ; size_t ncol = (*A)->ncol ; //-------------------------------------------------------------------------- // free the five arrays //-------------------------------------------------------------------------- CHOLMOD(free) (ncol+1, ei, (*A)->p, Common) ; CHOLMOD(free) (ncol, ei, (*A)->nz, Common) ; CHOLMOD(free) (nzmax, ei, (*A)->i, Common) ; CHOLMOD(free) (nzmax, ex, (*A)->x, Common) ; CHOLMOD(free) (nzmax, ez, (*A)->z, Common) ; //-------------------------------------------------------------------------- // free the header and return result //-------------------------------------------------------------------------- (*A) = CHOLMOD(free) (1, sizeof (cholmod_sparse), (*A), Common) ; return (TRUE) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_transpose_sym.c0000644000175100001440000000077014552026002024101 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_transpose_sym: symmetric permuted transpose //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_transpose_sym.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_xdtype.c0000644000175100001440000001743214552026002024343 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_xtype: change xtype and/or dtype of an object //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" //------------------------------------------------------------------------------ // t_change_xdtype_template //------------------------------------------------------------------------------ #define CHANGE_XDTYPE2 change_xdtype_d2d #define Real_IN double #define Real_OUT double #include "t_cholmod_change_xdtype_template.c" #define CHANGE_XDTYPE2 change_xdtype_d2s #define Real_IN double #define Real_OUT float #include "t_cholmod_change_xdtype_template.c" #define CHANGE_XDTYPE2 change_xdtype_s2d #define Real_IN float #define Real_OUT double #include "t_cholmod_change_xdtype_template.c" #define CHANGE_XDTYPE2 change_xdtype_s2s #define Real_IN float #define Real_OUT float #include "t_cholmod_change_xdtype_template.c" //------------------------------------------------------------------------------ // change_xdtype: change the xtype and/or dtype of an array //------------------------------------------------------------------------------ static int change_xdtype ( Int nz, // # of entries int *input_xtype, // xtype of input: pattern, real, complex, zomplex int output_xtype, // xtype of output: pattern, real, complex, zomplex int *input_dtype, // dtype of input: double or single int output_dtype, // dtype of output: double or single void **X, // X array for real, complex, zomplex cases void **Z, // Z array for zomplex case cholmod_common *Common ) { if (*input_dtype == CHOLMOD_DOUBLE) { if (output_dtype == CHOLMOD_DOUBLE) { // double to double return (change_xdtype_d2d (nz, input_xtype, output_xtype, input_dtype, output_dtype, X, Z, Common)) ; } else { // double to single return (change_xdtype_d2s (nz, input_xtype, output_xtype, input_dtype, output_dtype, X, Z, Common)) ; } } else { if (output_dtype == CHOLMOD_DOUBLE) { // single to double return (change_xdtype_s2d (nz, input_xtype, output_xtype, input_dtype, output_dtype, X, Z, Common)) ; } else { // single to single return (change_xdtype_s2s (nz, input_xtype, output_xtype, input_dtype, output_dtype, X, Z, Common)) ; } } } //------------------------------------------------------------------------------ // cholmod_sparse_xtype: change xtype and/or dtype of a sparse matrix //------------------------------------------------------------------------------ int CHOLMOD(sparse_xtype) ( // input: int to_xdtype, // requested xtype and dtype // input/output: cholmod_sparse *A, // sparse matrix to change cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_SPARSE_MATRIX_INVALID (A, FALSE) ; //-------------------------------------------------------------------------- // change the xtype and/or dtype //-------------------------------------------------------------------------- int output_xtype = to_xdtype & 3 ; // pattern, real, complex, or zomplex int output_dtype = to_xdtype & 4 ; // double or single return (change_xdtype (A->nzmax, &(A->xtype), output_xtype, &(A->dtype), output_dtype, &(A->x), &(A->z), Common)) ; } //------------------------------------------------------------------------------ // cholmod_triplet_xtype: change xtype and/or dtype of a triplet matrix //------------------------------------------------------------------------------ int CHOLMOD(triplet_xtype) ( // input: int to_xdtype, // requested xtype and dtype // input/output: cholmod_triplet *T, // triplet matrix to change cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_TRIPLET_MATRIX_INVALID (T, FALSE) ; //-------------------------------------------------------------------------- // change the xtype and/or dtype //-------------------------------------------------------------------------- int output_xtype = to_xdtype & 3 ; // pattern, real, complex, or zomplex int output_dtype = to_xdtype & 4 ; // double or single return (change_xdtype (T->nzmax, &(T->xtype), output_xtype, &(T->dtype), output_dtype, &(T->x), &(T->z), Common)) ; } //------------------------------------------------------------------------------ // cholmod_dense_xtype: change xtype and/or dtype of a dense matrix //------------------------------------------------------------------------------ int CHOLMOD(dense_xtype) ( // input: int to_xdtype, // requested xtype and dtype // input/output: cholmod_dense *X, // dense matrix to change cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_DENSE_MATRIX_INVALID (X, FALSE) ; //-------------------------------------------------------------------------- // change the xtype and/or dtype //-------------------------------------------------------------------------- int output_xtype = to_xdtype & 3 ; // real, complex, or zomplex int output_dtype = to_xdtype & 4 ; // double or single if (output_xtype <= CHOLMOD_PATTERN) { // output_xtype not supported ERROR (CHOLMOD_INVALID, "invalid xtype") ; return (FALSE) ; } return (change_xdtype (X->nzmax, &(X->xtype), output_xtype, &(X->dtype), output_dtype, &(X->x), &(X->z), Common)) ; } //------------------------------------------------------------------------------ // cholmod_factor_xtype: change xtype and/or dtype of a factor //------------------------------------------------------------------------------ int CHOLMOD(factor_xtype) ( // input: int to_xdtype, // requested xtype and dtype // input/output: cholmod_factor *L, // factor to change cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_FACTOR_INVALID (L, FALSE) ; //-------------------------------------------------------------------------- // change the xtype and/or dtype //-------------------------------------------------------------------------- int output_xtype = to_xdtype & 3 ; // real, complex, or zomplex int output_dtype = to_xdtype & 4 ; // double or single if (output_xtype <= CHOLMOD_PATTERN || (L->is_super && output_xtype == CHOLMOD_ZOMPLEX)) { // output_xtype not supported ERROR (CHOLMOD_INVALID, "invalid xtype") ; return (FALSE) ; } Int nzmax = L->is_super ? L->xsize : L->nzmax ; return (change_xdtype (nzmax, &(L->xtype), output_xtype, &(L->dtype), output_dtype, &(L->x), &(L->z), Common)) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_factor_to_sparse.c0000644000175100001440000000100314552026002025031 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_factor_to_sparse: convert factor to sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_factor_to_sparse.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_dense_to_sparse.c0000644000175100001440000000100014552026002024333 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_dense_to_sparse: convert a dense matrix to sparse //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_dense_to_sparse.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_dense2.c0000644000175100001440000001053314552026002023726 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_dense2: copy a dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Copies a dense matrix X into another dense matrix Y, which must already // be allocated on input. The dimensions, xtype, and dtype of X and Y must // match, but X->d and Y->d can differ. #include "cholmod_internal.h" //------------------------------------------------------------------------------ // t_cholmod_copy_dense2_worker template //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_copy_dense2_worker.c" #define COMPLEX #include "t_cholmod_copy_dense2_worker.c" #define ZOMPLEX #include "t_cholmod_copy_dense2_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_copy_dense2_worker.c" #define COMPLEX #include "t_cholmod_copy_dense2_worker.c" #define ZOMPLEX #include "t_cholmod_copy_dense2_worker.c" //------------------------------------------------------------------------------ int CHOLMOD(copy_dense2) ( // input: cholmod_dense *X, // input dense matrix // input/output: cholmod_dense *Y, // output dense matrix (already allocated on input) cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_DENSE_MATRIX_INVALID (X, FALSE) ; RETURN_IF_DENSE_MATRIX_INVALID (Y, FALSE) ; Common->status = CHOLMOD_OK ; if (X->nrow != Y->nrow || X->ncol != Y->ncol || X->xtype != Y->xtype || X->dtype != Y->dtype) { ERROR (CHOLMOD_INVALID, "X and Y: wrong dimensions or type") ; return (FALSE) ; } //-------------------------------------------------------------------------- // get the sizes of the entries //-------------------------------------------------------------------------- size_t e = (X->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * ((X->xtype == CHOLMOD_COMPLEX) ? 2 : 1) ; size_t ez = e * ((X->xtype == CHOLMOD_ZOMPLEX) ? 1 : 0) ; //-------------------------------------------------------------------------- // copy X = Y //-------------------------------------------------------------------------- if (X->d == Y->d) { //---------------------------------------------------------------------- // no change of leading dimension: copy all of X and Y as-is //---------------------------------------------------------------------- size_t nz = X->d * X->ncol ; if (X->x != NULL) memcpy (Y->x, X->x, nz * ex) ; if (X->z != NULL) memcpy (Y->z, X->z, nz * ez) ; } else { //---------------------------------------------------------------------- // copy Y into X, with possible change of leading dimension //---------------------------------------------------------------------- switch ((X->xtype + X->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_copy_dense2_worker (X, Y) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_copy_dense2_worker (X, Y) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_copy_dense2_worker (X, Y) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_copy_dense2_worker (X, Y) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_copy_dense2_worker (X, Y) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_copy_dense2_worker (X, Y) ; break ; } } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (TRUE) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_reallocate_sparse.c0000644000175100001440000000346514552026002025212 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_reallocate_sparse: reallocate sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Change the max # of nonzeros that can be held in a sparse matrix A. #include "cholmod_internal.h" int CHOLMOD(reallocate_sparse) ( // input: size_t nznew, // new max # of nonzeros the sparse matrix can hold // input/output: cholmod_sparse *A, // sparse matrix to reallocate cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_XTYPE_IS_INVALID (A->xtype, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // reallocate the sparse matrix //-------------------------------------------------------------------------- nznew = MAX (1, nznew) ; // ensure A can hold at least 1 entry int nint = 1 ; // reallocate just A->i CHOLMOD(realloc_multiple) (nznew, nint, A->xtype + A->dtype, &(A->i), NULL, &(A->x), &(A->z), &(A->nzmax), Common) ; //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (Common->status == CHOLMOD_OK) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_free_triplet.c0000644000175100001440000000075514552026002023662 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_free_triplet: free triplet matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_free_triplet.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_2_template.c0000644000175100001440000002114214552026002026411 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_change_factor_2_template //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Converts a simplicial numeric factor: to/from LL' and LDL', either // out-of-place or in-place. #ifdef OUT_OF_PLACE // the new L is created in new space: Li2, Lx2, Lz2 #define Li_NEW Li2 #define Lx_NEW Lx2 #define Lz_NEW Lz2 #else // L is modified in its existing space: Li, Lx, and Lz #define Li_NEW Li #define Lx_NEW Lx #define Lz_NEW Lz #endif #ifdef IN_PLACE // Li is not modified. Entries in Lx and Lz are changed but not moved // to a different place in Lx and Lz #define p_NEW p #else #define p_NEW pnew #endif //------------------------------------------------------------------------------ { #ifndef IN_PLACE Int pnew = 0 ; #endif if (make_ll) { //---------------------------------------------------------------------- // convert an LDL' factorization to LL' //---------------------------------------------------------------------- for (Int j = 0 ; j < n ; j++) { //------------------------------------------------------------------ // get column L(:,j) //------------------------------------------------------------------ Int p = Lp [j] ; Int len = Lnz [j] ; // get the diagonal entry, djj = D(j,j) Real djj [1] ; ASSIGN_REAL (djj, 0, Lx, p) ; if (djj [0] <= 0) { //-------------------------------------------------------------- // the matrix is not positive definite //-------------------------------------------------------------- // The matrix is not postive-definite and cannot be converted // to LL'. The column L(:,j) is moved to its new space but not // numerically modified so it can be converted back to a valid // LDL' factorization. if (L->minor == (size_t) n) { ERROR (CHOLMOD_NOT_POSDEF, "L not positive definite") ; L->minor = j ; } #ifndef IN_PLACE for (Int k = 0 ; k < len ; k++) { Li_NEW [p_NEW+k] = Li [p+k] ; ASSIGN (Lx_NEW, Lz_NEW, p_NEW+k, Lx, Lz, p+k) ; } #endif } else { //-------------------------------------------------------------- // convert L(:,j) from an LDL' factorization to LL' //-------------------------------------------------------------- // L(j,j) = sqrt (D(j,j)) Real ljj [1] ; ljj [0] = sqrt (djj [0]) ; #ifndef IN_PLACE Li_NEW [p_NEW] = j ; #endif ASSIGN_REAL (Lx_NEW, p_NEW, ljj, 0) ; CLEAR_IMAG (Lx_NEW, Lz_NEW, p_NEW) ; // L(j+1:n,j) = L(j+1:n,j) * L(j,j) for (Int k = 1 ; k < len ; k++) { #ifndef IN_PLACE Li_NEW [p_NEW+k] = Li [p+k] ; #endif MULT_REAL (Lx_NEW, Lz_NEW, p_NEW+k, Lx, Lz, p+k, ljj, 0) ; } } //------------------------------------------------------------------ // grow column L(:,j) if requested, and advance to column j+1 //------------------------------------------------------------------ #ifndef IN_PLACE Lp [j] = p_NEW ; #ifdef OUT_OF_PLACE if (grow) len = grow_column (len, grow1, grow2, n-j) ; #endif p_NEW += len ; #endif } // log the end of the last column #ifndef IN_PLACE Lp [n] = p_NEW ; #endif } else if (make_ldl) { //---------------------------------------------------------------------- // convert an LL' factorization to LDL' //---------------------------------------------------------------------- for (Int j = 0 ; j < n ; j++) { //------------------------------------------------------------------ // get column L(:,j) //------------------------------------------------------------------ Int len = Lnz [j] ; Int p = Lp [j] ; // get the diagonal entry, ljj = L(j,j) Real ljj [1] ; ASSIGN_REAL (ljj, 0, Lx, p) ; if (ljj [0] <= 0) { //-------------------------------------------------------------- // the matrix is not positive definite //-------------------------------------------------------------- // do not modify L(:,j), just copy it to its new place #ifndef IN_PLACE for (Int k = 0 ; k < len ; k++) { Li_NEW [p_NEW+k] = Li [p+k] ; ASSIGN (Lx_NEW, Lz_NEW, p_NEW+k, Lx, Lz, p+k) ; } #endif } else { //-------------------------------------------------------------- // convert L(:,j) from an LL' factorization to LDL' //-------------------------------------------------------------- // D(j,j) = L(j,j)^2 #ifndef IN_PLACE Li_NEW [p_NEW] = j ; #endif Real djj [1] ; djj [0] = ljj [0] * ljj [0] ; ASSIGN_REAL (Lx_NEW, p_NEW, djj, 0) ; CLEAR_IMAG (Lx_NEW, Lz_NEW, p_NEW) ; // L(j+1:n) = L(j+1:n) / L(j,j) for (Int k = 1 ; k < len ; k++) { #ifndef IN_PLACE Li_NEW [p_NEW+k] = Li [p+k] ; #endif DIV_REAL (Lx_NEW, Lz_NEW, p_NEW+k, Lx, Lz, p+k, ljj, 0) ; } } //------------------------------------------------------------------ // grow column L(:,j) if requested, and advance to column j+1 //------------------------------------------------------------------ #ifndef IN_PLACE Lp [j] = p_NEW ; #ifdef OUT_OF_PLACE if (grow) len = grow_column (len, grow1, grow2, n-j) ; #endif p_NEW += len ; #endif } // log the end of the last column #ifndef IN_PLACE Lp [n] = p_NEW ; #endif } else { //---------------------------------------------------------------------- // factorization remains as is, but space may be revised //---------------------------------------------------------------------- #ifndef IN_PLACE for (Int j = 0 ; j < n ; j++) { //------------------------------------------------------------------ // get column L(:,j) //------------------------------------------------------------------ Int len = Lnz [j] ; Int p = Lp [j] ; //------------------------------------------------------------------ // move L(:,j) to its new position //------------------------------------------------------------------ #ifdef TO_PACKED if (p_NEW < p) #endif { for (Int k = 0 ; k < len ; k++) { Li_NEW [p_NEW+k] = Li [p+k] ; ASSIGN (Lx_NEW, Lz_NEW, p_NEW+k, Lx, Lz, p+k) ; } Lp [j] = p_NEW ; } //------------------------------------------------------------------ // grow column L(:,j) if requested, and advance to column j+1 //------------------------------------------------------------------ #ifdef OUT_OF_PLACE if (grow) len = grow_column (len, grow1, grow2, n-j) ; #endif p_NEW += len ; } // log the end of the last column Lp [n] = p_NEW ; #endif } } #undef OUT_OF_PLACE #undef TO_PACKED #undef IN_PLACE #undef Li_NEW #undef Lx_NEW #undef Lz_NEW #undef p_NEW Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_reallocate_factor.c0000644000175100001440000000076714552026002024652 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_reallocate_factor: reallocate a factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_reallocate_factor.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_free_dense.c0000644000175100001440000000074714552026002023276 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_free_dense: free dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_free_dense.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_triplet_to_sparse.c0000644000175100001440000000077714552026002025257 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_triplet_to_sparse: convert triplet to sparse //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_triplet_to_sparse.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_set_empty.c0000644000175100001440000000076114552026002023517 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_set_empty: set an int64 array to EMPTY //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_set_empty.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_nnz.c0000644000175100001440000000342214552026002022320 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_nnz: # of entries in a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // returns the # of entries held in a sparse matrix data structure. If A is // symmetric and held in either upper/lower form, then only those entries // in the upper/lower part are counted. #include "cholmod_internal.h" int64_t CHOLMOD(nnz) // return # of entries in the sparse matrix ( // input: cholmod_sparse *A, // sparse matrix to query cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (EMPTY) ; RETURN_IF_SPARSE_MATRIX_INVALID (A, EMPTY) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // get the # of entries //-------------------------------------------------------------------------- if (!(A->packed)) { // A is held in unpacked form, so nnz(A) is sum (Anz [0..ncol-1]) int64_t anz = 0 ; int64_t ncol = A->ncol ; Int *Anz = (Int *) A->nz ; for (int64_t j = 0 ; j < ncol ; j++) { anz += (int64_t) Anz [j] ; } return (anz) ; } else { // A is held in packed form, so nnz(A) is just Ap [ncol] return ((int64_t) ((Int *) A->p) [A->ncol]) ; } } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_realloc_multiple.c0000644000175100001440000001233214552026002025047 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_realloc_multiple: multiple realloc (int64/int32) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" int CHOLMOD(realloc_multiple) // returns true if successful, false otherwise ( // input: size_t nnew, // # of items in newly reallocate memory int nint, // 0: do not allocate I or J, 1: just I, 2: both I and J int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX) // input/output: void **I, // integer block of memory (int32_t or int64_t) void **J, // integer block of memory (int32_t or int64_t) void **X, // real or complex, double or single, block void **Z, // zomplex only: double or single block size_t *n, // current size of I, J, X, and/or Z blocks on input, // changed to nnew on output, if successful cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; //-------------------------------------------------------------------------- // get the xtype and dtype //-------------------------------------------------------------------------- int xtype = xdtype & 3 ; // pattern, real, complex, or zomplex int dtype = xdtype & 4 ; // double or single if (nint < 1 && xtype == CHOLMOD_PATTERN) { return (TRUE) ; // nothing to reallocate } //-------------------------------------------------------------------------- // get the problem size //-------------------------------------------------------------------------- size_t ni = (*n) ; // size of I, if present size_t nj = (*n) ; // size of J, if present size_t nx = (*n) ; // size of X, if present size_t nz = (*n) ; // size of Z, if present size_t ei = sizeof (Int) ; size_t e = (dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * ((xtype == CHOLMOD_PATTERN) ? 0 : ((xtype == CHOLMOD_COMPLEX) ? 2 : 1)) ; size_t ez = e * ((xtype == CHOLMOD_ZOMPLEX) ? 1 : 0) ; if ((nint > 0 && I == NULL) || (nint > 1 && J == NULL) || (ex > 0 && X == NULL) || (ez > 0 && Z == NULL)) { // input argument missing if (Common->status != CHOLMOD_OUT_OF_MEMORY) { ERROR (CHOLMOD_INVALID, "argument missing") ; } return (FALSE) ; } //-------------------------------------------------------------------------- // reallocate all of the blocks //-------------------------------------------------------------------------- if (nint > 0) (*I) = CHOLMOD(realloc) (nnew, ei, *I, &ni, Common) ; if (nint > 1) (*J) = CHOLMOD(realloc) (nnew, ei, *J, &nj, Common) ; if (ex > 0) (*X) = CHOLMOD(realloc) (nnew, ex, *X, &nx, Common) ; if (ez > 0) (*Z) = CHOLMOD(realloc) (nnew, ez, *Z, &nz, Common) ; //-------------------------------------------------------------------------- // handle any errors //-------------------------------------------------------------------------- if (Common->status < CHOLMOD_OK) { if ((*n) == 0) { // free all blocks if they were just freshly allocated if (nint > 0) (*I) = CHOLMOD(free) (ni, ei, *I, Common) ; if (nint > 1) (*J) = CHOLMOD(free) (nj, ei, *J, Common) ; if (ex > 0) (*X) = CHOLMOD(free) (nx, ex, *X, Common) ; if (ez > 0) (*Z) = CHOLMOD(free) (nz, ez, *Z, Common) ; } else { // resize all blocks to their original size if (nint > 0) (*I) = CHOLMOD(realloc) ((*n), ei, *I, &ni, Common) ; if (nint > 1) (*J) = CHOLMOD(realloc) ((*n), ei, *J, &nj, Common) ; if (ex > 0) (*X) = CHOLMOD(realloc) ((*n), ex, *X, &nx, Common) ; if (ez > 0) (*Z) = CHOLMOD(realloc) ((*n), ez, *Z, &nz, Common) ; } return (FALSE) ; } //-------------------------------------------------------------------------- // clear the first entry of X and Z //-------------------------------------------------------------------------- if ((*n) == 0) { // X and Z have been freshly allocated. Set their first entry to zero, // so that valgrind doesn't complain about accessing uninitialized // space in cholmod_*_xtype. if (*X != NULL && ex > 0) memset (*X, 0, ex) ; if (*Z != NULL && ez > 0) memset (*Z, 0, ez) ; } //-------------------------------------------------------------------------- // log the new size and return result //-------------------------------------------------------------------------- (*n) = nnew ; return (TRUE) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_divcomplex.c0000644000175100001440000000134714552026002023661 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_divcomplex: complex divide //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" int cholmod_l_divcomplex ( // input: double ar, double ai, // a (real, imaginary) double br, double bi, // b (real, imaginary) double *cr, double *ci // c (real, imaginary) ) { return (SuiteSparse_config_divcomplex (ar, ai, br, bi, cr, ci)) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_maxrank.c0000644000175100001440000000273014552026002023155 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_maxrank: find valid value of Common->maxrank //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" // Returns 0 on error, or 2, 4, or 8 otherwise. size_t CHOLMOD(maxrank) // return validated Common->maxrank ( // input: size_t n, // # of rows of L and A cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (0) ; //-------------------------------------------------------------------------- // determine a valid value of maxrank //-------------------------------------------------------------------------- size_t maxrank = Common->maxrank ; if (n > 0) { // guard against size_t overflow (very unlikely) size_t max_maxrank = SIZE_MAX / (n * sizeof (float)) ; maxrank = MIN (maxrank, max_maxrank) ; } // maxrank of 2 or less: use 2 // maxrank of 3 or 4: use 4 // else use 8 return ((maxrank <= 2) ? 2 : ((maxrank <= 4) ? 4 : 8)) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_cumsum.c0000644000175100001440000000226514552026002023030 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_cumsum: cumulative sum //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Cp [0:n] = cumulative sum of Cnz [0:n-1]. Returns the total sum, or -1 // if integer overflow has occurred. // Cp [0] = 0 // Cp [1] = Cnz [0] // Cp [2] = Cnz [0] + Cnz [1] ; // Cp [3] = Cnz [0] + Cnz [1] + Cnz [2] ; // ... // Cp [k] = sum (Cnz [0 ... k-1]) // ... // Cp [n] = sum (Cnz [0 ... n-1]) #include "cholmod_internal.h" int64_t CHOLMOD(cumsum) ( Int *Cp, // size n+1, output array, the cumsum of Cnz Int *Cnz, // size n, input array size_t n // size of Cp and Cnz ) { Int p = 0 ; for (Int k = 0 ; k < n ; k++) { Cp [k] = p ; p += Cnz [k] ; if (p < 0) { // integer overflow has occured return (EMPTY) ; } } Cp [n] = p ; return ((int64_t) p) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_zeros.c0000644000175100001440000000560314552026002022660 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_zeros: allocate an all-zero dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Allocate a dense matrix. The space is set to zero. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_dense) (&X, Common) ; \ return (NULL) ; \ } cholmod_dense *CHOLMOD(zeros) ( // input: size_t nrow, // # of rows size_t ncol, // # of columns int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate a dense matrix //-------------------------------------------------------------------------- cholmod_dense *X = CHOLMOD(allocate_dense) (nrow, ncol, nrow, xdtype, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // get the xtype and dtype //-------------------------------------------------------------------------- int xtype = xdtype & 3 ; // real, complex, or zomplex (not pattern) int dtype = xdtype & 4 ; // double or single //-------------------------------------------------------------------------- // get the sizes of the entries //-------------------------------------------------------------------------- size_t e = (dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * ((xtype == CHOLMOD_COMPLEX) ? 2 : 1) ; size_t ez = e * ((xtype == CHOLMOD_ZOMPLEX) ? 1 : 0) ; //-------------------------------------------------------------------------- // clear the contents //-------------------------------------------------------------------------- if (X->x != NULL) memset (X->x, 0, X->nzmax * ex) ; if (X->z != NULL) memset (X->z, 0, X->nzmax * ez) ; //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_dense) (X, "zeros:X", Common) >= 0) ; return (X) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_add.c0000644000175100001440000000073414552026002021723 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_add: C = alpha*A + beta*B //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_add.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_free_factor.c0000644000175100001440000001252414552026002023775 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_free_factor: free a sparse factorization //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" //------------------------------------------------------------------------------ // cholmod_to_simplicial_sym //------------------------------------------------------------------------------ // L is converted into a valid simplicial symbolic object, containing just // L->Perm and L->ColCount. This method is used by cholmod_change_factor. L // itself is not freed. This method is for internal use, not for the end-user // (who should use cholmod_change_factor to access this functionality). void CHOLMOD(to_simplicial_sym) ( cholmod_factor *L, // sparse factorization to modify int to_ll, // change L to hold a LL' or LDL' factorization cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- ASSERT (Common != NULL) ; ASSERT (L != NULL) ; //-------------------------------------------------------------------------- // get the sizes of the entries //-------------------------------------------------------------------------- size_t ei = sizeof (Int) ; size_t e = (L->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * ((L->xtype == CHOLMOD_PATTERN) ? 0 : ((L->xtype == CHOLMOD_COMPLEX) ? 2 : 1)) ; size_t ez = e * ((L->xtype == CHOLMOD_ZOMPLEX) ? 1 : 0) ; size_t nzmax = L->nzmax ; size_t n = L->n ; size_t s = L->nsuper + 1 ; size_t xs = (L->is_super) ? L->xsize : nzmax ; size_t ss = (L->ssize) ; //-------------------------------------------------------------------------- // free the components of L //-------------------------------------------------------------------------- // symbolic part of L (except for L->Perm and L->ColCount) L->IPerm = CHOLMOD(free) (n, ei, L->IPerm, Common) ; // simplicial form of L L->p = CHOLMOD(free) (n+1, ei, L->p, Common) ; L->i = CHOLMOD(free) (nzmax, ei, L->i, Common) ; L->nz = CHOLMOD(free) (n, ei, L->nz, Common) ; L->next = CHOLMOD(free) (n+2, ei, L->next, Common) ; L->prev = CHOLMOD(free) (n+2, ei, L->prev, Common) ; // supernodal form of L L->pi = CHOLMOD(free) (s, ei, L->pi, Common) ; L->px = CHOLMOD(free) (s, ei, L->px, Common) ; L->super = CHOLMOD(free) (s, ei, L->super, Common) ; L->s = CHOLMOD(free) (ss, ei, L->s, Common) ; // numerical part of L L->x = CHOLMOD(free) (xs, ex, L->x, Common) ; L->z = CHOLMOD(free) (xs, ez, L->z, Common) ; //-------------------------------------------------------------------------- // change the header contents to reflect the simplicial symbolic status //-------------------------------------------------------------------------- L->nzmax = 0 ; // no entries L->is_super = FALSE ; // L is simplicial L->xtype = CHOLMOD_PATTERN ; // L is symbolic L->minor = n ; // see cholmod.h L->is_ll = to_ll ? 1: 0 ; // L represents an LL' or LDL' factorization L->ssize = 0 ; // L->s is not present L->xsize = 0 ; // L->x is not present L->nsuper = 0 ; // no supernodes L->maxesize = 0 ; // no rows in any supernodes L->maxcsize = 0 ; // largest update matrix is size zero } //------------------------------------------------------------------------------ // cholmod_free_factor //------------------------------------------------------------------------------ int CHOLMOD(free_factor) ( // input/output: cholmod_factor **L, // handle of sparse factorization to free cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; if (L == NULL || (*L) == NULL) { // L is already freed; nothing to do return (TRUE) ; } //-------------------------------------------------------------------------- // convert L to a simplicial symbolic LL' factorization //-------------------------------------------------------------------------- CHOLMOD(to_simplicial_sym) (*L, 1, Common) ; //-------------------------------------------------------------------------- // free the rest of L and return result //-------------------------------------------------------------------------- size_t n = (*L)->n ; size_t ei = sizeof (Int) ; CHOLMOD(free) (n, ei, (*L)->Perm, Common) ; CHOLMOD(free) (n, ei, (*L)->ColCount, Common) ; (*L) = CHOLMOD(free) (1, sizeof (cholmod_factor), (*L), Common) ; return (TRUE) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_defaults.c0000644000175100001440000000077014552026002023315 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_defaults: set CHOLMOD defaults (int64 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_defaults.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_allocate_triplet.c0000644000175100001440000000663614552026002025054 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_allocate_triplet: allocate triplet matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Allocate an empty triplet matrix, with space to hold a given max # of // entries. The contents of T->i, T->j, T->x, and T->z are not initialized. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_triplet) (&T, Common) ; \ return (NULL) ; \ } cholmod_triplet *CHOLMOD(allocate_triplet) // return triplet matrix T ( // input: size_t nrow, // # of rows size_t ncol, // # of columns size_t nzmax, // max # of entries the matrix can hold int stype, // the stype of the matrix (unsym, tril, or triu) int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; Common->status = CHOLMOD_OK ; if (stype != 0 && nrow != ncol) { ERROR (CHOLMOD_INVALID, "rectangular matrix with stype != 0 invalid") ; return (NULL) ; } //-------------------------------------------------------------------------- // get the xtype and dtype //-------------------------------------------------------------------------- int xtype = xdtype & 3 ; // pattern, real, complex, or zomplex int dtype = xdtype & 4 ; // double or single //-------------------------------------------------------------------------- // allocate the header for T //-------------------------------------------------------------------------- cholmod_triplet *T = CHOLMOD(calloc) (1, sizeof (cholmod_triplet), Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // fill the header //-------------------------------------------------------------------------- T->nrow = nrow ; // # rows T->ncol = ncol ; // # columns T->stype = stype ; // symmetry type T->itype = ITYPE ; // integer type T->xtype = xtype ; // pattern, real, complex, or zomplex T->dtype = dtype ; // double or single //-------------------------------------------------------------------------- // reallocate the triplet matrix to change T->nzmax from 0 to nzmax //-------------------------------------------------------------------------- CHOLMOD(reallocate_triplet) (nzmax, T, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_triplet) (T, "allocate_triplet:T", Common) >= 0) ; return (T) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_realloc_multiple.c0000644000175100001440000000100214552026002024514 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_realloc_multiple: multiple realloc (int32 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_realloc_multiple.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sort.c0000644000175100001440000000772514552026002022514 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_sort: sort a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Sorts the entries in each column of a sparse matrix. #include "cholmod_internal.h" //------------------------------------------------------------------------------ // random number generator for cm_qsort //------------------------------------------------------------------------------ // return a random uint64_t, in range 0 to 2^60 #define CM_RAND_MAX 32767 // return a random number between 0 and CM_RAND_MAX static inline uint64_t cm_rand15 (uint64_t *seed) { (*seed) = (*seed) * 1103515245 + 12345 ; return (((*seed) / 65536) % (CM_RAND_MAX + 1)) ; } // return a random uint64_t, in range 0 to 2^60 static inline uint64_t cm_rand (uint64_t *seed) { uint64_t i = cm_rand15 (seed) ; i = CM_RAND_MAX * i + cm_rand15 (seed) ; i = CM_RAND_MAX * i + cm_rand15 (seed) ; i = CM_RAND_MAX * i + cm_rand15 (seed) ; return (i) ; } // swap two entries A [a] and A [b] #define SWAP(type,A,a,b) \ { \ type t = A [a] ; \ A [a] = A [b] ; \ A [b] = t ; \ } //------------------------------------------------------------------------------ // t_cholmod_sort_worker template //------------------------------------------------------------------------------ #define PATTERN #include "t_cholmod_sort_worker.c" #define DOUBLE #define REAL #include "t_cholmod_sort_worker.c" #define COMPLEX #include "t_cholmod_sort_worker.c" #define ZOMPLEX #include "t_cholmod_sort_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_sort_worker.c" #define COMPLEX #include "t_cholmod_sort_worker.c" #define ZOMPLEX #include "t_cholmod_sort_worker.c" //------------------------------------------------------------------------------ // cholmod_sort //------------------------------------------------------------------------------ int CHOLMOD(sort) ( // input/output: cholmod_sparse *A, // input/output matrix to sort cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_SPARSE_MATRIX_INVALID (A, FALSE) ; ASSERT (CHOLMOD(dump_sparse) (A, "sort:A input", Common) >= 0) ; //-------------------------------------------------------------------------- // sort each column of A //-------------------------------------------------------------------------- switch ((A->xtype + A->dtype) % 8) { default: p_cholmod_sort_worker (A) ; break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_sort_worker (A) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_sort_worker (A) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_sort_worker (A) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_sort_worker (A) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_sort_worker (A) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_sort_worker (A) ; break ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_sparse) (A, "sort:A output", Common) >= 0) ; return (TRUE) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_copy.c0000644000175100001440000000076714552026002022466 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_copy: copy a sparse matrix (with change of stype) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_copy.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_band.c0000644000175100001440000001717114552026002022425 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_band: extract the band of a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Construct a sparse matrix C that contains entries in bands k1:k2 of an input // sparse matrix A. A can have any xtype, stype, or dtype. C is sorted if and // only if A is sorted. // A can be constructed in place, but only if it is in packed form. // The diagonal can be ignored, if the ignore_diag flag is true. // C can optionally be constructed as a pattern matrix. // The stype is not changed, and no transpose takes place, so a mode of 1 and 2 // have the same effect (unlike cholmod_tranpose, cholmod_copy, cholmod_aat, // cholmod_vertcat, cholmod_horzcat, ... #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_sparse) (&C2, Common) ; \ return (NULL) ; \ } //------------------------------------------------------------------------------ // t_cholmod_band_worker template //------------------------------------------------------------------------------ #define PATTERN #include "t_cholmod_band_worker.c" #define DOUBLE #define REAL #include "t_cholmod_band_worker.c" #define COMPLEX #include "t_cholmod_band_worker.c" #define ZOMPLEX #include "t_cholmod_band_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_band_worker.c" #define COMPLEX #include "t_cholmod_band_worker.c" #define ZOMPLEX #include "t_cholmod_band_worker.c" //------------------------------------------------------------------------------ // band_helper //------------------------------------------------------------------------------ static cholmod_sparse *band_helper ( cholmod_sparse *A, int64_t k1, // count entries in k1:k2 diagonals int64_t k2, bool values, // if true and A numerical, C is numerical bool inplace, // if true, convert A in place (A cannot be packed) bool ignore_diag, // if true, ignore diagonal cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_SPARSE_MATRIX_INVALID (A, NULL) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int nrow = A->nrow ; Int ncol = A->ncol ; if (A->stype > 0 && k1 < 0) { // A is symmetric with the strictly lower triangular part ignored k1 = 0 ; } else if (A->stype < 0 && k2 > 0) { // A is symmetric with the strictly upper triangular part ignored k2 = 0 ; } // ensure k1 and k2 are in range -nrow:ncol k1 = RANGE (k1, -nrow, ncol) ; k2 = RANGE (k2, -nrow, ncol) ; values = values && (A->xtype != CHOLMOD_PATTERN) ; //-------------------------------------------------------------------------- // allocate new matrix C, or operate on A in place //-------------------------------------------------------------------------- cholmod_sparse *C, *C2 = NULL ; if (inplace) { // convert A in place if (!values) { // change A to pattern CHOLMOD(sparse_xtype) (CHOLMOD_PATTERN + A->dtype, A, Common) ; } C = A ; } else { // count # of entries in C and allocate it int64_t cnz = CHOLMOD(band_nnz) (A, k1, k2, ignore_diag, Common) ; int cxtype = values ? A->xtype : CHOLMOD_PATTERN ; C2 = CHOLMOD(allocate_sparse) (nrow, ncol, cnz, A->sorted, /* C is packed: */ TRUE, A->stype, cxtype + A->dtype, Common) ; C = C2 ; } RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // C = band (A) //-------------------------------------------------------------------------- switch ((C->xtype + C->dtype) % 8) { default: p_cholmod_band_worker (C, A, k1, k2, ignore_diag) ; break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_band_worker (C, A, k1, k2, ignore_diag) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_band_worker (C, A, k1, k2, ignore_diag) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_band_worker (C, A, k1, k2, ignore_diag) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_band_worker (C, A, k1, k2, ignore_diag) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_band_worker (C, A, k1, k2, ignore_diag) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_band_worker (C, A, k1, k2, ignore_diag) ; break ; } //-------------------------------------------------------------------------- // shrink A if computed in-place //-------------------------------------------------------------------------- if (inplace) { int64_t anz = CHOLMOD(nnz) (A, Common) ; CHOLMOD(reallocate_sparse) (anz, A, Common) ; RETURN_IF_ERROR ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- DEBUG (int64_t nzdiag = CHOLMOD(dump_sparse) (C, "band:C", Common)) ; ASSERT (nzdiag >= 0) ; ASSERT (IMPLIES (ignore_diag, nzdiag == 0)) ; return (C) ; } //------------------------------------------------------------------------------ // cholmod_band //------------------------------------------------------------------------------ cholmod_sparse *CHOLMOD(band) // return a new matrix C ( // input: cholmod_sparse *A, // input matrix int64_t k1, // count entries in k1:k2 diagonals int64_t k2, int mode, // >0: numerical, 0: pattern, <0: pattern (no diag) cholmod_common *Common ) { mode = RANGE (mode, -1, 1) ; bool values = (mode > 0) ; bool inplace = FALSE ; bool ignore_diag = (mode < 0) ; return (band_helper (A, k1, k2, values, inplace, ignore_diag, Common)) ; } //------------------------------------------------------------------------------ // cholmod_band_inplace //------------------------------------------------------------------------------ int CHOLMOD(band_inplace) ( // input: int64_t k1, // count entries in k1:k2 diagonals int64_t k2, int mode, // >0: numerical, 0: pattern, <0: pattern (no diag) // input/output: cholmod_sparse *A, // input/output matrix cholmod_common *Common ) { mode = RANGE (mode, -1, 1) ; bool values = (mode > 0) ; bool inplace = TRUE ; bool ignore_diag = (mode < 0) ; if (A != NULL && !(A->packed)) { /* cannot operate on an unpacked matrix in place */ ERROR (CHOLMOD_INVALID, "cannot operate on unpacked matrix in-place") ; return (FALSE) ; } return (band_helper (A, k1, k2, values, inplace, ignore_diag, Common) != NULL) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_set_empty.c0000644000175100001440000000075714552026002023211 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_set_empty: set an int32 array to EMPTY //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_set_empty.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_transpose.c0000644000175100001440000000075514552026002023214 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_transpose: transpose a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_transpose.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_score_comp.c0000644000175100001440000000116614552026002023647 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_score_comp: for sorting supernodes //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" int CHOLMOD(score_comp) ( struct cholmod_descendant_score_t *i, struct cholmod_descendant_score_t *j ) { return ((i->score < j->score) ? 1 : -1) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_aat.c0000644000175100001440000002237514552026002022270 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_aat: compute A*A' or A(:,f)*A(:,f)' //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // C = A*A' or C = A(:,f)*A(:,f)', where for complex/zomplex matrices, A' can // be computed as a matrix (complex conjugate) transpose, or an array (complex // non-conjugate) transpose. On output the C->stype is zero. The input matrix // A must have A->stype = 0. // workspace: // Iwork of size max (nrow,ncol) // Xwork of size n if real and mode > 0, or 2*n if complex and mode > 0 // The mode parameter: // 2 numerical, with conjugate transpose // 1 numerical, with non-conjugate transpose // 0 pattern, keeping the diagonal // -1 pattern, remove the diagonal // -2 pattern, and add 50% + n extra space to C // as elbow room for AMD and CAMD, when converting // a symmetric matrix A to an unsymmetric matrix C #include "cholmod_internal.h" #define RETURN_IF_ERROR \ { \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_sparse) (&C, Common) ; \ CHOLMOD(free_sparse) (&F, Common) ; \ return (NULL) ; \ } \ } //------------------------------------------------------------------------------ // t_cholmod_aat_worker template //------------------------------------------------------------------------------ #define PATTERN #include "t_cholmod_aat_worker.c" #define DOUBLE #define REAL #include "t_cholmod_aat_worker.c" #define COMPLEX #include "t_cholmod_aat_worker.c" #define ZOMPLEX #include "t_cholmod_aat_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_aat_worker.c" #define COMPLEX #include "t_cholmod_aat_worker.c" #define ZOMPLEX #include "t_cholmod_aat_worker.c" //------------------------------------------------------------------------------ // cholmod_aat: C=A*A' or A(:,f)*A(:,f)' //------------------------------------------------------------------------------ cholmod_sparse *CHOLMOD(aat) ( // input: cholmod_sparse *A, // input matrix Int *fset, // a list of column indices in range 0:A->ncol-1 size_t fsize, // # of entries in fset int mode, // 2: numerical (conj) // 1: numerical (non-conj.) // 0: pattern (with diag) // -1: pattern (remove diag), // -2: pattern (remove diag; add ~50% extra space in C) cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_SPARSE_MATRIX_INVALID (A, NULL) ; Common->status = CHOLMOD_OK ; cholmod_sparse *C = NULL, *F = NULL ; if (A->stype != 0) { ERROR (CHOLMOD_INVALID, "input matrix must be unsymmetric") ; return (NULL) ; } mode = RANGE (mode, -2, 2) ; ASSERT (CHOLMOD(dump_sparse) (A, "aat:A", Common) >= 0) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- bool ignore_diag = (mode < 0) ; bool values = (mode > 0) && (A->xtype != CHOLMOD_PATTERN) ; int axtype = (values) ? A->xtype : CHOLMOD_PATTERN ; Int nrow = A->nrow ; Int ncol = A->ncol ; Int n = A->nrow ; Int *Ap = (Int *) A->p ; Int *Anz = (Int *) A->nz ; Int *Ai = (Int *) A->i ; bool packed = A->packed ; //-------------------------------------------------------------------------- // get the sizes of the entries of C and A //-------------------------------------------------------------------------- size_t ew = ((axtype == CHOLMOD_PATTERN) ? 0 : ((axtype == CHOLMOD_COMPLEX) ? 2 : 1)) ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- CHOLMOD(alloc_work) (0, MAX (ncol, nrow), ew, A->dtype, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // construct the transpose F = A' or F = A(:,f)', or complex conjugate //-------------------------------------------------------------------------- // no row permutation (Perm is NULL) // uses Common->Iwork if fset is not NULL F = CHOLMOD(ptranspose) (A, mode, /* Perm: */ NULL, fset, fsize, Common) ; RETURN_IF_ERROR ; Int *Fp = (Int *) F->p ; Int *Fi = (Int *) F->i ; Int *W = Common->Iwork ; // size n, not yet initialized CHOLMOD(set_empty) (W, n) ; // W [0..n-1] = EMPTY //-------------------------------------------------------------------------- // cnz = nnz (C) //-------------------------------------------------------------------------- int ok = TRUE ; size_t cnz = 0 ; size_t cnzmax = SIZE_MAX - A->nrow ; for (Int j = 0 ; ok && (j < n) ; j++) { //---------------------------------------------------------------------- // If W [i] != jmark then row i has not yet been seen in C(:,j) //---------------------------------------------------------------------- Int jmark = -j-2 ; //---------------------------------------------------------------------- // compute # of entries in C(:,j) = A*F(:,j) //---------------------------------------------------------------------- for (Int pf = Fp [j] ; pf < Fp [j+1] ; pf++) { //------------------------------------------------------------------ // get the F(t,j) entry //------------------------------------------------------------------ Int t = Fi [pf] ; //------------------------------------------------------------------ // add any entries A(i,t) not already in C(:,j) pattern //------------------------------------------------------------------ Int p = Ap [t] ; Int pend = (packed) ? (Ap [t+1]) : (p + Anz [t]) ; for ( ; p < pend ; p++) { // get A(i,t); it is seen for first time if W [i] != jmark Int i = Ai [p] ; if (ignore_diag && i == j) continue ; if (W [i] != jmark) { W [i] = jmark ; cnz++ ; } } } //---------------------------------------------------------------------- // check if nearing integer overflow //---------------------------------------------------------------------- ok = (cnz < cnzmax) ; } //-------------------------------------------------------------------------- // allocate C //-------------------------------------------------------------------------- if (mode == -2 && ok) { // add some extra space cnz = CHOLMOD(add_size_t) (cnz, cnz/2, &ok) ; cnz = CHOLMOD(add_size_t) (cnz, A->nrow, &ok) ; } C = CHOLMOD(allocate_sparse) (n, n, ok ? cnz : SIZE_MAX, /* C is not sorted: */ FALSE, /* C is packed: */ TRUE, /* C stype: */ 0, axtype + A->dtype, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // compute the pattern and values of C //-------------------------------------------------------------------------- switch ((C->xtype + C->dtype) % 8) { default: p_cholmod_aat_worker (C, A, F, ignore_diag, Common) ; break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_aat_worker (C, A, F, ignore_diag, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_aat_worker (C, A, F, ignore_diag, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_aat_worker (C, A, F, ignore_diag, Common) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_aat_worker (C, A, F, ignore_diag, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_aat_worker (C, A, F, ignore_diag, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_aat_worker (C, A, F, ignore_diag, Common) ; break ; } //-------------------------------------------------------------------------- // free workspace and return result //-------------------------------------------------------------------------- DEBUG (size_t nnzdiag = CHOLMOD(dump_sparse) (C, "aat:C", Common)) ; ASSERT (IMPLIES (ignore_diag, nnzdiag == 0)) ; CHOLMOD(free_sparse) (&F, Common) ; return (C) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_nnz.c0000644000175100001440000000075114552026002022312 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_nnz: # of entries in a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_nnz.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_band_nnz.c0000644000175100001440000000615014552026002023305 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_band_nnz: # of entries in a band of sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Counts the # of entries with diagonals k1 to k2 of a sparse matrix. // For example, to count entries in the tridagonal part, use k1=-1 and k2=1. // To include the diagonal (k = 0), use ignore_diag = false; to exclude it, use // ignore_diag = true. #include "cholmod_internal.h" int64_t CHOLMOD(band_nnz) // return # of entries in a band (-1 if error) ( // input: cholmod_sparse *A, // matrix to examine int64_t k1, // count entries in k1:k2 diagonals int64_t k2, bool ignore_diag, // if true, exclude any diagonal entries cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (EMPTY) ; RETURN_IF_SPARSE_MATRIX_INVALID (A, EMPTY) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Ap = (Int *) A->p ; Int *Ai = (Int *) A->i ; Int *Anz = (Int *) A->nz ; bool packed = (bool) A->packed ; Int nrow = A->nrow ; Int ncol = A->ncol ; if (A->stype > 0 && k1 < 0) { // A is symmetric with the strictly lower triangular part ignored k1 = 0 ; } else if (A->stype < 0 && k2 > 0) { // A is symmetric with the strictly upper triangular part ignored k2 = 0 ; } // ensure k1 and k2 are in range -nrow:ncol k1 = RANGE (k1, -nrow, ncol) ; k2 = RANGE (k2, -nrow, ncol) ; // check for quick return if (k1 > k2) return (0) ; // columns outside of j1:j2 have no entries in diagonals k1:k2 Int j1 = MAX (k1, 0) ; Int j2 = MIN (k2+nrow, ncol) ; //-------------------------------------------------------------------------- // count entries within the k1:k2 band //-------------------------------------------------------------------------- int64_t bnz = 0 ; for (Int j = j1 ; j < j2 ; j++) { Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { // A(i,j) is in the kth diagonal, where k = j-i Int k = j - Ai [p] ; // check if k is in range k1:k2; if k is zero and diagonal is // ignored, then skip this entry bnz += ((k >= k1) && (k <= k2) && !(k == 0 && ignore_diag)) ; } } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (bnz) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sparse_to_triplet.c0000644000175100001440000000727214552026002025264 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_sparse_to_triplet: convert sparse to triplet //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" //------------------------------------------------------------------------------ // t_cholmod_sparse_to_triplet_worker template //------------------------------------------------------------------------------ #define PATTERN #include "t_cholmod_sparse_to_triplet_worker.c" #define DOUBLE #define REAL #include "t_cholmod_sparse_to_triplet_worker.c" #define COMPLEX #include "t_cholmod_sparse_to_triplet_worker.c" #define ZOMPLEX #include "t_cholmod_sparse_to_triplet_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_sparse_to_triplet_worker.c" #define COMPLEX #include "t_cholmod_sparse_to_triplet_worker.c" #define ZOMPLEX #include "t_cholmod_sparse_to_triplet_worker.c" //------------------------------------------------------------------------------ // cholmod_sparse_to_triplet: convert sparse matrix to triplet form //------------------------------------------------------------------------------ cholmod_triplet *CHOLMOD(sparse_to_triplet) ( // input: cholmod_sparse *A, // matrix to copy into triplet form T cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_SPARSE_MATRIX_INVALID (A, NULL) ; Common->status = CHOLMOD_OK ; ASSERT (CHOLMOD(dump_sparse) (A, "sparse_triplet:A", Common) >= 0) ; //-------------------------------------------------------------------------- // allocate triplet matrix //-------------------------------------------------------------------------- size_t nz = (size_t) CHOLMOD(nnz) (A, Common) ; cholmod_triplet *T = CHOLMOD(allocate_triplet) (A->nrow, A->ncol, nz, A->stype, A->xtype + A->dtype, Common) ; if (Common->status < CHOLMOD_OK) { return (NULL) ; } //-------------------------------------------------------------------------- // copy a sparse matrix A to a triplet matrix T //-------------------------------------------------------------------------- switch ((A->xtype + A->dtype) % 8) { default: p_cholmod_sparse_to_triplet_worker (T, A) ; break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_sparse_to_triplet_worker (T, A) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_sparse_to_triplet_worker (T, A) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_sparse_to_triplet_worker (T, A) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_sparse_to_triplet_worker (T, A) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_sparse_to_triplet_worker (T, A) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_sparse_to_triplet_worker (T, A) ; break ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_triplet) (T, "sparse_to_triplet:T", Common)) ; return (T) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_ones.c0000644000175100001440000000074414552026002022453 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_ones: dense matrix of all ones //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_ones.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_band.c0000644000175100001440000000075714552026002022417 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_band: extract the band of a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_band.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_factor_to_sparse.c0000644000175100001440000000654014552026002025054 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_factor_to_sparse: convert factor to sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Creates a sparse matrix A from a factor L. The contents of L are // transferred into A, and L is returned as a simplicial symbolic factor. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_sparse) (&A, Common) ; \ return (NULL) ; \ } cholmod_sparse *CHOLMOD(factor_to_sparse) ( // input/output: cholmod_factor *L, // input: factor to convert; output: L is converted // to a simplicial symbolic factor cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_FACTOR_INVALID (L, NULL) ; Common->status = CHOLMOD_OK ; DEBUG (CHOLMOD(dump_factor) (L, "factor_to_sparse:L input", Common)) ; if (L->xtype == CHOLMOD_PATTERN) { ERROR (CHOLMOD_INVALID, "L must be numerical on input") ; return (NULL) ; } cholmod_sparse *A = NULL ; //-------------------------------------------------------------------------- // convert L in place //-------------------------------------------------------------------------- CHOLMOD(change_factor) (L->xtype, L->is_ll, /* L becomes simplicial: */ FALSE, /* L becomes packed: */ TRUE, /* L becomes monotonic: */ TRUE, L, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // allocate the sparse matrix A //-------------------------------------------------------------------------- A = CHOLMOD(calloc) (1, sizeof (cholmod_sparse), Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // move the contents of L into A, and make L pattern //-------------------------------------------------------------------------- A->nrow = L->n ; A->ncol = L->n ; A->p = L->p ; L->p = NULL ; A->i = L->i ; L->i = NULL ; A->x = L->x ; L->x = NULL ; A->z = L->z ; L->z = NULL ; A->stype = 0 ; A->itype = L->itype ; A->xtype = L->xtype ; L->xtype = CHOLMOD_PATTERN ; A->dtype = L->dtype ; A->sorted = TRUE ; A->packed = TRUE ; A->nzmax = L->nzmax ; CHOLMOD(change_factor) (CHOLMOD_PATTERN, FALSE, FALSE, TRUE, TRUE, L, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_sparse) (A, "factor to sparse:A", Common) >= 0) ; DEBUG (CHOLMOD(dump_factor) (L, "factor_to_sparse:L input", Common)) ; return (A) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_reallocate_sparse.c0000644000175100001440000000077614552026002025204 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_reallocate_sparse: reallocate sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_reallocate_sparse.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_unsym.c0000644000175100001440000003000214552026002024756 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_transpose_unsym: unsymmetric permuted transpose //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" // Creates C = A', A(:,f)' or A(p,f)' C must be already allocated on input. // The matrices A and C are unsymmetric (with stype of zero). See // cholmod_transpose and cholmod_ptranspose for methods with a simpler // interface. // The notation A(:,f) and A(p,f) refers to a matrix of the same size as A, // where p is a permutation vector and f is a vector fset of size fsize. // Any column j not in the fset list still appears in A(:,f), just empty. // p must be a permutation of 0:A->nrow-1, and f must be a permutation of // a subset of 0:A->ncol-1. #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ return (FALSE) ; \ } //------------------------------------------------------------------------------ // t_cholmod_transpose_unsym_worker template //------------------------------------------------------------------------------ #define NUMERIC #define PATTERN #include "t_cholmod_transpose_unsym_worker.c" #define DOUBLE #define REAL #include "t_cholmod_transpose_unsym_worker.c" #define COMPLEX #include "t_cholmod_transpose_unsym_worker.c" #define COMPLEX #define NCONJUGATE #include "t_cholmod_transpose_unsym_worker.c" #define ZOMPLEX #include "t_cholmod_transpose_unsym_worker.c" #define ZOMPLEX #define NCONJUGATE #include "t_cholmod_transpose_unsym_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_transpose_unsym_worker.c" #define COMPLEX #include "t_cholmod_transpose_unsym_worker.c" #define COMPLEX #define NCONJUGATE #include "t_cholmod_transpose_unsym_worker.c" #define ZOMPLEX #include "t_cholmod_transpose_unsym_worker.c" #define ZOMPLEX #define NCONJUGATE #include "t_cholmod_transpose_unsym_worker.c" #undef NUMERIC //------------------------------------------------------------------------------ // cm_copy_Cnz: copy Wi into Cnz //------------------------------------------------------------------------------ static void cm_copy_Cnz (Int *Cnz, Int *Wi, Int *Perm, Int nrow) { if (Perm == NULL) { // Cnz [0..nrow-1] = Wi [0..nrow-1] memcpy (Cnz, Wi, nrow * sizeof (Int)) ; } else { // Cnz [0..nrow-1] = Wi [Perm [0..nrow-1]] for (Int i = 0 ; i < nrow ; i++) { Cnz [i] = Wi [Perm [i]] ; } } } //------------------------------------------------------------------------------ // cholmod_transpose_unsym //------------------------------------------------------------------------------ int CHOLMOD(transpose_unsym) ( // input: cholmod_sparse *A, // input matrix int mode, // 2: numerical (conj) // 1: numerical (non-conj.) // 0: pattern (with diag) Int *Perm, // permutation for C=A(p,f)', or NULL Int *fset, // a list of column indices in range 0:A->ncol-1 size_t fsize, // # of entries in fset // input/output: cholmod_sparse *C, // output matrix, must be allocated on input cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_SPARSE_MATRIX_INVALID (A, FALSE) ; RETURN_IF_NULL (C, FALSE) ; Common->status = CHOLMOD_OK ; mode = RANGE (mode, 0, 2) ; if (A->xtype == CHOLMOD_PATTERN || C->xtype == CHOLMOD_PATTERN) { // A or C is pattern: C must be pattern, so mode can only be zero mode = 0 ; } Int nrow = A->nrow ; Int ncol = A->ncol ; if (A->stype != 0) { ERROR (CHOLMOD_INVALID, "A is invalid") ; return (FALSE) ; } if ((C->xtype != ((mode == 0) ? CHOLMOD_PATTERN : A->xtype)) || (C->dtype != A->dtype) || (nrow != C->ncol) || (ncol != C->nrow) || (C->stype != 0)) { ERROR (CHOLMOD_INVALID, "C is invalid") ; return (FALSE) ; } ASSERT (CHOLMOD(dump_sparse) (A, "transpose_unsym:A", Common) >= 0) ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- size_t iworksize = (fset == NULL) ? nrow : MAX (nrow, ncol) ; CHOLMOD(allocate_work) (0, iworksize, 0, Common) ; RETURN_IF_ERROR ; Int *Wi = (Int *) Common->Iwork ; // size n integers //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Ap = (Int *) A->p ; Int *Ai = (Int *) A->i ; Int *Anz = (Int *) A->nz ; Int *Cp = (Int *) C->p ; Int *Cnz = (Int *) C->nz ; //-------------------------------------------------------------------------- // check Perm if present //-------------------------------------------------------------------------- if (Perm != NULL) { memset (Wi, 0, nrow * sizeof (Int)) ; for (Int k = 0 ; k < nrow ; k++) { Int i = Perm [k] ; if (i < 0 || i > nrow || Wi [i] == 1) { ERROR (CHOLMOD_INVALID, "invalid permutation") ; return (FALSE) ; } Wi [i] = 1 ; } } ASSERT (CHOLMOD(dump_perm) (Perm, nrow, nrow, "Perm", Common)) ; //-------------------------------------------------------------------------- // check fset if present, and also determine if it's sorted //-------------------------------------------------------------------------- Int nf = (Int) fsize ; bool fsorted = true ; if (fset != NULL) { Int jlast = EMPTY ; memset (Wi, 0, ncol * sizeof (Int)) ; for (Int k = 0 ; k < nf ; k++) { Int j = fset [k] ; if (j < 0 || j > ncol || Wi [j] == 1) { ERROR (CHOLMOD_INVALID, "invalid fset") ; return (FALSE) ; } Wi [j] = 1 ; fsorted = fsorted && (j > jlast) ; jlast = j ; } } ASSERT (CHOLMOD(dump_perm) (fset, fsize, ncol, "fset", Common)) ; //-------------------------------------------------------------------------- // count entries in each row of A or A(:,f) //-------------------------------------------------------------------------- memset (Wi, 0, nrow * sizeof (Int)) ; if (fset != NULL) { //---------------------------------------------------------------------- // count entries in rows of (A:,f) //---------------------------------------------------------------------- if (A->packed) { #define PACKED #define FSET #include "t_cholmod_transpose_unsym_template.c" } else { #define FSET #include "t_cholmod_transpose_unsym_template.c" } //---------------------------------------------------------------------- // save the nz counts if C is unpacked, and recount all of A //---------------------------------------------------------------------- if (!(C->packed)) { cm_copy_Cnz (Cnz, Wi, Perm, nrow) ; //------------------------------------------------------------------ // count entries in rows of A //------------------------------------------------------------------ memset (Wi, 0, nrow * sizeof (Int)) ; if (A->packed) { #define PACKED #include "t_cholmod_transpose_unsym_template.c" } else { #include "t_cholmod_transpose_unsym_template.c" } } } else { //---------------------------------------------------------------------- // count entries in rows of A //---------------------------------------------------------------------- if (A->packed) { #define PACKED #include "t_cholmod_transpose_unsym_template.c" } else { #include "t_cholmod_transpose_unsym_template.c" } //---------------------------------------------------------------------- // save the nz counts if C is unpacked, and recount all of A //---------------------------------------------------------------------- if (!(C->packed)) { cm_copy_Cnz (Cnz, Wi, Perm, nrow) ; } } //-------------------------------------------------------------------------- // Compute Cp //-------------------------------------------------------------------------- Int p = 0 ; if (Perm == NULL) { // Cp = cumsum (Wi) p = CHOLMOD(cumsum) (Cp, Wi, nrow) ; // Wi [0..nrow-1] = Cp [0..nrow-1] memcpy (Wi, Cp, nrow * sizeof (Int)) ; } else { // Cp = cumsum (Wi [Perm]) for (Int i = 0 ; i < nrow ; i++) { Cp [i] = p ; p += Wi [Perm [i]] ; } Cp [nrow] = p ; // Wi [Perm [0..nrow-1]] = Cp [0..nrow-1] for (Int i = 0 ; i < nrow ; i++) { Wi [Perm [i]] = Cp [i] ; } } if (p > (Int) C->nzmax) { ERROR (CHOLMOD_INVALID, "C is too small") ; return (FALSE) ; } //-------------------------------------------------------------------------- // compute the pattern and values of C //-------------------------------------------------------------------------- bool conj = (mode == 2) ; switch ((C->xtype + C->dtype) % 8) { default: p_cholmod_transpose_unsym_worker (A, fset, nf, C, Wi) ; break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_transpose_unsym_worker (A, fset, nf, C, Wi) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: if (conj) { cs_cholmod_transpose_unsym_worker (A, fset, nf, C, Wi) ; } else { cs_t_cholmod_transpose_unsym_worker (A, fset, nf, C, Wi) ; } break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: if (conj) { zs_cholmod_transpose_unsym_worker (A, fset, nf, C, Wi) ; } else { zs_t_cholmod_transpose_unsym_worker (A, fset, nf, C, Wi) ; } break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_transpose_unsym_worker (A, fset, nf, C, Wi) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: if (conj) { cd_cholmod_transpose_unsym_worker (A, fset, nf, C, Wi) ; } else { cd_t_cholmod_transpose_unsym_worker (A, fset, nf, C, Wi) ; } break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: if (conj) { zd_cholmod_transpose_unsym_worker (A, fset, nf, C, Wi) ; } else { zd_t_cholmod_transpose_unsym_worker (A, fset, nf, C, Wi) ; } break ; } //-------------------------------------------------------------------------- // finalize C and return result //-------------------------------------------------------------------------- C->sorted = fsorted ; ASSERT (CHOLMOD(dump_sparse) (C, "transpose_unsym:C", Common) >= 0) ; return (TRUE) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_error.c0000644000175100001440000000074414552026002022640 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_error: CHOLMOD error handling //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_error.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor.c0000644000175100001440000013734414552026002024311 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_change_factor: change format of a factor object //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // The cholmod_factor object holds a sparse Cholesky factorization in one of // many formats. It can be numeric or symbolic, L*L' or L*D*L', simplicial // or supernodal, packed or unpacked, and its columns can appear in order // (monotonic) or not (non-monotonic). Not all combinations are possible. // The L->xtype field describes the type of the entries: // CHOLMOD_PATTERN: L->x and L->z are NULL, no values are stored. // CHOLMOD_REAL: L->x is float or double, and L->z is NULL. The numeric // value of the (p)th entry is L->x [p]. // CHOLMOD_COMPLEX: L->x is float or double, the matrix is complex, // where the value of (p)th entry is L->x [2*p] (the real part), // and L->x [2*p+1] (the imaginary part). L->z is NULL. // CHOLMOD_ZOMPLEX: L->x and L->z are float or double. The matrix is // "zomplex", which means the matrix is mathematically complex, but // the real and imaginary parts are held in two separate arrays. // The value of the (p)th entry is L->x [p] (the real part), and // L->z [p] (the imaginary part). Supernodal factors are never // zomplex. // This method can change the L->xtype of a factor object L, but only to // convert it to CHOLMOD_PATTERN (thus freeing all numeric values), or by // changing a factor of xtype CHOLMOD_PATTERN to any of the three other types // (thus allocating empty space, or placing a placeholder value of an // identitity matrix. // The L->dtype field, just like the CHOLMOD sparse matrix, triplet matrix, and // dense matrix formats, defines the underlying floating point type: single // (float) or double, as CHOLMOD_SINGLE or CHOLMOD_DOUBLE. Matrices of // different dtypes cannot be mixed. To convert the xtype and dtype of an // object, use the cholmod_*_xtype methods (named "_xtype" for backward // compatibility with CHOLMOD v4 and earlier). That method will preserve the // values of the factor L. // CHOLMOD has the following basic kinds of factor formats: // // (1) simplicial symbolic: this consists of just two arrays of size n. // L->Perm contains the fill-reducing ordering, and L->ColCount is an // array containing the # of entries in each column of L. All of the other // factor objects contain this information as well. The simplicial // symbolic format does not hold the pattern of the matrix L itself. // // (2) simplicial numeric: this can hold either an LL' or LDL' factorization. // // LDL': The numeric L matrix itself is unit-diagonal, and the diagonal // entries of L are not stored. The jth column appears in positions // L->p [j] to L->p [j] + L->nz [j], in the arrays L->i, L->x, and (if // zomplex), L->z. Thus, L->nz [j] is the # of entries in the jth column, // which includes the entry D(j,j) as the first entry held in that column. // The columns of L need not appear in order 0, 1, ... n-1 in L->(i,x,z). // Instead, a doubly-link list is used (with L->prev and L->next). // The value D(j,j) can be negative (that is, the matrix being factorized // can be symmetric indefinite but with all principal minor matrices being // full rank). // // LL': this is the same format as LL', except the first entry in each // column is L(j,j). The diagonal matrix D is not preset. // // (3) supernodal symbolic: this represents the nonzero pattern of the // supernodes for a supernodal factorization, with L->nsuper supernodes. // The kth supernode contains columns L->super [k] to L->super [k+1]-1. // Its row indices are held in L->s [L->pi [k] ... L->pi [k+1]-1]. // L->x is not allocated, and is NULL. // // (4) supernodal numeric: This is always an LL' factorization (not LDL'). // L->x holds then numeric values of each supernode. The values of // the kth supernode (for the real case) are held in // L->x [L->px [k] ... L->px [k+1]-1]. The factor can be complex but // not zomplex (L->z is never used for a supernodal numeric factor). // // Within each column, or which each supernode, the row indices in L->i // (simplicial) or L->s (supernodal) are kept sorted, from low to high. // // This function, cholmod_change_factor and cholmod_l_change_factor, converts // a factor object between these representations, with some limitations: // // (a) a simplicial numeric factor cannot be converted to supernodal. // // (b) only a symbolic factor (simplicial or supernodal) can be converted // into a supernodal numeric factor. // // (c) L->dtype is not changed (single or double precision). // // (d) L->xtype can be changed but the numeric contents of L are discarded. // // Some of these conversions are only meant for internal use by CHOLMOD itself, // and they allocate space whose contents are not defined: simplicial // symbolic to supernodal symbolic, and converting any factor to supernodal // numeric. CHOLMOD performs these conversions just before it does its // numeric factorization. #include "cholmod_internal.h" #define RETURN_IF_ERROR(result) \ { \ if (Common->status < CHOLMOD_OK) \ { \ return result ; \ } \ } //------------------------------------------------------------------------------ // grow_column: increase the space for a single column of L //------------------------------------------------------------------------------ static Int grow_column (Int len, double grow1, double grow2, Int maxlen) { double xlen = (double) len ; xlen = grow1 * xlen + grow2 ; xlen = MIN (xlen, maxlen) ; len = (Int) xlen ; len = MAX (1, len) ; len = MIN (len, maxlen) ; return (len) ; } //------------------------------------------------------------------------------ // grow_L: grow the space at the end of L //------------------------------------------------------------------------------ static Int grow_L (Int lnz, double grow0, Int n) { double xlnz = (double) lnz ; xlnz *= grow0 ; xlnz = MIN (xlnz, (double) Int_max) ; double d = (double) n ; d = (d*d + d) / 2 ; xlnz = MIN (xlnz, d) ; Int newlnz = MAX (lnz, (Int) xlnz) ; return (newlnz) ; } //------------------------------------------------------------------------------ // t_cholmod_change_factor_*_worker //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_change_factor_1_worker.c" #include "t_cholmod_change_factor_2_worker.c" #include "t_cholmod_change_factor_3_worker.c" #undef REAL #define COMPLEX #include "t_cholmod_change_factor_1_worker.c" #include "t_cholmod_change_factor_2_worker.c" #include "t_cholmod_change_factor_3_worker.c" #undef COMPLEX #define ZOMPLEX #include "t_cholmod_change_factor_1_worker.c" #include "t_cholmod_change_factor_2_worker.c" #undef ZOMPLEX #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_change_factor_1_worker.c" #include "t_cholmod_change_factor_2_worker.c" #include "t_cholmod_change_factor_3_worker.c" #undef REAL #define COMPLEX #include "t_cholmod_change_factor_1_worker.c" #include "t_cholmod_change_factor_2_worker.c" #include "t_cholmod_change_factor_3_worker.c" #undef COMPLEX #define ZOMPLEX #include "t_cholmod_change_factor_1_worker.c" #include "t_cholmod_change_factor_2_worker.c" #undef ZOMPLEX //------------------------------------------------------------------------------ // natural list: create a doubly-link list of columns, in ordering 0 to n-1 //------------------------------------------------------------------------------ // The head of the link list is always n+1, and the tail is always n, where // n = L->n. The actual columns of L are in range 0 to L->n. static void natural_list (cholmod_factor *L) { // get inputs Int *Lnext = (Int *) L->next ; Int *Lprev = (Int *) L->prev ; ASSERT (Lprev != NULL && Lnext != NULL) ; Int n = L->n ; // create the head node Int head = n+1 ; Lnext [head] = 0 ; Lprev [head] = EMPTY ; // create the tail node Int tail = n ; Lnext [tail] = EMPTY ; Lprev [tail] = n-1 ; // link columns 0 to n-1 in increasing order: 0, 1, 2, ... n-1 for (Int j = 0 ; j < n ; j++) { Lnext [j] = j+1 ; Lprev [j] = j-1 ; } // the prev node of the first coumn 0 is n+1 Lprev [0] = head ; // the columns appear in order 0, 1, 2, ... n-1 in the link list L->is_monotonic = TRUE ; } //------------------------------------------------------------------------------ // L_is_packed: return true if no column of L has any extra space after it //------------------------------------------------------------------------------ // This method is used for debugging only. #ifndef NDEBUG static int L_is_packed (cholmod_factor *L, cholmod_common *Common) { Int *Lnz = (Int *) L->nz ; Int *Lp = (Int *) L->p ; Int n = L->n ; if (Lnz == NULL || Lp == NULL || L->xtype == CHOLMOD_PATTERN || L->is_super) { // nothing to check: L is intrinsically packed return (TRUE) ; } if (!L->is_monotonic) { // L is not packed, by definition return (FALSE) ; } for (Int j = 0 ; j < n ; j++) { PRINT3 (("j: "ID" Lnz "ID" Lp[j+1] "ID" Lp[j] "ID"\n", j, Lnz [j], Lp [j+1], Lp [j])) ; Int total_space_for_column_j = Lp [j+1] - Lp [j] ; Int entries_in_column_j = Lnz [j] ; if (entries_in_column_j != total_space_for_column_j) { // L(:,j) has extra slack space at the end of the column PRINT2 (("L is not packed\n")) ; return (FALSE) ; } } // L is packed return (TRUE) ; } #endif //------------------------------------------------------------------------------ // alloc_simplicial_num: allocate size-n arrays for simplicial numeric //------------------------------------------------------------------------------ // Does not allocate L->i, L->x, or L->z, which are larger. // See also cholmod_alloc_factor, which allocates L->Perm and L->ColCount. static int alloc_simplicial_num ( cholmod_factor *L, cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- ASSERT (L->xtype == CHOLMOD_PATTERN || L->is_super) ; ASSERT (L->p == NULL) ; ASSERT (L->nz == NULL) ; ASSERT (L->prev == NULL) ; ASSERT (L->next == NULL) ; size_t n = L->n ; //-------------------------------------------------------------------------- // allocate the four arrays //-------------------------------------------------------------------------- Int *Lp = CHOLMOD(malloc) (n+1, sizeof (Int), Common) ; Int *Lnz = CHOLMOD(malloc) (n, sizeof (Int), Common) ; Int *Lprev = CHOLMOD(malloc) (n+2, sizeof (Int), Common) ; Int *Lnext = CHOLMOD(malloc) (n+2, sizeof (Int), Common) ; //-------------------------------------------------------------------------- // check if out of memory //-------------------------------------------------------------------------- if (Common->status < CHOLMOD_OK) { // out of memory CHOLMOD(free) (n+1, sizeof (Int), Lp, Common) ; CHOLMOD(free) (n, sizeof (Int), Lnz, Common) ; CHOLMOD(free) (n+2, sizeof (Int), Lprev, Common) ; CHOLMOD(free) (n+2, sizeof (Int), Lnext, Common) ; return (FALSE) ; } //-------------------------------------------------------------------------- // place the arrays in L //-------------------------------------------------------------------------- L->p = Lp ; L->nz = Lnz ; L->prev = Lprev ; L->next = Lnext ; //-------------------------------------------------------------------------- // initialize the link list of the columns of L //-------------------------------------------------------------------------- natural_list (L) ; return (TRUE) ; } //------------------------------------------------------------------------------ // simplicial_sym_to_super_sym: converts simplicial symbolic to super //------------------------------------------------------------------------------ // converts a simplicial symbolic factor to supernodal symbolic. The space // is allocated but not initialized. static int simplicial_sym_to_super_sym ( cholmod_factor *L, cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- ASSERT (L->xtype == CHOLMOD_PATTERN && !(L->is_super)) ; //-------------------------------------------------------------------------- // allocate L->super, L->pi, L->px, and L->s //-------------------------------------------------------------------------- Int *Lsuper = CHOLMOD(malloc) (L->nsuper+1, sizeof (Int), Common) ; Int *Lpi = CHOLMOD(malloc) (L->nsuper+1, sizeof (Int), Common) ; Int *Lpx = CHOLMOD(malloc) (L->nsuper+1, sizeof (Int), Common) ; Int *Ls = CHOLMOD(malloc) (L->ssize, sizeof (Int), Common) ; //-------------------------------------------------------------------------- // check if out of memory //-------------------------------------------------------------------------- if (Common->status < CHOLMOD_OK) { // out of memory CHOLMOD(free) (L->nsuper+1, sizeof (Int), Lsuper, Common) ; CHOLMOD(free) (L->nsuper+1, sizeof (Int), Lpi, Common) ; CHOLMOD(free) (L->nsuper+1, sizeof (Int), Lpx, Common) ; CHOLMOD(free) (L->ssize, sizeof (Int), Ls, Common) ; return (FALSE) ; } //-------------------------------------------------------------------------- // place the arrays in L //-------------------------------------------------------------------------- L->super = Lsuper ; L->pi = Lpi ; L->px = Lpx ; L->s = Ls ; //-------------------------------------------------------------------------- // revise the header of L (L->dtype is not changed) //-------------------------------------------------------------------------- L->xtype = CHOLMOD_PATTERN ; // L is symbolic (no L->x, L->i, L->z) L->is_super = TRUE ; // L is now supernodal Ls [0] = EMPTY ; // contents of supernodal pattern undefined L->is_ll = TRUE ; // L is a supernodal LL' factorization L->maxcsize = 0 ; // size of largest update matrix L->maxesize = 0 ; // max rows in any supernode excl tri. part) L->minor = L->n ; // see cholmod.h for a description return (TRUE) ; } //------------------------------------------------------------------------------ // super_num_to_super_sym: convert numeric supernodal to symbolic //------------------------------------------------------------------------------ // This method converts a supernodal numeric factor L to supernodal symbolic, // by freeing the numeric values of all the supernodes. The supernodal // pattern (L->s) is kept. static void super_num_to_super_sym ( cholmod_factor *L, cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- ASSERT (L->xtype != CHOLMOD_PATTERN) ; ASSERT (L->xtype != CHOLMOD_ZOMPLEX) ; ASSERT (L->is_super) ; ASSERT (L->is_ll) ; DEBUG (CHOLMOD(dump_factor) (L, "supernum to supersym:L input", Common)) ; //-------------------------------------------------------------------------- // free L->x only //-------------------------------------------------------------------------- size_t e = (L->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * ((L->xtype == CHOLMOD_PATTERN) ? 0 : ((L->xtype == CHOLMOD_COMPLEX) ? 2 : 1)) ; L->x = CHOLMOD(free) (L->xsize, ex, L->x, Common) ; //-------------------------------------------------------------------------- // change the header contents to reflect the supernodal symbolic status //-------------------------------------------------------------------------- L->xtype = CHOLMOD_PATTERN ; // L is symbolic L->minor = L->n ; // see cholmod.h L->is_ll = TRUE ; // supernodal factor is always LL', not LDL' DEBUG (CHOLMOD(dump_factor) (L, "supernum to supersym:L output", Common)) ; } //------------------------------------------------------------------------------ // simplicial_sym_to_simplicial_num: convert simplicial numeric to symbolic //------------------------------------------------------------------------------ // This methods allocates space and converts a simplicial symbolic L to // simplicial numeric. L is set to the identity matrix, except in one case // where the contents of L are not initialized (packed < 0 case). static void simplicial_sym_to_simplicial_num ( cholmod_factor *L, // factor to modify int to_ll, // if true, convert to LL. if false: to LDL' int packed, // if > 0: L is packed, if 0: L is unpacked, // if < 0: L is packed but contents are not initialized int to_xtype, // the L->xtype (real, complex, or zomplex) cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- ASSERT (L->xtype == CHOLMOD_PATTERN && !(L->is_super)) ; //-------------------------------------------------------------------------- // allocate space for the simplicial numeric factor (except L->(i,x,z)) //-------------------------------------------------------------------------- if (!alloc_simplicial_num (L, Common)) { // out of memory; error status is already in Common->status return ; } //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int n = L->n ; Int *Lp = L->p ; Int *Lnz = L->nz ; Int *ColCount = L->ColCount ; //-------------------------------------------------------------------------- // initialize L->p and L->nz //-------------------------------------------------------------------------- bool ok = true ; Int lnz = 0 ; if (packed < 0) { //---------------------------------------------------------------------- // do not initialize the space //---------------------------------------------------------------------- lnz = L->nzmax ; L->nzmax = 0 ; } else if (packed > 0) { //---------------------------------------------------------------------- // initialize the packed LL' or LDL' case (L is identity) //---------------------------------------------------------------------- for (Int j = 0 ; ok && (j < n) ; j++) { // ensure ColCount [j] is in the range 1 to n-j Int len = ColCount [j] ; len = MAX (1, len) ; len = MIN (len, n-j) ; lnz += len ; ok = (lnz >= 0) ; } // each column L(:,j) holds a single diagonal entry for (Int j = 0 ; j <= n ; j++) { Lp [j] = j ; } for (Int j = 0 ; j < n ; j++) { Lnz [j] = 1 ; } } else { //---------------------------------------------------------------------- // initialize the unpacked LL' or LDL' case (L is identity) //---------------------------------------------------------------------- // slack space will be added to L below double grow0 = Common->grow0 ; double grow1 = Common->grow1 ; double grow2 = (double) Common->grow2 ; grow0 = isnan (grow0) ? 1 : grow0 ; grow1 = isnan (grow1) ? 1 : grow1 ; Int grow = (grow0 >= 1.0) && (grow1 >= 1.0) && (grow2 > 0) ; for (Int j = 0 ; ok && (j < n) ; j++) { //------------------------------------------------------------------ // log the start of L(:,j), containing a single entry //------------------------------------------------------------------ Lp [j] = lnz ; Lnz [j] = 1 ; //------------------------------------------------------------------ // ensure ColCount [j] is in the range 1 to n-j //------------------------------------------------------------------ Int len = ColCount [j] ; len = MAX (1, len) ; len = MIN (len, n-j) ; //------------------------------------------------------------------ // add some slack space to L(:,j) //------------------------------------------------------------------ if (grow) { len = grow_column (len, grow1, grow2, n-j) ; } lnz += len ; ok = (lnz >= 0) ; } //---------------------------------------------------------------------- // add slack space at the end of L //---------------------------------------------------------------------- if (ok) { Lp [n] = lnz ; if (grow) { lnz = grow_L (lnz, grow0, n) ; } } } //-------------------------------------------------------------------------- // allocate L->i, L->x, and L->z with the new xtype and existing dtype //-------------------------------------------------------------------------- ASSERT (L->nzmax == 0) ; lnz = MAX (1, lnz) ; int nint = 1 ; Common->status = (ok) ? CHOLMOD_OK : CHOLMOD_TOO_LARGE ; if (!ok || !CHOLMOD(realloc_multiple) (lnz, nint, to_xtype + L->dtype, &(L->i), NULL, &(L->x), &(L->z), &(L->nzmax), Common)) { // out of memory: convert L back to simplicial symbolic CHOLMOD(to_simplicial_sym) (L, to_ll, Common) ; return ; } L->xtype = to_xtype ; L->minor = n ; //-------------------------------------------------------------------------- // set L to the identity matrix, if requested //-------------------------------------------------------------------------- if (packed >= 0) { switch ((L->xtype + L->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_change_factor_1_worker (L) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_change_factor_1_worker (L) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_change_factor_1_worker (L) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_change_factor_1_worker (L) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_change_factor_1_worker (L) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_change_factor_1_worker (L) ; break ; } } L->is_ll = to_ll ; } //------------------------------------------------------------------------------ // change_simplicial_num: change LL' to LDL' or LDL' to LL' //------------------------------------------------------------------------------ // L must be simplicial numeric. // // to_ll: if true, L is converted to LL'; if false, to LDL' // to_packed: if true, L is converted to packed and monotonic // (to_monotonic is treated as true) // // to_monotonoic: if true but to_packed is false, L is converted to monotonic // but the columns are not packed. Slack space is left in // the columns of L. // // If both to_packed and to_monotonic are false: the columns of L are // converted in place, and neither packed nor made monotonic. // // To convert LDL' to LL', columns with D(j,j) <= 0 are left as-is, but L is // not numerically valid. The column L(:,j) is unchanged. If converted back // to LDL', the column is also left as-is, so that the LDL' can be recovered. // L->minor is set to the first j where D(j,j) <= 0. static void change_simplicial_num ( cholmod_factor *L, // factor to modify int to_ll, // if true: convert to LL'; else LDL' int to_packed, // if true: pack the columns of L int to_monotonic, // if true: make columns of L monotonic cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- ASSERT (Common != NULL) ; DEBUG (CHOLMOD(dump_factor) (L, "change simplnum:L input", Common)) ; ASSERT (L->xtype != CHOLMOD_PATTERN) ; ASSERT (!L->is_super) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- bool out_of_place = ((to_packed || to_monotonic) && !(L->is_monotonic)) ; bool make_ll = (to_ll && !(L->is_ll)) ; bool make_ldl = (!to_ll && L->is_ll) ; Int n = L->n ; Int *Lnz = (Int *) L->nz ; bool grow = false ; double grow0 = Common->grow0 ; double grow1 = Common->grow1 ; double grow2 = (double) Common->grow2 ; grow0 = isnan (grow0) ? 1 : grow0 ; grow1 = isnan (grow1) ? 1 : grow1 ; void *Li2 = NULL ; void *Lx2 = NULL ; void *Lz2 = NULL ; size_t ei = sizeof (Int) ; size_t e = (L->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * ((L->xtype == CHOLMOD_COMPLEX) ? 2 : 1) ; size_t ez = e * ((L->xtype == CHOLMOD_ZOMPLEX) ? 1 : 0) ; //-------------------------------------------------------------------------- // resize if changing to monotonic and/or packed and not already monotonic //-------------------------------------------------------------------------- Int lnz = 0 ; if (out_of_place) { //---------------------------------------------------------------------- // out-of-place: construct L in new space (Li2, Lx2, and Lz2) //---------------------------------------------------------------------- // The columns of L are out of order (not monotonic), but L is being // changed to being either monotonic, or packed, or both. Thus, L // needs to be resized, in newly allocated space (Li2, Lx2, and Lz2). //---------------------------------------------------------------------- // determine if L should grow //---------------------------------------------------------------------- if (!to_packed) { grow = (grow0 >= 1.0) && (grow1 >= 1.0) && (grow2 > 0) ; } //---------------------------------------------------------------------- // compute the new space for each column of L //---------------------------------------------------------------------- bool ok = true ; for (Int j = 0 ; ok && (j < n) ; j++) { Int len = Lnz [j] ; ASSERT (len >= 1 && len <= n-j) ; if (grow) { len = grow_column (len, grow1, grow2, n-j) ; } ASSERT (len >= Lnz [j] && len <= n-j) ; lnz += len ; ok = (lnz >= 0) ; } Common->status = (ok) ? CHOLMOD_OK : CHOLMOD_TOO_LARGE ; if (ok) { //------------------------------------------------------------------ // add additional space at the end of L, if requested //------------------------------------------------------------------ if (grow) { lnz = grow_L (lnz, grow0, n) ; } //------------------------------------------------------------------ // allocate Li2, Lx2, and Lz2 (as newly allocated space) //------------------------------------------------------------------ lnz = MAX (1, lnz) ; int nint = 1 ; size_t nzmax0 = 0 ; CHOLMOD(realloc_multiple) (lnz, nint, L->xtype + L->dtype, &Li2, NULL, &Lx2, &Lz2, &nzmax0, Common) ; } //---------------------------------------------------------------------- // return if out of memory or problem too large //---------------------------------------------------------------------- RETURN_IF_ERROR () ; } //-------------------------------------------------------------------------- // convert the simplicial L //-------------------------------------------------------------------------- switch ((L->xtype + L->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_change_factor_2_worker (L, to_packed, Li2, Lx2, Lz2, lnz, grow, grow1, grow2, make_ll, out_of_place, make_ldl, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_change_factor_2_worker (L, to_packed, Li2, Lx2, Lz2, lnz, grow, grow1, grow2, make_ll, out_of_place, make_ldl, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_change_factor_2_worker (L, to_packed, Li2, Lx2, Lz2, lnz, grow, grow1, grow2, make_ll, out_of_place, make_ldl, Common) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_change_factor_2_worker (L, to_packed, Li2, Lx2, Lz2, lnz, grow, grow1, grow2, make_ll, out_of_place, make_ldl, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_change_factor_2_worker (L, to_packed, Li2, Lx2, Lz2, lnz, grow, grow1, grow2, make_ll, out_of_place, make_ldl, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_change_factor_2_worker (L, to_packed, Li2, Lx2, Lz2, lnz, grow, grow1, grow2, make_ll, out_of_place, make_ldl, Common) ; break ; } //-------------------------------------------------------------------------- // finalize the result L //-------------------------------------------------------------------------- L->is_ll = to_ll ; if (out_of_place) { //---------------------------------------------------------------------- // free the old space and move the new space into L //---------------------------------------------------------------------- CHOLMOD(free) (L->nzmax, ei, L->i, Common) ; CHOLMOD(free) (L->nzmax, ex, L->x, Common) ; CHOLMOD(free) (L->nzmax, ez, L->z, Common) ; L->i = Li2 ; L->x = Lx2 ; L->z = Lz2 ; L->nzmax = lnz ; //---------------------------------------------------------------------- // revise the link list (columns 0 to n-1 now in natural order) //---------------------------------------------------------------------- natural_list (L) ; } DEBUG (CHOLMOD(dump_factor) (L, "change simplnum:L output", Common)) ; } //------------------------------------------------------------------------------ // super_num_to_simplicial_num: convert supernodal numeric to simplicial numeric //------------------------------------------------------------------------------ static void super_num_to_simplicial_num ( cholmod_factor *L, int to_packed, int to_ll, cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- ASSERT (L != NULL) ; ASSERT (Common != NULL) ; DEBUG (CHOLMOD(dump_factor) (L, "supernum to simplnum:L input", Common)) ; ASSERT (L->xtype != CHOLMOD_PATTERN) ; ASSERT (L->xtype != CHOLMOD_ZOMPLEX) ; ASSERT (L->is_ll) ; ASSERT (L->is_super) ; ASSERT (L->x != NULL) ; ASSERT (L->i == NULL) ; ASSERT (L->z == NULL) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int nsuper = L->nsuper ; Int *Lpi = (Int *) L->pi ; Int *Super = (Int *) L->super ; size_t ei = sizeof (Int) ; size_t e = (L->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * ((L->xtype == CHOLMOD_COMPLEX) ? 2 : 1) ; //-------------------------------------------------------------------------- // determine the size of L after conversion to simplicial numeric //-------------------------------------------------------------------------- Int lnz = 0 ; if (to_packed) { //---------------------------------------------------------------------- // count the # of nonzeros in all supernodes of L //---------------------------------------------------------------------- // Each supernode is lower trapezoidal, with a top part that is lower // triangular (with diagonal present) and a bottom part that is // rectangular. In this example below, nscol = 5, so the supernode // represents 5 columns of L, and nsrow = 8, which means that the // first column of the supernode has 8 entries, including the // diagonal. // // x . . . . // x x . . . // x x x . . // x x x x . // x x x x x // x x x x x // x x x x x // x x x x x // // The '.' entries above are in the data structure but not used, and // are not copied into the simplicial factor L. The 'x' entries are // used, but some might be exactly equal to zero. Some of these zeros // come from relaxed supernodal algamation, and some come from exact // numeric cancellation. These entries appear in the final // simplicial factor L. for (Int s = 0 ; s < nsuper ; s++) { //------------------------------------------------------------------ // get the supernode //------------------------------------------------------------------ Int k1 = Super [s] ; // L(:,k1) is 1st col in supernode s Int k2 = Super [s+1] ; // L(:,k2) is 1st col in supernode s+1 Int psi = Lpi [s] ; // start of pattern in Ls of supernode s Int psend = Lpi [s+1] ; // start of pattern in Ls of s+1 Int nsrow = psend - psi ; // # entries in 1st col of supernode s Int nscol = k2 - k1 ; // # of columns in supernode ASSERT (nsrow >= nscol) ; Int erows = nsrow - nscol ; // # of rows below triangular part //------------------------------------------------------------------ // count the entries in the supernode, including any exact zeros //------------------------------------------------------------------ // lower triangular part lnz += nscol * (nscol+1) / 2 ; // rectangular part lnz += nscol * erows ; } } else { //---------------------------------------------------------------------- // the supernodal L will not be packed //---------------------------------------------------------------------- // L->x holds all numeric values of the supernodes, and these entries // will remain in place. L->x will not be decreased in size, so Li // will have the same size as L->x. lnz = L->xsize ; } ASSERT (lnz >= 0 && lnz <= (Int) (L->xsize)) ; //-------------------------------------------------------------------------- // allocate Li for the pattern L->i of the simplicial factor of L //-------------------------------------------------------------------------- Int *Li = CHOLMOD(malloc) (lnz, ei, Common) ; RETURN_IF_ERROR () ; //-------------------------------------------------------------------------- // allocate the size-n arrays for L: L->p, L->nz, L->prev, and L->nex //-------------------------------------------------------------------------- if (!alloc_simplicial_num (L, Common)) { // out of memory CHOLMOD(free) (lnz, ei, Li, Common) ; return ; } //-------------------------------------------------------------------------- // convert the supernodal numeric L into a simplicial numeric L //-------------------------------------------------------------------------- L->i = Li ; L->nzmax = lnz ; switch ((L->xtype + L->dtype) % 8) { case CHOLMOD_SINGLE + CHOLMOD_REAL: rs_cholmod_change_factor_3_worker (L, to_packed, to_ll, Common) ; break ; case CHOLMOD_SINGLE + CHOLMOD_COMPLEX: cs_cholmod_change_factor_3_worker (L, to_packed, to_ll, Common) ; break ; case CHOLMOD_DOUBLE + CHOLMOD_REAL: rd_cholmod_change_factor_3_worker (L, to_packed, to_ll, Common) ; break ; case CHOLMOD_DOUBLE + CHOLMOD_COMPLEX: cd_cholmod_change_factor_3_worker (L, to_packed, to_ll, Common) ; break ; } //-------------------------------------------------------------------------- // reduce the size of L->x to match L->i (this cannot fail) //-------------------------------------------------------------------------- L->x = CHOLMOD(realloc) (lnz, ex, L->x, &(L->xsize), Common) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // free the supernodal parts of L and return result //-------------------------------------------------------------------------- L->is_super = FALSE ; // L is now simplicial L->is_ll = to_ll ; // L is LL' or LDL', according to to_ll L->pi = CHOLMOD(free) (nsuper+1, ei, L->pi, Common) ; L->px = CHOLMOD(free) (nsuper+1, ei, L->px, Common) ; L->super = CHOLMOD(free) (nsuper+1, ei, L->super, Common) ; L->s = CHOLMOD(free) (L->ssize, ei, L->s, Common) ; L->ssize = 0 ; // L->s is not present L->xsize = 0 ; // L->x is not present L->nsuper = 0 ; // no supernodes L->maxesize = 0 ; // no rows in any supernodes L->maxcsize = 0 ; // largest update matrix is size zero DEBUG (CHOLMOD(dump_factor) (L, "supernum to simplnum:L output", Common)) ; } //------------------------------------------------------------------------------ // super_sym_to_super_num: convert supernodal symbolic to numeric //------------------------------------------------------------------------------ static int super_sym_to_super_num ( int to_xtype, cholmod_factor *L, cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- ASSERT (L != NULL) ; ASSERT (Common != NULL) ; ASSERT (L->xtype == CHOLMOD_PATTERN) ; ASSERT (L->is_super) ; ASSERT (L->x == NULL) ; ASSERT (to_xtype == CHOLMOD_REAL || to_xtype == CHOLMOD_COMPLEX) ; //-------------------------------------------------------------------------- // get the sizes of the entries //-------------------------------------------------------------------------- size_t e = (L->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * ((to_xtype == CHOLMOD_COMPLEX) ? 2 : 1) ; size_t xs = L->xsize ; //-------------------------------------------------------------------------- // allocate the space //-------------------------------------------------------------------------- double *Lx = CHOLMOD(malloc) (xs, ex, Common) ; RETURN_IF_ERROR ((FALSE)) ; //-------------------------------------------------------------------------- // finalize L and return result //-------------------------------------------------------------------------- // clear the first few entries so valgrind is satisfied memset (Lx, 0, MIN (2 * sizeof (double), xs*ex)) ; L->x = Lx ; // new space for numeric values L->xtype = to_xtype ; // real or complex L->minor = L->n ; return (TRUE) ; } //============================================================================== // cholmod_change_factor //============================================================================== // Convert a factor L. Some conversions simply allocate uninitialized space // that is meant to be filled later. int CHOLMOD(change_factor) ( int to_xtype, // CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX int to_ll, // if true: convert to LL'; else to LDL' int to_super, // if true: convert to supernodal; else to simplicial int to_packed, // if true: pack simplicial columns; else: do not pack int to_monotonic, // if true, put simplicial columns in order cholmod_factor *L, // factor to change cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (L, FALSE) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; Common->status = CHOLMOD_OK ; to_xtype = to_xtype & 3 ; to_ll = to_ll ? 1 : 0 ; if (to_super && (to_xtype == CHOLMOD_ZOMPLEX)) { ERROR (CHOLMOD_INVALID, "supernodal zomplex L not supported") ; return (FALSE) ; } PRINT1 (("-----convert from (%d,%d,%d,%d,%d) to (%d,%d,%d,%d,%d)\n", L->xtype, L->is_ll, L->is_super, L_is_packed (L, Common), L->is_monotonic, to_xtype, to_ll, to_super, to_packed, to_monotonic)) ; //-------------------------------------------------------------------------- // convert the factor L //-------------------------------------------------------------------------- if (to_xtype == CHOLMOD_PATTERN) { //---------------------------------------------------------------------- // convert to symbolic //---------------------------------------------------------------------- if (!to_super) { //------------------------------------------------------------------ // convert to simplicial symbolic factor (this cannot fail) //------------------------------------------------------------------ CHOLMOD(to_simplicial_sym) (L, to_ll, Common) ; } else { //------------------------------------------------------------------ // convert to supernodal symbolic factor //------------------------------------------------------------------ if (L->xtype != CHOLMOD_PATTERN && L->is_super) { // convert supernodal numeric to supernodal symbolic, // keeping the pattern but freeing the numeric values. super_num_to_super_sym (L, Common) ; } else if (L->xtype == CHOLMOD_PATTERN && !(L->is_super)) { // convert simplicial symbolic to supernodal symbolic, // only meant for use internally to CHOLMOD. simplicial_sym_to_super_sym (L, Common) ; } else { // can't convert simplicial numeric to supernodal symbolic ERROR (CHOLMOD_INVALID, "failed to change L") ; return (FALSE) ; } } } else { //---------------------------------------------------------------------- // convert to numeric //---------------------------------------------------------------------- if (to_super) { //------------------------------------------------------------------ // convert to supernodal numeric factor //------------------------------------------------------------------ if (L->xtype == CHOLMOD_PATTERN) { if (L->is_super) { // convert supernodal symbolic to supernodal numeric, // only meant for use internally to CHOLMOD. super_sym_to_super_num (to_xtype, L, Common) ; } else { // convert simplicial symbolic to supernodal numeric, // only meant for use internally to CHOLMOD. if (!simplicial_sym_to_super_sym (L, Common)) { // failure, convert back to simplicial symbolic CHOLMOD(to_simplicial_sym) (L, to_ll, Common) ; return (FALSE) ; } // convert supernodal symbolic to supernodal numeric super_sym_to_super_num (to_xtype, L, Common) ; } } else { // nothing to do if already supernodal numeric if (!(L->is_super)) { ERROR (CHOLMOD_INVALID, "failed to change L") ; return (FALSE) ; } } } else { //------------------------------------------------------------------ // convert any factor to simplicial numeric //------------------------------------------------------------------ if (L->xtype == CHOLMOD_PATTERN && !(L->is_super)) { // convert simplicial symbolic to simplicial numeric (L=D=I) simplicial_sym_to_simplicial_num (L, to_ll, to_packed, to_xtype, Common) ; } else if (L->xtype != CHOLMOD_PATTERN && L->is_super) { // convert a supernodal LL' to simplicial numeric super_num_to_simplicial_num (L, to_packed, to_ll, Common) ; } else if (L->xtype == CHOLMOD_PATTERN && L->is_super) { // convert a supernodal symbolic to simplicial numeric (L=D=I) CHOLMOD(to_simplicial_sym) (L, to_ll, Common) ; simplicial_sym_to_simplicial_num (L, to_ll, to_packed, to_xtype, Common) ; } else { // change a simplicial numeric factor: change LL' to LDL', LDL' // to LL', or leave as-is. pack the columns of L, or leave // as-is. Ensure the columns are monotonic, or leave as-is. change_simplicial_num (L, to_ll, to_packed, to_monotonic, Common) ; } } } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (Common->status >= CHOLMOD_OK) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_zeros.c0000644000175100001440000000075714552026002022655 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_zeros: allocate an all-zero dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_zeros.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_dense.c0000644000175100001440000000403414552026002023643 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_dense: copy a dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Copies a dense matrix X into a new dense matrix Y, with the same leading // dimensions. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_dense) (&Y, Common) ; \ return (NULL) ; \ } cholmod_dense *CHOLMOD(copy_dense) // returns new dense matrix ( // input: cholmod_dense *X, // input dense matrix cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_DENSE_MATRIX_INVALID (X, FALSE) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate the output matrix Y with same properties as X //-------------------------------------------------------------------------- cholmod_dense *Y = CHOLMOD(allocate_dense) (X->nrow, X->ncol, X->d, X->xtype + X->dtype, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // copy X = Y //-------------------------------------------------------------------------- CHOLMOD(copy_dense2) (X, Y, Common) ; //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (Y) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_reallocate_column_worker.c0000644000175100001440000000306014552026002026572 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_reallocate_column_worker //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_reallocate_column_worker) ( cholmod_factor *L, // L factor modified, L(:,j) resized Int j, // column L(:,j) to move Int pdest, // place to move it to Int psrc // place to move it from ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Lnz = (Int *) L->nz ; Int *Li = (Int *) L->i ; Real *Lx = (Real *) L->x ; #ifdef ZOMPLEX Real *Lz = (Real *) L->z ; #endif Int len = Lnz [j] ; //-------------------------------------------------------------------------- // move L(:,j) to its new position //-------------------------------------------------------------------------- for (Int k = 0 ; k < len ; k++, pdest++, psrc++) { // move L(i,j) from position psrc to position pdest Li [pdest] = Li [psrc] ; ASSIGN (Lx, Lz, pdest, Lx, Lz, psrc) ; } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_ptranspose.c0000644000175100001440000000075014552026002023367 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_ptranspose: permuted transpose //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_ptranspose.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_error.c0000644000175100001440000000074214552026002022323 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_error: CHOLMOD error handling //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_error.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_change_factor.c0000644000175100001440000000077614552026002024277 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_change_factor: change format of a factor object //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_change_factor.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_pack_factor_worker.c0000644000175100001440000000744114552026002025365 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_pack_factor_worker: pack a simplicial factorization //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" //------------------------------------------------------------------------------ // cholmod_pack_factor_worker //------------------------------------------------------------------------------ static void TEMPLATE (cholmod_pack_factor_worker) ( cholmod_factor *L, // factor to pack cholmod_common *Common ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int n = L->n ; Int *Lp = (Int *) L->p ; Int *Li = (Int *) L->i ; Real *Lx = (Real *) L->x ; #ifdef ZOMPLEX Real *Lz = (Real *) L->z ; #endif Int *Lnz = (Int *) L->nz ; Int *Lnext = (Int *) L->next ; Int slack = Common->grow2 ; //-------------------------------------------------------------------------- // pack, traversing the link list of columns of L //-------------------------------------------------------------------------- Int j = Lnext [n+1] ; // first column in the list is Lnext [n+1] Int pnew = 0 ; // next column can move to pnew while (j != n) // j=n is the fictious placeholder at end of list { //---------------------------------------------------------------------- // get column j, entries currently in Li and Lx [pold...pold+lnzj-1] //---------------------------------------------------------------------- Int pold = Lp [j] ; // start of column j in L->i and L->j Int lnzj = Lnz [j] ; // # of entries in column j ASSERT (lnzj > 0) ; //---------------------------------------------------------------------- // pack column j, if possible //---------------------------------------------------------------------- if (pnew < pold) { // Li,Lx [pnew...pnew+lnz-1] = Li,Lx [pold...pold+lnz-1] for (Int k = 0 ; k < lnzj ; k++) { // move L(i,j) from position pold+k to position pnew+k Li [pnew + k] = Li [pold + k] ; ASSIGN (Lx, Lz, pnew + k, Lx, Lz, pold + k) ; } // log the new position of the first entry of L(:,j) Lp [j] = pnew ; } //---------------------------------------------------------------------- // add some empty space at the end of column j //---------------------------------------------------------------------- Int desired_space = lnzj + slack ; // add slack space to column j Int max_space = n - j ; // no need for more than this space Int total_space = MIN (desired_space, max_space) ; //---------------------------------------------------------------------- // next column will move to position pnew, if possible //---------------------------------------------------------------------- Int jnext = Lnext [j] ; // jnext = next column in the list Int pnext = Lp [jnext] ; // next column jnext starts here Int pthis = Lp [j] + total_space ; // one past the end of column j pnew = MIN (pthis, pnext) ; // next column can move to pnew j = jnext ; // move to the next column } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_sparse_to_dense.c0000644000175100001440000000100014552026002024333 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_sparse_to_dense: convert a sparse matrix to dense //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_sparse_to_dense.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_dbound.c0000644000175100001440000000126514552026002022761 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_dbound: bound diagonal of LDL (double, int64) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_BOUND_FUNCTION cholmod_l_dbound #define COMMON_BOUND (Common->dbound) #define COMMON_BOUNDS_HIT (Common->ndbounds_hit) #define Real double #define CHOLMOD_INT64 #include "t_cholmod_bound.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_change_factor.c0000644000175100001440000000077414552026002023762 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_change_factor: change format of a factor object //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_change_factor.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_add_size_t.c0000644000175100001440000000227214552026002023622 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_add_size_t: add two size_t values //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" size_t CHOLMOD(add_size_t) (size_t a, size_t b, int *ok) { //-------------------------------------------------------------------------- // add a and b //-------------------------------------------------------------------------- size_t s = a + b ; //-------------------------------------------------------------------------- // check for size_t overflow //-------------------------------------------------------------------------- if (s < a || s < b) { (*ok) = FALSE ; s = 0 ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (s) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_1_worker.c0000644000175100001440000000352214552026002026110 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_change_factor_1_worker: change factor to identity //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" //------------------------------------------------------------------------------ // t_cholmod_change_factor_1_worker: set L to the identity matrix //------------------------------------------------------------------------------ // L is simplicial numeric. static void TEMPLATE (cholmod_change_factor_1_worker) ( cholmod_factor *L ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- ASSERT (L->xtype != CHOLMOD_PATTERN) ; ASSERT (!L->is_super) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Lp = (Int *) L->p ; Int *Li = (Int *) L->i ; Real *Lx = (Real *) L->x ; #ifdef ZOMPLEX Real *Lz = (Real *) L->z ; #endif Int n = L->n ; //-------------------------------------------------------------------------- // set L to the identity matrix //-------------------------------------------------------------------------- Real onex [2] = {1,0} ; #ifdef ZOMPLEX Real onez [1] = {0} ; #endif for (Int j = 0 ; j < n ; j++) { Int p = Lp [j] ; ASSERT (p < Lp [j+1]) ; Li [p] = j ; ASSIGN (Lx, Lz, p, onex, onez, 0) ; } } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_triplet_to_sparse.c0000644000175100001440000000077514552026002024742 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_triplet_to_sparse: convert triplet to sparse //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_triplet_to_sparse.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_malloc.c0000644000175100001440000000432614552026002022766 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_malloc: malloc/calloc (int64/int32) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" // This template creates 4 functions: // cholmod_malloc int32, malloc, using SuiteSparse_malloc // cholmod_l_malloc int64, malloc, using SuiteSparse_malloc // cholmod_calloc int32, calloc, using SuiteSparse_calloc // cholmod_l_calloc int64, calloc, using SuiteSparse_calloc void *CHOLMOD_ALLOC_FUNCTION // return pointer to newly allocated memory ( // input: size_t n, // number of items size_t size, // size of each item cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; //-------------------------------------------------------------------------- // allocate memory //-------------------------------------------------------------------------- void *p = SUITESPARSE_ALLOC_FUNCTION (n, size) ; // malloc or calloc //-------------------------------------------------------------------------- // log memory usage and return result //-------------------------------------------------------------------------- if (p != NULL) { // success: log the change in memory usage Common->memory_inuse += (n * size) ; Common->memory_usage = MAX (Common->memory_usage, Common->memory_inuse); Common->malloc_count++ ; PRINTM (("cholmod_malloc %p %g cnt: %g inuse %g\n", p, (double) n*size, (double) Common->malloc_count, (double) Common->memory_inuse)) ; #ifndef NDEBUG CM_memtable_add (p, n*size) ; #endif } else { ERROR (CHOLMOD_OUT_OF_MEMORY, "out of memory") ; } return (p) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_dense2_worker.c0000644000175100001440000000532014552026002025315 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_dense2_worker: copy a dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Copies a dense matrix X into Y, with change of leading dimension. If the // leading dimensions are the same, the copy is done in the caller, // t_cholmod_copy_dense2. #include "cholmod_template.h" static void TEMPLATE (cholmod_copy_dense2_worker) ( cholmod_dense *X, cholmod_dense *Y ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- ASSERT (X->d != Y->d) ; ASSERT (X->nrow == Y->nrow) ; ASSERT (X->ncol == Y->ncol) ; ASSERT (X->dtype == Y->dtype) ; ASSERT (X->xtype == Y->xtype) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Real *Xx = (Real *) X->x ; #ifdef ZOMPLEX Real *Xz = (Real *) X->z ; #endif Real *Yx = (Real *) Y->x ; #ifdef ZOMPLEX Real *Yz = (Real *) Y->z ; #endif size_t nrow = X->nrow ; size_t ncol = X->ncol ; size_t xd = X->d ; size_t yd = Y->d ; //-------------------------------------------------------------------------- // get the sizes of the entries //-------------------------------------------------------------------------- size_t e = (X->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t fx = ((X->xtype == CHOLMOD_COMPLEX) ? 2 : 1) ; #ifdef ZOMPLEX size_t fz = ((X->xtype == CHOLMOD_ZOMPLEX) ? 1 : 0) ; #endif size_t e_fx_nrow = e * fx * nrow ; #ifdef ZOMPLEX size_t e_fz_nrow = e * fz * nrow ; #endif //-------------------------------------------------------------------------- // copy X = Y //-------------------------------------------------------------------------- for (size_t j = 0 ; j < ncol ; j++) { //---------------------------------------------------------------------- // Y (:,j) = X (:,j) //---------------------------------------------------------------------- memcpy (Yx, Xx, e_fx_nrow) ; Xx += xd * fx ; Yx += yd * fx ; #if defined ( ZOMPLEX ) memcpy (Yz, Xz, e_fz_nrow) ; Xz += xd * fz ; Yz += yd * fz ; #endif } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_copy_triplet.c0000644000175100001440000000075714552026002023715 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_copy_triplet: copy a triplet matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_copy_triplet.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_sym_worker.c0000644000175100001440000000323714552026002026016 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_transpose_sym_worker: C = A' or A(p,p)' //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_transpose_sym_worker) ( cholmod_sparse *C, // output matrix of size n-by-n cholmod_sparse *A, // input matrix of size n-by-n Int *Pinv, // size n, inverse permutation, or NULL if none Int *Wi // size n workspace; column pointers of C on input ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int n = A->ncol ; Int *Ap = (Int *) A->p ; Int *Ai = (Int *) A->i ; Int *Anz = (Int *) A->nz ; #ifndef PATTERN Real *Ax = (Real *) A->x ; #ifdef ZOMPLEX Real *Az = (Real *) A->z ; #endif #endif Int *Ci = (Int *) C->i ; #ifndef PATTERN Real *Cx = (Real *) C->x ; #ifdef ZOMPLEX Real *Cz = (Real *) C->z ; #endif #endif //-------------------------------------------------------------------------- // compute pattern and values of C //-------------------------------------------------------------------------- #define NUMERIC #include "t_cholmod_transpose_sym_template.c" } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX #undef NCONJUGATE Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_allocate_sparse.c0000644000175100001440000000077214552026002024651 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_allocate_sparse: allocate a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_allocate_sparse.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_ones.c0000644000175100001440000000677214552026002022472 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_ones: dense matrix of all ones //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Create a dense matrix with all entries equal to one, of any xtype or dtype. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_dense) (&X, Common) ; \ return (NULL) ; \ } //------------------------------------------------------------------------------ // t_cholmod_ones_worker template //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_ones_worker.c" #define COMPLEX #include "t_cholmod_ones_worker.c" #define ZOMPLEX #include "t_cholmod_ones_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_ones_worker.c" #define COMPLEX #include "t_cholmod_ones_worker.c" #define ZOMPLEX #include "t_cholmod_ones_worker.c" //------------------------------------------------------------------------------ // cholmod_ones: create a dense matrix all equal to 1 //------------------------------------------------------------------------------ cholmod_dense *CHOLMOD(ones) ( // input: size_t nrow, // # of rows size_t ncol, // # of columns int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (_REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate the matrix //-------------------------------------------------------------------------- cholmod_dense *X = CHOLMOD(allocate_dense) (nrow, ncol, nrow, xdtype, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // fill the matrix with all 1's //-------------------------------------------------------------------------- switch (xdtype % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_ones_worker (X) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_ones_worker (X) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_ones_worker (X) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_ones_worker (X) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_ones_worker (X) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_ones_worker (X) ; break ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_dense) (X, "ones:X", Common) >= 0) ; return (X) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_free_sparse.c0000644000175100001440000000075214552026002023471 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_free_sparse: free sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_free_sparse.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sparse_to_dense.c0000644000175100001440000001054014552026002024667 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_sparse_to_dense: convert a sparse matrix to dense //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Converts a sparse matrix (as input) to a new dense matrix (as output). // The xtype and dtype are preserved, except if A->xtype is pattern. In that // case, the output matrix X has an xtype of real, and consists of 1's and 0's. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_dense) (&X, Common) ; \ return (NULL) ; \ } //------------------------------------------------------------------------------ // t_cholmod_sparse_to_dense_worker template //------------------------------------------------------------------------------ #define DOUBLE #define PATTERN #include "t_cholmod_sparse_to_dense_worker.c" #define REAL #include "t_cholmod_sparse_to_dense_worker.c" #define COMPLEX #include "t_cholmod_sparse_to_dense_worker.c" #define ZOMPLEX #include "t_cholmod_sparse_to_dense_worker.c" #undef DOUBLE #define SINGLE #define PATTERN #include "t_cholmod_sparse_to_dense_worker.c" #define REAL #include "t_cholmod_sparse_to_dense_worker.c" #define COMPLEX #include "t_cholmod_sparse_to_dense_worker.c" #define ZOMPLEX #include "t_cholmod_sparse_to_dense_worker.c" //------------------------------------------------------------------------------ // cholmod_sparse_to_dense //------------------------------------------------------------------------------ cholmod_dense *CHOLMOD(sparse_to_dense) // return a dense matrix ( // input: cholmod_sparse *A, // input matrix cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_SPARSE_MATRIX_INVALID (A, NULL) ; Common->status = CHOLMOD_OK ; ASSERT (CHOLMOD(dump_sparse) (A, "sparse_to_dense:A", Common) >= 0) ; //-------------------------------------------------------------------------- // allocate an all-zero dense matrix //-------------------------------------------------------------------------- int xxtype = (A->xtype == CHOLMOD_PATTERN)? CHOLMOD_REAL : A->xtype ; cholmod_dense *X = CHOLMOD(zeros) (A->nrow, A->ncol, xxtype + A->dtype, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // copy A into X //-------------------------------------------------------------------------- switch ((A->xtype + A->dtype) % 8) { case CHOLMOD_PATTERN + CHOLMOD_SINGLE: // input A is pattern but output X is single ps_cholmod_sparse_to_dense_worker (X, A) ; break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_sparse_to_dense_worker (X, A) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_sparse_to_dense_worker (X, A) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_sparse_to_dense_worker (X, A) ; break ; case CHOLMOD_PATTERN + CHOLMOD_DOUBLE: // input A is pattern but output X is double p_cholmod_sparse_to_dense_worker (X, A) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_sparse_to_dense_worker (X, A) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_sparse_to_dense_worker (X, A) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_sparse_to_dense_worker (X, A) ; break ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_dense) (X, "sparse_to_dense:X", Common) >= 0) ; return (X) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_allocate_dense.c0000644000175100001440000000674514552026002024470 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_allocate_dense: allocate dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Allocate a dense matrix. The space is not initialized. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_dense) (&X, Common) ; \ return (NULL) ; \ } cholmod_dense *CHOLMOD(allocate_dense) ( // input: size_t nrow, // # of rows size_t ncol, // # of columns size_t d, // leading dimension int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // get the xtype and dtype //-------------------------------------------------------------------------- int xtype = xdtype & 3 ; // real, complex, or zomplex (not pattern) int dtype = xdtype & 4 ; // double or single if (xtype == CHOLMOD_PATTERN) { ERROR (CHOLMOD_INVALID, "xtype invalid") ; return (NULL) ; } d = MAX (d, nrow) ; // leading dimension d must be >= nrow int ok = TRUE ; size_t nzmax = CHOLMOD(mult_size_t) (d, ncol, &ok) ; if (!ok || nzmax >= Int_max) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (NULL) ; } //-------------------------------------------------------------------------- // allocate the header //-------------------------------------------------------------------------- cholmod_dense *X = CHOLMOD(calloc) (1, sizeof (cholmod_dense), Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // fill the header //-------------------------------------------------------------------------- X->nrow = nrow ; // # rows X->ncol = ncol ; // # columns X->xtype = xtype ; // real, complex, or zomplex X->dtype = dtype ; // double or single X->d = d ; // leading dimension //-------------------------------------------------------------------------- // reallocate the dense matrix to change X->nzmax from 0 to nzmax //-------------------------------------------------------------------------- CHOLMOD(realloc_multiple) (nzmax, /* nint: */ 0, xtype + dtype, /* I not used: */ NULL, /* J not used: */ NULL, &(X->x), &(X->z), &(X->nzmax), Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- // ASSERT (CHOLMOD(dump_dense) (X, "allocate_dense:X", Common) >= 0) ; return (X) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_dense_to_sparse.c0000644000175100001440000001021114552026002024662 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_dense_to_sparse: convert a dense matrix to sparse //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Converts a dense matrix X (as input) to a new sparse matrix C (as output). // The xtype and dtype are preserved, except if mode is 0 in which case C is // returned as a pattern sparse matrix. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_sparse) (&C, Common) ; \ return (NULL) ; \ } //------------------------------------------------------------------------------ // t_cholmod_dense_to_sparse_worker template //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_dense_to_sparse_worker.c" #define COMPLEX #include "t_cholmod_dense_to_sparse_worker.c" #define ZOMPLEX #include "t_cholmod_dense_to_sparse_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_dense_to_sparse_worker.c" #define COMPLEX #include "t_cholmod_dense_to_sparse_worker.c" #define ZOMPLEX #include "t_cholmod_dense_to_sparse_worker.c" //------------------------------------------------------------------------------ // cholmod_dense_to_sparse //------------------------------------------------------------------------------ cholmod_sparse *CHOLMOD(dense_to_sparse) // return a sparse matrix C ( // input: cholmod_dense *X, // input matrix int mode, // 1: copy the values // 0: C is pattern cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_DENSE_MATRIX_INVALID (X, NULL) ; Common->status = CHOLMOD_OK ; ASSERT (CHOLMOD(dump_dense) (X, "dense_to_sparse:X", Common) >= 0) ; //-------------------------------------------------------------------------- // allocate the sparse matrix result C //-------------------------------------------------------------------------- mode = RANGE (mode, 0, 1) ; int cnz = CHOLMOD(dense_nnz) (X, Common) ; int cxtype = (mode == 0) ? CHOLMOD_PATTERN : X->xtype ; cholmod_sparse *C = CHOLMOD(allocate_sparse) (X->nrow, X->ncol, cnz, /* C is sorted: */ TRUE, /* C is packed: */ TRUE, /* C->stype: */ 0, cxtype + X->dtype, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // copy the nonzeros (or just their pattern) from X into C //-------------------------------------------------------------------------- switch ((X->xtype + X->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_dense_to_sparse_worker (C, X) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_dense_to_sparse_worker (C, X) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_dense_to_sparse_worker (C, X) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_dense_to_sparse_worker (C, X) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_dense_to_sparse_worker (C, X) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_dense_to_sparse_worker (C, X) ; break ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_sparse) (C, "sparse_to_dense:C", Common) >= 0) ; return (C) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_start.c0000644000175100001440000000425114552026002022651 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_start: start CHOLMOD (int32/int64 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" // cholmod_start or cholmod_l_start must be called once prior to calling any // other CHOLMOD method. It contains workspace that must be freed by // cholmod_finish or cholmod_l_finish. int CHOLMOD(start) (cholmod_common *Common) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- if (Common == NULL) return (FALSE) ; //-------------------------------------------------------------------------- // settings required before CHOLMOD(defaults) //-------------------------------------------------------------------------- memset ((void *) Common, 0, sizeof (struct cholmod_common_struct)) ; Common->itype = ITYPE ; // CHOLMOD_INT or CHOLMOD_LONG //-------------------------------------------------------------------------- // set defaults //-------------------------------------------------------------------------- CHOLMOD(defaults) (Common) ; //-------------------------------------------------------------------------- // initialize the rest of Common to various nonzero values //-------------------------------------------------------------------------- Common->gpuMemorySize = 1 ; Common->chunk = 128000 ; Common->nthreads_max = SUITESPARSE_OPENMP_MAX_THREADS ; Common->modfl = EMPTY ; Common->aatfl = EMPTY ; Common->blas_ok = TRUE ; Common->SPQR_grain = 1 ; Common->SPQR_small = 1e6 ; Common->SPQR_shrink = 1 ; Common->mark = EMPTY ; Common->fl = EMPTY ; Common->lnz = EMPTY ; #ifdef BLAS_DUMP Common->blas_dump = fopen ("blas_dump.txt", "a") ; #endif return (TRUE) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_cumsum.c0000644000175100001440000000074414552026002022505 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_cumsum: cumulative sum (int32) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_cumsum.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_finish.c0000644000175100001440000000075414552026002022455 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_finish: finish CHOLMOD (int32 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_finish.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_sbound.c0000644000175100001440000000126014552026002022460 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_sbound: bound diagonal of LDL (single, int32) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_BOUND_FUNCTION cholmod_sbound #define COMMON_BOUND (Common->sbound) #define COMMON_BOUNDS_HIT (Common->nsbounds_hit) #define Real float #define CHOLMOD_INT32 #include "t_cholmod_bound.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_clear_flag.c0000644000175100001440000000075214552026002023565 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_clear_flag: clear Common->Flag //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_clear_flag.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_dense_nnz_worker.c0000644000175100001440000000310314552026002025063 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_dense_nnz: # of nonzeros in a dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static int64_t TEMPLATE (cholmod_dense_nnz_worker) ( cholmod_dense *X // input dense matrix ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Real *Xx = (Real *) X->x ; #ifdef ZOMPLEX Real *Xz = (Real *) X->z ; #endif Int nrow = (Int) X->nrow ; Int ncol = (Int) X->ncol ; Int d = (Int) X->d ; //-------------------------------------------------------------------------- // count # of nonzeros in X //-------------------------------------------------------------------------- int64_t xnz = 0 ; for (Int j = 0, jx = 0 ; j < ncol ; j++, jx += d) { for (Int p = jx ; p < jx + nrow ; p++) { xnz += ENTRY_IS_NONZERO (Xx, Xz, p) ; } } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (xnz) ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_band.c0000644000175100001440000000075514552026002022102 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_band: extract the band of a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_band.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_copy_sparse.c0000644000175100001440000000075414552026002023524 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_copy_sparse: copy a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_copy_sparse.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_malloc.c0000644000175100001440000000111614552026002022435 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_malloc: malloc (int32 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_ALLOC_FUNCTION cholmod_malloc #define SUITESPARSE_ALLOC_FUNCTION SuiteSparse_malloc #define CHOLMOD_INT32 #include "t_cholmod_malloc.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sparse_to_dense_worker.c0000644000175100001440000000774314552026002026273 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_sparse_to_dense_worker: sparse to dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_sparse_to_dense_worker) ( cholmod_dense *X, // output dense matrix, already allocated cholmod_sparse *A // input sparse matrix ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- ASSERT (X->d == X->nrow) ; ASSERT (X->nrow == A->nrow) ; ASSERT (X->ncol == A->ncol) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Real *Xx = (Real *) X->x ; #ifdef ZOMPLEX Real *Xz = (Real *) X->z ; #endif Int *Ap = (Int *) A->p ; Int *Ai = (Int *) A->i ; Int *Anz = (Int *) A->nz ; #ifndef PATTERN Real *Ax = (Real *) A->x ; #ifdef ZOMPLEX Real *Az = (Real *) A->z ; #endif #endif Int nrow = (Int) A->nrow ; Int ncol = (Int) A->ncol ; bool packed = (bool) A->packed ; bool upper = (A->stype > 0) ; bool lower = (A->stype < 0) ; //-------------------------------------------------------------------------- // copy a sparse matrix A into a dense matrix X //-------------------------------------------------------------------------- for (Int j = 0, jx = 0 ; j < ncol ; j++, jx += nrow) { //---------------------------------------------------------------------- // copy A(:,j) into X(:,j) //---------------------------------------------------------------------- Int p = Ap [j] ; Int pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { //------------------------------------------------------------------ // get A(i,j) //------------------------------------------------------------------ Int i = Ai [p] ; Int q = i + jx ; if (upper) { //-------------------------------------------------------------- // A is symmetric with upper part stored //-------------------------------------------------------------- if (i > j) continue ; // X(i,j) = A(i,j) ASSIGN2 (Xx, Xz, q, Ax, Az, p) ; if (i < j) { // X(j,i) = conj (A(i,j)) Int s = j + i*nrow ; ASSIGN2_CONJ (Xx, Xz, s, Ax, Az, p) ; } } else if (lower) { //-------------------------------------------------------------- // A is symmetric with lower part stored //-------------------------------------------------------------- if (i < j) continue ; // X(i,j) = A(i,j) ASSIGN2 (Xx, Xz, q, Ax, Az, p) ; if (i > j) { // X(j,i) = conj (A(i,j)) Int s = j + i*nrow ; ASSIGN2_CONJ (Xx, Xz, s, Ax, Az, p) ; } } else { //-------------------------------------------------------------- // A and X are both unsymmetric //-------------------------------------------------------------- // X(i,j) = A(i,j) ASSIGN2 (Xx, Xz, q, Ax, Az, p) ; } } } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_realloc.c0000644000175100001440000000074714552026002022620 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_realloc: realloc (int32 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_realloc.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_alloc_factor.c0000644000175100001440000000706714552026002024154 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_alloc_factor: allocate a simplicial factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Allocates a simplicial symbolic factor, with only L->Perm and L->ColCount // created and set to empty values (L->Perm is the identity permutation, and // ColCount is all 1's). L is pattern. Unlike cholmod_allocate_factor, the // factor can be either single or double precision. L->xtype is // CHOLMOD_PATTERN. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_factor) (&L, Common) ; \ return (NULL) ; \ } cholmod_factor *CHOLMOD(alloc_factor) // return the new factor L ( // input: size_t n, // L is factorization of an n-by-n matrix int dtype, // CHOLMOD_SINGLE or CHOLMOD_DOUBLE cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; Common->status = CHOLMOD_OK ; if ((int64_t) n >= Int_max) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (NULL) ; } //-------------------------------------------------------------------------- // get the dtype //-------------------------------------------------------------------------- dtype = dtype & 4 ; // double or single //-------------------------------------------------------------------------- // allocate the header for L //-------------------------------------------------------------------------- cholmod_factor *L = CHOLMOD(calloc) (1, sizeof (cholmod_factor), Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // fill the header //-------------------------------------------------------------------------- L->n = n ; // # of rows and columns L->itype = ITYPE ; // integer type L->dtype = dtype ; // double or single L->is_monotonic = TRUE ; // columns of L appear in order 0..n-1 L->minor = n ; // L has not been factorized //-------------------------------------------------------------------------- // allocate Perm and ColCount //-------------------------------------------------------------------------- L->Perm = CHOLMOD(malloc) (n, sizeof (Int), Common) ; L->ColCount = CHOLMOD(malloc) (n, sizeof (Int), Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // initialize Perm and and ColCount //-------------------------------------------------------------------------- Int *Perm = (Int *) L->Perm ; Int *ColCount = (Int *) L->ColCount ; for (Int j = 0 ; j < n ; j++) { Perm [j] = j ; ColCount [j] = 1 ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (L) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_realloc_multiple.c0000644000175100001440000000100414552026002025031 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_realloc_multiple: multiple realloc (int64 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_realloc_multiple.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_version.c0000644000175100001440000000074114552026002023171 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_version: CHOLMOD version //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_version.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_free_work.c0000644000175100001440000000076414552026002023161 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_free_work: free workspace in Common (int32) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_free_work.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_sparse_to_dense.c0000644000175100001440000000100214552026002024650 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_sparse_to_dense: convert a sparse matrix to dense //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_sparse_to_dense.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_reallocate_triplet.c0000644000175100001440000000100114552026002025350 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_reallocate_triplet: reallocate triplet matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_reallocate_triplet.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_speye.c0000644000175100001440000000074414552026002022634 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_speye: sparse identity matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_speye.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_reallocate_sparse.c0000644000175100001440000000077414552026002024667 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_reallocate_sparse: reallocate sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_reallocate_sparse.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_finish.c0000644000175100001440000000075614552026002022772 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_finish: finish CHOLMOD (int64 version) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_finish.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_mult_size_t.c0000644000175100001440000000076414552026002024047 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_mult_size_t: multiply two size_t values //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_mult_size_t.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_ensure_dense.c0000644000175100001440000000077614552026002023660 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_ensure_dense: ensure dense matrix has a given size //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_ensure_dense.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_free_factor.c0000644000175100001440000000076314552026002023454 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_free_factor: free a sparse factorization //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_free_factor.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_band_nnz.c0000644000175100001440000000077314552026002023302 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_band_nnz: # of entries in a band of sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_band_nnz.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_bound.c0000644000175100001440000000533614552026002022630 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_bound: bound diagonal of LDL //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" // Template for creating the following functions: // cholmod_dbound double, int32, using Common->dbound and ndbounds_hit // cholmod_l_dbound double, int64, using Common->dbound and ndbounds_hit // cholmod_sbound single, int32, using Common->sbound and nsbounds_hit // cholmod_l_sbound single, int64, using Common->sbound and nsbounds_hit // This method ensures that the absolute value of D(j,j) is greater than dbound // (for double) or sbound (for single), for LDL' factorization and // update/downdate. It is not used for supernodal factorization. Real CHOLMOD_BOUND_FUNCTION // returns modified diagonal entry D(j,j) ( // input: Real djj, // input diagonal entry D(j,j) cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (0) ; if (isnan (djj)) return (djj) ; // no change if D(j,j) is NaN //-------------------------------------------------------------------------- // check the bound //-------------------------------------------------------------------------- bool hit ; Real bound ; if (djj >= 0) { // D(j,j) is positive: check if djj in range [0,Common->bound] bound = COMMON_BOUND ; hit = (djj < bound) ; } else { // D(j,j) is negative: check if djj in range [-Common->bound,0] bound = -COMMON_BOUND ; hit = (djj > bound) ; } //-------------------------------------------------------------------------- // record the hit //-------------------------------------------------------------------------- if (hit) { // bound the diagonal entry djj = bound ; // record the # of times the bound was hit COMMON_BOUNDS_HIT++ ; // set an error flag, if not already set if (Common->status == CHOLMOD_OK) { ERROR (CHOLMOD_DSMALL, "diagonal entry is below threshold") ; } } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (djj) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_cumsum.c0000644000175100001440000000074614552026002023022 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_cumsum: cumulative sum (int64) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_cumsum.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_unsym_worker.c0000644000175100001440000000473314552026002026363 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_transpose_unsym_worker: C = A', A(:,f)', or A(p,f)' //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static void TEMPLATE (cholmod_transpose_unsym_worker) ( cholmod_sparse *A, // input matrix Int *fset, // a list of column indices in range 0:A->ncol-1 Int nf, // # of entries in fset cholmod_sparse *C, // output matrix, must be allocated on input Int *Wi // workspace of size nrow ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Ap = (Int *) A->p ; Int *Ai = (Int *) A->i ; Int *Anz = (Int *) A->nz ; #ifndef PATTERN Real *Ax = (Real *) A->x ; #ifdef ZOMPLEX Real *Az = (Real *) A->z ; #endif #endif Int ncol = A->ncol ; Int *Ci = (Int *) C->i ; #ifndef PATTERN Real *Cx = (Real *) C->x ; #ifdef ZOMPLEX Real *Cz = (Real *) C->z ; #endif #endif //-------------------------------------------------------------------------- // compute the pattern and values of C //-------------------------------------------------------------------------- if (fset != NULL) { if (A->packed) { // C = A (p,f)' or A(:,f)' where A is packed #define PACKED #define FSET #include "t_cholmod_transpose_unsym_template.c" return ; } else { // C = A (p,f)' or A(:,f)' where A is unpacked #define FSET #include "t_cholmod_transpose_unsym_template.c" return ; } } else { if (A->packed) { // C = A (p,:)' or A' where A is packed #define PACKED #include "t_cholmod_transpose_unsym_template.c" return ; } else { // C = A (p,:)' or A' where A is unpacked #include "t_cholmod_transpose_unsym_template.c" return ; } } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX #undef NCONJUGATE Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_dense_nnz.c0000644000175100001440000000573014552026002023502 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_dense_nnz: # of nonzeros in a dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Returns the # of nonzero entries in a dense matrix. #include "cholmod_internal.h" //------------------------------------------------------------------------------ // t_cholmod_dense_nnz_worker template //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_dense_nnz_worker.c" #define COMPLEX #include "t_cholmod_dense_nnz_worker.c" #define ZOMPLEX #include "t_cholmod_dense_nnz_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_dense_nnz_worker.c" #define COMPLEX #include "t_cholmod_dense_nnz_worker.c" #define ZOMPLEX #include "t_cholmod_dense_nnz_worker.c" //------------------------------------------------------------------------------ // cholmod_dense_nnz //------------------------------------------------------------------------------ int64_t CHOLMOD(dense_nnz) // return # of entries in the dense matrix ( // input: cholmod_dense *X, // input matrix cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (EMPTY) ; RETURN_IF_DENSE_MATRIX_INVALID (X, EMPTY) ; Common->status = CHOLMOD_OK ; ASSERT (CHOLMOD(dump_dense) (X, "dense_nnz:X", Common) >= 0) ; //-------------------------------------------------------------------------- // count the # of nonzero entries in X //-------------------------------------------------------------------------- int xnz = 0 ; switch ((X->xtype + X->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: xnz = rs_cholmod_dense_nnz_worker (X) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: xnz = cs_cholmod_dense_nnz_worker (X) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: xnz = zs_cholmod_dense_nnz_worker (X) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: xnz = rd_cholmod_dense_nnz_worker (X) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: xnz = cd_cholmod_dense_nnz_worker (X) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: xnz = zd_cholmod_dense_nnz_worker (X) ; break ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (xnz) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_free.c0000644000175100001440000000346314552026002022441 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_free: free (int64/int32) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" void *CHOLMOD(free) // returns NULL to simplify its usage ( // input: size_t n, // number of items size_t size, // size of each item // input/output: void *p, // memory to free cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; if (p == NULL) return (NULL) ; // nothing to do (not an error) #ifndef NDEBUG size_t size2 = CM_memtable_size (p) ; ASSERT (n * size == size2) ; #endif //-------------------------------------------------------------------------- // free memory //-------------------------------------------------------------------------- SuiteSparse_free (p) ; //-------------------------------------------------------------------------- // log memory usage and return result //-------------------------------------------------------------------------- Common->memory_inuse -= (n * size) ; Common->malloc_count-- ; PRINTM (("cholmod_free %p %g cnt: %g inuse %g\n", p, (double) n*size, (double) Common->malloc_count, (double) Common->memory_inuse)) ; #ifndef NDEBUG CM_memtable_remove (p) ; #endif return (NULL) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_speye.c0000644000175100001440000000761614552026002022651 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_speye: sparse identity matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Create a sparse identity matrix, possibly rectangular, of any xtype or // dtype. The A->stype is zero (unsymmetric) but this can be modified by the // caller to either +1 or -1, and the matrix will still be valid. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_sparse) (&A, Common) ; \ return (NULL) ; \ } //------------------------------------------------------------------------------ // t_cholmod_speye_worker template //------------------------------------------------------------------------------ #define PATTERN #include "t_cholmod_speye_worker.c" #define DOUBLE #define REAL #include "t_cholmod_speye_worker.c" #define COMPLEX #include "t_cholmod_speye_worker.c" #define ZOMPLEX #include "t_cholmod_speye_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_speye_worker.c" #define COMPLEX #include "t_cholmod_speye_worker.c" #define ZOMPLEX #include "t_cholmod_speye_worker.c" //------------------------------------------------------------------------------ // cholmod_speye: create a sparse identity matrix //------------------------------------------------------------------------------ cholmod_sparse *CHOLMOD(speye) ( // input: size_t nrow, // # of rows size_t ncol, // # of columns int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate the matrix //-------------------------------------------------------------------------- cholmod_sparse *A = CHOLMOD(allocate_sparse) (nrow, ncol, MIN (nrow, ncol), /* A is sorted: */ TRUE, /* A is packed: */ TRUE, /* stype: */ 0, xdtype, Common) ; RETURN_IF_ERROR ; //-------------------------------------------------------------------------- // fill the matrix with all 1's on the diagonal //-------------------------------------------------------------------------- switch (xdtype % 8) { default: p_cholmod_speye_worker (A) ; break ; case CHOLMOD_REAL + CHOLMOD_SINGLE: rs_cholmod_speye_worker (A) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: cs_cholmod_speye_worker (A) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: zs_cholmod_speye_worker (A) ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_speye_worker (A) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_speye_worker (A) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: zd_cholmod_speye_worker (A) ; break ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_sparse) (A, "speye:A", Common) >= 0) ; return (A) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_allocate_factor.c0000644000175100001440000000160114552026002024622 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_allocate_factor: allocate a simplicial factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // For backward compatibilty; L is returned as double precision. // Use cholmod_l_alloc_factor to allocate a single precision factor. #define CHOLMOD_INT64 #include "cholmod_internal.h" cholmod_factor *cholmod_l_allocate_factor // return the new factor L ( // input: size_t n, // L is factorization of an n-by-n matrix cholmod_common *Common ) { return (cholmod_l_alloc_factor (n, CHOLMOD_DOUBLE, Common)) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_clear_flag.c0000644000175100001440000000075014552026002023250 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_clear_flag: clear Common->Flag //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_clear_flag.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_copy_dense2.c0000644000175100001440000000075314552026002023406 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_copy_dense2: copy a dense matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_copy_dense2.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_realloc.c0000644000175100001440000000540014552026002023132 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_realloc: realloc (int64/int32) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" void *CHOLMOD(realloc) // return newly reallocated block of memory ( // input: size_t nnew, // # of items in newly reallocate memory size_t size, // size of each item // input/output: void *p, // pointer to memory to reallocate (may be NULL) size_t *n, // # of items in p on input; nnew on output if success cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; //-------------------------------------------------------------------------- // realloc the block //-------------------------------------------------------------------------- int ok ; bool newly_allocated = (p == NULL) ; #ifndef NDEBUG void *pold = p ; #endif size_t nold = (*n) ; p = SuiteSparse_realloc (nnew, *n, size, p, &ok) ; //-------------------------------------------------------------------------- // log memory usage and return result //-------------------------------------------------------------------------- if (ok) { // success: log the change in memory usage and update n to new # items if (!newly_allocated) { PRINTM (("cholmod_free %p %g cnt: %g inuse %g\n", pold, (double) nold*size, (double) Common->malloc_count-1, (double) (Common->memory_inuse - nold*size))) ; #ifndef NDEBUG size_t size2 = CM_memtable_size (pold) ; ASSERT (nold * size == size2) ; CM_memtable_remove (pold) ; #endif } Common->memory_inuse += ((nnew-nold) * size) ; Common->memory_usage = MAX (Common->memory_usage, Common->memory_inuse); if (newly_allocated) { Common->malloc_count++ ; } PRINTM (("cholmod_malloc %p %g cnt: %g inuse %g\n", p, (double) nnew*size, (double) Common->malloc_count, (double) Common->memory_inuse)) ; #ifndef NDEBUG CM_memtable_add (p, nnew * size) ; #endif (*n) = nnew ; } else { // p is unchanged ERROR (CHOLMOD_OUT_OF_MEMORY, "out of memory") ; } return (p) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_triplet_to_sparse_worker.c0000644000175100001440000001504614552026002026653 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_triplet_to_sparse_worker //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static size_t TEMPLATE (cholmod_triplet_to_sparse_worker) // return nnz(R) ( cholmod_triplet *T, // input matrix cholmod_sparse *R, // output matrix cholmod_common *Common ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Rp = (Int *) R->p ; Int *Ri = (Int *) R->i ; Int *Rnz = (Int *) R->nz ; #ifndef PATTERN Real *Rx = (Real *) R->x ; #ifdef ZOMPLEX Real *Rz = (Real *) R->z ; #endif #endif Int *Ti = (Int *) T->i ; Int *Tj = (Int *) T->j ; #ifndef PATTERN Real *Tx = (Real *) T->x ; #ifdef ZOMPLEX Real *Tz = (Real *) T->z ; #endif #endif size_t nrow = T->nrow ; size_t ncol = T->ncol ; Int nz = T->nnz ; //-------------------------------------------------------------------------- // W [0..nrow-1] = Rp [0..nrow-1] using Iwork workspace //-------------------------------------------------------------------------- // using W [0..nrow-1] as workspace for row pointers [ Int *W = (Int *) Common->Iwork ; memcpy (W, Rp, nrow * sizeof (Int)) ; //-------------------------------------------------------------------------- // construct the matrix R, keeping duplicates for now //-------------------------------------------------------------------------- // R is treated as if it is stored by row, in the comments below int stype = T->stype ; for (Int k = 0 ; k < nz ; k++) { // get the T (i,j) entry Int i = Ti [k] ; Int j = Tj [k] ; Int p ; if (stype > 0) { // T represents a symmetric matrix with upper part stored if (i < j) { // R (i,j) = T (i,j), placed in row R (i,:) Ri [p = W [i]++] = j ; } else { // R (j,i) = T (i,j), placed in row R (j,:) Ri [p = W [j]++] = i ; } } else if (stype < 0) { // T represents a symmetric matrix with lower part stored if (i > j) { // R (i,j) = T (i,j), placed in row R (i,:) Ri [p = W [i]++] = j ; } else { // R (j,i) = T (i,j), placed in row R (j,:) Ri [p = W [j]++] = i ; } } else { // T represents an unsymmetric matrix // R (i,j) = T (i,j), placed in row R (i,:) Ri [p = W [i]++] = j ; } ASSIGN (Rx, Rz, p, Tx, Tz, k) ; // Rx [p] = Tx [k] } // no longer using W as temporary workspace for row pointers ] //-------------------------------------------------------------------------- // assemble any duplicate entries //-------------------------------------------------------------------------- // use W [0..ncol-1] for pointers to duplicates in each row of R [ CHOLMOD(set_empty) (W, ncol) ; size_t rnz = 0 ; // total # of entries in R after assembling duplicates for (Int i = 0 ; i < nrow ; i++) { //---------------------------------------------------------------------- // get the location of R (i,:) before assemblying duplicates //---------------------------------------------------------------------- // row R (i,:) is in located in Ri [pstart..pend-1]. If duplicates are // detected, the new row i will be located in Ri [pstart..pp-1]. Int pstart = Rp [i] ; Int pend = Rp [i+1] ; Int pp = pstart ; // W [j] is the position in Ri of the last time column j was seen. // Here, W [0..ncol-1] < pstart is true because R is stored by row, // and any column j already seen will have been seen in an earlier // row. If column j has never been seen, W [j] is EMPTY (-1). //---------------------------------------------------------------------- // assemble duplicates in R (i,:) //---------------------------------------------------------------------- for (Int p = pstart ; p < pend ; p++) { //------------------------------------------------------------------ // get R(i,j) //------------------------------------------------------------------ Int j = Ri [p] ; Int plastj = W [j] ; // last seen position of column index j //------------------------------------------------------------------ // assemble R(i,j) //------------------------------------------------------------------ if (plastj < pstart) { // column j has been seen for the first time in row R (i,:), // at position pp. Move the entry to position pp, and keep // track of it in case column j appears again in row R (i,:). // Rx [pp] = Rx [p] ASSIGN (Rx, Rz, pp, Rx, Rz, p) ; Ri [pp] = j ; // one more unique entry has been seen in R (i,:) W [j] = pp++ ; } else { // column j has already been seen in this row R (i,;), at // position plastj, so assemble this duplicate entry into that // position. // Rx [plastj] += Rx [p] ASSEMBLE (Rx, Rz, plastj, Rx, Rz, p) ; } } //---------------------------------------------------------------------- // count the number of entries in R (i,:) //---------------------------------------------------------------------- Int rnz_i = pp - pstart ; Rnz [i] = rnz_i ; rnz += rnz_i ; } // done using W [0..ncol-1] workspace ] //-------------------------------------------------------------------------- // return result: # of entries in R after assembling duplicates //-------------------------------------------------------------------------- return (rnz) ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_defaults.c0000644000175100001440000001301514552026002023321 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_defaults: set CHOLMOD defaults //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" // Sets all CHOLMOD parameters to their default values. int CHOLMOD(defaults) (cholmod_common *Common) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; //-------------------------------------------------------------------------- // set defaults //-------------------------------------------------------------------------- Common->dbound = 0.0 ; // bound D for LDL' (double case) Common->sbound = 0.0 ; // bound D for LDL' (single case) Common->grow0 = 1.2 ; // how to grow L for simplicial method Common->grow1 = 1.2 ; Common->grow2 = 5 ; Common->maxrank = 8 ; // max rank for update/downdate Common->final_asis = TRUE ; // leave L as-is Common->final_super = TRUE ; // leave L supernodal Common->final_ll = FALSE ; // leave factorization as LDL' Common->final_pack = TRUE ; // pack columns when done Common->final_monotonic = TRUE ; // sort columns when done Common->final_resymbol = FALSE ; // do not resymbol when done Common->supernodal = CHOLMOD_AUTO ; // select supernodal automatically Common->supernodal_switch = 40 ; // how to select super vs simpicial Common->prefer_zomplex = FALSE ; // use complex, not zomplex Common->prefer_upper = TRUE ; // sym case: use upper not lower Common->prefer_binary = FALSE ; // use 1's when converting from pattern Common->quick_return_if_not_posdef = FALSE ; // return early if not posdef Common->metis_memory = 0.0 ; // metis memory control Common->metis_nswitch = 3000 ; Common->metis_dswitch = 0.66 ; Common->nrelax [0] = 4 ; // supernodal relaxation parameters Common->nrelax [1] = 16 ; Common->nrelax [2] = 48 ; Common->zrelax [0] = 0.8 ; Common->zrelax [1] = 0.1 ; Common->zrelax [2] = 0.05 ; Common->print = 3 ; // print control Common->precise = FALSE ; // print 5 digits //-------------------------------------------------------------------------- // ordering methods //-------------------------------------------------------------------------- Common->nmethods = 0 ; // use default strategy Common->default_nesdis = FALSE ; // use METIS not NESDIS Common->current = 0 ; // method being evaluated Common->selected = EMPTY ; // final method chosen Common->postorder = TRUE ; // use weighted postordering // defaults for all methods (revised below) for (int i = 0 ; i <= CHOLMOD_MAXMETHODS ; i++) { Common->method [i].ordering = CHOLMOD_AMD ; // use AMD Common->method [i].fl = EMPTY ; // no flop counts yet Common->method [i].lnz = EMPTY ; // no lnz counts yet Common->method [i].prune_dense = 10.0 ; // dense row/col parameter Common->method [i].prune_dense2 = -1 ; // dense row/col parameter Common->method [i].aggressive = TRUE ; // aggressive absorption Common->method [i].order_for_lu = FALSE ; // order for chol, not lu Common->method [i].nd_small = 200 ; // nesdis: small graph Common->method [i].nd_compress = TRUE ; // nesdis: compression Common->method [i].nd_camd = 1 ; // nesdis: use CAMD Common->method [i].nd_components = FALSE ; // nesdis: use components Common->method [i].nd_oksep = 1.0 ; // nesdis: for good sep } // define the 9 methods: // (0) given (skipped if no user permutation) // (1) amd // (2) metis // (3) nesdis with defaults // (4) natural // (5) nesdis: stop at subgraphs of 20000 nodes // (6) nesdis: stop at subgraphs of 4 nodes, do not use CAMD // (7) nesdis: no pruning on of dense rows/cols // (8) colamd Common->method [0].ordering = CHOLMOD_GIVEN ; Common->method [2].ordering = CHOLMOD_METIS ; Common->method [3].ordering = CHOLMOD_NESDIS ; Common->method [4].ordering = CHOLMOD_NATURAL ; Common->method [5].ordering = CHOLMOD_NESDIS ; Common->method [5].nd_small = 20000 ; Common->method [6].ordering = CHOLMOD_NESDIS ; Common->method [6].nd_small = 4 ; Common->method [6].nd_camd = 0 ; Common->method [7].ordering = CHOLMOD_NESDIS ; Common->method [7].prune_dense = -1. ; Common->method [8].ordering = CHOLMOD_COLAMD ; //-------------------------------------------------------------------------- // GPU //-------------------------------------------------------------------------- #if defined ( CHOLMOD_INT64 ) // only use the GPU for the int64 version Common->useGPU = EMPTY ; #else Common->useGPU = 0 ; #endif //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (TRUE) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_sym_permuted.c0000644000175100001440000000440714552026002026332 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_transpose_sym_permuted //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // C = A(p,p)' where A and C are symmetric //------------------------------------------------------------------------------ // The including file must define or undef PACKED, NUMERIC, and LO. // define PACKED: if A->packed is true, undefine if A->packed is false // define LO: if A is symmetric lower, undefine it if A is upper // define NUMERIC: if computing values and pattern of C, undefine it if // computing just the column counts of C. //------------------------------------------------------------------------------ { for (Int jold = 0 ; jold < n ; jold++) { Int jnew = Pinv [jold] ; Int pa = Ap [jold] ; #ifdef PACKED Int paend = Ap [jold+1] ; #else Int paend = pa + Anz [jold] ; #endif for ( ; pa < paend ; pa++) { // get A(iold,jold) Int iold = Ai [pa] ; Int inew = Pinv [iold] ; #ifdef LO // A is symmetric lower, C is symmetric upper if (iold < jold) continue ; if (inew > jnew) #else // A is symmetric upper, C is symmetric lower if (iold > jold) continue ; if (inew < jnew) #endif { // C(jnew,inew) = conj (A(iold,jold)) #ifdef NUMERIC Int pc = #endif Wi [inew]++ ; #ifdef NUMERIC ASSIGN_CONJ_OR_NCONJ (Cx, Cz, pc, Ax, Az, pa) ; Ci [pc] = jnew ; #endif } else { // C(inew,jnew) = A(iold,jold) #ifdef NUMERIC Int pc = #endif Wi [jnew]++ ; #ifdef NUMERIC ASSIGN (Cx, Cz, pc, Ax, Az, pa) ; Ci [pc] = inew ; #endif } } } } #undef PACKED #undef LO Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_alloc_factor.c0000644000175100001440000000077014552026002024136 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_alloc_factor: allocate a simplicial factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_alloc_factor.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_transpose.c0000644000175100001440000000075714552026002023531 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_transpose: transpose a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_transpose.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_copy.c0000644000175100001440000000076514552026002022151 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_copy: copy a sparse matrix (with change of stype) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_copy.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_sparse_to_triplet.c0000644000175100001440000000077714552026002025257 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_sparse_to_triplet: convert sparse to triplet //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_sparse_to_triplet.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/t_cholmod_ensure_dense.c0000644000175100001440000000720014552026002024170 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/t_cholmod_ensure_dense: ensure dense matrix has a given size //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Ensure a dense matrix has a given size, xtype, and dtype. If not, it is // freed and reallocated. #include "cholmod_internal.h" #define RETURN_IF_ERROR \ if (Common->status < CHOLMOD_OK) \ { \ CHOLMOD(free_dense) (X, Common) ; \ return (NULL) ; \ } cholmod_dense *CHOLMOD(ensure_dense) ( // input/output: cholmod_dense **X, // matrix to resize as needed (*X may be NULL) // input: size_t nrow, // # of rows size_t ncol, // # of columns size_t d, // leading dimension int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_NULL (X, NULL) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // get the xtype and dtype //-------------------------------------------------------------------------- int xtype = xdtype & 3 ; // real, complex, or zomplex (not pattern) int dtype = xdtype & 4 ; // double or single if (xtype == CHOLMOD_PATTERN) { ERROR (CHOLMOD_INVALID, "xtype invalid") ; return (NULL) ; } //-------------------------------------------------------------------------- // get the dimensions //-------------------------------------------------------------------------- d = MAX (d, nrow) ; // leading dimension d must be >= nrow int ok = TRUE ; size_t nzmax_required = CHOLMOD(mult_size_t) (d, ncol, &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (NULL) ; } //-------------------------------------------------------------------------- // reshape or reallocate the matrix //-------------------------------------------------------------------------- if ((*X) != NULL && nzmax_required <= (*X)->nzmax && xtype == (*X)->xtype && dtype == (*X)->dtype) { // The required total size (nzmax_required) is ok, but the dimensions // might not be. This allows an n-by-m matrix to be reconfigured in // O(1) time into an m-by-n matrix. X->nzmax is not changed, so a // matrix can be reduced in size in O(1) time, and then enlarged again // back to the original size, also in O(1) time. (*X)->nrow = nrow ; (*X)->ncol = ncol ; (*X)->d = d ; RETURN_IF_DENSE_MATRIX_INVALID (*X, NULL) ; } else { // free the matrix and reallocate it with the right properties CHOLMOD(free_dense) (X, Common) ; (*X) = CHOLMOD(allocate_dense) (nrow, ncol, d, xdtype, Common) ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- return (*X) ; } Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_sort.c0000644000175100001440000000073614552026002022164 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_sort: sort a sparse matrix //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_sort.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_sparse_to_triplet.c0000644000175100001440000000077514552026002024742 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_sparse_to_triplet: convert sparse to triplet //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_sparse_to_triplet.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_allocate_triplet.c0000644000175100001440000000100314552026002025023 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_allocate_triplet: allocate triplet matrix (int64) //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_allocate_triplet.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_pack_factor.c0000644000175100001440000000076714552026002023455 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_pack_factor: pack a simplicial factorization //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT32 #include "t_cholmod_pack_factor.c" Matrix/src/SuiteSparse/CHOLMOD/Utility/cholmod_l_reallocate_factor.c0000644000175100001440000000077114552026002025160 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Utility/cholmod_l_reallocate_factor: reallocate a factor //------------------------------------------------------------------------------ // CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights // Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "t_cholmod_reallocate_factor.c" Matrix/src/SuiteSparse/CHOLMOD/Makefile0000644000175100001440000001664314576344042017342 0ustar hornikuserssources = \ Check/cholmod_check.c Check/cholmod_l_check.c \ Check/cholmod_read.c Check/cholmod_l_read.c \ Check/cholmod_write.c Check/cholmod_l_write.c \ Cholesky/cholmod_amd.c Cholesky/cholmod_l_amd.c \ Cholesky/cholmod_analyze.c Cholesky/cholmod_l_analyze.c \ Cholesky/cholmod_colamd.c Cholesky/cholmod_l_colamd.c \ Cholesky/cholmod_etree.c Cholesky/cholmod_l_etree.c \ Cholesky/cholmod_factorize.c Cholesky/cholmod_l_factorize.c \ Cholesky/cholmod_postorder.c Cholesky/cholmod_l_postorder.c \ Cholesky/cholmod_rcond.c Cholesky/cholmod_l_rcond.c \ Cholesky/cholmod_resymbol.c Cholesky/cholmod_l_resymbol.c \ Cholesky/cholmod_rowcolcounts.c Cholesky/cholmod_l_rowcolcounts.c \ Cholesky/cholmod_rowfac.c Cholesky/cholmod_l_rowfac.c \ Cholesky/cholmod_solve.c Cholesky/cholmod_l_solve.c \ Cholesky/cholmod_spsolve.c Cholesky/cholmod_l_spsolve.c \ Utility/cholmod_aat.c Utility/cholmod_l_aat.c \ Utility/cholmod_add.c Utility/cholmod_l_add.c \ Utility/cholmod_add_size_t.c Utility/cholmod_l_add_size_t.c \ Utility/cholmod_alloc_factor.c Utility/cholmod_l_alloc_factor.c \ Utility/cholmod_alloc_work.c Utility/cholmod_l_alloc_work.c \ Utility/cholmod_allocate_dense.c Utility/cholmod_l_allocate_dense.c \ Utility/cholmod_allocate_factor.c Utility/cholmod_l_allocate_factor.c \ Utility/cholmod_allocate_sparse.c Utility/cholmod_l_allocate_sparse.c \ Utility/cholmod_allocate_triplet.c Utility/cholmod_l_allocate_triplet.c \ Utility/cholmod_allocate_work.c Utility/cholmod_l_allocate_work.c \ Utility/cholmod_band.c Utility/cholmod_l_band.c \ Utility/cholmod_band_nnz.c Utility/cholmod_l_band_nnz.c \ Utility/cholmod_calloc.c Utility/cholmod_l_calloc.c \ Utility/cholmod_change_factor.c Utility/cholmod_l_change_factor.c \ Utility/cholmod_clear_flag.c Utility/cholmod_l_clear_flag.c \ Utility/cholmod_copy.c Utility/cholmod_l_copy.c \ Utility/cholmod_copy_dense.c Utility/cholmod_l_copy_dense.c \ Utility/cholmod_copy_dense2.c Utility/cholmod_l_copy_dense2.c \ Utility/cholmod_copy_factor.c Utility/cholmod_l_copy_factor.c \ Utility/cholmod_copy_sparse.c Utility/cholmod_l_copy_sparse.c \ Utility/cholmod_copy_triplet.c Utility/cholmod_l_copy_triplet.c \ Utility/cholmod_cumsum.c Utility/cholmod_l_cumsum.c \ Utility/cholmod_dbound.c Utility/cholmod_l_dbound.c \ Utility/cholmod_defaults.c Utility/cholmod_l_defaults.c \ Utility/cholmod_dense_nnz.c Utility/cholmod_l_dense_nnz.c \ Utility/cholmod_dense_to_sparse.c Utility/cholmod_l_dense_to_sparse.c \ Utility/cholmod_divcomplex.c Utility/cholmod_l_divcomplex.c \ Utility/cholmod_ensure_dense.c Utility/cholmod_l_ensure_dense.c \ Utility/cholmod_error.c Utility/cholmod_l_error.c \ Utility/cholmod_eye.c Utility/cholmod_l_eye.c \ Utility/cholmod_factor_to_sparse.c Utility/cholmod_l_factor_to_sparse.c \ Utility/cholmod_finish.c Utility/cholmod_l_finish.c \ Utility/cholmod_free.c Utility/cholmod_l_free.c \ Utility/cholmod_free_dense.c Utility/cholmod_l_free_dense.c \ Utility/cholmod_free_factor.c Utility/cholmod_l_free_factor.c \ Utility/cholmod_free_sparse.c Utility/cholmod_l_free_sparse.c \ Utility/cholmod_free_triplet.c Utility/cholmod_l_free_triplet.c \ Utility/cholmod_free_work.c Utility/cholmod_l_free_work.c \ Utility/cholmod_hypot.c Utility/cholmod_l_hypot.c \ Utility/cholmod_malloc.c Utility/cholmod_l_malloc.c \ Utility/cholmod_maxrank.c Utility/cholmod_l_maxrank.c \ Utility/cholmod_memdebug.c \ Utility/cholmod_mult_size_t.c Utility/cholmod_l_mult_size_t.c \ Utility/cholmod_mult_uint64_t.c \ Utility/cholmod_nnz.c Utility/cholmod_l_nnz.c \ Utility/cholmod_ones.c Utility/cholmod_l_ones.c \ Utility/cholmod_pack_factor.c Utility/cholmod_l_pack_factor.c \ Utility/cholmod_ptranspose.c Utility/cholmod_l_ptranspose.c \ Utility/cholmod_realloc.c Utility/cholmod_l_realloc.c \ Utility/cholmod_realloc_multiple.c Utility/cholmod_l_realloc_multiple.c \ Utility/cholmod_reallocate_column.c Utility/cholmod_l_reallocate_column.c \ Utility/cholmod_reallocate_factor.c Utility/cholmod_l_reallocate_factor.c \ Utility/cholmod_reallocate_sparse.c Utility/cholmod_l_reallocate_sparse.c \ Utility/cholmod_reallocate_triplet.c Utility/cholmod_l_reallocate_triplet.c \ Utility/cholmod_sbound.c Utility/cholmod_l_sbound.c \ Utility/cholmod_score_comp.c Utility/cholmod_l_score_comp.c \ Utility/cholmod_set_empty.c Utility/cholmod_l_set_empty.c \ Utility/cholmod_sort.c Utility/cholmod_l_sort.c \ Utility/cholmod_sparse_to_dense.c Utility/cholmod_l_sparse_to_dense.c \ Utility/cholmod_sparse_to_triplet.c Utility/cholmod_l_sparse_to_triplet.c \ Utility/cholmod_speye.c Utility/cholmod_l_speye.c \ Utility/cholmod_spzeros.c Utility/cholmod_l_spzeros.c \ Utility/cholmod_start.c Utility/cholmod_l_start.c \ Utility/cholmod_transpose.c Utility/cholmod_l_transpose.c \ Utility/cholmod_transpose_sym.c Utility/cholmod_l_transpose_sym.c \ Utility/cholmod_transpose_unsym.c Utility/cholmod_l_transpose_unsym.c \ Utility/cholmod_triplet_to_sparse.c Utility/cholmod_l_triplet_to_sparse.c \ Utility/cholmod_version.c Utility/cholmod_l_version.c \ Utility/cholmod_xtype.c Utility/cholmod_l_xtype.c \ Utility/cholmod_zeros.c Utility/cholmod_l_zeros.c \ MatrixOps/cholmod_drop.c MatrixOps/cholmod_l_drop.c \ MatrixOps/cholmod_horzcat.c MatrixOps/cholmod_l_horzcat.c \ MatrixOps/cholmod_norm.c MatrixOps/cholmod_l_norm.c \ MatrixOps/cholmod_scale.c MatrixOps/cholmod_l_scale.c \ MatrixOps/cholmod_sdmult.c MatrixOps/cholmod_l_sdmult.c \ MatrixOps/cholmod_ssmult.c MatrixOps/cholmod_l_ssmult.c \ MatrixOps/cholmod_submatrix.c MatrixOps/cholmod_l_submatrix.c \ MatrixOps/cholmod_symmetry.c MatrixOps/cholmod_l_symmetry.c \ MatrixOps/cholmod_vertcat.c MatrixOps/cholmod_l_vertcat.c \ Modify/cholmod_rowadd.c Modify/cholmod_l_rowadd.c \ Modify/cholmod_rowdel.c Modify/cholmod_l_rowdel.c \ Modify/cholmod_updown.c Modify/cholmod_l_updown.c \ Partition/cholmod_camd.c Partition/cholmod_l_camd.c \ Partition/cholmod_ccolamd.c Partition/cholmod_l_ccolamd.c \ Partition/cholmod_csymamd.c Partition/cholmod_l_csymamd.c \ Partition/cholmod_metis.c Partition/cholmod_l_metis.c \ Partition/cholmod_metis_wrapper.c \ Partition/cholmod_nesdis.c Partition/cholmod_l_nesdis.c \ Supernodal/cholmod_super_numeric.c Supernodal/cholmod_l_super_numeric.c \ Supernodal/cholmod_super_solve.c Supernodal/cholmod_l_super_solve.c \ Supernodal/cholmod_super_symbolic.c Supernodal/cholmod_l_super_symbolic.c objects = $(sources:.c=.o) archive = CHOLMOD.a PKG_CPPFLAGS = -I./Include -I../SuiteSparse_config \ -I../AMD/Include -I../COLAMD/Include \ -I../CAMD/Include -I../CCOLAMD/Include \ -I. -I./SuiteSparse_metis/include \ -I./SuiteSparse_metis/GKlib -I./SuiteSparse_metis/libmetis all : $(archive) $(archive) : $(objects) rm -f $@ $(AR) -cr $@ $(objects) $(RANLIB) $@ .c.o : $(CC) $(PKG_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) -c $< -o $*.o clean : @rm -f $(objects) $(archive) Matrix/src/SuiteSparse/CHOLMOD/Partition/0000755000175100001440000000000014576344041017640 5ustar hornikusersMatrix/src/SuiteSparse/CHOLMOD/Partition/cholmod_nesdis.c0000644000175100001440000023202414552026002022765 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Partition/cholmod_nesdis: CHOLMOD nested dissection, using METIS //------------------------------------------------------------------------------ // CHOLMOD/Partition Module. Copyright (C) 2005-2023, University of Florida. // All Rights Reserved. Author: Timothy A. Davis. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // CHOLMOD nested dissection and graph partitioning. // // cholmod_bisect: // // Finds a set of nodes that partitions the graph into two parts. // Compresses the graph first. Requires METIS. // // cholmod_nested_dissection: // // Nested dissection, using its own compression and connected-commponents // algorithms, an external graph partitioner (METIS), and a constrained // minimum degree ordering algorithm (CCOLAMD or CSYMAMD). Typically // gives better orderings than METIS_NodeND (about 5% to 10% fewer // nonzeros in L). // // cholmod_collapse_septree: // // Prune the separator tree returned by cholmod_nested_dissection. // // This file contains several routines private to this file: // // partition compress and partition a graph // clear_flag clear Common->Flag, but do not modify negative entries // find_components find the connected components of a graph // // Supports any xtype (pattern, real, complex, or zomplex) and any dtype. #include "cholmod_internal.h" #ifndef NPARTITION //------------------------------------------------------------------------------ // partition //------------------------------------------------------------------------------ // Find a set of nodes that partition a graph. The graph must be symmetric // with no diagonal entries. To compress the graph first, compress is TRUE // and on input Hash [j] holds the hash key for node j, which must be in the // range 0 to csize-1. The input graph (Cp, Ci) is destroyed. Cew is all 1's // on input and output. Cnw [j] > 0 is the initial weight of node j. On // output, Cnw [i] = 0 if node i is absorbed into j and the original weight // Cnw [i] is added to Cnw [j]. If compress is FALSE, the graph is not // compressed and Cnw and Hash are unmodified. The partition itself is held in // the output array Part of size n. Part [j] is 0, 1, or 2, depending on // whether node j is in the left part of the graph, the right part, or the // separator, respectively. Note that the input graph need not be connected, // and the output subgraphs (the three parts) may also be unconnected. // // Returns the size of the separator, in terms of the sum of the weights of // the nodes. It is guaranteed to be between 1 and the total weight of all // the nodes. If it is of size less than the total weight, then both the left // and right parts are guaranteed to be non-empty (this guarantee depends on // cholmod_metis_bisector). static int64_t partition // size of separator or -1 if failure ( // inputs, not modified on output #ifndef NDEBUG Int csize, // upper bound on # of edges in the graph; // csize >= MAX (n, nnz(C)) must hold. #endif int compress, // if TRUE the compress the graph first // input/output Int Hash [ ], // Hash [i] = hash >= 0 is the hash function for node // i on input. On output, Hash [i] = FLIP (j) if node // i is absorbed into j. Hash [i] >= 0 if i has not // been absorbed. // input graph, compressed graph of cn nodes on output cholmod_sparse *C, // input/output Int Cnw [ ], // size n. Cnw [j] > 0 is the weight of node j on // input. On output, if node i is absorbed into // node j, then Cnw [i] = 0 and the original weight of // node i is added to Cnw [j]. The sum of Cnw [0..n-1] // is not modified. // workspace Int Cew [ ], // size csize, all 1's on input and output // more workspace, undefined on input and output Int Cmap [ ], // size n // output Int Part [ ], // size n, Part [j] = 0, 1, or 2. cholmod_common *Common ) { Int n, hash, head, i, j, k, p, pend, ilen, ilast, pi, piend, jlen, ok, cn, csep, pdest, nodes_pruned, nz, total_weight, jscattered ; Int *Cp, *Ci, *Next, *Hhead ; #ifndef NDEBUG Int cnt, pruned ; double work = 0, goodwork = 0 ; #endif //-------------------------------------------------------------------------- // quick return for small or empty graphs //-------------------------------------------------------------------------- n = C->nrow ; Cp = C->p ; Ci = C->i ; nz = Cp [n] ; PRINT2 (("Partition start, n "ID" nz "ID"\n", n, nz)) ; total_weight = 0 ; for (j = 0 ; j < n ; j++) { ASSERT (Cnw [j] > 0) ; total_weight += Cnw [j] ; } if (n <= 2) { // very small graph for (j = 0 ; j < n ; j++) { Part [j] = 2 ; } return (total_weight) ; } else if (nz <= 0) { // no edges, this is easy PRINT2 (("diagonal matrix\n")) ; k = n/2 ; for (j = 0 ; j < k ; j++) { Part [j] = 0 ; } for ( ; j < n ; j++) { Part [j] = 1 ; } // ensure the separator is not empty (required by nested dissection) Part [n-1] = 2 ; return (Cnw [n-1]) ; } #ifndef NDEBUG ASSERT (n > 1 && nz > 0) ; PRINT2 (("original graph:\n")) ; for (j = 0 ; j < n ; j++) { PRINT2 ((""ID": ", j)) ; for (p = Cp [j] ; p < Cp [j+1] ; p++) { i = Ci [p] ; PRINT3 ((""ID" ", i)) ; ASSERT (i >= 0 && i < n && i != j) ; } PRINT2 (("hash: "ID"\n", Hash [j])) ; } DEBUG (for (p = 0 ; p < csize ; p++) ASSERT (Cew [p] == 1)) ; #endif nodes_pruned = 0 ; if (compress) { //---------------------------------------------------------------------- // get workspace //---------------------------------------------------------------------- Next = Part ; // use Part as workspace for Next [ Hhead = Cew ; // use Cew as workspace for Hhead [ //---------------------------------------------------------------------- // create the hash buckets //---------------------------------------------------------------------- for (j = 0 ; j < n ; j++) { // get the hash key for node j hash = Hash [j] ; ASSERT (hash >= 0 && hash < csize) ; head = Hhead [hash] ; if (head > EMPTY) { // hash bucket for this hash key is empty. head = EMPTY ; } else { // hash bucket for this hash key is not empty. get old head head = FLIP (head) ; ASSERT (head >= 0 && head < n) ; } // node j becomes the new head of the hash bucket. FLIP it so that // we can tell the difference between an empty or non-empty hash // bucket. Hhead [hash] = FLIP (j) ; Next [j] = head ; ASSERT (head >= EMPTY && head < n) ; } #ifndef NDEBUG for (cnt = 0, k = 0 ; k < n ; k++) { ASSERT (Hash [k] >= 0 && Hash [k] < csize) ; // k is alive hash = Hash [k] ; ASSERT (hash >= 0 && hash < csize) ; head = Hhead [hash] ; ASSERT (head < EMPTY) ; // hash bucket not empty j = FLIP (head) ; ASSERT (j >= 0 && j < n) ; if (j == k) { PRINT2 (("hash "ID": ", hash)) ; for ( ; j != EMPTY ; j = Next [j]) { PRINT3 ((" "ID"", j)) ; ASSERT (j >= 0 && j < n) ; ASSERT (Hash [j] == hash) ; cnt++ ; ASSERT (cnt <= n) ; } PRINT2 (("\n")) ; } } ASSERT (cnt == n) ; #endif //---------------------------------------------------------------------- // scan the non-empty hash buckets for indistinguishable nodes //---------------------------------------------------------------------- // If there are no hash collisions and no compression occurs, this takes // O(n) time. If no hash collisions, but some nodes are removed, this // takes time O(n+e) where e is the sum of the degress of the nodes // that are removed. Even with many hash collisions (a rare case), // this algorithm has never been observed to perform more than nnz(A) // useless work. // // Cmap is used as workspace to mark nodes of the graph, [ // for comparing the nonzero patterns of two nodes i and j. #define Cmap_MARK(i) Cmap [i] = j #define Cmap_MARKED(i) (Cmap [i] == j) for (i = 0 ; i < n ; i++) { Cmap [i] = EMPTY ; } for (k = 0 ; k < n ; k++) { hash = Hash [k] ; ASSERT (hash >= FLIP (n-1) && hash < csize) ; if (hash < 0) { // node k has already been absorbed into some other node ASSERT (FLIP (Hash [k]) >= 0 && FLIP (Hash [k] < n)) ; continue ; } head = Hhead [hash] ; ASSERT (head < EMPTY || head == 1) ; if (head == 1) { // hash bucket is already empty continue ; } PRINT2 (("\n--------------------hash "ID":\n", hash)) ; for (j = FLIP (head) ; j != EMPTY && Next[j] > EMPTY ; j = Next [j]) { // compare j with all nodes i following it in hash bucket ASSERT (j >= 0 && j < n && Hash [j] == hash) ; p = Cp [j] ; pend = Cp [j+1] ; jlen = pend - p ; jscattered = FALSE ; DEBUG (for (i = 0 ; i < n ; i++) ASSERT (!Cmap_MARKED (i))) ; DEBUG (pruned = FALSE) ; ilast = j ; for (i = Next [j] ; i != EMPTY ; i = Next [i]) { ASSERT (i >= 0 && i < n && Hash [i] == hash && i != j) ; pi = Cp [i] ; piend = Cp [i+1] ; ilen = piend - pi ; DEBUG (work++) ; if (ilen != jlen) { // i and j have different degrees ilast = i ; continue ; } // scatter the pattern of node j, if not already if (!jscattered) { Cmap_MARK (j) ; for ( ; p < pend ; p++) { Cmap_MARK (Ci [p]) ; } jscattered = TRUE ; DEBUG (work += jlen) ; } for (ok = Cmap_MARKED (i) ; ok && pi < piend ; pi++) { ok = Cmap_MARKED (Ci [pi]) ; DEBUG (work++) ; } if (ok) { // found it. kill node i and merge it into j PRINT2 (("found "ID" absorbed into "ID"\n", i, j)) ; Hash [i] = FLIP (j) ; Cnw [j] += Cnw [i] ; Cnw [i] = 0 ; ASSERT (ilast != i && ilast >= 0 && ilast < n) ; Next [ilast] = Next [i] ; // delete i from bucket nodes_pruned++ ; DEBUG (goodwork += (ilen+1)) ; DEBUG (pruned = TRUE) ; } else { // i and j are different ilast = i ; } } DEBUG (if (pruned) goodwork += jlen) ; } // empty the hash bucket, restoring Cew Hhead [hash] = 1 ; } DEBUG (if (((work - goodwork) / (double) nz) > 0.20) PRINT0 (( "work %12g good %12g nz %12g (wasted work/nz: %6.2f )\n", work, goodwork, (double) nz, (work - goodwork) / ((double) nz)))) ; // All hash buckets now empty. Cmap no longer needed as workspace. ] // Cew no longer needed as Hhead; Cew is now restored to all ones. ] // Part no longer needed as workspace for Next. ] } // Edge weights are all one, node weights reflect node absorption DEBUG (for (p = 0 ; p < csize ; p++) ASSERT (Cew [p] == 1)) ; DEBUG (for (cnt = 0, j = 0 ; j < n ; j++) cnt += Cnw [j]) ; ASSERT (cnt == total_weight) ; //-------------------------------------------------------------------------- // compress and partition the graph //-------------------------------------------------------------------------- if (nodes_pruned == 0) { //---------------------------------------------------------------------- // no pruning done at all. Do not create the compressed graph //---------------------------------------------------------------------- // FUTURE WORK: could call CHACO, SCOTCH, ... here too csep = CHOLMOD(metis_bisector) (C, Cnw, Cew, Part, Common) ; } else if (nodes_pruned == n-1) { //---------------------------------------------------------------------- // only one node left. This is a dense graph //---------------------------------------------------------------------- PRINT2 (("completely dense graph\n")) ; csep = total_weight ; for (j = 0 ; j < n ; j++) { Part [j] = 2 ; } } else { //---------------------------------------------------------------------- // compress the graph and partition the compressed graph //---------------------------------------------------------------------- //---------------------------------------------------------------------- // create the map from the uncompressed graph to the compressed graph //---------------------------------------------------------------------- // Cmap [j] = k if node j is alive and the kth node of compressed graph. // The mapping is done monotonically (that is, k <= j) to simplify the // uncompression later on. Cmap [j] = EMPTY if node j is dead. for (j = 0 ; j < n ; j++) { Cmap [j] = EMPTY ; } k = 0 ; for (j = 0 ; j < n ; j++) { if (Cnw [j] > 0) { ASSERT (k <= j) ; Cmap [j] = k++ ; } } cn = k ; // # of nodes in compressed graph PRINT2 (("compressed graph from "ID" to "ID" nodes\n", n, cn)) ; ASSERT (cn > 1 && cn == n - nodes_pruned) ; //---------------------------------------------------------------------- // create the compressed graph //---------------------------------------------------------------------- k = 0 ; pdest = 0 ; for (j = 0 ; j < n ; j++) { if (Cnw [j] > 0) { // node j in the full graph is node k in the compressed graph ASSERT (k <= j && Cmap [j] == k) ; p = Cp [j] ; pend = Cp [j+1] ; Cp [k] = pdest ; Cnw [k] = Cnw [j] ; for ( ; p < pend ; p++) { // prune dead nodes, and remap to new node numbering i = Ci [p] ; ASSERT (i >= 0 && i < n && i != j) ; i = Cmap [i] ; ASSERT (i >= EMPTY && i < cn && i != k) ; if (i > EMPTY) { ASSERT (pdest <= p) ; Ci [pdest++] = i ; } } k++ ; } } Cp [cn] = pdest ; C->nrow = cn ; C->ncol = cn ; // affects mem stats unless restored when C free'd #ifndef NDEBUG PRINT2 (("pruned graph ("ID"/"ID") nodes, ("ID"/"ID") edges\n", cn, n, pdest, nz)) ; PRINT2 (("compressed graph:\n")) ; for (cnt = 0, j = 0 ; j < cn ; j++) { PRINT2 ((""ID": ", j)) ; for (p = Cp [j] ; p < Cp [j+1] ; p++) { i = Ci [p] ; PRINT3 ((""ID" ", i)) ; ASSERT (i >= 0 && i < cn && i != j) ; } PRINT2 (("weight: "ID"\n", Cnw [j])) ; ASSERT (Cnw [j] > 0) ; cnt += Cnw [j] ; } ASSERT (cnt == total_weight) ; for (j = 0 ; j < n ; j++) PRINT2 (("Cmap ["ID"] = "ID"\n", j, Cmap[j])); ASSERT (k == cn) ; #endif //---------------------------------------------------------------------- // find the separator of the compressed graph //---------------------------------------------------------------------- // FUTURE WORK: could call CHACO, SCOTCH, ... here too csep = CHOLMOD(metis_bisector) (C, Cnw, Cew, Part, Common) ; if (csep < 0) { // failed return (-1) ; } PRINT2 (("Part: ")) ; DEBUG (for (j = 0 ; j < cn ; j++) PRINT2 ((""ID" ", Part [j]))) ; PRINT2 (("\n")) ; // Cp and Ci no longer needed //---------------------------------------------------------------------- // find the separator of the uncompressed graph //---------------------------------------------------------------------- // expand the separator to live nodes in the uncompressed graph for (j = n-1 ; j >= 0 ; j--) { // do this in reverse order so that Cnw can be expanded in place k = Cmap [j] ; ASSERT (k >= EMPTY && k < n) ; if (k > EMPTY) { // node k in compressed graph and is node j in full graph ASSERT (k <= j) ; ASSERT (Hash [j] >= EMPTY) ; Part [j] = Part [k] ; Cnw [j] = Cnw [k] ; } else { // node j is a dead node Cnw [j] = 0 ; DEBUG (Part [j] = EMPTY) ; ASSERT (Hash [j] < EMPTY) ; } } // find the components for the dead nodes for (i = 0 ; i < n ; i++) { if (Hash [i] < EMPTY) { // node i has been absorbed into node j j = FLIP (Hash [i]) ; ASSERT (Part [i] == EMPTY && j >= 0 && j < n && Cnw [i] == 0) ; Part [i] = Part [j] ; } ASSERT (Part [i] >= 0 && Part [i] <= 2) ; } #ifndef NDEBUG PRINT2 (("Part: ")) ; for (cnt = 0, j = 0 ; j < n ; j++) { ASSERT (Part [j] != EMPTY) ; PRINT2 ((""ID" ", Part [j])) ; if (Part [j] == 2) cnt += Cnw [j] ; } PRINT2 (("\n")) ; PRINT2 (("csep "ID" "ID"\n", cnt, csep)) ; ASSERT (cnt == csep) ; for (cnt = 0, j = 0 ; j < n ; j++) cnt += Cnw [j] ; ASSERT (cnt == total_weight) ; #endif } //-------------------------------------------------------------------------- // return the separator (or -1 if error) //-------------------------------------------------------------------------- PRINT2 (("Partition done, n "ID" csep "ID"\n", n, csep)) ; return (csep) ; } //------------------------------------------------------------------------------ // clear_flag //------------------------------------------------------------------------------ // A node j has been removed from the graph if Flag [j] < EMPTY. // If Flag [j] >= EMPTY && Flag [j] < mark, then node j is alive but unmarked. // Flag [j] == mark means that node j is alive and marked. Incrementing mark // means that all nodes are either (still) dead, or live but unmarked. // // If Map is NULL, then on output, Common->mark < Common->Flag [i] for all i // from 0 to Common->nrow. This is the same output condition as // cholmod_clear_flag, except that this routine maintains the Flag [i] < EMPTY // condition as well, if that condition was true on input. // // If Map is non-NULL, then on output, Common->mark < Common->Flag [i] for all // i in the set Map [0..cn-1]. // // workspace: Flag (nrow) static int64_t clear_flag (Int *Map, Int cn, cholmod_common *Common) { Int nrow, i ; Int *Flag ; PRINT2 (("old mark %ld\n", Common->mark)) ; Common->mark++ ; PRINT2 (("new mark %ld\n", Common->mark)) ; if (Common->mark <= 0) { nrow = Common->nrow ; Flag = Common->Flag ; if (Map != NULL) { for (i = 0 ; i < cn ; i++) { // if Flag [Map [i]] < EMPTY, leave it alone if (Flag [Map [i]] >= EMPTY) { Flag [Map [i]] = EMPTY ; } } // now Flag [Map [i]] <= EMPTY for all i } else { for (i = 0 ; i < nrow ; i++) { // if Flag [i] < EMPTY, leave it alone if (Flag [i] >= EMPTY) { Flag [i] = EMPTY ; } } // now Flag [i] <= EMPTY for all i } Common->mark = 0 ; } return (Common->mark) ; } //------------------------------------------------------------------------------ // find_components //------------------------------------------------------------------------------ // Find all connected components of the current subgraph C. The subgraph C // consists of the nodes of B that appear in the set Map [0..cn-1]. If Map // is NULL, then it is assumed to be the identity mapping // (Map [0..cn-1] = 0..cn-1). // // A node j does not appear in B if it has been ordered (Flag [j] < EMPTY, // which means that j has been ordered and is "deleted" from B). // // If the size of a component is large, it is placed on the component stack, // Cstack. Otherwise, its nodes are ordered and it is not placed on the Cstack. // // A component S is defined by a "representative node" (repnode for short) // called the snode, which is one of the nodes in the subgraph. Likewise, the // subgraph C is defined by its repnode, called cnode. // // If Part is not NULL on input, then Part [i] determines how the components // are placed on the stack. Components containing nodes i with Part [i] == 0 // are placed first, followed by components with Part [i] == 1. // // The first node placed in each of the two parts is flipped when placed in // the Cstack. This allows the components of the two parts to be found simply // by traversing the Cstack. // // workspace: Flag (nrow) static void find_components ( // inputs, not modified on output cholmod_sparse *B, Int Map [ ], // size n, only Map [0..cn-1] used Int cn, // # of nodes in C Int cnode, // root node of component C, or EMPTY if C is the // entire graph B Int Part [ ], // size cn, optional // input/output Int Bnz [ ], // size n. Bnz [j] = # nonzeros in column j of B. // Reduce since B is pruned of dead nodes. Int CParent [ ], // CParent [i] = j if component with repnode j is // the parent of the component with repnode i. // CParent [i] = EMPTY if the component with // repnode i is a root of the separator tree. // CParent [i] is -2 if i is not a repnode. Int Cstack [ ], // component stack for nested dissection Int *top, // Cstack [0..top] contains root nodes of the // the components currently in the stack // workspace, undefined on input and output: Int Queue [ ], // size n, for breadth-first search cholmod_common *Common ) { Int mark, cj, j, sj, sn, p, i, snode, pstart, pdest, pend, nd_components, part, first, save_mark ; #ifndef NDEBUG Int n ; #endif Int *Bp, *Bi, *Flag ; //-------------------------------------------------------------------------- // get workspace //-------------------------------------------------------------------------- PRINT2 (("find components: cn %d\n", cn)) ; Flag = Common->Flag ; // size n // force initialization of Flag [Map [0..cn-1]] save_mark = Common->mark ; // save the current mark Common->mark = EMPTY ; // clear Flag; preserve Flag [Map [i]] if Flag [Map [i]] already < EMPTY // this takes O(cn) time mark = clear_flag (Map, cn, Common) ; Bp = B->p ; Bi = B->i ; #ifndef NDEBUG n = B->nrow ; #endif ASSERT (cnode >= EMPTY && cnode < n) ; ASSERT (IMPLIES (cnode >= 0, Flag [cnode] < EMPTY)) ; // get ordering parameters nd_components = Common->method [Common->current].nd_components ; //-------------------------------------------------------------------------- // find the connected components of C via a breadth-first search //-------------------------------------------------------------------------- part = (Part == NULL) ? 0 : 1 ; // examine each part (part 1 and then part 0) for (part = (Part == NULL) ? 0 : 1 ; part >= 0 ; part--) { // first is TRUE for the first connected component in each part first = TRUE ; // find all connected components in the current part for (cj = 0 ; cj < cn ; cj++) { // get node snode, which is node cj of C. It might already be in // the separator of C (and thus ordered, with Flag [snode] < EMPTY) snode = (Map == NULL) ? (cj) : (Map [cj]) ; ASSERT (snode >= 0 && snode < n) ; if (Flag [snode] >= EMPTY && Flag [snode] < mark && ((Part == NULL) || Part [cj] == part)) { //-------------------------------------------------------------- // find new connected component S //-------------------------------------------------------------- // node snode is the repnode of a connected component S, the // parent of which is cnode, the repnode of C. If cnode is // EMPTY then C is the original graph B. PRINT2 (("----------:::snode "ID" cnode "ID"\n", snode, cnode)); ASSERT (CParent [snode] == -2) ; if (first || nd_components) { // If this is the first node in this part, then it becomes // the repnode of all components in this part, and all // components in this part form a single node in the // separator tree. If nd_components is TRUE, then all // connected components form their own node in the // separator tree. CParent [snode] = cnode ; } // place j in the queue and mark it Queue [0] = snode ; Flag [snode] = mark ; sn = 1 ; // breadth-first traversal, starting at node j for (sj = 0 ; sj < sn ; sj++) { // get node j from head of Queue and traverse its edges j = Queue [sj] ; PRINT2 ((" j: "ID"\n", j)) ; ASSERT (j >= 0 && j < n) ; ASSERT (Flag [j] == mark) ; pstart = Bp [j] ; pdest = pstart ; pend = pstart + Bnz [j] ; for (p = pstart ; p < pend ; p++) { i = Bi [p] ; if (i != j && Flag [i] >= EMPTY) { // node is still in the graph Bi [pdest++] = i ; if (Flag [i] < mark) { // node i is in this component S, and unflagged // (first time node i has been seen in this BFS) // place node i in the queue and mark it Queue [sn++] = i ; Flag [i] = mark ; } } } // edges to dead nodes have been removed Bnz [j] = pdest - pstart ; } //-------------------------------------------------------------- // order S if it is small; place it on Cstack otherwise //-------------------------------------------------------------- PRINT2 (("sn "ID"\n", sn)) ; // place the new component on the Cstack. Flip the node if // is the first connected component of the current part, // or if all components are treated as their own node in // the separator tree. Cstack [++(*top)] = (first || nd_components) ? FLIP (snode) : snode ; first = FALSE ; } } } // restore the flag (normally taking O(1) time except for Int overflow) Common->mark = save_mark++ ; clear_flag (NULL, 0, Common) ; DEBUG (for (i = 0 ; i < n ; i++) ASSERT (Flag [i] < Common->mark)) ; } #endif //------------------------------------------------------------------------------ // cholmod_bisect //------------------------------------------------------------------------------ // Finds a node bisector of A, A*A', A(:,f)*A(:,f)'. // // workspace: Flag (nrow), // Iwork (nrow if symmetric, max (nrow,ncol) if unsymmetric). // Allocates a temporary matrix B=A*A' or B=A, // and O(nnz(A)) temporary memory space. int64_t CHOLMOD(bisect) // returns # of nodes in separator ( // input: cholmod_sparse *A, // matrix to bisect Int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int compress, // if TRUE, compress the graph first // output: Int *Partition, // size A->nrow. Node i is in the left graph if // Partition [i] = 0, the right graph if 1, and in the // separator if 2. cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- #ifndef NPARTITION Int *Bp, *Bi, *Hash, *Cmap, *Bnw, *Bew, *Iwork ; cholmod_sparse *B ; UInt hash ; Int j, n, bnz, sepsize, p, pend ; RETURN_IF_NULL_COMMON (EMPTY) ; RETURN_IF_NULL (A, EMPTY) ; RETURN_IF_NULL (Partition, EMPTY) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, EMPTY) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // quick return //-------------------------------------------------------------------------- n = A->nrow ; if (n == 0) { return (0) ; } //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- // s = nrow + MAX (nrow, ncol) int ok = TRUE ; size_t s = CHOLMOD(add_size_t) (A->nrow, MAX (A->nrow, A->ncol), &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (EMPTY) ; } CHOLMOD(allocate_work) (A->nrow, s, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (EMPTY) ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; Iwork = Common->Iwork ; Hash = Iwork ; // size n Cmap = Iwork + n ; // size n //-------------------------------------------------------------------------- // convert the matrix to adjacency list form //-------------------------------------------------------------------------- // The input graph to must be symmetric, with no diagonal entries // present. The columns need not be sorted. // B = A, A*A', or A(:,f)*A(:,f)', upper and lower parts present if (A->stype) { // Add the upper/lower part to a symmetric lower/upper matrix by // converting to unsymmetric mode // workspace: Iwork (nrow) B = CHOLMOD(copy) (A, 0, -1, Common) ; } else { // B = A*A' or A(:,f)*A(:,f)', no diagonal // workspace: Flag (nrow), Iwork (max (nrow,ncol)) B = CHOLMOD(aat) (A, fset, fsize, -1, Common) ; } if (Common->status < CHOLMOD_OK) { return (EMPTY) ; } Bp = B->p ; Bi = B->i ; bnz = Bp [n] ; ASSERT ((Int) (B->nrow) == n && (Int) (B->ncol) == n) ; // B does not include the diagonal, and both upper and lower parts. // Common->anz includes the diagonal, and just the lower part of B Common->anz = bnz / 2 + ((double) n) ; // Bew should be at least size n for the hash function to work well // this cannot cause overflow, because the matrix is already created size_t csize = MAX (((size_t) n) + 1, (size_t) bnz) ; // create the graph using Flag as workspace for node weights [ Bnw = Common->Flag ; // size n workspace // compute hash for each node if compression requested if (compress) { for (j = 0 ; j < n ; j++) { hash = j ; pend = Bp [j+1] ; for (p = Bp [j] ; p < pend ; p++) { hash += Bi [p] ; ASSERT (Bi [p] != j) ; } // finalize the hash key for node j hash %= csize ; Hash [j] = (Int) hash ; ASSERT (Hash [j] >= 0 && Hash [j] < csize) ; } } // allocate edge weights Bew = CHOLMOD(malloc) (csize, sizeof (Int), Common) ; if (Common->status < CHOLMOD_OK) { // out of memory CHOLMOD(free_sparse) (&B, Common) ; CHOLMOD(free) (csize, sizeof (Int), Bew, Common) ; return (EMPTY) ; } // graph has unit node and edge weights for (j = 0 ; j < n ; j++) { Bnw [j] = 1 ; } for (s = 0 ; s < csize ; s++) { Bew [s] = 1 ; } //-------------------------------------------------------------------------- // compress and partition the graph //-------------------------------------------------------------------------- sepsize = partition ( #ifndef NDEBUG csize, #endif compress, Hash, B, Bnw, Bew, Cmap, Partition, Common) ; // contents of Bp, Bi, Bnw, and Bew no longer needed ] // If partition fails, free the workspace below and return sepsize < 0 //-------------------------------------------------------------------------- // free workspace //-------------------------------------------------------------------------- B->ncol = n ; // restore size for memory usage statistics CHOLMOD(free_sparse) (&B, Common) ; Common->mark = EMPTY ; CLEAR_FLAG (Common) ; ASSERT (check_flag (Common)) ; CHOLMOD(free) (csize, sizeof (Int), Bew, Common) ; return (sepsize) ; #else Common->status = CHOLMOD_NOT_INSTALLED ; return (EMPTY) ; #endif } //------------------------------------------------------------------------------ // cholmod_nested_dissection //------------------------------------------------------------------------------ // This method uses a node bisector, applied recursively (but using a // non-recursive algorithm). Once the graph is partitioned, it calls a // constrained min degree code (CAMD or CSYMAMD for A+A', and CCOLAMD for A*A') // to order all the nodes in the graph - but obeying the constraints determined // by the separators. This routine is similar to METIS_NodeND, except for how // it treats the leaf nodes. METIS_NodeND orders the leaves of the separator // tree with MMD, ignoring the rest of the matrix when ordering a single leaf. // This routine orders the whole matrix with CSYMAMD or CCOLAMD, all at once, // when the graph partitioning is done. // // This function also returns a postorderd separator tree (CParent), and a // mapping of nodes in the graph to nodes in the separator tree (Cmember). // // workspace: Flag (nrow), Head (nrow+1), Iwork (4*nrow + (ncol if unsymmetric)) // Allocates a temporary matrix B=A*A' or B=A, // and O(nnz(A)) temporary memory space. // Allocates an additional 3*n*sizeof(Int) temporary workspace int64_t CHOLMOD(nested_dissection) // returns # of components, or -1 if error ( // input: cholmod_sparse *A, // matrix to order Int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset // output: Int *Perm, // size A->nrow, output permutation Int *CParent, // size A->nrow. On output, CParent [c] is the parent // of component c, or EMPTY if c is a root, and where // c is in the range 0 to # of components minus 1 Int *Cmember, // size A->nrow. Cmember [j] = c if node j of A is // in component c cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- #ifndef NPARTITION double prune_dense, nd_oksep ; Int *Bp, *Bi, *Bnz, *Cstack, *Imap, *Map, *Flag, *Head, *Next, *Bnw, *Iwork, *Ipost, *NewParent, *Hash, *Cmap, *Cp, *Ci, *Cew, *Cnw, *Part, *Post, *Work3n ; UInt hash ; Int n, bnz, top, i, j, k, cnode, cdense, p, cj, cn, ci, cnz, mark, c, sepsize, parent, ncomponents, threshold, ndense, pstart, pdest, pend, nd_compress, nd_camd, csize, jnext, nd_small, total_weight, nchild, child = EMPTY ; cholmod_sparse *B, *C ; DEBUG (Int cnt) ; RETURN_IF_NULL_COMMON (EMPTY) ; RETURN_IF_NULL (A, EMPTY) ; RETURN_IF_NULL (Perm, EMPTY) ; RETURN_IF_NULL (CParent, EMPTY) ; RETURN_IF_NULL (Cmember, EMPTY) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, EMPTY) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // quick return //-------------------------------------------------------------------------- n = A->nrow ; if (n == 0) { return (1) ; } //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- // get ordering parameters prune_dense = Common->method [Common->current].prune_dense ; nd_compress = Common->method [Common->current].nd_compress ; nd_oksep = Common->method [Common->current].nd_oksep ; nd_oksep = MAX (0, nd_oksep) ; nd_oksep = MIN (1, nd_oksep) ; nd_camd = Common->method [Common->current].nd_camd ; nd_small = Common->method [Common->current].nd_small ; nd_small = MAX (4, nd_small) ; PRINT0 (("nd_components %d nd_small %d nd_oksep %g\n", Common->method [Common->current].nd_components, nd_small, nd_oksep)) ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- // s = 4*nrow + uncol size_t uncol = (A->stype == 0) ? A->ncol : 0 ; int ok = TRUE ; size_t s = CHOLMOD(mult_size_t) (A->nrow, 4, &ok) ; s = CHOLMOD(add_size_t) (s, uncol, &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (EMPTY) ; } CHOLMOD(allocate_work) (A->nrow, s, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (EMPTY) ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; //-------------------------------------------------------------------------- // get workspace //-------------------------------------------------------------------------- Flag = Common->Flag ; // size n Head = Common->Head ; // size n+1, all equal to -1 Iwork = Common->Iwork ; Imap = Iwork ; // size n, same as Queue in find_components Map = Iwork + n ; // size n Bnz = Iwork + 2*((size_t) n) ; // size n Hash = Iwork + 3*((size_t) n) ; // size n Work3n = CHOLMOD(malloc) (n, 3*sizeof (Int), Common) ; Part = Work3n ; // size n Bnw = Part + n ; // size n Cnw = Bnw + n ; // size n Cstack = Perm ; // size n, use Perm as workspace for Cstack [ Cmap = Cmember ; // size n, use Cmember as workspace [ if (Common->status < CHOLMOD_OK) { return (EMPTY) ; } //-------------------------------------------------------------------------- // convert B to symmetric form with both upper/lower parts present //-------------------------------------------------------------------------- // B = A+A', A*A', or A(:,f)*A(:,f)', upper and lower parts present if (A->stype) { // Add the upper/lower part to a symmetric lower/upper matrix by // converting to unsymmetric mode // workspace: Iwork (nrow) B = CHOLMOD(copy) (A, 0, -1, Common) ; } else { // B = A*A' or A(:,f)*A(:,f)', no diagonal // workspace: Flag (nrow), Iwork (max (nrow,ncol)) B = CHOLMOD(aat) (A, fset, fsize, -1, Common) ; } if (Common->status < CHOLMOD_OK) { CHOLMOD(free) (3*n, sizeof (Int), Work3n, Common) ; return (EMPTY) ; } Bp = B->p ; Bi = B->i ; bnz = CHOLMOD(nnz) (B, Common) ; ASSERT ((Int) (B->nrow) == n && (Int) (B->ncol) == n) ; csize = MAX (n, bnz) ; ASSERT (CHOLMOD(dump_sparse) (B, "B for nd:", Common) >= 0) ; //-------------------------------------------------------------------------- // initializations //-------------------------------------------------------------------------- // all nodes start out unmarked and unordered (Type 4, see below) Common->mark = EMPTY ; CLEAR_FLAG (Common) ; ASSERT (check_flag (Common)) ; ASSERT (Flag == Common->Flag) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; for (j = 0 ; j < n ; j++) { CParent [j] = -2 ; } // prune dense nodes from B if (isnan (prune_dense) || prune_dense < 0) { // only remove completely dense nodes threshold = n-2 ; } else { // remove nodes with degree more than threshold threshold = (Int) (MAX (16, prune_dense * sqrt ((double) (n)))) ; threshold = MIN (n, threshold) ; } ndense = 0 ; cnode = EMPTY ; cdense = EMPTY ; for (j = 0 ; j < n ; j++) { Bnz [j] = Bp [j+1] - Bp [j] ; if (Bnz [j] > threshold) { // node j is dense, prune it from B PRINT2 (("j is dense %d\n", j)) ; ndense++ ; if (cnode == EMPTY) { // first dense node found becomes root of this component, // which contains all of the dense nodes found here cdense = j ; cnode = j ; CParent [cnode] = EMPTY ; } Flag [j] = FLIP (cnode) ; } } B->packed = FALSE ; ASSERT (B->nz == NULL) ; if (ndense == n) { // all nodes removed: Perm is identity, all nodes in component zero, // and the separator tree has just one node. PRINT2 (("all nodes are dense\n")) ; for (k = 0 ; k < n ; k++) { Perm [k] = k ; Cmember [k] = 0 ; } CParent [0] = EMPTY ; CHOLMOD(free_sparse) (&B, Common) ; CHOLMOD(free) (3*n, sizeof (Int), Work3n, Common) ; Common->mark = EMPTY ; CLEAR_FLAG (Common) ; ASSERT (check_flag (Common)) ; return (1) ; } // Cp and Ci are workspace to construct the subgraphs to partition C = CHOLMOD(allocate_sparse) (n, n, csize, FALSE, TRUE, 0, CHOLMOD_PATTERN, Common) ; Cew = CHOLMOD(malloc) (csize, sizeof (Int), Common) ; if (Common->status < CHOLMOD_OK) { // out of memory CHOLMOD(free_sparse) (&C, Common) ; CHOLMOD(free_sparse) (&B, Common) ; CHOLMOD(free) (csize, sizeof (Int), Cew, Common) ; CHOLMOD(free) (3*n, sizeof (Int), Work3n, Common) ; Common->mark = EMPTY ; CLEAR_FLAG (Common) ; ASSERT (check_flag (Common)) ; PRINT2 (("out of memory for C, etc\n")) ; return (EMPTY) ; } Cp = C->p ; Ci = C->i ; // create initial unit node and edge weights for (j = 0 ; j < n ; j++) { Bnw [j] = 1 ; } for (p = 0 ; p < csize ; p++) { Cew [p] = 1 ; } // push the initial connnected components of B onto the Cstack top = EMPTY ; // Cstack is empty // workspace: Flag (nrow), Iwork (nrow); use Imap as workspace for Queue [ find_components (B, NULL, n, cnode, NULL, Bnz, CParent, Cstack, &top, Imap, Common) ; // done using Imap as workspace for Queue ] // Nodes can now be of Type 0, 1, 2, or 4 (see definition below) //-------------------------------------------------------------------------- // while Cstack is not empty, do: //-------------------------------------------------------------------------- while (top >= 0) { // clear the Flag array, but do not modify negative entries in Flag mark = clear_flag (NULL, 0, Common) ; DEBUG (for (i = 0 ; i < n ; i++) Imap [i] = EMPTY) ; //---------------------------------------------------------------------- // get node(s) from the top of the Cstack //---------------------------------------------------------------------- // i is the repnode of its (unordered) connected component. Get // all repnodes for all connected components of a single part. If // each connected component is to be ordered separately (nd_components // is TRUE), then this while loop iterates just once. cnode = EMPTY ; cn = 0 ; while (cnode == EMPTY) { i = Cstack [top--] ; if (i < 0) { // this is the last node in this component i = FLIP (i) ; cnode = i ; } ASSERT (i >= 0 && i < n && Flag [i] >= EMPTY) ; // place i in the queue and mark it Map [cn] = i ; Flag [i] = mark ; Imap [i] = cn ; cn++ ; } ASSERT (cnode != EMPTY) ; // During ordering, there are five kinds of nodes in the graph of B, // based on Flag [j] and CParent [j] for nodes j = 0 to n-1: // // Type 0: If cnode is a repnode of an unordered component, then // CParent [cnode] is in the range EMPTY to n-1 and // Flag [cnode] >= EMPTY. This is a "live" node. // // Type 1: If cnode is a repnode of an ordered separator component, // then Flag [cnode] < EMPTY and FLAG [cnode] = FLIP (cnode). // CParent [cnode] is in the range EMPTY to n-1. cnode is a root of // the separator tree if CParent [cnode] == EMPTY. This node is dead. // // Type 2: If node j isn't a repnode, has not been absorbed via // graph compression into another node, but is in an ordered separator // component, then cnode = FLIP (Flag [j]) gives the repnode of the // component that contains j and CParent [j] is -2. This node is dead. // Note that Flag [j] < EMPTY. // // Type 3: If node i has been absorbed via graph compression into some // other node j = FLIP (Flag [i]) where j is not a repnode. // CParent [j] is -2. Node i may or may not be in an ordered // component. This node is dead. Note that Flag [j] < EMPTY. // // Type 4: If node j is "live" (not in an ordered component, and not // absorbed into any other node), then Flag [j] >= EMPTY. // // Only "live" nodes (of type 0 or 4) are placed in a subgraph to be // partitioned. Node j is alive if Flag [j] >= EMPTY, and dead if // Flag [j] < EMPTY. //---------------------------------------------------------------------- // create the subgraph for this connected component C //---------------------------------------------------------------------- // Do a breadth-first search of the graph starting at cnode. // use Map [0..cn-1] for nodes in the component C [ // use Cnw and Cew for node and edge weights of the resulting subgraph [ // use Cp and Ci for the resulting subgraph [ // use Imap [i] for all nodes i in B that are in the component C [ cnz = 0 ; total_weight = 0 ; for (cj = 0 ; cj < cn ; cj++) { // get node j from the head of the queue; it is node cj of C j = Map [cj] ; ASSERT (Flag [j] == mark) ; Cp [cj] = cnz ; Cnw [cj] = Bnw [j] ; ASSERT (Cnw [cj] >= 0) ; total_weight += Cnw [cj] ; pstart = Bp [j] ; pdest = pstart ; pend = pstart + Bnz [j] ; hash = cj ; for (p = pstart ; p < pend ; p++) { i = Bi [p] ; // prune diagonal entries and dead edges from B if (i != j && Flag [i] >= EMPTY) { // live node i is in the current component Bi [pdest++] = i ; if (Flag [i] != mark) { // First time node i has been seen, it is a new node // of C. place node i in the queue and mark it Map [cn] = i ; Flag [i] = mark ; Imap [i] = cn ; cn++ ; } // place the edge (cj,ci) in the adjacency list of cj ci = Imap [i] ; ASSERT (ci >= 0 && ci < cn && ci != cj && cnz < csize) ; Ci [cnz++] = ci ; hash += ci ; } } // edges to dead nodes have been removed Bnz [j] = pdest - pstart ; // finalize the hash key for column j hash %= csize ; Hash [cj] = (Int) hash ; ASSERT (Hash [cj] >= 0 && Hash [cj] < csize) ; } Cp [cn] = cnz ; C->nrow = cn ; C->ncol = cn ; // affects mem stats unless restored when C free'd // contents of Imap no longer needed ] #ifndef NDEBUG for (cj = 0 ; cj < cn ; cj++) { j = Map [cj] ; PRINT2 (("----------------------------C column cj: "ID" j: "ID"\n", cj, j)) ; ASSERT (j >= 0 && j < n) ; ASSERT (Flag [j] >= EMPTY) ; for (p = Cp [cj] ; p < Cp [cj+1] ; p++) { ci = Ci [p] ; i = Map [ci] ; PRINT3 (("ci: "ID" i: "ID"\n", ci, i)) ; ASSERT (ci != cj && ci >= 0 && ci < cn) ; ASSERT (i != j && i >= 0 && i < n) ; ASSERT (Flag [i] >= EMPTY) ; } } #endif PRINT0 (("consider cn %d nd_small %d ", cn, nd_small)) ; if (cn < nd_small) // could be 'total_weight < nd_small' instead { // place all nodes in the separator PRINT0 ((" too small\n")) ; sepsize = total_weight ; } else { // Cp and Ci now contain the component, with cn nodes and cnz // nonzeros. The mapping of a node cj into node j the main graph // B is given by Map [cj] = j PRINT0 ((" cut\n")) ; //------------------------------------------------------------------ // compress and partition the graph C //------------------------------------------------------------------ // The edge weights Cew [0..csize-1] are all 1's on input to and // output from the partition routine. sepsize = partition ( #ifndef NDEBUG csize, #endif nd_compress, Hash, C, Cnw, Cew, Cmap, Part, Common) ; // contents of Cp and Ci no longer needed ] if (sepsize < 0) { // failed C->ncol = n ; // restore size for memory usage statistics CHOLMOD(free_sparse) (&C, Common) ; CHOLMOD(free_sparse) (&B, Common) ; CHOLMOD(free) (csize, sizeof (Int), Cew, Common) ; CHOLMOD(free) (3*n, sizeof (Int), Work3n, Common) ; Common->mark = EMPTY ; CLEAR_FLAG (Common) ; ASSERT (check_flag (Common)) ; return (EMPTY) ; } //------------------------------------------------------------------ // compress B based on how C was compressed //------------------------------------------------------------------ for (ci = 0 ; ci < cn ; ci++) { if (Hash [ci] < EMPTY) { // ci is dead in C, having been absorbed into cj cj = FLIP (Hash [ci]) ; PRINT2 (("In C, "ID" absorbed into "ID" (wgt now "ID")\n", ci, cj, Cnw [cj])) ; // i is dead in B, having been absorbed into j i = Map [ci] ; j = Map [cj] ; PRINT2 (("In B, "ID" (wgt "ID") => "ID" (wgt "ID")\n", i, Bnw [i], j, Bnw [j], Cnw [cj])) ; // more than one node may be absorbed into j. This is // accounted for in Cnw [cj]. Assign it here rather // than += Bnw [i] Bnw [i] = 0 ; Bnw [j] = Cnw [cj] ; Flag [i] = FLIP (j) ; } } DEBUG (for (cnt = 0, j = 0 ; j < n ; j++) cnt += Bnw [j]) ; ASSERT (cnt == n) ; } // contents of Cnw [0..cn-1] no longer needed ] //---------------------------------------------------------------------- // order the separator, and stack the components when C is split //---------------------------------------------------------------------- // one more component has been found: either the separator of C, // or all of C ASSERT (sepsize >= 0 && sepsize <= total_weight) ; PRINT0 (("sepsize %d tot %d : %8.4f ", sepsize, total_weight, ((double) sepsize) / ((double) total_weight))) ; if (sepsize == total_weight || sepsize == 0 || sepsize > nd_oksep * total_weight) { // Order the nodes in the component. The separator is too large, // or empty. Note that the partition routine cannot return a // sepsize of zero, but it can return a separator consisting of the // whole graph. The "sepsize == 0" test is kept, above, in case the // partition routine changes. In either case, this component // remains unsplit, and becomes a leaf of the separator tree. PRINT2 (("cnode %d sepsize zero or all of graph: "ID"\n", cnode, sepsize)) ; for (cj = 0 ; cj < cn ; cj++) { j = Map [cj] ; Flag [j] = FLIP (cnode) ; PRINT2 ((" node cj: "ID" j: "ID" ordered\n", cj, j)) ; } ASSERT (Flag [cnode] == FLIP (cnode)) ; ASSERT (cnode != EMPTY && Flag [cnode] < EMPTY) ; PRINT0 (("discarded\n")) ; } else { // Order the nodes in the separator of C and find a new repnode // cnode that is in the separator of C. This requires the separator // to be non-empty. PRINT0 (("sepsize not tiny: "ID"\n", sepsize)) ; parent = CParent [cnode] ; ASSERT (parent >= EMPTY && parent < n) ; CParent [cnode] = -2 ; cnode = EMPTY ; for (cj = 0 ; cj < cn ; cj++) { j = Map [cj] ; if (Part [cj] == 2) { // All nodes in the separator become part of a component // whose repnode is cnode PRINT2 (("node cj: "ID" j: "ID" ordered\n", cj, j)) ; if (cnode == EMPTY) { PRINT2(("------------new cnode: cj "ID" j "ID"\n", cj, j)) ; cnode = j ; } Flag [j] = FLIP (cnode) ; } else { PRINT2 ((" node cj: "ID" j: "ID" not ordered\n", cj, j)) ; } } ASSERT (cnode != EMPTY && Flag [cnode] < EMPTY) ; ASSERT (CParent [cnode] == -2) ; CParent [cnode] = parent ; // find the connected components when C is split, and push // them on the Cstack. Use Imap as workspace for Queue. [ // workspace: Flag (nrow) find_components (B, Map, cn, cnode, Part, Bnz, CParent, Cstack, &top, Imap, Common) ; // done using Imap as workspace for Queue ] } // contents of Map [0..cn-1] no longer needed ] } // done using Cmember as workspace for Cmap ] // done using Perm as workspace for Cstack ] //-------------------------------------------------------------------------- // place nodes removed via compression into their proper component //-------------------------------------------------------------------------- // At this point, all nodes are of Type 1, 2, or 3, as defined above. for (i = 0 ; i < n ; i++) { // find the repnode cnode that contains node i j = FLIP (Flag [i]) ; PRINT2 (("\nfind component for "ID", in: "ID"\n", i, j)) ; ASSERT (j >= 0 && j < n) ; DEBUG (cnt = 0) ; while (CParent [j] == -2) { j = FLIP (Flag [j]) ; PRINT2 ((" walk up to "ID" ", j)) ; ASSERT (j >= 0 && j < n) ; PRINT2 ((" CParent "ID"\n", CParent [j])) ; ASSERT (cnt < n) ; DEBUG (cnt++) ; } cnode = j ; ASSERT (cnode >= 0 && cnode < n) ; ASSERT (CParent [cnode] >= EMPTY && CParent [cnode] < n) ; PRINT2 (("i "ID" is in component with cnode "ID"\n", i, cnode)) ; ASSERT (Flag [cnode] == FLIP (cnode)) ; // Mark all nodes along the path from i to cnode as being in the // component whos repnode is cnode. Perform path compression. j = FLIP (Flag [i]) ; Flag [i] = FLIP (cnode) ; DEBUG (cnt = 0) ; while (CParent [j] == -2) { ASSERT (j >= 0 && j < n) ; jnext = FLIP (Flag [j]) ; PRINT2 ((" "ID" walk "ID" set cnode to "ID"\n", i, j, cnode)) ; ASSERT (cnt < n) ; DEBUG (cnt++) ; Flag [j] = FLIP (cnode) ; j = jnext ; } } // At this point, all nodes fall into Types 1 or 2, as defined above. #ifndef NDEBUG for (j = 0 ; j < n ; j++) { PRINT2 (("j %d CParent %d ", j, CParent [j])) ; if (CParent [j] >= EMPTY && CParent [j] < n) { // case 1: j is a repnode of a component cnode = j ; PRINT2 ((" a repnode\n")) ; } else { // case 2: j is not a repnode of a component cnode = FLIP (Flag [j]) ; PRINT2 ((" repnode is %d\n", cnode)) ; ASSERT (cnode >= 0 && cnode < n) ; ASSERT (CParent [cnode] >= EMPTY && CParent [cnode] < n) ; } ASSERT (Flag [cnode] == FLIP (cnode)) ; // case 3 no longer holds } #endif //-------------------------------------------------------------------------- // free workspace //-------------------------------------------------------------------------- C->ncol = n ; // restore size for memory usage statistics CHOLMOD(free_sparse) (&C, Common) ; CHOLMOD(free_sparse) (&B, Common) ; CHOLMOD(free) (csize, sizeof (Int), Cew, Common) ; CHOLMOD(free) (3*n, sizeof (Int), Work3n, Common) ; //-------------------------------------------------------------------------- // handle dense nodes //-------------------------------------------------------------------------- // The separator tree has nodes with either no children or two or more // children - with one exception. There may exist a single root node with // exactly one child, which holds the dense rows/columns of the matrix. // Delete this node if it exists. if (ndense > 0) { ASSERT (CParent [cdense] == EMPTY) ; // cdense has no parent // find the children of cdense nchild = 0 ; for (j = 0 ; j < n ; j++) { if (CParent [j] == cdense) { nchild++ ; child = j ; } } if (nchild == 1) { // the cdense node has just one child; merge the two nodes PRINT1 (("root has one child\n")) ; CParent [cdense] = -2 ; // cdense is deleted CParent [child] = EMPTY ; // child becomes a root for (j = 0 ; j < n ; j++) { if (Flag [j] == FLIP (cdense)) { // j is a dense node PRINT1 (("dense %d\n", j)) ; Flag [j] = FLIP (child) ; } } } } //-------------------------------------------------------------------------- // postorder the components //-------------------------------------------------------------------------- DEBUG (for (cnt = 0, j = 0 ; j < n ; j++) if (CParent [j] != -2) cnt++) ; // use Cmember as workspace for Post [ Post = Cmember ; // cholmod_postorder uses Head and Iwork [0..2n]. It does not use Flag, // which here holds the mapping of nodes to repnodes. It ignores all nodes // for which CParent [j] < -1, so it operates just on the repnodes. // workspace: Head (n), Iwork (2*n) ncomponents = CHOLMOD(postorder) (CParent, n, NULL, Post, Common) ; ASSERT (cnt == ncomponents) ; // use Iwork [0..n-1] as workspace for Ipost ( Ipost = Iwork ; DEBUG (for (j = 0 ; j < n ; j++) Ipost [j] = EMPTY) ; // compute inverse postorder for (c = 0 ; c < ncomponents ; c++) { cnode = Post [c] ; ASSERT (cnode >= 0 && cnode < n) ; Ipost [cnode] = c ; ASSERT (Head [c] == EMPTY) ; } // adjust the parent array // Iwork [n..2n-1] used for NewParent [ NewParent = Iwork + n ; for (c = 0 ; c < ncomponents ; c++) { parent = CParent [Post [c]] ; NewParent [c] = (parent == EMPTY) ? EMPTY : (Ipost [parent]) ; } for (c = 0 ; c < ncomponents ; c++) { CParent [c] = NewParent [c] ; } ASSERT (CHOLMOD(dump_parent) (CParent, ncomponents, "CParent", Common)) ; // Iwork [n..2n-1] no longer needed for NewParent ] // Cmember no longer needed for Post ] #ifndef NDEBUG // count the number of children of each node for (c = 0 ; c < ncomponents ; c++) { Cmember [c] = 0 ; } for (c = 0 ; c < ncomponents ; c++) { if (CParent [c] != EMPTY) Cmember [CParent [c]]++ ; } for (c = 0 ; c < ncomponents ; c++) { // a node is either a leaf, or has 2 or more children ASSERT (Cmember [c] == 0 || Cmember [c] >= 2) ; } #endif //-------------------------------------------------------------------------- // place each node in its component //-------------------------------------------------------------------------- for (j = 0 ; j < n ; j++) { // node j is in the cth component, whose repnode is cnode cnode = FLIP (Flag [j]) ; PRINT2 (("j "ID" flag "ID" cnode "ID"\n", j, Flag [j], FLIP (Flag [j]))) ; ASSERT (cnode >= 0 && cnode < n) ; c = Ipost [cnode] ; ASSERT (c >= 0 && c < ncomponents) ; Cmember [j] = c ; } // Flag no longer needed for the node-to-component mapping // done using Iwork [0..n-1] as workspace for Ipost ) //-------------------------------------------------------------------------- // clear the Flag array //-------------------------------------------------------------------------- Common->mark = EMPTY ; CLEAR_FLAG (Common) ; ASSERT (check_flag (Common)) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; //-------------------------------------------------------------------------- // find the permutation //-------------------------------------------------------------------------- PRINT1 (("nd_camd: %d A->stype %d\n", nd_camd, A->stype)) ; if (nd_camd) { //---------------------------------------------------------------------- // apply camd, csymamd, or ccolamd using the Cmember constraints //---------------------------------------------------------------------- if (A->stype != 0) { // ordering A+A', so fset and fsize are ignored. // Add the upper/lower part to a symmetric lower/upper matrix by // converting to unsymmetric mode // workspace: Iwork (nrow) B = CHOLMOD(copy) (A, 0, -1, Common) ; if (Common->status < CHOLMOD_OK) { PRINT0 (("make symmetric failed\n")) ; return (EMPTY) ; } ASSERT ((Int) (B->nrow) == n && (Int) (B->ncol) == n) ; PRINT2 (("nested dissection (2)\n")) ; B->stype = -1 ; if (nd_camd == 2) { // workspace: Head (nrow+1), Iwork (nrow) if symmetric-upper ok = CHOLMOD(csymamd) (B, Cmember, Perm, Common) ; } else { // workspace: Head (nrow), Iwork (4*nrow) ok = CHOLMOD(camd) (B, NULL, 0, Cmember, Perm, Common) ; } CHOLMOD(free_sparse) (&B, Common) ; if (!ok) { // failed PRINT0 (("camd/csymamd failed\n")) ; return (EMPTY) ; } } else { // ordering A*A' or A(:,f)*A(:,f)' // workspace: Iwork (nrow if no fset; MAX(nrow,ncol) if fset) if (!CHOLMOD(ccolamd) (A, fset, fsize, Cmember, Perm, Common)) { // ccolamd failed PRINT2 (("ccolamd failed\n")) ; return (EMPTY) ; } } } else { //---------------------------------------------------------------------- // natural ordering of each component //---------------------------------------------------------------------- // use Iwork [0..n-1] for Next [ Next = Iwork ; //---------------------------------------------------------------------- // place the nodes in link lists, one list per component //---------------------------------------------------------------------- // do so in reverse order, to preserve original ordering for (j = n-1 ; j >= 0 ; j--) { // node j is in the cth component c = Cmember [j] ; ASSERT (c >= 0 && c < ncomponents) ; // place node j in link list for component c Next [j] = Head [c] ; Head [c] = j ; } //---------------------------------------------------------------------- // order each node in each component //---------------------------------------------------------------------- k = 0 ; for (c = 0 ; c < ncomponents ; c++) { for (j = Head [c] ; j != EMPTY ; j = Next [j]) { Perm [k++] = j ; } Head [c] = EMPTY ; } ASSERT (k == n) ; // done using Iwork [0..n-1] for Next ] } //-------------------------------------------------------------------------- // clear workspace and return number of components //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; return (ncomponents) ; #else Common->status = CHOLMOD_NOT_INSTALLED ; return (EMPTY) ; #endif } //------------------------------------------------------------------------------ // cholmod_collapse_septree //------------------------------------------------------------------------------ // cholmod_nested_dissection returns the separator tree that was used in the // constrained minimum degree algorithm. Parameter settings (nd_small, // nd_oksep, etc) that give a good fill-reducing ordering may give too fine of // a separator tree for other uses (parallelism, multi-level LPDASA, etc). This // function takes as input the separator tree computed by // cholmod_nested_dissection, and collapses selected subtrees into single // nodes. A subtree is collapsed if its root node (the separator) is large // compared to the total number of nodes in the subtree, or if the subtree is // small. Note that the separator tree may actually be a forest. // // nd_oksep and nd_small act just like the ordering parameters in Common. // Returns the new number of nodes in the separator tree. int64_t CHOLMOD(collapse_septree) ( // input: size_t n, // # of nodes in the graph size_t ncomponents, // # of nodes in the separator tree (must be <= n) double nd_oksep, // collapse if #sep >= nd_oksep * #nodes in subtree size_t nd_small, // collapse if #nodes in subtree < nd_small // output: Int *CParent, // size ncomponents; from cholmod_nested_dissection Int *Cmember, // size n; from cholmod_nested_dissection cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- #ifndef NPARTITION Int *First, *Count, *Csubtree, *W, *Map ; Int c, j, k, nc, sepsize, total_weight, parent, nc_new, first ; int collapse = FALSE ; RETURN_IF_NULL_COMMON (EMPTY) ; RETURN_IF_NULL (CParent, EMPTY) ; RETURN_IF_NULL (Cmember, EMPTY) ; if (n < ncomponents) { ERROR (CHOLMOD_INVALID, "invalid separator tree") ; return (EMPTY) ; } Common->status = CHOLMOD_OK ; nc = ncomponents ; if (n <= 1 || ncomponents <= 1) { // no change; tree is one node already return (nc) ; } nd_oksep = MAX (0, nd_oksep) ; nd_oksep = MIN (1, nd_oksep) ; nd_small = MAX (4, nd_small) ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- // s = 3*ncomponents int ok = TRUE ; size_t s = CHOLMOD(mult_size_t) (ncomponents, 3, &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (EMPTY) ; } CHOLMOD(allocate_work) (0, s, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (EMPTY) ; } W = Common->Iwork ; Count = W ; W += ncomponents ; // size ncomponents Csubtree = W ; W += ncomponents ; // size ncomponents First = W ; W += ncomponents ; // size ncomponents //-------------------------------------------------------------------------- // find the first descendant of each node of the separator tree //-------------------------------------------------------------------------- ASSERT (ncomponents >= 1 && ncomponents <= n) ; for (c = 0 ; c < nc ; c++) { First [c] = EMPTY ; } for (k = 0 ; k < nc ; k++) { for (c = k ; c != EMPTY && First [c] == -1 ; c = CParent [c]) { ASSERT (c >= 0 && c < nc) ; First [c] = k ; } } //-------------------------------------------------------------------------- // find the number of nodes of the graph in each node of the tree //-------------------------------------------------------------------------- for (c = 0 ; c < nc ; c++) { Count [c] = 0 ; } for (j = 0 ; j < (Int) n ; j++) { ASSERT (Cmember [j] >= 0 && Cmember [j] < nc) ; Count [Cmember [j]]++ ; } //-------------------------------------------------------------------------- // find the number of nodes in each subtree //-------------------------------------------------------------------------- for (c = 0 ; c < nc ; c++) { // each subtree includes its root Csubtree [c] = Count [c] ; PRINT1 ((ID" size "ID" parent "ID" first "ID"\n", c, Count [c], CParent [c], First [c])) ; } for (c = 0 ; c < nc ; c++) { // add the subtree of the child, c, into the count of its parent parent = CParent [c] ; ASSERT (parent >= EMPTY && parent < nc) ; if (parent != EMPTY) { Csubtree [parent] += Csubtree [c] ; } } #ifndef NDEBUG // the sum of the roots should be n j = 0 ; for (c = 0 ; c < nc ; c++) if (CParent [c] == EMPTY) j += Csubtree [c] ; ASSERT (j == (Int) n) ; #endif //-------------------------------------------------------------------------- // find subtrees to collapse //-------------------------------------------------------------------------- // consider all nodes in reverse post-order for (c = nc-1 ; c >= 0 ; c--) { // consider the subtree rooted at node c sepsize = Count [c] ; total_weight = Csubtree [c] ; PRINT1 (("Node "ID" sepsize "ID" subtree "ID" ratio %g\n", c, sepsize, total_weight, ((double) sepsize)/((double) total_weight))) ; first = First [c] ; if (first < c && // c must not be a leaf (sepsize > nd_oksep * total_weight || total_weight < (int) nd_small)) { // this separator is too large, or the subtree is too small. // collapse the tree, by converting the entire subtree rooted at // c into a single node. The subtree consists of all nodes from // First[c] to the root c. Flag all nodes from First[c] to c-1 // as dead. collapse = TRUE ; for (k = first ; k < c ; k++) { CParent [k] = -2 ; PRINT1 ((" collapse node "ID"\n", k)) ; } // continue at the next node, first-1 c = first ; } } PRINT1 (("collapse: %d\n", collapse)) ; //-------------------------------------------------------------------------- // compress the tree //-------------------------------------------------------------------------- Map = Count ; // Count no longer needed nc_new = nc ; if (collapse) { nc_new = 0 ; for (c = 0 ; c < nc ; c++) { Map [c] = nc_new ; if (CParent [c] >= EMPTY) { // node c is alive, and becomes node Map[c] in the new tree. // Increment nc_new for the next node c. nc_new++ ; } } PRINT1 (("Collapse the tree from "ID" to "ID" nodes\n", nc, nc_new)) ; ASSERT (nc_new > 0) ; for (c = 0 ; c < nc ; c++) { parent = CParent [c] ; if (parent >= EMPTY) { // node c is alive CParent [Map [c]] = (parent == EMPTY) ? EMPTY : Map [parent] ; } } for (j = 0 ; j < (Int) n ; j++) { PRINT1 (("j "ID" Cmember[j] "ID" Map[Cmember[j]] "ID"\n", j, Cmember [j], Map [Cmember [j]])) ; Cmember [j] = Map [Cmember [j]] ; } } //-------------------------------------------------------------------------- // return new size of separator tree //-------------------------------------------------------------------------- return (nc_new) ; #else Common->status = CHOLMOD_NOT_INSTALLED ; return (EMPTY) ; #endif } Matrix/src/SuiteSparse/CHOLMOD/Partition/cholmod_metis_wrapper.h0000644000175100001440000020264714552026002024376 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Partition/cholmod_metis_wrapper.h: METIS renaming for CHOLMOD //------------------------------------------------------------------------------ // CHOLMOD/Partition Module. Copyright (C) 2005-2023, University of Florida. // All Rights Reserved. Author: Timothy A. Davis. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #ifndef CHOLMOD_METIS_WRAP_H #define CHOLMOD_METIS_WRAP_H // always use GKRAND instead of the system rand in METIS #ifndef USE_GKRAND #define USE_GKRAND #endif #if SUITESPARSE_COMPILER_MSC #undef __thread #define __thread __declspec(thread) #endif #define CoarsenGraphNlevels SuiteSparse_metis_CoarsenGraphNlevels #define ComputeAccuracy SuiteSparse_metis_ComputeAccuracy #define ComputeBFSOrdering SuiteSparse_metis_ComputeBFSOrdering #define ComputeMean SuiteSparse_metis_ComputeMean #define ComputeMedianRFP SuiteSparse_metis_ComputeMedianRFP #define ComputeROCn SuiteSparse_metis_ComputeROCn #define ComputeStdDev SuiteSparse_metis_ComputeStdDev #define decodeblock SuiteSparse_metis_decodeblock #define encodeblock SuiteSparse_metis_encodeblock #define errexit SuiteSparse_metis_errexit #define gk_CPUSeconds SuiteSparse_metis_gk_CPUSeconds #define gk_WClockSeconds SuiteSparse_metis_gk_WClockSeconds #define gk_cur_jbufs SuiteSparse_metis_gk_cur_jbufs #define gk_jbuf SuiteSparse_metis_gk_jbuf #define gk_jbufs SuiteSparse_metis_gk_jbufs #define gk_AllocMatrix SuiteSparse_metis_gk_AllocMatrix #define gk_array2csr SuiteSparse_metis_gk_array2csr #define gk_cargmax SuiteSparse_metis_gk_cargmax #define gk_cargmin SuiteSparse_metis_gk_cargmin #define gk_cincset SuiteSparse_metis_gk_cincset #define gk_cmax SuiteSparse_metis_gk_cmax #define gk_cmin SuiteSparse_metis_gk_cmin #define gk_cnorm2 SuiteSparse_metis_gk_cnorm2 #define gk_csum SuiteSparse_metis_gk_csum #define gk_cAllocMatrix SuiteSparse_metis_gk_cAllocMatrix #define gk_cargmax_n SuiteSparse_metis_gk_cargmax_n #define gk_caxpy SuiteSparse_metis_gk_caxpy #define gk_ccopy SuiteSparse_metis_gk_ccopy #define gk_cdot SuiteSparse_metis_gk_cdot #define gk_cFreeMatrix SuiteSparse_metis_gk_cFreeMatrix #define gk_ckvAllocMatrix SuiteSparse_metis_gk_ckvAllocMatrix #define gk_ckvcopy SuiteSparse_metis_gk_ckvcopy #define gk_ckvFreeMatrix SuiteSparse_metis_gk_ckvFreeMatrix #define gk_ckvmalloc SuiteSparse_metis_gk_ckvmalloc #define gk_ckvrealloc SuiteSparse_metis_gk_ckvrealloc #define gk_ckvset SuiteSparse_metis_gk_ckvset #define gk_ckvSetMatrix SuiteSparse_metis_gk_ckvSetMatrix #define gk_ckvsmalloc SuiteSparse_metis_gk_ckvsmalloc #define gk_ckvsortd SuiteSparse_metis_gk_ckvsortd #define gk_ckvsorti SuiteSparse_metis_gk_ckvsorti #define gk_cmalloc SuiteSparse_metis_gk_cmalloc #define gk_crand SuiteSparse_metis_gk_crand #define gk_crandArrayPermute SuiteSparse_metis_gk_crandArrayPermute #define gk_crandArrayPermuteFine SuiteSparse_metis_gk_crandArrayPermuteFine #define gk_crandInRange SuiteSparse_metis_gk_crandInRange #define gk_crealloc SuiteSparse_metis_gk_crealloc #define gk_cscale SuiteSparse_metis_gk_cscale #define gk_cset SuiteSparse_metis_gk_cset #define gk_cSetMatrix SuiteSparse_metis_gk_cSetMatrix #define gk_csmalloc SuiteSparse_metis_gk_csmalloc #define gk_csortd SuiteSparse_metis_gk_csortd #define gk_csorti SuiteSparse_metis_gk_csorti #define gk_csrand SuiteSparse_metis_gk_csrand #define gk_csr_CompactColumns SuiteSparse_metis_gk_csr_CompactColumns #define gk_csr_ComputeSimilarity SuiteSparse_metis_gk_csr_ComputeSimilarity #define gk_csr_ComputeSquaredNorms SuiteSparse_metis_gk_csr_ComputeSquaredNorms #define gk_csr_ComputeSums SuiteSparse_metis_gk_csr_ComputeSums #define gk_csr_Create SuiteSparse_metis_gk_csr_Create #define gk_csr_CreateIndex SuiteSparse_metis_gk_csr_CreateIndex #define gk_csr_Dup SuiteSparse_metis_gk_csr_Dup #define gk_csr_ExtractPartition SuiteSparse_metis_gk_csr_ExtractPartition #define gk_csr_ExtractRows SuiteSparse_metis_gk_csr_ExtractRows #define gk_csr_ExtractSubmatrix SuiteSparse_metis_gk_csr_ExtractSubmatrix #define gk_csr_Free SuiteSparse_metis_gk_csr_Free #define gk_csr_FreeContents SuiteSparse_metis_gk_csr_FreeContents #define gk_csr_GetSimilarRows SuiteSparse_metis_gk_csr_GetSimilarRows #define gk_csr_Init SuiteSparse_metis_gk_csr_Init #define gk_csr_LowFilter SuiteSparse_metis_gk_csr_LowFilter #define gk_csr_Normalize SuiteSparse_metis_gk_csr_Normalize #define gk_csr_Prune SuiteSparse_metis_gk_csr_Prune #define gk_csr_Scale SuiteSparse_metis_gk_csr_Scale #define gk_csr_SortIndices SuiteSparse_metis_gk_csr_SortIndices #define gk_csr_Split SuiteSparse_metis_gk_csr_Split #define gk_csr_TopKPlusFilter SuiteSparse_metis_gk_csr_TopKPlusFilter #define gk_csr_ZScoreFilter SuiteSparse_metis_gk_csr_ZScoreFilter #define GKDecodeBase64 SuiteSparse_metis_GKDecodeBase64 #define GKEncodeBase64 SuiteSparse_metis_GKEncodeBase64 #define gk_dfkvkselect SuiteSparse_metis_gk_dfkvkselect #define gk_dAllocMatrix SuiteSparse_metis_gk_dAllocMatrix #define gk_dargmax_n SuiteSparse_metis_gk_dargmax_n #define gk_daxpy SuiteSparse_metis_gk_daxpy #define gk_dcopy SuiteSparse_metis_gk_dcopy #define gk_ddot SuiteSparse_metis_gk_ddot #define gk_dFreeMatrix SuiteSparse_metis_gk_dFreeMatrix #define gk_dkvAllocMatrix SuiteSparse_metis_gk_dkvAllocMatrix #define gk_dkvcopy SuiteSparse_metis_gk_dkvcopy #define gk_dkvFreeMatrix SuiteSparse_metis_gk_dkvFreeMatrix #define gk_dkvmalloc SuiteSparse_metis_gk_dkvmalloc #define gk_dkvrealloc SuiteSparse_metis_gk_dkvrealloc #define gk_dkvset SuiteSparse_metis_gk_dkvset #define gk_dkvSetMatrix SuiteSparse_metis_gk_dkvSetMatrix #define gk_dkvsmalloc SuiteSparse_metis_gk_dkvsmalloc #define gk_dkvsortd SuiteSparse_metis_gk_dkvsortd #define gk_dkvsorti SuiteSparse_metis_gk_dkvsorti #define gk_dmalloc SuiteSparse_metis_gk_dmalloc #define gk_dpqCheckHeap SuiteSparse_metis_gk_dpqCheckHeap #define gk_dpqCreate SuiteSparse_metis_gk_dpqCreate #define gk_dpqDelete SuiteSparse_metis_gk_dpqDelete #define gk_dpqDestroy SuiteSparse_metis_gk_dpqDestroy #define gk_dpqFree SuiteSparse_metis_gk_dpqFree #define gk_dpqGetTop SuiteSparse_metis_gk_dpqGetTop #define gk_dpqInit SuiteSparse_metis_gk_dpqInit #define gk_dpqInsert SuiteSparse_metis_gk_dpqInsert #define gk_dpqLength SuiteSparse_metis_gk_dpqLength #define gk_dpqReset SuiteSparse_metis_gk_dpqReset #define gk_dpqSeeKey SuiteSparse_metis_gk_dpqSeeKey #define gk_dpqSeeTopKey SuiteSparse_metis_gk_dpqSeeTopKey #define gk_dpqSeeTopVal SuiteSparse_metis_gk_dpqSeeTopVal #define gk_dpqUpdate SuiteSparse_metis_gk_dpqUpdate #define gk_drand SuiteSparse_metis_gk_drand #define gk_drandArrayPermute SuiteSparse_metis_gk_drandArrayPermute #define gk_drandArrayPermuteFine SuiteSparse_metis_gk_drandArrayPermuteFine #define gk_drandInRange SuiteSparse_metis_gk_drandInRange #define gk_drealloc SuiteSparse_metis_gk_drealloc #define gk_dscale SuiteSparse_metis_gk_dscale #define gk_dset SuiteSparse_metis_gk_dset #define gk_dSetMatrix SuiteSparse_metis_gk_dSetMatrix #define gk_dsmalloc SuiteSparse_metis_gk_dsmalloc #define gk_dsortd SuiteSparse_metis_gk_dsortd #define gk_dsorti SuiteSparse_metis_gk_dsorti #define gk_dsrand SuiteSparse_metis_gk_dsrand #define gk_dargmax SuiteSparse_metis_gk_dargmax #define gk_dargmin SuiteSparse_metis_gk_dargmin #define gk_dincset SuiteSparse_metis_gk_dincset #define gk_dmax SuiteSparse_metis_gk_dmax #define gk_dmin SuiteSparse_metis_gk_dmin #define gk_dnorm2 SuiteSparse_metis_gk_dnorm2 #define gk_dsum SuiteSparse_metis_gk_dsum #define gk_errexit SuiteSparse_metis_gk_errexit #define gkfooo SuiteSparse_metis_gkfooo #define gk_FreeMatrix SuiteSparse_metis_gk_FreeMatrix #define gk_fAllocMatrix SuiteSparse_metis_gk_fAllocMatrix #define gk_fargmax_n SuiteSparse_metis_gk_fargmax_n #define gk_faxpy SuiteSparse_metis_gk_faxpy #define gk_fcopy SuiteSparse_metis_gk_fcopy #define gk_fdot SuiteSparse_metis_gk_fdot #define gk_fFreeMatrix SuiteSparse_metis_gk_fFreeMatrix #define gk_find_frequent_itemsets SuiteSparse_metis_gk_find_frequent_itemsets #define gk_fkvAllocMatrix SuiteSparse_metis_gk_fkvAllocMatrix #define gk_fkvcopy SuiteSparse_metis_gk_fkvcopy #define gk_fkvFreeMatrix SuiteSparse_metis_gk_fkvFreeMatrix #define gk_fkvmalloc SuiteSparse_metis_gk_fkvmalloc #define gk_fkvrealloc SuiteSparse_metis_gk_fkvrealloc #define gk_fkvset SuiteSparse_metis_gk_fkvset #define gk_fkvSetMatrix SuiteSparse_metis_gk_fkvSetMatrix #define gk_fkvsmalloc SuiteSparse_metis_gk_fkvsmalloc #define gk_fkvsortd SuiteSparse_metis_gk_fkvsortd #define gk_fkvsorti SuiteSparse_metis_gk_fkvsorti #define gk_flog2 SuiteSparse_metis_gk_flog2 #define gk_fmalloc SuiteSparse_metis_gk_fmalloc #define gk_fpqCheckHeap SuiteSparse_metis_gk_fpqCheckHeap #define gk_fpqCreate SuiteSparse_metis_gk_fpqCreate #define gk_fpqDelete SuiteSparse_metis_gk_fpqDelete #define gk_fpqDestroy SuiteSparse_metis_gk_fpqDestroy #define gk_fpqFree SuiteSparse_metis_gk_fpqFree #define gk_fpqGetTop SuiteSparse_metis_gk_fpqGetTop #define gk_fpqInit SuiteSparse_metis_gk_fpqInit #define gk_fpqInsert SuiteSparse_metis_gk_fpqInsert #define gk_fpqLength SuiteSparse_metis_gk_fpqLength #define gk_fpqReset SuiteSparse_metis_gk_fpqReset #define gk_fpqSeeKey SuiteSparse_metis_gk_fpqSeeKey #define gk_fpqSeeTopKey SuiteSparse_metis_gk_fpqSeeTopKey #define gk_fpqSeeTopVal SuiteSparse_metis_gk_fpqSeeTopVal #define gk_fpqUpdate SuiteSparse_metis_gk_fpqUpdate #define gk_frand SuiteSparse_metis_gk_frand #define gk_frandArrayPermute SuiteSparse_metis_gk_frandArrayPermute #define gk_frandArrayPermuteFine SuiteSparse_metis_gk_frandArrayPermuteFine #define gk_frandInRange SuiteSparse_metis_gk_frandInRange #define gk_frealloc SuiteSparse_metis_gk_frealloc #define gk_free SuiteSparse_metis_gk_free #define gk_fscale SuiteSparse_metis_gk_fscale #define gk_fset SuiteSparse_metis_gk_fset #define gk_fSetMatrix SuiteSparse_metis_gk_fSetMatrix #define gk_fsmalloc SuiteSparse_metis_gk_fsmalloc #define gk_fsortd SuiteSparse_metis_gk_fsortd #define gk_fsorti SuiteSparse_metis_gk_fsorti #define gk_fsrand SuiteSparse_metis_gk_fsrand #define gk_fargmax SuiteSparse_metis_gk_fargmax #define gk_fargmin SuiteSparse_metis_gk_fargmin #define gk_fincset SuiteSparse_metis_gk_fincset #define gk_fmax SuiteSparse_metis_gk_fmax #define gk_fmin SuiteSparse_metis_gk_fmin #define gk_fnorm2 SuiteSparse_metis_gk_fnorm2 #define gk_fsum SuiteSparse_metis_gk_fsum #define gk_GetCurMemoryUsed SuiteSparse_metis_gk_GetCurMemoryUsed #define gk_GetMaxMemoryUsed SuiteSparse_metis_gk_GetMaxMemoryUsed #define gk_getopt SuiteSparse_metis_gk_getopt #define gk_getopt_long SuiteSparse_metis_gk_getopt_long #define gk_getopt_long_only SuiteSparse_metis_gk_getopt_long_only #define gk_gkmcoreAdd SuiteSparse_metis_gk_gkmcoreAdd #define gk_gkmcoreCreate SuiteSparse_metis_gk_gkmcoreCreate #define gk_gkmcoreDel SuiteSparse_metis_gk_gkmcoreDel #define gk_gkmcoreDestroy SuiteSparse_metis_gk_gkmcoreDestroy #define gk_gkmcorePop SuiteSparse_metis_gk_gkmcorePop #define gk_gkmcorePush SuiteSparse_metis_gk_gkmcorePush #define gk_graph_ComputeBestFOrdering SuiteSparse_metis_gk_graph_ComputeBestFOrdering #define gk_graph_ComputeBestFOrdering0 SuiteSparse_metis_gk_graph_ComputeBestFOrdering0 #define gk_graph_ComputeBFSOrdering SuiteSparse_metis_gk_graph_ComputeBFSOrdering #define gk_graph_Create SuiteSparse_metis_gk_graph_Create #define gk_graph_Dup SuiteSparse_metis_gk_graph_Dup #define gk_graph_ExtractSubgraph SuiteSparse_metis_gk_graph_ExtractSubgraph #define gk_graph_FindComponents SuiteSparse_metis_gk_graph_FindComponents #define gk_graph_Free SuiteSparse_metis_gk_graph_Free #define gk_graph_FreeContents SuiteSparse_metis_gk_graph_FreeContents #define gk_graph_Init SuiteSparse_metis_gk_graph_Init #define gk_graph_Reorder SuiteSparse_metis_gk_graph_Reorder #define gk_graph_SingleSourceShortestPaths SuiteSparse_metis_gk_graph_SingleSourceShortestPaths #define gk_i32AllocMatrix SuiteSparse_metis_gk_i32AllocMatrix #define gk_i32argmax_n SuiteSparse_metis_gk_i32argmax_n #define gk_i32axpy SuiteSparse_metis_gk_i32axpy #define gk_i32copy SuiteSparse_metis_gk_i32copy #define gk_i32dot SuiteSparse_metis_gk_i32dot #define gk_i32FreeMatrix SuiteSparse_metis_gk_i32FreeMatrix #define gk_i32kvAllocMatrix SuiteSparse_metis_gk_i32kvAllocMatrix #define gk_i32kvcopy SuiteSparse_metis_gk_i32kvcopy #define gk_i32kvFreeMatrix SuiteSparse_metis_gk_i32kvFreeMatrix #define gk_i32kvmalloc SuiteSparse_metis_gk_i32kvmalloc #define gk_i32kvrealloc SuiteSparse_metis_gk_i32kvrealloc #define gk_i32kvset SuiteSparse_metis_gk_i32kvset #define gk_i32kvSetMatrix SuiteSparse_metis_gk_i32kvSetMatrix #define gk_i32kvsmalloc SuiteSparse_metis_gk_i32kvsmalloc #define gk_i32kvsortd SuiteSparse_metis_gk_i32kvsortd #define gk_i32kvsorti SuiteSparse_metis_gk_i32kvsorti #define gk_i32malloc SuiteSparse_metis_gk_i32malloc #define gk_i32pqCheckHeap SuiteSparse_metis_gk_i32pqCheckHeap #define gk_i32pqCreate SuiteSparse_metis_gk_i32pqCreate #define gk_i32pqDelete SuiteSparse_metis_gk_i32pqDelete #define gk_i32pqDestroy SuiteSparse_metis_gk_i32pqDestroy #define gk_i32pqFree SuiteSparse_metis_gk_i32pqFree #define gk_i32pqGetTop SuiteSparse_metis_gk_i32pqGetTop #define gk_i32pqInit SuiteSparse_metis_gk_i32pqInit #define gk_i32pqInsert SuiteSparse_metis_gk_i32pqInsert #define gk_i32pqLength SuiteSparse_metis_gk_i32pqLength #define gk_i32pqReset SuiteSparse_metis_gk_i32pqReset #define gk_i32pqSeeKey SuiteSparse_metis_gk_i32pqSeeKey #define gk_i32pqSeeTopKey SuiteSparse_metis_gk_i32pqSeeTopKey #define gk_i32pqSeeTopVal SuiteSparse_metis_gk_i32pqSeeTopVal #define gk_i32pqUpdate SuiteSparse_metis_gk_i32pqUpdate #define gk_i32realloc SuiteSparse_metis_gk_i32realloc #define gk_i32scale SuiteSparse_metis_gk_i32scale #define gk_i32set SuiteSparse_metis_gk_i32set #define gk_i32SetMatrix SuiteSparse_metis_gk_i32SetMatrix #define gk_i32smalloc SuiteSparse_metis_gk_i32smalloc #define gk_i32argmax SuiteSparse_metis_gk_i32argmax #define gk_i32argmin SuiteSparse_metis_gk_i32argmin #define gk_i32incset SuiteSparse_metis_gk_i32incset #define gk_i32max SuiteSparse_metis_gk_i32max #define gk_i32min SuiteSparse_metis_gk_i32min #define gk_i32norm2 SuiteSparse_metis_gk_i32norm2 #define gk_i32sum SuiteSparse_metis_gk_i32sum #define gk_i64AllocMatrix SuiteSparse_metis_gk_i64AllocMatrix #define gk_i64argmax_n SuiteSparse_metis_gk_i64argmax_n #define gk_i64axpy SuiteSparse_metis_gk_i64axpy #define gk_i64copy SuiteSparse_metis_gk_i64copy #define gk_i64dot SuiteSparse_metis_gk_i64dot #define gk_i64FreeMatrix SuiteSparse_metis_gk_i64FreeMatrix #define gk_i64kvAllocMatrix SuiteSparse_metis_gk_i64kvAllocMatrix #define gk_i64kvcopy SuiteSparse_metis_gk_i64kvcopy #define gk_i64kvFreeMatrix SuiteSparse_metis_gk_i64kvFreeMatrix #define gk_i64kvmalloc SuiteSparse_metis_gk_i64kvmalloc #define gk_i64kvrealloc SuiteSparse_metis_gk_i64kvrealloc #define gk_i64kvset SuiteSparse_metis_gk_i64kvset #define gk_i64kvSetMatrix SuiteSparse_metis_gk_i64kvSetMatrix #define gk_i64kvsmalloc SuiteSparse_metis_gk_i64kvsmalloc #define gk_i64kvsortd SuiteSparse_metis_gk_i64kvsortd #define gk_i64kvsorti SuiteSparse_metis_gk_i64kvsorti #define gk_i64malloc SuiteSparse_metis_gk_i64malloc #define gk_i64pqCheckHeap SuiteSparse_metis_gk_i64pqCheckHeap #define gk_i64pqCreate SuiteSparse_metis_gk_i64pqCreate #define gk_i64pqDelete SuiteSparse_metis_gk_i64pqDelete #define gk_i64pqDestroy SuiteSparse_metis_gk_i64pqDestroy #define gk_i64pqFree SuiteSparse_metis_gk_i64pqFree #define gk_i64pqGetTop SuiteSparse_metis_gk_i64pqGetTop #define gk_i64pqInit SuiteSparse_metis_gk_i64pqInit #define gk_i64pqInsert SuiteSparse_metis_gk_i64pqInsert #define gk_i64pqLength SuiteSparse_metis_gk_i64pqLength #define gk_i64pqReset SuiteSparse_metis_gk_i64pqReset #define gk_i64pqSeeKey SuiteSparse_metis_gk_i64pqSeeKey #define gk_i64pqSeeTopKey SuiteSparse_metis_gk_i64pqSeeTopKey #define gk_i64pqSeeTopVal SuiteSparse_metis_gk_i64pqSeeTopVal #define gk_i64pqUpdate SuiteSparse_metis_gk_i64pqUpdate #define gk_i64realloc SuiteSparse_metis_gk_i64realloc #define gk_i64scale SuiteSparse_metis_gk_i64scale #define gk_i64set SuiteSparse_metis_gk_i64set #define gk_i64SetMatrix SuiteSparse_metis_gk_i64SetMatrix #define gk_i64smalloc SuiteSparse_metis_gk_i64smalloc #define gk_i64argmax SuiteSparse_metis_gk_i64argmax #define gk_i64argmin SuiteSparse_metis_gk_i64argmin #define gk_i64incset SuiteSparse_metis_gk_i64incset #define gk_i64max SuiteSparse_metis_gk_i64max #define gk_i64min SuiteSparse_metis_gk_i64min #define gk_i64norm2 SuiteSparse_metis_gk_i64norm2 #define gk_i64sum SuiteSparse_metis_gk_i64sum #define gk_idxAllocMatrix SuiteSparse_metis_gk_idxAllocMatrix #define gk_idxargmax_n SuiteSparse_metis_gk_idxargmax_n #define gk_idxaxpy SuiteSparse_metis_gk_idxaxpy #define gk_idxcopy SuiteSparse_metis_gk_idxcopy #define gk_idxdot SuiteSparse_metis_gk_idxdot #define gk_idxargmax SuiteSparse_metis_gk_idxargmax #define gk_idxargmin SuiteSparse_metis_gk_idxargmin #define gk_idxincset SuiteSparse_metis_gk_idxincset #define gk_idxmax SuiteSparse_metis_gk_idxmax #define gk_idxmin SuiteSparse_metis_gk_idxmin #define gk_idxnorm2 SuiteSparse_metis_gk_idxnorm2 #define gk_idxsum SuiteSparse_metis_gk_idxsum #define gk_idxFreeMatrix SuiteSparse_metis_gk_idxFreeMatrix #define gk_idxkvAllocMatrix SuiteSparse_metis_gk_idxkvAllocMatrix #define gk_idxkvcopy SuiteSparse_metis_gk_idxkvcopy #define gk_idxkvFreeMatrix SuiteSparse_metis_gk_idxkvFreeMatrix #define gk_idxkvmalloc SuiteSparse_metis_gk_idxkvmalloc #define gk_idxkvrealloc SuiteSparse_metis_gk_idxkvrealloc #define gk_idxkvset SuiteSparse_metis_gk_idxkvset #define gk_idxkvSetMatrix SuiteSparse_metis_gk_idxkvSetMatrix #define gk_idxkvsmalloc SuiteSparse_metis_gk_idxkvsmalloc #define gk_idxkvsortd SuiteSparse_metis_gk_idxkvsortd #define gk_idxkvsorti SuiteSparse_metis_gk_idxkvsorti #define gk_idxmalloc SuiteSparse_metis_gk_idxmalloc #define gk_idxpqCheckHeap SuiteSparse_metis_gk_idxpqCheckHeap #define gk_idxpqCreate SuiteSparse_metis_gk_idxpqCreate #define gk_idxpqDelete SuiteSparse_metis_gk_idxpqDelete #define gk_idxpqDestroy SuiteSparse_metis_gk_idxpqDestroy #define gk_idxpqFree SuiteSparse_metis_gk_idxpqFree #define gk_idxpqGetTop SuiteSparse_metis_gk_idxpqGetTop #define gk_idxpqInit SuiteSparse_metis_gk_idxpqInit #define gk_idxpqInsert SuiteSparse_metis_gk_idxpqInsert #define gk_idxpqLength SuiteSparse_metis_gk_idxpqLength #define gk_idxpqReset SuiteSparse_metis_gk_idxpqReset #define gk_idxpqSeeKey SuiteSparse_metis_gk_idxpqSeeKey #define gk_idxpqSeeTopKey SuiteSparse_metis_gk_idxpqSeeTopKey #define gk_idxpqSeeTopVal SuiteSparse_metis_gk_idxpqSeeTopVal #define gk_idxpqUpdate SuiteSparse_metis_gk_idxpqUpdate #define gk_idxrand SuiteSparse_metis_gk_idxrand #define gk_idxrandArrayPermute SuiteSparse_metis_gk_idxrandArrayPermute #define gk_idxrandArrayPermuteFine SuiteSparse_metis_gk_idxrandArrayPermuteFine #define gk_idxrandInRange SuiteSparse_metis_gk_idxrandInRange #define gk_idxrealloc SuiteSparse_metis_gk_idxrealloc #define gk_idxscale SuiteSparse_metis_gk_idxscale #define gk_idxset SuiteSparse_metis_gk_idxset #define gk_idxSetMatrix SuiteSparse_metis_gk_idxSetMatrix #define gk_idxsmalloc SuiteSparse_metis_gk_idxsmalloc #define gk_idxsortd SuiteSparse_metis_gk_idxsortd #define gk_idxsorti SuiteSparse_metis_gk_idxsorti #define gk_idxsrand SuiteSparse_metis_gk_idxsrand #define gk_iAllocMatrix SuiteSparse_metis_gk_iAllocMatrix #define gk_iargmax_n SuiteSparse_metis_gk_iargmax_n #define gk_iaxpy SuiteSparse_metis_gk_iaxpy #define gk_icopy SuiteSparse_metis_gk_icopy #define gk_idot SuiteSparse_metis_gk_idot #define gk_i2cc2i_create_common SuiteSparse_metis_gk_i2cc2i_create_common #define gk_ifkvkselect SuiteSparse_metis_gk_ifkvkselect #define gk_iargmax SuiteSparse_metis_gk_iargmax #define gk_iargmin SuiteSparse_metis_gk_iargmin #define gk_iincset SuiteSparse_metis_gk_iincset #define gk_imax SuiteSparse_metis_gk_imax #define gk_imin SuiteSparse_metis_gk_imin #define gk_inorm2 SuiteSparse_metis_gk_inorm2 #define gk_isum SuiteSparse_metis_gk_isum #define gk_iFreeMatrix SuiteSparse_metis_gk_iFreeMatrix #define gk_ikvAllocMatrix SuiteSparse_metis_gk_ikvAllocMatrix #define gk_ikvcopy SuiteSparse_metis_gk_ikvcopy #define gk_ikvFreeMatrix SuiteSparse_metis_gk_ikvFreeMatrix #define gk_ikvmalloc SuiteSparse_metis_gk_ikvmalloc #define gk_ikvrealloc SuiteSparse_metis_gk_ikvrealloc #define gk_ikvset SuiteSparse_metis_gk_ikvset #define gk_ikvSetMatrix SuiteSparse_metis_gk_ikvSetMatrix #define gk_ikvsmalloc SuiteSparse_metis_gk_ikvsmalloc #define gk_ikvsortd SuiteSparse_metis_gk_ikvsortd #define gk_ikvsorti SuiteSparse_metis_gk_ikvsorti #define gk_imalloc SuiteSparse_metis_gk_imalloc #define gk_ipqCheckHeap SuiteSparse_metis_gk_ipqCheckHeap #define gk_ipqCreate SuiteSparse_metis_gk_ipqCreate #define gk_ipqDelete SuiteSparse_metis_gk_ipqDelete #define gk_ipqDestroy SuiteSparse_metis_gk_ipqDestroy #define gk_ipqFree SuiteSparse_metis_gk_ipqFree #define gk_ipqGetTop SuiteSparse_metis_gk_ipqGetTop #define gk_ipqInit SuiteSparse_metis_gk_ipqInit #define gk_ipqInsert SuiteSparse_metis_gk_ipqInsert #define gk_ipqLength SuiteSparse_metis_gk_ipqLength #define gk_ipqReset SuiteSparse_metis_gk_ipqReset #define gk_ipqSeeKey SuiteSparse_metis_gk_ipqSeeKey #define gk_ipqSeeTopKey SuiteSparse_metis_gk_ipqSeeTopKey #define gk_ipqSeeTopVal SuiteSparse_metis_gk_ipqSeeTopVal #define gk_ipqUpdate SuiteSparse_metis_gk_ipqUpdate #define gk_irand SuiteSparse_metis_gk_irand #define gk_irandArrayPermute SuiteSparse_metis_gk_irandArrayPermute #define gk_irandArrayPermuteFine SuiteSparse_metis_gk_irandArrayPermuteFine #define gk_irandInRange SuiteSparse_metis_gk_irandInRange #define gk_irealloc SuiteSparse_metis_gk_irealloc #define gk_iscale SuiteSparse_metis_gk_iscale #define gk_iset SuiteSparse_metis_gk_iset #define gk_iSetMatrix SuiteSparse_metis_gk_iSetMatrix #define gk_ismalloc SuiteSparse_metis_gk_ismalloc #define gk_isortd SuiteSparse_metis_gk_isortd #define gk_isorti SuiteSparse_metis_gk_isorti #define gk_ispow2 SuiteSparse_metis_gk_ispow2 #define gk_isrand SuiteSparse_metis_gk_isrand #define gk_log2 SuiteSparse_metis_gk_log2 #define gk_malloc SuiteSparse_metis_gk_malloc #define gk_malloc_cleanup SuiteSparse_metis_gk_malloc_cleanup #define gk_malloc_init SuiteSparse_metis_gk_malloc_init #define gk_mcoreAdd SuiteSparse_metis_gk_mcoreAdd #define gk_mcoreCreate SuiteSparse_metis_gk_mcoreCreate #define gk_mcoreDel SuiteSparse_metis_gk_mcoreDel #define gk_mcoreDestroy SuiteSparse_metis_gk_mcoreDestroy #define gk_mcoreMalloc SuiteSparse_metis_gk_mcoreMalloc #define gk_mcorePop SuiteSparse_metis_gk_mcorePop #define gk_mcorePush SuiteSparse_metis_gk_mcorePush #define gk_NonLocalExit_Handler SuiteSparse_metis_gk_NonLocalExit_Handler #define gk_randinit SuiteSparse_metis_gk_randinit #define gk_randint32 SuiteSparse_metis_gk_randint32 #define gk_randint64 SuiteSparse_metis_gk_randint64 #define gk_RandomPermute SuiteSparse_metis_gk_RandomPermute #define gk_realloc SuiteSparse_metis_gk_realloc #define gk_rw_PageRank SuiteSparse_metis_gk_rw_PageRank #define gk_seq_free SuiteSparse_metis_gk_seq_free #define gk_seq_init SuiteSparse_metis_gk_seq_init #define gk_set_exit_on_error SuiteSparse_metis_gk_set_exit_on_error #define gk_SetSignalHandlers SuiteSparse_metis_gk_SetSignalHandlers #define gk_sigthrow SuiteSparse_metis_gk_sigthrow #define gk_sigtrap SuiteSparse_metis_gk_sigtrap #define gk_siguntrap SuiteSparse_metis_gk_siguntrap #define gk_skvAllocMatrix SuiteSparse_metis_gk_skvAllocMatrix #define gk_skvcopy SuiteSparse_metis_gk_skvcopy #define gk_skvFreeMatrix SuiteSparse_metis_gk_skvFreeMatrix #define gk_skvmalloc SuiteSparse_metis_gk_skvmalloc #define gk_skvrealloc SuiteSparse_metis_gk_skvrealloc #define gk_skvset SuiteSparse_metis_gk_skvset #define gk_skvSetMatrix SuiteSparse_metis_gk_skvSetMatrix #define gk_skvsmalloc SuiteSparse_metis_gk_skvsmalloc #define gk_skvsortd SuiteSparse_metis_gk_skvsortd #define gk_skvsorti SuiteSparse_metis_gk_skvsorti #define gk_strdup SuiteSparse_metis_gk_strdup #define gk_UnsetSignalHandlers SuiteSparse_metis_gk_UnsetSignalHandlers #define gk_zAllocMatrix SuiteSparse_metis_gk_zAllocMatrix #define gk_zargmax_n SuiteSparse_metis_gk_zargmax_n #define gk_zaxpy SuiteSparse_metis_gk_zaxpy #define gk_zcopy SuiteSparse_metis_gk_zcopy #define gk_zdot SuiteSparse_metis_gk_zdot #define gk_zFreeMatrix SuiteSparse_metis_gk_zFreeMatrix #define gk_zkvAllocMatrix SuiteSparse_metis_gk_zkvAllocMatrix #define gk_zkvcopy SuiteSparse_metis_gk_zkvcopy #define gk_zkvFreeMatrix SuiteSparse_metis_gk_zkvFreeMatrix #define gk_zkvmalloc SuiteSparse_metis_gk_zkvmalloc #define gk_zkvrealloc SuiteSparse_metis_gk_zkvrealloc #define gk_zkvset SuiteSparse_metis_gk_zkvset #define gk_zkvSetMatrix SuiteSparse_metis_gk_zkvSetMatrix #define gk_zkvsmalloc SuiteSparse_metis_gk_zkvsmalloc #define gk_zkvsortd SuiteSparse_metis_gk_zkvsortd #define gk_zkvsorti SuiteSparse_metis_gk_zkvsorti #define gk_zmalloc SuiteSparse_metis_gk_zmalloc #define gk_zrand SuiteSparse_metis_gk_zrand #define gk_zrandArrayPermute SuiteSparse_metis_gk_zrandArrayPermute #define gk_zrandArrayPermuteFine SuiteSparse_metis_gk_zrandArrayPermuteFine #define gk_zrandInRange SuiteSparse_metis_gk_zrandInRange #define gk_zrealloc SuiteSparse_metis_gk_zrealloc #define gk_zscale SuiteSparse_metis_gk_zscale #define gk_zset SuiteSparse_metis_gk_zset #define gk_zSetMatrix SuiteSparse_metis_gk_zSetMatrix #define gk_zsmalloc SuiteSparse_metis_gk_zsmalloc #define gk_zsrand SuiteSparse_metis_gk_zsrand #define gk_zargmax SuiteSparse_metis_gk_zargmax #define gk_zargmin SuiteSparse_metis_gk_zargmin #define gk_zincset SuiteSparse_metis_gk_zincset #define gk_zmax SuiteSparse_metis_gk_zmax #define gk_zmin SuiteSparse_metis_gk_zmin #define gk_znorm2 SuiteSparse_metis_gk_znorm2 #define gk_zsum SuiteSparse_metis_gk_zsum #define GrowBisectionNode2 SuiteSparse_metis_GrowBisectionNode2 #define HTable_Create SuiteSparse_metis_HTable_Create #define HTable_Delete SuiteSparse_metis_HTable_Delete #define HTable_Destroy SuiteSparse_metis_HTable_Destroy #define HTable_GetNext SuiteSparse_metis_HTable_GetNext #define HTable_HFunction SuiteSparse_metis_HTable_HFunction #define HTable_Insert SuiteSparse_metis_HTable_Insert #define HTable_Reset SuiteSparse_metis_HTable_Reset #define HTable_Resize SuiteSparse_metis_HTable_Resize #define HTable_Search SuiteSparse_metis_HTable_Search #define HTable_SearchAndDelete SuiteSparse_metis_HTable_SearchAndDelete #define itemsets_find_frequent_itemsets SuiteSparse_metis_itemsets_find_frequent_itemsets #define itemsets_project_matrix SuiteSparse_metis_itemsets_project_matrix #define libmetis__Allocate2WayNodePartitionMemory SuiteSparse_metis_libmetis__Allocate2WayNodePartitionMemory #define libmetis__Allocate2WayPartitionMemory SuiteSparse_metis_libmetis__Allocate2WayPartitionMemory #define libmetis__AllocateKWayPartitionMemory SuiteSparse_metis_libmetis__AllocateKWayPartitionMemory #define libmetis__AllocateRefinementWorkSpace SuiteSparse_metis_libmetis__AllocateRefinementWorkSpace #define libmetis__AllocateWorkSpace SuiteSparse_metis_libmetis__AllocateWorkSpace #define libmetis__Balance2Way SuiteSparse_metis_libmetis__Balance2Way #define libmetis__BetterBalance2Way SuiteSparse_metis_libmetis__BetterBalance2Way #define libmetis__BetterBalanceKWay SuiteSparse_metis_libmetis__BetterBalanceKWay #define libmetis__BetterVBalance SuiteSparse_metis_libmetis__BetterVBalance #define libmetis__Bnd2WayBalance SuiteSparse_metis_libmetis__Bnd2WayBalance #define libmetis__BucketSortKeysInc SuiteSparse_metis_libmetis__BucketSortKeysInc #define libmetis__Change2CNumbering SuiteSparse_metis_libmetis__Change2CNumbering #define libmetis__Change2FNumbering SuiteSparse_metis_libmetis__Change2FNumbering #define libmetis__Change2FNumbering2 SuiteSparse_metis_libmetis__Change2FNumbering2 #define libmetis__Change2FNumberingOrder SuiteSparse_metis_libmetis__Change2FNumberingOrder #define libmetis__ChangeMesh2CNumbering SuiteSparse_metis_libmetis__ChangeMesh2CNumbering #define libmetis__ChangeMesh2FNumbering SuiteSparse_metis_libmetis__ChangeMesh2FNumbering #define libmetis__ChangeMesh2FNumbering2 SuiteSparse_metis_libmetis__ChangeMesh2FNumbering2 #define libmetis__CheckBnd SuiteSparse_metis_libmetis__CheckBnd #define libmetis__CheckBnd2 SuiteSparse_metis_libmetis__CheckBnd2 #define libmetis__CheckGraph SuiteSparse_metis_libmetis__CheckGraph #define libmetis__CheckInputGraphWeights SuiteSparse_metis_libmetis__CheckInputGraphWeights #define libmetis__CheckKWayVolPartitionParams SuiteSparse_metis_libmetis__CheckKWayVolPartitionParams #define libmetis__CheckNodeBnd SuiteSparse_metis_libmetis__CheckNodeBnd #define libmetis__CheckNodePartitionParams SuiteSparse_metis_libmetis__CheckNodePartitionParams #define libmetis__CheckParams SuiteSparse_metis_libmetis__CheckParams #define libmetis__CheckRInfo SuiteSparse_metis_libmetis__CheckRInfo #define libmetis__cnbrpoolGetNext SuiteSparse_metis_libmetis__cnbrpoolGetNext #define libmetis__cnbrpoolReset SuiteSparse_metis_libmetis__cnbrpoolReset #define libmetis__CoarsenGraph SuiteSparse_metis_libmetis__CoarsenGraph #define libmetis__CompressGraph SuiteSparse_metis_libmetis__CompressGraph #define libmetis__Compute2WayNodePartitionParams SuiteSparse_metis_libmetis__Compute2WayNodePartitionParams #define libmetis__Compute2WayPartitionParams SuiteSparse_metis_libmetis__Compute2WayPartitionParams #define libmetis__ComputeCut SuiteSparse_metis_libmetis__ComputeCut #define libmetis__ComputeElementBalance SuiteSparse_metis_libmetis__ComputeElementBalance #define libmetis__ComputeKWayBoundary SuiteSparse_metis_libmetis__ComputeKWayBoundary #define libmetis__ComputeKWayPartitionParams SuiteSparse_metis_libmetis__ComputeKWayPartitionParams #define libmetis__ComputeKWayVolGains SuiteSparse_metis_libmetis__ComputeKWayVolGains #define libmetis__ComputeLoadImbalance SuiteSparse_metis_libmetis__ComputeLoadImbalance #define libmetis__ComputeLoadImbalanceDiff SuiteSparse_metis_libmetis__ComputeLoadImbalanceDiff #define libmetis__ComputeLoadImbalanceDiffVec SuiteSparse_metis_libmetis__ComputeLoadImbalanceDiffVec #define libmetis__ComputeLoadImbalanceVec SuiteSparse_metis_libmetis__ComputeLoadImbalanceVec #define libmetis__ComputeMaxCut SuiteSparse_metis_libmetis__ComputeMaxCut #define libmetis__ComputePartitionBalance SuiteSparse_metis_libmetis__ComputePartitionBalance #define libmetis__ComputePartitionInfoBipartite SuiteSparse_metis_libmetis__ComputePartitionInfoBipartite #define libmetis__ComputeSubDomainGraph SuiteSparse_metis_libmetis__ComputeSubDomainGraph #define libmetis__ComputeVolume SuiteSparse_metis_libmetis__ComputeVolume #define libmetis__ConstructMinCoverSeparator SuiteSparse_metis_libmetis__ConstructMinCoverSeparator #define libmetis__ConstructSeparator SuiteSparse_metis_libmetis__ConstructSeparator #define libmetis__CreateCoarseGraph SuiteSparse_metis_libmetis__CreateCoarseGraph #define libmetis__CreateCoarseGraphNoMask SuiteSparse_metis_libmetis__CreateCoarseGraphNoMask #define libmetis__CreateCoarseGraphPerm SuiteSparse_metis_libmetis__CreateCoarseGraphPerm #define libmetis__CreateGraph SuiteSparse_metis_libmetis__CreateGraph #define libmetis__CreateGraphDual SuiteSparse_metis_libmetis__CreateGraphDual #define libmetis__CreateGraphNodal SuiteSparse_metis_libmetis__CreateGraphNodal #define libmetis__CreateMesh SuiteSparse_metis_libmetis__CreateMesh #define libmetis__EliminateComponents SuiteSparse_metis_libmetis__EliminateComponents #define libmetis__EliminateSubDomainEdges SuiteSparse_metis_libmetis__EliminateSubDomainEdges #define libmetis__FindCommonElements SuiteSparse_metis_libmetis__FindCommonElements #define libmetis__FindCommonNodes SuiteSparse_metis_libmetis__FindCommonNodes #define libmetis__FindPartitionInducedComponents SuiteSparse_metis_libmetis__FindPartitionInducedComponents #define libmetis__FindSepInducedComponents SuiteSparse_metis_libmetis__FindSepInducedComponents #define libmetis__FixGraph SuiteSparse_metis_libmetis__FixGraph #define libmetis__FM_2WayCutRefine SuiteSparse_metis_libmetis__FM_2WayCutRefine #define libmetis__FM_2WayNodeBalance SuiteSparse_metis_libmetis__FM_2WayNodeBalance #define libmetis__FM_2WayNodeRefine1Sided SuiteSparse_metis_libmetis__FM_2WayNodeRefine1Sided #define libmetis__FM_2WayNodeRefine1SidedP SuiteSparse_metis_libmetis__FM_2WayNodeRefine1SidedP #define libmetis__FM_2WayNodeRefine2Sided SuiteSparse_metis_libmetis__FM_2WayNodeRefine2Sided #define libmetis__FM_2WayNodeRefine2SidedP SuiteSparse_metis_libmetis__FM_2WayNodeRefine2SidedP #define libmetis__FM_2WayRefine SuiteSparse_metis_libmetis__FM_2WayRefine #define libmetis__FM_Mc2WayCutRefine SuiteSparse_metis_libmetis__FM_Mc2WayCutRefine #define libmetis__FreeCtrl SuiteSparse_metis_libmetis__FreeCtrl #define libmetis__FreeGraph SuiteSparse_metis_libmetis__FreeGraph #define libmetis__FreeMesh SuiteSparse_metis_libmetis__FreeMesh #define libmetis__FreeRData SuiteSparse_metis_libmetis__FreeRData #define libmetis__FreeWorkSpace SuiteSparse_metis_libmetis__FreeWorkSpace #define libmetis__General2WayBalance SuiteSparse_metis_libmetis__General2WayBalance #define libmetis__genmmd SuiteSparse_metis_libmetis__genmmd #define libmetis__Greedy_KWayCutOptimize SuiteSparse_metis_libmetis__Greedy_KWayCutOptimize #define libmetis__Greedy_KWayOptimize SuiteSparse_metis_libmetis__Greedy_KWayOptimize #define libmetis__Greedy_KWayVolOptimize SuiteSparse_metis_libmetis__Greedy_KWayVolOptimize #define libmetis__Greedy_McKWayCutOptimize SuiteSparse_metis_libmetis__Greedy_McKWayCutOptimize #define libmetis__Greedy_McKWayVolOptimize SuiteSparse_metis_libmetis__Greedy_McKWayVolOptimize #define libmetis__GrowBisection SuiteSparse_metis_libmetis__GrowBisection #define libmetis__GrowBisectionNode SuiteSparse_metis_libmetis__GrowBisectionNode #define libmetis__iAllocMatrix SuiteSparse_metis_libmetis__iAllocMatrix #define libmetis__iargmax SuiteSparse_metis_libmetis__iargmax #define libmetis__iargmax2_nrm SuiteSparse_metis_libmetis__iargmax2_nrm #define libmetis__iargmax_n SuiteSparse_metis_libmetis__iargmax_n #define libmetis__iargmax_nrm SuiteSparse_metis_libmetis__iargmax_nrm #define libmetis__iargmax_strd SuiteSparse_metis_libmetis__iargmax_strd #define libmetis__iargmin SuiteSparse_metis_libmetis__iargmin #define libmetis__iarray2csr SuiteSparse_metis_libmetis__iarray2csr #define libmetis__iaxpy SuiteSparse_metis_libmetis__iaxpy #define libmetis__icopy SuiteSparse_metis_libmetis__icopy #define libmetis__idot SuiteSparse_metis_libmetis__idot #define libmetis__iFreeMatrix SuiteSparse_metis_libmetis__iFreeMatrix #define libmetis__iincset SuiteSparse_metis_libmetis__iincset #define libmetis__ikvAllocMatrix SuiteSparse_metis_libmetis__ikvAllocMatrix #define libmetis__ikvcopy SuiteSparse_metis_libmetis__ikvcopy #define libmetis__ikvFreeMatrix SuiteSparse_metis_libmetis__ikvFreeMatrix #define libmetis__ikvmalloc SuiteSparse_metis_libmetis__ikvmalloc #define libmetis__ikvrealloc SuiteSparse_metis_libmetis__ikvrealloc #define libmetis__ikvset SuiteSparse_metis_libmetis__ikvset #define libmetis__ikvSetMatrix SuiteSparse_metis_libmetis__ikvSetMatrix #define libmetis__ikvsmalloc SuiteSparse_metis_libmetis__ikvsmalloc #define libmetis__ikvsortd SuiteSparse_metis_libmetis__ikvsortd #define libmetis__ikvsorti SuiteSparse_metis_libmetis__ikvsorti #define libmetis__ikvsortii SuiteSparse_metis_libmetis__ikvsortii #define libmetis__ikvwspacemalloc SuiteSparse_metis_libmetis__ikvwspacemalloc #define libmetis__imalloc SuiteSparse_metis_libmetis__imalloc #define libmetis__imax SuiteSparse_metis_libmetis__imax #define libmetis__imin SuiteSparse_metis_libmetis__imin #define libmetis__InduceRowPartFromColumnPart SuiteSparse_metis_libmetis__InduceRowPartFromColumnPart #define libmetis__Init2WayPartition SuiteSparse_metis_libmetis__Init2WayPartition #define libmetis__InitGraph SuiteSparse_metis_libmetis__InitGraph #define libmetis__InitKWayPartitioning SuiteSparse_metis_libmetis__InitKWayPartitioning #define libmetis__InitMesh SuiteSparse_metis_libmetis__InitMesh #define libmetis__InitRandom SuiteSparse_metis_libmetis__InitRandom #define libmetis__InitSeparator SuiteSparse_metis_libmetis__InitSeparator #define libmetis__InitTimers SuiteSparse_metis_libmetis__InitTimers #define libmetis__inorm2 SuiteSparse_metis_libmetis__inorm2 #define libmetis__ipqCheckHeap SuiteSparse_metis_libmetis__ipqCheckHeap #define libmetis__ipqCreate SuiteSparse_metis_libmetis__ipqCreate #define libmetis__ipqDelete SuiteSparse_metis_libmetis__ipqDelete #define libmetis__ipqDestroy SuiteSparse_metis_libmetis__ipqDestroy #define libmetis__ipqFree SuiteSparse_metis_libmetis__ipqFree #define libmetis__ipqGetTop SuiteSparse_metis_libmetis__ipqGetTop #define libmetis__ipqInit SuiteSparse_metis_libmetis__ipqInit #define libmetis__ipqInsert SuiteSparse_metis_libmetis__ipqInsert #define libmetis__ipqLength SuiteSparse_metis_libmetis__ipqLength #define libmetis__ipqReset SuiteSparse_metis_libmetis__ipqReset #define libmetis__ipqSeeKey SuiteSparse_metis_libmetis__ipqSeeKey #define libmetis__ipqSeeTopKey SuiteSparse_metis_libmetis__ipqSeeTopKey #define libmetis__ipqSeeTopVal SuiteSparse_metis_libmetis__ipqSeeTopVal #define libmetis__ipqUpdate SuiteSparse_metis_libmetis__ipqUpdate #define libmetis__irand SuiteSparse_metis_libmetis__irand #define libmetis__irandArrayPermute SuiteSparse_metis_libmetis__irandArrayPermute #define libmetis__irandArrayPermuteFine SuiteSparse_metis_libmetis__irandArrayPermuteFine #define libmetis__irandInRange SuiteSparse_metis_libmetis__irandInRange #define libmetis__irealloc SuiteSparse_metis_libmetis__irealloc #define libmetis__IsArticulationNode SuiteSparse_metis_libmetis__IsArticulationNode #define libmetis__IsBalanced SuiteSparse_metis_libmetis__IsBalanced #define libmetis__iscale SuiteSparse_metis_libmetis__iscale #define libmetis__IsConnected SuiteSparse_metis_libmetis__IsConnected #define libmetis__IsConnectedSubdomain SuiteSparse_metis_libmetis__IsConnectedSubdomain #define libmetis__iset SuiteSparse_metis_libmetis__iset #define libmetis__iSetMatrix SuiteSparse_metis_libmetis__iSetMatrix #define libmetis__ismalloc SuiteSparse_metis_libmetis__ismalloc #define libmetis__isortd SuiteSparse_metis_libmetis__isortd #define libmetis__isorti SuiteSparse_metis_libmetis__isorti #define libmetis__isrand SuiteSparse_metis_libmetis__isrand #define libmetis__IsSeparable SuiteSparse_metis_libmetis__IsSeparable #define libmetis__isum SuiteSparse_metis_libmetis__isum #define libmetis__ivecaxpygez SuiteSparse_metis_libmetis__ivecaxpygez #define libmetis__ivecaxpylez SuiteSparse_metis_libmetis__ivecaxpylez #define libmetis__ivecge SuiteSparse_metis_libmetis__ivecge #define libmetis__ivecle SuiteSparse_metis_libmetis__ivecle #define libmetis__iwspacemalloc SuiteSparse_metis_libmetis__iwspacemalloc #define libmetis__KWayVolUpdate SuiteSparse_metis_libmetis__KWayVolUpdate #define libmetis__Match_2Hop SuiteSparse_metis_libmetis__Match_2Hop #define libmetis__Match_2HopAll SuiteSparse_metis_libmetis__Match_2HopAll #define libmetis__Match_2HopAny SuiteSparse_metis_libmetis__Match_2HopAny #define libmetis__Match_RM SuiteSparse_metis_libmetis__Match_RM #define libmetis__Match_SHEM SuiteSparse_metis_libmetis__Match_SHEM #define libmetis__McGeneral2WayBalance SuiteSparse_metis_libmetis__McGeneral2WayBalance #define libmetis__McGrowBisection SuiteSparse_metis_libmetis__McGrowBisection #define libmetis__McRandomBisection SuiteSparse_metis_libmetis__McRandomBisection #define libmetis__metis_rcode SuiteSparse_metis_libmetis__metis_rcode #define libmetis__MinCover SuiteSparse_metis_libmetis__MinCover #define libmetis__MinCover_Augment SuiteSparse_metis_libmetis__MinCover_Augment #define libmetis__MinCover_ColDFS SuiteSparse_metis_libmetis__MinCover_ColDFS #define libmetis__MinCover_Decompose SuiteSparse_metis_libmetis__MinCover_Decompose #define libmetis__MinCover_RowDFS SuiteSparse_metis_libmetis__MinCover_RowDFS #define libmetis__MlevelKWayPartitioning SuiteSparse_metis_libmetis__MlevelKWayPartitioning #define libmetis__MlevelNestedDissection SuiteSparse_metis_libmetis__MlevelNestedDissection #define libmetis__MlevelNestedDissectionCC SuiteSparse_metis_libmetis__MlevelNestedDissectionCC #define libmetis__MlevelNestedDissectionP SuiteSparse_metis_libmetis__MlevelNestedDissectionP #define libmetis__MlevelNodeBisectionL1 SuiteSparse_metis_libmetis__MlevelNodeBisectionL1 #define libmetis__MlevelNodeBisectionL2 SuiteSparse_metis_libmetis__MlevelNodeBisectionL2 #define libmetis__MlevelNodeBisectionMultiple SuiteSparse_metis_libmetis__MlevelNodeBisectionMultiple #define libmetis__MlevelRecursiveBisection SuiteSparse_metis_libmetis__MlevelRecursiveBisection #define libmetis__mmdelm SuiteSparse_metis_libmetis__mmdelm #define libmetis__mmdint SuiteSparse_metis_libmetis__mmdint #define libmetis__mmdnum SuiteSparse_metis_libmetis__mmdnum #define libmetis__MMDOrder SuiteSparse_metis_libmetis__MMDOrder #define libmetis__mmdupd SuiteSparse_metis_libmetis__mmdupd #define libmetis__MoveGroupContigForCut SuiteSparse_metis_libmetis__MoveGroupContigForCut #define libmetis__MoveGroupContigForVol SuiteSparse_metis_libmetis__MoveGroupContigForVol #define libmetis__MoveGroupMinConnForCut SuiteSparse_metis_libmetis__MoveGroupMinConnForCut #define libmetis__MoveGroupMinConnForVol SuiteSparse_metis_libmetis__MoveGroupMinConnForVol #define libmetis__MultilevelBisect SuiteSparse_metis_libmetis__MultilevelBisect #define libmetis__Print2WayRefineStats SuiteSparse_metis_libmetis__Print2WayRefineStats #define libmetis__PrintCGraphStats SuiteSparse_metis_libmetis__PrintCGraphStats #define libmetis__PrintCtrl SuiteSparse_metis_libmetis__PrintCtrl #define libmetis__PrintSubDomainGraph SuiteSparse_metis_libmetis__PrintSubDomainGraph #define libmetis__PrintTimers SuiteSparse_metis_libmetis__PrintTimers #define libmetis__Project2WayNodePartition SuiteSparse_metis_libmetis__Project2WayNodePartition #define libmetis__Project2WayPartition SuiteSparse_metis_libmetis__Project2WayPartition #define libmetis__ProjectKWayPartition SuiteSparse_metis_libmetis__ProjectKWayPartition #define libmetis__PruneGraph SuiteSparse_metis_libmetis__PruneGraph #define libmetis__rAllocMatrix SuiteSparse_metis_libmetis__rAllocMatrix #define libmetis__RandomBisection SuiteSparse_metis_libmetis__RandomBisection #define libmetis__rargmax SuiteSparse_metis_libmetis__rargmax #define libmetis__rargmax2 SuiteSparse_metis_libmetis__rargmax2 #define libmetis__rargmax_n SuiteSparse_metis_libmetis__rargmax_n #define libmetis__rargmin SuiteSparse_metis_libmetis__rargmin #define libmetis__raxpy SuiteSparse_metis_libmetis__raxpy #define libmetis__rcopy SuiteSparse_metis_libmetis__rcopy #define libmetis__rdot SuiteSparse_metis_libmetis__rdot #define libmetis__ReAdjustMemory SuiteSparse_metis_libmetis__ReAdjustMemory #define libmetis__Refine2Way SuiteSparse_metis_libmetis__Refine2Way #define libmetis__Refine2WayNode SuiteSparse_metis_libmetis__Refine2WayNode #define libmetis__RefineKWay SuiteSparse_metis_libmetis__RefineKWay #define libmetis__rFreeMatrix SuiteSparse_metis_libmetis__rFreeMatrix #define libmetis__rincset SuiteSparse_metis_libmetis__rincset #define libmetis__rkvAllocMatrix SuiteSparse_metis_libmetis__rkvAllocMatrix #define libmetis__rkvcopy SuiteSparse_metis_libmetis__rkvcopy #define libmetis__rkvFreeMatrix SuiteSparse_metis_libmetis__rkvFreeMatrix #define libmetis__rkvmalloc SuiteSparse_metis_libmetis__rkvmalloc #define libmetis__rkvrealloc SuiteSparse_metis_libmetis__rkvrealloc #define libmetis__rkvset SuiteSparse_metis_libmetis__rkvset #define libmetis__rkvSetMatrix SuiteSparse_metis_libmetis__rkvSetMatrix #define libmetis__rkvsmalloc SuiteSparse_metis_libmetis__rkvsmalloc #define libmetis__rkvsortd SuiteSparse_metis_libmetis__rkvsortd #define libmetis__rkvsorti SuiteSparse_metis_libmetis__rkvsorti #define libmetis__rmalloc SuiteSparse_metis_libmetis__rmalloc #define libmetis__rmax SuiteSparse_metis_libmetis__rmax #define libmetis__rmin SuiteSparse_metis_libmetis__rmin #define libmetis__rnorm2 SuiteSparse_metis_libmetis__rnorm2 #define libmetis__rpqCheckHeap SuiteSparse_metis_libmetis__rpqCheckHeap #define libmetis__rpqCreate SuiteSparse_metis_libmetis__rpqCreate #define libmetis__rpqDelete SuiteSparse_metis_libmetis__rpqDelete #define libmetis__rpqDestroy SuiteSparse_metis_libmetis__rpqDestroy #define libmetis__rpqFree SuiteSparse_metis_libmetis__rpqFree #define libmetis__rpqGetTop SuiteSparse_metis_libmetis__rpqGetTop #define libmetis__rpqInit SuiteSparse_metis_libmetis__rpqInit #define libmetis__rpqInsert SuiteSparse_metis_libmetis__rpqInsert #define libmetis__rpqLength SuiteSparse_metis_libmetis__rpqLength #define libmetis__rpqReset SuiteSparse_metis_libmetis__rpqReset #define libmetis__rpqSeeKey SuiteSparse_metis_libmetis__rpqSeeKey #define libmetis__rpqSeeTopKey SuiteSparse_metis_libmetis__rpqSeeTopKey #define libmetis__rpqSeeTopVal SuiteSparse_metis_libmetis__rpqSeeTopVal #define libmetis__rpqUpdate SuiteSparse_metis_libmetis__rpqUpdate #define libmetis__rrealloc SuiteSparse_metis_libmetis__rrealloc #define libmetis__rscale SuiteSparse_metis_libmetis__rscale #define libmetis__rset SuiteSparse_metis_libmetis__rset #define libmetis__rSetMatrix SuiteSparse_metis_libmetis__rSetMatrix #define libmetis__rsmalloc SuiteSparse_metis_libmetis__rsmalloc #define libmetis__rsortd SuiteSparse_metis_libmetis__rsortd #define libmetis__rsorti SuiteSparse_metis_libmetis__rsorti #define libmetis__rsum SuiteSparse_metis_libmetis__rsum #define libmetis__rvecge SuiteSparse_metis_libmetis__rvecge #define libmetis__rvecle SuiteSparse_metis_libmetis__rvecle #define libmetis__rvecmaxdiff SuiteSparse_metis_libmetis__rvecmaxdiff #define libmetis__rvecsumle SuiteSparse_metis_libmetis__rvecsumle #define libmetis__rwspacemalloc SuiteSparse_metis_libmetis__rwspacemalloc #define libmetis__SelectQueue SuiteSparse_metis_libmetis__SelectQueue #define libmetis__Setup2WayBalMultipliers SuiteSparse_metis_libmetis__Setup2WayBalMultipliers #define libmetis__SetupCoarseGraph SuiteSparse_metis_libmetis__SetupCoarseGraph #define libmetis__SetupCtrl SuiteSparse_metis_libmetis__SetupCtrl #define libmetis__SetupGraph SuiteSparse_metis_libmetis__SetupGraph #define libmetis__SetupGraph_label SuiteSparse_metis_libmetis__SetupGraph_label #define libmetis__SetupGraph_tvwgt SuiteSparse_metis_libmetis__SetupGraph_tvwgt #define libmetis__SetupKWayBalMultipliers SuiteSparse_metis_libmetis__SetupKWayBalMultipliers #define libmetis__SetupSplitGraph SuiteSparse_metis_libmetis__SetupSplitGraph #define libmetis__SplitGraphOrder SuiteSparse_metis_libmetis__SplitGraphOrder #define libmetis__SplitGraphOrderCC SuiteSparse_metis_libmetis__SplitGraphOrderCC #define libmetis__SplitGraphPart SuiteSparse_metis_libmetis__SplitGraphPart #define libmetis__UpdateEdgeSubDomainGraph SuiteSparse_metis_libmetis__UpdateEdgeSubDomainGraph #define libmetis__uvwsorti SuiteSparse_metis_libmetis__uvwsorti #define libmetis__vnbrpoolGetNext SuiteSparse_metis_libmetis__vnbrpoolGetNext #define libmetis__vnbrpoolReset SuiteSparse_metis_libmetis__vnbrpoolReset #define libmetis__wspacemalloc SuiteSparse_metis_libmetis__wspacemalloc #define libmetis__wspacepop SuiteSparse_metis_libmetis__wspacepop #define libmetis__wspacepush SuiteSparse_metis_libmetis__wspacepush #define METIS_ComputeVertexSeparator SuiteSparse_metis_METIS_ComputeVertexSeparator #define METIS_Free SuiteSparse_metis_METIS_Free #define METIS_MeshToDual SuiteSparse_metis_METIS_MeshToDual #define METIS_MeshToNodal SuiteSparse_metis_METIS_MeshToNodal #define METIS_NodeND SuiteSparse_metis_METIS_NodeND #define METIS_NodeNDP SuiteSparse_metis_METIS_NodeNDP #define METIS_NodeRefine SuiteSparse_metis_METIS_NodeRefine #define METIS_PartGraphKway SuiteSparse_metis_METIS_PartGraphKway #define METIS_PartGraphRecursive SuiteSparse_metis_METIS_PartGraphRecursive #define METIS_PartMeshDual SuiteSparse_metis_METIS_PartMeshDual #define METIS_PartMeshNodal SuiteSparse_metis_METIS_PartMeshNodal #define METIS_SetDefaultOptions SuiteSparse_metis_METIS_SetDefaultOptions #define PrintBackTrace SuiteSparse_metis_PrintBackTrace #include "SuiteSparse_metis/GKlib/GKlib.h" #include "SuiteSparse_metis/include/metis.h" #if (IDXTYPEWIDTH != 64) #error "SuiteSparse requires the 64-bit version of METIS 5.1.0 (with IDXTYPEWIDTH set to 64)" #endif #endif Matrix/src/SuiteSparse/CHOLMOD/Partition/cholmod_l_metis.c0000644000175100001440000000103014552026002023123 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Partition/cholmod_l_metis.c: int64_t version of cholmod_metis //------------------------------------------------------------------------------ // CHOLMOD/Partition Module. Copyright (C) 2005-2023, University of Florida. // All Rights Reserved. Author: Timothy A. Davis. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_metis.c" Matrix/src/SuiteSparse/CHOLMOD/Partition/cholmod_l_ccolamd.c0000644000175100001440000000103614552026002023412 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Partition/cholmod_l_ccolamd.c: int64_t version of cholmod_ccolamd //------------------------------------------------------------------------------ // CHOLMOD/Partition Module. Copyright (C) 2005-2023, University of Florida. // All Rights Reserved. Author: Timothy A. Davis. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_ccolamd.c" Matrix/src/SuiteSparse/CHOLMOD/Partition/cholmod_ccolamd.c0000644000175100001440000001470214552026002023103 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Partition/cholmod_ccolamd: CHOLMOD interface to CCOLAMD //------------------------------------------------------------------------------ // CHOLMOD/Partition Module. Copyright (C) 2005-2023, University of Florida. // All Rights Reserved. Author: Timothy A. Davis. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // CHOLMOD interface to the CCOLAMD ordering routine. Finds a permutation // p such that the Cholesky factorization of PAA'P' is sparser than AA'. // The column etree is found and postordered, and the ccolamd ordering is then // combined with its postordering. A must be unsymmetric. // // workspace: Iwork (MAX (nrow,ncol)) // Allocates a copy of its input matrix, which is // then used as CCOLAMD's workspace. // // Supports any xtype (pattern, real, complex, or zomplex) and any dtype. #include "cholmod_internal.h" #ifndef NCAMD #include "ccolamd.h" #if (CCOLAMD_VERSION < CCOLAMD_VERSION_CODE (3,3)) #error "CHOLMOD:Partition requires CCOLAMD 3.3.1 or later" #endif //------------------------------------------------------------------------------ // ccolamd_interface //------------------------------------------------------------------------------ // Order with ccolamd static int ccolamd_interface ( cholmod_sparse *A, size_t alen, Int *Perm, Int *Cmember, Int *fset, Int fsize, cholmod_sparse *C, cholmod_common *Common ) { double knobs [CCOLAMD_KNOBS] ; Int *Cp = NULL ; Int ok, k, nrow, ncol, stats [CCOLAMD_STATS] ; nrow = A->nrow ; ncol = A->ncol ; //-------------------------------------------------------------------------- // copy (and transpose) the input matrix A into the ccolamd workspace //-------------------------------------------------------------------------- // C = A (:,f)', which also packs A if needed. // workspace: Iwork (nrow if no fset; MAX (nrow,ncol) if fset non-NULL) ok = CHOLMOD(transpose_unsym) (A, 0, NULL, fset, fsize, C, Common) ; //-------------------------------------------------------------------------- // order the matrix (destroys the contents of C->i and C->p) //-------------------------------------------------------------------------- // get parameters #if defined ( CHOLMOD_INT64 ) ccolamd_l_set_defaults (knobs) ; #else ccolamd_set_defaults (knobs) ; #endif if (Common->current < 0 || Common->current >= CHOLMOD_MAXMETHODS) { // this is the CHOLMOD default, not the CCOLAMD default knobs [CCOLAMD_DENSE_ROW] = -1 ; } else { // get the knobs from the Common parameters knobs [CCOLAMD_DENSE_COL] =Common->method[Common->current].prune_dense ; knobs [CCOLAMD_DENSE_ROW] =Common->method[Common->current].prune_dense2; knobs [CCOLAMD_AGGRESSIVE]=Common->method[Common->current].aggressive ; knobs [CCOLAMD_LU] =Common->method[Common->current].order_for_lu; } if (ok) { #if defined ( CHOLMOD_INT64 ) ccolamd_l (ncol, nrow, alen, C->i, C->p, knobs, stats, Cmember) ; #else ccolamd (ncol, nrow, alen, C->i, C->p, knobs, stats, Cmember) ; #endif ok = stats [CCOLAMD_STATUS] ; ok = (ok == CCOLAMD_OK || ok == CCOLAMD_OK_BUT_JUMBLED) ; // permutation returned in C->p, if the ordering succeeded Cp = C->p ; for (k = 0 ; k < nrow ; k++) { Perm [k] = Cp [k] ; } } return (ok) ; } //------------------------------------------------------------------------------ // cholmod_ccolamd //------------------------------------------------------------------------------ // Order AA' or A(:,f)*A(:,f)' using CCOLAMD. int CHOLMOD(ccolamd) ( // input: cholmod_sparse *A, // matrix to order Int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset Int *Cmember, // size A->nrow. Cmember [i] = c if row i is in the // constraint set c. c must be >= 0. The # of // constraint sets is max (Cmember) + 1. If Cmember is // NULL, then it is interpretted as Cmember [i] = 0 for // all i. // output: Int *Perm, // size A->nrow, output permutation cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- cholmod_sparse *C ; Int ok, nrow, ncol ; size_t alen ; RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (Perm, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; if (A->stype != 0) { ERROR (CHOLMOD_INVALID, "matrix must be unsymmetric") ; return (FALSE) ; } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- nrow = A->nrow ; ncol = A->ncol ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- #if defined ( CHOLMOD_INT64 ) alen = ccolamd_l_recommended (A->nzmax, ncol, nrow) ; #else alen = ccolamd_recommended (A->nzmax, ncol, nrow) ; #endif if (alen == 0) { ERROR (CHOLMOD_TOO_LARGE, "matrix invalid or too large") ; return (FALSE) ; } CHOLMOD(allocate_work) (0, MAX (nrow,ncol), 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } C = CHOLMOD(allocate_sparse) (ncol, nrow, alen, TRUE, TRUE, 0, CHOLMOD_PATTERN + A->dtype, Common) ; //-------------------------------------------------------------------------- // order with ccolamd //-------------------------------------------------------------------------- ok = ccolamd_interface (A, alen, Perm, Cmember, fset, fsize, C, Common) ; //-------------------------------------------------------------------------- // free the workspace and return result //-------------------------------------------------------------------------- CHOLMOD(free_sparse) (&C, Common) ; return (ok) ; } #endif Matrix/src/SuiteSparse/CHOLMOD/Partition/cholmod_l_csymamd.c0000644000175100001440000000103614552026002023445 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Partition/cholmod_l_csymamd.c: int64_t version of cholmod_csymamd //------------------------------------------------------------------------------ // CHOLMOD/Partition Module. Copyright (C) 2005-2023, University of Florida. // All Rights Reserved. Author: Timothy A. Davis. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_csymamd.c" Matrix/src/SuiteSparse/CHOLMOD/Partition/cholmod_metis.c0000644000175100001440000007464314552026002022634 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Partition/cholmod_metis: CHOLMOD interface to METIS //------------------------------------------------------------------------------ // CHOLMOD/Partition Module. Copyright (C) 2005-2023, University of Florida. // All Rights Reserved. Author: Timothy A. Davis. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // CHOLMOD interface to the METIS package (Version 5.1.0): // // cholmod_metis_bisector: // // Wrapper for the METIS node separator function, // METIS_ComputeVertexSeparator (METIS 5.1). // // Finds a set of nodes that partitions the graph into two parts. METIS // 4.0 (the function METIS_ComputeVertexSeparator) allowed for edge // weights to be passed to the bisector. This feature is removed in METIS // 5.1. CHOLMOD itself does not rely on this feature (it calls the METIS // bisector with edge weights of all 1s). However, user code can call // cholmod_metis_bisector directly, and pass in edge weights. If you use // METIS 5.1, these edge weights are now ignored; if you pass a non-NULL // entry for edge weights, an error will be returned. // // cholmod_metis: // // Wrapper for METIS_NodeND, METIS's own nested dissection algorithm. // Typically faster than cholmod_nested_dissection, mostly because it // uses minimum degree on just the leaves of the separator tree, rather // than the whole matrix. // // Note that METIS does not return an error if it runs out of memory. Instead, // it terminates the program. This interface attempts to avoid that problem // by preallocating space that should be large enough for any memory allocations // within METIS, and then freeing that space, just before the call to METIS. // While this is not guaranteed to work, it is very unlikely to fail. If you // encounter this problem, increase Common->metis_memory. If you don't mind // having your program terminated, set Common->metis_memory to zero (a value of // 2.0 is usually safe). Several other METIS workarounds are made in the // routines in this file. See the description of metis_memory_ok, just below, // for more details. // // FUTURE WORK: interfaces to other partitioners (CHACO, SCOTCH, JOSTLE, ... ) // // workspace: several size-nz and size-n temporary arrays. Uses no workspace // in Common. // // Supports any xtype (pattern, real, complex, or zomplex) and any dtype. #include "cholmod_internal.h" #ifndef NPARTITION #undef ASSERT #include "cholmod_metis_wrapper.h" #include "SuiteSparse_metis/include/metis.h" #undef ASSERT #ifndef NDEBUG #define ASSERT(expr) assert (expr) #else #define ASSERT(expr) #endif #undef malloc #undef calloc #undef realloc #undef free //------------------------------------------------------------------------------ // test coverage //------------------------------------------------------------------------------ // SuiteSparse_metis has been modified from the original METIS 5.1.0. It uses // the SuiteSparse_config function pointers for malloc/calloc/realloc/free, so // that it can use the same memory manager functions as the rest of // SuiteSparse. However, during test coverage in CHOLMOD/Tcov, the call to // malloc inside SuiteSparse_metis pretends to fail, to test CHOLMOD's memory // handling. This causes METIS to terminate the program. To avoid this, METIS // is allowed to use the standard ANSI C11 malloc/calloc/realloc/free functions // during testing. #ifdef TEST_COVERAGE //-------------------------------------------------------------------------- // CHOLMOD during test coverage in CHOLMOD/Tcov. //-------------------------------------------------------------------------- void *(*save_malloc_func) (size_t) ; // pointer to malloc void *(*save_calloc_func) (size_t, size_t) ; // pointer to calloc void *(*save_realloc_func) (void *, size_t) ; // pointer to realloc void (*save_free_func) (void *) ; // pointer to free #define TEST_COVERAGE_PAUSE \ { \ save_malloc_func = SuiteSparse_config_malloc_func_get ( ) ; \ save_calloc_func = SuiteSparse_config_calloc_func_get ( ) ; \ save_realloc_func = SuiteSparse_config_realloc_func_get ( ) ; \ save_free_func = SuiteSparse_config_free_func_get ( ) ; \ SuiteSparse_config_malloc_func_set (malloc) ; \ SuiteSparse_config_calloc_func_set (calloc) ; \ SuiteSparse_config_realloc_func_set (realloc) ; \ SuiteSparse_config_free_func_set (free) ; \ } #define TEST_COVERAGE_RESUME \ { \ SuiteSparse_config_malloc_func_set (save_malloc_func) ; \ SuiteSparse_config_calloc_func_set (save_calloc_func) ; \ SuiteSparse_config_realloc_func_set (save_realloc_func) ; \ SuiteSparse_config_free_func_set (save_free_func) ; \ } #else //-------------------------------------------------------------------------- // CHOLMOD in production: no change to SuiteSparse_config //-------------------------------------------------------------------------- #define TEST_COVERAGE_PAUSE #define TEST_COVERAGE_RESUME #endif //------------------------------------------------------------------------------ // dumpgraph //------------------------------------------------------------------------------ // For dumping the input graph to METIS_NodeND, to check with METIS's onmetis // and graphchk programs. For debugging only. To use, uncomment this #define: // #define DUMP_GRAPH #ifdef DUMP_GRAPH // After dumping the graph with this routine, run "onmetis metisgraph" static void dumpgraph (idx_t *Mp, idx_t *Mi, int64_t n, cholmod_common *Common) { int64_t i, j, p, nz ; FILE *f ; nz = Mp [n] ; printf ("Dumping METIS graph n %ld nz %ld\n", n, nz) ; // DUMP_GRAPH f = fopen ("metisgraph", "w") ; if (f == NULL) { ERROR (-99, "cannot open metisgraph") ; return ; } fprintf (f, "%ld %ld\n", n, nz/2) ; // DUMP_GRAPH for (j = 0 ; j < n ; j++) { for (p = Mp [j] ; p < Mp [j+1] ; p++) { i = Mi [p] ; fprintf (f, " %ld", i+1) ; // DUMP_GRAPH } fprintf (f, "\n") ; // DUMP_GRAPH } fclose (f) ; } #endif //------------------------------------------------------------------------------ // error handling //------------------------------------------------------------------------------ #define RETURN_IF_METIS_FAILED(metis_result, error) \ { \ if (metis_result != METIS_OK) \ { \ int status = (metis_result == METIS_ERROR_MEMORY) ? \ CHOLMOD_OUT_OF_MEMORY : CHOLMOD_INVALID ; \ ERROR (status, "METIS failed") ; \ return (error) ; \ } \ } //------------------------------------------------------------------------------ // metis_memory_ok //------------------------------------------------------------------------------ // METIS will terminate your program if it runs out of memory. In an attempt // to workaround METIS' behavior, this routine allocates a single block of // memory of size equal to an observed upper bound on METIS' memory usage. It // then immediately deallocates the block. If the allocation fails, METIS is // not called. // // Median memory usage for a graph with n nodes and nz edges (counting each // edge twice, or both upper and lower triangular parts of a matrix) is 4*nz + // 40*n + 4096 integers. A "typical" upper bound is 10*nz + 50*n + 4096 // integers. Nearly all matrices tested fit within that upper bound, with the // exception two in the SuiteSparse matrix collection: Schenk_IBMNA/c-64 and // Gupta/gupta2. The latter exceeds the "upper bound" by a factor of just less // than 2. // // If you do not mind having your program terminated if it runs out of memory, // set Common->metis_memory to zero. Its default value is 2, which allows for // some memory fragmentation, and also accounts for the Gupta/gupta2 matrix. #define GUESS(nz,n) (10 * (nz) + 50 * (n) + 4096) static int metis_memory_ok ( Int n, Int nz, cholmod_common *Common ) { double s ; void *p ; size_t metis_guard ; if (Common->metis_memory <= 0) { // do not prevent METIS from running out of memory return (TRUE) ; } n = MAX (1, n) ; nz = MAX (0, nz) ; // compute in double, to avoid integer overflow s = GUESS ((double) nz, (double) n) ; s *= Common->metis_memory ; if (s * sizeof (idx_t) >= ((double) SIZE_MAX)) { // don't even attempt to malloc such a large block return (FALSE) ; } // recompute in size_t metis_guard = GUESS ((size_t) nz, (size_t) n) ; metis_guard *= Common->metis_memory ; // attempt to malloc the block p = CHOLMOD(malloc) (metis_guard, sizeof (idx_t), Common) ; if (p == NULL) { // failure - return out-of-memory condition return (FALSE) ; } // success - free the block CHOLMOD(free) (metis_guard, sizeof (idx_t), p, Common) ; return (TRUE) ; } #endif //------------------------------------------------------------------------------ // cholmod_metis_bisector //------------------------------------------------------------------------------ // Finds a set of nodes that bisects the graph of A or AA' (direct interface // to METIS_ComputeVertexSeparator. // // The input matrix A must be square, symmetric (with both upper and lower // parts present) and with no diagonal entries. These conditions are NOT // checked. int64_t CHOLMOD(metis_bisector) // returns separator size ( // input: cholmod_sparse *A, // matrix to bisect Int *Anw, // size A->nrow, node weights, can be NULL, // which means the graph is unweighted. Int *Aew, // size nz, edge weights (silently ignored). // This option was available with METIS 4, but not // in METIS 5. This argument is now unused, but // it remains for backward compatibilty, so as not // to change the API for cholmod_metis_bisector. // output: Int *Partition, // size A->nrow cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- #ifndef NPARTITION Int *Ap, *Ai ; idx_t *Mp, *Mi, *Mnw, *Mpart ; Int n, nleft, nright, j, p, csep, total_weight, lightest, nz ; idx_t nn, csp ; DEBUG (Int nsep) ; RETURN_IF_NULL_COMMON (EMPTY) ; RETURN_IF_NULL (A, EMPTY) ; RETURN_IF_NULL (Partition, EMPTY) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, EMPTY) ; if (A->stype || A->nrow != A->ncol) { // A must be square, with both upper and lower parts present ERROR (CHOLMOD_INVALID, "matrix must be square, symmetric," " and with both upper/lower parts present") ; return (EMPTY) ; } Common->status = CHOLMOD_OK ; ASSERT (CHOLMOD(dump_sparse) (A, "A for bisector", Common) >= 0) ; //-------------------------------------------------------------------------- // quick return //-------------------------------------------------------------------------- n = A->nrow ; if (n == 0) { return (0) ; } size_t n1 = A->nrow + 1 ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Ap = A->p ; Ai = A->i ; nz = Ap [n] ; if (Anw != NULL) DEBUG (for (j = 0 ; j < n ; j++) ASSERT (Anw [j] > 0)) ; //-------------------------------------------------------------------------- // copy Int to METIS idx_t, if necessary //-------------------------------------------------------------------------- if (sizeof (Int) == sizeof (idx_t)) { // this is the typical case Mi = (idx_t *) Ai ; Mp = (idx_t *) Ap ; Mnw = (idx_t *) Anw ; Mpart = (idx_t *) Partition ; } else { // idx_t and Int differ; copy the graph into the METIS idx_t Mi = CHOLMOD(malloc) (nz, sizeof (idx_t), Common) ; Mp = CHOLMOD(malloc) (n1, sizeof (idx_t), Common) ; Mnw = Anw ? (CHOLMOD(malloc) (n, sizeof (idx_t), Common)) : NULL ; Mpart = CHOLMOD(malloc) (n, sizeof (idx_t), Common) ; if (Common->status < CHOLMOD_OK) { CHOLMOD(free) (nz, sizeof (idx_t), Mi, Common) ; CHOLMOD(free) (n1, sizeof (idx_t), Mp, Common) ; CHOLMOD(free) (n, sizeof (idx_t), Mnw, Common) ; CHOLMOD(free) (n, sizeof (idx_t), Mpart, Common) ; return (EMPTY) ; } for (p = 0 ; p < nz ; p++) { Mi [p] = (idx_t) Ai [p] ; } for (j = 0 ; j <= n ; j++) { Mp [j] = (idx_t) Ap [j] ; } if (Anw != NULL) { for (j = 0 ; j < n ; j++) { Mnw [j] = (idx_t) Anw [j] ; } } } //-------------------------------------------------------------------------- // METIS workaround: try to ensure METIS doesn't run out of memory //-------------------------------------------------------------------------- if (!metis_memory_ok (n, nz, Common)) { // METIS might ask for too much memory and thus terminate the program if (sizeof (Int) != sizeof (idx_t)) { CHOLMOD(free) (nz, sizeof (idx_t), Mi, Common) ; CHOLMOD(free) (n1, sizeof (idx_t), Mp, Common) ; CHOLMOD(free) (n, sizeof (idx_t), Mnw, Common) ; CHOLMOD(free) (n, sizeof (idx_t), Mpart, Common) ; } return (EMPTY) ; } //-------------------------------------------------------------------------- // partition the graph //-------------------------------------------------------------------------- #ifndef NDEBUG PRINT1 (("Metis graph, n = "ID"\n", n)) ; for (j = 0 ; j < n ; j++) { Int ppp, nodeweight = (Mnw ? Mnw [j] : 1) ; PRINT2 (("M(:,"ID") node weight "ID"\n", j, nodeweight)) ; ASSERT (nodeweight > 0) ; for (ppp = Mp [j] ; ppp < Mp [j+1] ; ppp++) { PRINT3 ((" "ID "\n", (Int) Mi [ppp])) ; ASSERT (Mi [ppp] != j) ; } } #endif // METIS_ComputeVertexSeparator( // idx_t *nvtxs, number of nodes // idx_t *xadj, column pointers // idx_t *adjncy, row indices // idx_t *vwgt, vertex weights (NULL means unweighted) // idx_t *options, options (NULL means defaults) // idx_t *sepsize, separator size // idx_t *part); partition. part [i] = 0,1,2, where: // 0:left, 1:right, 2:separator nn = n ; TEST_COVERAGE_PAUSE ; int metis_result = SuiteSparse_metis_METIS_ComputeVertexSeparator (&nn, Mp, Mi, Mnw, NULL, &csp, Mpart) ; TEST_COVERAGE_RESUME ; csep = csp ; PRINT1 (("METIS csep "ID"\n", csep)) ; //-------------------------------------------------------------------------- // copy the results back from idx_t, if required //-------------------------------------------------------------------------- if (metis_result == METIS_OK && (sizeof (Int) != sizeof (idx_t))) { for (j = 0 ; j < n ; j++) { Partition [j] = Mpart [j] ; } } //-------------------------------------------------------------------------- // free workspace and check for METIS error //-------------------------------------------------------------------------- if (sizeof (Int) != sizeof (idx_t)) { CHOLMOD(free) (nz, sizeof (idx_t), Mi, Common) ; CHOLMOD(free) (n1, sizeof (idx_t), Mp, Common) ; CHOLMOD(free) (n, sizeof (idx_t), Mnw, Common) ; CHOLMOD(free) (n, sizeof (idx_t), Mpart, Common) ; } RETURN_IF_METIS_FAILED (metis_result, EMPTY) ; //-------------------------------------------------------------------------- // ensure a reasonable separator //-------------------------------------------------------------------------- // METIS can return a valid separator with no nodes in (for example) the // left part. In this case, there really is no separator. CHOLMOD // prefers, in this case, for all nodes to be in the separator (and both // left and right parts to be empty). Also, if the graph is unconnected, // METIS can return a valid empty separator. CHOLMOD prefers at least one // node in the separator. Note that cholmod_nested_dissection only calls // this routine on connected components, but cholmod_bisect can call this // routine for any graph. if (csep == 0) { // The separator is empty, select lightest node as separator. If // ties, select the highest numbered node. lightest = n-1 ; if (Anw != NULL) { lightest = 0 ; for (j = 0 ; j < n ; j++) { if (Anw [j] <= Anw [lightest]) { lightest = j ; } } } PRINT1 (("Force "ID" as sep\n", lightest)) ; Partition [lightest] = 2 ; csep = (Anw ? (Anw [lightest]) : 1) ; } // determine the node weights in the left and right part of the graph nleft = 0 ; nright = 0 ; DEBUG (nsep = 0) ; for (j = 0 ; j < n ; j++) { PRINT1 (("Partition ["ID"] = "ID"\n", j, Partition [j])) ; if (Partition [j] == 0) { nleft += (Anw ? (Anw [j]) : 1) ; } else if (Partition [j] == 1) { nright += (Anw ? (Anw [j]) : 1) ; } #ifndef NDEBUG else { ASSERT (Partition [j] == 2) ; nsep += (Anw ? (Anw [j]) : 1) ; } #endif } ASSERT (csep == nsep) ; total_weight = nleft + nright + csep ; if (csep < total_weight) { // The separator is less than the whole graph. Make sure the left and // right parts are either both empty or both non-empty. PRINT1 (("nleft "ID" nright "ID" csep "ID" tot "ID"\n", nleft, nright, csep, total_weight)) ; ASSERT (nleft + nright + csep == total_weight) ; ASSERT (nleft > 0 || nright > 0) ; if ((nleft == 0 && nright > 0) || (nleft > 0 && nright == 0)) { // left or right is empty; put all nodes in the separator PRINT1 (("Force all in sep\n")) ; csep = total_weight ; for (j = 0 ; j < n ; j++) { Partition [j] = 2 ; } } } ASSERT (CHOLMOD(dump_partition) (n, Ap, Ai, Anw, Partition, csep, Common)) ; //-------------------------------------------------------------------------- // return the sum of the weights of nodes in the separator //-------------------------------------------------------------------------- return (csep) ; #else Common->status = CHOLMOD_NOT_INSTALLED ; return (EMPTY) ; #endif } //------------------------------------------------------------------------------ // cholmod_metis //------------------------------------------------------------------------------ // CHOLMOD wrapper for the METIS_NodeND ordering routine. Creates A+A', // A*A' or A(:,f)*A(:,f)' and then calls METIS_NodeND on the resulting graph. // This routine is comparable to cholmod_nested_dissection, except that it // calls METIS_NodeND directly, and it does not return the separator tree. // // workspace: Flag (nrow), Iwork (4*n+uncol) // Allocates a temporary matrix B=A*A' or B=A. int CHOLMOD(metis) ( // input: cholmod_sparse *A, // matrix to order Int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int postorder, // if TRUE, follow with etree or coletree postorder // output: Int *Perm, // size A->nrow, output permutation cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- #ifndef NPARTITION double d ; Int *Iperm, *Iwork, *Bp, *Bi ; idx_t *Mp, *Mi, *Mperm, *Miperm ; cholmod_sparse *B ; Int i, j, n, nz, p, identity ; idx_t nn ; RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (Perm, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // quick return //-------------------------------------------------------------------------- n = A->nrow ; if (n == 0) { return (TRUE) ; } size_t n1 = A->nrow + 1 ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- // s = 4*nrow + uncol size_t uncol = (A->stype == 0) ? A->ncol : 0 ; int ok = TRUE ; size_t s = CHOLMOD(mult_size_t) (A->nrow, 4, &ok) ; s = CHOLMOD(add_size_t) (s, uncol, &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (FALSE) ; } CHOLMOD(allocate_work) (A->nrow, s, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; //-------------------------------------------------------------------------- // convert the matrix to adjacency list form //-------------------------------------------------------------------------- // The input graph for METIS must be symmetric, with both upper and lower // parts present, and with no diagonal entries. The columns need not be // sorted. // B = A+A', A*A', or A(:,f)*A(:,f)', upper and lower parts present if (A->stype) { // Add the upper/lower part to a symmetric lower/upper matrix by // converting to unsymmetric mode // workspace: Iwork (nrow) B = CHOLMOD(copy) (A, 0, -1, Common) ; } else { // B = A*A' or A(:,f)*A(:,f)', no diagonal // workspace: Flag (nrow), Iwork (max (nrow,ncol)) B = CHOLMOD(aat) (A, fset, fsize, -1, Common) ; } ASSERT (CHOLMOD(dump_sparse) (B, "B for NodeND", Common) >= 0) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } ASSERT (B->nrow == A->nrow) ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Iwork = Common->Iwork ; Iperm = Iwork ; // size n Bp = B->p ; Bi = B->i ; nz = Bp [n] ; // B does not include the diagonal, and both upper and lower parts. // Common->anz includes the diagonal, and just the lower part of B Common->anz = nz / 2 + n ; //-------------------------------------------------------------------------- // allocate the METIS input arrays, if needed //-------------------------------------------------------------------------- if (sizeof (Int) == sizeof (idx_t)) { // This is the typical case. Miperm = (idx_t *) Iperm ; Mperm = (idx_t *) Perm ; Mp = (idx_t *) Bp ; Mi = (idx_t *) Bi ; } else { // allocate graph for METIS only if Int and idx_t differ Miperm = CHOLMOD(malloc) (n, sizeof (idx_t), Common) ; Mperm = CHOLMOD(malloc) (n, sizeof (idx_t), Common) ; Mp = CHOLMOD(malloc) (n1, sizeof (idx_t), Common) ; Mi = CHOLMOD(malloc) (nz, sizeof (idx_t), Common) ; if (Common->status < CHOLMOD_OK) { // out of memory CHOLMOD(free_sparse) (&B, Common) ; CHOLMOD(free) (n, sizeof (idx_t), Miperm, Common) ; CHOLMOD(free) (n, sizeof (idx_t), Mperm, Common) ; CHOLMOD(free) (n1, sizeof (idx_t), Mp, Common) ; CHOLMOD(free) (nz, sizeof (idx_t), Mi, Common) ; return (FALSE) ; } for (j = 0 ; j <= n ; j++) { Mp [j] = Bp [j] ; } for (p = 0 ; p < nz ; p++) { Mi [p] = Bi [p] ; } } //-------------------------------------------------------------------------- // METIS workarounds //-------------------------------------------------------------------------- identity = FALSE ; if (nz == 0) { // The matrix has no off-diagonal entries. METIS_NodeND fails in this // case, so avoid using it. The best permutation is identity anyway, // so this is an easy fix. identity = TRUE ; PRINT1 (("METIS:: no nz\n")) ; } else if (Common->metis_nswitch > 0) { // METIS_NodeND in METIS 4.0.1 gives a seg fault with one matrix of // order n = 3005 and nz = 6,036,025, including the diagonal entries. // The workaround is to return the identity permutation instead of // using METIS for matrices of dimension 3000 or more and with density // of 66% or more - admittedly an uncertain fix, but such matrices are // so dense that any reasonable ordering will do, even identity (n^2 is // only 50% higher than nz in this case). CHOLMOD's nested dissection // method (cholmod_nested_dissection) has no problems with the same // matrix, even though it too uses METIS_ComputeVertexSeparator. The // matrix is derived from LPnetlib/lpi_cplex1 in the SuiteSparse matrix // collection. If C is the lpi_cplex matrix (of order 3005-by-5224), A // = (C*C')^2 results in the seg fault. The seg fault also occurs in // the stand- alone onmetis program that comes with METIS. If a future // version of METIS fixes this problem, then set Common->metis_nswitch // to zero. d = ((double) nz) / (((double) n) * ((double) n)) ; if (n > (Int) (Common->metis_nswitch) && d > Common->metis_dswitch) { identity = TRUE ; PRINT1 (("METIS:: nswitch/dswitch activated\n")) ; } } if (!identity && !metis_memory_ok (n, nz, Common)) { // METIS might ask for too much memory and thus terminate the program identity = TRUE ; } //-------------------------------------------------------------------------- // find the permutation //-------------------------------------------------------------------------- int metis_result = METIS_OK ; if (identity) { // no need to do the postorder postorder = FALSE ; for (i = 0 ; i < n ; i++) { Mperm [i] = i ; } } else { #ifdef DUMP_GRAPH printf ("Calling METIS_NodeND n "ID" nz "ID" density " // DUMP_GRAPH "%g\n", n, nz, ((double) nz) / (((double) n) * ((double) n))) ; dumpgraph (Mp, Mi, n, Common) ; #endif // int METIS_NodeND( // idx_t *nvtxs, number of nodes // idx_t *xadj, column pointers // idx_t *adjncy, row indices // idx_t *vwgt, vertex weights (NULL means unweighted) // idx_t *options, options (NULL means defaults) // idx_t *perm, fill-reducing ordering // idx_t *iperm); inverse of perm nn = n ; TEST_COVERAGE_PAUSE ; metis_result = SuiteSparse_metis_METIS_NodeND (&nn, Mp, Mi, NULL, NULL, Mperm, Miperm) ; TEST_COVERAGE_RESUME ; PRINT0 (("METIS_NodeND done\n")) ; } //-------------------------------------------------------------------------- // free workspace and check for METIS error //-------------------------------------------------------------------------- if (sizeof (Int) != sizeof (idx_t)) { for (i = 0 ; i < n ; i++) { Perm [i] = (Int) (Mperm [i]) ; } CHOLMOD(free) (n, sizeof (idx_t), Miperm, Common) ; CHOLMOD(free) (n, sizeof (idx_t), Mperm, Common) ; CHOLMOD(free) (n+1, sizeof (idx_t), Mp, Common) ; CHOLMOD(free) (nz, sizeof (idx_t), Mi, Common) ; } CHOLMOD(free_sparse) (&B, Common) ; RETURN_IF_METIS_FAILED (metis_result, false) ; //-------------------------------------------------------------------------- // etree or column-etree postordering, using the Cholesky Module //-------------------------------------------------------------------------- if (postorder) { Int *Parent, *Post, *NewPerm ; Int k ; Parent = Iwork + 2*((size_t) n) + uncol ; // size n = nrow Post = Parent + n ; // size n // workspace: Iwork (2*nrow+uncol), Flag (nrow), Head (nrow+1) CHOLMOD(analyze_ordering) (A, CHOLMOD_METIS, Perm, fset, fsize, Parent, Post, NULL, NULL, NULL, Common) ; if (Common->status == CHOLMOD_OK) { // combine the METIS permutation with its postordering NewPerm = Parent ; // use Parent as workspace for (k = 0 ; k < n ; k++) { NewPerm [k] = Perm [Post [k]] ; } for (k = 0 ; k < n ; k++) { Perm [k] = NewPerm [k] ; } } } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; PRINT1 (("cholmod_metis done\n")) ; return (Common->status == CHOLMOD_OK) ; #else Common->status = CHOLMOD_NOT_INSTALLED ; return (false) ; #endif } Matrix/src/SuiteSparse/CHOLMOD/Partition/cholmod_metis_wrapper.c0000644000175100001440000000760214552026002024363 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Partition/cholmod_metis_wrapper: METIS functions embedded in CHOLMOD //------------------------------------------------------------------------------ // CHOLMOD/Partition Module. Copyright (C) 2005-2023, University of Florida. // All Rights Reserved. Author: Timothy A. Davis. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #include "cholmod_internal.h" #undef ASSERT #ifndef NPARTITION //------------------------------------------------------------------------------ // redefine the METIS name space and include all METIS source files needed //------------------------------------------------------------------------------ #include "cholmod_metis_wrapper.h" #include "SuiteSparse_metis/GKlib/blas.c" #include "SuiteSparse_metis/GKlib/error.c" #include "SuiteSparse_metis/GKlib/evaluate.c" #include "SuiteSparse_metis/GKlib/fkvkselect.c" #include "SuiteSparse_metis/GKlib/mcore.c" #include "SuiteSparse_metis/GKlib/memory.c" #include "SuiteSparse_metis/GKlib/omp.c" #include "SuiteSparse_metis/GKlib/random.c" #include "SuiteSparse_metis/GKlib/sort.c" #include "SuiteSparse_metis/GKlib/util.c" // unused by CHOLMOD: // #include "SuiteSparse_metis/GKlib/timers.c" // replace the timer functions from timers.c: double gk_WClockSeconds(void) { return (0) ; } double gk_CPUSeconds(void) { return (0) ; } // #include "SuiteSparse_metis/GKlib/fs.c" // #include "SuiteSparse_metis/GKlib/getopt.c" // #include "SuiteSparse_metis/GKlib/gkregex.c" // #include "SuiteSparse_metis/GKlib/io.c" // #include "SuiteSparse_metis/GKlib/pdb.c" // #include "SuiteSparse_metis/GKlib/rw.c" // #include "SuiteSparse_metis/GKlib/seq.c" // #include "SuiteSparse_metis/GKlib/tokenizer.c" // #include "SuiteSparse_metis/GKlib/string.c" // #include "SuiteSparse_metis/GKlib/pqueue.c" // #include "SuiteSparse_metis/GKlib/csr.c" // #include "SuiteSparse_metis/GKlib/graph.c" // #include "SuiteSparse_metis/GKlib/itemsets.c" // #include "SuiteSparse_metis/GKlib/b64.c" // #include "SuiteSparse_metis/GKlib/htable.c" // for parmetis.c: replace abs with 64-bit version #define abs SuiteSparse_metis_abs64 #include "SuiteSparse_metis/libmetis/auxapi.c" #include "SuiteSparse_metis/libmetis/balance.c" #include "SuiteSparse_metis/libmetis/bucketsort.c" #include "SuiteSparse_metis/libmetis/coarsen.c" #include "SuiteSparse_metis/libmetis/compress.c" #include "SuiteSparse_metis/libmetis/contig.c" #include "SuiteSparse_metis/libmetis/debug.c" #include "SuiteSparse_metis/libmetis/fm.c" #include "SuiteSparse_metis/libmetis/fortran.c" #include "SuiteSparse_metis/libmetis/gklib.c" #include "SuiteSparse_metis/libmetis/graph.c" #include "SuiteSparse_metis/libmetis/initpart.c" #include "SuiteSparse_metis/libmetis/kmetis.c" #include "SuiteSparse_metis/libmetis/kwayfm.c" #include "SuiteSparse_metis/libmetis/kwayrefine.c" #include "SuiteSparse_metis/libmetis/mcutil.c" #include "SuiteSparse_metis/libmetis/minconn.c" #include "SuiteSparse_metis/libmetis/mincover.c" #include "SuiteSparse_metis/libmetis/mmd.c" #include "SuiteSparse_metis/libmetis/ometis.c" #include "SuiteSparse_metis/libmetis/options.c" #include "SuiteSparse_metis/libmetis/parmetis.c" #include "SuiteSparse_metis/libmetis/pmetis.c" #include "SuiteSparse_metis/libmetis/refine.c" #include "SuiteSparse_metis/libmetis/separator.c" #include "SuiteSparse_metis/libmetis/sfm.c" #include "SuiteSparse_metis/libmetis/srefine.c" #include "SuiteSparse_metis/libmetis/stat.c" #include "SuiteSparse_metis/libmetis/timing.c" #include "SuiteSparse_metis/libmetis/util.c" #include "SuiteSparse_metis/libmetis/wspace.c" // unused by CHOLMOD: #ifndef NDEBUG #include "SuiteSparse_metis/libmetis/checkgraph.c" #endif // #include "SuiteSparse_metis/libmetis/frename.c" // #include "SuiteSparse_metis/libmetis/mesh.c" // #include "SuiteSparse_metis/libmetis/meshpart.c" #endif Matrix/src/SuiteSparse/CHOLMOD/Partition/cholmod_csymamd.c0000644000175100001440000001113214552026002023130 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Partition/cholmod_csymamd: CHOLMOD interface to CSYMAMD //------------------------------------------------------------------------------ // CHOLMOD/Partition Module. Copyright (C) 2005-2023, University of Florida. // All Rights Reserved. Author: Timothy A. Davis. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // CHOLMOD interface to the CSYMAMD ordering routine. Finds a permutation // p such that the Cholesky factorization of PAP' is sparser than A. // The column etree is found and postordered, and the CSYMAMD // ordering is then combined with its postordering. If A is unsymmetric, // A+A' is ordered (A must be square). // // workspace: Head (nrow+1) // // Supports any xtype (pattern, real, complex, or zomplex) and any dtype. #include "cholmod_internal.h" #ifndef NCAMD #include "ccolamd.h" #if (CCOLAMD_VERSION < CCOLAMD_VERSION_CODE (3,3)) #error "CHOLMOD:Partition requires CCOLAMD 3.3.1 or later" #endif //------------------------------------------------------------------------------ // cholmod_csymamd //------------------------------------------------------------------------------ int CHOLMOD(csymamd) ( // input: cholmod_sparse *A, // matrix to order // output: Int *Cmember, // size nrow. see cholmod_ccolamd.c for description Int *Perm, // size A->nrow, output permutation cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- double knobs [CCOLAMD_KNOBS] ; Int *perm, *Head ; Int ok, i, nrow, stats [CCOLAMD_STATS] ; RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (Perm, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; Common->status = CHOLMOD_OK ; if (A->nrow != A->ncol || !(A->packed)) { ERROR (CHOLMOD_INVALID, "matrix must be square and packed") ; return (FALSE) ; } //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- nrow = A->nrow ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- CHOLMOD(allocate_work) (nrow, 0, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } //-------------------------------------------------------------------------- // order the matrix (does not affect A->p or A->i) //-------------------------------------------------------------------------- perm = Common->Head ; // size nrow+1 // get parameters #if defined ( CHOLMOD_INT64 ) ccolamd_l_set_defaults (knobs) ; #else ccolamd_set_defaults (knobs) ; #endif if (Common->current >= 0 && Common->current < CHOLMOD_MAXMETHODS) { // get the knobs from the Common parameters knobs [CCOLAMD_DENSE_ROW] =Common->method[Common->current].prune_dense ; knobs [CCOLAMD_AGGRESSIVE]=Common->method[Common->current].aggressive ; } { void * (*calloc_func) (size_t, size_t) ; void (*free_func) (void *) ; calloc_func = SuiteSparse_config_calloc_func_get ( ) ; free_func = SuiteSparse_config_free_func_get ( ) ; #if defined ( CHOLMOD_INT64 ) csymamd_l (nrow, A->i, A->p, perm, knobs, stats, calloc_func, free_func, Cmember, A->stype) ; #else csymamd (nrow, A->i, A->p, perm, knobs, stats, calloc_func, free_func, Cmember, A->stype) ; #endif ok = stats [CCOLAMD_STATUS] ; } if (ok == CCOLAMD_ERROR_out_of_memory) { ERROR (CHOLMOD_OUT_OF_MEMORY, "out of memory") ; } ok = (ok == CCOLAMD_OK || ok == CCOLAMD_OK_BUT_JUMBLED) ; //-------------------------------------------------------------------------- // free the workspace and return result //-------------------------------------------------------------------------- // permutation returned in perm [0..n-1] for (i = 0 ; i < nrow ; i++) { Perm [i] = perm [i] ; } // clear Head workspace (used for perm, in csymamd): Head = Common->Head ; for (i = 0 ; i <= nrow ; i++) { Head [i] = EMPTY ; } return (ok) ; } #endif Matrix/src/SuiteSparse/CHOLMOD/Partition/cholmod_camd.c0000644000175100001440000001615614552026002022412 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Partition/cholmod_camd: CHOLMOD interface to CAMD //------------------------------------------------------------------------------ // CHOLMOD/Partition Module. Copyright (C) 2005-2023, University of Florida. // All Rights Reserved. Author: Timothy A. Davis. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // CHOLMOD interface to the CAMD ordering routine. Orders A if the matrix is // symmetric. On output, Perm [k] = i if row/column i of A is the kth // row/column of P*A*P'. This corresponds to A(p,p) in MATLAB notation. // // If A is unsymmetric, cholmod_camd orders A*A'. On output, Perm [k] = i if // row/column i of A*A' is the kth row/column of P*A*A'*P'. This corresponds to // A(p,:)*A(p,:)' in MATLAB notation. If f is present, A(p,f)*A(p,f)' is // ordered. // // Computes the flop count for a subsequent LL' factorization, the number // of nonzeros in L, and the number of nonzeros in the matrix ordered (A, // A*A' or A(:,f)*A(:,f)'). // // workspace: Iwork (4*nrow). Head (nrow). // // Allocates a temporary copy of A+A' or A*A' (with // both upper and lower triangular parts) as input to CAMD. // Also allocates 3*(n+1) additional integer workspace (not in Common). // // Supports any xtype (pattern, real, complex, or zomplex) and any dtype. #include "cholmod_internal.h" #ifndef NCAMD #include "camd.h" #if (CAMD_VERSION < CAMD_VERSION_CODE (3,3)) #error "CHOLMOD:Partition requires CAMD 3.3.1 or later" #endif //------------------------------------------------------------------------------ // cholmod_camd //------------------------------------------------------------------------------ int CHOLMOD(camd) ( // input: cholmod_sparse *A, // matrix to order Int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset Int *Cmember, // size nrow. see cholmod_ccolamd.c for description. // output: Int *Perm, // size A->nrow, output permutation cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- double Info [CAMD_INFO], Control2 [CAMD_CONTROL], *Control ; Int *Cp, *Len, *Nv, *Head, *Elen, *Degree, *Wi, *Next, *BucketSet, *Work3n, *p ; cholmod_sparse *C ; Int j, n, cnz ; RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; n = A->nrow ; // s = 4*nrow int ok = TRUE ; size_t s = CHOLMOD(mult_size_t) (A->nrow, 4, &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (FALSE) ; } RETURN_IF_NULL (Perm, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; Common->status = CHOLMOD_OK ; if (n == 0) { // nothing to do Common->fl = 0 ; Common->lnz = 0 ; Common->anz = 0 ; return (TRUE) ; } //-------------------------------------------------------------------------- // get workspace //-------------------------------------------------------------------------- // cholmod_analyze has allocated Cmember at Common->Iwork + 5*n+uncol, and // CParent at Common->Iwork + 4*n+uncol, where uncol is 0 if A is symmetric // or A->ncol otherwise. Thus, only the first 4n integers in Common->Iwork // can be used here. CHOLMOD(allocate_work) (A->nrow, s, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } p = Common->Iwork ; Degree = p ; p += n ; // size n Elen = p ; p += n ; // size n Len = p ; p += n ; // size n Nv = p ; p += n ; // size n Work3n = CHOLMOD(malloc) (n+1, 3*sizeof (Int), Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } p = Work3n ; Next = p ; p += n ; // size n Wi = p ; p += (n+1) ; // size n+1 BucketSet = p ; // size n Head = Common->Head ; // size n+1 //-------------------------------------------------------------------------- // construct the input matrix for CAMD //-------------------------------------------------------------------------- if (A->stype == 0) { // C = A*A' or A(:,f)*A(:,f)', add extra space of nnz(C)/2+n to C C = CHOLMOD(aat) (A, fset, fsize, -2, Common) ; } else { // C = A+A', but use only the upper triangular part of A if A->stype = 1 // and only the lower part of A if A->stype = -1. Add extra space of // nnz(C)/2+n to C. C = CHOLMOD(copy) (A, 0, -2, Common) ; } if (Common->status < CHOLMOD_OK) { // out of memory, fset invalid, or other error CHOLMOD(free) (n+1, 3*sizeof (Int), Work3n, Common) ; return (FALSE) ; } Cp = C->p ; for (j = 0 ; j < n ; j++) { Len [j] = Cp [j+1] - Cp [j] ; } // C does not include the diagonal, and both upper and lower parts. // Common->anz includes the diagonal, and just the lower part of C cnz = Cp [n] ; Common->anz = cnz / 2 + n ; //-------------------------------------------------------------------------- // order C using CAMD //-------------------------------------------------------------------------- // get parameters if (Common->current < 0 || Common->current >= CHOLMOD_MAXMETHODS) { // use CAMD defaults Control = NULL ; } else { Control = Control2 ; Control [CAMD_DENSE] = Common->method [Common->current].prune_dense ; Control [CAMD_AGGRESSIVE] = Common->method [Common->current].aggressive; } #if defined ( CHOLMOD_INT64 ) // DEBUG (camd_l_debug_init ("cholmod_l_camd")) ; camd_l2 (n, C->p, C->i, Len, C->nzmax, cnz, Nv, Next, Perm, Head, Elen, Degree, Wi, Control, Info, Cmember, BucketSet) ; #else // DEBUG (camd_debug_init ("cholmod_camd")) ; camd_2 (n, C->p, C->i, Len, C->nzmax, cnz, Nv, Next, Perm, Head, Elen, Degree, Wi, Control, Info, Cmember, BucketSet) ; #endif // LL' flop count. Need to subtract n for LL' flop count. Note that this // is a slight upper bound which is often exact (see CAMD/Source/camd_2.c // for details). cholmod_analyze computes an exact flop count and // fill-in. Common->fl = Info [CAMD_NDIV] + 2 * Info [CAMD_NMULTSUBS_LDL] + n ; // Info [CAMD_LNZ] excludes the diagonal Common->lnz = n + Info [CAMD_LNZ] ; //-------------------------------------------------------------------------- // free the CAMD workspace and clear the persistent workspace in Common //-------------------------------------------------------------------------- ASSERT (IMPLIES (Common->status == CHOLMOD_OK, CHOLMOD(dump_perm) (Perm, n, n, "CAMD2 perm", Common))) ; CHOLMOD(free_sparse) (&C, Common) ; for (j = 0 ; j <= n ; j++) { Head [j] = EMPTY ; } CHOLMOD(free) (n+1, 3*sizeof (Int), Work3n, Common) ; return (TRUE) ; } #endif Matrix/src/SuiteSparse/CHOLMOD/Partition/cholmod_l_camd.c0000644000175100001440000000102514552026002022712 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Partition/cholmod_l_camd.c: int64_t version of cholmod_camd //------------------------------------------------------------------------------ // CHOLMOD/Partition Module. Copyright (C) 2005-2023, University of Florida. // All Rights Reserved. Author: Timothy A. Davis. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_camd.c" Matrix/src/SuiteSparse/CHOLMOD/Partition/cholmod_l_nesdis.c0000644000175100001440000000103314552026002023272 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Partition/cholmod_l_nesdis.c: int64_t version of cholmod_nesdis //------------------------------------------------------------------------------ // CHOLMOD/Partition Module. Copyright (C) 2005-2023, University of Florida. // All Rights Reserved. Author: Timothy A. Davis. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_nesdis.c" Matrix/src/SuiteSparse/CHOLMOD/Modify/0000755000175100001440000000000014576344041017116 5ustar hornikusersMatrix/src/SuiteSparse/CHOLMOD/Modify/cholmod_rowadd.c0000644000175100001440000002022014552026002022227 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Modify/cholmod_rowadd: add row/column to an LDL' factorization //------------------------------------------------------------------------------ // CHOLMOD/Modify Module. Copyright (C) 2005-2023, Timothy A. Davis, // and William W. Hager. All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // Adds a row and column to an LDL' factorization, and optionally updates the // solution to Lx=b. // // workspace: Flag (nrow), Head (nrow+1), W (2*nrow), Iwork (2*nrow) // // Only real matrices are supported (single or double). A symbolic L is // converted into a numeric identity matrix before the row is added. // The dtypes of all matrices must match, except when L is symbolic (in which // case it is converted to the dtype of R). #include "cholmod_internal.h" #ifndef NGPL #ifndef NMODIFY //------------------------------------------------------------------------------ // icomp: for sorting by qsort //------------------------------------------------------------------------------ static int icomp (Int *i, Int *j) { if (*i < *j) { return (-1) ; } else { return (1) ; } } //------------------------------------------------------------------------------ // t_cholmod_rowadd_worker //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_rowadd_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_rowadd_worker.c" //------------------------------------------------------------------------------ // cholmod_rowadd //------------------------------------------------------------------------------ // cholmod_rowadd adds a row to the LDL' factorization. It computes the kth // row and kth column of L, and then updates the submatrix L (k+1:n,k+1:n) // accordingly. The kth row and column of L should originally be equal to the // kth row and column of the identity matrix (they are treated as such, if they // are not). The kth row/column of L is computed as the factorization of the // kth row/column of the matrix to factorize, which is provided as a single // n-by-1 sparse matrix R. The sparse vector R need not be sorted. int CHOLMOD(rowadd) ( // input: size_t k, // row/column index to add cholmod_sparse *R, // row/column of matrix to factorize (n-by-1) // input/output: cholmod_factor *L, // factor to modify cholmod_common *Common ) { double bk [2] ; bk [0] = 0. ; bk [1] = 0. ; return (CHOLMOD(rowadd_mark) (k, R, bk, NULL, L, NULL, NULL, Common)) ; } //------------------------------------------------------------------------------ // cholmod_rowadd_solve //------------------------------------------------------------------------------ // Does the same as cholmod_rowadd, and also updates the solution to Lx=b // See cholmod_updown for a description of how Lx=b is updated. There is on // additional parameter: bk specifies the new kth entry of b. int CHOLMOD(rowadd_solve) ( // input: size_t k, // row/column index to add cholmod_sparse *R, // row/column of matrix to factorize (n-by-1) double bk [2], // kth entry of the right-hand-side b // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) { return (CHOLMOD(rowadd_mark) (k, R, bk, NULL, L, X, DeltaB, Common)) ; } //------------------------------------------------------------------------------ // cholmod_rowadd_mark //------------------------------------------------------------------------------ // Does the same as cholmod_rowadd_solve, except only part of L is used in // the update/downdate of the solution to Lx=b. This routine is an "expert" // routine. It is meant for use in LPDASA only. int CHOLMOD(rowadd_mark) ( // input: size_t kadd, // row/column index to add cholmod_sparse *R, // row/column of matrix to factorize (n-by-1) double bk [2], // kth entry of the right hand side, b Int *colmark, // Int array of size 1. See cholmod_updown.c // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (L, FALSE) ; RETURN_IF_NULL (R, FALSE) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_REAL, FALSE) ; RETURN_IF_XTYPE_INVALID (R, CHOLMOD_REAL, CHOLMOD_REAL, FALSE) ; Int k = kadd ; if (kadd >= L->n || k < 0) { ERROR (CHOLMOD_INVALID, "k invalid") ; return (FALSE) ; } if (R->ncol != 1 || R->nrow != L->n) { ERROR (CHOLMOD_INVALID, "R invalid") ; return (FALSE) ; } if (L->xtype != CHOLMOD_PATTERN && L->dtype != R->dtype) { ERROR (CHOLMOD_INVALID, "R and L must have the same dtype") ; return (FALSE) ; } if ((X != NULL) && (DeltaB != NULL)) { // also update the solution to Lx=b RETURN_IF_XTYPE_INVALID (X, CHOLMOD_REAL, CHOLMOD_REAL, FALSE) ; RETURN_IF_XTYPE_INVALID (DeltaB, CHOLMOD_REAL, CHOLMOD_REAL, FALSE) ; if (X->nrow != L->n || X->ncol != 1 || DeltaB->nrow != L->n || DeltaB->ncol != 1 || X->dtype != R->dtype || DeltaB->dtype != R->dtype) { ERROR (CHOLMOD_INVALID, "X and/or DeltaB invalid") ; return (FALSE) ; } } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- // s = 2*n int ok = TRUE ; size_t s = CHOLMOD(mult_size_t) (L->n, 2, &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (FALSE) ; } CHOLMOD(alloc_work) (L->n, s, s, R->dtype, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, s, R->dtype, Common)) ; //-------------------------------------------------------------------------- // convert to simplicial numeric LDL' factor, if not already //-------------------------------------------------------------------------- if (L->xtype == CHOLMOD_PATTERN || L->is_super || L->is_ll) { // can only update/downdate a simplicial LDL' factorization if (L->xtype == CHOLMOD_PATTERN) { // L is symbolic; convert it to R->dtype L->dtype = R->dtype ; } CHOLMOD(change_factor) (CHOLMOD_REAL, FALSE, FALSE, FALSE, FALSE, L, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory, L is returned unchanged return (FALSE) ; } } ASSERT (L->dtype == R->dtype) ; //-------------------------------------------------------------------------- // update L and X //-------------------------------------------------------------------------- float s_bk [2] ; s_bk [0] = (float) bk [0] ; s_bk [1] = (float) bk [1] ; switch (L->dtype & 4) { case CHOLMOD_SINGLE: ok = rs_cholmod_rowadd_worker (k, R, s_bk, colmark, L, X, DeltaB, Common) ; break ; case CHOLMOD_DOUBLE: ok = rd_cholmod_rowadd_worker (k, R, bk, colmark, L, X, DeltaB, Common) ; break ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- DEBUG (CHOLMOD(dump_factor) (L, "LDL factorization, L:", Common)) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, s, R->dtype, Common)) ; return (ok) ; } #endif #endif Matrix/src/SuiteSparse/CHOLMOD/Modify/t_cholmod_updown_numkr.c0000644000175100001440000006312614552026002024036 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Modify/t_cholmod_updown_numkr: template for update/downdate //------------------------------------------------------------------------------ // CHOLMOD/Modify Module. Copyright (C) 2005-2023, Timothy A. Davis, // and William W. Hager. All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // Supernodal numerical update/downdate of rank K = RANK, along a single path. // This routine operates on a simplicial factor, but operates on adjacent // columns of L that would fit within a single supernode. "Adjacent" means // along a single path in the elimination tree; they may or may not be // adjacent in the matrix L. // // external defines: UPDOWN, WDIM, RANK, and DOUBLE / SINGLE. // // WDIM is 1, 2, 4, or 8. RANK can be 1 to WDIM. // // A simple method is included (#define SIMPLE). The code works, but is slow. // It is meant only to illustrate what this routine is doing. // // A rank-K update proceeds along a single path, using single-column, dual- // column, or quad-column updates of L. If a column j and the next column // in the path (its parent) do not have the same nonzero pattern, a single- // column update is used. If they do, but the 3rd and 4th column from j do // not have the same pattern, a dual-column update is used, in which the two // columns are treated as if they were a single supernode of two columns. If // there are 4 columns in the path that all have the same nonzero pattern, then // a quad-column update is used. All three kinds of updates can be used along // a single path, in a single call to this function. // // Single-column update: // // When updating a single column of L, each iteration of the for loop, // below, processes four rows of W (all columns involved) and one column // of L. Suppose we have a rank-5 update, and columns 2 through 6 of W // are involved. In this case, W in this routine is a pointer to column // 2 of the matrix W in the caller. W (in the caller, shown as 'W') is // held in row-major order, and is 8-by-n (a dense matrix storage format), // but shown below in column form to match the column of L. Suppose there // are 13 nonzero entries in column 27 of L, with row indices 27 (the // diagonal, D), 28, 30, 31, 42, 43, 44, 50, 51, 67, 81, 83, and 84. This // pattern is held in Li [Lp [27] ... Lp [27 + Lnz [27] - 1], where // Lnz [27] = 13. The modification of the current column j of L is done // in the following order. A dot (.) means the entry of W is not accessed. // // W0 points to row 27 of W, and G is a 1-by-8 temporary vector. // // G[0] G[4] // G x x x x x . . . // // W0 // | // v // 27 . . x x x x x . W0 points to W (27,2) // // // row 'W' W column j = 27 // | | | of L // v v v | // first iteration of for loop: v // // 28 . . 1 5 9 13 17 . x // 30 . . 2 6 10 14 18 . x // 31 . . 3 7 11 15 19 . x // 42 . . 4 8 12 16 20 . x // // second iteration of for loop: // // 43 . . 1 5 9 13 17 . x // 44 . . 2 6 10 14 18 . x // 50 . . 3 7 11 15 19 . x // 51 . . 4 8 12 16 20 . x // // third iteration of for loop: // // 67 . . 1 5 9 13 17 . x // 81 . . 2 6 10 14 18 . x // 83 . . 3 7 11 15 19 . x // 84 . . 4 8 12 16 20 . x // // If the number of offdiagonal nonzeros in column j of L is not divisible // by 4, then the switch-statement does the work for the first nz % 4 rows. // // Dual-column update: // // In this case, two columns of L that are adjacent in the path are being // updated, by 1 to 8 columns of W. Suppose columns j=27 and j=28 are // adjacent columns in the path (they need not be j and j+1). Two rows // of G and W are used as coefficients during the update: (G0, G1) and // (W0, W1). // // G0 x x x x x . . . // G1 x x x x x . . . // // 27 . . x x x x x . W0 points to W (27,2) // 28 . . x x x x x . W1 points to W (28,2) // // // row 'W' W0,W1 column j = 27 // | | | of L // v v v | // | |-- column j = 28 of L // v v // update L (j1,j): // // 28 . . 1 2 3 4 5 . x - ("-" is not stored in L) // // cleanup iteration since length is odd: // // 30 . . 1 2 3 4 5 . x x // // then each iteration does two rows of both columns of L: // // 31 . . 1 3 5 7 9 . x x // 42 . . 2 4 6 8 10 . x x // // 43 . . 1 3 5 7 9 . x x // 44 . . 2 4 6 8 10 . x x // // 50 . . 1 3 5 7 9 . x x // 51 . . 2 4 6 8 10 . x x // // 67 . . 1 3 5 7 9 . x x // 81 . . 2 4 6 8 10 . x x // // 83 . . 1 3 5 7 9 . x x // 84 . . 2 4 6 8 10 . x x // // If the number of offdiagonal nonzeros in column j of L is not even, // then the cleanup iteration does the work for the first row. // // Quad-column update: // // In this case, four columns of L that are adjacent in the path are being // updated, by 1 to 8 columns of W. Suppose columns j=27, 28, 30, and 31 // are adjacent columns in the path (they need not be j, j+1, ...). Four // rows of G and W are used as coefficients during the update: (G0 through // G3) and (W0 through W3). j=27, j1=28, j2=30, and j3=31. // // G0 x x x x x . . . // G1 x x x x x . . . // G3 x x x x x . . . // G4 x x x x x . . . // // 27 . . x x x x x . W0 points to W (27,2) // 28 . . x x x x x . W1 points to W (28,2) // 30 . . x x x x x . W2 points to W (30,2) // 31 . . x x x x x . W3 points to W (31,2) // // // row 'W' W0,W1,.. column j = 27 // | | | of L // v v v | // | |-- column j = 28 of L // | | |-- column j = 30 of L // | | | |-- column j = 31 of L // v v v v // update L (j1,j): // 28 . . 1 2 3 4 5 . x - - - // // update L (j2,j): // 30 . . 1 2 3 4 5 . # x - - (# denotes modified) // // update L (j2,j1) // 30 . . 1 2 3 4 5 . x # - - // // update L (j3,j) // 31 . . 1 2 3 4 5 . # x x - // // update L (j3,j1) // 31 . . 1 2 3 4 5 . x # x - // // update L (j3,j2) // 31 . . 1 2 3 4 5 . x x # - // // cleanup iteration since length is odd: // 42 . . 1 2 3 4 5 . x x x x // // then each iteration does one row of all four colummns of L: // // 43 . . 1 2 3 4 5 . x x x x // 44 . . 1 2 3 4 5 . x x x x // 50 . . 1 3 5 4 5 . x x x x // 51 . . 1 2 3 4 5 . x x x x // 67 . . 1 3 5 4 5 . x x x x // 81 . . 1 2 3 4 5 . x x x x // 83 . . 1 3 5 4 5 . x x x x // 84 . . 1 2 3 4 5 . x x x x // // This file is included in t_cholmod_updown_wdim.c, only. // It is not compiled separately. It contains no user-callable routines. // // workspace: Xwork (WDIM*nrow) //------------------------------------------------------------------------------ // loop unrolling macros //------------------------------------------------------------------------------ #undef RANK1 #undef RANK2 #undef RANK3 #undef RANK4 #undef RANK5 #undef RANK6 #undef RANK7 #undef RANK8 #define RANK1(statement) statement #if RANK < 2 #define RANK2(statement) #else #define RANK2(statement) statement #endif #if RANK < 3 #define RANK3(statement) #else #define RANK3(statement) statement #endif #if RANK < 4 #define RANK4(statement) #else #define RANK4(statement) statement #endif #if RANK < 5 #define RANK5(statement) #else #define RANK5(statement) statement #endif #if RANK < 6 #define RANK6(statement) #else #define RANK6(statement) statement #endif #if RANK < 7 #define RANK7(statement) #else #define RANK7(statement) statement #endif #if RANK < 8 #define RANK8(statement) #else #define RANK8(statement) statement #endif #define FOR_ALL_K \ RANK1 (DO (0)) \ RANK2 (DO (1)) \ RANK3 (DO (2)) \ RANK4 (DO (3)) \ RANK5 (DO (4)) \ RANK6 (DO (5)) \ RANK7 (DO (6)) \ RANK8 (DO (7)) //------------------------------------------------------------------------------ // dbound/sbound //------------------------------------------------------------------------------ #undef USE_DBOUND #undef BOUND_DJ #ifdef DOUBLE // double case #define USE_DBOUND bool use_dbound = (Common->dbound > 0) ; #define BOUND_DJ(Dj,dj) \ Dj = ((use_dbound) ? (CHOLMOD(dbound) (dj, Common)) : (dj)) ; #else // single case #define USE_DBOUND bool use_sbound = (Common->sbound > 0) ; #define BOUND_DJ(Dj,dj) \ Dj = ((use_sbound) ? (CHOLMOD(sbound) (dj, Common)) : (dj)) ; #endif //------------------------------------------------------------------------------ // alpha/gamma //------------------------------------------------------------------------------ #undef ALPHA_GAMMA #define ALPHA_GAMMA(Dj,Alpha,Gamma,W) \ { \ Real dj = Dj ; \ if (update) \ { \ for (k = 0 ; k < RANK ; k++) \ { \ Real w = W [k] ; \ Real alpha = Alpha [k] ; \ Real a = alpha + (w * w) / dj ; \ dj *= a ; \ Alpha [k] = a ; \ Gamma [k] = (- w / dj) ; \ dj /= alpha ; \ } \ } \ else \ { \ for (k = 0 ; k < RANK ; k++) \ { \ Real w = W [k] ; \ Real alpha = Alpha [k] ; \ Real a = alpha - (w * w) / dj ; \ dj *= a ; \ Alpha [k] = a ; \ Gamma [k] = w / dj ; \ dj /= alpha ; \ } \ } \ BOUND_DJ (Dj, dj) ; \ } //------------------------------------------------------------------------------ // numeric update/downdate along one path //------------------------------------------------------------------------------ static void UPDOWN (WDIM, RANK) ( int update, // TRUE for update, FALSE for downdate Int j, // first column in the path Int e, // last column in the path Real Alpha [ ], // alpha, for each column of W Real W [ ], // W is an n-by-WDIM array, stored in row-major order cholmod_factor *L, // with unit diagonal (diagonal not stored) cholmod_common *Common ) { USE_DBOUND ; #ifdef SIMPLE #define w(row,col) W [WDIM*(row) + (col)] //-------------------------------------------------------------------------- // concise but slow version for illustration only //-------------------------------------------------------------------------- Real Gamma [WDIM] ; Int *Li = L->i ; Real *Lx = L->x ; Int *Lp = L->p ; Int *Lnz = L->nz ; // walk up the etree from node j to its ancestor e for ( ; j <= e ; j = (Lnz [j] > 1) ? (Li [Lp [j] + 1]) : Int_max) { // update the diagonal entry D (j,j) with each column of W ALPHA_GAMMA (Lx [Lp [j]], Alpha, Gamma, (&(w (j,0)))) ; // update column j of L for (Int p = Lp [j] + 1 ; p < Lp [j] + Lnz [j] ; p++) { // update row Li [p] of column j of L with each column of W Int i = Li [p] ; for (Int k = 0 ; k < RANK ; k++) { w (i,k) -= w (j,k) * Lx [p] ; Lx [p] -= Gamma [k] * w (i,k) ; } } // clear workspace W for (Int k = 0 ; k < RANK ; k++) { w (j,k) = 0 ; } } #else //-------------------------------------------------------------------------- // dynamic supernodal version: supernodes detected dynamically //-------------------------------------------------------------------------- Real G0 [RANK], G1 [RANK], G2 [RANK], G3 [RANK] ; Real Z0 [RANK], Z1 [RANK], Z2 [RANK], Z3 [RANK] ; Real *W0, *W1, *W2, *W3, *Lx ; Int *Li, *Lp, *Lnz ; Int j1, j2, j3, p0, p1, p2, p3, parent, lnz, pend, k ; Li = L->i ; Lx = L->x ; Lp = L->p ; Lnz = L->nz ; // walk up the etree from node j to its ancestor e for ( ; j <= e ; j = parent) { p0 = Lp [j] ; // col j is Li,Lx [p0 ... p0+lnz-1] lnz = Lnz [j] ; W0 = W + WDIM * j ; // pointer to row j of W pend = p0 + lnz ; // for k = 0 to RANK-1 do: #define DO(k) Z0 [k] = W0 [k] ; FOR_ALL_K #undef DO // for k = 0 to RANK-1 do: #define DO(k) W0 [k] = 0 ; FOR_ALL_K #undef DO // update D (j,j) ALPHA_GAMMA (Lx [p0], Alpha, G0, Z0) ; p0++ ; // determine how many columns of L to update at the same time parent = (lnz > 1) ? (Li [p0]) : Int_max ; if (parent <= e && lnz == Lnz [parent] + 1) { //------------------------------------------------------------------ // node j and its parent j1 can be updated at the same time //------------------------------------------------------------------ j1 = parent ; j2 = (lnz > 2) ? (Li [p0+1]) : Int_max ; j3 = (lnz > 3) ? (Li [p0+2]) : Int_max ; W1 = W + WDIM * j1 ; // pointer to row j1 of W p1 = Lp [j1] ; // for k = 0 to RANK-1 do: #define DO(k) Z1 [k] = W1 [k] ; FOR_ALL_K #undef DO // for k = 0 to RANK-1 do: #define DO(k) W1 [k] = 0 ; FOR_ALL_K #undef DO // update L (j1,j) { Real lx = Lx [p0] ; // for k = 0 to RANK-1 do: #define DO(k) \ Z1 [k] -= Z0 [k] * lx ; \ lx -= G0 [k] * Z1 [k] ; FOR_ALL_K #undef DO Lx [p0++] = lx ; } // update D (j1,j1) ALPHA_GAMMA (Lx [p1], Alpha, G1, Z1) ; p1++ ; //------------------------------------------------------------------ // update 2 or 4 columns of L //------------------------------------------------------------------ if ((j2 <= e) && // j2 in the current path (j3 <= e) && // j3 in the current path (lnz == Lnz [j2] + 2) && // column j2 matches (lnz == Lnz [j3] + 3)) // column j3 matches { //-------------------------------------------------------------- // update 4 columns of L //-------------------------------------------------------------- // p0 and p1 currently point to row j2 in cols j and j1 of L parent = (lnz > 4) ? (Li [p0+2]) : Int_max ; W2 = W + WDIM * j2 ; // pointer to row j2 of W W3 = W + WDIM * j3 ; // pointer to row j3 of W p2 = Lp [j2] ; p3 = Lp [j3] ; // for k = 0 to RANK-1 do: #define DO(k) Z2 [k] = W2 [k] ; FOR_ALL_K #undef DO // for k = 0 to RANK-1 do: #define DO(k) Z3 [k] = W3 [k] ; FOR_ALL_K #undef DO // for k = 0 to RANK-1 do: #define DO(k) W2 [k] = 0 ; FOR_ALL_K #undef DO // for k = 0 to RANK-1 do: #define DO(k) W3 [k] = 0 ; FOR_ALL_K #undef DO // update L (j2,j) and update L (j2,j1) { Real lx [2] ; lx [0] = Lx [p0] ; lx [1] = Lx [p1] ; // for k = 0 to RANK-1 do: #define DO(k) \ Z2 [k] -= Z0 [k] * lx [0] ; lx [0] -= G0 [k] * Z2 [k] ; \ Z2 [k] -= Z1 [k] * lx [1] ; lx [1] -= G1 [k] * Z2 [k] ; FOR_ALL_K #undef DO Lx [p0++] = lx [0] ; Lx [p1++] = lx [1] ; } // update D (j2,j2) ALPHA_GAMMA (Lx [p2], Alpha, G2, Z2) ; p2++ ; // update L (j3,j), L (j3,j1), and L (j3,j2) { Real lx [3] ; lx [0] = Lx [p0] ; lx [1] = Lx [p1] ; lx [2] = Lx [p2] ; // for k = 0 to RANK-1 do: #define DO(k) \ Z3 [k] -= Z0 [k] * lx [0] ; lx [0] -= G0 [k] * Z3 [k] ; \ Z3 [k] -= Z1 [k] * lx [1] ; lx [1] -= G1 [k] * Z3 [k] ; \ Z3 [k] -= Z2 [k] * lx [2] ; lx [2] -= G2 [k] * Z3 [k] ; FOR_ALL_K #undef DO Lx [p0++] = lx [0] ; Lx [p1++] = lx [1] ; Lx [p2++] = lx [2] ; } // update D (j3,j3) ALPHA_GAMMA (Lx [p3], Alpha, G3, Z3) ; p3++ ; // each iteration updates L (i, [j j1 j2 j3]) for ( ; p0 < pend ; p0++, p1++, p2++, p3++) { Real lx [4], *w0 ; lx [0] = Lx [p0] ; lx [1] = Lx [p1] ; lx [2] = Lx [p2] ; lx [3] = Lx [p3] ; w0 = W + WDIM * Li [p0] ; // for k = 0 to RANK-1 do: #define DO(k) \ w0 [k] -= Z0 [k] * lx [0] ; lx [0] -= G0 [k] * w0 [k] ; \ w0 [k] -= Z1 [k] * lx [1] ; lx [1] -= G1 [k] * w0 [k] ; \ w0 [k] -= Z2 [k] * lx [2] ; lx [2] -= G2 [k] * w0 [k] ; \ w0 [k] -= Z3 [k] * lx [3] ; lx [3] -= G3 [k] * w0 [k] ; FOR_ALL_K #undef DO Lx [p0] = lx [0] ; Lx [p1] = lx [1] ; Lx [p2] = lx [2] ; Lx [p3] = lx [3] ; } } else { //-------------------------------------------------------------- // update 2 columns of L //-------------------------------------------------------------- parent = j2 ; // cleanup iteration if length is odd if ((lnz - 2) % 2) { Real lx [2] , *w0 ; lx [0] = Lx [p0] ; lx [1] = Lx [p1] ; w0 = W + WDIM * Li [p0] ; // for k = 0 to RANK-1 do: #define DO(k) \ w0 [k] -= Z0 [k] * lx [0] ; lx [0] -= G0 [k] * w0 [k] ; \ w0 [k] -= Z1 [k] * lx [1] ; lx [1] -= G1 [k] * w0 [k] ; FOR_ALL_K #undef DO Lx [p0++] = lx [0] ; Lx [p1++] = lx [1] ; } for ( ; p0 < pend ; p0 += 2, p1 += 2) { Real lx [2][2], w [2], *w0, *w1 ; lx [0][0] = Lx [p0 ] ; lx [1][0] = Lx [p0+1] ; lx [0][1] = Lx [p1 ] ; lx [1][1] = Lx [p1+1] ; w0 = W + WDIM * Li [p0 ] ; w1 = W + WDIM * Li [p0+1] ; // for k = 0 to RANK-1 do: #define DO(k) \ w [0] = w0 [k] - Z0 [k] * lx [0][0] ; \ w [1] = w1 [k] - Z0 [k] * lx [1][0] ; \ lx [0][0] -= G0 [k] * w [0] ; \ lx [1][0] -= G0 [k] * w [1] ; \ w0 [k] = w [0] -= Z1 [k] * lx [0][1] ; \ w1 [k] = w [1] -= Z1 [k] * lx [1][1] ; \ lx [0][1] -= G1 [k] * w [0] ; \ lx [1][1] -= G1 [k] * w [1] ; FOR_ALL_K #undef DO Lx [p0 ] = lx [0][0] ; Lx [p0+1] = lx [1][0] ; Lx [p1 ] = lx [0][1] ; Lx [p1+1] = lx [1][1] ; } } } else { //------------------------------------------------------------------ // update one column of L //------------------------------------------------------------------ // cleanup iteration if length is not a multiple of 4 switch ((lnz - 1) % 4) { case 1: { Real lx , *w0 ; lx = Lx [p0] ; w0 = W + WDIM * Li [p0] ; // for k = 0 to RANK-1 do: #define DO(k) \ w0 [k] -= Z0 [k] * lx ; lx -= G0 [k] * w0 [k] ; FOR_ALL_K #undef DO Lx [p0++] = lx ; } break ; case 2: { Real lx [2], *w0, *w1 ; lx [0] = Lx [p0 ] ; lx [1] = Lx [p0+1] ; w0 = W + WDIM * Li [p0 ] ; w1 = W + WDIM * Li [p0+1] ; // for k = 0 to RANK-1 do: #define DO(k) \ w0 [k] -= Z0 [k] * lx [0] ; \ w1 [k] -= Z0 [k] * lx [1] ; \ lx [0] -= G0 [k] * w0 [k] ; \ lx [1] -= G0 [k] * w1 [k] ; FOR_ALL_K #undef DO Lx [p0++] = lx [0] ; Lx [p0++] = lx [1] ; } break ; case 3: { Real lx [3], *w0, *w1, *w2 ; lx [0] = Lx [p0 ] ; lx [1] = Lx [p0+1] ; lx [2] = Lx [p0+2] ; w0 = W + WDIM * Li [p0 ] ; w1 = W + WDIM * Li [p0+1] ; w2 = W + WDIM * Li [p0+2] ; // for k = 0 to RANK-1 do: #define DO(k) \ w0 [k] -= Z0 [k] * lx [0] ; \ w1 [k] -= Z0 [k] * lx [1] ; \ w2 [k] -= Z0 [k] * lx [2] ; \ lx [0] -= G0 [k] * w0 [k] ; \ lx [1] -= G0 [k] * w1 [k] ; \ lx [2] -= G0 [k] * w2 [k] ; FOR_ALL_K #undef DO Lx [p0++] = lx [0] ; Lx [p0++] = lx [1] ; Lx [p0++] = lx [2] ; } } for ( ; p0 < pend ; p0 += 4) { Real lx [4], *w0, *w1, *w2, *w3 ; lx [0] = Lx [p0 ] ; lx [1] = Lx [p0+1] ; lx [2] = Lx [p0+2] ; lx [3] = Lx [p0+3] ; w0 = W + WDIM * Li [p0 ] ; w1 = W + WDIM * Li [p0+1] ; w2 = W + WDIM * Li [p0+2] ; w3 = W + WDIM * Li [p0+3] ; // for k = 0 to RANK-1 do: #define DO(k) \ w0 [k] -= Z0 [k] * lx [0] ; \ w1 [k] -= Z0 [k] * lx [1] ; \ w2 [k] -= Z0 [k] * lx [2] ; \ w3 [k] -= Z0 [k] * lx [3] ; \ lx [0] -= G0 [k] * w0 [k] ; \ lx [1] -= G0 [k] * w1 [k] ; \ lx [2] -= G0 [k] * w2 [k] ; \ lx [3] -= G0 [k] * w3 [k] ; FOR_ALL_K #undef DO Lx [p0 ] = lx [0] ; Lx [p0+1] = lx [1] ; Lx [p0+2] = lx [2] ; Lx [p0+3] = lx [3] ; } } } #endif } // prepare this file for another inclusion in t_cholmod_updown_wdim.c: #undef RANK Matrix/src/SuiteSparse/CHOLMOD/Modify/t_cholmod_rowdel_worker.c0000644000175100001440000002136714552026002024174 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Modify/t_cholmod_rowdel_worker: delete row/col from LDL' //------------------------------------------------------------------------------ // CHOLMOD/Modify Module. Copyright (C) 2005-2023, Timothy A. Davis, // and William W. Hager. All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static int TEMPLATE (cholmod_rowdel_worker) ( // input: Int k, // row/column index to delete cholmod_sparse *R, // NULL, or the nonzero pattern of kth row of L Real yk [2], // kth entry in the solution to A*y=b Int *colmark, // Int array of size 1. See cholmod_updown.c // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int n = L->n ; Real dk, xk, dj ; Real *Xx, *Nx ; Int *Rj, *Rp ; Int j, p, pend, kk, lnz, left, right, middle, i, klast, given_row, rnz ; if (R == NULL) { Rj = NULL ; rnz = EMPTY ; } else { Rj = R->i ; Rp = R->p ; rnz = Rp [1] ; } bool do_solve = (X != NULL) && (DeltaB != NULL) ; if (do_solve) { Xx = X->x ; Nx = DeltaB->x ; } else { Xx = NULL ; Nx = NULL ; } // inputs, not modified on output: Int *Lp = L->p ; // size n+1 // outputs, contents defined on input for incremental case only: Int *Lnz = L->nz ; // size n Int *Li = L->i ; // size L->nzmax. Can change in size. Real *Lx = L->x ; // size L->nzmax. Can change in size. ASSERT (L->nz != NULL) ; //-------------------------------------------------------------------------- // get workspace //-------------------------------------------------------------------------- Real *W = Common->Xwork ; // size n, used only in cholmod_updown Real *Cx = W + n ; // use 2nd column of Xwork for C (size n) Int *Iwork = Common->Iwork ; Int *Ci = Iwork + n ; // size n // NOTE: cholmod_updown uses Iwork [0..n-1] as Stack //-------------------------------------------------------------------------- // prune row k from all columns of L //-------------------------------------------------------------------------- given_row = (rnz >= 0) ; klast = given_row ? rnz : k ; PRINT2 (("given_row "ID"\n", given_row)) ; for (kk = 0 ; kk < klast ; kk++) { // either search j = 0:k-1 or j = Rj [0:rnz-1] j = given_row ? (Rj [kk]) : (kk) ; if (j < 0 || j >= k) { ERROR (CHOLMOD_INVALID, "R invalid") ; return (FALSE) ; } PRINT2 (("Prune col j = "ID":\n", j)) ; lnz = Lnz [j] ; dj = Lx [Lp [j]] ; ASSERT (Lnz [j] > 0 && Li [Lp [j]] == j) ; if (lnz > 1) { left = Lp [j] ; pend = left + lnz ; right = pend - 1 ; i = Li [right] ; if (i < k) { // row k is not in column j continue ; } else if (i == k) { // k is the last row index in this column (quick delete) if (do_solve) { Xx [j] -= yk [0] * dj * Lx [right] ; } Lx [right] = 0 ; } else { // binary search for row k in column j PRINT2 (("\nBinary search: lnz "ID" k = "ID"\n", lnz, k)) ; while (left < right) { middle = (left + right) / 2 ; PRINT2 (("left "ID" right "ID" middle "ID": ["ID" "ID"" ""ID"]\n", left, right, middle, Li [left], Li [middle], Li [right])) ; if (k > Li [middle]) { left = middle + 1 ; } else { right = middle ; } } ASSERT (left >= Lp [j] && left < pend) ; #ifndef NDEBUG // brute force, linear-time search { Int p3 = Lp [j] ; i = EMPTY ; PRINT2 (("Brute force:\n")) ; for ( ; p3 < pend ; p3++) { i = Li [p3] ; PRINT2 (("p "ID" ["ID"]\n", p3, i)) ; if (i >= k) { break ; } } if (i == k) { ASSERT (k == Li [p3]) ; ASSERT (p3 == left) ; } } #endif if (k == Li [left]) { if (do_solve) { Xx [j] -= yk [0] * dj * Lx [left] ; } // found row k in column j. Prune it from the column. Lx [left] = 0 ; } } } } #ifndef NDEBUG // ensure that row k has been deleted from the matrix L for (j = 0 ; j < k ; j++) { Int lasti ; lasti = EMPTY ; p = Lp [j] ; pend = p + Lnz [j] ; // look for row k in column j PRINT1 (("Pruned column "ID"\n", j)) ; for ( ; p < pend ; p++) { i = Li [p] ; PRINT2 ((" "ID"", i)) ; PRINT2 ((" %g\n", Lx [p])) ; ASSERT (IMPLIES (i == k, Lx [p] == 0)) ; ASSERT (i > lasti) ; lasti = i ; } PRINT1 (("\n")) ; } #endif //-------------------------------------------------------------------------- // set diagonal and clear column k of L //-------------------------------------------------------------------------- lnz = Lnz [k] - 1 ; ASSERT (Lnz [k] > 0) ; //-------------------------------------------------------------------------- // update/downdate //-------------------------------------------------------------------------- // update or downdate L (k+1:n, k+1:n) with the vector // C = L (:,k) * sqrt (abs (D [k])) // Do a numeric update if D[k] > 0, numeric downdate otherwise. PRINT1 (("rowdel downdate lnz = "ID"\n", lnz)) ; // store the new unit diagonal p = Lp [k] ; pend = p + lnz + 1 ; dk = Lx [p] ; Lx [p++] = 1 ; PRINT2 (("D [k = "ID"] = %g\n", k, dk)) ; int ok = TRUE ; double fl = 0 ; if (lnz > 0) { // compute DeltaB for updown (in DeltaB) if (do_solve) { xk = Xx [k] - yk [0] * dk ; for ( ; p < pend ; p++) { Nx [Li [p]] += Lx [p] * xk ; } } bool do_update = (dk > 0) ; if (!do_update) { dk = -dk ; } Real sqrt_dk = sqrt (dk) ; p = Lp [k] + 1 ; for (kk = 0 ; kk < lnz ; kk++, p++) { Ci [kk] = Li [p] ; Cx [kk] = Lx [p] * sqrt_dk ; Lx [p] = 0 ; // clear column k } fl = lnz + 1 ; // create a n-by-1 sparse matrix to hold the single column cholmod_sparse *C, Cmatrix ; Int Cp [2] ; C = &Cmatrix ; C->nrow = n ; C->ncol = 1 ; C->nzmax = lnz ; C->sorted = TRUE ; C->packed = TRUE ; C->p = Cp ; C->i = Ci ; C->x = Cx ; C->nz = NULL ; C->itype = L->itype ; C->xtype = L->xtype ; C->dtype = L->dtype ; C->z = NULL ; C->stype = 0 ; Cp [0] = 0 ; Cp [1] = lnz ; // numeric update if dk > 0, and with Lx=b change // workspace: Flag (nrow), Head (nrow+1), W (nrow), Iwork (2*nrow) ok = CHOLMOD(updown_mark) (do_update ? (1) : (0), C, colmark, L, X, DeltaB, Common) ; // clear workspace for (kk = 0 ; kk < lnz ; kk++) { Cx [kk] = 0 ; } } Common->modfl += fl ; if (do_solve) { // kth equation becomes identity, so X(k) is now Y(k) Xx [k] = yk [0] ; } return (ok) ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Modify/cholmod_l_rowadd.c0000644000175100001440000000100714552026002022544 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Modify/cholmod_l_rowadd.c: int64_t version of cholmod_rowadd //------------------------------------------------------------------------------ // CHOLMOD/Modify Module. Copyright (C) 2005-2023, Timothy A. Davis, // William W. Hager. All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_rowadd.c" Matrix/src/SuiteSparse/CHOLMOD/Modify/cholmod_updown.c0000644000175100001440000004644714552026002022306 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Modify/cholmod_updown: sparse Cholesky update/downdate //------------------------------------------------------------------------------ // CHOLMOD/Modify Module. Copyright (C) 2005-2023, Timothy A. Davis, // and William W. Hager. All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // Updates/downdates the LDL' factorization (symbolic, then numeric), by // computing a new factorization of // // Lnew * Dnew * Lnew' = Lold * Dold * Lold' +/- C*C' // // C must be sorted. It can be either packed or unpacked. As in all CHOLMOD // routines, the columns of L are sorted on input, and also on output. // // If the factor is not an unpacked LDL' or dynamic LDL', it is converted // to an LDL' dynamic factor. An unpacked LDL' factor may be updated, but if // any one column runs out of space, the factor is converted to an LDL' // dynamic one. If the initial conversion fails, the factor is returned // unchanged. // // If memory runs out during the update, the factor is returned as a simplicial // symbolic factor. That is, everything is freed except for the fill-reducing // ordering and its corresponding column counts (typically computed by // cholmod_analyze). // // Note that the fill-reducing permutation L->Perm is NOT used. The row // indices of C refer to the rows of L, not A. If your original system is // LDL' = PAP' (where P = L->Perm), and you want to compute the LDL' // factorization of A+CC', then you must permute C first. That is: // // PAP' = LDL' // P(A+CC')P' = PAP'+PCC'P' = LDL' + (PC)(PC)' = LDL' + Cnew*Cnew' // where Cnew = P*C. // // You can use the cholmod_submatrix routine in the MatrixOps module // to permute C, with: // // Cnew = cholmod_submatrix (C, L->Perm, L->n, NULL, -1, TRUE, TRUE, Common) ; // // Note that the sorted input parameter to cholmod_submatrix must be TRUE, // because cholmod_updown requires C with sorted columns. // // The system Lx=b can also be updated/downdated. The old system was Lold*x=b. // The new system is Lnew*xnew = b + deltab. The old solution x is overwritten // with xnew. Note that as in the update/downdate of L itself, the fill- // reducing permutation L->Perm is not used. x and b are in the permuted // ordering, not your original ordering. x and b are n-by-1; this routine // does not handle multiple right-hand-sides. // // workspace: Flag (nrow), Head (nrow+1), W (maxrank*nrow), Iwork (nrow), // where maxrank is 2, 4, or 8. // // Only real matrices are supported (single and double). A symbolic L is // converted into a numeric identity matrix. #include "cholmod_internal.h" #ifndef NGPL #ifndef NMODIFY //------------------------------------------------------------------------------ // cholmod_updown //------------------------------------------------------------------------------ // Compute the new LDL' factorization of LDL'+CC' (an update) or LDL'-CC' // (a downdate). The factor object L need not be an LDL' factorization; it // is converted to one if it isn't. int CHOLMOD(updown) ( // input: int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // the incoming sparse update // input/output: cholmod_factor *L, // factor to modify cholmod_common *Common ) { return (CHOLMOD(updown_mask2) (update, C, /* colmark: */ NULL, /* mask: */ NULL, /* maskmark: */ 0, L, /* X: */ NULL, /* DeltaB: */ NULL, Common)) ; } //------------------------------------------------------------------------------ // cholmod_updown_solve //------------------------------------------------------------------------------ // Does the same as cholmod_updown, except that it also updates/downdates the // solution to Lx=b+DeltaB. x and b must be n-by-1 dense matrices. b is not // need as input to this routine, but a sparse change to b is (DeltaB). Only // entries in DeltaB corresponding to columns modified in L are accessed; the // rest are ignored. int CHOLMOD(updown_solve) ( // input: int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // the incoming sparse update // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) { return (CHOLMOD(updown_mask2) (update, C, /* colmark: */ NULL, /* mask: */ NULL, /* maskmark: */ 0, L, X, DeltaB, Common)) ; } //------------------------------------------------------------------------------ // Power2 //------------------------------------------------------------------------------ // Power2 [i] is smallest power of 2 that is >= i (for i in range 0 to 8) static size_t Power2 [ ] = { // 0 1 2 3 4 5 6 7 8 0, 1, 2, 4, 4, 8, 8, 8, 8 } ; //------------------------------------------------------------------------------ // debug routines //------------------------------------------------------------------------------ #ifndef NDEBUG static void dump_set (Int s, Int **Set_ps1, Int **Set_ps2, Int j, Int n, cholmod_common *Common) { Int *p, len, i, ilast ; if (CHOLMOD(dump) < -1) { // no checks if debug level is -2 or less return ; } len = Set_ps2 [s] - Set_ps1 [s] ; PRINT2 (("Set s: "ID" len: "ID":", s, len)) ; ASSERT (len > 0) ; ilast = j ; for (p = Set_ps1 [s] ; p < Set_ps2 [s] ; p++) { i = *p ; PRINT3 ((" "ID"", i)) ; ASSERT (i > ilast && i < n) ; ilast = i ; } PRINT3 (("\n")) ; } #endif //------------------------------------------------------------------------------ // Path_type //------------------------------------------------------------------------------ // A path is a set of nodes of the etree which are all affected by the same // columns of C. typedef struct Path_struct { Int start ; // column at which to start, or EMPTY if initial Int end ; // column at which to end, or EMPTY if initial Int ccol ; // column of C to which path refers Int parent ; // parent path Int c ; // child of j along this path Int next ; // next path in link list Int rank ; // number of rank-1 paths merged onto this path Int order ; // dfs order of this path Int wfirst ; // first column of W to affect this path Int pending ; // column at which the path is pending Int botrow ; // for partial update/downdate of solution to Lx=b } Path_type ; //------------------------------------------------------------------------------ // dfs //------------------------------------------------------------------------------ // Compute the DFS order of the set of paths. This can be recursive because // there are at most 23 paths to sort: one for each column of C (8 at most), // and one for each node in a balanced binary tree with 8 leaves (15). // Stack overflow is thus not a problem. static void dfs ( Path_type *Path, // the set of Paths Int k, // the rank of the update/downdate Int path, // which path to work on Int *path_order, // the current path order Int *w_order, // the current order of the columns of W Int depth, Int npaths // total number of paths ) { Int c ; // child path ASSERT (path >= 0 && path < npaths) ; if (path < k) { // this is a leaf node, corresponding to column W (:,path) // and column C (:, Path [path].ccol) ASSERT (Path [path].ccol >= 0) ; Path [path].wfirst = *w_order ; Path [path].order = *w_order ; (*w_order)++ ; } else { // this is a non-leaf path, within the tree ASSERT (Path [path].c != EMPTY) ; ASSERT (Path [path].ccol == EMPTY) ; // order each child path for (c = Path [path].c ; c != EMPTY ; c = Path [c].next) { dfs (Path, k, c, path_order, w_order, depth+1, npaths) ; if (Path [path].wfirst == EMPTY) { Path [path].wfirst = Path [c].wfirst ; } } // order this path next Path [path].order = (*path_order)++ ; } } //------------------------------------------------------------------------------ // numeric update/downdate routines //------------------------------------------------------------------------------ // naming scheme for the update/downdate worker methods: // // single case: s_updown_k_rank // double case: d_updown_k_rank // // where k is 1, 2, 4, or 8, and rank is r for the t_cholmod_updown_wdim // method, or 1 to 8 for the lowest level kernels. See t_cholmod_updown_wdim.c // for details. #define UPDOWN_METHOD(prefix,k,rank) prefix ## updown_ ## k ## _ ## rank #define DOUBLE #define REAL #include "t_cholmod_updown_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_updown_worker.c" //------------------------------------------------------------------------------ // cholmod_updown_mark //------------------------------------------------------------------------------ // Update/downdate LDL' +/- C*C', and update/downdate selected portions of the // solution to Lx=b. // // The original system is L*x = b. The new system is Lnew*xnew = b + deltab. // deltab(i) can be nonzero only if column i of L is modified by the update/ // downdate. If column i is not modified, the deltab(i) is not accessed. // // The solution to Lx=b is not modified if either X or DeltaB are NULL. // // Rowmark and colmark: // -------------------- // // rowmark and colmark affect which portions of L take part in the update/ // downdate of the solution to Lx=b. They do not affect how L itself is // updated/downdated. They are both ignored if X or DeltaB are NULL. // // If not NULL, rowmark is an integer array of size n where L is n-by-n. // rowmark [j] defines the part of column j of L that takes part in the update/ // downdate of the forward solve, Lx=b. Specifically, if i = rowmark [j], // then L(j:i-1,j) is used, and L(i:end,j) is ignored. // // If not NULL, colmark is an integer array of size C->ncol. colmark [ccol] // for a column C(:,ccol) redefines those parts of L that take part in the // update/downdate of Lx=b. Each column of C affects a set of columns of L. // If column ccol of C affects column j of L, then the new rowmark [j] of // column j of L is defined as colmark [ccol]. In a multiple-rank update/ // downdate, if two or more columns of C affect column j, its new rowmark [j] // is the colmark of the least-numbered column of C. colmark is ignored if // it is NULL, in which case rowmark is not modified. If colmark [ccol] is // EMPTY (-1), then rowmark is not modified for that particular column of C. // colmark is ignored if it is NULL, or rowmark, X, or DeltaB are NULL. // // The algorithm for modifying the solution to Lx=b when rowmark and colmark // are NULL is as follows: // // for each column j of L that is modified: // deltab (j:end) += L (j:end,j) * x(j) // modify L // for each column j of L that is modified: // x (j) = deltab (j) // deltab (j) = 0 // deltab (j+1:end) -= L (j+1:end,j) * x(j) // // If rowmark is non-NULL but colmark is NULL: // // for each column j of L that is modified: // deltab (j:rowmark(j)-1) += L (j:rowmark(j)-1,j) * x(j) // modify L // for each column j of L that is modified: // x (j) = deltab (j) // deltab (j) = 0 // deltab (j+1:rowmark(j)-1) -= L (j+1:rowmark(j)-1,j) * x(j) // // If both rowmark and colmark are non-NULL: // // for each column j of L that is modified: // deltab (j:rowmark(j)-1) += L (j:rowmark(j)-1,j) * x(j) // modify L // for each column j of L that is modified: // modify rowmark (j) according to colmark // for each column j of L that is modified: // x (j) = deltab (j) // deltab (j) = 0 // deltab (j+1:rowmark(j)-1) -= L (j+1:rowmark(j)-1,j) * x(j) // // Note that if the rank of C exceeds k = Common->maxrank (which is 2, 4, or 8), // then the update/downdate is done as a series of rank-k updates. In this // case, the above algorithm is repeated for each block of k columns of C. // // Unless it leads to no changes in rowmark, colmark should be used only if // C->ncol <= Common->maxrank, because the update/downdate is done with maxrank // columns at a time. Otherwise, the results are undefined. // // This routine is an "expert" routine. It is meant for use in LPDASA only. int CHOLMOD(updown_mark) ( // input: int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // the incoming sparse update Int *colmark, // array of size n. See cholmod_updown.c for details // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) { return (CHOLMOD(updown_mask2) (update, C, colmark, /* mask: */ NULL, /* maskmark: */ 0, L, X, DeltaB, Common)) ; } //------------------------------------------------------------------------------ // cholmod_updown_mask //------------------------------------------------------------------------------ int CHOLMOD(updown_mask) ( // input: int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // the incoming sparse update Int *colmark, // array of size n. See cholmod_updown.c for details Int *mask, // size n // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) { return (CHOLMOD(updown_mask2) (update, C, colmark, mask, /* maskmark: */ 0, L, X, DeltaB, Common)) ; } //------------------------------------------------------------------------------ // cholmod_updown_mask2 //------------------------------------------------------------------------------ int CHOLMOD(updown_mask2) ( // input: int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // the incoming sparse update Int *colmark, // array of size n. See cholmod_updown.c for details Int *mask, // size n Int maskmark, // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (C, FALSE) ; RETURN_IF_NULL (L, FALSE) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_REAL, FALSE) ; RETURN_IF_XTYPE_INVALID (C, CHOLMOD_REAL, CHOLMOD_REAL, FALSE) ; Int n = L->n ; Int cncol = C->ncol ; if (!(C->sorted)) { ERROR (CHOLMOD_INVALID, "C must have sorted columns") ; return (FALSE) ; } if (L->n != C->nrow) { ERROR (CHOLMOD_INVALID, "C and L dimensions do not match") ; return (FALSE) ; } if (L->dtype != C->dtype) { ERROR (CHOLMOD_INVALID, "C and L must have the same dtype") ; return (FALSE) ; } if ((X != NULL) && (DeltaB != NULL)) { RETURN_IF_XTYPE_INVALID (X, CHOLMOD_REAL, CHOLMOD_REAL, FALSE) ; RETURN_IF_XTYPE_INVALID (DeltaB, CHOLMOD_REAL, CHOLMOD_REAL, FALSE) ; if (X->nrow != L->n || X->ncol != 1 || DeltaB->nrow != L->n || DeltaB->ncol != 1 || X->dtype != L->dtype || DeltaB->dtype != L->dtype) { ERROR (CHOLMOD_INVALID, "X and/or DeltaB invalid") ; return (FALSE) ; } } Common->status = CHOLMOD_OK ; Common->modfl = 0 ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- // Note: cholmod_rowadd and cholmod_rowdel use the second n doubles in // Common->Xwork for Cx, and then perform a rank-1 update here, which uses // the first n doubles in Common->Xwork. Both the rowadd and rowdel // routines allocate enough workspace so that Common->Xwork isn't destroyed // below. Also, both cholmod_rowadd and cholmod_rowdel use the second n // ints in Common->Iwork for C->i. // make sure maxrank is in the proper range size_t maxrank = CHOLMOD(maxrank) (n, Common) ; Int k = MIN (cncol, (Int) maxrank) ; // maximum k is wdim size_t wdim = Power2 [k] ; // number of columns needed in W ASSERT (wdim <= maxrank) ; PRINT1 (("updown wdim final "ID" k "ID"\n", (Int) wdim, k)) ; // w = wdim * n int ok = TRUE ; size_t w = CHOLMOD(mult_size_t) (L->n, wdim, &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (FALSE) ; } CHOLMOD(alloc_work) (L->n, L->n, w, L->dtype, Common) ; if (Common->status < CHOLMOD_OK || maxrank == 0) { // out of memory, L is returned unchanged return (FALSE) ; } //-------------------------------------------------------------------------- // convert to simplicial numeric LDL' factor, if not already //-------------------------------------------------------------------------- if (L->xtype == CHOLMOD_PATTERN || L->is_super || L->is_ll) { // can only update/downdate a simplicial LDL' factorization CHOLMOD(change_factor) (CHOLMOD_REAL, FALSE, FALSE, FALSE, FALSE, L, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory, L is returned unchanged return (FALSE) ; } } CLEAR_FLAG (Common) ; ASSERT (check_flag (Common)) ; PRINT1 (("updown, rank %g update %d\n", (double) C->ncol, update)) ; DEBUG (CHOLMOD(dump_factor) (L, "input L for updown", Common)) ; ASSERT (CHOLMOD(dump_sparse) (C, "input C for updown", Common) >= 0) ; //-------------------------------------------------------------------------- // quick return //-------------------------------------------------------------------------- if (cncol <= 0 || n == 0) { // nothing to do return (TRUE) ; } //-------------------------------------------------------------------------- // update/downdate //-------------------------------------------------------------------------- switch (L->dtype & 4) { case CHOLMOD_SINGLE: ok = rs_cholmod_updown_worker (k, update, C, colmark, mask, maskmark, L, X, DeltaB, Common) ; break ; case CHOLMOD_DOUBLE: ok = rd_cholmod_updown_worker (k, update, C, colmark, mask, maskmark, L, X, DeltaB, Common) ; break ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; DEBUG (CHOLMOD(dump_factor) (L, "output L for updown", Common)) ; return (ok) ; } #endif #endif Matrix/src/SuiteSparse/CHOLMOD/Modify/cholmod_l_updown.c0000644000175100001440000000100714552026002022600 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Modify/cholmod_l_updown.c: int64_t version of cholmod_updown //------------------------------------------------------------------------------ // CHOLMOD/Modify Module. Copyright (C) 2005-2023, Timothy A. Davis, // William W. Hager. All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_updown.c" Matrix/src/SuiteSparse/CHOLMOD/Modify/t_cholmod_rowadd_worker.c0000644000175100001440000003653214552026002024160 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Modify/t_cholmod_rowadd_worker: add row/col to an LDL' factorization //------------------------------------------------------------------------------ // CHOLMOD/Modify Module. Copyright (C) 2005-2023, Timothy A. Davis, // and William W. Hager. All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #include "cholmod_template.h" static int TEMPLATE (cholmod_rowadd_worker) ( // input: Int k, // row/column index to add cholmod_sparse *R, // row/column of matrix to factorize (n-by-1) Real bk [2], // kth entry of the right hand side, b Int *colmark, // Int array of size 1. See cholmod_updown.c // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int n = L->n ; Int *Rj = R->i ; Int *Rp = R->p ; Int *Rnz = R->nz ; Real *Rx = R->x ; Int rnz = (R->packed) ? (Rp [1]) : (Rnz [0]) ; bool do_solve = (X != NULL) && (DeltaB != NULL) ; Real *Xx = NULL ; Real *Nx = NULL ; if (do_solve) { Xx = X->x ; Nx = DeltaB->x ; } else { Xx = NULL ; Nx = NULL ; } // inputs, not modified on output: Int *Lp = L->p ; // size n+1. input, not modified on output // outputs, contents defined on input for incremental case only: Int *Lnz = L->nz ; // size n Int *Li = L->i ; // size L->nzmax. Can change in size. Real *Lx = L->x ; // size L->nzmax. Can change in size. Int *Lnext = L->next ; // size n+2 ASSERT (L->nz != NULL) ; PRINT1 (("rowadd:\n")) ; double fl = 0 ; //-------------------------------------------------------------------------- // get workspace //-------------------------------------------------------------------------- Int *Flag = Common->Flag ; // size n Real *W = Common->Xwork ; // size n Real *Cx = W + n ; // size n (use 2nd column of Xwork for C) Int *Stack = Common->Iwork ; // size n, also in cholmod_updown Int *Ci = Stack + n ; // size n // NOTE: cholmod_updown uses Iwork [0..n-1] as Stack as well Int mark = Common->mark ; // copy Rj/Rx into W/Ci for (Int p = 0 ; p < rnz ; p++) { Int i = Rj [p] ; ASSERT (i >= 0 && i < n) ; W [i] = Rx [p] ; Ci [p] = i ; } // At this point, W [Ci [0..rnz-1]] holds the sparse vector to add // The nonzero pattern of column W is held in Ci (it may be unsorted). //-------------------------------------------------------------------------- // symbolic factorization to get pattern of kth row of L //-------------------------------------------------------------------------- DEBUG (for (Int p = 0 ; p < rnz ; p++) PRINT1 (("C ("ID",%g)\n", Ci [p], W [Ci [p]]))) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; // flag the diagonal Flag [k] = mark ; // find the union of all the paths Int top = n ; Int lnz = 0 ; // # of nonzeros in column k of L, excluding diagonal for (Int p = 0 ; p < rnz ; p++) { Int i = Ci [p] ; if (i < k) { // walk from i = entry in Ci to root (and stop if i marked) PRINT2 (("\nwalk from i = "ID" towards k = "ID"\n", i, k)) ; Int len = 0 ; // walk up tree, but stop if we go below the diagonal while (i < k && i != EMPTY && Flag [i] < mark) { PRINT2 ((" Add "ID" to path\n", i)) ; ASSERT (i >= 0 && i < k) ; Stack [len++] = i ; // place i on the stack Flag [i] = mark ; // mark i as visited // parent is the first entry in the column after the diagonal ASSERT (Lnz [i] > 0) ; Int parent = (Lnz [i] > 1) ? (Li [Lp [i] + 1]) : EMPTY ; PRINT2 ((" parent: "ID"\n", parent)) ; i = parent ; // go up the tree } ASSERT (len <= top) ; // move the path down to the bottom of the stack // this shifts Stack [0..len-1] down to [ ... oldtop-1] while (len > 0) { Stack [--top] = Stack [--len] ; } } else if (i > k) { // prune the diagonal and upper triangular entries from Ci Ci [lnz++] = i ; Flag [i] = mark ; } } #ifndef NDEBUG PRINT1 (("length of S after prune: "ID"\n", lnz)) ; for (Int p = 0 ; p < lnz ; p++) { PRINT1 (("After prune Ci ["ID"] = "ID"\n", p, Ci [p])) ; ASSERT (Ci [p] > k) ; } #endif //-------------------------------------------------------------------------- // ensure each column of L has enough space to grow //-------------------------------------------------------------------------- for (Int kk = top ; kk < n ; kk++) { // could skip this if we knew column j already included row k Int j = Stack [kk] ; if (Lp [j] + Lnz [j] >= Lp [Lnext [j]]) { PRINT1 (("Col "ID" realloc, old Lnz "ID"\n", j, Lnz [j])) ; if (!CHOLMOD(reallocate_column) (j, Lnz [j] + 1, L, Common)) { // out of memory, L is now simplicial symbolic CLEAR_FLAG (Common) ; ASSERT (check_flag (Common)) ; for (Int i = 0 ; i < n ; i++) { W [i] = 0 ; } return (FALSE) ; } // L->i and L->x may have moved Li = L->i ; Lx = L->x ; } ASSERT (Lp [j] + Lnz [j] < Lp [Lnext [j]] || (Lp [Lnext [j]] - Lp [j] == n-j)) ; } //-------------------------------------------------------------------------- // compute kth row of L and store in column form //-------------------------------------------------------------------------- // solve L (1:k-1, 1:k-1) * y (1:k-1) = b (1:k-1) // where b (1:k) is in W and Ci // L (k, 1:k-1) = y (1:k-1) ./ D (1:k-1) // D (k) = B (k,k) - L (k, 1:k-1) * y (1:k-1) PRINT2 (("\nForward solve: "ID" to "ID"\n", top, n)) ; ASSERT (Lnz [k] >= 1 && Li [Lp [k]] == k) ; DEBUG (for (Int i = top ; i < n ; i++) PRINT2 ((" Path: "ID"\n", Stack [i]))) ; Real dk = W [k] ; W [k] = 0.0 ; // if do_solve: compute x (k) = b (k) - L (k, 1:k-1) * x (1:k-1) Real xk = bk [0] ; PRINT2 (("B [k] = %g\n", xk)) ; for (Int kk = top ; kk < n ; kk++) { Int j = Stack [kk] ; Int i = j ; PRINT2 (("Forward solve col j = "ID":\n", j)) ; ASSERT (j >= 0 && j < k) ; // forward solve using L (j+1:k-1,j) Real yj = W [j] ; W [j] = 0.0 ; Int p = Lp [j] ; Int pend = p + Lnz [j] ; ASSERT (Lnz [j] > 0) ; Real dj = Lx [p++] ; for ( ; p < pend ; p++) { i = Li [p] ; PRINT2 ((" row "ID"\n", i)) ; ASSERT (i > j) ; ASSERT (i < n) ; // stop at row k if (i >= k) { break ; } W [i] -= Lx [p] * yj ; } // each iteration of the above for loop did 2 flops, and 3 flops // are done below. so: fl += 2 * (Lp [j] - p - 1) + 3 becomes: fl += 2 * (Lp [j] - p) + 1 ; // scale L (k,1:k-1) and compute dot product for D (k,k) Real l_kj = yj / dj ; dk -= l_kj * yj ; // compute dot product for X(k) if (do_solve) { xk -= l_kj * Xx [j] ; } // store l_kj in the jth column of L // and shift the rest of the column down Int li = k ; Real lx = l_kj ; if (i == k) { // no need to modify the nonzero pattern of L, since it already // contains row index k. ASSERT (Li [p] == k) ; Lx [p] = l_kj ; for (p++ ; p < pend ; p++) { i = Li [p] ; Real l_ij = Lx [p] ; ASSERT (i > k && i < n) ; PRINT2 ((" apply to row "ID" of column k of L\n", i)) ; // add to the pattern of the kth column of L if (Flag [i] < mark) { PRINT2 ((" add Ci["ID"] = "ID"\n", lnz, i)) ; ASSERT (i > k) ; Ci [lnz++] = i ; Flag [i] = mark ; } // apply the update to the kth column of L // yj is equal to l_kj * d_j W [i] -= l_ij * yj ; } } else { PRINT2 (("Shift col j = "ID", apply saxpy to col k of L\n", j)) ; for ( ; p < pend ; p++) { // swap (Li [p],Lx [p]) with (li,lx) i = Li [p] ; Real l_ij = Lx [p] ; Li [p] = li ; Lx [p] = lx ; li = i ; lx = l_ij ; ASSERT (i > k && i < n) ; PRINT2 ((" apply to row "ID" of column k of L\n", i)) ; // add to the pattern of the kth column of L if (Flag [i] < mark) { PRINT2 ((" add Ci["ID"] = "ID"\n", lnz, i)) ; ASSERT (i > k) ; Ci [lnz++] = i ; Flag [i] = mark ; } // apply the update to the kth column of L // yj is equal to l_kj * d_j W [i] -= l_ij * yj ; } // store the last value in the jth column of L Li [p] = li ; Lx [p] = lx ; Lnz [j]++ ; } } //-------------------------------------------------------------------------- // merge C with the pattern of the existing column of L //-------------------------------------------------------------------------- // This column should be zero, but it may contain explicit zero entries. // These entries should be kept, not dropped. Int p = Lp [k] ; Int pend = p + Lnz [k] ; for (p++ ; p < pend ; p++) { Int i = Li [p] ; // add to the pattern of the kth column of L if (Flag [i] < mark) { PRINT2 ((" add Ci["ID"] = "ID" from existing col k\n", lnz, i)) ; ASSERT (i > k) ; Ci [lnz++] = i ; Flag [i] = mark ; } } //-------------------------------------------------------------------------- // update X(k) //-------------------------------------------------------------------------- if (do_solve) { Xx [k] = xk ; PRINT2 (("Xx [k] = %g\n", Xx [k])) ; } //-------------------------------------------------------------------------- // ensure abs (dk) >= dbound/sbound, if given //-------------------------------------------------------------------------- #ifdef DOUBLE dk = (Common->dbound > 0) ? (CHOLMOD(dbound) (dk, Common)) : dk ; #else dk = (Common->sbound > 0) ? (CHOLMOD(sbound) (dk, Common)) : dk ; #endif PRINT2 (("D [k = "ID"] = %g\n", k, dk)) ; //-------------------------------------------------------------------------- // store the kth column of L //-------------------------------------------------------------------------- // ensure the new column of L has enough space if (Lp [k] + lnz + 1 > Lp [Lnext [k]]) { PRINT1 (("New Col "ID" realloc, old Lnz "ID"\n", k, Lnz [k])) ; if (!CHOLMOD(reallocate_column) (k, lnz + 1, L, Common)) { // out of memory, L is now simplicial symbolic CHOLMOD(clear_flag) (Common) ; for (Int i = 0 ; i < n ; i++) { W [i] = 0 ; } return (FALSE) ; } // L->i and L->x may have moved Li = L->i ; Lx = L->x ; } ASSERT (Lp [k] + lnz + 1 <= Lp [Lnext [k]]) ; #ifndef NDEBUG PRINT2 (("\nPrior to sort: lnz "ID" (excluding diagonal)\n", lnz)) ; for (Int kk = 0 ; kk < lnz ; kk++) { Int i = Ci [kk] ; PRINT2 (("L ["ID"] kept: "ID" %e\n", kk, i, W [i] / dk)) ; } #endif // sort Ci qsort (Ci, lnz, sizeof (Int), (int (*) (const void *, const void *)) icomp); // store the kth column of L DEBUG (Int lastrow = k) ; p = Lp [k] ; Lx [p++] = dk ; Lnz [k] = lnz + 1 ; fl += lnz ; for (Int kk = 0 ; kk < lnz ; kk++, p++) { Int i = Ci [kk] ; PRINT2 (("L ["ID"] after sort: "ID", %e\n", kk, i, W [i] / dk)) ; ASSERT (i > lastrow) ; Li [p] = i ; Lx [p] = W [i] / dk ; W [i] = 0.0 ; DEBUG (lastrow = i) ; } // compute DeltaB for updown (in DeltaB) if (do_solve) { Int p = Lp [k] ; Int pend = p + Lnz [k] ; for (p++ ; p < pend ; p++) { ASSERT (Li [p] > k) ; Nx [Li [p]] -= Lx [p] * xk ; } } // clear the flag for the update mark = CHOLMOD(clear_flag) (Common) ; // workspaces are now cleared ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 2*n, R->dtype, Common)) ; //-------------------------------------------------------------------------- // update/downdate //-------------------------------------------------------------------------- // update or downdate L (k+1:n, k+1:n) with the vector // C = L (:,k) * sqrt (abs (D [k])). // Do a numeric update if D[k] < 0, numeric downdate otherwise. int ok = TRUE ; Common->modfl = 0 ; PRINT1 (("rowadd update lnz = "ID"\n", lnz)) ; if (lnz > 0) { bool do_update = (dk < 0) ; if (do_update) { dk = -dk ; } Real sqrt_dk = sqrt (dk) ; Int p = Lp [k] + 1 ; for (Int kk = 0 ; kk < lnz ; kk++, p++) { Cx [kk] = Lx [p] * sqrt_dk ; } fl += lnz + 1 ; // create a n-by-1 sparse matrix to hold the single column cholmod_sparse *C, Cmatrix ; Int Cp [2] ; C = &Cmatrix ; C->nrow = n ; C->ncol = 1 ; C->nzmax = lnz ; C->sorted = TRUE ; C->packed = TRUE ; C->p = Cp ; C->i = Ci ; C->x = Cx ; C->nz = NULL ; C->itype = L->itype ; C->xtype = L->xtype ; C->dtype = L->dtype ; C->z = NULL ; C->stype = 0 ; Cp [0] = 0 ; Cp [1] = lnz ; // numeric downdate if dk > 0, and optional Lx=b change // workspace: Flag (nrow), Head (nrow+1), W (nrow), Iwork (2*nrow) ok = CHOLMOD(updown_mark) (do_update ? (1) : (0), C, colmark, L, X, DeltaB, Common) ; // clear workspace for (Int kk = 0 ; kk < lnz ; kk++) { Cx [kk] = 0 ; } } Common->modfl += fl ; return (ok) ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Modify/t_cholmod_updown_wdim.c0000644000175100001440000001617414552026002023643 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Modify/t_cholmod_updown_wdim: template for t_cholmod_updown_worker //------------------------------------------------------------------------------ // CHOLMOD/Modify Module. Copyright (C) 2005-2023, Timothy A. Davis, // and William W. Hager. All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // Updates/downdates the LDL' factorization, by computing a new factorization of // // Lnew * Dnew * Lnew' = Lold * Dold * Lold' +/- C*C' // // This file is not compiled separately. It is #included twice into // t_cholmod_updown_worker.c, to create all the kernels for double and single // precision update/downdate. There are no user-callable routines in this // file. // // The next #include statements, below, create the numerical update/downdate // kernels from t_cholmod_updown_numkr.c. For the double case, there are 4 // compiled versions of this file, one for each value of WDIM in the set 1, 2, // 4, and 8. Each calls multiple versions of t_cholmod_updown_numkr; the // number of versions of each is equal to WDIM. Each t_cholmod_updown_numkr // version is #included as a static function within its t_cholmod_updown_wdim.c // caller routine. Thus, for the double case: // // t*_updown_wdim.c creates these versions of t_cholmod_updown_numkr.c: // ---------------- --------------------------------------------------- // // d_updown_1_r d_updown_1_1 // // d_updown_2_r d_updown_2_1 d_updown_2_2 // // d_updown_4_r d_updown_4_1 d_updown_4_2 d_updown_4_3 d_updown_4_4 // // d_updown_8_r d_updown_8_1 d_updown_8_2 d_updown_8_3 d_updown_8_4 // d_updown_8_5 d_updown_8_6 d_updown_8_7 d_updown_8_8 // // For the single (float) case, all the functions are named s_updown_*_*. // // workspace: Xwork (nrow*wdim) //------------------------------------------------------------------------------ // routines for numeric update/downdate along one path //------------------------------------------------------------------------------ #define RANK 1 #include "t_cholmod_updown_numkr.c" #if WDIM >= 2 #define RANK 2 #include "t_cholmod_updown_numkr.c" #endif #if WDIM >= 4 #define RANK 3 #include "t_cholmod_updown_numkr.c" #define RANK 4 #include "t_cholmod_updown_numkr.c" #endif #if WDIM == 8 #define RANK 5 #include "t_cholmod_updown_numkr.c" #define RANK 6 #include "t_cholmod_updown_numkr.c" #define RANK 7 #include "t_cholmod_updown_numkr.c" #define RANK 8 #include "t_cholmod_updown_numkr.c" #endif //------------------------------------------------------------------------------ // numeric update/downdate for all paths //------------------------------------------------------------------------------ static void UPDOWN (WDIM, r) // WDIM is a compile-time constant (1,2,4, or 8) ( int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // in packed or unpacked, and sorted form // no empty columns Int rank, // rank of the update/downdate cholmod_factor *L, // with unit diagonal (diagonal not stored) // temporary workspaces: Real W [ ], // n-by-WDIM dense matrix, initially zero Path_type Path [ ], Int npaths, Int mask [ ], // size n Int maskmark, cholmod_common *Common ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Real Alpha [8] ; Real *Cx, *Wpath, *W1, *a ; Int i, j, p, ccol, pend, wfirst, e, path, packed ; Int *Ci, *Cp, *Cnz ; Ci = C->i ; Cx = C->x ; Cp = C->p ; Cnz = C->nz ; packed = C->packed ; ASSERT (IMPLIES (!packed, Cnz != NULL)) ; ASSERT (L->n == C->nrow) ; DEBUG (CHOLMOD(dump_real) ("num_d: in W:", W, L->dtype, WDIM, L->n, FALSE, 1, Common)) ; //-------------------------------------------------------------------------- // scatter C into W //-------------------------------------------------------------------------- for (path = 0 ; path < rank ; path++) { // W (:, path) = C (:, Path [path].col) ccol = Path [path].ccol ; Wpath = W + path ; PRINT1 (("Ordered Columns [path = "ID"] = "ID"\n", path, ccol)) ; p = Cp [ccol] ; pend = (packed) ? (Cp [ccol+1]) : (p + Cnz [ccol]) ; // column C can be empty for ( ; p < pend ; p++) { i = Ci [p] ; ASSERT (i >= 0 && i < (Int) (C->nrow)) ; if (mask == NULL || mask [i] < maskmark) { Wpath [WDIM * i] = Cx [p] ; } PRINT1 ((" row "ID" : %g mask "ID"\n", i, Cx [p], (mask) ? mask [i] : 0)) ; } Alpha [path] = 1.0 ; } DEBUG (CHOLMOD(dump_real) ("num_d: W:", W, L->dtype, WDIM, L->n, FALSE, 1,Common)) ; //-------------------------------------------------------------------------- // numeric update/downdate of the paths //-------------------------------------------------------------------------- // for each disjoint subpath in Tbar in DFS order do for (path = rank ; path < npaths ; path++) { // determine which columns of W to use wfirst = Path [path].wfirst ; e = Path [path].end ; j = Path [path].start ; ASSERT (e >= 0 && e < (Int) (L->n)) ; ASSERT (j >= 0 && j < (Int) (L->n)) ; W1 = W + wfirst ; // pointer to row 0, column wfirst of W a = Alpha + wfirst ; // pointer to Alpha [wfirst] PRINT1 (("Numerical update/downdate of path "ID"\n", path)) ; PRINT1 (("start "ID" end "ID" wfirst "ID" rank "ID" ccol "ID"\n", j, e, wfirst, Path [path].rank, Path [path].ccol)) ; #if WDIM == 1 UPDOWN (WDIM,1) (update, j, e, a, W1, L, Common) ; #else switch (Path [path].rank) { case 1: UPDOWN (WDIM,1) (update, j, e, a, W1, L, Common) ; break ; #if WDIM >= 2 case 2: UPDOWN (WDIM,2) (update, j, e, a, W1, L, Common) ; break ; #endif #if WDIM >= 4 case 3: UPDOWN (WDIM,3) (update, j, e, a, W1, L, Common) ; break ; case 4: UPDOWN (WDIM,4) (update, j, e, a, W1, L, Common) ; break ; #endif #if WDIM == 8 case 5: UPDOWN (WDIM,5) (update, j, e, a, W1, L, Common) ; break ; case 6: UPDOWN (WDIM,6) (update, j, e, a, W1, L, Common) ; break ; case 7: UPDOWN (WDIM,7) (update, j, e, a, W1, L, Common) ; break ; case 8: UPDOWN (WDIM,8) (update, j, e, a, W1, L, Common) ; break ; #endif } #endif } } // prepare for the next inclusion of this file in t_cholmod_updown_worker.c #undef WDIM Matrix/src/SuiteSparse/CHOLMOD/Modify/t_cholmod_updown_worker.c0000644000175100001440000013130414552026002024205 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Modify/t_cholmod_updown_worker: sparse Cholesky update/downdate //------------------------------------------------------------------------------ // CHOLMOD/Modify Module. Copyright (C) 2005-2023, Timothy A. Davis, // and William W. Hager. All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // This method, TEMPLATE (cholmod_updown_worker), is #included twice in // cholmod_updown.c, to create rs_cholmod_updown_worker for the single case, // and r_cholmod_updown_worker for the double case. // t_cholmod_update_wdim.c is #included four times below, to create the set of // update/downdate methods for each value of WDIM (1, 2, 4, and 8). Then each // of the four t_cholmod_update_wdim.c methods in turn #includes // t_cholmod_updown_numkr.c WDIM times. #include "cholmod_template.h" //------------------------------------------------------------------------------ // templates for each size of W //------------------------------------------------------------------------------ #undef UPDOWN #ifdef DOUBLE // double: d_updown_k_rank #define UPDOWN(k,rank) UPDOWN_METHOD(d_,k,rank) #else // single: s_updown_k_rank #define UPDOWN(k,rank) UPDOWN_METHOD(s_,k,rank) #endif #define WDIM 1 #include "t_cholmod_updown_wdim.c" #define WDIM 2 #include "t_cholmod_updown_wdim.c" #define WDIM 4 #include "t_cholmod_updown_wdim.c" #define WDIM 8 #include "t_cholmod_updown_wdim.c" //------------------------------------------------------------------------------ // debug routine //------------------------------------------------------------------------------ #ifndef NDEBUG static void TEMPLATE (dump_col) ( char *w, Int j, Int p1, Int p2, Int *Li, Real *Lx, Int n, cholmod_common *Common ) { Int p, row, lastrow ; if (CHOLMOD(dump) < -1) { // no checks if debug level is -2 or less return ; } PRINT3 (("\n\nDUMP COL==== j = "ID" %s: p1="ID" p2="ID" \n", j, w, p1,p2)); lastrow = -1 ; for (p = p1 ; p < p2 ; p++) { PRINT3 ((" "ID": ", p)) ; row = Li [p] ; PRINT3 ((""ID" ", Li [p])) ; PRINT3 (("%g ", Lx [p])) ; PRINT3 (("\n")) ; ASSERT (row > lastrow && row < n) ; lastrow = row ; } ASSERT (p1 < p2) ; ASSERT (Li [p1] == j) ; PRINT3 (("\n")) ; } #endif //------------------------------------------------------------------------------ // t_cholmod_updown_worker: for the single and double cases //------------------------------------------------------------------------------ static int TEMPLATE (cholmod_updown_worker) ( // input: Int k, // maximum rank for each update/downdate int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // the incoming sparse update Int *colmark, // array of size n. See cholmod_updown.c for details Int *mask, // size n Int maskmark, // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Int *Set_ps1 [32], *Set_ps2 [32] ; Path_type OrderedPath [32], Path [32] ; Int npaths, i, j, row, packed, ccol, p, jj, j2, kk, nextj, p1, p2, c, newlnz, newpath, path_order, w_order, scattered, path, pp1, pp2, smax, maxrow, row1, nsets, s, p3, newlnz1, Set [32], top, len, lnz, m, botrow ; DEBUG (Int oldparent) ; Int mark = Common->mark ; Int *Ci = C->i ; Int *Cp = C->p ; Int *Cnz = C->nz ; packed = C->packed ; Int cncol = C->ncol ; ASSERT (IMPLIES (!packed, Cnz != NULL)) ; Real *Xx, *Nx ; bool do_solve = (X != NULL) && (DeltaB != NULL) ; if (do_solve) { Xx = X->x ; Nx = DeltaB->x ; } else { Xx = NULL ; Nx = NULL ; } Int n = L->n ; Int *Li = L->i ; Real *Lx = L->x ; Int *Lp = L->p ; Int *Lnz = L->nz ; Int *Lnext = L->next ; ASSERT (Lnz != NULL) ; Int wdim = Power2 [k] ; // number of columns in W double fl = 0 ; bool use_colmark = (colmark != NULL) ; #ifndef NDEBUG Int *ps1 = NULL ; #endif Int *ps2 = NULL ; //-------------------------------------------------------------------------- // get workspace //-------------------------------------------------------------------------- Int *Flag = Common->Flag ; // size n, Flag [i] <= mark must hold Int *Head = Common->Head ; // size n, Head [i] == EMPTY must hold Real *W = Common->Xwork ; // size n-by-wdim, zero on input and output // note that Iwork [n .. 2*n-1] (i/i/l) may be in use in rowadd/rowdel: Int *Iwork = Common->Iwork ; Int *Stack = Iwork ; // size n, uninitialized //-------------------------------------------------------------------------- // entire rank-cncol update, done as a sequence of rank-k updates //-------------------------------------------------------------------------- for (Int k1 = 0 ; k1 < cncol ; k1 += k) { //---------------------------------------------------------------------- // get the next k columns of C for the update/downdate //---------------------------------------------------------------------- // the last update/downdate might be less than rank-k if (k > cncol - k1) { k = cncol - k1 ; wdim = Power2 [k] ; } Int k2 = k1 + k - 1 ; // workspaces are in the following state, on input and output ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, wdim, L->dtype, Common)) ; //---------------------------------------------------------------------- // create a zero-length path for each column of W //---------------------------------------------------------------------- nextj = n ; path = 0 ; for (ccol = k1 ; ccol <= k2 ; ccol++) { PRINT1 (("Column ["ID"]: "ID"\n", path, ccol)) ; ASSERT (ccol >= 0 && ccol <= cncol) ; pp1 = Cp [ccol] ; pp2 = (packed) ? (Cp [ccol+1]) : (pp1 + Cnz [ccol]) ; // get the row index j of the first entry in C (:,ccol) if (pp2 > pp1) { // Column ccol of C has at least one entry. j = Ci [pp1] ; } else { // Column ccol of C is empty. Pretend it has one entry in // the last column with numerical value of zero. j = n-1 ; } ASSERT (j >= 0 && j < n) ; // find first column to work on nextj = MIN (nextj, j) ; Path [path].ccol = ccol ; // which column of C this path is for Path [path].start = EMPTY ; // paths for C have zero length Path [path].end = EMPTY ; Path [path].parent = EMPTY ; // no parent yet Path [path].rank = 1 ; // one column of W Path [path].c = EMPTY ; // no child of this path (case A) Path [path].next = Head [j] ; // this path is pending at col j Path [path].pending = j ; // this path is pending at col j Head [j] = path ; // this path is pending at col j PRINT1(("Path "ID" starts: start "ID" end "ID" parent "ID" c "ID"" "j "ID" ccol "ID"\n", path, Path [path].start, Path [path].end, Path [path].parent, Path [path].c, j, ccol)) ; // initialize botrow for this path Path [path].botrow = (use_colmark) ? colmark [ccol] : n ; path++ ; } // we start with paths 0 to k-1. Next one (now unused) is npaths npaths = k ; j = nextj ; ASSERT (j < n) ; scattered = FALSE ; //---------------------------------------------------------------------- // symbolic update of columns of L //---------------------------------------------------------------------- while (j < n) { ASSERT (j >= 0 && j < n && Lnz [j] > 0) ; // the old column, Li [p1..p2-1]. D (j,j) is stored in Lx [p1] p1 = Lp [j] ; newlnz = Lnz [j] ; p2 = p1 + newlnz ; #ifndef NDEBUG PRINT1 (("\n=========Column j="ID" p1 "ID" p2 "ID" lnz "ID" \n", j, p1, p2, newlnz)) ; TEMPLATE (dump_col) ("Old", j, p1, p2, Li, Lx, n, Common) ; oldparent = (Lnz [j] > 1) ? (Li [p1 + 1]) : EMPTY ; ASSERT (CHOLMOD(dump_work) (TRUE, FALSE, 0, 0, Common)) ; ASSERT (!scattered) ; PRINT1 (("Col "ID": Checking paths, npaths: "ID"\n", j, npaths)) ; for (kk = 0 ; kk < npaths ; kk++) { Int kk2, found, j3 = Path [kk].pending ; PRINT2 (("Path "ID" pending at "ID".\n", kk, j3)) ; if (j3 != EMPTY) { // Path kk must be somewhere in link list for column j3 ASSERT (Head [j3] != EMPTY) ; PRINT3 ((" List at "ID": ", j3)) ; found = FALSE ; for (kk2 = Head [j3] ; kk2 != EMPTY ; kk2 = Path [kk2].next) { PRINT3 ((""ID" ", kk2)) ; ASSERT (Path [kk2].pending == j3) ; found = found || (kk2 == kk) ; } PRINT3 (("\n")) ; ASSERT (found) ; } } PRINT1 (("\nCol "ID": Paths at this column, head "ID"\n", j, Head [j])); ASSERT (Head [j] != EMPTY) ; for (kk = Head [j] ; kk != EMPTY ; kk = Path [kk].next) { PRINT1 (("path "ID": (c="ID" j="ID") npaths "ID"\n", kk, Path[kk].c, j, npaths)) ; ASSERT (kk >= 0 && kk < npaths) ; ASSERT (Path [kk].pending == j) ; } #endif //------------------------------------------------------------------ // determine the path we're on //------------------------------------------------------------------ // get the first old path at column j path = Head [j] ; //------------------------------------------------------------------ // update/downdate of forward solve, Lx=b //------------------------------------------------------------------ if (do_solve) { Real xj = Xx [j] ; if (xj != 0) { xj = Xx [j] ; // This is first time column j has been seen for entire // rank-k update/downdate. // DeltaB += Lold (j:botrow-1,j) * X (j) Nx [j] += xj ; // diagonal of L // find the botrow for this column botrow = (use_colmark) ? Path [path].botrow : n ; for (p = p1 + 1 ; p < p2 ; p++) { i = Li [p] ; if (i >= botrow) { break ; } Nx [i] += Lx [p] * xj ; } // clear X[j] to flag col j of Lold as having been seen. If // X (j) was initially zero, then the above code is never // executed for column j. This is safe, since if xj=0 the // code above does not do anything anyway. Xx [j] = 0.0 ; } } //------------------------------------------------------------------ // start a new path at this column if two or more paths merge //------------------------------------------------------------------ newpath = // start a new path if paths have merged (Path [path].next != EMPTY) // or if j is the first node on a path (case A). || (Path [path].c == EMPTY) ; if (newpath) { // get the botrow of the first path at column j botrow = (use_colmark) ? Path [path].botrow : n ; path = npaths++ ; ASSERT (npaths <= 3*k) ; Path [path].ccol = EMPTY ; // no single col of C for this path Path [path].start = j ; // path starts at this column j Path [path].end = EMPTY ; // don't know yet where it ends Path [path].parent = EMPTY ;// don't know parent path yet Path [path].rank = 0 ; // rank is sum of child path ranks PRINT1 (("Path "ID" starts: start "ID" end "ID" parent "ID"\n", path, Path [path].start, Path [path].end, Path [path].parent)) ; // set the botrow of the new path Path [path].botrow = (use_colmark) ? botrow : n ; } //------------------------------------------------------------------ // for each path kk pending at column j //------------------------------------------------------------------ // make a list of the sets that need to be merged into column j nsets = 0 ; for (kk = Head [j] ; kk != EMPTY ; kk = Path [kk].next) { //-------------------------------------------------------------- // path kk is at (c,j) //-------------------------------------------------------------- c = Path [kk].c ; ASSERT (c < j) ; PRINT1 (("TUPLE on path "ID" (c="ID" j="ID")\n", kk, c, j)) ; ASSERT (Path [kk].pending == j) ; if (newpath) { // finalize path kk and find rank of this path Path [kk].end = c ; // end of old path is previous node c Path [kk].parent = path ; // parent is this path Path [path].rank += Path [kk].rank ; // sum up ranks Path [kk].pending = EMPTY ; PRINT1 (("Path "ID" done:start "ID" end "ID" parent "ID"\n", kk, Path [kk].start, Path [kk].end, Path [kk].parent)) ; } if (c == EMPTY) { //---------------------------------------------------------- // CASE A: first node in path //---------------------------------------------------------- // update: add pattern of incoming column // Column ccol of C is in Ci [pp1 ... pp2-1] ccol = Path [kk].ccol ; pp1 = Cp [ccol] ; pp2 = (packed) ? (Cp [ccol+1]) : (pp1 + Cnz [ccol]) ; PRINT1 (("Case A, ccol = "ID" len "ID"\n", ccol, pp2-pp1)) ; ASSERT (IMPLIES (pp2 > pp1, Ci [pp1] == j)) ; if (!scattered) { // scatter the original pattern of column j of L for (p = p1 ; p < p2 ; p++) { Flag [Li [p]] = mark ; } scattered = TRUE ; } // scatter column ccol of C (skip first entry, j) newlnz1 = newlnz ; for (p = pp1 + 1 ; p < pp2 ; p++) { row = Ci [p] ; if (Flag [row] < mark) { // this is a new entry in Lj' Flag [row] = mark ; newlnz++ ; } } if (newlnz1 != newlnz) { // column ccol of C adds something to column j of L Set [nsets++] = FLIP (ccol) ; } } else if (Head [c] == 1) { //---------------------------------------------------------- // CASE B: c is old, but changed, child of j // CASE C: new child of j //---------------------------------------------------------- // Head [c] is 1 if col c of L has new entries, // EMPTY otherwise Flag [c] = 0 ; Head [c] = EMPTY ; // update: add Lc' // column c of L is in Li [pp1 .. pp2-1] pp1 = Lp [c] ; pp2 = pp1 + Lnz [c] ; PRINT1 (("Case B/C: c = "ID"\n", c)) ; DEBUG (TEMPLATE (dump_col) ("Child", c, pp1, pp2, Li, Lx, n, Common)) ; ASSERT (j == Li [pp1 + 1]) ; // j is new parent of c if (!scattered) { // scatter the original pattern of column j of L for (p = p1 ; p < p2 ; p++) { Flag [Li [p]] = mark ; } scattered = TRUE ; } // scatter column c of L (skip first two entries, c and j) newlnz1 = newlnz ; for (p = pp1 + 2 ; p < pp2 ; p++) { row = Li [p] ; if (Flag [row] < mark) { // this is a new entry in Lj' Flag [row] = mark ; newlnz++ ; } } PRINT2 (("\n")) ; if (newlnz1 != newlnz) { // column c of L adds something to column j of L Set [nsets++] = c ; } } } //------------------------------------------------------------------ // update the pattern of column j of L //------------------------------------------------------------------ // Column j of L will be in Li/Lx [p1 .. p3-1] p3 = p1 + newlnz ; ASSERT (IMPLIES (nsets == 0, newlnz == Lnz [j])) ; PRINT1 (("p1 "ID" p2 "ID" p3 "ID" nsets "ID"\n", p1, p2, p3,nsets)); //------------------------------------------------------------------ // ensure we have enough space for the longer column //------------------------------------------------------------------ if (nsets > 0 && p3 > Lp [Lnext [j]]) { PRINT1 (("Col realloc: j "ID" newlnz "ID"\n", j, newlnz)) ; if (!CHOLMOD(reallocate_column) (j, newlnz, L, Common)) { // out of memory, L is now simplicial symbolic CHOLMOD(clear_flag) (Common) ; for (j = 0 ; j <= n ; j++) { Head [j] = EMPTY ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, wdim, L->dtype, Common)) ; return (FALSE) ; } // L->i and L->x may have moved. Column j has moved too Li = L->i ; Lx = L->x ; p1 = Lp [j] ; p2 = p1 + Lnz [j] ; p3 = p1 + newlnz ; } //------------------------------------------------------------------ // create set pointers //------------------------------------------------------------------ for (s = 0 ; s < nsets ; s++) { // Pattern of Set s is *(Set_ps1 [s] ... Set_ps2 [s]-1) c = Set [s] ; if (c < EMPTY) { // column ccol of C, skip first entry (j) ccol = FLIP (c) ; pp1 = Cp [ccol] ; pp2 = (packed) ? (Cp [ccol+1]) : (pp1 + Cnz [ccol]) ; ASSERT (pp2 - pp1 > 1) ; Set_ps1 [s] = &(Ci [pp1 + 1]) ; Set_ps2 [s] = &(Ci [pp2]) ; PRINT1 (("set "ID" is ccol "ID"\n", s, ccol)) ; } else { // column c of L, skip first two entries (c and j) pp1 = Lp [c] ; pp2 = pp1 + Lnz [c] ; ASSERT (Lnz [c] > 2) ; Set_ps1 [s] = &(Li [pp1 + 2]) ; Set_ps2 [s] = &(Li [pp2]) ; PRINT1 (("set "ID" is L "ID"\n", s, c)) ; } DEBUG (dump_set (s, Set_ps1, Set_ps2, j, n, Common)) ; } //------------------------------------------------------------------ // multiset merge //------------------------------------------------------------------ // Merge the sets into a single sorted set, Lj'. Before the merge // starts, column j is located in Li/Lx [p1 ... p2-1] and the // space Li/Lx [p2 ... p3-1] is empty. p1 is Lp [j], p2 is // Lp [j] + Lnz [j] (the old length of the column), and p3 is // Lp [j] + newlnz (the new and longer length of the column). // // The sets 0 to nsets-1 are defined by the Set_ps1 and Set_ps2 // pointers. Set s is located in *(Set_ps1 [s] ... Set_ps2 [s]-1). // It may be a column of C, or a column of L. All row indices i in // the sets are in the range i > j and i < n. All sets are sorted. // // The merge into column j of L is done in place. // // During the merge, p2 and p3 are updated. Li/Lx [p1..p2-1] // reflects the indices of the old column j of L that are yet to // be merged into the new column. Entries in their proper place in // the new column j of L are located in Li/Lx [p3 ... p1+newlnz-1]. // The merge finishes when p2 == p3. // // During the merge, set s consumed as it is merged into column j of // L. Its unconsumed contents are *(Set_ps1 [s] ... Set_ps2 [s]-1). // When a set is completely consumed, it is removed from the set of // sets, and nsets is decremented. // // The multiset merge and 2-set merge finishes when p2 == p3. PRINT1 (("Multiset merge p3 "ID" p2 "ID" nsets "ID"\n", p3, p2, nsets)) ; while (p3 > p2 && nsets > 1) { #ifndef NDEBUG PRINT2 (("\nMultiset merge. nsets = "ID"\n", nsets)) ; PRINT2 (("Source col p1 = "ID", p2 = "ID", p3= "ID"\n", p1, p2, p3)) ; for (p = p1 + 1 ; p < p2 ; p++) { PRINT2 ((" p: "ID" source row "ID" %g\n", p, Li[p], Lx[p])) ; ASSERT (Li [p] > j && Li [p] < n) ; } PRINT2 (("---\n")) ; for (p = p3 ; p < p1 + newlnz ; p++) { PRINT2 ((" p: "ID" target row "ID" %g\n", p, Li[p], Lx[p])) ; ASSERT (Li [p] > j && Li [p] < n) ; } for (s = 0 ; s < nsets ; s++) { dump_set (s, Set_ps1, Set_ps2, j, n, Common) ; } #endif // get the entry at the tail end of source column Lj row1 = Li [p2 - 1] ; ASSERT (row1 >= j && p2 >= p1) ; // find the largest row in all the sets maxrow = row1 ; smax = EMPTY ; for (s = nsets-1 ; s >= 0 ; s--) { ASSERT (Set_ps1 [s] < Set_ps2 [s]) ; row = *(Set_ps2 [s] - 1) ; if (row == maxrow) { // skip past this entry in set s (it is a duplicate) Set_ps2 [s]-- ; if (Set_ps1 [s] == Set_ps2 [s]) { // nothing more in this set nsets-- ; Set_ps1 [s] = Set_ps1 [nsets] ; Set_ps2 [s] = Set_ps2 [nsets] ; if (smax == nsets) { // Set smax redefined; it is now this set smax = s ; } } } else if (row > maxrow) { maxrow = row ; smax = s ; } } ASSERT (maxrow > j) ; // move the row onto the stack of the target column if (maxrow == row1) { // next entry is in Lj, move to the bottom of Lj' ASSERT (smax == EMPTY) ; p2-- ; p3-- ; Li [p3] = maxrow ; Lx [p3] = Lx [p2] ; } else { // new entry in Lj' ASSERT (smax >= 0 && smax < nsets) ; Set_ps2 [smax]-- ; p3-- ; Li [p3] = maxrow ; Lx [p3] = 0.0 ; if (Set_ps1 [smax] == Set_ps2 [smax]) { // nothing more in this set nsets-- ; Set_ps1 [smax] = Set_ps1 [nsets] ; Set_ps2 [smax] = Set_ps2 [nsets] ; PRINT1 (("Set "ID" now empty\n", smax)) ; } } } //------------------------------------------------------------------ // 2-set merge: //------------------------------------------------------------------ // This the same as the multi-set merge, except there is only one // set s = 0 left. The source column j and the set 0 are being // merged into the target column j. if (nsets > 0) { #ifndef NDEBUG ps1 = Set_ps1 [0] ; #endif ps2 = Set_ps2 [0] ; } while (p3 > p2) { #ifndef NDEBUG PRINT2 (("\n2-set merge.\n")) ; ASSERT (nsets == 1) ; PRINT2 (("Source col p1 = "ID", p2 = "ID", p3= "ID"\n", p1, p2, p3)) ; for (p = p1 + 1 ; p < p2 ; p++) { PRINT2 ((" p: "ID" source row "ID" %g\n", p, Li[p], Lx[p])) ; ASSERT (Li [p] > j && Li [p] < n) ; } PRINT2 (("---\n")) ; for (p = p3 ; p < p1 + newlnz ; p++) { PRINT2 ((" p: "ID" target row "ID" %g\n", p, Li[p], Lx[p])) ; ASSERT (Li [p] > j && Li [p] < n) ; } dump_set (0, Set_ps1, Set_ps2, j, n, Common) ; #endif if (p2 == p1 + 1) { // the top of Lj is empty; copy the set and quit while (p3 > p2) { // new entry in Lj' row = *(--ps2) ; p3-- ; Li [p3] = row ; Lx [p3] = 0.0 ; } } else { // get the entry at the tail end of Lj row1 = Li [p2 - 1] ; ASSERT (row1 > j && row1 < n) ; // get the entry at the tail end of the incoming set ASSERT (ps1 < ps2) ; row = *(ps2-1) ; ASSERT (row > j && row1 < n) ; // move the larger of the two entries to the target set if (row1 >= row) { // next entry is in Lj, move to the bottom if (row1 == row) { // skip past this entry in the set ps2-- ; } p2-- ; p3-- ; Li [p3] = row1 ; Lx [p3] = Lx [p2] ; } else { // new entry in Lj' ps2-- ; p3-- ; Li [p3] = row ; Lx [p3] = 0.0 ; } } } //------------------------------------------------------------------ // The new column j of L is now in Li/Lx [p1 ... p2-1] //------------------------------------------------------------------ p2 = p1 + newlnz ; DEBUG (TEMPLATE (dump_col) ("After merge: ", j, p1, p2, Li, Lx, n, Common)) ; fl += Path [path].rank * (6 + 4 * (double) newlnz) ; //------------------------------------------------------------------ // clear Flag; original pattern of column j L no longer marked //------------------------------------------------------------------ mark = CHOLMOD(clear_flag) (Common) ; scattered = FALSE ; //------------------------------------------------------------------ // find the new parent //------------------------------------------------------------------ Int newparent = (newlnz > 1) ? (Li [p1 + 1]) : EMPTY ; PRINT1 (("\nNew parent, Lnz: "ID": "ID" "ID"\n", j, newparent,newlnz)); ASSERT (oldparent == EMPTY || newparent <= oldparent) ; //------------------------------------------------------------------ // go to the next node in the path //------------------------------------------------------------------ // path moves to (j,nextj) unless j is a root nextj = (newparent == EMPTY) ? n : newparent ; // place path at head of list for nextj, or terminate the path PRINT1 (("\n j = "ID" nextj = "ID"\n\n", j, nextj)) ; Path [path].c = j ; if (nextj < n) { // put path on link list of pending paths at column nextj Path [path].next = Head [nextj] ; Path [path].pending = nextj ; Head [nextj] = path ; PRINT1 (("Path "ID" continues to ("ID","ID"). Rank "ID"\n", path, Path [path].c, nextj, Path [path].rank)) ; } else { // path has ended here, at a root Path [path].next = EMPTY ; Path [path].pending = EMPTY ; Path [path].end = j ; PRINT1 (("Path "ID" ends at root ("ID"). Rank "ID"\n", path, Path [path].end, Path [path].rank)) ; } // The link list Head [j] can now be emptied. Set Head [j] to 1 // if column j has changed (it is no longer used as a link list). PRINT1 (("column "ID", oldlnz = "ID"\n", j, Lnz [j])) ; Head [j] = (Lnz [j] != newlnz) ? 1 : EMPTY ; Lnz [j] = newlnz ; PRINT1 (("column "ID", newlnz = "ID"\n", j, newlnz)) ; DEBUG (TEMPLATE (dump_col) ("New", j, p1, p2, Li, Lx, n, Common)) ; // move to the next column if (k == Path [path].rank) { // only one path left j = nextj ; } else { // The current path is moving from column j to column nextj // (nextj is n if the path has ended). However, there may be // other paths pending in columns j+1 to nextj-1. There are // two methods for looking for the next column with a pending // update. The first one looks at all columns j+1 to nextj-1 // for a non-empty link list. This can be costly if j and // nextj differ by a large amount (it can be O(n), but this // entire routine may take Omega(1) time). The second method // looks at all paths and finds the smallest column at which any // path is pending. It takes O(# of paths), which is bounded // by 23: one for each column of C (up to 8), and then 15 for a // balanced binary tree with 8 leaves. However, if j and // nextj differ by a tiny amount (nextj is often j+1 near // the end of the matrix), looking at columns j+1 to nextj // would be faster. Both methods give the same answer. if (nextj - j < npaths) { // there are fewer columns to search than paths PRINT1 (("check j="ID" to nextj="ID"\n", j, nextj)) ; for (j2 = j + 1 ; j2 < nextj ; j2++) { PRINT1 (("check j="ID" "ID"\n", j2, Head [j2])) ; if (Head [j2] != EMPTY) { PRINT1 (("found, j="ID"\n", j2)) ; ASSERT (Path [Head [j2]].pending == j2) ; break ; } } } else { // there are fewer paths than columns to search j2 = nextj ; for (kk = 0 ; kk < npaths ; kk++) { jj = Path [kk].pending ; PRINT2 (("Path "ID" pending at "ID"\n", kk, jj)) ; if (jj != EMPTY) j2 = MIN (j2, jj) ; } } j = j2 ; } } // ensure workspaces are back to the values required on input ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; //---------------------------------------------------------------------- // depth-first-search of tree to order the paths //---------------------------------------------------------------------- // create lists of child paths PRINT1 (("\n\nDFS search:\n\n")) ; for (path = 0 ; path < npaths ; path++) { Path [path].c = EMPTY ; // first child of path Path [path].next = EMPTY ; // next sibling of path Path [path].order = EMPTY ; // path is not ordered yet Path [path].wfirst = EMPTY ; // 1st column of W not found yet #ifndef NDEBUG j = Path [path].start ; PRINT1 (("Path "ID" : start "ID" end "ID" parent "ID" ccol "ID"\n", path, j, Path [path].end, Path [path].parent, Path [path].ccol)) ; for ( ; ; ) { PRINT1 ((" column "ID"\n", j)) ; ASSERT (j == EMPTY || (j >= 0 && j < n)) ; if (j == Path [path].end) { break ; } ASSERT (j >= 0 && j < n) ; j = (Lnz [j] > 1) ? (Li [Lp [j] + 1]) : EMPTY ; } #endif } for (path = 0 ; path < npaths ; path++) { p = Path [path].parent ; // add path to child list of parent if (p != EMPTY) { ASSERT (p < npaths) ; Path [path].next = Path [p].c ; Path [p].c = path ; } } path_order = k ; w_order = 0 ; for (path = npaths-1 ; path >= 0 ; path--) { if (Path [path].order == EMPTY) { // this path is the root of a subtree of Tbar PRINT1 (("Root path "ID"\n", path)) ; ASSERT (path >= k) ; dfs (Path, k, path, &path_order, &w_order, 0, npaths) ; } } ASSERT (path_order == npaths) ; ASSERT (w_order == k) ; // reorder the paths for (path = 0 ; path < npaths ; path++) { // old order is path, new order is Path [path].order OrderedPath [Path [path].order] = Path [path] ; } #ifndef NDEBUG for (path = 0 ; path < npaths ; path++) { PRINT1 (("Ordered Path "ID": start "ID" end "ID" wfirst "ID" rank " ""ID" ccol "ID"\n", path, OrderedPath [path].start, OrderedPath [path].end, OrderedPath [path].wfirst, OrderedPath [path].rank, OrderedPath [path].ccol)) ; if (path < k) { ASSERT (OrderedPath [path].ccol >= 0) ; } else { ASSERT (OrderedPath [path].ccol == EMPTY) ; } } #endif //---------------------------------------------------------------------- // numeric update/downdate for all paths //---------------------------------------------------------------------- ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, wdim, L->dtype, Common)) ; switch (wdim) { case 1: UPDOWN (1,r) (update, C, k, L, W, OrderedPath, npaths, mask, maskmark, Common) ; break ; case 2: UPDOWN (2,r) (update, C, k, L, W, OrderedPath, npaths, mask, maskmark, Common) ; break ; case 4: UPDOWN (4,r) (update, C, k, L, W, OrderedPath, npaths, mask, maskmark, Common) ; break ; case 8: UPDOWN (8,r) (update, C, k, L, W, OrderedPath, npaths, mask, maskmark, Common) ; break ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, wdim, L->dtype, Common)) ; } //-------------------------------------------------------------------------- // update/downdate the forward solve //-------------------------------------------------------------------------- if (do_solve) { // We now have DeltaB += Lold (:,j) * X (j) for all columns j in union // of all paths seen during the entire rank-cncol update/downdate. For // each j in path, do DeltaB -= Lnew (:,j)*DeltaB(j) // in topological order. #ifndef NDEBUG PRINT1 (("\ndo_solve, DeltaB + Lold(:,Path)*X(Path):\n")) ; for (i = 0 ; i < n ; i++) { PRINT1 (("do_solve: "ID" %30.20e\n", i, Nx [i])) ; } #endif // Note that the downdate, if it deleted entries, would need to compute // the Stack prior to doing any downdates. // find the union of all the paths in the new L top = n ; // "top" is stack pointer, not a row or column index for (ccol = 0 ; ccol < cncol ; ccol++) { //------------------------------------------------------------------ // j = first row index of C (:,ccol) //------------------------------------------------------------------ pp1 = Cp [ccol] ; pp2 = (packed) ? (Cp [ccol+1]) : (pp1 + Cnz [ccol]) ; if (pp2 > pp1) { // Column ccol of C has at least one entry. j = Ci [pp1] ; } else { // Column ccol of C is empty j = n-1 ; } PRINT1 (("\ndo_solve: ccol= "ID"\n", ccol)) ; ASSERT (j >= 0 && j < n) ; len = 0 ; //------------------------------------------------------------------ // find the new rowmark //------------------------------------------------------------------ // Each column of C can redefine the region of L that takes part in // the update/downdate of the triangular solve Lx=b. If // i = colmark [ccol] for column C(:,ccol), then i = rowmark [j] is // redefined for all columns along the path modified by C(:,ccol). // If more than one column modifies any given column j of L, then // the rowmark of j is determined by the colmark of the least- // numbered column that affects column j. That is, if both // C(:,ccol1) and C(:,ccol2) affect column j of L, then // rowmark [j] = colmark [MIN (ccol1, ccol2)]. // // rowmark [j] is not modified if rowmark or colmark are NULL, // or if colmark [ccol] is EMPTY. botrow = (use_colmark) ? (colmark [ccol]) : EMPTY ; //------------------------------------------------------------------ // traverse from j towards root, stopping if node already visited //------------------------------------------------------------------ while (j != EMPTY && Flag [j] < mark) { PRINT1 (("do_solve: subpath j= "ID"\n", j)) ; ASSERT (j >= 0 && j < n) ; Stack [len++] = j ; // place j on the stack Flag [j] = mark ; // flag j as visited // if using colmark, mark column j with botrow ASSERT (Li [Lp [j]] == j) ; // diagonal is always present if (use_colmark) { Li [Lp [j]] = botrow ; // use the space for botrow } // go up the tree, to the parent of j j = (Lnz [j] > 1) ? (Li [Lp [j] + 1]) : EMPTY ; } //------------------------------------------------------------------ // move the path down to the bottom of the stack //------------------------------------------------------------------ ASSERT (len <= top) ; while (len > 0) { Stack [--top] = Stack [--len] ; } } #ifndef NDEBUG // Union of paths now in Stack [top..n-1] in topological order PRINT1 (("\nTopological order:\n")) ; for (i = top ; i < n ; i++) { PRINT1 (("column "ID" in full path\n", Stack [i])) ; } #endif // Do the forward solve for the full path part of L for (m = top ; m < n ; m++) { j = Stack [m] ; ASSERT (j >= 0 && j < n) ; PRINT1 (("do_solve: path j= "ID"\n", j)) ; p1 = Lp [j] ; lnz = Lnz [j] ; p2 = p1 + lnz ; Real xj = Nx [j] ; // copy new solution onto old one, for all cols in full path Xx [j] = xj ; Nx [j] = 0. ; // DeltaB -= Lnew (j+1:botrow-1,j) * deltab(j) if (use_colmark) { botrow = Li [p1] ; // get botrow Li [p1] = j ; // restore diagonal entry for (p = p1 + 1 ; p < p2 ; p++) { i = Li [p] ; if (i >= botrow) break ; Nx [i] -= Lx [p] * xj ; } } else { for (p = p1 + 1 ; p < p2 ; p++) { Nx [Li [p]] -= Lx [p] * xj ; } } } // clear the Flag mark = CHOLMOD(clear_flag) (Common) ; } //-------------------------------------------------------------------------- // successful update/downdate //-------------------------------------------------------------------------- Common->modfl = fl ; DEBUG (for (j = 0 ; j < n ; j++) ASSERT (IMPLIES (do_solve, Nx[j] == 0.))) ; return (TRUE) ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Modify/cholmod_l_rowdel.c0000644000175100001440000000100714552026002022560 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Modify/cholmod_l_rowdel.c: int64_t version of cholmod_rowdel //------------------------------------------------------------------------------ // CHOLMOD/Modify Module. Copyright (C) 2005-2023, Timothy A. Davis, // William W. Hager. All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_rowdel.c" Matrix/src/SuiteSparse/CHOLMOD/Modify/cholmod_rowdel.c0000644000175100001440000001733514552026002022260 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Modify/cholmod_rowdel: delete row/column from an LDL' factorization //------------------------------------------------------------------------------ // CHOLMOD/Modify Module. Copyright (C) 2005-2023, Timothy A. Davis, // and William W. Hager. All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // Deletes a row and column from an LDL' factorization. The row and column k // is set to the kth row and column of the identity matrix. Optionally // downdates the solution to Lx=b. // // workspace: Flag (nrow), Head (nrow+1), W (nrow*2), Iwork (2*nrow) // // Only real matrices (single or double) are supported (exception: since only // the pattern of R is used, it can have any valid xtype). #include "cholmod_internal.h" #ifndef NGPL #ifndef NMODIFY //------------------------------------------------------------------------------ // t_cholmod_rowdel_worker //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_rowdel_worker.c" #undef DOUBLE #define SINGLE #define REAL #include "t_cholmod_rowdel_worker.c" //------------------------------------------------------------------------------ // cholmod_rowdel //------------------------------------------------------------------------------ // Sets the kth row and column of L to be the kth row and column of the identity // matrix, and updates L(k+1:n,k+1:n) accordingly. To reduce the running time, // the caller can optionally provide the nonzero pattern (or an upper bound) of // kth row of L, as the sparse n-by-1 vector R. Provide R as NULL if you want // CHOLMOD to determine this itself, which is easier for the caller, but takes // a little more time. int CHOLMOD(rowdel) ( // input: size_t k, // row/column index to delete cholmod_sparse *R, // NULL, or the nonzero pattern of kth row of L // input/output: cholmod_factor *L, // factor to modify cholmod_common *Common ) { double yk [2] ; yk [0] = 0. ; yk [1] = 0. ; return (CHOLMOD(rowdel_mark) (k, R, yk, NULL, L, NULL, NULL, Common)) ; } //------------------------------------------------------------------------------ // cholmod_rowdel_solve //------------------------------------------------------------------------------ // Does the same as cholmod_rowdel, but also downdates the solution to Lx=b. // When row/column k of A is "deleted" from the system A*y=b, this can induce // a change to x, in addition to changes arising when L and b are modified. // If this is the case, the kth entry of y is required as input (yk). int CHOLMOD(rowdel_solve) ( // input: size_t k, // row/column index to delete cholmod_sparse *R, // NULL, or the nonzero pattern of kth row of L double yk [2], // kth entry in the solution to A*y=b // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) { return (CHOLMOD(rowdel_mark) (k, R, yk, NULL, L, X, DeltaB, Common)) ; } //------------------------------------------------------------------------------ // cholmod_rowdel_mark //------------------------------------------------------------------------------ // Does the same as cholmod_rowdel_solve, except only part of L is used in // the update/downdate of the solution to Lx=b. This routine is an "expert" // routine. It is meant for use in LPDASA only. // // if R == NULL then columns 0:k-1 of L are searched for row k. Otherwise, it // searches columns in the set defined by the pattern of the first column of R. // This is meant to be the pattern of row k of L (a superset of that pattern is // OK too). R must be a permutation of a subset of 0:k-1. int CHOLMOD(rowdel_mark) ( // input: size_t kdel, // row/column index to delete cholmod_sparse *R, // NULL, or the nonzero pattern of kth row of L double yk [2], // kth entry in the solution to A*y=b Int *colmark, // Int array of size 1. See cholmod_updown.c // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (L, FALSE) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_REAL, FALSE) ; Int k = kdel ; if (kdel >= L->n || k < 0) { ERROR (CHOLMOD_INVALID, "k invalid") ; return (FALSE) ; } if (R != NULL) { RETURN_IF_XTYPE_INVALID (R, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; if (R->ncol != 1 || R->nrow != L->n) { ERROR (CHOLMOD_INVALID, "R invalid") ; return (FALSE) ; } } if ((X != NULL) && (DeltaB != NULL)) { RETURN_IF_XTYPE_INVALID (X, CHOLMOD_REAL, CHOLMOD_REAL, FALSE) ; RETURN_IF_XTYPE_INVALID (DeltaB, CHOLMOD_REAL, CHOLMOD_REAL, FALSE) ; if (X->nrow != L->n || X->ncol != 1 || DeltaB->nrow != L->n || DeltaB->ncol != 1 || X->dtype != L->dtype || DeltaB->dtype != L->dtype) { ERROR (CHOLMOD_INVALID, "X and/or DeltaB invalid") ; return (FALSE) ; } } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- // s = 2*n int ok = TRUE ; size_t s = CHOLMOD(mult_size_t) (L->n, 2, &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (FALSE) ; } CHOLMOD(alloc_work) (L->n, s, s, L->dtype, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 2*n, L->dtype, Common)) ; //-------------------------------------------------------------------------- // convert to simplicial numeric LDL' factor, if not already //-------------------------------------------------------------------------- if (L->xtype == CHOLMOD_PATTERN || L->is_super || L->is_ll) { // can only update/downdate a simplicial LDL' factorization CHOLMOD(change_factor) (CHOLMOD_REAL, FALSE, FALSE, FALSE, FALSE, L, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory, L is returned unchanged return (FALSE) ; } } //-------------------------------------------------------------------------- // update L and X //-------------------------------------------------------------------------- float s_yk [2] ; s_yk [0] = (float) yk [0] ; s_yk [1] = (float) yk [1] ; switch (L->dtype & 4) { case CHOLMOD_SINGLE: ok = rs_cholmod_rowdel_worker (k, R, s_yk, colmark, L, X, DeltaB, Common) ; break ; case CHOLMOD_DOUBLE: ok = rd_cholmod_rowdel_worker (k, R, yk, colmark, L, X, DeltaB, Common) ; break ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- DEBUG (CHOLMOD(dump_factor) (L, "LDL factorization, L:", Common)) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, s, L->dtype, Common)) ; return (ok) ; } #endif #endif Matrix/src/SuiteSparse/CHOLMOD/Check/0000755000175100001440000000000014576344041016704 5ustar hornikusersMatrix/src/SuiteSparse/CHOLMOD/Check/cholmod_read.c0000644000175100001440000015005214552026002021457 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Check/cholmod_read: read a sparse matrix from a file //------------------------------------------------------------------------------ // CHOLMOD/Check Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Read a sparse matrix in triplet or dense form. A triplet matrix can be // returned as compressed-column sparse matrix. The file format is compatible // with all variations of the Matrix Market "coordinate" and "array" format // (http://www.nist.gov/MatrixMarket). The format supported by these routines // also allow other formats, where the Matrix Market header is optional. // // Although the Matrix Market header is optional, I recommend that users stick // with the strict Matrix Market format. The optional format appears here to // support the reading of symmetric matrices stored with just their upper // triangular parts present, for testing and development of the A->stype > 0 // format in CHOLMOD. That format is not included in the Matrix Market format. // // If the first line of the file starts with %%MatrixMarket, then it is // interpretted as a file in Matrix Market format. This line must have // the following format: // // %%MatrixMarket matrix // // is one of: coordinate or array. The former is a sparse matrix in // triplet form. The latter is a dense matrix in column-major form. // // is one of: real, complex, pattern, or integer. // The functions here convert the "integer" and "pattern" types to real. // // is one of: general, hermitian, symmetric, or skew-symmetric // // The strings are case-insensitive. Only the first character is // significant (or the first two for skew-symmetric). // // is ignored for all matrices; the actual type (real, complex, // or pattern) is inferred from the number of tokens in each line of the // file. For a "coordinate" matrix: 2: pattern, 3: real, 4: complex; for // a dense "array" matrix: 1: real, 2: complex. This is compatible with // the Matrix Market format, since pattern matrices must have two tokens // per line, real matrices must have 3, and complex matrices must have 4. // A storage of "general" implies an stype of zero (see below). // "symmetric" and "hermitian" imply an stype of -1. Skew-symmetric and // complex symmetric matrices are always returned with both upper and lower // triangular parts present, with an stype of zero, since CHOLMOD does not // have a method for representing skew-symmetric and complex symmetric // matrices. real symmetric and complex Hermitian matrices may optionally // be returned with both parts present. // // Any other lines starting with "%" are treated as comments, and are ignored. // Blank lines are ignored. The Matrix Market header is optional in this // routine (it is not optional in the Matrix Market format). // // Note that complex matrices are always returned in CHOLMOD_COMPLEX format, // not CHOLMOD_ZOMPLEX. // // ----------------------------------------------------------------------------- // Triplet matrices: // ----------------------------------------------------------------------------- // // The first data line of a triplet matrix contains 3 or 4 integers: // // nrow ncol nnz stype // // where stype is optional (stype does not appear in the Matrix Market format). // The matrix is nrow-by-ncol. The following nnz lines (excluding comments // and blank lines) each contain a single entry. Duplicates are permitted, // and are summed in the output matrix. // // The stype is first derived from the Matrix Market header. If the stype // appears as the fourth integer in the first data line, it is determined from // that line. // // If stype is present, it denotes the storage format for the matrix. // stype = 0 denotes an unsymmetric matrix (same as Matrix Market "general"). // stype = -1 denotes a real symmetric or complex Hermitian matrix whose lower // triangular entries are stored. Entries may be present in the upper // triangular part, but these are ignored (same as Matrix Market // "real symmetric" and "complex Hermitian"). // stype = 1 denotes a real symmetric or complex Hermitian matrix whose upper // triangular entries are stored. Entries may be present in the lower // triangular part, but these are ignored. This option is not present // in the Matrix Market format. // // If stype is not present (no Matrix Market header and not in the first data // line) it is inferred from the rest of the data. If the matrix is // rectangular, or has entries in both the upper and lower triangular parts, // then it is assumed to be unsymmetric (stype=0). If only entries in the // lower triangular part are present, the matrix is assumed to have stype = -1. // If only entries in the upper triangular part are present, the matrix is // assumed to have stype = 1. // // After the first data line (with nrow, ncol, nnz, and optionally stype), // each nonzero consists of one line with 2, 3, or 4 entries. All lines must // have the same number of entries. The first two entries are the row and // column indices of the nonzero. If 3 entries are present, the 3rd entry is // the numerical value, and the matrix is real. If 4 entries are present, // the 3rd and 4th entries in the line are the real and imaginary parts of // a complex value. // // The matrix can be either 0-based or 1-based. It is first assumed to be // one-based (all matrices in the Matrix Market are one-based), with row indices // in the range 1 to ncol and column indices in the range 1 to nrow. If a row // or column index of zero is found, the matrix is assumed to be zero-based // (with row indices in the range 0 to ncol-1 and column indices in the range 0 // to nrow-1). // // If Common->prefer_binary is set to its default value of FALSE, then // for symmetric pattern-only matrices, the kth diagonal (if present) is set to // one plus the degree of the row/column k, and the off-diagonal entries are set // to -1. A symmetric pattern-only matrix with a zero-free diagonal is thus // converted into a symmetric positive definite matrix. All entries are set to // one for an unsymmetric pattern-only matrix. This differs from the // Matrix Market format (A = mmread ('file') returns a binary pattern for A for // symmetric pattern-only matrices). If Common->prefer_binary is TRUE, then // this function returns a binary matrix (just like mmread('file')). // // ----------------------------------------------------------------------------- // Dense matrices: // ----------------------------------------------------------------------------- // // A dense matrix is specified by the Matrix Market "array" format. The // Matrix Market header is optional; if not present, the matrix is assumed to // be in the Matrix Market "general" format. The first data line contains just // two integers: // // nrow ncol // // The can be real, integer, or complex (not pattern). These functions // convert an integer type to real. The entries in the matrix are stored in // column-major format, with one line per entry. Two entries are present in // each line for complex matrices, one for real and integer matrices. In // rectangular and unsymmetric matrices, all entries are present. For real // symmetric or complex Hermitian matrices, only entries in the lower triangular // part appear. For skew-symmetric matrices, only entries in the strictly // lower triangular part appear. // // Since CHOLMOD does not have a data structure for presenting dense symmetric/ // Hermitian matrices, these functions always return a dense matrix in its // general form, with both upper and lower parts present. #ifndef NCHECK #include "cholmod_internal.h" // The MatrixMarket format specificies a maximum line length of 1024 #define MAXLINE 1030 //------------------------------------------------------------------------------ // get_line //------------------------------------------------------------------------------ // Read one line of the file, return TRUE if successful, FALSE if EOF. static int get_line (FILE *f, char *buf) { buf [0] = '\0' ; buf [1] = '\0' ; buf [MAXLINE] = '\0' ; return (fgets (buf, MAXLINE, f) != NULL) ; } //------------------------------------------------------------------------------ // fix_inf //------------------------------------------------------------------------------ // Replace huge values with +/- Inf's, since scanf and printf don't deal // with Inf's properly. static double fix_inf (double x) { if (x >= HUGE_DOUBLE) { x = INFINITY ; } else if (x <= -HUGE_DOUBLE) { x = -INFINITY ; } return (x) ; } //------------------------------------------------------------------------------ // is_blank_line //------------------------------------------------------------------------------ // TRUE if s is a blank line or comment, FALSE otherwise static int is_blank_line ( char *s ) { int c, k ; if (s [0] == '%') { // a comment line return (TRUE) ; } for (k = 0 ; k <= MAXLINE ; k++) { c = s [k] ; if (c == '\0') { // end of line break ; } if (!isspace (c)) { // non-space character return (FALSE) ; } } return (TRUE) ; } //------------------------------------------------------------------------------ // read_header //------------------------------------------------------------------------------ // Read the header. This consists of zero or more comment lines (blank, or // starting with a "%" in the first column), followed by a single data line // containing up to four numerical values. // // The first line may optionally be a Matrix Market header line, of the form // // %%MatrixMarket matrix // // The first data line of a sparse matrix in triplet form consists of 3 or 4 // numerical values: // // nrow ncol nnz stype // // where stype is optional (it does not appear in the Matrix Market file // format). The first line of a dense matrix in column-major form consists of // two numerical values: // // nrow ncol // // The stype of the matrix is determine either from the Matrix Market header, // or (optionally) from the first data line. stypes of 0 to -3 directly // correlate with the Matrix Market format; stype = 1 is an extension to that // format. // // 999: unknown (will be inferred from the data) // 1: real symmetric or complex Hermitian with upper part stored // (not in the Matrix Market format) // 0: unsymmetric (same as Matrix Market "general") // -1: real symmetric or complex Hermitian, with lower part stored // (Matrix Market "real symmetric" or "complex hermitian") // -2: real or complex skew symmetric (lower part stored, can only be // specified by Matrix Market header) // -3: complex symmetric (lower part stored) // specified by Matrix Market header) // // The Matrix Market header is optional. If stype appears in the first data // line, it is determine by that data line. Otherwise, if the Matrix Market // header appears, stype is determined from that header. If stype does not // appear, it is set to "unknown" (999). #define STYPE_UNKNOWN 999 #define STYPE_SYMMETRIC_UPPER 1 #define STYPE_UNSYMMETRIC 0 #define STYPE_SYMMETRIC_LOWER -1 #define STYPE_SKEW_SYMMETRIC -2 #define STYPE_COMPLEX_SYMMETRIC_LOWER -3 static int read_header // returns TRUE if successful, FALSE on error ( // input: FILE *f, // file to read from // output: char *buf, // a character array of size MAXLINE+1 int *mtype, // CHOLMOD_TRIPLET or CHOLMOD_DENSE size_t *nrow, // number of rows in the matrix size_t *ncol, // number of columns in the matrix size_t *nnz, // number of entries in a triplet matrix (0 for dense) int *stype // stype (see above) ) { char *p ; int first = TRUE, got_mm_header = FALSE, c, c2, is_complex, nitems ; double l1, l2, l3, l4 ; *mtype = CHOLMOD_TRIPLET ; *nrow = 0 ; *ncol = 0 ; *nnz = 0 ; *stype = STYPE_UNKNOWN ; for ( ; ; ) { //---------------------------------------------------------------------- // get the next line //---------------------------------------------------------------------- if (!get_line (f, buf)) { // premature end of file return (FALSE) ; } if (first && (strncmp (buf, "%%MatrixMarket", 14) == 0)) { //------------------------------------------------------------------ // read a Matrix Market header //------------------------------------------------------------------ got_mm_header = TRUE ; p = buf ; //------------------------------------------------------------------ // get "matrix" token //------------------------------------------------------------------ while (*p && !isspace (*p)) p++ ; while (*p && isspace (*p)) p++ ; c = tolower (*p) ; if (c != 'm') { // bad format return (FALSE) ; } //------------------------------------------------------------------ // get the fmt token ("coord" or "array") //------------------------------------------------------------------ while (*p && !isspace (*p)) p++ ; while (*p && isspace (*p)) p++ ; c = tolower (*p) ; if (c == 'c') { *mtype = CHOLMOD_TRIPLET ; } else if (c == 'a') { *mtype = CHOLMOD_DENSE ; } else { // bad format, neither "coordinate" nor "array" return (FALSE) ; } //------------------------------------------------------------------ // get type token (real, pattern, complex, integer) //------------------------------------------------------------------ while (*p && !isspace (*p)) p++ ; while (*p && isspace (*p)) p++ ; c = tolower (*p) ; if (!(c == 'r' || c == 'p' || c == 'c' || c == 'i')) { // bad format return (FALSE) ; } is_complex = (c == 'c') ; //------------------------------------------------------------------ // get storage token (general, hermitian, symmetric, skew) //------------------------------------------------------------------ while (*p && !isspace (*p)) p++ ; while (*p && isspace (*p)) p++ ; c = tolower (*p) ; c2 = tolower (*(p+1)) ; if (c == 'g') { // "general" storage (unsymmetric matrix), both parts present *stype = STYPE_UNSYMMETRIC ; } else if (c == 's' && c2 == 'y') { // "symmetric" if (is_complex) { // complex symmetric, lower triangular part present *stype = STYPE_COMPLEX_SYMMETRIC_LOWER ; } else { // real symmetric, lower triangular part present *stype = STYPE_SYMMETRIC_LOWER ; } } else if (c == 'h') { // "hermitian" matrix, lower triangular part present *stype = STYPE_SYMMETRIC_LOWER ; } else if (c == 's' && c2 == 'k') { // "skew-symmetric" (real or complex), lower part present *stype = STYPE_SKEW_SYMMETRIC ; } else { // bad format return (FALSE) ; } } else if (is_blank_line (buf)) { //------------------------------------------------------------------ // blank line or comment line //------------------------------------------------------------------ continue ; } else { //------------------------------------------------------------------ // read the first data line and return //------------------------------------------------------------------ // format: nrow ncol nnz stype l1 = EMPTY ; l2 = EMPTY ; l3 = 0 ; l4 = 0 ; nitems = sscanf (buf, "%lg %lg %lg %lg\n", &l1, &l2, &l3, &l4) ; if (nitems < 2 || nitems > 4 || l1 > (double) Int_max || l2 > (double) Int_max) { // invalid matrix return (FALSE) ; } *nrow = l1 ; *ncol = l2 ; if (nitems == 2) { // a dense matrix if (!got_mm_header) { *mtype = CHOLMOD_DENSE ; *stype = STYPE_UNSYMMETRIC ; } } if (nitems == 3 || nitems == 4) { // a sparse triplet matrix *nnz = l3 ; if (!got_mm_header) { *mtype = CHOLMOD_TRIPLET ; } } if (nitems == 4) { // an stype specified here can only be 1, 0, or -1 if (l4 < 0) { *stype = STYPE_SYMMETRIC_LOWER ; } else if (l4 > 0) { *stype = STYPE_SYMMETRIC_UPPER ; } else { *stype = STYPE_UNSYMMETRIC ; } } if (*nrow != *ncol) { // a rectangular matrix must be unsymmetric *stype = STYPE_UNSYMMETRIC ; } return (TRUE) ; } first = FALSE ; } } //------------------------------------------------------------------------------ // read_triplet //------------------------------------------------------------------------------ // Header has already been read in, including first line (nrow ncol nnz stype). // Read the triplets. static cholmod_triplet *read_triplet ( // input: FILE *f, // file to read from, must already be open size_t nrow, // number of rows size_t ncol, // number of columns size_t nnz, // number of triplets in file to read int stype, // stype from header, or "unknown" int prefer_unsym, // if TRUE, always return T->stype of zero int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE // workspace: char *buf, // of size MAXLINE+1 cholmod_common *Common ) { double x, z ; Int *Ti, *Tj, *Rdeg, *Cdeg ; cholmod_triplet *T ; double l1, l2 ; Int nitems, xtype, unknown, k, nshould, is_lower, is_upper, one_based, i, j, imax, jmax, skew_symmetric, p, complex_symmetric ; //-------------------------------------------------------------------------- // quick return for empty matrix //-------------------------------------------------------------------------- if (nrow == 0 || ncol == 0 || nnz == 0) { // return an empty matrix return (CHOLMOD(allocate_triplet) (nrow, ncol, 0, 0, CHOLMOD_REAL + dtype, Common)) ; } //-------------------------------------------------------------------------- // special stype cases: unknown, skew symmetric, and complex symmetric //-------------------------------------------------------------------------- unknown = (stype == STYPE_UNKNOWN) ; skew_symmetric = (stype == STYPE_SKEW_SYMMETRIC) ; complex_symmetric = (stype == STYPE_COMPLEX_SYMMETRIC_LOWER) ; size_t extra = 0 ; if (stype < STYPE_SYMMETRIC_LOWER || (prefer_unsym && stype != STYPE_UNSYMMETRIC)) { // 999: unknown might be converted to unsymmetric // 1: symmetric upper converted to unsym. if prefer_unsym is TRUE // -1: symmetric lower converted to unsym. if prefer_unsym is TRUE // -2: real or complex skew symmetric converted to unsymmetric // -3: complex symmetric converted to unsymmetric stype = STYPE_UNSYMMETRIC ; extra = nnz ; } int ok = TRUE ; size_t nnz2 = CHOLMOD(add_size_t) (nnz, extra, &ok) ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- // s = nrow + ncol size_t s = CHOLMOD(add_size_t) (nrow, ncol, &ok) ; if (!ok || nrow > Int_max || ncol > Int_max || nnz > Int_max) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (NULL) ; } CHOLMOD(allocate_work) (0, s, 0, Common) ; Rdeg = Common->Iwork ; // size nrow Cdeg = Rdeg + nrow ; // size ncol //-------------------------------------------------------------------------- // read the triplets //-------------------------------------------------------------------------- is_lower = TRUE ; is_upper = TRUE ; one_based = TRUE ; imax = 0 ; jmax = 0 ; Ti = NULL ; Tj = NULL ; xtype = 999 ; nshould = 0 ; for (k = 0 ; k < (Int) nnz ; k++) { //---------------------------------------------------------------------- // get the next triplet, skipping blank lines and comment lines //---------------------------------------------------------------------- l1 = EMPTY ; l2 = EMPTY ; x = 0 ; z = 0 ; for ( ; ; ) { if (!get_line (f, buf)) { // premature end of file - not enough triplets read in ERROR (CHOLMOD_INVALID, "premature EOF") ; return (NULL) ; } if (is_blank_line (buf)) { // blank line or comment continue ; } nitems = sscanf (buf, "%lg %lg %lg %lg\n", &l1, &l2, &x, &z) ; x = fix_inf (x) ; z = fix_inf (z) ; break ; } nitems = (nitems == EOF) ? 0 : nitems ; i = l1 ; j = l2 ; //---------------------------------------------------------------------- // for first triplet: determine type and allocate triplet matrix //---------------------------------------------------------------------- if (k == 0) { if (nitems < 2 || nitems > 4) { // invalid matrix ERROR (CHOLMOD_INVALID, "invalid format") ; return (NULL) ; } else if (nitems == 2) { // this will be converted into a real matrix later xtype = CHOLMOD_PATTERN ; } else if (nitems == 3) { xtype = CHOLMOD_REAL ; } else if (nitems == 4) { xtype = CHOLMOD_COMPLEX ; } // the rest of the lines should have the same number of entries nshould = nitems ; // allocate triplet matrix T = CHOLMOD(allocate_triplet) (nrow, ncol, nnz2, stype, (xtype == CHOLMOD_PATTERN ? CHOLMOD_REAL : xtype) + dtype, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (NULL) ; } Ti = T->i ; Tj = T->j ; T->nnz = nnz ; } //---------------------------------------------------------------------- // save the entry in the triplet matrix //---------------------------------------------------------------------- if (nitems != nshould || i < 0 || j < 0) { // wrong format, premature end-of-file, or negative indices CHOLMOD(free_triplet) (&T, Common) ; ERROR (CHOLMOD_INVALID, "invalid matrix file") ; return (NULL) ; } Ti [k] = i ; Tj [k] = j ; if (i < j) { // this entry is in the upper triangular part is_lower = FALSE ; } if (i > j) { // this entry is in the lower triangular part is_upper = FALSE ; } #define ASSIGN_TRIPLET_VALUE(fltype) \ { \ fltype *Tx = (fltype *) T->x ; \ if (xtype == CHOLMOD_REAL) \ { \ Tx [k] = x ; \ } \ else if (xtype == CHOLMOD_COMPLEX) \ { \ Tx [2*k ] = x ; \ Tx [2*k+1] = z ; \ } \ } if (dtype == CHOLMOD_DOUBLE) { ASSIGN_TRIPLET_VALUE (double) ; } else { ASSIGN_TRIPLET_VALUE (float) ; } if (i == 0 || j == 0) { one_based = FALSE ; } imax = MAX (i, imax) ; jmax = MAX (j, jmax) ; } //-------------------------------------------------------------------------- // convert to zero-based //-------------------------------------------------------------------------- if (one_based) { // input matrix is one-based; convert matrix to zero-based for (k = 0 ; k < (Int) nnz ; k++) { Ti [k]-- ; Tj [k]-- ; } } if (one_based ? (imax > (Int) nrow || jmax > (Int) ncol) : (imax >= (Int) nrow || jmax >= (Int) ncol)) { // indices out of range CHOLMOD(free_triplet) (&T, Common) ; ERROR (CHOLMOD_INVALID, "indices out of range") ; return (NULL) ; } //-------------------------------------------------------------------------- // determine the stype, if not yet known //-------------------------------------------------------------------------- if (unknown) { if (is_lower && is_upper) { // diagonal matrix, symmetric with upper part present stype = STYPE_SYMMETRIC_UPPER ; } else if (is_lower && !is_upper) { // symmetric, lower triangular part present stype = STYPE_SYMMETRIC_LOWER ; } else if (!is_lower && is_upper) { // symmetric, upper triangular part present stype = STYPE_SYMMETRIC_UPPER ; } else { // unsymmetric stype = STYPE_UNSYMMETRIC ; extra = 0 ; } } //-------------------------------------------------------------------------- // add the remainder of symmetric, skew-symmetric or Hermitian matrices //-------------------------------------------------------------------------- // note that this step is not done for real symmetric or complex Hermitian // matrices, unless prefer_unsym is TRUE if (extra > 0) { p = nnz ; for (k = 0 ; k < (Int) nnz ; k++) { i = Ti [k] ; j = Tj [k] ; if (i != j) { Ti [p] = j ; Tj [p] = i ; #define ASSIGN_SYMMETRIC_TRIPLET(fltype) \ { \ fltype *Tx = (fltype *) T->x ; \ if (xtype == CHOLMOD_REAL) \ { \ if (skew_symmetric) \ { \ Tx [p] = -Tx [k] ; \ } \ else \ { \ Tx [p] = Tx [k] ; \ } \ } \ else if (xtype == CHOLMOD_COMPLEX) \ { \ if (skew_symmetric) \ { \ Tx [2*p ] = -Tx [2*k ] ; \ Tx [2*p+1] = -Tx [2*k+1] ; \ } \ else if (complex_symmetric) \ { \ Tx [2*p ] = Tx [2*k ] ; \ Tx [2*p+1] = Tx [2*k+1] ; \ } \ else /* Hermitian */ \ { \ Tx [2*p ] = Tx [2*k ] ; \ Tx [2*p+1] = -Tx [2*k+1] ; \ } \ } \ } if (dtype == CHOLMOD_DOUBLE) { ASSIGN_SYMMETRIC_TRIPLET (double) ; } else { ASSIGN_SYMMETRIC_TRIPLET (float) ; } p++ ; } } T->nnz = p ; nnz = p ; } T->stype = stype ; //-------------------------------------------------------------------------- // create values for a pattern-only matrix //-------------------------------------------------------------------------- if (xtype == CHOLMOD_PATTERN) { if (stype == STYPE_UNSYMMETRIC || Common->prefer_binary) { // unsymmetric case, or binary case #define TRIPLETS_ALL_ONE(fltype) \ { \ fltype *Tx = (fltype *) T->x ; \ for (k = 0 ; k < (Int) nnz ; k++) \ { \ Tx [k] = 1 ; \ } \ } if (dtype == CHOLMOD_DOUBLE) { TRIPLETS_ALL_ONE (double) ; } else { TRIPLETS_ALL_ONE (float) ; } } else { // compute the row and columm degrees (excluding the diagonal) for (i = 0 ; i < (Int) nrow ; i++) { Rdeg [i] = 0 ; } for (j = 0 ; j < (Int) ncol ; j++) { Cdeg [j] = 0 ; } for (k = 0 ; k < (Int) nnz ; k++) { i = Ti [k] ; j = Tj [k] ; if ((stype < 0 && i > j) || (stype > 0 && i < j)) { // both a(i,j) and a(j,i) appear in the matrix Rdeg [i]++ ; Cdeg [j]++ ; Rdeg [j]++ ; Cdeg [i]++ ; } } // assign the numerical values #define TRIPLET_LAPLACIAN(fltype) \ { \ fltype *Tx = (fltype *) T->x ; \ for (k = 0 ; k < (Int) nnz ; k++) \ { \ i = Ti [k] ; \ j = Tj [k] ; \ Tx [k] = (i == j) ? (1 + MAX (Rdeg[i], Cdeg[j])) : (-1) ; \ } \ } if (dtype == CHOLMOD_DOUBLE) { TRIPLET_LAPLACIAN (double) ; } else { TRIPLET_LAPLACIAN (float) ; } } } //-------------------------------------------------------------------------- // return the new triplet matrix //-------------------------------------------------------------------------- return (T) ; } //------------------------------------------------------------------------------ // read_dense //------------------------------------------------------------------------------ // Header has already been read in, including first line (nrow ncol). // Read a dense matrix. static cholmod_dense *read_dense ( // input: FILE *f, // file to read from, must already be open size_t nrow, // number of rows size_t ncol, // number of columns int stype, // stype from header int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE // workspace: char *buf, // of size MAXLINE+1 cholmod_common *Common ) { double x, z ; cholmod_dense *X ; Int nitems, xtype = -1, nshould = 0, i, j, k, kup, first ; //-------------------------------------------------------------------------- // quick return for empty matrix //-------------------------------------------------------------------------- if (nrow == 0 || ncol == 0) { // return an empty dense matrix return (CHOLMOD(zeros) (nrow, ncol, CHOLMOD_REAL + dtype, Common)) ; } //-------------------------------------------------------------------------- // read the entries //-------------------------------------------------------------------------- first = TRUE ; for (j = 0 ; j < (Int) ncol ; j++) { //---------------------------------------------------------------------- // get the row index of the first entry in the file for column j //---------------------------------------------------------------------- if (stype == STYPE_UNSYMMETRIC) { i = 0 ; } else if (stype == STYPE_SKEW_SYMMETRIC) { i = j+1 ; } else // real symmetric or complex Hermitian lower { i = j ; } //---------------------------------------------------------------------- // get column j //---------------------------------------------------------------------- for ( ; i < (Int) nrow ; i++) { //------------------------------------------------------------------ // get the next entry, skipping blank lines and comment lines //------------------------------------------------------------------ x = 0 ; z = 0 ; for ( ; ; ) { if (!get_line (f, buf)) { // premature end of file - not enough entries read in ERROR (CHOLMOD_INVALID, "premature EOF") ; return (NULL) ; } if (is_blank_line (buf)) { // blank line or comment continue ; } nitems = sscanf (buf, "%lg %lg\n", &x, &z) ; x = fix_inf (x) ; z = fix_inf (z) ; break ; } nitems = (nitems == EOF) ? 0 : nitems ; //------------------------------------------------------------------ // for first entry: determine type and allocate dense matrix //------------------------------------------------------------------ if (first) { first = FALSE ; if (nitems < 1 || nitems > 2) { // invalid matrix ERROR (CHOLMOD_INVALID, "invalid format") ; return (NULL) ; } else if (nitems == 1) { // a real matrix xtype = CHOLMOD_REAL ; } else if (nitems == 2) { // a complex matrix xtype = CHOLMOD_COMPLEX ; } // the rest of the lines should have same number of entries nshould = nitems ; // allocate the result X = CHOLMOD(zeros) (nrow, ncol, xtype + dtype, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (NULL) ; } } //------------------------------------------------------------------ // save the entry in the dense matrix //------------------------------------------------------------------ if (nitems != nshould) { // wrong format or premature end-of-file CHOLMOD(free_dense) (&X, Common) ; ERROR (CHOLMOD_INVALID, "invalid matrix file") ; return (NULL) ; } k = i + j*nrow ; kup = j + i*nrow ; #define ASSIGN_DENSE_VALUE(fltype) \ { \ fltype *Xx = (fltype *) X->x ; \ if (xtype == CHOLMOD_REAL) \ { \ /* real matrix */ \ Xx [k] = x ; \ if (k != kup) \ { \ if (stype == STYPE_SYMMETRIC_LOWER) \ { \ /* real symmetric matrix */ \ Xx [kup] = x ; \ } \ else if (stype == STYPE_SKEW_SYMMETRIC) \ { \ /* real skew symmetric matrix */ \ Xx [kup] = -x ; \ } \ } \ } \ else if (xtype == CHOLMOD_COMPLEX) \ { \ Xx [2*k ] = x ; /* real part */ \ Xx [2*k+1] = z ; /* imaginary part */ \ if (k != kup) \ { \ if (stype == STYPE_SYMMETRIC_LOWER) \ { \ /* complex Hermitian */ \ Xx [2*kup ] = x ; /* real part */ \ Xx [2*kup+1] = -z ; /* imaginary part */ \ } \ else if (stype == STYPE_SKEW_SYMMETRIC) \ { \ /* complex skew symmetric */ \ Xx [2*kup ] = -x ; /* real part */ \ Xx [2*kup+1] = -z ; /* imaginary part */ \ } \ if (stype == STYPE_COMPLEX_SYMMETRIC_LOWER) \ { \ /* complex symmetric */ \ Xx [2*kup ] = x ; /* real part */ \ Xx [2*kup+1] = z ; /* imaginary part */ \ } \ } \ } \ } if (dtype == CHOLMOD_DOUBLE) { ASSIGN_DENSE_VALUE (double) ; } else { ASSIGN_DENSE_VALUE (float) ; } } } //-------------------------------------------------------------------------- // return the new dense matrix //-------------------------------------------------------------------------- return (X) ; } //------------------------------------------------------------------------------ // cholmod_read_triplet //------------------------------------------------------------------------------ // Read in a triplet matrix from a file (as double, not float) cholmod_triplet *CHOLMOD(read_triplet) ( // input: FILE *f, // file to read from, must already be open cholmod_common *Common ) { return (CHOLMOD(read_triplet2) (f, CHOLMOD_DOUBLE, Common)) ; } //------------------------------------------------------------------------------ // cholmod_read_triplet2 //------------------------------------------------------------------------------ // Read in a triplet matrix from a file (as float or double) cholmod_triplet *CHOLMOD(read_triplet2) ( // input: FILE *f, // file to read from, must already be open int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE cholmod_common *Common ) { char buf [MAXLINE+1] ; size_t nrow, ncol, nnz ; int stype, mtype ; //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_NULL (f, NULL) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // read the header and first data line //-------------------------------------------------------------------------- if (!read_header (f, buf, &mtype, &nrow, &ncol, &nnz, &stype) || mtype != CHOLMOD_TRIPLET) { // invalid matrix - this function can only read in a triplet matrix ERROR (CHOLMOD_INVALID, "invalid format") ; return (NULL) ; } //-------------------------------------------------------------------------- // read the triplet matrix //-------------------------------------------------------------------------- return (read_triplet (f, nrow, ncol, nnz, stype, FALSE, dtype, buf, Common)) ; } //------------------------------------------------------------------------------ // cholmod_read_sparse //------------------------------------------------------------------------------ // Read a sparse matrix from a file (as double). See cholmod_read_triplet for // a discussion of the file format. // // If Common->prefer_upper is TRUE (the default case), a symmetric matrix is // returned stored in upper-triangular form (A->stype == 1). cholmod_sparse *CHOLMOD(read_sparse) ( // input: FILE *f, // file to read from, must already be open cholmod_common *Common ) { return (CHOLMOD(read_sparse2) (f, CHOLMOD_DOUBLE, Common)) ; } //------------------------------------------------------------------------------ // cholmod_read_sparse2: read sparse matrix from a file (double or single) //------------------------------------------------------------------------------ cholmod_sparse *CHOLMOD(read_sparse2) ( // input: FILE *f, // file to read from, must already be open int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE cholmod_common *Common ) { cholmod_sparse *A, *A2 ; cholmod_triplet *T ; //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_NULL (f, NULL) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // convert to a sparse matrix in compressed-column form //-------------------------------------------------------------------------- T = CHOLMOD(read_triplet2) (f, dtype, Common) ; A = CHOLMOD(triplet_to_sparse) (T, 0, Common) ; CHOLMOD(free_triplet) (&T, Common) ; if (Common->prefer_upper && A != NULL && A->stype == -1) { // A=A' A2 = CHOLMOD(transpose) (A, 2, Common) ; CHOLMOD(free_sparse) (&A, Common) ; A = A2 ; } return (A) ; } //------------------------------------------------------------------------------ // cholmod_read_dense //------------------------------------------------------------------------------ // Read a dense matrix from a file (double only). cholmod_dense *CHOLMOD(read_dense) ( // input: FILE *f, // file to read from, must already be open cholmod_common *Common ) { return (CHOLMOD(read_dense2) (f, CHOLMOD_DOUBLE, Common)) ; } //------------------------------------------------------------------------------ // cholmod_read_dense2 //------------------------------------------------------------------------------ // Read a dense matrix from a file (float or double). cholmod_dense *CHOLMOD(read_dense2) ( // input: FILE *f, // file to read from, must already be open int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE cholmod_common *Common ) { char buf [MAXLINE+1] ; size_t nrow, ncol, nnz ; int stype, mtype ; //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_NULL (f, NULL) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // read the header and first data line //-------------------------------------------------------------------------- if (!read_header (f, buf, &mtype, &nrow, &ncol, &nnz, &stype) || mtype != CHOLMOD_DENSE) { // invalid matrix - this function can only read in a dense matrix ERROR (CHOLMOD_INVALID, "invalid format") ; return (NULL) ; } //-------------------------------------------------------------------------- // read the dense matrix //-------------------------------------------------------------------------- return (read_dense (f, nrow, ncol, stype, dtype, buf, Common)) ; } //------------------------------------------------------------------------------ // cholmod_read_matrix //------------------------------------------------------------------------------ // Read a triplet matrix, sparse matrix or a dense matrix from a file. Returns // a void pointer to either a cholmod_triplet, cholmod_sparse, or cholmod_dense // object. The type of object is passed back to the caller as the mtype // argument. The matrix is read in double precision only. void *CHOLMOD(read_matrix) ( // input: FILE *f, // file to read from, must already be open int prefer, // If 0, a sparse matrix is always return as a // cholmod_triplet form. It can have any stype // (symmetric-lower, unsymmetric, or symmetric-upper). // If 1, a sparse matrix is returned as an unsymmetric // cholmod_sparse form (A->stype == 0), with both upper and // lower triangular parts present. This is what the MATLAB // mread mexFunction does, since MATLAB does not have an // stype. // If 2, a sparse matrix is returned with an stype of 0 or // 1 (unsymmetric, or symmetric with upper part stored). // This argument has no effect for dense matrices. // output: int *mtype, // CHOLMOD_TRIPLET, CHOLMOD_SPARSE or CHOLMOD_DENSE cholmod_common *Common ) { return (CHOLMOD(read_matrix2) (f, prefer, CHOLMOD_DOUBLE, mtype, Common)) ; } //------------------------------------------------------------------------------ // cholmod_read_matrix2: same as cholmod_read_matrix, but float or double //------------------------------------------------------------------------------ void *CHOLMOD(read_matrix2) ( // input: FILE *f, // file to read from, must already be open int prefer, // see cholmod_read_matrix int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE // output: int *mtype, // CHOLMOD_TRIPLET, CHOLMOD_SPARSE or CHOLMOD_DENSE cholmod_common *Common ) { void *G = NULL ; cholmod_sparse *A, *A2 ; cholmod_triplet *T ; char buf [MAXLINE+1] ; size_t nrow, ncol, nnz ; int stype ; //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_NULL (f, NULL) ; RETURN_IF_NULL (mtype, NULL) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // read the header to determine the mtype //-------------------------------------------------------------------------- if (!read_header (f, buf, mtype, &nrow, &ncol, &nnz, &stype)) { // invalid matrix ERROR (CHOLMOD_INVALID, "invalid format") ; return (NULL) ; } //-------------------------------------------------------------------------- // read a matrix //-------------------------------------------------------------------------- if (*mtype == CHOLMOD_TRIPLET) { // read in the triplet matrix, converting to unsymmetric format if // prefer == 1 T = read_triplet (f, nrow, ncol, nnz, stype, prefer == 1, dtype, buf, Common) ; if (prefer == 0) { // return matrix in its original triplet form G = T ; } else { // return matrix in a compressed-column form A = CHOLMOD(triplet_to_sparse) (T, 0, Common) ; CHOLMOD(free_triplet) (&T, Common) ; if (A != NULL && prefer == 2 && A->stype == -1) { // convert A from symmetric-lower to symmetric-upper A2 = CHOLMOD(transpose) (A, 2, Common) ; CHOLMOD(free_sparse) (&A, Common) ; A = A2 ; } *mtype = CHOLMOD_SPARSE ; G = A ; } } else if (*mtype == CHOLMOD_DENSE) { // return a dense matrix G = read_dense (f, nrow, ncol, stype, dtype, buf, Common) ; } return (G) ; } #endif Matrix/src/SuiteSparse/CHOLMOD/Check/cholmod_l_write.c0000644000175100001440000000075714552026002022217 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Check/cholmod_l_write.c: int64_t version of cholmod_write //------------------------------------------------------------------------------ // CHOLMOD/Check Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_write.c" Matrix/src/SuiteSparse/CHOLMOD/Check/cholmod_l_check.c0000644000175100001440000000075714552026002022142 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Check/cholmod_l_check.c: int64_t version of cholmod_check //------------------------------------------------------------------------------ // CHOLMOD/Check Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_check.c" Matrix/src/SuiteSparse/CHOLMOD/Check/cholmod_write.c0000644000175100001440000005561714552026002021711 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Check/cholmod_write: write a matrix to a file in Matrix Market format //------------------------------------------------------------------------------ // CHOLMOD/Check Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Write a matrix to a file in Matrix Market form. // // A can be sparse or full. // // If present and non-empty, A and Z must have the same dimension. Z contains // the explicit zero entries in the matrix (which MATLAB drops). The entries // of Z appear as explicit zeros in the output file. Z is optional. If it is // an empty matrix it is ignored. Z must be sparse or empty, if present. // It is ignored if A is full. // // filename is the name of the output file. comments is file whose // contents are include after the Matrix Market header and before the first // data line. Ignored if an empty string or not present. // // Except for the workspace used by cholmod_symmetry (ncol integers) for // the sparse case, these routines use no workspace at all. #ifndef NCHECK #include "cholmod_internal.h" #define MMLEN 1024 #define MAXLINE MMLEN+6 //------------------------------------------------------------------------------ // include_comments //------------------------------------------------------------------------------ // Read in the comments file, if it exists, and copy it to the Matrix Market // file. A "%" is prepended to each line. Returns TRUE if successful, FALSE // otherwise. static int include_comments (FILE *f, const char *comments) { FILE *cf = NULL ; char buffer [MAXLINE] ; int ok = TRUE ; if (comments != NULL && comments [0] != '\0') { cf = fopen (comments, "r") ; if (cf == NULL) { return (FALSE) ; } while (ok && fgets (buffer, MAXLINE, cf) != NULL) { // ensure the line is not too long buffer [MMLEN-1] = '\0' ; buffer [MMLEN-2] = '\n' ; ok = ok && (fprintf (f, "%%%s", buffer) > 0) ; } fclose (cf) ; } return (ok) ; } //------------------------------------------------------------------------------ // get_value //------------------------------------------------------------------------------ // Get the pth value in a double or float matrix. Resulting scalar is returned // as double (x and z). static void get_value ( void *Ax_in, // real values, or real/imag. for CHOLMOD_COMPLEX type void *Az_in, // imaginary values for CHOLMOD_ZOMPLEX type Int p, // get the pth entry int xtype, // A->xtype: pattern, real, complex, or zomplex int dtype, // A->dtype: double or single double *x, // the real part double *z // the imaginary part ) { #define GET_VALUE(fltype) \ { \ fltype *Ax = (fltype *) Ax_in ; \ fltype *Az = (fltype *) Az_in ; \ switch (xtype) \ { \ case CHOLMOD_PATTERN: \ *x = 1 ; \ *z = 0 ; \ break ; \ case CHOLMOD_REAL: \ *x = (double) Ax [p] ; \ *z = 0 ; \ break ; \ case CHOLMOD_COMPLEX: \ *x = (double) Ax [2*p] ; \ *z = (double) Ax [2*p+1] ; \ break ; \ case CHOLMOD_ZOMPLEX: \ *x = (double) Ax [p] ; \ *z = (double) Az [p] ; \ break ; \ } \ } if (dtype == CHOLMOD_DOUBLE) { GET_VALUE (double) ; } else { GET_VALUE (float) ; } } //------------------------------------------------------------------------------ // print_value //------------------------------------------------------------------------------ // Print a numeric value to the file, using the shortest format that ensures // the value is written precisely. Returns TRUE if successful, FALSE otherwise. static int print_value ( FILE *f, // file to print to double x, // value to print Int is_integer // TRUE if printing as an integer ) { double y ; char s [MAXLINE], *p ; Int i, dest = 0, src = 0 ; int width, ok ; if (is_integer) { i = (Int) x ; ok = (fprintf (f, ID, i) > 0) ; return (ok) ; } //-------------------------------------------------------------------------- // handle Inf and NaN //-------------------------------------------------------------------------- // change -inf to -HUGE_DOUBLE, and change +inf and nan to +HUGE_DOUBLE if (isnan (x) || x >= HUGE_DOUBLE) { x = HUGE_DOUBLE ; } else if (x <= -HUGE_DOUBLE) { x = -HUGE_DOUBLE ; } //-------------------------------------------------------------------------- // find the smallest acceptable precision //-------------------------------------------------------------------------- for (width = 6 ; width < 20 ; width++) { sprintf (s, "%.*g", width, x) ; sscanf (s, "%lg", &y) ; if (x == y) break ; } //-------------------------------------------------------------------------- // shorten the string //-------------------------------------------------------------------------- // change "e+0" to "e", change "e+" to "e", and change "e-0" to "e-" for (i = 0 ; i < MAXLINE && s [i] != '\0' ; i++) { if (s [i] == 'e') { if (s [i+1] == '+') { dest = i+1 ; if (s [i+2] == '0') { // delete characters s[i+1] and s[i+2] src = i+3 ; } else { // delete characters s[i+1] src = i+2 ; } } else if (s [i+1] == '-') { dest = i+2 ; if (s [i+2] == '0') { // delete character s[i+2] src = i+3 ; } else { // no change break ; } } while (s [src] != '\0') { s [dest++] = s [src++] ; } s [dest] = '\0' ; break ; } } // delete the leading "0" if present and not necessary p = s ; s [MAXLINE-1] = '\0' ; i = strlen (s) ; if (i > 2 && s [0] == '0' && s [1] == '.') { // change "0.x" to ".x" p = s + 1 ; } else if (i > 3 && s [0] == '-' && s [1] == '0' && s [2] == '.') { // change "-0.x" to "-.x" s [1] = '-' ; p = s + 1 ; } //-------------------------------------------------------------------------- // print the value to the file //-------------------------------------------------------------------------- ok = (fprintf (f, "%s", p) > 0) ; return (ok) ; } //------------------------------------------------------------------------------ // print_triplet //------------------------------------------------------------------------------ // Print a triplet, converting it to one-based. Returns TRUE if successful, // FALSE otherwise. static int print_triplet ( FILE *f, // file to print to Int is_binary, // TRUE if file is "pattern" Int is_complex, // TRUE if file is "complex" Int is_integer, // TRUE if file is "integer" Int i, // row index (zero-based) Int j, // column index (zero-based) double x, // real part double z // imaginary part ) { int ok ; ok = (fprintf (f, ID " " ID, 1+i, 1+j) > 0) ; if (!is_binary) { fprintf (f, " ") ; ok = ok && print_value (f, x, is_integer) ; if (is_complex) { fprintf (f, " ") ; ok = ok && print_value (f, z, is_integer) ; } } ok = ok && (fprintf (f, "\n") > 0) ; return (ok) ; } //------------------------------------------------------------------------------ // ntriplets //------------------------------------------------------------------------------ // Compute the number of triplets that will be printed to the file // from the matrix A. static Int ntriplets ( cholmod_sparse *A, // matrix that will be printed Int is_sym // TRUE if the file is symmetric (lower part only) ) { Int *Ap, *Ai, *Anz, packed, i, j, p, pend, ncol, stype, nz = 0 ; if (A == NULL) { // the Z matrix is NULL return (0) ; } stype = A->stype ; Ap = A->p ; Ai = A->i ; Anz = A->nz ; packed = A->packed ; ncol = A->ncol ; for (j = 0 ; j < ncol ; j++) { p = Ap [j] ; pend = (packed) ? Ap [j+1] : p + Anz [j] ; for ( ; p < pend ; p++) { i = Ai [p] ; if ((stype < 0 && i >= j) || (stype == 0 && (i >= j || !is_sym))) { // CHOLMOD matrix is symmetric-lower (and so is the file); // or CHOLMOD matrix is unsymmetric and either A(i,j) is in // the lower part or the file is unsymmetric. nz++ ; } else if (stype > 0 && i <= j) { // CHOLMOD matrix is symmetric-upper, but the file is // symmetric-lower. Need to transpose the entry. nz++ ; } } } return (nz) ; } //------------------------------------------------------------------------------ // cholmod_write_sparse //------------------------------------------------------------------------------ // Write a sparse matrix to a file in Matrix Market format. Optionally include // comments, and print explicit zero entries given by the pattern of the Z // matrix. If not NULL, the Z matrix must have the same dimensions and stype // as A. // // Returns the symmetry in which the matrix was printed (1 to 7, see the // CHOLMOD_MM_* codes in CHOLMOD/Include/cholmod.h), or -1 on failure. // // If A and Z are sorted on input, and either unsymmetric (stype = 0) or // symmetric-lower (stype < 0), and if A and Z do not overlap, then the triplets // are sorted, first by column and then by row index within each column, with // no duplicate entries. If all the above holds except stype > 0, then the // triplets are sorted by row first and then column. int CHOLMOD(write_sparse) ( // input: FILE *f, // file to write to, must already be open cholmod_sparse *A, // matrix to print cholmod_sparse *Z, // optional matrix with pattern of explicit zeros const char *comments, // optional filename of comments to include cholmod_common *Common ) { double x = 0, z = 0 ; void *Ax, *Az ; Int *Ap, *Ai, *Anz, *Zp, *Zi, *Znz ; Int nrow, ncol, is_complex, i, j, q, iz, p, nz, is_binary, stype, is_integer, asym, is_sym, apacked, zpacked, pend, qend, zsym ; int ok, xtype, dtype ; //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (EMPTY) ; RETURN_IF_NULL (f, EMPTY) ; RETURN_IF_NULL (A, EMPTY) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, EMPTY) ; if (Z != NULL && (Z->nrow == 0 || Z->ncol == 0)) { // Z is non-NULL but empty, so treat it as a NULL matrix Z = NULL ; } if (Z != NULL) { RETURN_IF_XTYPE_INVALID (Z, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, EMPTY) ; if (Z->nrow != A->nrow || Z->ncol != A->ncol || Z->stype != A->stype) { ERROR (CHOLMOD_INVALID, "dimension or type of A and Z mismatch") ; return (EMPTY) ; } } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // get the A matrix //-------------------------------------------------------------------------- Ap = A->p ; Ai = A->i ; Ax = A->x ; Az = A->z ; Anz = A->nz ; nrow = A->nrow ; ncol = A->ncol ; xtype = A->xtype ; dtype = A->dtype ; apacked = A->packed ; if (xtype == CHOLMOD_PATTERN) { // a CHOLMOD pattern matrix is printed as "pattern" in the file is_binary = TRUE ; is_integer = FALSE ; is_complex = FALSE ; } else if (xtype == CHOLMOD_REAL) { // determine if a real matrix is in fact binary or integer is_binary = TRUE ; is_integer = TRUE ; is_complex = FALSE ; for (j = 0 ; (is_binary || is_integer) && j < ncol ; j++) { p = Ap [j] ; pend = (apacked) ? Ap [j+1] : p + Anz [j] ; for ( ; (is_binary || is_integer) && p < pend ; p++) { get_value (Ax, Az, p, xtype, dtype, &x, &z) ; if (x != 1) { is_binary = FALSE ; } // convert to Int and then back to double i = (Int) x ; z = (double) i ; if (z != x) { is_integer = FALSE ; } } } } else { // a CHOLMOD complex matrix is printed as "complex" in the file is_binary = FALSE ; is_integer = FALSE ; is_complex = TRUE ; } //-------------------------------------------------------------------------- // get the Z matrix (only consider the pattern) //-------------------------------------------------------------------------- Zp = NULL ; Zi = NULL ; Znz = NULL ; zpacked = TRUE ; if (Z != NULL) { Zp = Z->p ; Zi = Z->i ; Znz = Z->nz ; zpacked = Z->packed ; } //-------------------------------------------------------------------------- // determine the symmetry of A and Z //-------------------------------------------------------------------------- stype = A->stype ; if (A->nrow != A->ncol) { asym = CHOLMOD_MM_RECTANGULAR ; } else if (stype != 0) { // CHOLMOD's A and Z matrices have a symmetric (and matching) stype. // Note that the diagonal is not checked. asym = is_complex ? CHOLMOD_MM_HERMITIAN : CHOLMOD_MM_SYMMETRIC ; } else if (!A->sorted) { // A is in unsymmetric storage, but unsorted asym = CHOLMOD_MM_UNSYMMETRIC ; } else { // CHOLMOD's stype is zero (stored in unsymmetric form) asym = EMPTY ; zsym = EMPTY ; #ifndef NMATRIXOPS // determine if the matrices are in fact symmetric or Hermitian asym = CHOLMOD(symmetry) (A, 1, NULL, NULL, NULL, NULL, Common) ; zsym = (Z == NULL) ? 999 : CHOLMOD(symmetry) (Z, 1, NULL, NULL, NULL, NULL, Common) ; #endif if (asym == EMPTY || zsym <= CHOLMOD_MM_UNSYMMETRIC) { // not computed, out of memory, or Z is unsymmetric asym = CHOLMOD_MM_UNSYMMETRIC ; } } //-------------------------------------------------------------------------- // write the Matrix Market header //-------------------------------------------------------------------------- ok = fprintf (f, "%%%%MatrixMarket matrix coordinate") > 0 ; if (is_complex) { ok = ok && (fprintf (f, " complex") > 0) ; } else if (is_binary) { ok = ok && (fprintf (f, " pattern") > 0) ; } else if (is_integer) { ok = ok && (fprintf (f, " integer") > 0) ; } else { ok = ok && (fprintf (f, " real") > 0) ; } is_sym = FALSE ; switch (asym) { case CHOLMOD_MM_RECTANGULAR: case CHOLMOD_MM_UNSYMMETRIC: // A is rectangular or unsymmetric ok = ok && (fprintf (f, " general\n") > 0) ; is_sym = FALSE ; break ; case CHOLMOD_MM_SYMMETRIC: case CHOLMOD_MM_SYMMETRIC_POSDIAG: // A is symmetric ok = ok && (fprintf (f, " symmetric\n") > 0) ; is_sym = TRUE ; break ; case CHOLMOD_MM_HERMITIAN: case CHOLMOD_MM_HERMITIAN_POSDIAG: // A is Hermitian ok = ok && (fprintf (f, " Hermitian\n") > 0) ; is_sym = TRUE ; break ; case CHOLMOD_MM_SKEW_SYMMETRIC: // A is skew symmetric ok = ok && (fprintf (f, " skew-symmetric\n") > 0) ; is_sym = TRUE ; break ; } //-------------------------------------------------------------------------- // include the comments if present //-------------------------------------------------------------------------- ok = ok && include_comments (f, comments) ; //-------------------------------------------------------------------------- // write a sparse matrix (A and Z) //-------------------------------------------------------------------------- nz = ntriplets (A, is_sym) + ntriplets (Z, is_sym) ; // write the first data line, with nrow, ncol, and # of triplets ok = ok && (fprintf (f, ID " " ID " " ID "\n", nrow, ncol, nz) > 0) ; for (j = 0 ; ok && j < ncol ; j++) { // merge column of A and Z p = Ap [j] ; pend = (apacked) ? Ap [j+1] : p + Anz [j] ; q = (Z == NULL) ? 0 : Zp [j] ; qend = (Z == NULL) ? 0 : ((zpacked) ? Zp [j+1] : q + Znz [j]) ; while (ok) { // get the next row index from A and Z i = (p < pend) ? Ai [p] : (nrow+1) ; iz = (q < qend) ? Zi [q] : (nrow+2) ; if (i <= iz) { // get A(i,j), or quit if both A and Z are exhausted if (i == nrow+1) break ; get_value (Ax, Az, p, xtype, dtype, &x, &z) ; p++ ; } else { // get Z(i,j) i = iz ; x = 0 ; z = 0 ; q++ ; } if ((stype < 0 && i >= j) || (stype == 0 && (i >= j || !is_sym))) { // CHOLMOD matrix is symmetric-lower (and so is the file); // or CHOLMOD matrix is unsymmetric and either A(i,j) is in // the lower part or the file is unsymmetric. ok = ok && print_triplet (f, is_binary, is_complex, is_integer, i,j, x,z) ; } else if (stype > 0 && i <= j) { // CHOLMOD matrix is symmetric-upper, but the file is // symmetric-lower. Need to transpose the entry. If the // matrix is real, the complex part is ignored. If the matrix // is complex, it Hermitian. ASSERT (IMPLIES (is_complex, asym == CHOLMOD_MM_HERMITIAN)) ; if (z != 0) { z = -z ; } ok = ok && print_triplet (f, is_binary, is_complex, is_integer, j,i, x,z) ; } } } if (!ok) { ERROR (CHOLMOD_INVALID, "error reading/writing file") ; return (EMPTY) ; } return (asym) ; } //------------------------------------------------------------------------------ // cholmod_write_dense //------------------------------------------------------------------------------ // Write a dense matrix to a file in Matrix Market format. Optionally include // comments. Returns > 0 if successful, -1 otherwise (1 if rectangular, 2 if // square). Future versions may return 1 to 7 on success (a CHOLMOD_MM_* code, // just as cholmod_write_sparse does). // // A dense matrix is written in "general" format; symmetric formats in the // Matrix Market standard are not exploited. int CHOLMOD(write_dense) ( // input: FILE *f, // file to write to, must already be open cholmod_dense *X, // matrix to print const char *comments, // optional filename of comments to include cholmod_common *Common ) { double x = 0, z = 0 ; void *Xx, *Xz ; Int nrow, ncol, is_complex, i, j, p ; int ok, xtype, dtype ; //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (EMPTY) ; RETURN_IF_NULL (f, EMPTY) ; RETURN_IF_NULL (X, EMPTY) ; RETURN_IF_XTYPE_INVALID (X, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, EMPTY) ; Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // get the X matrix //-------------------------------------------------------------------------- nrow = X->nrow ; ncol = X->ncol ; xtype = X->xtype ; dtype = X->dtype ; is_complex = (xtype == CHOLMOD_COMPLEX) || (xtype == CHOLMOD_ZOMPLEX) ; //-------------------------------------------------------------------------- // write the Matrix Market header //-------------------------------------------------------------------------- ok = (fprintf (f, "%%%%MatrixMarket matrix array") > 0) ; if (is_complex) { ok = ok && (fprintf (f, " complex general\n") > 0) ; } else { ok = ok && (fprintf (f, " real general\n") > 0) ; } //-------------------------------------------------------------------------- // include the comments if present //-------------------------------------------------------------------------- ok = ok && include_comments (f, comments) ; //-------------------------------------------------------------------------- // write a dense matrix //-------------------------------------------------------------------------- // write the first data line, with nrow and ncol ok = ok && (fprintf (f, ID " " ID "\n", nrow, ncol) > 0) ; Xx = X->x ; Xz = X->z ; for (j = 0 ; ok && j < ncol ; j++) { for (i = 0 ; ok && i < nrow ; i++) { p = i + j*nrow ; get_value (Xx, Xz, p, xtype, dtype, &x, &z) ; ok = ok && print_value (f, x, FALSE) ; if (is_complex) { ok = ok && (fprintf (f, " ") > 0) ; ok = ok && print_value (f, z, FALSE) ; } ok = ok && (fprintf (f, "\n") > 0) ; } } if (!ok) { ERROR (CHOLMOD_INVALID, "error reading/writing file") ; return (EMPTY) ; } return ((nrow == ncol) ? CHOLMOD_MM_UNSYMMETRIC : CHOLMOD_MM_RECTANGULAR) ; } #endif Matrix/src/SuiteSparse/CHOLMOD/Check/cholmod_l_read.c0000644000175100001440000000075414552026002021775 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Check/cholmod_l_read.c: int64_t version of cholmod_read //------------------------------------------------------------------------------ // CHOLMOD/Check Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_read.c" Matrix/src/SuiteSparse/CHOLMOD/Check/cholmod_check.c0000644000175100001440000023010214552026002021614 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Check/cholmod_check: check and print each CHOLMOD object //------------------------------------------------------------------------------ // CHOLMOD/Check Module. Copyright (C) 2005-2023, Timothy A. Davis // All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ //------------------------------------------------------------------------------ // Routines to check and print the contents of the 5 CHOLMOD objects: // // No CHOLMOD routine calls the check or print routines. If a user wants to // check CHOLMOD's input parameters, a separate call to the appropriate check // routine should be used before calling other CHOLMOD routines. // // cholmod_check_common check statistics and workspace in Common // cholmod_check_sparse check sparse matrix in compressed column form // cholmod_check_dense check dense matrix // cholmod_check_factor check factorization // cholmod_check_triplet check sparse matrix in triplet form // // cholmod_print_common print statistics in Common // cholmod_print_sparse print sparse matrix in compressed column form // cholmod_print_dense print dense matrix // cholmod_print_factor print factorization // cholmod_print_triplet print sparse matrix in triplet form // // In addition, this file contains routines to check and print three types of // integer vectors: // // cholmod_check_perm check a permutation of 0:n-1 (no duplicates) // cholmod_check_subset check a subset of 0:n-1 (duplicates OK) // cholmod_check_parent check an elimination tree // // cholmod_print_perm print a permutation // cholmod_print_subset print a subset // cholmod_print_parent print an elimination tree // // Each Common->print level prints the items at or below the given level: // // 0: print nothing; just check the data structures and return TRUE/FALSE // 1: error messages // 2: warning messages // 3: one-line summary of each object printed // 4: short summary of each object (first and last few entries) // 5: entire contents of the object // // No CHOLMOD routine calls these routines, so no printing occurs unless // the user specifically calls a cholmod_print_* routine. Thus, the default // print level is 3. // // Common->precise controls the # of digits printed for numerical entries // (5 if FALSE, 15 if TRUE). // // If the SuiteSparse_config printf_func is NULL, then no printing occurs. The // cholmod_check_* and cholmod_print_* routines still check their inputs and // return TRUE/FALSE if the object is valid or not. // // This file also includes debugging routines that are enabled only when // NDEBUG is defined in cholmod_internal.h (cholmod_dump_*). #ifndef NCHECK #include "cholmod_internal.h" //------------------------------------------------------------------------------ // printing definitions //------------------------------------------------------------------------------ #if defined ( CHOLMOD_INT64 ) #define I8 "%8ld" #define I_8 "%-8ld" #else #define I8 "%8d" #define I_8 "%-8d" #endif #define PR(i,format,arg) \ { \ if ((print) >= (i)) \ { \ int (*printf_func) (const char *, ...) ; \ printf_func = SuiteSparse_config_printf_func_get ( ) ; \ if (printf_func != NULL) \ { \ (void) (printf_func) (format, arg) ; \ } \ } \ } #define P1(format,arg) PR(1,format,arg) #define P2(format,arg) PR(2,format,arg) #define P3(format,arg) PR(3,format,arg) #define P4(format,arg) PR(4,format,arg) #define ERR(msg) \ { \ P1 ("\nCHOLMOD ERROR: %s: ", type) ; \ if (name != NULL) \ { \ P1 ("%s", name) ; \ } \ P1 (": %s\n", msg) ; \ ERROR (CHOLMOD_INVALID, "invalid") ; \ return (FALSE) ; \ } // start printing #define ETC_START(count,limit) \ { \ count = (init_print == 4) ? (limit) : (-1) ; \ } // re-enable printing if condition is met #define ETC_ENABLE(condition,count,limit) \ { \ if ((condition) && init_print == 4) \ { \ count = limit ; \ print = 4 ; \ } \ } // turn off printing if limit is reached #define ETC_DISABLE(count) \ { \ if ((count >= 0) && (count-- == 0) && print == 4) \ { \ P4 ("%s", " ...\n") ; \ print = 3 ; \ } \ } // re-enable printing, or turn if off after limit is reached #define ETC(condition,count,limit) \ { \ ETC_ENABLE (condition, count, limit) ; \ ETC_DISABLE (count) ; \ } #define BOOLSTR(x) ((x) ? "true " : "false") //------------------------------------------------------------------------------ // print_value //------------------------------------------------------------------------------ // get a double or float value from an array at X [p] #define GETVAL(X,p,dtype) \ ((dtype == CHOLMOD_DOUBLE) ? (((double *) X) [p]) : (((float *) X) [p])) // print a numerical value in X [p], as float or double #define PRINTVALUE(X,p,dtype) \ { \ double value = GETVAL (X, p, dtype) ; \ char *fmt = (Common->precise) ? \ ((dtype == CHOLMOD_DOUBLE) ? (" %23.15e") : (" %15.7e")) : \ (" %.5g ") ; \ P4 (fmt, value) ; \ } static void print_value ( int print, int xtype, // CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX int dtype, // CHOLMOD_SINGLE or _DOUBLE void *Xx, // pointer to float or double (real part) void *Xz, // pointer to float or double (zomplex only) Int p, cholmod_common *Common) { if (xtype == CHOLMOD_REAL) { PRINTVALUE (Xx, p, dtype) ; } else if (xtype == CHOLMOD_COMPLEX) { P4 ("%s", "(") ; PRINTVALUE (Xx, 2*p , dtype) ; P4 ("%s", " , ") ; PRINTVALUE (Xx, 2*p+1, dtype) ; P4 ("%s", ")") ; } else if (xtype == CHOLMOD_ZOMPLEX) { P4 ("%s", "(") ; PRINTVALUE (Xx, p, dtype) ; P4 ("%s", " , ") ; PRINTVALUE (Xz, p, dtype) ; P4 ("%s", ")") ; } } //------------------------------------------------------------------------------ // cholmod_check_common //------------------------------------------------------------------------------ // Print and verify the contents of Common static int check_common ( int print, const char *name, cholmod_common *Common ) { double fl, lnz ; Int *Flag, *Head ; int64_t mark ; Int i, nrow, nmethods, ordering, amd_backup ; const char *type = "common" ; //-------------------------------------------------------------------------- // print control parameters and statistics //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; P2 ("%s", "\n") ; P1 ("CHOLMOD version %d", CHOLMOD_MAIN_VERSION) ; P1 (".%d", CHOLMOD_SUB_VERSION) ; P1 (".%d", CHOLMOD_SUBSUB_VERSION) ; P1 (", %s: ", CHOLMOD_DATE) ; if (name != NULL) { P1 ("%s: ", name) ; } switch (Common->status) { case CHOLMOD_OK: P1 ("%s", "status: OK\n") ; break ; case CHOLMOD_OUT_OF_MEMORY: P1 ("%s", "status: ERROR, out of memory\n") ; break ; case CHOLMOD_INVALID: P1 ("%s", "status: ERROR, invalid parameter\n") ; break ; case CHOLMOD_TOO_LARGE: P1 ("%s", "status: ERROR, problem too large\n") ; break ; case CHOLMOD_NOT_INSTALLED: P1 ("%s", "status: ERROR, method not installed\n") ; break ; case CHOLMOD_GPU_PROBLEM: P1 ("%s", "status: ERROR, GPU had a fatal error\n") ; break ; case CHOLMOD_NOT_POSDEF: P1 ("%s", "status: warning, matrix not positive definite\n") ; break ; case CHOLMOD_DSMALL: P1 ("%s", "status: warning, diagonal entry has tiny abs. value\n") ; break ; default: ERR ("unknown status") ; } P3 ("%s", " Architecture:\n") ; P3 (" sizeof(int): %d\n", (int) sizeof (int)) ; P3 (" sizeof(int64_t): %d\n", (int) sizeof (int64_t)); P3 (" sizeof(void *): %d\n", (int) sizeof (void *)) ; P3 (" sizeof(double): %d\n", (int) sizeof (double)) ; P3 (" sizeof(Int): %d (CHOLMOD's basic integer)\n", (int) sizeof (Int)) ; P3 (" sizeof(SUITESPARSE_BLAS_INT): %d (integer used in the BLAS)\n", (int) sizeof (SUITESPARSE_BLAS_INT)) ; if (Common->fl != EMPTY) { P2 ("%s", " Results from most recent analysis:\n") ; P2 (" Cholesky flop count: %.5g\n", Common->fl) ; P2 (" Nonzeros in L: %.5g\n", Common->lnz) ; } if (Common->modfl != EMPTY) { P2 (" Update/downdate flop count: %.5g\n", Common->modfl) ; } P2 (" memory blocks in use: %8.0f\n", (double) (Common->malloc_count)) ; P2 (" memory in use (MB): %8.1f\n", (double) (Common->memory_inuse) / 1048576.) ; P2 (" peak memory usage (MB): %8.1f\n", (double) (Common->memory_usage) / 1048576.) ; //-------------------------------------------------------------------------- // primary control parameters and related ordering statistics //-------------------------------------------------------------------------- P3 (" maxrank: update/downdate rank: "ID"\n", (Int) CHOLMOD(maxrank) (0, Common)) ; P3 (" supernodal control: %d", Common->supernodal) ; P3 (" %g ", Common->supernodal_switch) ; if (Common->supernodal <= CHOLMOD_SIMPLICIAL) { P3 ("%s", "(always do simplicial)\n") ; } else if (Common->supernodal == CHOLMOD_AUTO) { P3 ("(supernodal if flops/lnz >= %g)\n", Common->supernodal_switch) ; } else { P3 ("%s", "(always do supernodal)\n") ; } nmethods = MIN (Common->nmethods, CHOLMOD_MAXMETHODS) ; nmethods = MAX (0, nmethods) ; if (nmethods > 0) { P3 ("%s", " nmethods: number of ordering methods to try: ") ; P3 (""ID"\n", nmethods) ; amd_backup = (nmethods > 1) || (nmethods == 1 && (Common->method [0].ordering == CHOLMOD_METIS || Common->method [0].ordering == CHOLMOD_NESDIS)) ; } else { P3 ("%s", " nmethods=0: default strategy: Try user permutation if " "given. Try AMD.\n") ; #ifndef NPARTITION if (Common->default_nesdis) { P3 ("%s", " Try NESDIS if AMD reports flops/nnz(L) >= 500 and " "nnz(L)/nnz(A) >= 5.\n") ; } else { P3 ("%s", " Try METIS if AMD reports flops/nnz(L) >= 500 and " "nnz(L)/nnz(A) >= 5.\n") ; } #endif P3 ("%s", " Select best ordering tried.\n") ; Common->method [0].ordering = CHOLMOD_GIVEN ; Common->method [1].ordering = CHOLMOD_AMD ; Common->method [2].ordering = (Common->default_nesdis ? CHOLMOD_NESDIS : CHOLMOD_METIS) ; amd_backup = FALSE ; #ifndef NPARTITION nmethods = 3 ; #else nmethods = 2 ; #endif } for (i = 0 ; i < nmethods ; i++) { P3 (" method "ID": ", i) ; ordering = Common->method [i].ordering ; fl = Common->method [i].fl ; lnz = Common->method [i].lnz ; switch (ordering) { case CHOLMOD_NATURAL: P3 ("%s", "natural\n") ; break ; case CHOLMOD_GIVEN: P3 ("%s", "user permutation (if given)\n") ; break ; case CHOLMOD_AMD: P3 ("%s", "AMD (or COLAMD if factorizing AA')\n") ; amd_backup = FALSE ; break ; case CHOLMOD_COLAMD: P3 ("%s", "AMD if factorizing A, COLAMD if factorizing AA')\n"); amd_backup = FALSE ; break ; case CHOLMOD_METIS: P3 ("%s", "METIS_NodeND nested dissection\n") ; break ; case CHOLMOD_NESDIS: P3 ("%s", "CHOLMOD nested dissection\n") ; P3 (" nd_small: # nodes in uncut subgraph: "ID"\n", (Int) (Common->method [i].nd_small)) ; P3 (" nd_compress: compress the graph: %s\n", BOOLSTR (Common->method [i].nd_compress)) ; P3 (" nd_camd: use constrained min degree: %s\n", BOOLSTR (Common->method [i].nd_camd)) ; break ; default: P3 (ID, ordering) ; ERR ("unknown ordering method") ; break ; } if (!(ordering == CHOLMOD_NATURAL || ordering == CHOLMOD_GIVEN)) { if (Common->method [i].prune_dense < 0) { P3 (" prune_dense: for pruning dense nodes: %s\n", " none pruned") ; } else { P3 (" prune_dense: for pruning dense nodes: " "%.5g\n", Common->method [i].prune_dense) ; P3 (" a dense node has degree " ">= max(16,(%.5g)*sqrt(n))\n", Common->method [i].prune_dense) ; } } if (ordering == CHOLMOD_COLAMD || ordering == CHOLMOD_NESDIS) { if (Common->method [i].prune_dense2 < 0) { P3 (" prune_dense2: for pruning dense rows for AA':" " %s\n", " none pruned") ; } else { P3 (" prune_dense2: for pruning dense rows for AA':" " %.5g\n", Common->method [i].prune_dense2) ; P3 (" a dense row has degree " ">= max(16,(%.5g)*sqrt(ncol))\n", Common->method [i].prune_dense2) ; } } if (fl != EMPTY) P3 (" flop count: %.5g\n", fl) ; if (lnz != EMPTY) P3 (" nnz(L): %.5g\n", lnz) ; } // backup AMD results, if any if (amd_backup) { P3 ("%s", " backup method: ") ; P3 ("%s", "AMD (or COLAMD if factorizing AA')\n") ; fl = Common->method [nmethods].fl ; lnz = Common->method [nmethods].lnz ; if (fl != EMPTY) P3 (" AMD flop count: %.5g\n", fl) ; if (lnz != EMPTY) P3 (" AMD nnz(L): %.5g\n", lnz) ; } //-------------------------------------------------------------------------- // arcane control parameters //-------------------------------------------------------------------------- if (Common->final_asis) { P4 ("%s", " final_asis: TRUE, leave as is\n") ; } else { P4 ("%s", " final_asis: FALSE, convert when done\n") ; if (Common->final_super) { P4 ("%s", " final_super: TRUE, leave in supernodal form\n") ; } else { P4 ("%s", " final_super: FALSE, convert to simplicial form\n") ; } if (Common->final_ll) { P4 ("%s", " final_ll: TRUE, convert to LL' form\n") ; } else { P4 ("%s", " final_ll: FALSE, convert to LDL' form\n") ; } if (Common->final_pack) { P4 ("%s", " final_pack: TRUE, pack when done\n") ; } else { P4 ("%s", " final_pack: FALSE, do not pack when done\n") ; } if (Common->final_monotonic) { P4 ("%s", " final_monotonic: TRUE, ensure L is monotonic\n") ; } else { P4 ("%s", " final_monotonic: FALSE, do not ensure L is monotonic\n") ; } P4 (" final_resymbol: remove zeros from amalgamation: %s\n", BOOLSTR (Common->final_resymbol)) ; } P4 (" dbound: LDL' diagonal threshold: % .5g\n Entries with abs. value" " less than dbound are replaced with +/- dbound.\n" " (for double precision case)\n", Common->dbound) ; P4 (" sbound: LDL' diagonal threshold: % .5g\n Entries with abs. value" " less than sbound are replaced with +/- sbound.\n" " (for single precision case)\n", Common->sbound) ; P4 (" grow0: memory reallocation: % .5g\n", Common->grow0) ; P4 (" grow1: memory reallocation: % .5g\n", Common->grow1) ; P4 (" grow2: memory reallocation: %g\n", (double) (Common->grow2)) ; P4 ("%s", " nrelax, zrelax: supernodal amalgamation rule:\n") ; P4 ("%s", " s = # columns in two adjacent supernodes\n") ; P4 ("%s", " z = % of zeros in new supernode if they are merged.\n") ; P4 ("%s", " Two supernodes are merged if") ; P4 (" (s <= %g) or (no new zero entries) or\n", (double) (Common->nrelax [0])) ; P4 (" (s <= %g and ", (double) (Common->nrelax [1])) ; P4 ("z < %.5g%%) or", Common->zrelax [0] * 100) ; P4 (" (s <= %g and ", (double) (Common->nrelax [2])) ; P4 ("z < %.5g%%) or", Common->zrelax [1] * 100) ; P4 (" (z < %.5g%%)\n", Common->zrelax [2] * 100) ; //-------------------------------------------------------------------------- // check workspace //-------------------------------------------------------------------------- mark = Common->mark ; nrow = Common->nrow ; Flag = Common->Flag ; Head = Common->Head ; if (nrow > 0) { if (mark < 0 || Flag == NULL || Head == NULL) { ERR ("workspace corrupted (Flag and/or Head missing)") ; } for (i = 0 ; i < nrow ; i++) { if (Flag [i] >= mark) { PRINT0 (("Flag ["ID"]="ID", mark = %ld\n", i, Flag [i], mark)) ; ERR ("workspace corrupted (Flag)") ; } } for (i = 0 ; i <= nrow ; i++) { if (Head [i] != EMPTY) { PRINT0 (("Head ["ID"] = "ID",\n", i, Head [i])) ; ERR ("workspace corrupted (Head)") ; } } } size_t xworkbytes = Common->xworkbytes ; uint8_t *Xwork = Common->Xwork ; if (xworkbytes > 0) { if (Xwork == NULL) { ERR ("workspace corrupted (Xwork missing)") ; } for (i = 0 ; i < xworkbytes ; i++) { if (Xwork [i] != 0.) { PRINT0 (("Xwork ["ID"] = %d\n", i, Xwork [i])) ; ERR ("workspace corrupted (Xwork)") ; } } } // workspace and parameters are valid P3 ("%s", " OK\n") ; P4 ("%s", "\n") ; return (TRUE) ; } int CHOLMOD(check_common) ( cholmod_common *Common ) { return (check_common (0, NULL, Common)) ; } int CHOLMOD(print_common) ( // input: const char *name, // printed name of Common object cholmod_common *Common ) { int print = (Common == NULL) ? 3 : (Common->print) ; return (check_common (print, name, Common)) ; } //------------------------------------------------------------------------------ // cholmod_gpu_stats //------------------------------------------------------------------------------ // Print CPU / GPU statistics. If the timer is not installed, the times are // reported as zero, but this function still works. Likewise, the function // still works if the GPU BLAS is not installed. int CHOLMOD(gpu_stats) ( cholmod_common *Common // input ) { RETURN_IF_NULL_COMMON (FALSE) ; #ifdef BLAS_TIMER int print = Common->print ; double cpu_time, gpu_time ; #ifdef CHOLMOD_HAS_CUDA P2 ("%s", "\nCHOLMOD GPU/CPU statistics:\n") ; #else P2 ("%s", "\nCHOLMOD BLAS statistics:\n") ; #endif P2 ("SYRK CPU calls %12.0f", (double) Common->CHOLMOD_CPU_SYRK_CALLS) ; P2 (" time %12.4e\n", Common->CHOLMOD_CPU_SYRK_TIME) ; #ifdef CHOLMOD_HAS_CUDA P2 (" GPU calls %12.0f", (double) Common->CHOLMOD_GPU_SYRK_CALLS) ; P2 (" time %12.4e\n", Common->CHOLMOD_GPU_SYRK_TIME) ; #endif P2 ("GEMM CPU calls %12.0f", (double) Common->CHOLMOD_CPU_GEMM_CALLS) ; P2 (" time %12.4e\n", Common->CHOLMOD_CPU_GEMM_TIME) ; #ifdef CHOLMOD_HAS_CUDA P2 (" GPU calls %12.0f", (double) Common->CHOLMOD_GPU_GEMM_CALLS) ; P2 (" time %12.4e\n", Common->CHOLMOD_GPU_GEMM_TIME) ; #endif P2 ("POTRF CPU calls %12.0f", (double) Common->CHOLMOD_CPU_POTRF_CALLS) ; P2 (" time %12.4e\n", Common->CHOLMOD_CPU_POTRF_TIME) ; #ifdef CHOLMOD_HAS_CUDA P2 (" GPU calls %12.0f", (double) Common->CHOLMOD_GPU_POTRF_CALLS) ; P2 (" time %12.4e\n", Common->CHOLMOD_GPU_POTRF_TIME) ; #endif P2 ("TRSM CPU calls %12.0f", (double) Common->CHOLMOD_CPU_TRSM_CALLS) ; P2 (" time %12.4e\n", Common->CHOLMOD_CPU_TRSM_TIME) ; #ifdef CHOLMOD_HAS_CUDA P2 (" GPU calls %12.0f", (double) Common->CHOLMOD_GPU_TRSM_CALLS) ; P2 (" time %12.4e\n", Common->CHOLMOD_GPU_TRSM_TIME) ; #endif cpu_time = Common->CHOLMOD_CPU_SYRK_TIME + Common->CHOLMOD_CPU_TRSM_TIME + Common->CHOLMOD_CPU_GEMM_TIME + Common->CHOLMOD_CPU_POTRF_TIME ; gpu_time = Common->CHOLMOD_GPU_SYRK_TIME + Common->CHOLMOD_GPU_TRSM_TIME + Common->CHOLMOD_GPU_GEMM_TIME + Common->CHOLMOD_GPU_POTRF_TIME ; #ifdef CHOLMOD_HAS_CUDA P2 ("time in the BLAS: CPU %12.4e", cpu_time) ; P2 (" GPU %12.4e", gpu_time) ; P2 (" total: %12.4e\n", cpu_time + gpu_time) ; #else P2 ("total time in the BLAS: %12.4e\n", cpu_time) ; #endif // P2 ("assembly time %12.4e", Common->CHOLMOD_ASSEMBLE_TIME) ; // P2 (" %12.4e\n", Common->CHOLMOD_ASSEMBLE_TIME2) ; #endif return (TRUE) ; } //------------------------------------------------------------------------------ // cholmod_check_sparse //------------------------------------------------------------------------------ // Ensure that a sparse matrix in column-oriented form is valid, and optionally // print it. Returns the number of entries on the diagonal or -1 if error. // // workspace: Iwork (nrow) static int64_t check_sparse ( Int *Wi, int print, const char *name, cholmod_sparse *A, int64_t *nnzdiag, cholmod_common *Common ) { void *Ax, *Az ; Int *Ap, *Ai, *Anz ; Int nrow, ncol, nzmax, sorted, packed, j, p, pend, i, nz, ilast, init_print, dnz, count ; const char *type = "sparse" ; //-------------------------------------------------------------------------- // print header information //-------------------------------------------------------------------------- P4 ("%s", "\n") ; P3 ("%s", "CHOLMOD sparse: ") ; if (name != NULL) { P3 ("%s: ", name) ; } if (A == NULL) { ERR ("null") ; } nrow = A->nrow ; ncol = A->ncol ; nzmax = A->nzmax ; sorted = A->sorted ; packed = A->packed ; int xtype = A->xtype ; int dtype = A->dtype ; Ap = A->p ; Ai = A->i ; Ax = A->x ; Az = A->z ; Anz = A->nz ; nz = CHOLMOD(nnz) (A, Common) ; P3 (" "ID"", nrow) ; P3 ("-by-"ID", ", ncol) ; P3 ("nz "ID",", nz) ; if (A->stype > 0) { P3 ("%s", " upper.") ; } else if (A->stype < 0) { P3 ("%s", " lower.") ; } else { P3 ("%s", " up/lo.") ; } P4 ("\n nzmax "ID", ", nzmax) ; if (nz > nzmax) { ERR ("nzmax too small") ; } if (!sorted) { P4 ("%s", "un") ; } P4 ("%s", "sorted, ") ; if (!packed) { P4 ("%s", "un") ; } P4 ("%s", "packed, ") ; switch (A->itype) { case CHOLMOD_INT: P4 ("%s", "\n scalar types: int32_t, ") ; break ; case CHOLMOD_LONG: P4 ("%s", "\n scalar types: int64_t, ") ; break ; default: ERR ("unknown itype") ; } switch (A->xtype) { case CHOLMOD_PATTERN: P4 ("%s", "pattern") ; break ; case CHOLMOD_REAL: P4 ("%s", "real") ; break ; case CHOLMOD_COMPLEX: P4 ("%s", "complex") ; break ; case CHOLMOD_ZOMPLEX: P4 ("%s", "zomplex") ; break ; default: ERR ("unknown xtype") ; } switch (A->dtype) { case CHOLMOD_DOUBLE: P4 ("%s", ", double\n") ; break ; case CHOLMOD_SINGLE: P4 ("%s", ", single\n") ; break ; default: ERR ("unknown dtype") ; } if (A->itype != ITYPE) { ERR ("integer type must match routine") ; } if (A->stype && nrow != ncol) { ERR ("symmetric but not square") ; } // check for existence of Ap, Ai, Anz, Ax, and Az arrays if (Ap == NULL) { ERR ("p array not present") ; } if (Ai == NULL) { ERR ("i array not present") ; } if (!packed && Anz == NULL) { ERR ("nz array not present") ; } if (xtype != CHOLMOD_PATTERN && Ax == NULL) { ERR ("x array not present") ; } if (xtype == CHOLMOD_ZOMPLEX && Az == NULL) { ERR ("z array not present") ; } // packed matrices must start at Ap [0] = 0 if (packed && Ap [0] != 0) { ERR ("p [0] must be zero") ; } if (packed && (Ap [ncol] < Ap [0] || Ap [ncol] > nzmax)) { ERR ("p [ncol] invalid") ; } //-------------------------------------------------------------------------- // allocate workspace if needed //-------------------------------------------------------------------------- if (!sorted) { if (Wi == NULL) { CHOLMOD(allocate_work) (0, nrow, 0, Common) ; Wi = Common->Iwork ; // size nrow } if (Common->status < CHOLMOD_OK) { return (FALSE) ; // out of memory } for (i = 0 ; i < nrow ; i++) { Wi [i] = EMPTY ; } } //-------------------------------------------------------------------------- // check and print each column //-------------------------------------------------------------------------- init_print = print ; dnz = 0 ; ETC_START (count, 8) ; for (j = 0 ; j < ncol ; j++) { ETC (j == ncol-1, count, 4) ; p = Ap [j] ; if (packed) { pend = Ap [j+1] ; nz = pend - p ; } else { // Note that Anz [j] < 0 is treated as zero nz = MAX (0, Anz [j]) ; pend = p + nz ; } P4 (" col "ID":", j) ; P4 (" nz "ID"", nz) ; P4 (" start "ID"", p) ; P4 (" end "ID"", pend) ; P4 ("%s", ":\n") ; if (p < 0 || pend > nzmax) { ERR ("pointer invalid") ; } if (nz < 0 || nz > nrow) { ERR ("nz invalid") ; } ilast = EMPTY ; for ( ; p < pend ; p++) { ETC (j == ncol-1 && p >= pend-4, count, -1) ; i = Ai [p] ; P4 (" "I8":", i) ; print_value (print, xtype, dtype, Ax, Az, p, Common) ; if (i == j) { dnz++ ; } if (i < 0 || i >= nrow) { ERR ("row index out of range") ; } if (sorted && i <= ilast) { ERR ("row indices out of order") ; } if (!sorted && Wi [i] == j) { ERR ("duplicate row index") ; } P4 ("%s", "\n") ; ilast = i ; if (!sorted) { Wi [i] = j ; } } } // matrix is valid P4 (" nnz on diagonal: "ID"\n", dnz) ; P3 ("%s", " OK\n") ; P4 ("%s", "\n") ; *nnzdiag = dnz ; return (TRUE) ; } int CHOLMOD(check_sparse) ( // input: cholmod_sparse *A, // sparse matrix to check cholmod_common *Common ) { int64_t nnzdiag ; RETURN_IF_NULL_COMMON (FALSE) ; Common->status = CHOLMOD_OK ; return (check_sparse (NULL, 0, NULL, A, &nnzdiag, Common)) ; } int CHOLMOD(print_sparse) ( // input: cholmod_sparse *A, // sparse matrix to print const char *name, // printed name of sparse matrix cholmod_common *Common ) { int64_t nnzdiag ; RETURN_IF_NULL_COMMON (FALSE) ; Common->status = CHOLMOD_OK ; return (check_sparse (NULL, Common->print, name, A, &nnzdiag, Common)) ; } //------------------------------------------------------------------------------ // cholmod_check_dense //------------------------------------------------------------------------------ // Ensure a dense matrix is valid, and optionally print it. static int check_dense ( int print, const char *name, cholmod_dense *X, cholmod_common *Common ) { void *Xx, *Xz ; Int i, j, d, nrow, ncol, nzmax, init_print, count ; const char *type = "dense" ; //-------------------------------------------------------------------------- // print header information //-------------------------------------------------------------------------- P4 ("%s", "\n") ; P3 ("%s", "CHOLMOD dense: ") ; if (name != NULL) { P3 ("%s: ", name) ; } if (X == NULL) { ERR ("null") ; } nrow = X->nrow ; ncol = X->ncol ; nzmax = X->nzmax ; d = X->d ; Xx = X->x ; Xz = X->z ; int xtype = X->xtype ; int dtype = X->dtype ; P3 (" "ID"", nrow) ; P3 ("-by-"ID", ", ncol) ; P4 ("\n leading dimension "ID", ", d) ; P4 ("nzmax "ID", ", nzmax) ; if (d * ncol > nzmax) { ERR ("nzmax too small") ; } if (d < nrow) { ERR ("leading dimension must be >= # of rows") ; } if (Xx == NULL) { ERR ("null") ; } switch (X->xtype) { case CHOLMOD_PATTERN: ERR ("pattern unsupported") ; break ; case CHOLMOD_REAL: P4 ("%s", "real") ; break ; case CHOLMOD_COMPLEX: P4 ("%s", "complex") ; break ; case CHOLMOD_ZOMPLEX: P4 ("%s", "zomplex") ; break ; default: ERR ("unknown xtype") ; } switch (X->dtype) { case CHOLMOD_DOUBLE: P4 ("%s", ", double\n") ; break ; case CHOLMOD_SINGLE: P4 ("%s", ", single\n") ; break ; default: ERR ("unknown dtype") ; } //-------------------------------------------------------------------------- // check and print each entry //-------------------------------------------------------------------------- if (print >= 4) { init_print = print ; ETC_START (count, 9) ; for (j = 0 ; j < ncol ; j++) { ETC (j == ncol-1, count, 5) ; P4 (" col "ID":\n", j) ; for (i = 0 ; i < nrow ; i++) { ETC (j == ncol-1 && i >= nrow-4, count, -1) ; P4 (" "I8":", i) ; print_value (print, xtype, dtype, Xx, Xz, i+j*d, Common) ; P4 ("%s", "\n") ; } } } // dense is valid P3 ("%s", " OK\n") ; P4 ("%s", "\n") ; return (TRUE) ; } int CHOLMOD(check_dense) ( // input: cholmod_dense *X, // dense matrix to check cholmod_common *Common ) { RETURN_IF_NULL_COMMON (FALSE) ; Common->status = CHOLMOD_OK ; return (check_dense (0, NULL, X, Common)) ; } int CHOLMOD(print_dense) ( // input: cholmod_dense *X, // dense matrix to print const char *name, // printed name of dense matrix cholmod_common *Common ) { RETURN_IF_NULL_COMMON (FALSE) ; Common->status = CHOLMOD_OK ; return (check_dense (Common->print, name, X, Common)) ; } //------------------------------------------------------------------------------ // cholmod_check_subset //------------------------------------------------------------------------------ // Ensure S (0:len-1) is a subset of 0:n-1. Duplicates are allowed. S may be // NULL. A negative len denotes the set 0:n-1. // // To check the rset and cset for A(rset,cset), where nc and nr are the length // of cset and rset respectively: // // cholmod_check_subset (cset, nc, A->ncol, Common) ; // cholmod_check_subset (rset, nr, A->nrow, Common) ; // // workspace: none static int check_subset ( Int *S, int64_t len, size_t n, int print, const char *name, cholmod_common *Common ) { Int i, k, init_print, count ; const char *type = "subset" ; init_print = print ; if (S == NULL) { // zero len denotes S = [ ], negative len denotes S = 0:n-1 len = (len < 0) ? (-1) : 0 ; } P4 ("%s", "\n") ; P3 ("%s", "CHOLMOD subset: ") ; if (name != NULL) { P3 ("%s: ", name) ; } P3 (" len: %ld ", len) ; if (len < 0) { P3 ("%s", "(denotes 0:n-1) ") ; } P3 ("n: "ID"", (Int) n) ; P4 ("%s", "\n") ; if (len <= 0 || S == NULL) { P3 ("%s", " OK\n") ; P4 ("%s", "\n") ; return (TRUE) ; } if (print >= 4) { ETC_START (count, 8) ; for (k = 0 ; k < ((Int) len) ; k++) { ETC (k == ((Int) len) - 4, count, -1) ; i = S [k] ; P4 (" "I8":", k) ; P4 (" "ID"\n", i) ; if (i < 0 || i >= ((Int) n)) { ERR ("entry out range") ; } } } else { for (k = 0 ; k < ((Int) len) ; k++) { i = S [k] ; if (i < 0 || i >= ((Int) n)) { ERR ("entry out range") ; } } } P3 ("%s", " OK\n") ; P4 ("%s", "\n") ; return (TRUE) ; } int CHOLMOD(check_subset) ( // input: Int *Set, // Set [0:len-1] is a subset of 0:n-1. Duplicates OK int64_t len, // size of Set (an integer array), or < 0 if 0:n-1 size_t n, // 0:n-1 is valid range cholmod_common *Common ) { RETURN_IF_NULL_COMMON (FALSE) ; Common->status = CHOLMOD_OK ; return (check_subset (Set, len, n, 0, NULL, Common)) ; } int CHOLMOD(print_subset) ( // input: Int *Set, // Set [0:len-1] is a subset of 0:n-1. Duplicates OK int64_t len, // size of Set (an integer array), or < 0 if 0:n-1 size_t n, // 0:n-1 is valid range const char *name, // printed name of Set cholmod_common *Common ) { RETURN_IF_NULL_COMMON (FALSE) ; Common->status = CHOLMOD_OK ; return (check_subset (Set, len, n, Common->print, name, Common)) ; } //------------------------------------------------------------------------------ // cholmod_check_perm //------------------------------------------------------------------------------ // Ensure that Perm [0..len-1] is a permutation of a subset of 0:n-1. Perm // may be NULL, which is interpreted as the identity permutation. There can // be no duplicate entries (len must be <= n). // // If n <= Common->nrow, then this routine takes O(len) time and does not // allocate any memory, by using Common->Flag. Otherwise, it takes O(n) time // and ensures that Common->Iwork is at least n*sizeof(Int) in size. // // To check the fset: cholmod_check_perm (fset, fsize, ncol, Common) ; // To check a permutation: cholmod_check_perm (Perm, n, n, Common) ; // // workspace: Flag (n) if n <= Common->nrow, Iwork (n) otherwise. static int check_perm ( Int *Wi, int print, const char *name, Int *Perm, size_t len, size_t n, cholmod_common *Common ) { Int *Flag ; Int i, k, mark, init_print, count ; const char *type = "perm" ; //-------------------------------------------------------------------------- // checks that take O(1) time //-------------------------------------------------------------------------- if (Perm == NULL || n == 0) { // Perm is valid implicit identity, or empty return (TRUE) ; } //-------------------------------------------------------------------------- // checks that take O(n) time or require memory allocation //-------------------------------------------------------------------------- init_print = print ; ETC_START (count, 8) ; if (Wi == NULL && n <= Common->nrow) { // use the Common->Flag array if it's big enough mark = CHOLMOD(clear_flag) (Common) ; Flag = Common->Flag ; ASSERT (CHOLMOD(dump_work) (TRUE, FALSE, 0, 0, Common)) ; if (print >= 4) { for (k = 0 ; k < ((Int) len) ; k++) { ETC (k >= ((Int) len) - 4, count, -1) ; i = Perm [k] ; P4 (" "I8":", k) ; P4 (""ID"\n", i) ; if (i < 0 || i >= ((Int) n) || Flag [i] == mark) { CHOLMOD(clear_flag) (Common) ; ERR ("invalid permutation") ; } Flag [i] = mark ; } } else { for (k = 0 ; k < ((Int) len) ; k++) { i = Perm [k] ; if (i < 0 || i >= ((Int) n) || Flag [i] == mark) { CHOLMOD(clear_flag) (Common) ; ERR ("invalid permutation") ; } Flag [i] = mark ; } } CHOLMOD(clear_flag) (Common) ; ASSERT (CHOLMOD(dump_work) (TRUE, FALSE, 0, 0, Common)) ; } else { if (Wi == NULL) { // use Common->Iwork instead, but initialize it first CHOLMOD(allocate_work) (0, n, 0, Common) ; Wi = Common->Iwork ; // size n } if (Common->status < CHOLMOD_OK) { return (FALSE) ; // out of memory } for (i = 0 ; i < ((Int) n) ; i++) { Wi [i] = FALSE ; } if (print >= 4) { for (k = 0 ; k < ((Int) len) ; k++) { ETC (k >= ((Int) len) - 4, count, -1) ; i = Perm [k] ; P4 (" "I8":", k) ; P4 (""ID"\n", i) ; if (i < 0 || i >= ((Int) n) || Wi [i]) { ERR ("invalid permutation") ; } Wi [i] = TRUE ; } } else { for (k = 0 ; k < ((Int) len) ; k++) { i = Perm [k] ; if (i < 0 || i >= ((Int) n) || Wi [i]) { ERR ("invalid permutation") ; } Wi [i] = TRUE ; } } } // perm is valid return (TRUE) ; } int CHOLMOD(check_perm) ( // input: Int *Perm, // Perm [0:len-1] is a permutation of subset of 0:n-1 size_t len, // size of Perm (an integer array) size_t n, // 0:n-1 is valid range cholmod_common *Common ) { RETURN_IF_NULL_COMMON (FALSE) ; Common->status = CHOLMOD_OK ; return (check_perm (NULL, 0, NULL, Perm, len, n, Common)) ; } int CHOLMOD(print_perm) ( // input: Int *Perm, // Perm [0:len-1] is a permutation of subset of 0:n-1 size_t len, // size of Perm (an integer array) size_t n, // 0:n-1 is valid range const char *name, // printed name of Perm cholmod_common *Common ) { Int ok, print ; RETURN_IF_NULL_COMMON (FALSE) ; Common->status = CHOLMOD_OK ; print = Common->print ; P4 ("%s", "\n") ; P3 ("%s", "CHOLMOD perm: ") ; if (name != NULL) { P3 ("%s: ", name) ; } P3 (" len: "ID"", (Int) len) ; P3 (" n: "ID"", (Int) n) ; P4 ("%s", "\n") ; ok = check_perm (NULL, print, name, Perm, len, n, Common) ; if (ok) { P3 ("%s", " OK\n") ; P4 ("%s", "\n") ; } return (ok) ; } //------------------------------------------------------------------------------ // cholmod_check_parent //------------------------------------------------------------------------------ // Ensure that Parent is a valid elimination tree of nodes 0 to n-1. // If j is a root of the tree then Parent [j] is EMPTY (-1). // // NOTE: this check will fail if applied to the component tree (CParent) in // cholmod_nested_dissection, unless it has been postordered and renumbered. // // workspace: none static int check_parent ( Int *Parent, size_t n, int print, const char *name, cholmod_common *Common ) { Int j, p, init_print, count ; const char *type = "parent" ; init_print = print ; P4 ("%s", "\n") ; P3 ("%s", "CHOLMOD parent: ") ; if (name != NULL) { P3 ("%s: ", name) ; } P3 (" n: "ID"", (Int) n) ; P4 ("%s", "\n") ; if (Parent == NULL) { ERR ("null") ; } //-------------------------------------------------------------------------- // checks that take O(n) time //-------------------------------------------------------------------------- ETC_START (count, 8) ; for (j = 0 ; j < ((Int) n) ; j++) { ETC (j == ((Int) n) - 4, count, -1) ; p = Parent [j] ; P4 (" "I8":", j) ; P4 (" "ID"\n", p) ; if (!(p == EMPTY || p > j)) { ERR ("invalid") ; } } P3 ("%s", " OK\n") ; P4 ("%s", "\n") ; return (TRUE) ; } int CHOLMOD(check_parent) ( // input: Int *Parent, // Parent [0:n-1] is an elimination tree size_t n, // size of Parent cholmod_common *Common ) { RETURN_IF_NULL_COMMON (FALSE) ; Common->status = CHOLMOD_OK ; return (check_parent (Parent, n, 0, NULL, Common)) ; } int CHOLMOD(print_parent) ( // input: Int *Parent, // Parent [0:n-1] is an elimination tree size_t n, // size of Parent const char *name, // printed name of Parent cholmod_common *Common ) { RETURN_IF_NULL_COMMON (FALSE) ; Common->status = CHOLMOD_OK ; return (check_parent (Parent, n, Common->print, name, Common)) ; } //------------------------------------------------------------------------------ // cholmod_check_factor //------------------------------------------------------------------------------ static int check_factor ( Int *Wi, int print, const char *name, cholmod_factor *L, cholmod_common *Common ) { void *Lx, *Lz ; Int *Lp, *Li, *Lnz, *Lnext, *Lprev, *Perm, *ColCount, *Lpi, *Lpx, *Super, *Ls ; Int n, nzmax, j, p, pend, i, nz, space, is_monotonic, minor, count, init_print, ilast, lnz, head, tail, jprev, plast, jnext, examine_super, nsuper, s, k1, k2, psi, psend, psx = 0, nsrow, nscol, psxend, ssize, xsize, maxcsize, maxesize, nsrow2, jj, ii ; Int check_Lpx ; const char *type = "factor" ; //-------------------------------------------------------------------------- // print header information //-------------------------------------------------------------------------- P4 ("%s", "\n") ; P3 ("%s", "CHOLMOD factor: ") ; if (name != NULL) { P3 ("%s: ", name) ; } if (L == NULL) { ERR ("null") ; } n = L->n ; minor = L->minor ; int xtype = L->xtype ; int dtype = L->dtype ; Perm = L->Perm ; ColCount = L->ColCount ; lnz = 0 ; P3 (" "ID"", n) ; P3 ("-by-"ID"", n) ; if (minor < n) { P3 (" not positive definite (column "ID")", minor) ; } switch (L->itype) { case CHOLMOD_INT: P4 ("%s", "\n scalar types: int32_t, ") ; break ; case CHOLMOD_LONG: P4 ("%s", "\n scalar types: int64_t, ") ; break ; default: ERR ("unknown itype") ; } switch (L->xtype) { case CHOLMOD_PATTERN: P4 ("%s", "pattern") ; break ; case CHOLMOD_REAL: P4 ("%s", "real") ; break ; case CHOLMOD_COMPLEX: P4 ("%s", "complex") ; break ; case CHOLMOD_ZOMPLEX: P4 ("%s", "zomplex") ; break ; default: ERR ("unknown xtype") ; } switch (L->dtype) { case CHOLMOD_DOUBLE: P4 ("%s", ", double\n") ; break ; case CHOLMOD_SINGLE: P4 ("%s", ", single\n") ; break ; default: ERR ("unknown dtype") ; } if (L->itype != ITYPE) { ERR ("integer type must match routine") ; } if (L->is_super) { P3 ("%s", " supernodal") ; } else { P3 ("%s", " simplicial") ; } if (L->is_ll) { P3 ("%s", ", LL'.") ; } else { P3 ("%s", ", LDL'.") ; } P4 ("%s", "\n ordering method used: ") ; switch (L->ordering) { case CHOLMOD_POSTORDERED:P4("%s", "natural (postordered)") ; break ; case CHOLMOD_NATURAL: P4 ("%s", "natural") ; break ; case CHOLMOD_GIVEN: P4 ("%s", "user-provided") ; break ; case CHOLMOD_AMD: P4 ("%s", "AMD") ; break ; case CHOLMOD_COLAMD: P4 ("%s", "AMD for A, COLAMD for A*A'") ;break ; #ifndef NPARTITION case CHOLMOD_METIS: P4 ("%s", "METIS NodeND") ; break ; case CHOLMOD_NESDIS: P4 ("%s", "CHOLMOD nested dissection") ; break ; #endif default: ERR ("unknown ordering") ; } P4 ("%s", "\n") ; init_print = print ; if (L->is_super && L->xtype == CHOLMOD_ZOMPLEX) { ERR ("Supernodal zomplex L not supported") ; } //-------------------------------------------------------------------------- // check L->Perm //-------------------------------------------------------------------------- if (!check_perm (Wi, print, name, Perm, n, n, Common)) { return (FALSE) ; } //-------------------------------------------------------------------------- // check L->ColCount //-------------------------------------------------------------------------- if (ColCount == NULL) { ERR ("ColCount vector invalid") ; } ETC_START (count, 8) ; for (j = 0 ; j < n ; j++) { ETC (j >= n-4, count, -1) ; P4 (" col: "ID" ", j) ; nz = ColCount [j] ; P4 ("colcount: "ID"\n", nz) ; if (nz < 0 || nz > n-j) { ERR ("ColCount out of range") ; } } //-------------------------------------------------------------------------- // check factor //-------------------------------------------------------------------------- if (L->xtype == CHOLMOD_PATTERN && !(L->is_super)) { //---------------------------------------------------------------------- // check simplicial symbolic factor //---------------------------------------------------------------------- // nothing else to do ; } else if (L->xtype != CHOLMOD_PATTERN && !(L->is_super)) { //---------------------------------------------------------------------- // check simplicial numerical factor //---------------------------------------------------------------------- P4 ("monotonic: %d\n", L->is_monotonic) ; nzmax = L->nzmax ; P3 (" nzmax "ID".", nzmax) ; P4 ("%s", "\n") ; Lp = L->p ; Li = L->i ; Lx = L->x ; Lz = L->z ; Lnz = L->nz ; Lnext = L->next ; Lprev = L->prev ; // check for existence of Lp, Li, Lnz, Lnext, Lprev, and Lx arrays if (Lp == NULL) { ERR ("p array not present") ; } if (Li == NULL) { ERR ("i array not present") ; } if (Lnz == NULL) { ERR ("nz array not present") ; } if (Lx == NULL) { ERR ("x array not present") ; } if (xtype == CHOLMOD_ZOMPLEX && Lz == NULL) { ERR ("z array not present") ; } if (Lnext == NULL) { ERR ("next array not present") ; } if (Lprev == NULL) { ERR ("prev array not present") ; } ETC_START (count, 8) ; // check each column of L plast = 0 ; is_monotonic = TRUE ; for (j = 0 ; j < n ; j++) { ETC (j >= n-3, count, -1) ; p = Lp [j] ; nz = Lnz [j] ; pend = p + nz ; lnz += nz ; P4 (" col "ID":", j) ; P4 (" nz "ID"", nz) ; P4 (" start "ID"", p) ; P4 (" end "ID"", pend) ; if (Lnext [j] < 0 || Lnext [j] > n) { ERR ("invalid link list") ; } space = Lp [Lnext [j]] - p ; P4 (" space "ID"", space) ; P4 (" free "ID":\n", space - nz) ; if (p < 0 || pend > nzmax || space < 1) { ERR ("pointer invalid") ; } if (nz < 1 || nz > (n-j) || nz > space) { ERR ("nz invalid") ; } ilast = j-1 ; if (p < plast) { is_monotonic = FALSE ; } plast = p ; // print the diagonal entry i = Li [p] ; P4 (" "I8":", i) ; if (i != j) { ERR ("diagonal missing") ; } print_value (print, xtype, dtype, Lx, Lz, p, Common) ; // print the off-diagonal entries P4 ("%s", "\n") ; ilast = j ; for (p++ ; p < pend ; p++) { ETC_DISABLE (count) ; i = Li [p] ; P4 (" "I8":", i) ; if (i < j || i >= n) { ERR ("row index out of range") ; } if (i <= ilast) { ERR ("row indices out of order") ; } print_value (print, xtype, dtype, Lx, Lz, p, Common) ; P4 ("%s", "\n") ; ilast = i ; } } if (L->is_monotonic && !is_monotonic) { ERR ("columns not monotonic") ; } // check the link list head = n+1 ; tail = n ; j = head ; jprev = EMPTY ; count = 0 ; for ( ; ; ) { if (j < 0 || j > n+1 || count > n+2) { ERR ("invalid link list") ; } jnext = Lnext [j] ; if (j >= 0 && j < n) { if (jprev != Lprev [j]) { ERR ("invalid link list") ; } } count++ ; if (j == tail) { break ; } jprev = j ; j = jnext ; } if (Lnext [tail] != EMPTY || count != n+2) { ERR ("invalid link list") ; } } else { //---------------------------------------------------------------------- // check supernodal numeric or symbolic factor //---------------------------------------------------------------------- nsuper = L->nsuper ; ssize = L->ssize ; xsize = L->xsize ; maxcsize = L->maxcsize ; maxesize = L->maxesize ; Ls = L->s ; Lpi = L->pi ; Lpx = L->px ; Super = L->super ; Lx = L->x ; ETC_START (count, 8) ; P4 (" ssize "ID" ", ssize) ; P4 ("xsize "ID" ", xsize) ; P4 ("maxcsize "ID" ", maxcsize) ; P4 ("maxesize "ID"\n", maxesize) ; if (Ls == NULL) { ERR ("invalid: L->s missing") ; } if (Lpi == NULL) { ERR ("invalid: L->pi missing") ; } if (Lpx == NULL) { ERR ("invalid: L->px missing") ; } if (Super == NULL) { ERR ("invalid: L->super missing") ; } if (L->xtype != CHOLMOD_PATTERN) { // numerical supernodal factor if (Lx == NULL) { ERR ("invalid: L->x missing") ; } if (Ls [0] == EMPTY) { ERR ("invalid: L->s not defined") ; } examine_super = TRUE ; } else { // symbolic supernodal factor, but only if it has been computed examine_super = (Ls [0] != EMPTY) ; } if (examine_super) { if (Lpi [0] != 0 || MAX (1, Lpi [nsuper]) != ssize) { PRINT0 (("Lpi [0] "ID", Lpi [nsuper = "ID"] = "ID"\n", Lpi [0], nsuper, Lpi [nsuper])) ; ERR ("invalid: L->pi invalid") ; } // If Lpx [0] is 123456, then supernodes are present but // Lpx [0...nsuper] is not defined, so don't check it. This is // used in the non-GPU accelerated SPQR check_Lpx = (Lpx [0] != 123456) ; if (check_Lpx && (Lpx [0] != 0 || MAX (1, Lpx[nsuper]) != xsize)) { ERR ("invalid: L->px invalid") ; } // check and print each supernode for (s = 0 ; s < nsuper ; s++) { k1 = Super [s] ; k2 = Super [s+1] ; psi = Lpi [s] ; psend = Lpi [s+1] ; nsrow = psend - psi ; nscol = k2 - k1 ; nsrow2 = nsrow - nscol ; if (check_Lpx) { psx = Lpx [s] ; psxend = Lpx [s+1] ; } ETC (s == nsuper-1, count, 4) ; P4 (" supernode "ID", ", s) ; P4 ("col "ID" ", k1) ; P4 ("to "ID". ", k2-1) ; P4 ("nz in first col: "ID".\n", nsrow) ; if (check_Lpx) { P4 (" values start "ID", ", psx) ; P4 ("end "ID"\n", psxend) ; } if (k1 > k2 || k1 < 0 || k2 > n || nsrow < nscol || nsrow2 < 0 || (check_Lpx && psxend - psx != nsrow * nscol)) { ERR ("invalid supernode") ; } lnz += nscol * nsrow - (nscol*nscol - nscol)/2 ; if (L->xtype != CHOLMOD_PATTERN) { // print each column of the supernode for (jj = 0 ; jj < nscol ; jj++) { ETC_ENABLE (s == nsuper-1 && jj >= nscol-3, count, -1) ; j = k1 + jj ; P4 (" col "ID"\n", j) ; ilast = j ; i = Ls [psi + jj] ; P4 (" "I8":", i) ; if (i != j) { ERR ("row index invalid") ; } // print (Lx [psx + jj + jj*nsrow]) print_value (print, xtype, dtype, Lx, NULL, psx + jj + jj*nsrow, Common) ; P4 ("%s", "\n") ; for (ii = jj + 1 ; ii < nsrow ; ii++) { ETC_DISABLE (count) ; i = Ls [psi + ii] ; P4 (" "I8":", i) ; if (i <= ilast || i > n) { ERR ("row index out of range") ; } // print (Lx [psx + ii + jj*nsrow]) print_value (print, xtype, dtype, Lx, NULL, psx + ii + jj*nsrow, Common) ; P4 ("%s", "\n") ; ilast = i ; } } } else { // just print the leading column of the supernode P4 (" col "ID"\n", k1) ; for (jj = 0 ; jj < nscol ; jj++) { ETC (s == nsuper-1 && jj >= nscol-3, count, -1) ; j = k1 + jj ; i = Ls [psi + jj] ; P4 (" "I8"", i) ; if (i != j) { ERR ("row index invalid") ; } P4 ("%s", "\n") ; } ilast = j ; for (ii = nscol ; ii < nsrow ; ii++) { ETC_DISABLE (count) ; i = Ls [psi + ii] ; P4 (" "I8"", i) ; if (i <= ilast || i > n) { ERR ("row index out of range") ; } P4 ("%s", "\n") ; ilast = i ; } } } } } // factor is valid P3 (" nz "ID"", lnz) ; P3 ("%s", " OK\n") ; P4 ("%s", "\n") ; return (TRUE) ; } int CHOLMOD(check_factor) ( // input: cholmod_factor *L, // factor to check cholmod_common *Common ) { RETURN_IF_NULL_COMMON (FALSE) ; Common->status = CHOLMOD_OK ; return (check_factor (NULL, 0, NULL, L, Common)) ; } int CHOLMOD(print_factor) ( // input: cholmod_factor *L, // factor to print const char *name, // printed name of factor cholmod_common *Common ) { RETURN_IF_NULL_COMMON (FALSE) ; Common->status = CHOLMOD_OK ; return (check_factor (NULL, Common->print, name, L, Common)) ; } //------------------------------------------------------------------------------ // cholmod_check_triplet //------------------------------------------------------------------------------ // Ensure a triplet matrix is valid, and optionally print it. static int check_triplet ( int print, const char *name, cholmod_triplet *T, cholmod_common *Common ) { void *Tx, *Tz ; Int *Ti, *Tj ; Int i, j, p, nrow, ncol, nzmax, nz, init_print, count ; const char *type = "triplet" ; //-------------------------------------------------------------------------- // print header information //-------------------------------------------------------------------------- P4 ("%s", "\n") ; P3 ("%s", "CHOLMOD triplet: ") ; if (name != NULL) { P3 ("%s: ", name) ; } if (T == NULL) { ERR ("null") ; } nrow = T->nrow ; ncol = T->ncol ; nzmax = T->nzmax ; nz = T->nnz ; Ti = T->i ; Tj = T->j ; Tx = T->x ; Tz = T->z ; int xtype = T->xtype ; int dtype = T->dtype ; P3 (" "ID"", nrow) ; P3 ("-by-"ID", ", ncol) ; P3 ("nz "ID",", nz) ; if (T->stype > 0) { P3 ("%s", " upper.") ; } else if (T->stype < 0) { P3 ("%s", " lower.") ; } else { P3 ("%s", " up/lo.") ; } P4 ("\n nzmax "ID", ", nzmax) ; if (nz > nzmax) { ERR ("nzmax too small") ; } switch (T->itype) { case CHOLMOD_INT: P4 ("%s", "\n scalar types: int32_t, ") ; break ; case CHOLMOD_LONG: P4 ("%s", "\n scalar types: int64_t, ") ; break ; default: ERR ("unknown itype") ; } switch (T->xtype) { case CHOLMOD_PATTERN: P4 ("%s", "pattern") ; break ; case CHOLMOD_REAL: P4 ("%s", "real") ; break ; case CHOLMOD_COMPLEX: P4 ("%s", "complex") ; break ; case CHOLMOD_ZOMPLEX: P4 ("%s", "zomplex") ; break ; default: ERR ("unknown xtype") ; } switch (T->dtype) { case CHOLMOD_DOUBLE: P4 ("%s", ", double\n") ; break ; case CHOLMOD_SINGLE: P4 ("%s", ", single\n") ; break ; default: ERR ("unknown dtype") ; } if (T->itype != ITYPE) { ERR ("integer type must match routine") ; } if (T->stype && nrow != ncol) { ERR ("symmetric but not square") ; } // check for existence of Ti, Tj, Tx arrays if (Tj == NULL) { ERR ("j array not present") ; } if (Ti == NULL) { ERR ("i array not present") ; } if (xtype != CHOLMOD_PATTERN && Tx == NULL) { ERR ("x array not present") ; } if (xtype == CHOLMOD_ZOMPLEX && Tz == NULL) { ERR ("z array not present") ; } //-------------------------------------------------------------------------- // check and print each entry //-------------------------------------------------------------------------- init_print = print ; ETC_START (count, 8) ; for (p = 0 ; p < nz ; p++) { ETC (p >= nz-4, count, -1) ; i = Ti [p] ; P4 (" "I8":", p) ; P4 (" "I_8"", i) ; if (i < 0 || i >= nrow) { ERR ("row index out of range") ; } j = Tj [p] ; P4 (" "I_8"", j) ; if (j < 0 || j >= ncol) { ERR ("column index out of range") ; } print_value (print, xtype, dtype, Tx, Tz, p, Common) ; P4 ("%s", "\n") ; } // triplet matrix is valid P3 ("%s", " OK\n") ; P4 ("%s", "\n") ; return (TRUE) ; } int CHOLMOD(check_triplet) ( // input: cholmod_triplet *T, // triplet matrix to check cholmod_common *Common ) { RETURN_IF_NULL_COMMON (FALSE) ; Common->status = CHOLMOD_OK ; return (check_triplet (0, NULL, T, Common)) ; } int CHOLMOD(print_triplet) ( // input: cholmod_triplet *T, // triplet matrix to print const char *name, // printed name of triplet matrix cholmod_common *Common ) { RETURN_IF_NULL_COMMON (FALSE) ; Common->status = CHOLMOD_OK ; return (check_triplet (Common->print, name, T, Common)) ; } //------------------------------------------------------------------------------ // CHOLMOD debugging routines //------------------------------------------------------------------------------ #ifndef NDEBUG // The global variables present only when debugging enabled. int CHOLMOD(dump) = 0 ; int CHOLMOD(dump_malloc) = -1 ; // workspace: no debug routines use workspace in Common //------------------------------------------------------------------------------ // cholmod_dump_init //------------------------------------------------------------------------------ void CHOLMOD(dump_init) (const char *s, cholmod_common *Common) { int i = 0 ; FILE *f ; f = fopen ("debug", "r") ; CHOLMOD(dump) = 0 ; if (f != NULL) { i = fscanf (f, "%d", &CHOLMOD(dump)) ; fclose (f) ; } PRINT1 (("%s: cholmod_dump_init, D = %d\n", s, CHOLMOD(dump))) ; } //------------------------------------------------------------------------------ // cholmod_dump_sparse //------------------------------------------------------------------------------ // returns nnz (diag (A)) or EMPTY if error int64_t CHOLMOD(dump_sparse) ( cholmod_sparse *A, const char *name, cholmod_common *Common ) { Int *Wi ; int64_t nnzdiag ; Int ok ; if (CHOLMOD(dump) < -1) { // no checks if debug level is -2 or less return (0) ; } RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; Wi = malloc (MAX (1, A->nrow) * sizeof (Int)) ; ok = check_sparse (Wi, CHOLMOD(dump), name, A, &nnzdiag, Common) ; if (Wi != NULL) free (Wi) ; return (ok ? nnzdiag : EMPTY) ; } //------------------------------------------------------------------------------ // cholmod_dump_factor //------------------------------------------------------------------------------ int CHOLMOD(dump_factor) ( cholmod_factor *L, const char *name, cholmod_common *Common ) { Int *Wi ; int ok ; if (CHOLMOD(dump) < -1) { // no checks if debug level is -2 or less return (TRUE) ; } RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (L, FALSE) ; Wi = malloc (MAX (1, L->n) * sizeof (Int)) ; ok = check_factor (Wi, CHOLMOD(dump), name, L, Common) ; if (Wi != NULL) free (Wi) ; return (ok) ; } //------------------------------------------------------------------------------ // cholmod_dump_perm //------------------------------------------------------------------------------ int CHOLMOD(dump_perm) ( Int *Perm, size_t len, size_t n, const char *name, cholmod_common *Common ) { Int *Wi ; int ok ; if (CHOLMOD(dump) < -1) { // no checks if debug level is -2 or less return (TRUE) ; } RETURN_IF_NULL_COMMON (FALSE) ; Wi = malloc (MAX (1, n) * sizeof (Int)) ; ok = check_perm (Wi, CHOLMOD(dump), name, Perm, len, n,Common) ; if (Wi != NULL) free (Wi) ; return (ok) ; } //------------------------------------------------------------------------------ // cholmod_dump_dense //------------------------------------------------------------------------------ int CHOLMOD(dump_dense) ( cholmod_dense *X, const char *name, cholmod_common *Common ) { if (CHOLMOD(dump) < -1) { // no checks if debug level is -2 or less return (TRUE) ; } RETURN_IF_NULL_COMMON (FALSE) ; return (check_dense (CHOLMOD(dump), name, X, Common)) ; } //------------------------------------------------------------------------------ // cholmod_dump_triplet //------------------------------------------------------------------------------ int CHOLMOD(dump_triplet) ( cholmod_triplet *T, const char *name, cholmod_common *Common ) { if (CHOLMOD(dump) < -1) { // no checks if debug level is -2 or less return (TRUE) ; } RETURN_IF_NULL_COMMON (FALSE) ; return (check_triplet (CHOLMOD(dump), name, T, Common)) ; } //------------------------------------------------------------------------------ // cholmod_dump_subset //------------------------------------------------------------------------------ int CHOLMOD(dump_subset) ( Int *S, size_t len, size_t n, const char *name, cholmod_common *Common ) { if (CHOLMOD(dump) < -1) { // no checks if debug level is -2 or less return (TRUE) ; } RETURN_IF_NULL_COMMON (FALSE) ; return (check_subset (S, len, n, CHOLMOD(dump), name, Common)) ; } //------------------------------------------------------------------------------ // cholmod_dump_parent //------------------------------------------------------------------------------ int CHOLMOD(dump_parent) ( Int *Parent, size_t n, const char *name, cholmod_common *Common ) { if (CHOLMOD(dump) < -1) { // no checks if debug level is -2 or less return (TRUE) ; } RETURN_IF_NULL_COMMON (FALSE) ; return (check_parent (Parent, n, CHOLMOD(dump), name, Common)) ; } //------------------------------------------------------------------------------ // cholmod_dump_real //------------------------------------------------------------------------------ void CHOLMOD(dump_real) ( const char *name, void *X, // float or double, in column-major form int dtype, // CHOLMOD_SINGLE or CHOLMOD_DOUBLE int64_t nrow, // # of rows int64_t ncol, // # of cols int lower, // if true, only print lower triangular part int xentry, // 1 if real, 2 if complex (never zomplex) cholmod_common *Common ) { // dump an nrow-by-ncol real or complex dense matrix if (CHOLMOD(dump) < -1) { // no checks if debug level is -2 or less return ; } PRINT1 (("%s: dump_real, nrow: %ld ncol: %ld lower: %d\n", name, nrow, ncol, lower)) ; int64_t p = 0 ; for (int64_t j = 0 ; j < ncol ; j++) { PRINT2 ((" col %ld\n", j)) ; for (int64_t i = 0 ; i < nrow ; i++) { // X is stored in column-major form if (lower && i < j) { PRINT2 ((" %5ld: -", i)) ; } else { // x = X [p] double x = GETVAL (X, p, dtype) ; PRINT2 ((" %5ld: %e", i, x)) ; if (xentry == 2) { // x = X [p+1] double z = GETVAL (X, p+1, dtype) ; PRINT2 ((", %e", z)) ; } } PRINT2 (("\n")) ; p += xentry ; } } } //------------------------------------------------------------------------------ // cholmod_dump_super //------------------------------------------------------------------------------ void CHOLMOD(dump_super) ( int64_t s, Int *Super, Int *Lpi, Int *Ls, Int *Lpx, void *Lx, // float or double int dtype, // CHOLMOD_SINGLE or CHOLMOD_DOUBLE int xentry, cholmod_common *Common ) { Int k1, k2, do_values, psi, psx, nsrow, nscol, psend, ilast, p, i ; if (CHOLMOD(dump) < -1) { // no checks if debug level is -2 or less return ; } k1 = Super [s] ; k2 = Super [s+1] ; nscol = k2 - k1 ; do_values = (Lpx != NULL) && (Lx != NULL) ; psi = Lpi [s] ; psend = Lpi [s+1] ; nsrow = psend - psi ; PRINT1 (("\nSuper %ld, columns "ID" to "ID", "ID" rows "ID" cols\n", s, k1, k2-1, nsrow, nscol)) ; ilast = -1 ; for (p = psi ; p < psend ; p++) { i = Ls [p] ; PRINT2 ((" "ID" : p-psi "ID"\n", i, p-psi)) ; ASSERT (IMPLIES (p-psi < nscol, i == k1 + (p-psi))) ; if (p-psi == nscol-1) PRINT2 (("------\n")) ; ASSERT (i > ilast) ; ilast = i ; } if (do_values) { psx = Lpx [s] ; if (dtype == CHOLMOD_DOUBLE) { double *X = (double *) Lx ; CHOLMOD(dump_real) ("Supernode", X + xentry*psx, dtype, nsrow, nscol, TRUE, xentry, Common) ; } else { float *X = (float *) Lx ; CHOLMOD(dump_real) ("Supernode", X + xentry*psx, dtype, nsrow, nscol, TRUE, xentry, Common) ; } } } //------------------------------------------------------------------------------ // cholmod_dump_mem //------------------------------------------------------------------------------ int CHOLMOD(dump_mem) ( const char *where, int64_t should, cholmod_common *Common ) { int64_t diff = should - Common->memory_inuse ; if (diff != 0) { PRINT0 (("mem: %-15s peak %10g inuse %10g should %10g\n", where, (double) Common->memory_usage, (double) Common->memory_inuse, (double) should)) ; PRINT0 (("mem: %s diff %ld !\n", where, diff)) ; } return (diff == 0) ; } //------------------------------------------------------------------------------ // cholmod_dump_partition //------------------------------------------------------------------------------ // make sure we have a proper separator (for debugging only) // // workspace: none int CHOLMOD(dump_partition) ( int64_t n, Int *Cp, Int *Ci, Int *Cnw, // can be NULL Int *Part, int64_t sepsize, cholmod_common *Common ) { Int chek [3], which, ok, i, j, p ; PRINT1 (("bisect sepsize %ld\n", sepsize)) ; ok = TRUE ; chek [0] = 0 ; chek [1] = 0 ; chek [2] = 0 ; for (j = 0 ; j < n ; j++) { PRINT2 (("--------j "ID" in part "ID" nw "ID"\n", j, Part [j], Cnw ? (Cnw[j]):1)); which = Part [j] ; for (p = Cp [j] ; p < Cp [j+1] ; p++) { i = Ci [p] ; PRINT3 (("i "ID", part "ID"\n", i, Part [i])) ; if (which == 0) { if (Part [i] == 1) { PRINT0 (("Error! "ID" "ID"\n", i, j)) ; ok = FALSE ; } } else if (which == 1) { if (Part [i] == 0) { PRINT0 (("Error! "ID" "ID"\n", i, j)) ; ok = FALSE ; } } } if (which < 0 || which > 2) { PRINT0 (("Part out of range\n")) ; ok = FALSE ; } chek [which] += (Cnw ? (Cnw [j]) : 1) ; } PRINT1 (("sepsize %ld check "ID" "ID" "ID"\n", sepsize, chek[0], chek[1],chek[2])); if (sepsize != chek[2]) { PRINT0 (("mismatch!\n")) ; ok = FALSE ; } return (ok) ; } //------------------------------------------------------------------------------ // cholmod_dump_work //------------------------------------------------------------------------------ int CHOLMOD(dump_work) (int flag, int head, int64_t wsize, int dtype, cholmod_common *Common) { Int *Flag, *Head ; Int k, nrow, mark ; if (CHOLMOD(dump) < -1) { // no checks if debug level is -2 or less return (TRUE) ; } RETURN_IF_NULL_COMMON (FALSE) ; nrow = Common->nrow ; Flag = Common->Flag ; Head = Common->Head ; mark = Common->mark ; if (flag) { for (k = 0 ; k < nrow ; k++) { if (Flag [k] >= mark) { PRINT0 (("Flag invalid, Flag ["ID"] = "ID", mark = "ID"\n", k, Flag [k], mark)) ; return (FALSE) ; } } } if (head) { for (k = 0 ; k < nrow ; k++) { if (Head [k] != EMPTY) { PRINT0 (("Head invalid, Head ["ID"] = "ID"\n", k, Head [k])) ; return (FALSE) ; } } } // if wsize is negative, all of Common->Xwork is checked. #define CHECK_XWORK(fltype) \ { \ fltype *W = Common->Xwork ; \ int64_t s = (int64_t) (Common->xworkbytes / sizeof (fltype)) ; \ if (wsize < 0) \ { \ wsize = s ; \ } \ else \ { \ wsize = MIN (wsize, s) ; \ } \ for (k = 0 ; k < wsize ; k++) \ { \ if (W [k] != 0.) \ { \ PRINT0 (("W invalid, W ["ID"] = %g\n", k, W [k])) ; \ return (FALSE) ; \ } \ } \ } if (dtype == CHOLMOD_DOUBLE) { CHECK_XWORK (double) ; } else { CHECK_XWORK (float) ; } return (TRUE) ; } #endif #endif Matrix/src/SuiteSparse/CHOLMOD/Supernodal/0000755000175100001440000000000014576344041020003 5ustar hornikusersMatrix/src/SuiteSparse/CHOLMOD/Supernodal/cholmod_super_symbolic.c0000644000175100001440000010505214552026002024702 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Supernodal/cholmod_super_symbolic: symbolic supernodal analysis //------------------------------------------------------------------------------ // CHOLMOD/Supernodal Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // Supernodal symbolic analysis of the LL' factorization of A, A*A', // A(:,f)*A(:,f)'. // // This routine must be preceded by a simplicial symbolic analysis // (cholmod_rowcolcounts). See cholmod_analyze.c for an example of how to use // this routine. // // The user need not call this directly; cholmod_analyze is a "simple" wrapper // for this routine. // // Symmetric case: // // A is stored in column form, with entries stored in the upper triangular // part. Entries in the lower triangular part are ignored. // // Unsymmetric case: // // A is stored in column form. If F is equal to the transpose of A, then // A*A' is analyzed. F can include a subset of the columns of A // (F=A(:,f)'), in which case F*F' is analyzed. // // Requires Parent and L->ColCount to be defined on input; these are the // simplicial Parent and ColCount arrays as computed by cholmod_rowcolcounts. // Does not use L->Perm; the input matrices A and F must already be properly // permuted. Allocates and computes the supernodal pattern of L (L->super, // L->pi, L->px, and L->s). Does not allocate the real part (L->x). // // Supports any xtype (pattern, real, complex, or zomplex) and any dtype. #include "cholmod_internal.h" #ifndef NGPL #ifndef NSUPERNODAL //------------------------------------------------------------------------------ // subtree //------------------------------------------------------------------------------ // In the symmetric case, traverse the kth row subtree from the nonzeros in // A (0:k1-1,k) and add the new entries found to the pattern of the kth row // of L. The current supernode s contains the diagonal block k1:k2-1, so it // can be skipped. // // In the unsymmetric case, the nonzero pattern of A*F is computed one column // at a time (thus, the total time spent in this function is bounded below by // the time taken to multiply A*F, which can be high if A is tall and thin). // The kth column is A*F(:,k), or the set union of all columns A(:,j) for which // F(j,k) is nonzero. This routine is called once for each entry j. Only the // upper triangular part is needed, so only A (0:k1-1,j) is accessed, where // k1:k2-1 are the columns of the current supernode s (k is in the range k1 to // k2-1). // // If A is sorted, then the total time taken by this function is proportional // to the number of nonzeros in the strictly block upper triangular part of A, // plus the number of entries in the strictly block lower triangular part of // the supernodal part of L. This excludes entries in the diagonal blocks // corresponding to the columns in each supernode. That is, if k1:k2-1 are // in a single supernode, then only A (0:k1-1,k1:k2-1) are accessed. // // For the unsymmetric case, only the strictly block upper triangular part // of A*F is constructed. // // Only adds column indices corresponding to the leading columns of each // relaxed supernode. static void subtree ( // inputs, not modified: Int j, // j = k for symmetric case Int k, Int Ap [ ], Int Ai [ ], Int Anz [ ], Int SuperMap [ ], Int Sparent [ ], Int mark, Int sorted, // true if the columns of A are sorted Int k1, // only consider A (0:k1-1,k) // input/output: Int Flag [ ], Int Ls [ ], Int Lpi2 [ ] ) { Int p, pend, i, si ; p = Ap [j] ; pend = (Anz == NULL) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { i = Ai [p] ; if (i < k1) { // (i,k) is an entry in the upper triangular part of A or A*F'. // symmetric case: A(i,k) is nonzero (j=k). // unsymmetric case: A(i,j) and F(j,k) are both nonzero. // // Column i is in supernode si = SuperMap [i]. Follow path from si // to root of supernodal etree, stopping at the first flagged // supernode. The root of the row subtree is supernode SuperMap[k], // which is flagged already. This traversal will stop there, or it // might stop earlier if supernodes have been flagged by previous // calls to this routine for the same k. for (si = SuperMap [i] ; Flag [si] < mark ; si = Sparent [si]) { ASSERT (si <= SuperMap [k]) ; Ls [Lpi2 [si]++] = k ; Flag [si] = mark ; } } else if (sorted) { break ; } } } // clear workspace used by cholmod_super_symbolic #define FREE_WORKSPACE \ { \ CLEAR_FLAG (Common) ; \ ASSERT (check_flag (Common)) ; \ for (k = 0 ; k <= nfsuper ; k++) \ { \ Head [k] = EMPTY ; \ } \ ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; \ } //------------------------------------------------------------------------------ // cholmod_super_symbolic2 //------------------------------------------------------------------------------ // Analyze for supernodal Cholesky or multifrontal QR. int CHOLMOD(super_symbolic2) ( // input: int for_whom, // FOR_SPQR (0): for SPQR but not GPU-accelerated // FOR_CHOLESKY (1): for Cholesky (GPU or not) // FOR_SPQRGPU (2): for SPQR with GPU acceleration cholmod_sparse *A, // matrix to analyze cholmod_sparse *F, // F = A' or A(:,f)' Int *Parent, // elimination tree // input/output: cholmod_factor *L, // simplicial symbolic on input, // supernodal symbolic on output cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- double zrelax0, zrelax1, zrelax2 ; Int *Wi, *Wj, *Super, *Snz, *Ap, *Ai, *Flag, *Head, *Ls, *Lpi, *Lpx, *Fnz, *Sparent, *Anz, *SuperMap, *Merged, *Nscol, *Zeros, *Fp, *Fj, *ColCount, *Lpi2, *Lsuper, *Iwork ; Int nsuper, d, n, j, k, s, mark, parent, p, pend, k1, k2, packed, ndrow1, ndrow2, stype, sparent, plast, slast, csize, maxcsize, ss, nscol0, nscol1, ns, nfsuper, newzeros, totzeros, merge, snext, esize, maxesize, nrelax0, nrelax1, nrelax2, Asorted ; int find_xsize ; #if (defined(CHOLMOD_HAS_CUDA) && defined(CHOLMOD_INT64)) const char* env_use_gpu; const char* env_max_bytes; size_t max_bytes; const char* env_max_fraction; double max_fraction ; #endif RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (L, FALSE) ; RETURN_IF_NULL (Parent, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_PATTERN, FALSE) ; stype = A->stype ; if (stype < 0) { // invalid symmetry; symmetric lower form not supported ERROR (CHOLMOD_INVALID, "symmetric lower not supported") ; return (FALSE) ; } if (stype == 0) { // F must be present in the unsymmetric case RETURN_IF_NULL (F, FALSE) ; } if (L->is_super) { // L must be a simplicial symbolic factor ERROR (CHOLMOD_INVALID, "L must be symbolic on input") ; return (FALSE) ; } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate workspace //-------------------------------------------------------------------------- n = A->nrow ; // w = 5*nrow int ok = TRUE ; size_t w = CHOLMOD(mult_size_t) (A->nrow, 5, &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (FALSE) ; } CHOLMOD(allocate_work) (A->nrow, w, 0, Common) ; if (Common->status < CHOLMOD_OK) { // out of memory return (FALSE) ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; //-------------------------------------------------------------------------- // allocate GPU workspace //-------------------------------------------------------------------------- L->useGPU = 0 ; // only used for Cholesky factorization, not QR #ifdef CHOLMOD_HAS_CUDA // GPU module is installed if (for_whom == CHOLMOD_ANALYZE_FOR_CHOLESKY && A->dtype == CHOLMOD_DOUBLE) { // only allocate GPU workspace for supernodal Cholesky (double // real/complex/zomples only), and only when the GPU is requested and // available. #ifdef CHOLMOD_INT64 max_bytes = 0; max_fraction = 0; if ( Common->useGPU == EMPTY ) { // useGPU not explicitly requested by the user, but not explicitly // prohibited either. Query OS environment variables for request. env_use_gpu = getenv("CHOLMOD_USE_GPU") ; if ( env_use_gpu ) { // CHOLMOD_USE_GPU environment variable is set to something if ( atoi ( env_use_gpu ) == 0 ) { Common->useGPU = 0; // don't use the gpu } else { Common->useGPU = 1; // use the gpu env_max_bytes = getenv("CHOLMOD_GPU_MEM_BYTES") ; env_max_fraction = getenv("CHOLMOD_GPU_MEM_FRACTION") ; if ( env_max_bytes ) { max_bytes = atol(env_max_bytes) ; Common->maxGpuMemBytes = max_bytes; } if ( env_max_fraction ) { max_fraction = atof (env_max_fraction) ; if ( max_fraction < 0 ) max_fraction = 0; if ( max_fraction > 1 ) max_fraction = 1; Common->maxGpuMemFraction = max_fraction; } } } else { // CHOLMOD_USE_GPU environment variable not set, so no GPU // acceleration will be used Common->useGPU = 0; } // fprintf (stderr, "useGPU queried: %d\n", Common->useGPU) ; } // Ensure that a GPU is present if ( Common->useGPU == 1 ) { // fprintf (stderr, "\nprobe GPU:\n") ; // Cholesky only, not SPQR Common->useGPU = CHOLMOD(gpu_probe) (Common) ; // fprintf (stderr, "\nprobe GPU: result %d\n", Common->useGPU) ; } if ( Common->useGPU == 1 ) { // Cholesky + GPU, so allocate space // fprintf (stderr, "allocate GPU:\n") ; // Cholesky only, not SPQR CHOLMOD(gpu_allocate) ( Common ) ; // fprintf (stderr, "allocate GPU done\n") ; } #else // GPU acceleration is only supported for long int version Common->useGPU = 0; #endif // Cache the fact that the symbolic factorization supports // GPU acceleration L->useGPU = Common->useGPU ; } #else // GPU module is not installed Common->useGPU = 0 ; #endif //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- // A is now either A or triu(A(p,p)) for the symmetric case. It is either // A or A(p,f) for the unsymmetric case (both in column form). It can be // either packed or unpacked, and either sorted or unsorted. Entries in // the lower triangular part may be present if A is symmetric, but these // are ignored. Ap = A->p ; Ai = A->i ; Anz = A->nz ; if (stype != 0) { // F not accessed Fp = NULL ; Fj = NULL ; Fnz = NULL ; packed = TRUE ; } else { // F = A(:,f) or A(p,f) in packed row form, either sorted or unsorted Fp = F->p ; Fj = F->i ; Fnz = F->nz ; packed = F->packed ; } ColCount = L->ColCount ; nrelax0 = Common->nrelax [0] ; nrelax1 = Common->nrelax [1] ; nrelax2 = Common->nrelax [2] ; zrelax0 = Common->zrelax [0] ; zrelax1 = Common->zrelax [1] ; zrelax2 = Common->zrelax [2] ; zrelax0 = isnan (zrelax0) ? 0 : zrelax0 ; zrelax1 = isnan (zrelax1) ? 0 : zrelax1 ; zrelax2 = isnan (zrelax2) ? 0 : zrelax2 ; ASSERT (CHOLMOD(dump_parent) (Parent, n, "Parent", Common)) ; //-------------------------------------------------------------------------- // get workspace //-------------------------------------------------------------------------- // Sparent, Snz, and Merged could be allocated later, of size nfsuper Iwork = Common->Iwork ; Wi = Iwork ; // size n Wj = Iwork + n ; // size n Sparent = Iwork + 2*((size_t) n) ; // size nfsuper <= n [ Snz = Iwork + 3*((size_t) n) ; // size nfsuper <= n [ Merged = Iwork + 4*((size_t) n) ; // size nfsuper <= n [ Flag = Common->Flag ; // size n Head = Common->Head ; // size n+1 //-------------------------------------------------------------------------- // find the fundamental supernodes //-------------------------------------------------------------------------- // count the number of children of each node, using Wi [ for (j = 0 ; j < n ; j++) { Wi [j] = 0 ; } for (j = 0 ; j < n ; j++) { parent = Parent [j] ; if (parent != EMPTY) { Wi [parent]++ ; } } Super = Head ; // use Head [0..nfsuper] as workspace for Super list ( // column 0 always starts a new supernode nfsuper = (n == 0) ? 0 : 1 ; // number of fundamental supernodes Super [0] = 0 ; for (j = 1 ; j < n ; j++) { // check if j starts new supernode, or in the same supernode as j-1 if (Parent [j-1] != j // parent of j-1 is not j || (ColCount [j-1] != ColCount [j] + 1) // j-1 not subset of j || Wi [j] > 1 // j has more than one child #ifdef CHOLMOD_HAS_CUDA // Ensure that the supernode will fit in the GPU buffers // Data size of 16 bytes must be assumed for case of PATTERN || (for_whom == CHOLMOD_ANALYZE_FOR_CHOLESKY && L->useGPU && (j-Super[nfsuper-1]+1) * ColCount[Super[nfsuper-1]] * sizeof(double) * 2 >= Common->devBuffSize) #endif ) { // j is the leading node of a supernode Super [nfsuper++] = j ; } } Super [nfsuper] = n ; // contents of Wi no longer needed for child count ] Nscol = Wi ; // use Wi as size-nfsuper workspace for Nscol [ //-------------------------------------------------------------------------- // find the mapping of fundamental nodes to supernodes //-------------------------------------------------------------------------- SuperMap = Wj ; // use Wj as workspace for SuperMap [ // SuperMap [k] = s if column k is contained in supernode s for (s = 0 ; s < nfsuper ; s++) { for (k = Super [s] ; k < Super [s+1] ; k++) { SuperMap [k] = s ; } } //-------------------------------------------------------------------------- // construct the fundamental supernodal etree //-------------------------------------------------------------------------- for (s = 0 ; s < nfsuper ; s++) { j = Super [s+1] - 1 ; // last node in supernode s parent = Parent [j] ; // parent of last node Sparent [s] = (parent == EMPTY) ? EMPTY : SuperMap [parent] ; PRINT1 (("Sparent ["ID"] = "ID"\n", s, Sparent [s])) ; } // contents of Wj no longer needed as workspace for SuperMap ] // SuperMap will be recomputed below, for the relaxed supernodes. Zeros = Wj ; // use Wj for Zeros, workspace of size nfsuper [ //-------------------------------------------------------------------------- // relaxed amalgamation //-------------------------------------------------------------------------- for (s = 0 ; s < nfsuper ; s++) { Merged [s] = EMPTY ; // s not merged into another Nscol [s] = Super [s+1] - Super [s] ; // # of columns in s Zeros [s] = 0 ; // # of zero entries in s ASSERT (s <= Super [s]) ; Snz [s] = ColCount [Super [s]] ; // # of entries in leading col of s PRINT2 (("lnz ["ID"] "ID"\n", s, Snz [s])) ; } for (s = nfsuper-2 ; s >= 0 ; s--) { double lnz1 ; // should supernodes s and s+1 merge into a new node s? PRINT1 (("\n========= Check relax of s "ID" and s+1 "ID"\n", s, s+1)) ; ss = Sparent [s] ; if (ss == EMPTY) { PRINT1 (("s "ID" is a root, no merge with s+1 = "ID"\n", s, s+1)) ; continue ; } // find the current parent of s (perform path compression as needed) for (ss = Sparent [s] ; Merged [ss] != EMPTY ; ss = Merged [ss]) ; sparent = ss ; PRINT2 (("Current sparent of s "ID" is "ID"\n", s, sparent)) ; // ss is the current parent of s for (ss = Sparent [s] ; Merged [ss] != EMPTY ; ss = snext) { snext = Merged [ss] ; PRINT2 (("ss "ID" is dead, merged into snext "ID"\n", ss, snext)) ; Merged [ss] = sparent ; } // if s+1 is not the current parent of s, do not merge if (sparent != s+1) { continue ; } nscol0 = Nscol [s] ; // # of columns in s nscol1 = Nscol [s+1] ; // # of columns in s+1 ns = nscol0 + nscol1 ; PRINT2 (("ns "ID" nscol0 "ID" nscol1 "ID"\n", ns, nscol0, nscol1)) ; totzeros = Zeros [s+1] ; // current # of zeros in s+1 lnz1 = (double) (Snz [s+1]) ; // # entries in leading column of s+1 // determine if supernodes s and s+1 should merge if (ns <= nrelax0) { PRINT2 (("ns is tiny ("ID"), so go ahead and merge\n", ns)) ; merge = TRUE ; } else { // use double to avoid integer overflow; approximations are OK double lnz0 = Snz [s] ; // # entries in leading column of s double xnewzeros = nscol0 * (lnz1 + nscol0 - lnz0) ; // use Int for the final update of Zeros [s] below newzeros = nscol0 * (Snz [s+1] + nscol0 - Snz [s]) ; ASSERT (newzeros == xnewzeros) ; PRINT2 (("lnz0 %g lnz1 %g xnewzeros %g\n", lnz0, lnz1, xnewzeros)) ; if (xnewzeros == 0) { // no new zeros, so go ahead and merge PRINT2 (("no new fillin, so go ahead and merge\n")) ; merge = TRUE ; } else { // # of zeros if merged double xtotzeros = ((double) totzeros) + xnewzeros ; // xtotsize: total size of merged supernode, if merged: double xns = (double) ns ; double xtotsize = (xns * (xns+1) / 2) + xns * (lnz1 - nscol1) ; double z = xtotzeros / xtotsize ; PRINT2 (("oldzeros "ID" newzeros "ID" xtotsize %g z %g\n", Zeros [s+1], newzeros, xtotsize, z)) ; // use Int for the final update of Zeros [s] below totzeros += newzeros ; // do not merge if supernode would become too big // (Int overflow). Continue computing; not (yet) an error. // fl.pt. compare, but no NaN's can occur here merge = ((ns <= nrelax1 && z < zrelax0) || (ns <= nrelax2 && z < zrelax1) || (z < zrelax2)) && (xtotsize < ((double) Int_max) / sizeof (double)) ; } } #ifdef CHOLMOD_HAS_CUDA if ( for_whom == CHOLMOD_ANALYZE_FOR_CHOLESKY && L->useGPU ) { // Ensure that the aggregated supernode fits in the device // supernode buffers double xns = (double) ns; if ( ((xns * xns) + xns * (lnz1 - nscol1))*sizeof(double)*2 >= Common->devBuffSize ) { merge = FALSE; } } #endif if (merge) { PRINT1 (("Merge node s ("ID") and s+1 ("ID")\n", s, s+1)) ; Zeros [s] = totzeros ; Merged [s+1] = s ; Snz [s] = nscol0 + Snz [s+1] ; Nscol [s] += Nscol [s+1] ; } } // contents of Wj no longer needed for Zeros ] // contents of Wi no longer needed for Nscol ] // contents of Sparent no longer needed (recomputed below) //-------------------------------------------------------------------------- // construct the relaxed supernode list //-------------------------------------------------------------------------- nsuper = 0 ; for (s = 0 ; s < nfsuper ; s++) { if (Merged [s] == EMPTY) { PRINT1 (("live supernode: "ID" snz "ID"\n", s, Snz [s])) ; Super [nsuper] = Super [s] ; Snz [nsuper] = Snz [s] ; nsuper++ ; } } Super [nsuper] = n ; PRINT1 (("Fundamental supernodes: "ID" relaxed "ID"\n", nfsuper, nsuper)) ; // Merged no longer needed ] //-------------------------------------------------------------------------- // find the mapping of relaxed nodes to supernodes //-------------------------------------------------------------------------- // use Wj as workspace for SuperMap { // SuperMap [k] = s if column k is contained in supernode s for (s = 0 ; s < nsuper ; s++) { for (k = Super [s] ; k < Super [s+1] ; k++) { SuperMap [k] = s ; } } //-------------------------------------------------------------------------- // construct the relaxed supernodal etree //-------------------------------------------------------------------------- for (s = 0 ; s < nsuper ; s++) { j = Super [s+1] - 1 ; // last node in supernode s parent = Parent [j] ; // parent of last node Sparent [s] = (parent == EMPTY) ? EMPTY : SuperMap [parent] ; PRINT1 (("new Sparent ["ID"] = "ID"\n", s, Sparent [s])) ; } //-------------------------------------------------------------------------- // determine the size of L->s and L->x //-------------------------------------------------------------------------- size_t ssize = 0 ; size_t xsize = 0 ; find_xsize = for_whom == CHOLMOD_ANALYZE_FOR_CHOLESKY || for_whom == CHOLMOD_ANALYZE_FOR_SPQRGPU ; for (s = 0 ; s < nsuper ; s++) { // do the computations in 64-bits to guard against integer overflow uint64_t nscol = (uint64_t) (Super [s+1] - Super [s]) ; uint64_t nsrow = (uint64_t) Snz [s] ; // ssize += nsrow ssize = CHOLMOD(add_size_t) (ssize, (size_t) nsrow, &ok) ; if (find_xsize) { // c = nscol * nsrow uint64_t c = 0 ; ok = ok && cholmod_mult_uint64_t (&c, nscol, nsrow) ; // xsize += c xsize = CHOLMOD(add_size_t) (xsize, c, &ok) ; } } ok = ok && (ssize < Int_max) && (xsize < Int_max) ; L->ssize = (ok) ? MAX (1, ssize) : SIZE_MAX ; L->xsize = (ok) ? MAX (1, xsize) : SIZE_MAX ; Common->status = (ok) ? CHOLMOD_OK : CHOLMOD_TOO_LARGE ; L->nsuper = nsuper ; //-------------------------------------------------------------------------- // allocate L (all except real part L->x) //-------------------------------------------------------------------------- if (ok) { CHOLMOD(change_factor) (CHOLMOD_PATTERN, TRUE, TRUE, TRUE, TRUE, L, Common) ; } if (Common->status < CHOLMOD_OK) { // out of memory; L is still a valid simplicial symbolic factor FREE_WORKSPACE ; return (FALSE) ; } DEBUG (CHOLMOD(dump_factor) (L, "L to symbolic super", Common)) ; ASSERT (L->is_ll && L->xtype == CHOLMOD_PATTERN && L->is_super) ; Lpi = L->pi ; Lpx = L->px ; Ls = L->s ; Ls [0] = 0 ; // flag for cholmod_check_factor; supernodes are defined Lsuper = L->super ; // copy the list of relaxed supernodes into the final list in L for (s = 0 ; s <= nsuper ; s++) { Lsuper [s] = Super [s] ; } // Head no longer needed as workspace for fundamental Super list ) Super = Lsuper ; // Super is now the list of relaxed supernodes //-------------------------------------------------------------------------- // construct column pointers of relaxed supernodal pattern (L->pi) //-------------------------------------------------------------------------- p = 0 ; for (s = 0 ; s < nsuper ; s++) { Lpi [s] = p ; p += Snz [s] ; PRINT1 (("Snz ["ID"] = "ID", Super ["ID"] = "ID"\n", s, Snz [s], s, Super[s])) ; } Lpi [nsuper] = p ; ASSERT ((Int) (L->ssize) == MAX (1,p)) ; //-------------------------------------------------------------------------- // construct pointers for supernodal values (L->px) //-------------------------------------------------------------------------- // L->px is not needed for non-GPU accelerated QR factorization. // Use a magic number to tell cholmod_check_factor to ignore Lpx. Lpx [0] = 123456 ; if (for_whom == CHOLMOD_ANALYZE_FOR_CHOLESKY || for_whom == CHOLMOD_ANALYZE_FOR_SPQRGPU) { Lpx [0] = 0 ; p = 0 ; for (s = 0 ; s < nsuper ; s++) { Int nscol = Super [s+1] - Super [s] ; // number of columns in s Int nsrow = Snz [s] ; // # of rows, incl triangular part Lpx [s] = p ; // pointer to numerical part of s p += nscol * nsrow ; } Lpx [s] = p ; ASSERT ((Int) (L->xsize) == MAX (1,p)) ; } // Snz no longer needed ] //-------------------------------------------------------------------------- // symbolic analysis to construct the relaxed supernodal pattern (L->s) //-------------------------------------------------------------------------- Lpi2 = Wi ; // copy Lpi into Lpi2, using Wi as workspace for Lpi2 [ for (s = 0 ; s < nsuper ; s++) { Lpi2 [s] = Lpi [s] ; } Asorted = A->sorted ; for (s = 0 ; s < nsuper ; s++) { // sth supernode is in columns k1 to k2-1. // compute nonzero pattern of L (k1:k2-1,:). // place rows k1 to k2-1 in leading column of supernode s k1 = Super [s] ; k2 = Super [s+1] ; PRINT1 (("=========>>> Supernode "ID" k1 "ID" k2-1 "ID"\n", s, k1, k2-1)) ; for (k = k1 ; k < k2 ; k++) { Ls [Lpi2 [s]++] = k ; } // compute nonzero pattern each row k1 to k2-1 for (k = k1 ; k < k2 ; k++) { // compute row k of L. In the symmetric case, the pattern of L(k,:) // is the set of nodes reachable in the supernodal etree from any // row i in the nonzero pattern of A(0:k,k). In the unsymmetric // case, the pattern of the kth column of A*A' is the set union // of all columns A(0:k,j) for each nonzero F(j,k). // clear the Flag array and mark the current supernode CLEAR_FLAG (Common) ; mark = Common->mark ; Flag [s] = mark ; ASSERT (s == SuperMap [k]) ; // traverse the row subtree for each nonzero in A or AA' if (stype != 0) { subtree (k, k, Ap, Ai, Anz, SuperMap, Sparent, mark, Asorted, k1, Flag, Ls, Lpi2) ; } else { // for each j nonzero in F (:,k) do p = Fp [k] ; pend = (packed) ? (Fp [k+1]) : (p + Fnz [k]) ; for ( ; p < pend ; p++) { subtree (Fj [p], k, Ap, Ai, Anz, SuperMap, Sparent, mark, Asorted, k1, Flag, Ls, Lpi2) ; } } } } #ifndef NDEBUG for (s = 0 ; s < nsuper ; s++) { PRINT1 (("Lpi2[s] "ID" Lpi[s+1] "ID"\n", Lpi2 [s], Lpi [s+1])) ; ASSERT (Lpi2 [s] == Lpi [s+1]) ; CHOLMOD(dump_super) (s, Super, Lpi, Ls, NULL, NULL, 0, 0, Common) ; } #endif // contents of Wi no longer needed for Lpi2 ] // Sparent no longer needed ] //-------------------------------------------------------------------------- // determine the largest update matrix (L->maxcsize) //-------------------------------------------------------------------------- // maxcsize could be determined before L->s is allocated and defined, which // would mean that all memory requirements for both the symbolic and numeric // factorizations could be computed using O(nnz(A)+O(n)) space. However, it // would require a lot of extra work. The analysis phase, above, would need // to be duplicated, but with Ls not kept; instead, the algorithm would keep // track of the current s and slast for each supernode d, and update them // when a new row index appears in supernode d. An alternative would be to // do this computation only if the allocation of L->s failed, in which case // the following code would be skipped. // // The csize for a supernode is the size of its largest contribution to // a subsequent ancestor supernode. For example, suppose the rows of #'s // in the figure below correspond to the columns of a subsequent supernode, // and the dots are the entries in that ancestore. // // c // c c // c c c // x x x // x x x // # # # . // # # # . . // * * * . . // * * * . . // * * * . . // . . // // Then for this update, the csize is 3-by-2, or 6, because there are 3 // rows of *'s which is the number of rows in the update, and there are // 2 rows of #'s, which is the number columns in the update. The csize // of a supernode is the largest such contribution for any ancestor // supernode. maxcsize, for the whole matrix, has a rough upper bound of // the maximum size of any supernode. This bound is loose, because the // the contribution must be less than the size of the ancestor supernodal // that it's updating. maxcsize of a completely dense matrix, with one // supernode, is zero. // // maxesize is the column dimension for the workspace E needed for the // solve. E is of size nrhs-by-maxesize, where the nrhs is the number of // columns in the right-hand-side. The maxesize is the largest esize of // any supernode. The esize of a supernode is the number of row indices // it contains, excluding the column indices of the supernode itself. // For the following example, esize is 4: // // c // c c // c c c // x x x // x x x // x x x // x x x // // maxesize can be no bigger than n. maxcsize = 1 ; maxesize = 1 ; if (for_whom == CHOLMOD_ANALYZE_FOR_CHOLESKY || for_whom == CHOLMOD_ANALYZE_FOR_SPQRGPU) { // this is not needed for non-GPU accelerated QR factorization for (d = 0 ; d < nsuper ; d++) { Int nscol = Super [d+1] - Super [d] ; p = Lpi [d] + nscol ; plast = p ; pend = Lpi [d+1] ; esize = pend - p ; maxesize = MAX (maxesize, esize) ; slast = (p == pend) ? (EMPTY) : (SuperMap [Ls [p]]) ; for ( ; p <= pend ; p++) { s = (p == pend) ? (EMPTY) : (SuperMap [Ls [p]]) ; if (s != slast) { // row i is the start of a new supernode ndrow1 = p - plast ; ndrow2 = pend - plast ; csize = ndrow2 * ndrow1 ; PRINT1 (("Supernode "ID" ancestor "ID" C: "ID"-by-"ID " csize "ID"\n", d, slast, ndrow1, ndrow2, csize)) ; maxcsize = MAX (maxcsize, csize) ; plast = p ; slast = s ; } } } PRINT1 (("max csize "ID"\n", maxcsize)) ; } // Wj no longer needed for SuperMap } L->maxcsize = maxcsize ; L->maxesize = maxesize ; L->is_super = TRUE ; ASSERT (L->xtype == CHOLMOD_PATTERN && L->is_ll) ; //-------------------------------------------------------------------------- // supernodal symbolic factorization is complete //-------------------------------------------------------------------------- FREE_WORKSPACE ; return (TRUE) ; } //------------------------------------------------------------------------------ // cholmod_super_symbolic //------------------------------------------------------------------------------ // Analyzes A, AA', or A(:,f)*A(:,f)' in preparation for a supernodal numeric // factorization. The user need not call this directly; cholmod_analyze is // a "simple" wrapper for this routine. // // This function does all the analysis for a supernodal Cholesky factorization. // // workspace: Flag (nrow), Head (nrow), Iwork (2*nrow), // and temporary space of size 3*nfsuper*sizeof(Int), where nfsuper <= n // is the number of fundamental supernodes. int CHOLMOD(super_symbolic) ( // input: cholmod_sparse *A, // matrix to analyze cholmod_sparse *F, // F = A' or A(:,f)' Int *Parent, // elimination tree // input/output: cholmod_factor *L, // simplicial symbolic on input, // supernodal symbolic on output cholmod_common *Common ) { return (CHOLMOD(super_symbolic2) (CHOLMOD_ANALYZE_FOR_CHOLESKY, A, F, Parent, L, Common)) ; } #endif #endif Matrix/src/SuiteSparse/CHOLMOD/Supernodal/t_cholmod_super_solve_worker.c0000644000175100001440000005471414552026002026135 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Supernodal/t_cholmod_super_solve: template for cholmod_super_solve //------------------------------------------------------------------------------ // CHOLMOD/Supernodal Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // Template routine for cholmod_super_solve. Supports real or complex L, // not pattern, nor complex. All dtypes are supported. #include "cholmod_template.h" //------------------------------------------------------------------------------ // t_cholmod_super_lsolve_worker: solve x = L\b //------------------------------------------------------------------------------ static void TEMPLATE (cholmod_super_lsolve_worker) ( // input: cholmod_factor *L, // factor to use for the forward solve // input/output: cholmod_dense *X, // b on input, solution to Lx=b on output // workspace: cholmod_dense *E, // workspace of size nrhs*(L->maxesize) cholmod_common *Common ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Real *Lx, *Xx, *Ex ; Real minus_one [2], one [2] ; Int *Lpi, *Lpx, *Ls, *Super ; Int nsuper, k1, k2, psi, psend, psx, nsrow, nscol, ii, s, nsrow2, ps2, j, i, d, nrhs ; nrhs = X->ncol ; Ex = E->x ; Xx = X->x ; d = X->d ; nsuper = L->nsuper ; Lpi = L->pi ; Lpx = L->px ; Ls = L->s ; Super = L->super ; Lx = L->x ; minus_one [0] = -1.0 ; minus_one [1] = 0 ; one [0] = 1.0 ; one [1] = 0 ; //-------------------------------------------------------------------------- // solve Lx=b //-------------------------------------------------------------------------- if (nrhs == 1) { for (s = 0 ; s < nsuper ; s++) { k1 = Super [s] ; k2 = Super [s+1] ; psi = Lpi [s] ; psend = Lpi [s+1] ; psx = Lpx [s] ; nsrow = psend - psi ; nscol = k2 - k1 ; nsrow2 = nsrow - nscol ; ps2 = psi + nscol ; ASSERT ((size_t) nsrow2 <= L->maxesize) ; // L1 is nscol-by-nscol, lower triangular with non-unit diagonal. // L2 is nsrow2-by-nscol. L1 and L2 have leading dimension of // nsrow. x1 is nscol-by-nsrow, with leading dimension n. // E is nsrow2-by-1, with leading dimension nsrow2. // gather X into E for (ii = 0 ; ii < nsrow2 ; ii++) { // Ex [ii] = Xx [Ls [ps2 + ii]] ASSIGN (Ex,-,ii, Xx,-,Ls [ps2 + ii]) ; } #if (defined (DOUBLE) && defined (REAL)) // solve L1*x1 (that is, x1 = L1\x1) SUITESPARSE_BLAS_dtrsv ("L", "N", "N", nscol, // N: L1 is nscol-by-nscol Lx + ENTRY_SIZE*psx, nsrow, // A, LDA: L1 Xx + ENTRY_SIZE*k1, 1, // X, INCX: x1 Common->blas_ok) ; // E = E - L2*x1 SUITESPARSE_BLAS_dgemv ("N", nsrow2, nscol, // M, N: L2 is nsrow2-by-nscol minus_one, // ALPHA: -1 Lx + ENTRY_SIZE*(psx + nscol), // A, LDA: L2 nsrow, Xx + ENTRY_SIZE*k1, 1, // X, INCX: x1 one, // BETA: 1 Ex, 1, // Y, INCY: E Common->blas_ok) ; #elif (defined (SINGLE) && defined (REAL)) // solve L1*x1 (that is, x1 = L1\x1) SUITESPARSE_BLAS_strsv ("L", "N", "N", nscol, // N: L1 is nscol-by-nscol Lx + ENTRY_SIZE*psx, nsrow, // A, LDA: L1 Xx + ENTRY_SIZE*k1, 1, // X, INCX: x1 Common->blas_ok) ; // E = E - L2*x1 SUITESPARSE_BLAS_sgemv ("N", nsrow2, nscol, // M, N: L2 is nsrow2-by-nscol minus_one, // ALPHA: -1 Lx + ENTRY_SIZE*(psx + nscol), // A, LDA: L2 nsrow, Xx + ENTRY_SIZE*k1, 1, // X, INCX: x1 one, // BETA: 1 Ex, 1, // Y, INCY: E Common->blas_ok) ; #elif (defined (DOUBLE) && !defined (REAL)) // solve L1*x1 (that is, x1 = L1\x1) SUITESPARSE_BLAS_ztrsv ("L", "N", "N", nscol, // N: L1 is nscol-by-nscol Lx + ENTRY_SIZE*psx, nsrow, // A, LDA: L1 Xx + ENTRY_SIZE*k1, 1, // X, INCX: x1 Common->blas_ok) ; // E = E - L2*x1 SUITESPARSE_BLAS_zgemv ("N", nsrow2, nscol, // M, N: L2 is nsrow2-by-nscol minus_one, // ALPHA: -1 Lx + ENTRY_SIZE*(psx + nscol), // A, LDA: L2 nsrow, Xx + ENTRY_SIZE*k1, 1, // X, INCX: x1 one, // BETA: 1 Ex, 1, // Y, INCY: E Common->blas_ok) ; #elif (defined (SINGLE) && !defined (REAL)) // solve L1*x1 (that is, x1 = L1\x1) SUITESPARSE_BLAS_ctrsv ("L", "N", "N", nscol, // N: L1 is nscol-by-nscol Lx + ENTRY_SIZE*psx, nsrow, // A, LDA: L1 Xx + ENTRY_SIZE*k1, 1, // X, INCX: x1 Common->blas_ok) ; // E = E - L2*x1 SUITESPARSE_BLAS_cgemv ("N", nsrow2, nscol, // M, N: L2 is nsrow2-by-nscol minus_one, // ALPHA: -1 Lx + ENTRY_SIZE*(psx + nscol), // A, LDA: L2 nsrow, Xx + ENTRY_SIZE*k1, 1, // X, INCX: x1 one, // BETA: 1 Ex, 1, // Y, INCY: E Common->blas_ok) ; #endif // scatter E back into X for (ii = 0 ; ii < nsrow2 ; ii++) { // Xx [Ls [ps2 + ii]] = Ex [ii] ASSIGN (Xx,-,Ls [ps2 + ii], Ex,-,ii) ; } } } else { for (s = 0 ; s < nsuper ; s++) { k1 = Super [s] ; k2 = Super [s+1] ; psi = Lpi [s] ; psend = Lpi [s+1] ; psx = Lpx [s] ; nsrow = psend - psi ; nscol = k2 - k1 ; nsrow2 = nsrow - nscol ; ps2 = psi + nscol ; ASSERT ((size_t) nsrow2 <= L->maxesize) ; // E is nsrow2-by-nrhs, with leading dimension nsrow2. // gather X into E for (ii = 0 ; ii < nsrow2 ; ii++) { i = Ls [ps2 + ii] ; for (j = 0 ; j < nrhs ; j++) { // Ex [ii + j*nsrow2] = Xx [i + j*d] ASSIGN (Ex,-,ii+j*nsrow2, Xx,-,i+j*d) ; } } #if (defined (DOUBLE) && defined (REAL)) // solve L1*x1 SUITESPARSE_BLAS_dtrsm ("L", "L", "N", "N", nscol, nrhs, // M, N: x1 is nscol-by-nrhs one, // ALPHA: 1 Lx + ENTRY_SIZE*psx, nsrow, // A, LDA: L1 Xx + ENTRY_SIZE*k1, d, // B, LDB: x1 Common->blas_ok) ; // E = E - L2*x1 if (nsrow2 > 0) { SUITESPARSE_BLAS_dgemm ("N", "N", nsrow2, nrhs, nscol, // M, N, K minus_one, // ALPHA: -1 Lx + ENTRY_SIZE*(psx + nscol), // A, LDA: L2 nsrow, Xx + ENTRY_SIZE*k1, d, // B, LDB: X1 one, // BETA: 1 Ex, nsrow2, // C, LDC: E Common->blas_ok) ; } #elif (defined (SINGLE) && defined (REAL)) // solve L1*x1 SUITESPARSE_BLAS_strsm ("L", "L", "N", "N", nscol, nrhs, // M, N: x1 is nscol-by-nrhs one, // ALPHA: 1 Lx + ENTRY_SIZE*psx, nsrow, // A, LDA: L1 Xx + ENTRY_SIZE*k1, d, // B, LDB: x1 Common->blas_ok) ; // E = E - L2*x1 if (nsrow2 > 0) { SUITESPARSE_BLAS_sgemm ("N", "N", nsrow2, nrhs, nscol, // M, N, K minus_one, // ALPHA: -1 Lx + ENTRY_SIZE*(psx + nscol), // A, LDA: L2 nsrow, Xx + ENTRY_SIZE*k1, d, // B, LDB: X1 one, // BETA: 1 Ex, nsrow2, // C, LDC: E Common->blas_ok) ; } #elif (defined (DOUBLE) && !defined (REAL)) // solve L1*x1 SUITESPARSE_BLAS_ztrsm ("L", "L", "N", "N", nscol, nrhs, // M, N: x1 is nscol-by-nrhs one, // ALPHA: 1 Lx + ENTRY_SIZE*psx, nsrow, // A, LDA: L1 Xx + ENTRY_SIZE*k1, d, // B, LDB: x1 Common->blas_ok) ; // E = E - L2*x1 if (nsrow2 > 0) { SUITESPARSE_BLAS_zgemm ("N", "N", nsrow2, nrhs, nscol, // M, N, K minus_one, // ALPHA: -1 Lx + ENTRY_SIZE*(psx + nscol), // A, LDA: L2 nsrow, Xx + ENTRY_SIZE*k1, d, // B, LDB: X1 one, // BETA: 1 Ex, nsrow2, // C, LDC: E Common->blas_ok) ; } #elif (defined (SINGLE) && !defined (REAL)) // solve L1*x1 SUITESPARSE_BLAS_ctrsm ("L", "L", "N", "N", nscol, nrhs, // M, N: x1 is nscol-by-nrhs one, // ALPHA: 1 Lx + ENTRY_SIZE*psx, nsrow, // A, LDA: L1 Xx + ENTRY_SIZE*k1, d, // B, LDB: x1 Common->blas_ok) ; // E = E - L2*x1 if (nsrow2 > 0) { SUITESPARSE_BLAS_cgemm ("N", "N", nsrow2, nrhs, nscol, // M, N, K minus_one, // ALPHA: -1 Lx + ENTRY_SIZE*(psx + nscol), // A, LDA: L2 nsrow, Xx + ENTRY_SIZE*k1, d, // B, LDB: X1 one, // BETA: 1 Ex, nsrow2, // C, LDC: E Common->blas_ok) ; } #endif // scatter E back into X for (ii = 0 ; ii < nsrow2 ; ii++) { i = Ls [ps2 + ii] ; for (j = 0 ; j < nrhs ; j++) { // Xx [i + j*d] = Ex [ii + j*nsrow2] ASSIGN (Xx,-,i+j*d, Ex,-,ii+j*nsrow2) ; } } } } } //------------------------------------------------------------------------------ // t_cholmod_super_ltsolve_worker: solve x=L'\b //------------------------------------------------------------------------------ static void TEMPLATE (cholmod_super_ltsolve_worker) ( // input: cholmod_factor *L, // factor to use for the forward solve // input/output: cholmod_dense *X, // b on input, solution to Lx=b on output // workspace: cholmod_dense *E, // workspace of size nrhs*(L->maxesize) cholmod_common *Common ) { //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- Real *Lx, *Xx, *Ex ; Real minus_one [2], one [2] ; Int *Lpi, *Lpx, *Ls, *Super ; Int nsuper, k1, k2, psi, psend, psx, nsrow, nscol, ii, s, nsrow2, ps2, j, i, d, nrhs ; nrhs = X->ncol ; Ex = E->x ; Xx = X->x ; d = X->d ; nsuper = L->nsuper ; Lpi = L->pi ; Lpx = L->px ; Ls = L->s ; Super = L->super ; Lx = L->x ; minus_one [0] = -1.0 ; minus_one [1] = 0 ; one [0] = 1.0 ; one [1] = 0 ; #ifdef DOUBLE ASSERT (L->dtype == CHOLMOD_DOUBLE) ; #else ASSERT (L->dtype == CHOLMOD_SINGLE) ; #endif ASSERT (L->dtype == X->dtype) ; //-------------------------------------------------------------------------- // solve L'x=b //-------------------------------------------------------------------------- if (nrhs == 1) { for (s = nsuper-1 ; s >= 0 ; s--) { k1 = Super [s] ; k2 = Super [s+1] ; psi = Lpi [s] ; psend = Lpi [s+1] ; psx = Lpx [s] ; nsrow = psend - psi ; nscol = k2 - k1 ; nsrow2 = nsrow - nscol ; ps2 = psi + nscol ; ASSERT ((size_t) nsrow2 <= L->maxesize) ; // L1 is nscol-by-nscol, lower triangular with non-unit diagonal. // L2 is nsrow2-by-nscol. L1 and L2 have leading dimension of // nsrow. x1 is nscol-by-nsrow, with leading dimension n. // E is nsrow2-by-1, with leading dimension nsrow2. // gather X into E for (ii = 0 ; ii < nsrow2 ; ii++) { // Ex [ii] = Xx [Ls [ps2 + ii]] ASSIGN (Ex,-,ii, Xx,-,Ls [ps2 + ii]) ; } #if (defined (DOUBLE) && defined (REAL)) // x1 = x1 - L2'*E SUITESPARSE_BLAS_dgemv ("C", nsrow2, nscol, // M, N: L2 is nsrow2-by-nscol minus_one, // ALPHA: -1 Lx + ENTRY_SIZE*(psx + nscol), // A, LDA: L2 nsrow, Ex, 1, // X, INCX: Ex one, // BETA: 1 Xx + ENTRY_SIZE*k1, 1, // Y, INCY: x1 Common->blas_ok) ; // solve L1'*x1 SUITESPARSE_BLAS_dtrsv ("L", "C", "N", nscol, // N: L1 is nscol-by-nscol Lx + ENTRY_SIZE*psx, nsrow, // A, LDA: L1 Xx + ENTRY_SIZE*k1, 1, // X, INCX: x1 Common->blas_ok) ; #elif (defined (SINGLE) && defined (REAL)) // x1 = x1 - L2'*E SUITESPARSE_BLAS_sgemv ("C", nsrow2, nscol, // M, N: L2 is nsrow2-by-nscol minus_one, // ALPHA: -1 Lx + ENTRY_SIZE*(psx + nscol), // A, LDA: L2 nsrow, Ex, 1, // X, INCX: Ex one, // BETA: 1 Xx + ENTRY_SIZE*k1, 1, // Y, INCY: x1 Common->blas_ok) ; // solve L1'*x1 SUITESPARSE_BLAS_strsv ("L", "C", "N", nscol, // N: L1 is nscol-by-nscol Lx + ENTRY_SIZE*psx, nsrow, // A, LDA: L1 Xx + ENTRY_SIZE*k1, 1, // X, INCX: x1 Common->blas_ok) ; #elif (defined (DOUBLE) && !defined (REAL)) // x1 = x1 - L2'*E SUITESPARSE_BLAS_zgemv ("C", nsrow2, nscol, // M, N: L2 is nsrow2-by-nscol minus_one, // ALPHA: -1 Lx + ENTRY_SIZE*(psx + nscol), // A, LDA: L2 nsrow, Ex, 1, // X, INCX: Ex one, // BETA: 1 Xx + ENTRY_SIZE*k1, 1, // Y, INCY: x1 Common->blas_ok) ; // solve L1'*x1 SUITESPARSE_BLAS_ztrsv ("L", "C", "N", nscol, // N: L1 is nscol-by-nscol Lx + ENTRY_SIZE*psx, nsrow, // A, LDA: L1 Xx + ENTRY_SIZE*k1, 1, // X, INCX: x1 Common->blas_ok) ; #elif (defined (SINGLE) && !defined (REAL)) // x1 = x1 - L2'*E SUITESPARSE_BLAS_cgemv ("C", nsrow2, nscol, // M, N: L2 is nsrow2-by-nscol minus_one, // ALPHA: -1 Lx + ENTRY_SIZE*(psx + nscol), // A, LDA: L2 nsrow, Ex, 1, // X, INCX: Ex one, // BETA: 1 Xx + ENTRY_SIZE*k1, 1, // Y, INCY: x1 Common->blas_ok) ; // solve L1'*x1 SUITESPARSE_BLAS_ctrsv ("L", "C", "N", nscol, // N: L1 is nscol-by-nscol Lx + ENTRY_SIZE*psx, nsrow, // A, LDA: L1 Xx + ENTRY_SIZE*k1, 1, // X, INCX: x1 Common->blas_ok) ; #endif } } else { for (s = nsuper-1 ; s >= 0 ; s--) { k1 = Super [s] ; k2 = Super [s+1] ; psi = Lpi [s] ; psend = Lpi [s+1] ; psx = Lpx [s] ; nsrow = psend - psi ; nscol = k2 - k1 ; nsrow2 = nsrow - nscol ; ps2 = psi + nscol ; ASSERT ((size_t) nsrow2 <= L->maxesize) ; // E is nsrow2-by-nrhs, with leading dimension nsrow2. // gather X into E for (ii = 0 ; ii < nsrow2 ; ii++) { i = Ls [ps2 + ii] ; for (j = 0 ; j < nrhs ; j++) { // Ex [ii + j*nsrow2] = Xx [i + j*d] ASSIGN (Ex,-,ii+j*nsrow2, Xx,-,i+j*d) ; } } #if (defined (DOUBLE) && defined (REAL)) // x1 = x1 - L2'*E if (nsrow2 > 0) { SUITESPARSE_BLAS_dgemm ("C", "N", nscol, nrhs, nsrow2, // M, N, K minus_one, // ALPHA: -1 Lx + ENTRY_SIZE*(psx + nscol), // A, LDA: L2 nsrow, Ex, nsrow2, // B, LDB: E one, // BETA: 1 Xx + ENTRY_SIZE*k1, d, // C, LDC: x1 Common->blas_ok) ; } // solve L1'*x1 SUITESPARSE_BLAS_dtrsm ("L", "L", "C", "N", nscol, nrhs, // M, N: x1 is nscol-by-nrhs one, // ALPHA: 1 Lx + ENTRY_SIZE*psx, nsrow, // A, LDA: L1 Xx + ENTRY_SIZE*k1, d, // B, LDB: x1 Common->blas_ok) ; #elif (defined (SINGLE) && defined (REAL)) // x1 = x1 - L2'*E if (nsrow2 > 0) { SUITESPARSE_BLAS_sgemm ("C", "N", nscol, nrhs, nsrow2, // M, N, K minus_one, // ALPHA: -1 Lx + ENTRY_SIZE*(psx + nscol), // A, LDA: L2 nsrow, Ex, nsrow2, // B, LDB: E one, // BETA: 1 Xx + ENTRY_SIZE*k1, d, // C, LDC: x1 Common->blas_ok) ; } // solve L1'*x1 SUITESPARSE_BLAS_strsm ("L", "L", "C", "N", nscol, nrhs, // M, N: x1 is nscol-by-nrhs one, // ALPHA: 1 Lx + ENTRY_SIZE*psx, nsrow, // A, LDA: L1 Xx + ENTRY_SIZE*k1, d, // B, LDB: x1 Common->blas_ok) ; #elif (defined (DOUBLE) && !defined (REAL)) // x1 = x1 - L2'*E if (nsrow2 > 0) { SUITESPARSE_BLAS_zgemm ("C", "N", nscol, nrhs, nsrow2, // M, N, K minus_one, // ALPHA: -1 Lx + ENTRY_SIZE*(psx + nscol), // A, LDA: L2 nsrow, Ex, nsrow2, // B, LDB: E one, // BETA: 1 Xx + ENTRY_SIZE*k1, d, // C, LDC: x1 Common->blas_ok) ; } // solve L1'*x1 SUITESPARSE_BLAS_ztrsm ("L", "L", "C", "N", nscol, nrhs, // M, N: x1 is nscol-by-nrhs one, // ALPHA: 1 Lx + ENTRY_SIZE*psx, nsrow, // A, LDA: L1 Xx + ENTRY_SIZE*k1, d, // B, LDB: x1 Common->blas_ok) ; #elif (defined (SINGLE) && !defined (REAL)) // x1 = x1 - L2'*E if (nsrow2 > 0) { SUITESPARSE_BLAS_cgemm ("C", "N", nscol, nrhs, nsrow2, // M, N, K minus_one, // ALPHA: -1 Lx + ENTRY_SIZE*(psx + nscol), // A, LDA: L2 nsrow, Ex, nsrow2, // B, LDB: E one, // BETA: 1 Xx + ENTRY_SIZE*k1, d, // C, LDC: x1 Common->blas_ok) ; } // solve L1'*x1 SUITESPARSE_BLAS_ctrsm ("L", "L", "C", "N", nscol, nrhs, // M, N: x1 is nscol-by-nrhs one, // ALPHA: 1 Lx + ENTRY_SIZE*psx, nsrow, // A, LDA: L1 Xx + ENTRY_SIZE*k1, d, // B, LDB: x1 Common->blas_ok) ; #endif } } } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Supernodal/cholmod_l_super_symbolic.c0000644000175100001440000000102714552026002025212 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Supernodal/cholmod_l_super_symbolic.c: // int64_t version of cholmod_super_symbolic //------------------------------------------------------------------------------ // CHOLMOD/Supernodal Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_super_symbolic.c" Matrix/src/SuiteSparse/CHOLMOD/Supernodal/t_cholmod_super_numeric_worker.c0000644000175100001440000014676714552026002026461 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Supernodal/t_cholmod_super_numeric: cholmod_super_numeric template //------------------------------------------------------------------------------ // CHOLMOD/Supernodal Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #include "cholmod_template.h" // Template routine for cholmod_super_numeric. All xtypes supported, except // that a zomplex A and F result in a complex L (there is no supernodal zomplex // L). The GPU is only used for the double cases, not single. All dtypes are // supported (A, L and F must have the same dtype). //------------------------------------------------------------------------------ // complex arithmetic //------------------------------------------------------------------------------ #undef L_ENTRY #undef L_CLEAR #undef L_ASSIGN #undef L_MULTADD #undef L_ASSEMBLE #undef L_ASSEMBLESUB #ifdef REAL //-------------------------------------------------------------------------- // A, F, and L are all real //-------------------------------------------------------------------------- #define L_ENTRY 1 #define L_CLEAR(Lx,p) Lx [p] = 0 #define L_ASSIGN(Lx,q, Ax,Az,p) Lx [q] = Ax [p] #define L_MULTADD(Lx,q, Ax,Az,p, f) Lx [q] += Ax [p] * f [0] #define L_ASSEMBLE(Lx,q,b) Lx [q] += b [0] #define L_ASSEMBLESUB(Lx,q,C,p) Lx [q] -= C [p] #else //-------------------------------------------------------------------------- // A and F are complex or zomplex, L and C are complex //-------------------------------------------------------------------------- #define L_ENTRY 2 #define L_CLEAR(Lx,p) Lx [2*(p)] = 0 ; Lx [2*(p)+1] = 0 #define L_ASSEMBLE(Lx,q,b) Lx [2*(q)] += b [0] ; #define L_ASSEMBLESUB(Lx,q,C,p) \ Lx [2*(q) ] -= C [2*(p) ] ; \ Lx [2*(q)+1] -= C [2*(p)+1] ; #ifdef COMPLEX //---------------------------------------------------------------------- // A, F, L, and C are all complex //---------------------------------------------------------------------- #define L_ASSIGN(Lx,q, Ax,Az,p) \ Lx [2*(q) ] = Ax [2*(p) ] ; \ Lx [2*(q)+1] = Ax [2*(p)+1] #define L_MULTADD(Lx,q, Ax,Az,p, f) \ Lx [2*(q) ] += Ax [2*(p) ] * f [0] - Ax [2*(p)+1] * f [1] ; \ Lx [2*(q)+1] += Ax [2*(p)+1] * f [0] + Ax [2*(p) ] * f [1] #else //---------------------------------------------------------------------- // A and F are zomplex, L and C is complex //---------------------------------------------------------------------- #define L_ASSIGN(Lx,q, Ax,Az,p) \ Lx [2*(q) ] = Ax [p] ; \ Lx [2*(q)+1] = Az [p] ; #define L_MULTADD(Lx,q, Ax,Az,p, f) \ Lx [2*(q) ] += Ax [p] * f [0] - Az [p] * f [1] ; \ Lx [2*(q)+1] += Az [p] * f [0] + Ax [p] * f [1] #endif #endif //------------------------------------------------------------------------------ // blas_dump //------------------------------------------------------------------------------ #undef BLAS_DUMP_TO_FILE #undef WHICH #ifdef BLAS_DUMP #if (defined (DOUBLE) && defined (REAL)) #define WHICH 0 #elif (defined (SINGLE) && defined (REAL)) #define WHICH 1 #elif (defined (DOUBLE) && !defined (REAL)) #define WHICH 2 #elif (defined (SINGLE) && !defined (REAL)) #define WHICH 3 #endif #define BLAS_DUMP_TO_FILE(kernel,m,n,k,lda,ldb,ldc) \ { \ if (Common->blas_dump != NULL) \ { \ fprintf (Common->blas_dump, \ "%2d %d %d %6d %6d %6d %6d %6d %6d %12.4e\n", \ kernel + WHICH, /* dgemm, sgemm, etc. */ \ (int) sizeof (SUITESPARSE_BLAS_INT), /* BLAS integer */ \ (int) sizeof (Int), /* CHOLMOD index */ \ (int) m, (int) n, (int) k, /* problem size */ \ (int) lda, (int) ldb, (int) ldc, /* leading dimensions */\ blas_time) ; /* time taken */ \ } \ } #else #define BLAS_DUMP_TO_FILE(kernel,m,n,k,lda,ldb,ldc) #endif //------------------------------------------------------------------------------ // t_cholmod_super_numeric //------------------------------------------------------------------------------ // This function returns FALSE only if integer overflow occurs in the BLAS. // It returns TRUE otherwise whether or not the matrix is positive definite. static int TEMPLATE (cholmod_super_numeric_worker) ( // input: cholmod_sparse *A, // matrix to factorize cholmod_sparse *F, // F = A' or A(:,f)' Real beta [2], // beta*I is added to diagonal of matrix to factorize // input/output: cholmod_factor *L, // factorization // workspace: cholmod_dense *Cwork, // size (L->maxcsize)-by-1 cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- Real one [2], zero [2] ; #ifdef BLAS_TIMER double tstart, blas_time ; #endif Real *Lx, *Ax, *Fx, *C ; #ifdef ZOMPLEX Real *Az, *Fz ; #endif Int *Super, *Head, *Ls, *Lpi, *Lpx, *Map, *SuperMap, *RelativeMap, *Next, *Lpos, *Fp, *Fi, *Fnz, *Ap, *Ai, *Anz, *Iwork, *Next_save, *Lpos_save; Int nsuper, n, s, k1, k2, nscol, psi, psx, psend, nsrow, d, kd1, kd2, info, ndcol, ndrow, pdi, pdx, pdend, pdi2, ndrow1, ndrow2, dancestor, sparent, dnext, nsrow2, ndrow3, stype, Apacked, Fpacked, repeat_supernode, nscol2, ss, nscol_new = 0; #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) Int *Previous ; Int tail ; #endif info = 0 ; ASSERT (L->dtype == A->dtype) ; //-------------------------------------------------------------------------- // declarations for the GPU //-------------------------------------------------------------------------- // these variables are not used if the GPU module is not installed #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) Int ndescendants, mapCreatedOnGpu, supernodeUsedGPU, idescendant, dlarge, dsmall, skips ; int iHostBuff, iDevBuff, useGPU, GPUavailable ; cholmod_gpu_pointers *gpu_p, gpu_pointer_struct ; gpu_p = &gpu_pointer_struct ; #endif //-------------------------------------------------------------------------- // guard against integer overflow in the BLAS //-------------------------------------------------------------------------- // If integer overflow occurs in the BLAS, Common->status is set to // CHOLMOD_TOO_LARGE, and the contents of Lx are undefined. Common->blas_ok = TRUE ; //-------------------------------------------------------------------------- // get inputs //-------------------------------------------------------------------------- nsuper = L->nsuper ; n = L->n ; C = Cwork->x ; // workspace of size L->maxcsize one [0] = 1.0 ; // ALPHA for *syrk, *herk, *gemm, and *trsm one [1] = 0. ; zero [0] = 0. ; // BETA for *syrk, *herk, and *gemm zero [1] = 0. ; // Iwork must be of size 2n + 5*nsuper, allocated in the caller, // cholmod_super_numeric. The memory cannot be allocated here because the // cholmod_super_numeric initializes SuperMap, and cholmod_allocate_work // does not preserve existing workspace if the space needs to be increase // in size. // allocate integer workspace Iwork = Common->Iwork ; SuperMap = Iwork ; // size n RelativeMap = Iwork + n ; // size n Next = Iwork + 2*((size_t) n) ; // size nsuper Lpos = Iwork + 2*((size_t) n) + nsuper ; // size nsuper Next_save = Iwork + 2*((size_t) n) + 2*((size_t) nsuper) ;// size nsuper Lpos_save = Iwork + 2*((size_t) n) + 3*((size_t) nsuper) ;// size nsuper #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) Previous = Iwork + 2*((size_t) n) + 4*((size_t) nsuper) ;// size nsuper #endif Map = Common->Flag ; // size n, use Flag as workspace for Map array Head = Common->Head ; // size n+1, only Head [0..nsuper-1] used Ls = L->s ; Lpi = L->pi ; Lpx = L->px ; Super = L->super ; Lx = L->x ; #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) // local copy of useGPU if ( (Common->useGPU == 1) && L->useGPU) { // Initialize the GPU. If not found, don't use it. useGPU = TEMPLATE2 (CHOLMOD (gpu_init)) (C, L, Common, nsuper, n, Lpi[nsuper]-Lpi[0], gpu_p) ; } else { useGPU = 0; } // fprintf (stderr, "local useGPU %d\n", useGPU) ; #endif #ifdef BLAS_TIMER // clear GPU / CPU statistics Common->CHOLMOD_CPU_GEMM_CALLS = 0 ; Common->CHOLMOD_CPU_SYRK_CALLS = 0 ; Common->CHOLMOD_CPU_TRSM_CALLS = 0 ; Common->CHOLMOD_CPU_POTRF_CALLS = 0 ; Common->CHOLMOD_GPU_GEMM_CALLS = 0 ; Common->CHOLMOD_GPU_SYRK_CALLS = 0 ; Common->CHOLMOD_GPU_TRSM_CALLS = 0 ; Common->CHOLMOD_GPU_POTRF_CALLS = 0 ; Common->CHOLMOD_CPU_GEMM_TIME = 0 ; Common->CHOLMOD_CPU_SYRK_TIME = 0 ; Common->CHOLMOD_CPU_TRSM_TIME = 0 ; Common->CHOLMOD_CPU_POTRF_TIME = 0 ; Common->CHOLMOD_GPU_GEMM_TIME = 0 ; Common->CHOLMOD_GPU_SYRK_TIME = 0 ; Common->CHOLMOD_GPU_TRSM_TIME = 0 ; Common->CHOLMOD_GPU_POTRF_TIME = 0 ; Common->CHOLMOD_ASSEMBLE_TIME = 0 ; Common->CHOLMOD_ASSEMBLE_TIME2 = 0 ; #endif stype = A->stype ; if (stype != 0) { // F not accessed Fp = NULL ; Fi = NULL ; Fx = NULL ; #ifdef ZOMPLEX Fz = NULL ; #endif Fnz = NULL ; Fpacked = TRUE ; } else { ASSERT (F != NULL) ; ASSERT (L->dtype == F->dtype) ; Fp = F->p ; Fi = F->i ; Fx = F->x ; #ifdef ZOMPLEX Fz = F->z ; #endif Fnz = F->nz ; Fpacked = F->packed ; } Ap = A->p ; Ai = A->i ; Ax = A->x ; #ifdef ZOMPLEX Az = A->z ; #endif Anz = A->nz ; Apacked = A->packed ; // clear the Map so that changes in the pattern of A can be detected #ifdef _OPENMP int nthreads = cholmod_nthreads ((double) n, Common) ; #endif Int ii ; #ifdef _OPENMP #pragma omp parallel for num_threads(nthreads) \ if ( n > 128 ) schedule (static) #endif for (ii = 0 ; ii < n ; ii++) { Map [ii] = EMPTY ; } // If the matrix is not positive definite, the supernode s containing the // first zero or negative diagonal entry of L is repeated (but factorized // only up to just before the problematic diagonal entry). The purpose is // to provide MATLAB with [R,p]=chol(A) ; columns 1 to p-1 of L=R' are // required, where L(p,p) is the problematic diagonal entry. The // repeat_supernode flag tells us whether this is the repeated supernode. // Once supernode s is repeated, the factorization is terminated. repeat_supernode = FALSE ; #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) if ( useGPU ) { // Case of GPU, zero all supernodes at one time for better performance int nthreads = cholmod_nthreads ((double) L->xsize, Common) ; TEMPLATE2 (CHOLMOD (gpu_clear_memory))(Lx, L->xsize, nthreads) ; } #endif //-------------------------------------------------------------------------- // supernodal numerical factorization //-------------------------------------------------------------------------- for (s = 0 ; s < nsuper ; s++) { //---------------------------------------------------------------------- // get the size of supernode s //---------------------------------------------------------------------- k1 = Super [s] ; // s contains columns k1 to k2-1 of L k2 = Super [s+1] ; nscol = k2 - k1 ; // # of columns in all of s psi = Lpi [s] ; // pointer to first row of s in Ls psx = Lpx [s] ; // pointer to first row of s in Lx psend = Lpi [s+1] ; // pointer just past last row of s in Ls nsrow = psend - psi ; // # of rows in all of s PRINT1 (("====================================================\n" "S "ID" k1 "ID" k2 "ID" nsrow "ID" nscol "ID" psi "ID" psend " ""ID" psx "ID"\n", s, k1, k2, nsrow, nscol, psi, psend, psx)) ; //---------------------------------------------------------------------- // zero the supernode s //---------------------------------------------------------------------- ASSERT ((size_t) (psx + nsrow*nscol) <= L->xsize) ; #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) if ( !useGPU ) #endif { // Case of no GPU, zero individual supernodes Int pend = psx + nsrow * nscol ; // s is nsrow-by-nscol #ifdef _OPENMP double work = (double) (pend - psx) * L_ENTRY ; int nthreads = cholmod_nthreads (work, Common) ; #endif Int p ; #ifdef _OPENMP #pragma omp parallel for num_threads(nthreads) \ schedule (static) if ( pend - psx > 1024 ) #endif for (p = psx ; p < pend ; p++) { L_CLEAR (Lx,p) ; } } //---------------------------------------------------------------------- // construct the scattered Map for supernode s //---------------------------------------------------------------------- // If row i is the kth row in s, then Map [i] = k. Similarly, if // column j is the kth column in s, then Map [j] = k. #ifdef _OPENMP int nthreads = cholmod_nthreads ((double) nsrow, Common) ; #endif Int k ; #ifdef _OPENMP #pragma omp parallel for num_threads(nthreads) \ if ( nsrow > 128 ) #endif for (k = 0 ; k < nsrow ; k++) { PRINT1 ((" "ID" map "ID"\n", Ls [psi+k], k)) ; Map [Ls [psi + k]] = k ; } //---------------------------------------------------------------------- // when using GPU, reorder supernodes by levels. // (all supernodes in a level are independent) //---------------------------------------------------------------------- #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) if ( useGPU ) { TEMPLATE2 (CHOLMOD (gpu_reorder_descendants)) ( Common, Super, &s, Lpi, Lpos, Head, Next, Previous, &ndescendants, &tail, &mapCreatedOnGpu, gpu_p ) ; } #endif //---------------------------------------------------------------------- // copy matrix into supernode s (lower triangular part only) //---------------------------------------------------------------------- #ifdef _OPENMP double work ; if (stype != 0) { Int pfirst = Ap [k1] ; Int plast = (Apacked) ? (Ap [k2]) : (pfirst + Anz [k2-1]) ; work = (double) (plast - pfirst) ; } else { Int pfirst = Fp [k1] ; Int plast = (Fpacked) ? (Fp [k2]) : (pfirst + Fnz [k2-1]) ; work = (double) (plast - pfirst) ; } nthreads = cholmod_nthreads (work, Common) ; #endif #ifdef _OPENMP #pragma omp parallel for num_threads(nthreads) \ if ( k2-k1 > 64 ) #endif for (k = k1 ; k < k2 ; k++) { if (stype != 0) { //-------------------------------------------------------------- // copy the kth column of A into the supernode //-------------------------------------------------------------- Int p = Ap [k] ; Int pend = (Apacked) ? (Ap [k+1]) : (p + Anz [k]) ; for ( ; p < pend ; p++) { // row i of L is located in row Map [i] of s Int i = Ai [p] ; if (i >= k) { // If the test is false, the numeric factorization of A // is undefined. The test does not detect all invalid // entries, only some of them (when debugging is // enabled, and Map is cleared after each step, then // all entries not in the pattern of L are detected). Int imap = Map [i] ; if (imap >= 0 && imap < nsrow) { // Lx [Map [i] + pk] = Ax [p] L_ASSIGN (Lx,(imap+(psx+(k-k1)*nsrow)), Ax,Az,p) ; } } } } else { //-------------------------------------------------------------- // copy the kth column of A*F into the supernode //-------------------------------------------------------------- Real fjk [2] ; Int pf = Fp [k] ; Int pfend = (Fpacked) ? (Fp [k+1]) : (pf + Fnz [k]) ; for ( ; pf < pfend ; pf++) { Int j = Fi [pf] ; // fjk = Fx [pf] L_ASSIGN (fjk,0, Fx,Fz,pf) ; Int p = Ap [j] ; Int pend = (Apacked) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { Int i = Ai [p] ; if (i >= k) { // See the discussion of imap above. Int imap = Map [i] ; if (imap >= 0 && imap < nsrow) { // Lx [Map [i] + pk] += Ax [p] * fjk L_MULTADD (Lx,(imap+(psx+(k-k1)*nsrow)), Ax,Az,p, fjk) ; } } } } } } // add beta to the diagonal of the supernode, if nonzero if (beta [0] != 0.0) { // note that only the real part of beta is used Int pk = psx ; for (Int k = k1 ; k < k2 ; k++) { // Lx [pk] += beta [0] L_ASSEMBLE (Lx,pk, beta) ; pk += nsrow + 1 ; // advance to the next diagonal entry } } PRINT1 (("Supernode with just A: repeat: "ID"\n", repeat_supernode)) ; DEBUG (CHOLMOD(dump_super) (s, Super, Lpi, Ls, Lpx, Lx, L->dtype, L_ENTRY, Common)) ; PRINT1 (("\n\n")) ; //---------------------------------------------------------------------- // save/restore the list of supernodes //---------------------------------------------------------------------- if (!repeat_supernode) { // Save the list of pending descendants in case s is not positive // definite. Also save Lpos for each descendant d, so that we can // find which part of d is used to update s. for (d = Head [s] ; d != EMPTY ; d = Next [d]) { Lpos_save [d] = Lpos [d] ; Next_save [d] = Next [d] ; } } else { // restore Lpos from prior failed supernode for (d = Head [s] ; d != EMPTY ; d = Next [d]) { Lpos [d] = Lpos_save [d] ; Next [d] = Next_save [d] ; } } //---------------------------------------------------------------------- // update supernode s with each pending descendant d //---------------------------------------------------------------------- #ifndef NDEBUG for (d = Head [s] ; d != EMPTY ; d = Next [d]) { PRINT1 (("\nWill update "ID" with Child: "ID"\n", s, d)) ; DEBUG (CHOLMOD(dump_super) (d, Super, Lpi, Ls, Lpx, Lx, L->dtype, L_ENTRY, Common)) ; } PRINT1 (("\nNow factorizing supernode "ID":\n", s)) ; #endif #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) if ( useGPU ) { // initialize the buffer counter Common->ibuffer = 0; supernodeUsedGPU = 0; idescendant = 0; d = Head[s] ; dnext = d; dlarge = Next[d] ; dsmall = tail; GPUavailable = 1; skips = 0; } else #endif { // GPU not installed or not used dnext = Head [s] ; } while #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) ( (!useGPU && (dnext != EMPTY)) || (useGPU && (idescendant < ndescendants))) #else ( dnext != EMPTY ) #endif { #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) if ( useGPU ) { // Conditionally select the next descendant supernode to // assemble. // + first, select the largest descendant // + subsequently, if gpu host buffers are available, select // the largest remaining descendant for assembly on the GPU // + otherwise select the smallest remaining descendant for // assembly on the CPU // // The objective is to keep the GPU busy assembling the largest // descendants, and simultaneously keep the CPU busy assembling // the smallest descendants. // // As this is called for every descendent supernode, moving // this code to t_cholmod_gpu incurs substantial overhead - // ~20 GF/s on audikw_1 - so it is being left here. iHostBuff = (Common->ibuffer) % CHOLMOD_HOST_SUPERNODE_BUFFERS; cudaError_t cuErr; if ( idescendant > 0 ) { if ( GPUavailable == -1 || skips > 0) { d = dsmall; dsmall = Previous[dsmall] ; skips--; } else { cuErr = cudaEventQuery ( Common->updateCBuffersFree[iHostBuff] ) ; if ( cuErr == cudaSuccess ) { // buffers are available, so assemble a large // descendant (anticipating that this will be // assembled on the GPU) d = dlarge; dlarge = Next[dlarge] ; GPUavailable = 1; skips = 0; } else { // buffers are not available, so the GPU is busy, // so assemble a small descendant (anticipating // that it will be assembled on the host) d = dsmall; dsmall = Previous[dsmall] ; GPUavailable = 0; // if the GPUs are busy, then do this many // supernodes on the CPU before querying GPUs // again. skips = CHOLMOD_GPU_SKIP; } } } idescendant++; } else #endif { // GPU not installed or not used d = dnext ; } //------------------------------------------------------------------ // get the size of supernode d //------------------------------------------------------------------ kd1 = Super [d] ; // d contains cols kd1 to kd2-1 of L kd2 = Super [d+1] ; ndcol = kd2 - kd1 ; // # of columns in all of d pdi = Lpi [d] ; // pointer to first row of d in Ls pdx = Lpx [d] ; // pointer to first row of d in Lx pdend = Lpi [d+1] ; // pointer just past last row of d in Ls ndrow = pdend - pdi ; // # rows in all of d PRINT1 (("Child: ")) ; DEBUG (CHOLMOD(dump_super) (d, Super, Lpi, Ls, Lpx, Lx, L->dtype, L_ENTRY, Common)) ; //------------------------------------------------------------------ // find the range of rows of d that affect rows k1 to k2-1 of s //------------------------------------------------------------------ Int p = Lpos [d] ; // offset of 1st row of d affecting s Int pdi1 = pdi + p ; // ptr to 1st row of d affecting s in Ls Int pdx1 = pdx + p ; // ptr to 1st row of d affecting s in Lx // there must be at least one row remaining in d to update s ASSERT (pdi1 < pdend) ; PRINT1 (("Lpos[d] "ID" pdi1 "ID" Ls[pdi1] "ID"\n", Lpos[d], pdi1, Ls [pdi1])) ; ASSERT (Ls [pdi1] >= k1 && Ls [pdi1] < k2) ; for (pdi2 = pdi1 ; pdi2 < pdend && Ls [pdi2] < k2 ; pdi2++) ; ndrow1 = pdi2 - pdi1 ; // # rows in first part of d ndrow2 = pdend - pdi1 ; // # rows in remaining d // rows Ls [pdi1 ... pdi2-1] are in the range k1 to k2-1. Since d // affects s, this set cannot be empty. ASSERT (pdi1 < pdi2 && pdi2 <= pdend) ; PRINT1 (("ndrow1 "ID" ndrow2 "ID"\n", ndrow1, ndrow2)) ; DEBUG (for (p = pdi1 ; p < pdi2 ; p++) PRINT1 (("Ls["ID"] "ID"\n", p, Ls[p]))) ; //------------------------------------------------------------------ // construct the update matrix C for this supernode d //------------------------------------------------------------------ // C = L (k1:n-1, kd1:kd2-1) * L (k1:k2-1, kd1:kd2-1)', except // that k1:n-1 refers to all of the rows in L, but many of the // rows are all zero. Supernode d holds columns kd1 to kd2-1 of L. // Nonzero rows in the range k1:k2-1 are in the list // Ls [pdi1 ... pdi2-1], of size ndrow1. Nonzero rows in the range // k2:n-1 are in the list Ls [pdi2 ... pdend], of size ndrow2. Let // L1 = L (Ls [pdi1 ... pdi2-1], kd1:kd2-1), and let // L2 = L (Ls [pdi2 ... pdend], kd1:kd2-1). C is ndrow2-by-ndrow1. // Let C1 be the first ndrow1 rows of C and let C2 be the last // ndrow2-ndrow1 rows of C. Only the lower triangular part of C1 // needs to be computed since C1 is symmetric. // maxcsize is the largest size of C for all pairs (d,s) ASSERT (ndrow2 * ndrow1 <= ((Int) L->maxcsize)) ; // compute leading ndrow1-by-ndrow1 lower triangular block of C, // C1 = L1*L1' ndrow3 = ndrow2 - ndrow1 ; // number of rows of C2 ASSERT (ndrow3 >= 0) ; #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) if ( useGPU ) { // set up GPU to assemble new supernode if ( GPUavailable == 1) { if ( ndrow2 * L_ENTRY >= CHOLMOD_ND_ROW_LIMIT && ndcol * L_ENTRY >= CHOLMOD_ND_COL_LIMIT ) { if ( ! mapCreatedOnGpu ) { TEMPLATE2 ( CHOLMOD (gpu_initialize_supernode)) ( Common, nscol, nsrow, psi, gpu_p ) ; mapCreatedOnGpu = 1; } } else { // we've reached the limit of GPU-eligible descendants // flag to stop stop performing cudaEventQueries GPUavailable = -1; } } } #endif #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) if ( !useGPU || GPUavailable!=1 || !TEMPLATE2 (CHOLMOD (gpu_updateC)) (ndrow1, ndrow2, ndrow, ndcol, nsrow, pdx1, pdi1, Lx, C, Common, gpu_p)) #endif { // GPU not installed, or not used #ifdef BLAS_TIMER Common->CHOLMOD_CPU_SYRK_CALLS++ ; tstart = SUITESPARSE_TIME ; #endif #if (defined (DOUBLE) && defined (REAL)) SUITESPARSE_BLAS_dsyrk ("L", "N", ndrow1, ndcol, // N, K: L1 is ndrow1-by-ndcol one, // ALPHA: 1 Lx + L_ENTRY*pdx1, ndrow, // A, LDA: L1, ndrow zero, // BETA: 0 C, ndrow2, // C, LDC: C1 Common->blas_ok) ; #elif (defined (SINGLE) && defined (REAL)) SUITESPARSE_BLAS_ssyrk ("L", "N", ndrow1, ndcol, // N, K: L1 is ndrow1-by-ndcol one, // ALPHA: 1 Lx + L_ENTRY*pdx1, ndrow, // A, LDA: L1, ndrow zero, // BETA: 0 C, ndrow2, // C, LDC: C1 Common->blas_ok) ; #elif (defined (DOUBLE) && !defined (REAL)) SUITESPARSE_BLAS_zherk ("L", "N", ndrow1, ndcol, // N, K: L1 is ndrow1-by-ndcol one, // ALPHA: 1 Lx + L_ENTRY*pdx1, ndrow, // A, LDA: L1, ndrow zero, // BETA: 0 C, ndrow2, // C, LDC: C1 Common->blas_ok) ; #elif (defined (SINGLE) && !defined (REAL)) SUITESPARSE_BLAS_cherk ("L", "N", ndrow1, ndcol, // N, K: L1 is ndrow1-by-ndcol one, // ALPHA: 1 Lx + L_ENTRY*pdx1, ndrow, // A, LDA: L1, ndrow zero, // BETA: 0 C, ndrow2, // C, LDC: C1 Common->blas_ok) ; #endif #ifdef BLAS_TIMER blas_time = SUITESPARSE_TIME - tstart ; Common->CHOLMOD_CPU_SYRK_TIME += blas_time ; BLAS_DUMP_TO_FILE (0, // dsyrk ("L", "N", ...) ndrow1, ndcol, 0, // N, K, 0 ndrow, ndrow2, 0) ; // LDA, LDC, 0 #endif // compute remaining (ndrow2-ndrow1)-by-ndrow1 block of C, // C2 = L2*L1' if (ndrow3 > 0) { #ifdef BLAS_TIMER Common->CHOLMOD_CPU_GEMM_CALLS++ ; tstart = SUITESPARSE_TIME ; #endif #if (defined (DOUBLE) && defined (REAL)) SUITESPARSE_BLAS_dgemm ("N", "C", ndrow3, ndrow1, ndcol, // M, N, K one, // ALPHA: 1 Lx + L_ENTRY*(pdx1 + ndrow1), // A, LDA: L2 ndrow, // ndrow Lx + L_ENTRY*pdx1, // B, LDB: L1 ndrow, // ndrow zero, // BETA: 0 C + L_ENTRY*ndrow1, // C, LDC: C2 ndrow2, Common->blas_ok) ; #elif (defined (SINGLE) && defined (REAL)) SUITESPARSE_BLAS_sgemm ("N", "C", ndrow3, ndrow1, ndcol, // M, N, K one, // ALPHA: 1 Lx + L_ENTRY*(pdx1 + ndrow1), // A, LDA: L2 ndrow, // ndrow Lx + L_ENTRY*pdx1, // B, LDB: L1 ndrow, // ndrow zero, // BETA: 0 C + L_ENTRY*ndrow1, // C, LDC: C2 ndrow2, Common->blas_ok) ; #elif (defined (DOUBLE) && !defined (REAL)) SUITESPARSE_BLAS_zgemm ("N", "C", ndrow3, ndrow1, ndcol, // M, N, K one, // ALPHA: 1 Lx + L_ENTRY*(pdx1 + ndrow1), // A, LDA: L2 ndrow, // ndrow Lx + L_ENTRY*pdx1, // B, LDB: L1, ndrow ndrow, zero, // BETA: 0 C + L_ENTRY*ndrow1, // C, LDC: C2 ndrow2, Common->blas_ok) ; #elif (defined (SINGLE) && !defined (REAL)) SUITESPARSE_BLAS_cgemm ("N", "C", ndrow3, ndrow1, ndcol, // M, N, K one, // ALPHA: 1 Lx + L_ENTRY*(pdx1 + ndrow1), // A, LDA: L2 ndrow, // ndrow Lx + L_ENTRY*pdx1, // B, LDB: L1, ndrow ndrow, zero, // BETA: 0 C + L_ENTRY*ndrow1, // C, LDC: C2 ndrow2, Common->blas_ok) ; #endif #ifdef BLAS_TIMER blas_time = SUITESPARSE_TIME - tstart ; Common->CHOLMOD_CPU_GEMM_TIME += blas_time ; BLAS_DUMP_TO_FILE (4, // dgemm ("N", "C", ...) ndrow3, ndrow1, ndcol, // M, N, K ndrow, ndrow, ndrow2) ; // LDA, LDB, LDC #endif } //-------------------------------------------------------------- // construct relative map to assemble d into s //-------------------------------------------------------------- DEBUG (CHOLMOD(dump_real) ("C", C, L->dtype, ndrow2, ndrow1, TRUE, L_ENTRY, Common)) ; #ifdef _OPENMP int nthreads = cholmod_nthreads ((double) ndrow2, Common) ; #endif Int i ; #ifdef _OPENMP #pragma omp parallel for num_threads(nthreads) \ if ( ndrow2 > 64 ) #endif for (i = 0 ; i < ndrow2 ; i++) { RelativeMap [i] = Map [Ls [pdi1 + i]] ; ASSERT (RelativeMap [i] >= 0 && RelativeMap [i] < nsrow) ; } //-------------------------------------------------------------- // assemble C into supernode s using the relative map //-------------------------------------------------------------- #ifdef _OPENMP double work = (double) ndcol * (double) ndrow2 * L_ENTRY ; nthreads = cholmod_nthreads (work, Common) ; #endif Int j ; #ifdef _OPENMP #pragma omp parallel for num_threads(nthreads) \ if (ndrow1 > 64 ) #endif for (j = 0 ; j < ndrow1 ; j++) // cols k1:k2-1 { ASSERT (RelativeMap [j] == Map [Ls [pdi1 + j]]) ; ASSERT (RelativeMap [j] >= 0 && RelativeMap [j] < nscol) ; Int px = psx + RelativeMap [j] * nsrow ; for (Int i = j ; i < ndrow2 ; i++) // rows k1:n-1 { ASSERT (RelativeMap [i] == Map [Ls [pdi1 + i]]) ; ASSERT (RelativeMap [i] >= j && RelativeMap[i] < nsrow); // Lx [px + RelativeMap [i]] -= C [i + pj] Int q = px + RelativeMap [i] ; L_ASSEMBLESUB (Lx,q, C, i+ndrow2*j) ; } } } #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) else { supernodeUsedGPU = 1; // GPU was used for this supernode Common->ibuffer++; // gpu_updateC is asynchronous, so use // the next host buffer for the next // supernode Common->ibuffer = Common->ibuffer% (CHOLMOD_HOST_SUPERNODE_BUFFERS*CHOLMOD_DEVICE_STREAMS) ; } #endif //------------------------------------------------------------------ // prepare this supernode d for its next ancestor //------------------------------------------------------------------ dnext = Next [d] ; if (!repeat_supernode) { // If node s is being repeated, Head [dancestor] has already // been cleared (set to EMPTY). It must remain EMPTY. The // dancestor will not be factorized since the factorization // terminates at node s. Lpos [d] = pdi2 - pdi ; if (Lpos [d] < ndrow) { dancestor = SuperMap [Ls [pdi2]] ; ASSERT (dancestor > s && dancestor < nsuper) ; // place d in the link list of its next ancestor Next [d] = Head [dancestor] ; Head [dancestor] = d ; } } } // end of descendant supernode loop #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) if ( useGPU ) { iHostBuff = (Common->ibuffer)%CHOLMOD_HOST_SUPERNODE_BUFFERS; iDevBuff = (Common->ibuffer)%CHOLMOD_DEVICE_STREAMS; // combine updates assembled on the GPU with updates // assembled on the CPU TEMPLATE2 ( CHOLMOD (gpu_final_assembly )) ( Common, Lx, psx, nscol, nsrow, supernodeUsedGPU, &iHostBuff, &iDevBuff, gpu_p ) ; } #endif PRINT1 (("\nSupernode with contributions A: repeat: "ID"\n", repeat_supernode)) ; DEBUG (CHOLMOD(dump_super) (s, Super, Lpi, Ls, Lpx, Lx, L->dtype, L_ENTRY, Common)) ; PRINT1 (("\n\n")) ; //---------------------------------------------------------------------- // factorize diagonal block of supernode s in LL' //---------------------------------------------------------------------- // The current supernode s is ready to factorize. It has been updated // by all descendant supernodes. Let S = the current supernode, which // holds rows k1:n-1 and columns k1:k2-1 of the updated matrix. It // splits into two parts: the square diagonal block S1, and the // rectangular part S2. Here, S1 is factorized into L1*L1' and // overwritten by L1. // // If supernode s is being repeated, only factorize it up to but not // including the column containing the problematic entry. nscol2 = (repeat_supernode) ? (nscol_new) : (nscol) ; #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) if ( !useGPU || !supernodeUsedGPU || !TEMPLATE2 (CHOLMOD (gpu_lower_potrf))(nscol2, nsrow, psx, Lx, &info, Common, gpu_p)) #endif { // Note that the GPU will not be used for the triangular solve #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) supernodeUsedGPU = 0; #endif #ifdef BLAS_TIMER Common->CHOLMOD_CPU_POTRF_CALLS++ ; tstart = SUITESPARSE_TIME ; #endif #if (defined (DOUBLE) && defined (REAL)) SUITESPARSE_LAPACK_dpotrf ("L", nscol2, // N: nscol2 Lx + L_ENTRY*psx, nsrow, // A, LDA: S1, nsrow info, // INFO Common->blas_ok) ; #elif (defined (SINGLE) && defined (REAL)) SUITESPARSE_LAPACK_spotrf ("L", nscol2, // N: nscol2 Lx + L_ENTRY*psx, nsrow, // A, LDA: S1, nsrow info, // INFO Common->blas_ok) ; #elif (defined (DOUBLE) && !defined (REAL)) SUITESPARSE_LAPACK_zpotrf ("L", nscol2, // N: nscol2 Lx + L_ENTRY*psx, nsrow, // A, LDA: S1, nsrow info, // INFO Common->blas_ok) ; #elif (defined (SINGLE) && !defined (REAL)) SUITESPARSE_LAPACK_cpotrf ("L", nscol2, // N: nscol2 Lx + L_ENTRY*psx, nsrow, // A, LDA: S1, nsrow info, // INFO Common->blas_ok) ; #endif #ifdef BLAS_TIMER blas_time = SUITESPARSE_TIME - tstart ; Common->CHOLMOD_CPU_POTRF_TIME += blas_time ; BLAS_DUMP_TO_FILE (8, // dpotrf ("L", ... ) nscol2, 0, 0, // N, 0, 0 nsrow, 0, 0) ; // LDA, 0, 0 #endif } //---------------------------------------------------------------------- // check if the matrix is not positive definite //---------------------------------------------------------------------- if (repeat_supernode) { // the leading part has been refactorized; it must have succeeded info = 0 ; // zero out the rest of this supernode Int p = psx + nsrow * nscol_new ; Int pend = psx + nsrow * nscol ; // s is nsrow-by-nscol for ( ; p < pend ; p++) { // Lx [p] = 0 L_CLEAR (Lx,p) ; } } // info is set to one in SUITESPARSE_LAPACK_*potrf if blas_ok is FALSE. // It is set to zero in dpotrf/zpotrf if the factorization was // successful. CHECK_FOR_BLAS_INTEGER_OVERFLOW ; if (info != 0) { // Matrix is not positive definite. dpotrf/zpotrf do NOT report an // error if the diagonal of L has NaN's, only if it has a zero. if (Common->status == CHOLMOD_OK) { ERROR (CHOLMOD_NOT_POSDEF, "matrix not positive definite") ; } // L->minor is the column of L that contains a zero or negative // diagonal term. L->minor = k1 + info - 1 ; // clear the link lists of all subsequent supernodes for (ss = s+1 ; ss < nsuper ; ss++) { Head [ss] = EMPTY ; } // zero this supernode, and all remaining supernodes Int pend = L->xsize ; for (Int p = psx ; p < pend ; p++) { // Lx [p] = 0 L_CLEAR (Lx,p) ; } // If L is indefinite, it still contains useful information. // Supernodes 0 to s-1 are valid, similar to MATLAB [R,p]=chol(A), // where the 1-based p is identical to the 0-based L->minor. Since // L->minor is in the current supernode s, it and any columns to the // left of it in supernode s are also all zero. This differs from // [R,p]=chol(A), which contains nonzero rows 1 to p-1. Fix this // by setting repeat_supernode to TRUE, and repeating supernode s. // // If Common->quick_return_if_not_posdef is true, then the entire // supernode s is not factorized; it is left as all zero. if (info == 1 || Common->quick_return_if_not_posdef) { // If the first column of supernode s contains a zero or // negative diagonal entry, then it is already properly set to // zero. Also, info will be 1 if integer overflow occured in // the BLAS. Head [s] = EMPTY ; #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) if ( useGPU ) { CHOLMOD (gpu_end) (Common) ; } #endif return (Common->status >= CHOLMOD_OK) ; } else { // Repeat supernode s, but only factorize it up to but not // including the column containing the problematic diagonal // entry. repeat_supernode = TRUE ; s-- ; nscol_new = info - 1 ; continue ; } } //---------------------------------------------------------------------- // compute the subdiagonal block and prepare supernode for its parent //---------------------------------------------------------------------- nsrow2 = nsrow - nscol2 ; if (nsrow2 > 0) { // The current supernode is columns k1 to k2-1 of L. Let L1 be the // diagonal block (factorized by dpotrf/zpotrf above; rows/cols // k1:k2-1), and L2 be rows k2:n-1 and columns k1:k2-1 of L. The // triangular system to solve is L2*L1' = S2, where S2 is // overwritten with L2. More precisely, L2 = S2 / L1' in MATLAB // notation. #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) if ( !useGPU || !supernodeUsedGPU || !TEMPLATE2 (CHOLMOD(gpu_triangular_solve)) (nsrow2, nscol2, nsrow, psx, Lx, Common, gpu_p)) #endif { #ifdef BLAS_TIMER Common->CHOLMOD_CPU_TRSM_CALLS++ ; tstart = SUITESPARSE_TIME ; #endif #if (defined (DOUBLE) && defined (REAL)) SUITESPARSE_BLAS_dtrsm ("R", "L", "C", "N", nsrow2, nscol2, // M, N one, // ALPHA: 1 Lx + L_ENTRY*psx, nsrow, // A, LDA: L1, nsrow Lx + L_ENTRY*(psx + nscol2), // B, LDB, L2, nsrow nsrow, Common->blas_ok) ; #elif (defined (SINGLE) && defined (REAL)) SUITESPARSE_BLAS_strsm ("R", "L", "C", "N", nsrow2, nscol2, // M, N one, // ALPHA: 1 Lx + L_ENTRY*psx, nsrow, // A, LDA: L1, nsrow Lx + L_ENTRY*(psx + nscol2), // B, LDB, L2, nsrow nsrow, Common->blas_ok) ; #elif (defined (DOUBLE) && !defined (REAL)) SUITESPARSE_BLAS_ztrsm ("R", "L", "C", "N", nsrow2, nscol2, // M, N one, // ALPHA: 1 Lx + L_ENTRY*psx, nsrow, // A, LDA: L1, nsrow Lx + L_ENTRY*(psx + nscol2), // B, LDB, L2, nsrow nsrow, Common->blas_ok) ; #elif (defined (SINGLE) && !defined (REAL)) SUITESPARSE_BLAS_ctrsm ("R", "L", "C", "N", nsrow2, nscol2, // M, N one, // ALPHA: 1 Lx + L_ENTRY*psx, nsrow, // A, LDA: L1, nsrow Lx + L_ENTRY*(psx + nscol2), // B, LDB, L2, nsrow nsrow, Common->blas_ok) ; #endif #ifdef BLAS_TIMER blas_time = SUITESPARSE_TIME - tstart ; Common->CHOLMOD_CPU_TRSM_TIME += blas_time ; BLAS_DUMP_TO_FILE (12, // dtrsm ("R", "L", "C", "N"...) nsrow2, nscol2, 0, // M, N nsrow, nsrow, 0) ; // LDA, LDB #endif } CHECK_FOR_BLAS_INTEGER_OVERFLOW ; if (!repeat_supernode) { // Lpos [s] is offset of first row of s affecting its parent Lpos [s] = nscol ; sparent = SuperMap [Ls [psi + nscol]] ; ASSERT (sparent != EMPTY) ; ASSERT (Ls [psi + nscol] >= Super [sparent]) ; ASSERT (Ls [psi + nscol] < Super [sparent+1]) ; ASSERT (SuperMap [Ls [psi + nscol]] == sparent) ; ASSERT (sparent > s && sparent < nsuper) ; // place s in link list of its parent Next [s] = Head [sparent] ; Head [sparent] = s ; } } else { #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) TEMPLATE2 ( CHOLMOD (gpu_copy_supernode) ) ( Common, Lx, psx, nscol, nscol2, nsrow, supernodeUsedGPU, iHostBuff, gpu_p) ; #endif } Head [s] = EMPTY ; // link list for supernode s no longer needed // clear the Map (debugging only, to detect changes in pattern of A) DEBUG (for (k = 0 ; k < nsrow ; k++) Map [Ls [psi + k]] = EMPTY) ; DEBUG (CHOLMOD(dump_super) (s, Super, Lpi, Ls, Lpx, Lx, L->dtype, L_ENTRY, Common)) ; if (repeat_supernode) { // matrix is not positive definite; finished clean-up for supernode // containing negative diagonal #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) if ( useGPU ) { CHOLMOD (gpu_end) (Common) ; } #endif return (Common->status >= CHOLMOD_OK) ; } } // success; matrix is positive definite L->minor = n ; #if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) if ( useGPU ) { CHOLMOD (gpu_end) (Common) ; } #endif return (Common->status >= CHOLMOD_OK) ; } #undef PATTERN #undef REAL #undef COMPLEX #undef ZOMPLEX Matrix/src/SuiteSparse/CHOLMOD/Supernodal/cholmod_l_super_solve.c0000644000175100001440000000101614552026002024517 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Supernodal/cholmod_l_super_solve.c: // int64_t version of cholmod_super_solve //------------------------------------------------------------------------------ // CHOLMOD/Supernodal Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_super_solve.c" Matrix/src/SuiteSparse/CHOLMOD/Supernodal/cholmod_l_super_numeric.c0000644000175100001440000000102414552026002025030 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Supernodal/cholmod_l_super_numeric.c: // int64_t version of cholmod_super_numeric //------------------------------------------------------------------------------ // CHOLMOD/Supernodal Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ #define CHOLMOD_INT64 #include "cholmod_super_numeric.c" Matrix/src/SuiteSparse/CHOLMOD/Supernodal/cholmod_super_solve.c0000644000175100001440000001716414552026002024217 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Supernodal/cholmod_super_solve: solve using supernodal factorization //------------------------------------------------------------------------------ // CHOLMOD/Supernodal Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // Solve Lx=b or L'x=b for a supernodal factorization. These routines do not // apply the permutation L->Perm. See cholmod_solve for a more general // interface that performs that operation. // // L is supernodal, and real or complex (not pattern, nor zomplex). The xtype // and dtype of L, X, and E must match. #include "cholmod_internal.h" #ifndef NGPL #ifndef NSUPERNODAL //------------------------------------------------------------------------------ // t_cholmod_super_solve //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_super_solve_worker.c" #define COMPLEX #include "t_cholmod_super_solve_worker.c" //------------------------------------------------------------------------------ // cholmod_super_lsolve: solve x=L\b //------------------------------------------------------------------------------ // Solve Lx=b where x and b are of size n-by-nrhs. b is overwritten by the // solution x. On input, b is stored in col-major order with leading dimension // of d, and on output x is stored in the same manner. // // The contents of the workspace E are undefined on both input and output. // // workspace: none int CHOLMOD(super_lsolve) // TRUE if OK, FALSE if BLAS overflow occured ( // input: cholmod_factor *L, // factor to use for the forward solve // input/output: cholmod_dense *X, // b on input, solution to Lx=b on output // workspace: cholmod_dense *E, // workspace of size nrhs*(L->maxesize) cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (L, FALSE) ; RETURN_IF_NULL (X, FALSE) ; RETURN_IF_NULL (E, FALSE) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_REAL, CHOLMOD_COMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (X, CHOLMOD_REAL, CHOLMOD_COMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (E, CHOLMOD_REAL, CHOLMOD_COMPLEX, FALSE) ; if (L->xtype != X->xtype || L->dtype != X->dtype) { ERROR (CHOLMOD_INVALID, "L and X must have the same xtype and dtype") ; return (FALSE) ; } if (L->xtype != E->xtype || L->dtype != E->dtype) { ERROR (CHOLMOD_INVALID, "L and E must have the same xtype and dtype") ; return (FALSE) ; } if (X->d < X->nrow || L->n != X->nrow) { ERROR (CHOLMOD_INVALID, "X and L dimensions must match") ; return (FALSE) ; } if (E->nzmax < X->ncol * (L->maxesize)) { ERROR (CHOLMOD_INVALID, "workspace E not large enough") ; return (FALSE) ; } if (!(L->is_ll) || !(L->is_super)) { ERROR (CHOLMOD_INVALID, "L not supernodal") ; return (FALSE) ; } Common->status = CHOLMOD_OK ; ASSERT (IMPLIES (L->n == 0, L->nsuper == 0)) ; if (L->n == 0 || X->ncol == 0) { // nothing to do return (TRUE) ; } //-------------------------------------------------------------------------- // solve Lx=b using template routine //-------------------------------------------------------------------------- switch ((L->xtype + L->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: return FALSE ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: return FALSE ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_super_lsolve_worker (L, X, E, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_super_lsolve_worker (L, X, E, Common) ; break ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- CHECK_FOR_BLAS_INTEGER_OVERFLOW ; return (Common->blas_ok) ; } //------------------------------------------------------------------------------ // cholmod_super_ltsolve: solve x=L'\b //------------------------------------------------------------------------------ // Solve L'x=b where x and b are of size n-by-nrhs. b is overwritten by the // solution x. On input, b is stored in col-major order with leading dimension // of d, and on output x is stored in the same manner. // // The contents of the workspace E are undefined on both input and output. // // workspace: none int CHOLMOD(super_ltsolve) // TRUE if OK, FALSE if BLAS overflow occured ( // input: cholmod_factor *L, // factor to use for the backsolve // input/output: cholmod_dense *X, // b on input, solution to L'x=b on output // workspace: cholmod_dense *E, // workspace of size nrhs*(L->maxesize) cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (L, FALSE) ; RETURN_IF_NULL (X, FALSE) ; RETURN_IF_NULL (E, FALSE) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_REAL, CHOLMOD_COMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (X, CHOLMOD_REAL, CHOLMOD_COMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (E, CHOLMOD_REAL, CHOLMOD_COMPLEX, FALSE) ; if (L->xtype != X->xtype || L->dtype != X->dtype) { ERROR (CHOLMOD_INVALID, "L and X must have the same xtype and dtype") ; return (FALSE) ; } if (L->xtype != E->xtype || L->dtype != E->dtype) { ERROR (CHOLMOD_INVALID, "L and E must have the same xtype and dtype") ; return (FALSE) ; } if (X->d < X->nrow || L->n != X->nrow) { ERROR (CHOLMOD_INVALID, "X and L dimensions must match") ; return (FALSE) ; } if (E->nzmax < X->ncol * (L->maxesize)) { ERROR (CHOLMOD_INVALID, "workspace E not large enough") ; return (FALSE) ; } if (!(L->is_ll) || !(L->is_super)) { ERROR (CHOLMOD_INVALID, "L not supernodal") ; return (FALSE) ; } Common->status = CHOLMOD_OK ; ASSERT (IMPLIES (L->n == 0, L->nsuper == 0)) ; if (L->n == 0 || X->ncol == 0) { // nothing to do return (TRUE) ; } //-------------------------------------------------------------------------- // solve Lx=b using template routine //-------------------------------------------------------------------------- switch ((L->xtype + L->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: return FALSE ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: return FALSE ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: rd_cholmod_super_ltsolve_worker (L, X, E, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: cd_cholmod_super_ltsolve_worker (L, X, E, Common) ; break ; } //-------------------------------------------------------------------------- // return result //-------------------------------------------------------------------------- CHECK_FOR_BLAS_INTEGER_OVERFLOW ; return (Common->blas_ok) ; } #endif #endif Matrix/src/SuiteSparse/CHOLMOD/Supernodal/cholmod_super_numeric.c0000644000175100001440000002736014552026002024530 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Supernodal/cholmod_super_numeric: supernodal Cholesky factorization //------------------------------------------------------------------------------ // CHOLMOD/Supernodal Module. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // Computes the Cholesky factorization of A+beta*I or A*F+beta*I. Only the // the lower triangular part of A+beta*I or A*F+beta*I is accessed. The // matrices A and F must already be permuted according to the fill-reduction // permutation L->Perm. cholmod_factorize is an "easy" wrapper for this code // which applies that permutation. beta is real. // // Symmetric case: A is a symmetric (lower) matrix. F is not accessed. // With a fill-reducing permutation, A(p,p) should be passed instead, where is // p is L->Perm. // // Unsymmetric case: A is unsymmetric, and F must be present. Normally, F=A'. // With a fill-reducing permutation, A(p,f) and A(p,f)' should be passed as A // and F, respectively, where f is a list of the subset of the columns of A. // // The input factorization L must be supernodal (L->is_super is TRUE). It can // either be symbolic or numeric. In the first case, L has been analyzed by // cholmod_analyze or cholmod_super_symbolic, but the matrix has not yet been // numerically factorized. The numerical values are allocated here and the // factorization is computed. In the second case, a prior matrix has been // analyzed and numerically factorized, and a new matrix is being factorized. // The numerical values of L are replaced with the new numerical factorization. // // L->is_ll is ignored, and set to TRUE. This routine always computes an LL' // factorization. Supernodal LDL' factorization is not (yet) supported. // FUTURE WORK: perform a supernodal LDL' factorization if L->is_ll is FALSE. // // If the matrix is not positive definite the routine returns TRUE, but sets // Common->status to CHOLMOD_NOT_POSDEF and L->minor is set to the column at // which the failure occurred. The supernode containing the non-positive // diagonal entry is set to zero (this includes columns to the left of L->minor // in the same supernode), as are all subsequent supernodes. // // workspace: Flag (nrow), Head (nrow+1), Iwork (2*nrow + 5*nsuper). // Allocates temporary space of size L->maxcsize * sizeof(double) // (twice that for the complex/zomplex case). // // If L is supernodal symbolic on input, it is converted to a supernodal numeric // factor on output, with an xtype of real if A is real, or complex if A is // complex or zomplex. If L is supernodal numeric on input, its xtype must // match A (except that L can be complex and A zomplex). The xtype of A and F // must match. The dtypes of all matrices must match. #include "cholmod_internal.h" #ifndef NGPL #ifndef NSUPERNODAL //------------------------------------------------------------------------------ // GPU templates: double and double complex cases only //------------------------------------------------------------------------------ #define DOUBLE #ifdef CHOLMOD_INT64 #ifdef CHOLMOD_HAS_CUDA #include "cholmod_gpu_kernels.h" #define REAL #include "../GPU/t_cholmod_gpu.c" #define COMPLEX #include "../GPU/t_cholmod_gpu.c" #endif #endif //------------------------------------------------------------------------------ // CPU templates: all cases //------------------------------------------------------------------------------ #define DOUBLE #define REAL #include "t_cholmod_super_numeric_worker.c" #define COMPLEX #include "t_cholmod_super_numeric_worker.c" #define ZOMPLEX #include "t_cholmod_super_numeric_worker.c" //------------------------------------------------------------------------------ // cholmod_super_numeric //------------------------------------------------------------------------------ // Returns TRUE if successful, or if the matrix is not positive definite. // Returns FALSE if out of memory, inputs are invalid, or other fatal error // occurs. int CHOLMOD(super_numeric) ( // input: cholmod_sparse *A, // matrix to factorize cholmod_sparse *F, // F = A' or A(:,f)' double beta [2], // beta*I is added to diagonal of matrix to factorize // input/output: cholmod_factor *L, // factorization cholmod_common *Common ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- cholmod_dense *C ; Int *Super, *Map, *SuperMap ; size_t maxcsize ; Int nsuper, n, i, k, s, nrow ; int symbolic ; RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (L, FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_COMPLEX, FALSE) ; if (A->stype < 0) { if (A->nrow != A->ncol || A->nrow != L->n) { ERROR (CHOLMOD_INVALID, "invalid dimensions") ; return (FALSE) ; } } else if (A->stype == 0) { if (A->nrow != L->n) { ERROR (CHOLMOD_INVALID, "invalid dimensions") ; return (FALSE) ; } RETURN_IF_NULL (F, FALSE) ; RETURN_IF_XTYPE_INVALID (F, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ; if (A->nrow != F->ncol || A->ncol != F->nrow || F->stype != 0) { ERROR (CHOLMOD_INVALID, "F invalid") ; return (FALSE) ; } if (A->xtype != F->xtype || A->dtype != F->dtype) { ERROR (CHOLMOD_INVALID, "A and F must have same xtype and dtype") ; return (FALSE) ; } } else { // symmetric upper case not supported ERROR (CHOLMOD_INVALID, "symmetric upper case not supported") ; return (FALSE) ; } if (!(L->is_super)) { ERROR (CHOLMOD_INVALID, "L not supernodal") ; return (FALSE) ; } if (L->xtype != CHOLMOD_PATTERN) { if (! ((A->xtype == CHOLMOD_REAL && L->xtype == CHOLMOD_REAL) || (A->xtype == CHOLMOD_COMPLEX && L->xtype == CHOLMOD_COMPLEX) || (A->xtype == CHOLMOD_ZOMPLEX && L->xtype == CHOLMOD_COMPLEX))) { ERROR (CHOLMOD_INVALID, "complex type mismatch") ; return (FALSE) ; } if (A->dtype != L->dtype) { ERROR (CHOLMOD_INVALID, "A and L must have the same dtype") ; return (FALSE) ; } } Common->status = CHOLMOD_OK ; //-------------------------------------------------------------------------- // allocate workspace in Common //-------------------------------------------------------------------------- nsuper = L->nsuper ; maxcsize = L->maxcsize ; nrow = A->nrow ; n = nrow ; PRINT1 (("nsuper "ID" maxcsize %g\n", nsuper, (double) maxcsize)) ; ASSERT (nsuper >= 0 && maxcsize > 0) ; // w = 2*nrow + 5*nsuper int ok = TRUE ; size_t w = CHOLMOD(mult_size_t) (A->nrow, 2, &ok) ; size_t t = CHOLMOD(mult_size_t) (L->nsuper, 5, &ok) ; w = CHOLMOD(add_size_t) (w, t, &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (FALSE) ; } CHOLMOD(allocate_work) (A->nrow, w, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; //-------------------------------------------------------------------------- // get the current factor L and allocate numerical part, if needed //-------------------------------------------------------------------------- Super = L->super ; symbolic = (L->xtype == CHOLMOD_PATTERN) ; if (symbolic) { // convert to supernodal numeric by allocating L->x L->dtype = A->dtype ; // ensure L has the same dtype as A CHOLMOD(change_factor) ( (A->xtype == CHOLMOD_REAL) ? CHOLMOD_REAL : CHOLMOD_COMPLEX, TRUE, TRUE, TRUE, TRUE, L, Common) ; if (Common->status < CHOLMOD_OK) { // the factor L remains in symbolic supernodal form return (FALSE) ; } } ASSERT (L->dtype == A->dtype) ; ASSERT (L->dtype == CHOLMOD_DOUBLE || L->dtype == CHOLMOD_SINGLE) ; ASSERT (L->xtype == CHOLMOD_REAL || L->xtype == CHOLMOD_COMPLEX) ; // supernodal LDL' is not supported L->is_ll = TRUE ; //-------------------------------------------------------------------------- // get more workspace //-------------------------------------------------------------------------- C = CHOLMOD(allocate_dense) (maxcsize, 1, maxcsize, L->xtype + L->dtype, Common) ; if (Common->status < CHOLMOD_OK) { int status = Common->status ; if (symbolic) { // Change L back to symbolic, since the numeric values are not // initialized. This cannot fail. CHOLMOD(change_factor) (CHOLMOD_PATTERN, TRUE, TRUE, TRUE, TRUE, L, Common) ; } // the factor L is now back to the form it had on input Common->status = status ; return (FALSE) ; } //-------------------------------------------------------------------------- // get workspace //-------------------------------------------------------------------------- SuperMap = Common->Iwork ; // size n Map = Common->Flag ; // size n, use Flag as workspace for Map array for (i = 0 ; i < n ; i++) { Map [i] = EMPTY ; } //-------------------------------------------------------------------------- // find the mapping of nodes to relaxed supernodes //-------------------------------------------------------------------------- // SuperMap [k] = s if column k is contained in supernode s for (s = 0 ; s < nsuper ; s++) { PRINT1 (("Super ["ID"] "ID" ncols "ID"\n", s, Super[s], Super[s+1]-Super[s])) ; for (k = Super [s] ; k < Super [s+1] ; k++) { SuperMap [k] = s ; PRINT2 (("relaxed SuperMap ["ID"] = "ID"\n", k, SuperMap [k])) ; } } //-------------------------------------------------------------------------- // supernodal numerical factorization, using template routine //-------------------------------------------------------------------------- switch ((A->xtype + A->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: ok = FALSE ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: ok = FALSE ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: // A is zomplex, but L is complex ok = FALSE ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: ok = rd_cholmod_super_numeric_worker (A, F, beta, L, C, Common) ; break ; case CHOLMOD_COMPLEX + CHOLMOD_DOUBLE: ok = cd_cholmod_super_numeric_worker (A, F, beta, L, C, Common) ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_DOUBLE: // A is zomplex, but L is complex ok = zd_cholmod_super_numeric_worker (A, F, beta, L, C, Common) ; break ; } //-------------------------------------------------------------------------- // clear Common workspace, free temp workspace C, and return //-------------------------------------------------------------------------- // Flag array was used as workspace, clear it Common->mark = EMPTY ; CLEAR_FLAG (Common) ; ASSERT (check_flag (Common)) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, 0, Common)) ; CHOLMOD(free_dense) (&C, Common) ; return (ok) ; } #endif #endif Matrix/src/SuiteSparse/SuiteSparse_config/0000755000175100001440000000000014576344041020376 5ustar hornikusersMatrix/src/SuiteSparse/SuiteSparse_config/SuiteSparse_config.h0000644000175100001440000027365114575233601024357 0ustar hornikusers//------------------------------------------------------------------------------ // SuiteSparse_config/SuiteSparse_config.h: common utilites for SuiteSparse //------------------------------------------------------------------------------ // SuiteSparse_config, Copyright (c) 2012-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ // Configuration file for SuiteSparse: a Suite of Sparse matrix packages: AMD, // COLAMD, CCOLAMD, CAMD, CHOLMOD, UMFPACK, CXSparse, SuiteSparseQR, ParU, ... // The SuiteSparse_config.h file is configured by CMake to be specific to the // C/C++ compiler and BLAS library being used for SuiteSparse. The original // file is SuiteSparse_config/SuiteSparse_config.h.in. Do not edit the // SuiteSparse_config.h file directly. #ifndef SUITESPARSE_CONFIG_H #define SUITESPARSE_CONFIG_H #ifdef __cplusplus extern "C" { #endif //------------------------------------------------------------------------------ // SuiteSparse-wide ANSI C11 #include files //------------------------------------------------------------------------------ #include #include #include #include #include #include #include #include #include #include #include #include #ifndef INT32_MAX # define int32_t long # define INT32_MIN LONG_MIN # define INT32_MAX LONG_MAX # define PRId32 "ld" # define SCNd32 "ld" #endif #ifndef INT64_MAX # define int64_t long long # define INT64_MIN LLONG_MIN # define INT64_MAX LLONG_MAX # define PRId64 "lld" # define SCNd64 "lld" #endif #ifndef UINT32_MAX # define uint32_t unsigned long # define UINT32_MAX ULONG_MAX # define PRIu32 "lu" # define SCNu32 "lu" #endif #ifndef UINT64_MAX # define uint64_t unsigned long long # define UINT64_MAX ULLONG_MAX # define PRIu64 "llu" # define SCNu64 "llu" #endif //------------------------------------------------------------------------------ // SuiteSparse_long is now int64_t in SuiteSparse v6.0.0 and later //------------------------------------------------------------------------------ // The use of SuiteSparse_long is deprecated. User applications should use // int64_t instead. #undef SuiteSparse_long #undef SuiteSparse_long_max #undef SuiteSparse_long_idd #undef SuiteSparse_long_id #define SuiteSparse_long int64_t #define SuiteSparse_long_max INT64_MAX #define SuiteSparse_long_idd PRId64 #define SuiteSparse_long_id "%" SuiteSparse_long_idd //------------------------------------------------------------------------------ // OpenMP //------------------------------------------------------------------------------ #if defined ( _OPENMP ) #include #define SUITESPARSE_OPENMP_MAX_THREADS omp_get_max_threads ( ) #define SUITESPARSE_OPENMP_GET_NUM_THREADS omp_get_num_threads ( ) #define SUITESPARSE_OPENMP_GET_WTIME omp_get_wtime ( ) #define SUITESPARSE_OPENMP_GET_THREAD_ID omp_get_thread_num ( ) #else // OpenMP not available #define SUITESPARSE_OPENMP_MAX_THREADS (1) #define SUITESPARSE_OPENMP_GET_NUM_THREADS (1) #define SUITESPARSE_OPENMP_GET_WTIME (0) #define SUITESPARSE_OPENMP_GET_THREAD_ID (0) #endif //------------------------------------------------------------------------------ // MATLAB/Octave //------------------------------------------------------------------------------ #if defined ( MATLAB_MEX_FILE ) #include "mex.h" #include "matrix.h" #endif //------------------------------------------------------------------------------ // string and token handling macros //------------------------------------------------------------------------------ // SUITESPARSE_STR: convert the content of x into a string "x" #define SUITESPARSE_XSTR(x) SUITESPARSE_STR(x) #define SUITESPARSE_STR(x) #x // SUITESPARSE_CAT(x,y): concatenate two tokens #define SUITESPARSE_CAT2(x,y) x ## y #define SUITESPARSE_CAT(x,y) SUITESPARSE_CAT2(x,y) //------------------------------------------------------------------------------ // determine which compiler is in use //------------------------------------------------------------------------------ #define SUITESPARSE_COMPILER_NVCC 0 #define SUITESPARSE_COMPILER_ICX 0 #define SUITESPARSE_COMPILER_ICC 0 #define SUITESPARSE_COMPILER_CLANG 0 #define SUITESPARSE_COMPILER_GCC 0 #define SUITESPARSE_COMPILER_MSC 0 #define SUITESPARSE_COMPILER_XLC 0 #if defined ( __NVCC__ ) // NVIDIA nvcc compiler #undef SUITESPARSE_COMPILER_NVCC #define SUITESPARSE_COMPILER_NVCC 1 #define SUITESPARSE_COMPILER_MAJOR __CUDACC_VER_MAJOR__ #define SUITESPARSE_COMPILER_MINOR __CUDACC_VER_MINOR__ #define SUITESPARSE_COMPILER_SUB __CUDACC_VER_BUILD__ #define SUITESPARSE_COMPILER_NAME "nvcc" #elif defined ( __INTEL_CLANG_COMPILER ) // Intel icx compiler, 2022.0.0 based on clang/llvm 14.0.0 #undef SUITESPARSE_COMPILER_ICX #define SUITESPARSE_COMPILER_ICX 1 #define SUITESPARSE_COMPILER_MAJOR __INTEL_CLANG_COMPILER #define SUITESPARSE_COMPILER_MINOR 0 #define SUITESPARSE_COMPILER_SUB 0 #define SUITESPARSE_COMPILER_NAME __VERSION__ #elif defined ( __INTEL_COMPILER ) // Intel icc compiler: 2021.5.0 uses "gcc 7.5 mode" #undef SUITESPARSE_COMPILER_ICC #define SUITESPARSE_COMPILER_ICC 1 #define SUITESPARSE_COMPILER_MAJOR __INTEL_COMPILER #define SUITESPARSE_COMPILER_MINOR __INTEL_COMPILER_UPDATE #define SUITESPARSE_COMPILER_SUB 0 #define SUITESPARSE_COMPILER_NAME __VERSION__ #elif defined ( __clang__ ) // clang #undef SUITESPARSE_COMPILER_CLANG #define SUITESPARSE_COMPILER_CLANG 1 #define SUITESPARSE_COMPILER_MAJOR __clang_major__ #define SUITESPARSE_COMPILER_MINOR __clang_minor__ #define SUITESPARSE_COMPILER_SUB __clang_patchlevel__ #define SUITESPARSE_COMPILER_NAME "clang " __clang_version__ #elif defined ( __xlC__ ) // xlc #undef SUITESPARSE_COMPILER_XLC #define SUITESPARSE_COMPILER_XLC 1 #define SUITESPARSE_COMPILER_MAJOR ( __xlC__ / 256 ) #define SUITESPARSE_COMPILER_MINOR \ ( __xlC__ - 256 * SUITESPARSE_COMPILER_MAJOR) #define SUITESPARSE_COMPILER_SUB 0 #define SUITESPARSE_COMPILER_NAME "IBM xlc " SUITESPARSE_XSTR (__xlC__) #elif defined ( __GNUC__ ) // gcc #undef SUITESPARSE_COMPILER_GCC #define SUITESPARSE_COMPILER_GCC 1 #define SUITESPARSE_COMPILER_MAJOR __GNUC__ #define SUITESPARSE_COMPILER_MINOR __GNUC_MINOR__ #define SUITESPARSE_COMPILER_SUB __GNUC_PATCHLEVEL__ #define SUITESPARSE_COMPILER_NAME "GNU gcc " \ SUITESPARSE_XSTR (__GNUC__) "." \ SUITESPARSE_XSTR (__GNUC_MINOR__) "." \ SUITESPARSE_XSTR (__GNUC_PATCHLEVEL__) #elif defined ( _MSC_VER ) // Microsoft Visual Studio (cl compiler) #undef SUITESPARSE_COMPILER_MSC #define SUITESPARSE_COMPILER_MSC 1 #define SUITESPARSE_COMPILER_MAJOR ( _MSC_VER / 100 ) #define SUITESPARSE_COMPILER_MINOR \ ( _MSC_VER - 100 * SUITESPARSE_COMPILER_MAJOR) #define SUITESPARSE_COMPILER_SUB 0 #define SUITESPARSE_COMPILER_NAME \ "Microsoft Visual Studio " SUITESPARSE_XSTR (_MSC_VER) #else // other compiler #define SUITESPARSE_COMPILER_MAJOR 0 #define SUITESPARSE_COMPILER_MINOR 0 #define SUITESPARSE_COMPILER_SUB 0 #define SUITESPARSE_COMPILER_NAME "other C compiler" #endif //------------------------------------------------------------------------------ // malloc.h: required include file for Microsoft Visual Studio //------------------------------------------------------------------------------ #if SUITESPARSE_COMPILER_MSC #include #endif // this was formerly "extern", or "__declspec ..." for Windows. #define SUITESPARSE_PUBLIC //------------------------------------------------------------------------------ // determine the ANSI C version //------------------------------------------------------------------------------ #ifdef __STDC_VERSION__ // ANSI C17: 201710L // ANSI C11: 201112L // ANSI C99: 199901L // ANSI C95: 199409L #define SUITESPARSE_STDC_VERSION __STDC_VERSION__ #else // assume ANSI C90 / C89 #define SUITESPARSE_STDC_VERSION 199001L #endif //------------------------------------------------------------------------------ // handle the restrict keyword //------------------------------------------------------------------------------ #if defined ( __cplusplus ) // C++ does not have the "restrict" keyword #define SUITESPARSE_RESTRICT #elif SUITESPARSE_COMPILER_MSC // MS Visual Studio #define SUITESPARSE_RESTRICT __restrict #elif SUITESPARSE_COMPILER_NVCC // NVIDIA nvcc #define SUITESPARSE_RESTRICT __restrict__ #elif SUITESPARSE_STDC_VERSION >= 199901L // ANSI C99 or later #define SUITESPARSE_RESTRICT restrict #else // ANSI C95 and earlier: no restrict keyword #define SUITESPARSE_RESTRICT #endif //============================================================================== // SuiteSparse_config parameters and functions //============================================================================== // SuiteSparse-wide parameters are placed in a single static struct, defined // locally in SuiteSparse_config.c. It is not meant to be updated frequently // by multiple threads. Rather, if an application needs to modify // SuiteSparse_config, it should do it once at the beginning of the // application, before multiple threads are launched. // The intent of these function pointers is that they not be used in your // application directly, except to assign them to the desired user-provided // functions. Rather, you should use the SuiteSparse_malloc/calloc, etc // wrappers defined below to access them. // The SuiteSparse_config_*_get methods return the contents of the struct: void *(*SuiteSparse_config_malloc_func_get (void)) (size_t); void *(*SuiteSparse_config_calloc_func_get (void)) (size_t, size_t); void *(*SuiteSparse_config_realloc_func_get (void)) (void *, size_t); void (*SuiteSparse_config_free_func_get (void)) (void *); int (*SuiteSparse_config_printf_func_get (void)) (const char *, ...); double (*SuiteSparse_config_hypot_func_get (void)) (double, double); int (*SuiteSparse_config_divcomplex_func_get (void)) (double, double, double, double, double *, double *); // The SuiteSparse_config_*_set methods modify the contents of the struct: void SuiteSparse_config_malloc_func_set (void *(*malloc_func) (size_t)); void SuiteSparse_config_calloc_func_set (void *(*calloc_func) (size_t, size_t)); void SuiteSparse_config_realloc_func_set (void *(*realloc_func) (void *, size_t)); void SuiteSparse_config_free_func_set (void (*free_func) (void *)); void SuiteSparse_config_printf_func_set (int (*printf_func) (const char *, ...)); void SuiteSparse_config_hypot_func_set (double (*hypot_func) (double, double)); void SuiteSparse_config_divcomplex_func_set (int (*divcomplex_func) (double, double, double, double, double *, double *)); // The SuiteSparse_config_*_func methods are wrappers that call the function // pointers in the struct. Note that there is no wrapper for the printf_func. // See the SUITESPARSE_PRINTF macro instead. void *SuiteSparse_config_malloc (size_t s) ; void *SuiteSparse_config_calloc (size_t n, size_t s) ; void *SuiteSparse_config_realloc (void *, size_t s) ; void SuiteSparse_config_free (void *) ; double SuiteSparse_config_hypot (double x, double y) ; int SuiteSparse_config_divcomplex ( double xr, double xi, double yr, double yi, double *zr, double *zi ) ; void SuiteSparse_start ( void ) ; // called to start SuiteSparse void SuiteSparse_finish ( void ) ; // called to finish SuiteSparse void *SuiteSparse_malloc // pointer to allocated block of memory ( size_t nitems, // number of items to malloc (>=1 is enforced) size_t size_of_item // sizeof each item ) ; void *SuiteSparse_calloc // pointer to allocated block of memory ( size_t nitems, // number of items to calloc (>=1 is enforced) size_t size_of_item // sizeof each item ) ; void *SuiteSparse_realloc // pointer to reallocated block of memory, or ///to original block if the realloc failed. ( size_t nitems_new, // new number of items in the object size_t nitems_old, // old number of items in the object size_t size_of_item, // sizeof each item void *p, // old object to reallocate int *ok // 1 if successful, 0 otherwise ) ; void *SuiteSparse_free // always returns NULL ( void *p // block to free ) ; void SuiteSparse_tic // start the timer ( double tic [2] // output, contents undefined on input ) ; double SuiteSparse_toc // return time in seconds since last tic ( double tic [2] // input: from last call to SuiteSparse_tic ) ; double SuiteSparse_time // returns current wall clock time in seconds ( void ) ; // returns sqrt (x^2 + y^2), computed reliably double SuiteSparse_hypot (double x, double y) ; // complex division of c = a/b int SuiteSparse_divcomplex ( double ar, double ai, // real and imaginary parts of a double br, double bi, // real and imaginary parts of b double *cr, double *ci // real and imaginary parts of c ) ; // determine which timer to use, if any #ifndef NTIMER // SuiteSparse_config itself can be compiled without OpenMP, // but other packages can themselves use OpenMP. In this case, // those packages should use omp_get_wtime() directly. This can // be done via the SUITESPARSE_TIME macro, defined below: #define SUITESPARSE_HAVE_CLOCK_GETTIME #if defined ( _OPENMP ) #define SUITESPARSE_TIMER_ENABLED #define SUITESPARSE_TIME (omp_get_wtime ( )) #elif defined ( SUITESPARSE_HAVE_CLOCK_GETTIME ) #define SUITESPARSE_TIMER_ENABLED #define SUITESPARSE_TIME (SuiteSparse_time ( )) #else // No timer is available #define SUITESPARSE_TIME (0) #endif #else // The timer is explictly disabled #define SUITESPARSE_TIME (0) #endif // SuiteSparse printf macro #define SUITESPARSE_PRINTF(params) \ { \ int (*printf_func) (const char *, ...) ; \ printf_func = SuiteSparse_config_printf_func_get ( ) ; \ if (printf_func != NULL) \ { \ (void) (printf_func) params ; \ } \ } //============================================================================== // SuiteSparse version //============================================================================== // SuiteSparse is not a package itself, but a collection of packages, some of // which must be used together (UMFPACK requires AMD, CHOLMOD requires AMD, // COLAMD, CAMD, and CCOLAMD, etc). A version number is provided here for the // collection itself, which is also the version number of SuiteSparse_config. int SuiteSparse_version // returns SUITESPARSE_VERSION ( // output, not defined on input. Not used if NULL. Returns // the three version codes in version [0..2]: // version [0] is SUITESPARSE_MAIN_VERSION // version [1] is SUITESPARSE_SUB_VERSION // version [2] is SUITESPARSE_SUBSUB_VERSION int version [3] ) ; #define SUITESPARSE_HAS_VERSION_FUNCTION #define SUITESPARSE_DATE "Jan 20, 2024" #define SUITESPARSE_MAIN_VERSION 7 #define SUITESPARSE_SUB_VERSION 6 #define SUITESPARSE_SUBSUB_VERSION 0 // version format x.y #define SUITESPARSE_VER_CODE(main,sub) ((main) * 1000 + (sub)) #define SUITESPARSE_VERSION SUITESPARSE_VER_CODE(7, 6) // version format x.y.z #define SUITESPARSE__VERCODE(main,sub,patch) \ (((main)*1000ULL + (sub))*1000ULL + (patch)) #define SUITESPARSE__VERSION SUITESPARSE__VERCODE(7,6,0) //============================================================================== // SuiteSparse interface to the BLAS and LAPACK libraries //============================================================================== // Several SuiteSparse packages rely on the BLAS/LAPACK libraries (UMFPACK // CHOLMOD, and SPQR, and likely GraphBLAS in the future). All of these // packages are written in C/C++, but rely on the Fortran interface to // BLAS/LAPACK. SuiteSparse does not use the cblas / lapacke interfaces to // these libraries, mainly because FindBLAS.cmake does not locate them (or at // least does not locate their respective cblas.h and lapacke.h files). In // addition, the original definition of these files do not include a different // name space for 64-bit integer versions. Finally, Intel renames cblas.h as // mkl_cblas.h. As a result of these many portability issues, different // implementations of those libraries extend them in different ways. Thus, // SuiteSparse simply calls the Fortran functions directly. // However, the method for how C/C++ calling Fortran depends on the compilers // involved. This connection is handled by the FortranCInterface.cmake module // of CMake. // On typical systems (Linux with the GCC compiler for example, or on the Mac // with clang) the Fortan name "dgemm" is called by C as "dgemm_", Other // systems do not append the underscore. //------------------------------------------------------------------------------ // SUITESPARSE_FORTRAN: macros created by CMake describing how C calls Fortran //------------------------------------------------------------------------------ // SUITESPARSE_FORTAN: for Fortran routines with no "_" in their names // SUITESPARSE__FORTAN: for Fortran routines with "_" in their names // The decision on which of these macros to use is based on the presence of // underscores in the original Fortran names, not the (commonly) appended // underscore needed for C to all the corresponding Fortran routine. // These two macros are created by the CMake module, FortranCInterface.cmake, // which is then used by CMake to configure this file. // The CMAKE decision can be superceded by setting -DBLAS_NO_UNDERSCORE, so // that "dgemm" remains "dgemm" (for MS Visual Studio for example). Setting // -DBLAS_UNDERSCORE changes "dgemm" to "dgemm_", the common case for Mac and // Linux. #if defined ( BLAS_NO_UNDERSCORE ) // no name mangling, use lower case #define SUITESPARSE_FORTRAN(name,NAME) name #define SUITESPARSE__FORTRAN(name,NAME) name #elif defined ( BLAS_UNDERSCORE ) // append an underscore, use lower case #define SUITESPARSE_FORTRAN(name,NAME) name ## _ #define SUITESPARSE__FORTRAN(name,NAME) name ## _ #else // let CMake decide how C calls Fortran #define SUITESPARSE_FORTRAN(name,NAME) name##_ #define SUITESPARSE__FORTRAN(name,NAME) name##_ #endif //------------------------------------------------------------------------------ // SUITESPARSE_BLAS_INT: the BLAS/LAPACK integer (int32_t or int64_t) //------------------------------------------------------------------------------ // CMake 3.22 and later allow the selection of the BLAS/LAPACK integer size. // This information is then used to configure this file with the definition of // this integer: int32_t or int64_t. // When compiling SuiteSparse for a MATLAB mexFunction, the MATLAB libmwblas is // used, which is a 64-bit integer version of the BLAS. CMake is not used to // configure SuiteSparse in this case. The flag -DBLAS64 can be used to ensure // a 64-bit BLAS is used. Likewise, -DBLAS32 ensures a 32-bit BLAS is used. #if defined ( BLAS64 ) // override the BLAS found by CMake, and force a 64-bit interface #define SUITESPARSE_BLAS_INT int64_t #elif defined ( BLAS32 ) // override the BLAS found by CMake, and force a 32-bit interface #define SUITESPARSE_BLAS_INT int32_t #else // let CMake determine the size of the integer in the Fortran BLAS #define SUITESPARSE_BLAS_INT int32_t #endif // SUITESPARSE_TO_BLAS_INT: convert an integer k to a BLAS integer K and set ok // to false if the conversion changes its value. This is implemented as a // macro so that can work with any type of the integer k. #define SUITESPARSE_TO_BLAS_INT(K,k,ok) \ SUITESPARSE_BLAS_INT K = (k) ; \ ok = ok && ((sizeof (K) >= sizeof (k)) || ((int64_t)(K) == (int64_t)(k))) ; //------------------------------------------------------------------------------ // SUITESPARSE_BLAS_SUFFIX: modify the name of a Fortran BLAS/LAPACK routine //------------------------------------------------------------------------------ // OpenBLAS can be compiled by appending a suffix to each routine, so that the // Fortan routine dgemm becomes dgemm_64, which denotes a version of dgemm with // 64-bit integer parameters. The Sun Performance library does the same thing, // but without the internal underscore, as dgemm64. // If the suffix does not contain "_", use (Sun Perf., for example): // cd build && cmake -DBLAS64_SUFFIX="64" .. // If the suffix contains "_" (OpenBLAS in spack for example), use the // following: // cd build && cmake -DBLAS64_SUFFIX="_64" .. // This setting could be used by the spack packaging of SuiteSparse when linked // with the spack-installed OpenBLAS with 64-bit integers. See // https://github.com/spack/spack/blob/develop/var/spack/repos/builtin/packages/suite-sparse/package.py #if defined ( BLAS64__SUFFIX ) // The suffix includes an undersore (such as "_64"), so the Fortran name // must be processed with the SUITESPARSE__FORTRAN macro. #define SUITESPARSE_G(name,NAME) SUITESPARSE__FORTRAN(name,NAME) #define SUITESPARSE_F(name,NAME) \ SUITESPARSE_G (SUITESPARSE_CAT (name, BLAS64__SUFFIX), \ SUITESPARSE_CAT (NAME, BLAS64__SUFFIX)) #define SUITESPARSE_BLAS(name,NAME) SUITESPARSE_F(name,NAME) #elif defined ( BLAS64_SUFFIX ) // The suffix does not include an undersore, and neither do the original // names of the BLAS and LAPACK routines. Thus, the Fortran name must be // processed with the SUITESPARSE_FORTRAN macro. #define SUITESPARSE_G(name,NAME) SUITESPARSE_FORTRAN(name,NAME) #define SUITESPARSE_F(name,NAME) \ SUITESPARSE_G (SUITESPARSE_CAT (name, BLAS64_SUFFIX), \ SUITESPARSE_CAT (NAME, BLAS64_SUFFIX)) #define SUITESPARSE_BLAS(name,NAME) SUITESPARSE_F(name,NAME) #else // No suffix is need, so the final Fortran name includes no suffix. #define SUITESPARSE_BLAS(name,NAME) SUITESPARSE_FORTRAN(name,NAME) #endif //------------------------------------------------------------------------------ // C names of Fortan BLAS and LAPACK functions used by SuiteSparse //------------------------------------------------------------------------------ // double #define SUITESPARSE_BLAS_DTRSV SUITESPARSE_BLAS ( dtrsv , DTRSV ) #define SUITESPARSE_BLAS_DGEMV SUITESPARSE_BLAS ( dgemv , DGEMV ) #define SUITESPARSE_BLAS_DTRSM SUITESPARSE_BLAS ( dtrsm , DTRSM ) #define SUITESPARSE_BLAS_DGEMM SUITESPARSE_BLAS ( dgemm , DGEMM ) #define SUITESPARSE_BLAS_DSYRK SUITESPARSE_BLAS ( dsyrk , DSYRK ) #define SUITESPARSE_BLAS_DGER SUITESPARSE_BLAS ( dger , DGER ) #define SUITESPARSE_BLAS_DSCAL SUITESPARSE_BLAS ( dscal , DSCAL ) #define SUITESPARSE_BLAS_DNRM2 SUITESPARSE_BLAS ( dnrm2 , DNRM2 ) #define SUITESPARSE_LAPACK_DPOTRF SUITESPARSE_BLAS ( dpotrf , DPOTRF ) #define SUITESPARSE_LAPACK_DLARF SUITESPARSE_BLAS ( dlarf , DLARF ) #define SUITESPARSE_LAPACK_DLARFG SUITESPARSE_BLAS ( dlarfg , DLARFG ) #define SUITESPARSE_LAPACK_DLARFT SUITESPARSE_BLAS ( dlarft , DLARFT ) #define SUITESPARSE_LAPACK_DLARFB SUITESPARSE_BLAS ( dlarfb , DLARFB ) // double complex #define SUITESPARSE_BLAS_ZTRSV SUITESPARSE_BLAS ( ztrsv , ZTRSV ) #define SUITESPARSE_BLAS_ZGEMV SUITESPARSE_BLAS ( zgemv , ZGEMV ) #define SUITESPARSE_BLAS_ZTRSM SUITESPARSE_BLAS ( ztrsm , ZTRSM ) #define SUITESPARSE_BLAS_ZGEMM SUITESPARSE_BLAS ( zgemm , ZGEMM ) #define SUITESPARSE_BLAS_ZHERK SUITESPARSE_BLAS ( zherk , ZHERK ) #define SUITESPARSE_BLAS_ZGERU SUITESPARSE_BLAS ( zgeru , ZGERU ) #define SUITESPARSE_BLAS_ZSCAL SUITESPARSE_BLAS ( zscal , ZSCAL ) #define SUITESPARSE_BLAS_DZNRM2 SUITESPARSE_BLAS ( dznrm2 , DZNRM2 ) #define SUITESPARSE_LAPACK_ZPOTRF SUITESPARSE_BLAS ( zpotrf , ZPOTRF ) #define SUITESPARSE_LAPACK_ZLARF SUITESPARSE_BLAS ( zlarf , ZLARF ) #define SUITESPARSE_LAPACK_ZLARFG SUITESPARSE_BLAS ( zlarfg , ZLARFG ) #define SUITESPARSE_LAPACK_ZLARFT SUITESPARSE_BLAS ( zlarft , ZLARFT ) #define SUITESPARSE_LAPACK_ZLARFB SUITESPARSE_BLAS ( zlarfb , ZLARFB ) // single #define SUITESPARSE_BLAS_STRSV SUITESPARSE_BLAS ( strsv , STRSV ) #define SUITESPARSE_BLAS_SGEMV SUITESPARSE_BLAS ( sgemv , SGEMV ) #define SUITESPARSE_BLAS_STRSM SUITESPARSE_BLAS ( strsm , STRSM ) #define SUITESPARSE_BLAS_SGEMM SUITESPARSE_BLAS ( sgemm , SGEMM ) #define SUITESPARSE_BLAS_SSYRK SUITESPARSE_BLAS ( ssyrk , SSYRK ) #define SUITESPARSE_BLAS_SGER SUITESPARSE_BLAS ( sger , SGER ) #define SUITESPARSE_BLAS_SSCAL SUITESPARSE_BLAS ( sscal , SSCAL ) #define SUITESPARSE_BLAS_SNRM2 SUITESPARSE_BLAS ( snrm2 , SNRM2 ) #define SUITESPARSE_LAPACK_SPOTRF SUITESPARSE_BLAS ( spotrf , SPOTRF ) #define SUITESPARSE_LAPACK_SLARF SUITESPARSE_BLAS ( slarf , SLARF ) #define SUITESPARSE_LAPACK_SLARFG SUITESPARSE_BLAS ( slarfg , SLARFG ) #define SUITESPARSE_LAPACK_SLARFT SUITESPARSE_BLAS ( slarft , SLARFT ) #define SUITESPARSE_LAPACK_SLARFB SUITESPARSE_BLAS ( slarfb , SLARFB ) // single complex #define SUITESPARSE_BLAS_CTRSV SUITESPARSE_BLAS ( ctrsv , CTRSV ) #define SUITESPARSE_BLAS_CGEMV SUITESPARSE_BLAS ( cgemv , CGEMV ) #define SUITESPARSE_BLAS_CTRSM SUITESPARSE_BLAS ( ctrsm , CTRSM ) #define SUITESPARSE_BLAS_CGEMM SUITESPARSE_BLAS ( cgemm , CGEMM ) #define SUITESPARSE_BLAS_CHERK SUITESPARSE_BLAS ( cherk , CHERK ) #define SUITESPARSE_BLAS_CGERU SUITESPARSE_BLAS ( cgeru , CGERU ) #define SUITESPARSE_BLAS_CSCAL SUITESPARSE_BLAS ( cscal , CSCAL ) #define SUITESPARSE_BLAS_SCNRM2 SUITESPARSE_BLAS ( scnrm2 , SCNRM2 ) #define SUITESPARSE_LAPACK_CPOTRF SUITESPARSE_BLAS ( cpotrf , CPOTRF ) #define SUITESPARSE_LAPACK_CLARF SUITESPARSE_BLAS ( clarf , CLARF ) #define SUITESPARSE_LAPACK_CLARFG SUITESPARSE_BLAS ( clarfg , CLARFG ) #define SUITESPARSE_LAPACK_CLARFT SUITESPARSE_BLAS ( clarft , CLARFT ) #define SUITESPARSE_LAPACK_CLARFB SUITESPARSE_BLAS ( clarfb , CLARFB ) //------------------------------------------------------------------------------ // prototypes of BLAS and SUITESPARSE_LAPACK functions //------------------------------------------------------------------------------ // For complex functions, the (void *) parameters are actually pointers to // arrays of complex values. They are prototyped here as (void *) to allow // them to be called from both C and C++. // See https://netlib.org/blas/ and https://netlib.org/lapack/ for the // definitions of the inputs/outputs of these functions. // These prototypes need to be found by UMFPACK, CHOLMOD, and SPQR, and to do // so, they need to appear in this public header to ensure the correct BLAS // library and integer size is used. However, these definitions should not // (normally) be exposed to the user application. // If a user application wishes to use these definitions, simply add // #define SUITESPARSE_BLAS_DEFINITIONS // #include "SuiteSparse_config.h" // prior to #include'ing any SuiteSparse headers (amd.h, and so on). #if defined ( SUITESPARSE_BLAS_DEFINITIONS ) #ifndef USE_FC_LEN_T # define USE_FC_LEN_T #endif #include #ifdef FC_LEN_T # define FCLEN , FC_LEN_T # define FCONE , (FC_LEN_T) 1 #else # define FCLEN # define FCONE #endif //------------------------------------------------------------------------------ // gemv: Y = alpha*A*x + beta*Y //------------------------------------------------------------------------------ void SUITESPARSE_BLAS_DGEMV ( // input: const char *trans, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const double *alpha, const double *A, const SUITESPARSE_BLAS_INT *lda, const double *X, const SUITESPARSE_BLAS_INT *incx, const double *beta, // input/output: double *Y, // input: const SUITESPARSE_BLAS_INT *incy FCLEN ) ; #define SUITESPARSE_BLAS_dgemv(trans,m,n,alpha,A,lda,X,incx,beta,Y,incy,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_DGEMV (trans, &M_blas_int, &N_blas_int, alpha, A, \ &LDA_blas_int, X, &INCX_blas_int, beta, Y, &INCY_blas_int FCONE) ; \ } \ } void SUITESPARSE_BLAS_SGEMV ( // input: const char *trans, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const float *alpha, const float *A, const SUITESPARSE_BLAS_INT *lda, const float *X, const SUITESPARSE_BLAS_INT *incx, const float *beta, // input/output: float *Y, // input: const SUITESPARSE_BLAS_INT *incy FCLEN ) ; #define SUITESPARSE_BLAS_sgemv(trans,m,n,alpha,A,lda,X,incx,beta,Y,incy,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_SGEMV (trans, &M_blas_int, &N_blas_int, alpha, A, \ &LDA_blas_int, X, &INCX_blas_int, beta, Y, &INCY_blas_int FCONE) ; \ } \ } void SUITESPARSE_BLAS_ZGEMV ( // input: const char *trans, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const void *alpha, const void *A, const SUITESPARSE_BLAS_INT *lda, const void *X, const SUITESPARSE_BLAS_INT *incx, const void *beta, // input/output: void *Y, // input: const SUITESPARSE_BLAS_INT *incy FCLEN ) ; #define SUITESPARSE_BLAS_zgemv(trans,m,n,alpha,A,lda,X,incx,beta,Y,incy,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_ZGEMV (trans, &M_blas_int, &N_blas_int, alpha, A, \ &LDA_blas_int, X, &INCX_blas_int, beta, Y, &INCY_blas_int FCONE) ; \ } \ } void SUITESPARSE_BLAS_CGEMV ( // input: const char *trans, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const void *alpha, const void *A, const SUITESPARSE_BLAS_INT *lda, const void *X, const SUITESPARSE_BLAS_INT *incx, const void *beta, // input/output: void *Y, // input: const SUITESPARSE_BLAS_INT *incy FCLEN ) ; #define SUITESPARSE_BLAS_cgemv(trans,m,n,alpha,A,lda,X,incx,beta,Y,incy,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_CGEMV (trans, &M_blas_int, &N_blas_int, alpha, A, \ &LDA_blas_int, X, &INCX_blas_int, beta, Y, &INCY_blas_int FCONE) ; \ } \ } //------------------------------------------------------------------------------ // trsv: solve Lx=b, Ux=b, L'x=b, or U'x=b //------------------------------------------------------------------------------ void SUITESPARSE_BLAS_DTRSV ( // input: const char *uplo, const char *trans, const char *diag, const SUITESPARSE_BLAS_INT *n, const double *A, const SUITESPARSE_BLAS_INT *lda, // input/output: double *X, // input: const SUITESPARSE_BLAS_INT *incx FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_dtrsv(uplo,trans,diag,n,A,lda,X,incx,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_DTRSV (uplo, trans, diag, &N_blas_int, A, \ &LDA_blas_int, X, &INCX_blas_int FCONE FCONE FCONE) ; \ } \ } void SUITESPARSE_BLAS_STRSV ( // input: const char *uplo, const char *trans, const char *diag, const SUITESPARSE_BLAS_INT *n, const float *A, const SUITESPARSE_BLAS_INT *lda, // input/output: float *X, // input: const SUITESPARSE_BLAS_INT *incx FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_strsv(uplo,trans,diag,n,A,lda,X,incx,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_STRSV (uplo, trans, diag, &N_blas_int, A, \ &LDA_blas_int, X, &INCX_blas_int FCONE FCONE FCONE) ; \ } \ } void SUITESPARSE_BLAS_ZTRSV ( // input: const char *uplo, const char *trans, const char *diag, const SUITESPARSE_BLAS_INT *n, const void *A, const SUITESPARSE_BLAS_INT *lda, // input/output: void *X, // input: const SUITESPARSE_BLAS_INT *incx FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_ztrsv(uplo,trans,diag,n,A,lda,X,incx,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_ZTRSV (uplo, trans, diag, &N_blas_int, A, \ &LDA_blas_int, X, &INCX_blas_int FCONE FCONE FCONE) ; \ } \ } void SUITESPARSE_BLAS_CTRSV ( // input: const char *uplo, const char *trans, const char *diag, const SUITESPARSE_BLAS_INT *n, const void *A, const SUITESPARSE_BLAS_INT *lda, // input/output: void *X, // input: const SUITESPARSE_BLAS_INT *incx FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_ctrsv(uplo,trans,diag,n,A,lda,X,incx,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_CTRSV (uplo, trans, diag, &N_blas_int, A, \ &LDA_blas_int, X, &INCX_blas_int FCONE FCONE FCONE) ; \ } \ } //------------------------------------------------------------------------------ // trsm: solve LX=B, UX=B, L'X=B, or U'X=B //------------------------------------------------------------------------------ void SUITESPARSE_BLAS_DTRSM ( // input: const char *side, const char *uplo, const char *transa, const char *diag, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const double *alpha, const double *A, const SUITESPARSE_BLAS_INT *lda, // input/output: double *B, // input: const SUITESPARSE_BLAS_INT *ldb FCLEN FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_dtrsm(side,uplo,transa,diag,m,n,alpha,A,lda,B,ldb,ok)\ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDB_blas_int, ldb, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_DTRSM (side, uplo, transa, diag, &M_blas_int, \ &N_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int FCONE FCONE FCONE FCONE) ; \ } \ } void SUITESPARSE_BLAS_STRSM ( // input: const char *side, const char *uplo, const char *transa, const char *diag, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const float *alpha, const float *A, const SUITESPARSE_BLAS_INT *lda, // input/output: float *B, // input: const SUITESPARSE_BLAS_INT *ldb FCLEN FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_strsm(side,uplo,transa,diag,m,n,alpha,A,lda,B,ldb,ok)\ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDB_blas_int, ldb, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_STRSM (side, uplo, transa, diag, &M_blas_int, \ &N_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int FCONE FCONE FCONE FCONE) ; \ } \ } void SUITESPARSE_BLAS_ZTRSM ( // input: const char *side, const char *uplo, const char *transa, const char *diag, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const void *alpha, const void *A, const SUITESPARSE_BLAS_INT *lda, // input/output: void *B, // input: const SUITESPARSE_BLAS_INT *ldb FCLEN FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_ztrsm(side,uplo,transa,diag,m,n,alpha,A,lda,B,ldb,ok)\ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDB_blas_int, ldb, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_ZTRSM (side, uplo, transa, diag, &M_blas_int, \ &N_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int FCONE FCONE FCONE FCONE) ; \ } \ } void SUITESPARSE_BLAS_CTRSM ( // input: const char *side, const char *uplo, const char *transa, const char *diag, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const void *alpha, const void *A, const SUITESPARSE_BLAS_INT *lda, // input/output: void *B, // input: const SUITESPARSE_BLAS_INT *ldb FCLEN FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_ctrsm(side,uplo,transa,diag,m,n,alpha,A,lda,B,ldb,ok)\ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDB_blas_int, ldb, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_CTRSM (side, uplo, transa, diag, &M_blas_int, \ &N_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int FCONE FCONE FCONE FCONE) ; \ } \ } //------------------------------------------------------------------------------ // gemm: C = alpha*A*B + beta*C //------------------------------------------------------------------------------ void SUITESPARSE_BLAS_DGEMM ( // input: const char *transa, const char *transb, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const SUITESPARSE_BLAS_INT *k, const double *alpha, const double *A, const SUITESPARSE_BLAS_INT *lda, const double *B, const SUITESPARSE_BLAS_INT *ldb, const double *beta, // input/output: double *C, // input: const SUITESPARSE_BLAS_INT *ldc FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_dgemm(transa,transb,m,n,k,alpha,A,lda,B,ldb,beta, \ C,ldc,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDB_blas_int, ldb, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_DGEMM (transa, transb, &M_blas_int, &N_blas_int, \ &K_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int, beta, C, \ &LDC_blas_int FCONE FCONE) ; \ } \ } void SUITESPARSE_BLAS_SGEMM ( // input: const char *transa, const char *transb, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const SUITESPARSE_BLAS_INT *k, const float *alpha, const float *A, const SUITESPARSE_BLAS_INT *lda, const float *B, const SUITESPARSE_BLAS_INT *ldb, const float *beta, // input/output: float *C, // input: const SUITESPARSE_BLAS_INT *ldc FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_sgemm(transa,transb,m,n,k,alpha,A,lda,B,ldb,beta, \ C,ldc,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDB_blas_int, ldb, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_SGEMM (transa, transb, &M_blas_int, &N_blas_int, \ &K_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int, beta, C, \ &LDC_blas_int FCONE FCONE) ; \ } \ } void SUITESPARSE_BLAS_ZGEMM ( // input: const char *transa, const char *transb, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const SUITESPARSE_BLAS_INT *k, const void *alpha, const void *A, const SUITESPARSE_BLAS_INT *lda, const void *B, const SUITESPARSE_BLAS_INT *ldb, const void *beta, // input/output: void *C, // input: const SUITESPARSE_BLAS_INT *ldc FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_zgemm(transa,transb,m,n,k,alpha,A,lda,B,ldb,beta, \ C,ldc,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDB_blas_int, ldb, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_ZGEMM (transa, transb, &M_blas_int, &N_blas_int, \ &K_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int, beta, C, \ &LDC_blas_int FCONE FCONE) ; \ } \ } void SUITESPARSE_BLAS_CGEMM ( // input: const char *transa, const char *transb, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const SUITESPARSE_BLAS_INT *k, const void *alpha, const void *A, const SUITESPARSE_BLAS_INT *lda, const void *B, const SUITESPARSE_BLAS_INT *ldb, const void *beta, // input/output: void *C, // input: const SUITESPARSE_BLAS_INT *ldc FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_cgemm(transa,transb,m,n,k,alpha,A,lda,B,ldb,beta, \ C,ldc,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDB_blas_int, ldb, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_CGEMM (transa, transb, &M_blas_int, &N_blas_int, \ &K_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int, beta, C, \ &LDC_blas_int FCONE FCONE) ; \ } \ } //------------------------------------------------------------------------------ // syrk/herk: C = alpha*A*A' + beta*C ; or C = alpha*A'*A + beta*C //------------------------------------------------------------------------------ void SUITESPARSE_BLAS_DSYRK ( // input: const char *uplo, const char *trans, const SUITESPARSE_BLAS_INT *n, const SUITESPARSE_BLAS_INT *k, const double *alpha, const double *A, const SUITESPARSE_BLAS_INT *lda, const double *beta, // input/output: double *C, // input: const SUITESPARSE_BLAS_INT *ldc FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_dsyrk(uplo,trans,n,k,alpha,A,lda,beta,C,ldc,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_DSYRK (uplo, trans, &N_blas_int, &K_blas_int, alpha, \ A, &LDA_blas_int, beta, C, &LDC_blas_int FCONE FCONE) ; \ } \ } void SUITESPARSE_BLAS_SSYRK ( // input: const char *uplo, const char *trans, const SUITESPARSE_BLAS_INT *n, const SUITESPARSE_BLAS_INT *k, const float *alpha, const float *A, const SUITESPARSE_BLAS_INT *lda, const float *beta, // input/output: float *C, // input: const SUITESPARSE_BLAS_INT *ldc FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_ssyrk(uplo,trans,n,k,alpha,A,lda,beta,C,ldc,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_SSYRK (uplo, trans, &N_blas_int, &K_blas_int, alpha, \ A, &LDA_blas_int, beta, C, &LDC_blas_int FCONE FCONE) ; \ } \ } void SUITESPARSE_BLAS_ZHERK ( // input: const char *uplo, const char *trans, const SUITESPARSE_BLAS_INT *n, const SUITESPARSE_BLAS_INT *k, const void *alpha, const void *A, const SUITESPARSE_BLAS_INT *lda, const void *beta, // input/output: void *C, // input: const SUITESPARSE_BLAS_INT *ldc FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_zherk(uplo,trans,n,k,alpha,A,lda,beta,C,ldc,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_ZHERK (uplo, trans, &N_blas_int, &K_blas_int, alpha, \ A, &LDA_blas_int, beta, C, &LDC_blas_int FCONE FCONE) ; \ } \ } void SUITESPARSE_BLAS_CHERK ( // input: const char *uplo, const char *trans, const SUITESPARSE_BLAS_INT *n, const SUITESPARSE_BLAS_INT *k, const void *alpha, const void *A, const SUITESPARSE_BLAS_INT *lda, const void *beta, // input/output: void *C, // input: const SUITESPARSE_BLAS_INT *ldc FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_cherk(uplo,trans,n,k,alpha,A,lda,beta,C,ldc,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_CHERK (uplo, trans, &N_blas_int, &K_blas_int, alpha, \ A, &LDA_blas_int, beta, C, &LDC_blas_int FCONE FCONE) ; \ } \ } //------------------------------------------------------------------------------ // potrf: Cholesky factorization //------------------------------------------------------------------------------ void SUITESPARSE_LAPACK_DPOTRF ( // input: const char *uplo, const SUITESPARSE_BLAS_INT *n, // input/output: double *A, // input: const SUITESPARSE_BLAS_INT *lda, // output: SUITESPARSE_BLAS_INT *info FCLEN ) ; #define SUITESPARSE_LAPACK_dpotrf(uplo,n,A,lda,info,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ info = 1 ; \ if (ok) \ { \ SUITESPARSE_BLAS_INT LAPACK_Info = -999 ; \ SUITESPARSE_LAPACK_DPOTRF (uplo, &N_blas_int, A, &LDA_blas_int, \ &LAPACK_Info FCONE) ; \ info = (Int) LAPACK_Info ; \ } \ } void SUITESPARSE_LAPACK_SPOTRF ( // input: const char *uplo, const SUITESPARSE_BLAS_INT *n, // input/output: float *A, // input: const SUITESPARSE_BLAS_INT *lda, // output: SUITESPARSE_BLAS_INT *info FCLEN ) ; #define SUITESPARSE_LAPACK_spotrf(uplo,n,A,lda,info,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ info = 1 ; \ if (ok) \ { \ SUITESPARSE_BLAS_INT LAPACK_Info = -999 ; \ SUITESPARSE_LAPACK_SPOTRF (uplo, &N_blas_int, A, &LDA_blas_int, \ &LAPACK_Info FCONE) ; \ info = (Int) LAPACK_Info ; \ } \ } void SUITESPARSE_LAPACK_ZPOTRF ( // input: const char *uplo, const SUITESPARSE_BLAS_INT *n, // input/output: void *A, // input: const SUITESPARSE_BLAS_INT *lda, // output: SUITESPARSE_BLAS_INT *info FCLEN ) ; #define SUITESPARSE_LAPACK_zpotrf(uplo,n,A,lda,info,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ info = 1 ; \ if (ok) \ { \ SUITESPARSE_BLAS_INT LAPACK_Info = -999 ; \ SUITESPARSE_LAPACK_ZPOTRF (uplo, &N_blas_int, A, &LDA_blas_int, \ &LAPACK_Info FCONE) ; \ info = LAPACK_Info ; \ } \ } void SUITESPARSE_LAPACK_CPOTRF ( // input: const char *uplo, const SUITESPARSE_BLAS_INT *n, // input/output: void *A, // input: const SUITESPARSE_BLAS_INT *lda, // output: SUITESPARSE_BLAS_INT *info FCLEN ) ; #define SUITESPARSE_LAPACK_cpotrf(uplo,n,A,lda,info,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ info = 1 ; \ if (ok) \ { \ SUITESPARSE_BLAS_INT LAPACK_Info = -999 ; \ SUITESPARSE_LAPACK_CPOTRF (uplo, &N_blas_int, A, &LDA_blas_int, \ &LAPACK_Info FCONE) ; \ info = LAPACK_Info ; \ } \ } //------------------------------------------------------------------------------ // scal: Y = alpha*Y //------------------------------------------------------------------------------ void SUITESPARSE_BLAS_DSCAL ( // input: const SUITESPARSE_BLAS_INT *n, const double *alpha, // input/output: double *Y, // input: const SUITESPARSE_BLAS_INT *incy ) ; #define SUITESPARSE_BLAS_dscal(n,alpha,Y,incy,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_DSCAL (&N_blas_int, alpha, Y, &INCY_blas_int) ; \ } \ } void SUITESPARSE_BLAS_SSCAL ( // input: const SUITESPARSE_BLAS_INT *n, const float *alpha, // input/output: float *Y, // input: const SUITESPARSE_BLAS_INT *incy ) ; #define SUITESPARSE_BLAS_sscal(n,alpha,Y,incy,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_SSCAL (&N_blas_int, alpha, Y, &INCY_blas_int) ; \ } \ } void SUITESPARSE_BLAS_ZSCAL ( // input: const SUITESPARSE_BLAS_INT *n, const void *alpha, // input/output: void *Y, // input: const SUITESPARSE_BLAS_INT *incy ) ; #define SUITESPARSE_BLAS_zscal(n,alpha,Y,incy,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_ZSCAL (&N_blas_int, alpha, Y, &INCY_blas_int) ; \ } \ } void SUITESPARSE_BLAS_CSCAL ( // input: const SUITESPARSE_BLAS_INT *n, const void *alpha, // input/output: void *Y, // input: const SUITESPARSE_BLAS_INT *incy ) ; #define SUITESPARSE_BLAS_cscal(n,alpha,Y,incy,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_CSCAL (&N_blas_int, alpha, Y, &INCY_blas_int) ; \ } \ } //------------------------------------------------------------------------------ // ger/geru: A = alpha*x*y' + A //------------------------------------------------------------------------------ void SUITESPARSE_BLAS_DGER ( // input: const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const double *alpha, const double *X, const SUITESPARSE_BLAS_INT *incx, const double *Y, const SUITESPARSE_BLAS_INT *incy, // input/output: double *A, // input: const SUITESPARSE_BLAS_INT *lda ) ; #define SUITESPARSE_BLAS_dger(m,n,alpha,X,incx,Y,incy,A,lda,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_DGER (&M_blas_int, &N_blas_int, alpha, X, \ &INCX_blas_int, Y, &INCY_blas_int, A, &LDA_blas_int) ; \ } \ } void SUITESPARSE_BLAS_SGER ( // input: const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const float *alpha, const float *X, const SUITESPARSE_BLAS_INT *incx, const float *Y, const SUITESPARSE_BLAS_INT *incy, // input/output: float *A, // input: const SUITESPARSE_BLAS_INT *lda ) ; #define SUITESPARSE_BLAS_sger(m,n,alpha,X,incx,Y,incy,A,lda,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_SGER (&M_blas_int, &N_blas_int, alpha, X, \ &INCX_blas_int, Y, &INCY_blas_int, A, &LDA_blas_int) ; \ } \ } void SUITESPARSE_BLAS_ZGERU ( // input: const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const void *alpha, const void *X, const SUITESPARSE_BLAS_INT *incx, const void *Y, const SUITESPARSE_BLAS_INT *incy, // input/output: void *A, // input: const SUITESPARSE_BLAS_INT *lda ) ; #define SUITESPARSE_BLAS_zgeru(m,n,alpha,X,incx,Y,incy,A,lda,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_ZGERU (&M_blas_int, &N_blas_int, alpha, X, \ &INCX_blas_int, Y, &INCY_blas_int, A, &LDA_blas_int) ; \ } \ } void SUITESPARSE_BLAS_CGERU ( // input: const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const void *alpha, const void *X, const SUITESPARSE_BLAS_INT *incx, const void *Y, const SUITESPARSE_BLAS_INT *incy, // input/output: void *A, // input: const SUITESPARSE_BLAS_INT *lda ) ; #define SUITESPARSE_BLAS_cgeru(m,n,alpha,X,incx,Y,incy,A,lda,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ; \ if (ok) \ { \ SUITESPARSE_BLAS_CGERU (&M_blas_int, &N_blas_int, alpha, X, \ &INCX_blas_int, Y, &INCY_blas_int, A, &LDA_blas_int) ; \ } \ } //------------------------------------------------------------------------------ // larft: T = block Householder factor //------------------------------------------------------------------------------ void SUITESPARSE_LAPACK_DLARFT ( // input: const char *direct, const char *storev, const SUITESPARSE_BLAS_INT *n, const SUITESPARSE_BLAS_INT *k, const double *V, const SUITESPARSE_BLAS_INT *ldv, const double *Tau, // output: double *T, // input: const SUITESPARSE_BLAS_INT *ldt FCLEN FCLEN ) ; #define SUITESPARSE_LAPACK_dlarft(direct,storev,n,k,V,ldv,Tau,T,ldt,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDV_blas_int, ldv, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDT_blas_int, ldt, ok) ; \ if (ok) \ { \ SUITESPARSE_LAPACK_DLARFT (direct, storev, &N_blas_int, &K_blas_int, \ V, &LDV_blas_int, Tau, T, &LDT_blas_int FCONE FCONE) ; \ } \ } void SUITESPARSE_LAPACK_SLARFT ( // input: const char *direct, const char *storev, const SUITESPARSE_BLAS_INT *n, const SUITESPARSE_BLAS_INT *k, const float *V, const SUITESPARSE_BLAS_INT *ldv, const float *Tau, // output: float *T, // input: const SUITESPARSE_BLAS_INT *ldt FCLEN FCLEN ) ; #define SUITESPARSE_LAPACK_slarft(direct,storev,n,k,V,ldv,Tau,T,ldt,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDV_blas_int, ldv, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDT_blas_int, ldt, ok) ; \ if (ok) \ { \ SUITESPARSE_LAPACK_SLARFT (direct, storev, &N_blas_int, &K_blas_int, \ V, &LDV_blas_int, Tau, T, &LDT_blas_int FCONE FCONE) ; \ } \ } void SUITESPARSE_LAPACK_ZLARFT ( // input: const char *direct, const char *storev, const SUITESPARSE_BLAS_INT *n, const SUITESPARSE_BLAS_INT *k, const void *V, const SUITESPARSE_BLAS_INT *ldv, const void *Tau, // output: void *T, // input: const SUITESPARSE_BLAS_INT *ldt FCLEN FCLEN ) ; #define SUITESPARSE_LAPACK_zlarft(direct,storev,n,k,V,ldv,Tau,T,ldt,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDV_blas_int, ldv, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDT_blas_int, ldt, ok) ; \ if (ok) \ { \ SUITESPARSE_LAPACK_ZLARFT (direct, storev, &N_blas_int, &K_blas_int, \ V, &LDV_blas_int, Tau, T, &LDT_blas_int FCONE FCONE) ; \ } \ } void SUITESPARSE_LAPACK_CLARFT ( // input: const char *direct, const char *storev, const SUITESPARSE_BLAS_INT *n, const SUITESPARSE_BLAS_INT *k, const void *V, const SUITESPARSE_BLAS_INT *ldv, const void *Tau, // output: void *T, // input: const SUITESPARSE_BLAS_INT *ldt FCLEN FCLEN ) ; #define SUITESPARSE_LAPACK_clarft(direct,storev,n,k,V,ldv,Tau,T,ldt,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDV_blas_int, ldv, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDT_blas_int, ldt, ok) ; \ if (ok) \ { \ SUITESPARSE_LAPACK_CLARFT (direct, storev, &N_blas_int, &K_blas_int, \ V, &LDV_blas_int, Tau, T, &LDT_blas_int FCONE FCONE) ; \ } \ } //------------------------------------------------------------------------------ // larfb: apply block Householder reflector //------------------------------------------------------------------------------ void SUITESPARSE_LAPACK_DLARFB ( // input: const char *side, const char *trans, const char *direct, const char *storev, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const SUITESPARSE_BLAS_INT *k, const double *V, const SUITESPARSE_BLAS_INT *ldv, const double *T, const SUITESPARSE_BLAS_INT *ldt, // input/output: double *C, // input: const SUITESPARSE_BLAS_INT *ldc, // workspace: double *Work, // input: const SUITESPARSE_BLAS_INT *ldwork FCLEN FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_LAPACK_dlarfb(side,trans,direct,storev,m,n,k,V,ldv,T,ldt, \ C,ldc,Work,ldwork,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDV_blas_int, ldv, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDT_blas_int, ldt, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDWORK_blas_int, ldwork, ok) ; \ if (ok) \ { \ SUITESPARSE_LAPACK_DLARFB (side, trans, direct, storev, &M_blas_int, \ &N_blas_int, &K_blas_int, V, &LDV_blas_int, T, &LDT_blas_int, C, \ &LDC_blas_int, Work, &LDWORK_blas_int FCONE FCONE FCONE FCONE) ; \ } \ } void SUITESPARSE_LAPACK_SLARFB ( // input: const char *side, const char *trans, const char *direct, const char *storev, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const SUITESPARSE_BLAS_INT *k, const float *V, const SUITESPARSE_BLAS_INT *ldv, const float *T, const SUITESPARSE_BLAS_INT *ldt, // input/output: float *C, // input: const SUITESPARSE_BLAS_INT *ldc, // workspace: float *Work, // input: const SUITESPARSE_BLAS_INT *ldwork FCLEN FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_LAPACK_slarfb(side,trans,direct,storev,m,n,k,V,ldv,T,ldt, \ C,ldc,Work,ldwork,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDV_blas_int, ldv, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDT_blas_int, ldt, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDWORK_blas_int, ldwork, ok) ; \ if (ok) \ { \ SUITESPARSE_LAPACK_SLARFB (side, trans, direct, storev, &M_blas_int, \ &N_blas_int, &K_blas_int, V, &LDV_blas_int, T, &LDT_blas_int, C, \ &LDC_blas_int, Work, &LDWORK_blas_int FCONE FCONE FCONE FCONE) ; \ } \ } void SUITESPARSE_LAPACK_ZLARFB ( // input: const char *side, const char *trans, const char *direct, const char *storev, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const SUITESPARSE_BLAS_INT *k, const void *V, const SUITESPARSE_BLAS_INT *ldv, const void *T, const SUITESPARSE_BLAS_INT *ldt, // input/output: void *C, // input: const SUITESPARSE_BLAS_INT *ldc, // workspace: void *Work, // input: const SUITESPARSE_BLAS_INT *ldwork FCLEN FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_LAPACK_zlarfb(side,trans,direct,storev,m,n,k,V,ldv,T,ldt, \ C,ldc,Work,ldwork,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDV_blas_int, ldv, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDT_blas_int, ldt, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDWORK_blas_int, ldwork, ok) ; \ if (ok) \ { \ SUITESPARSE_LAPACK_ZLARFB (side, trans, direct, storev, &M_blas_int, \ &N_blas_int, &K_blas_int, V, &LDV_blas_int, T, &LDT_blas_int, C, \ &LDC_blas_int, Work, &LDWORK_blas_int FCONE FCONE FCONE FCONE) ; \ } \ } void SUITESPARSE_LAPACK_CLARFB ( // input: const char *side, const char *trans, const char *direct, const char *storev, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const SUITESPARSE_BLAS_INT *k, const void *V, const SUITESPARSE_BLAS_INT *ldv, const void *T, const SUITESPARSE_BLAS_INT *ldt, // input/output: void *C, // input: const SUITESPARSE_BLAS_INT *ldc, // workspace: void *Work, // input: const SUITESPARSE_BLAS_INT *ldwork FCLEN FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_LAPACK_clarfb(side,trans,direct,storev,m,n,k,V,ldv,T,ldt, \ C,ldc,Work,ldwork,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDV_blas_int, ldv, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDT_blas_int, ldt, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDWORK_blas_int, ldwork, ok) ; \ if (ok) \ { \ SUITESPARSE_LAPACK_CLARFB (side, trans, direct, storev, &M_blas_int, \ &N_blas_int, &K_blas_int, V, &LDV_blas_int, T, &LDT_blas_int, C, \ &LDC_blas_int, Work, &LDWORK_blas_int FCONE FCONE FCONE FCONE) ; \ } \ } //------------------------------------------------------------------------------ // nrm2: vector 2-norm //------------------------------------------------------------------------------ double SUITESPARSE_BLAS_DNRM2 ( // input: const SUITESPARSE_BLAS_INT *n, const double *X, const SUITESPARSE_BLAS_INT *incx ) ; #define SUITESPARSE_BLAS_dnrm2(result,n,X,incx,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ result = 0 ; \ if (ok) \ { \ result = SUITESPARSE_BLAS_DNRM2 (&N_blas_int, X, &INCX_blas_int) ; \ } \ } float SUITESPARSE_BLAS_SNRM2 ( // input: const SUITESPARSE_BLAS_INT *n, const float *X, const SUITESPARSE_BLAS_INT *incx ) ; #define SUITESPARSE_BLAS_snrm2(result,n,X,incx,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ result = 0 ; \ if (ok) \ { \ result = SUITESPARSE_BLAS_SNRM2 (&N_blas_int, X, &INCX_blas_int) ; \ } \ } double SUITESPARSE_BLAS_DZNRM2 ( // input: const SUITESPARSE_BLAS_INT *n, const void *X, const SUITESPARSE_BLAS_INT *incx ) ; #define SUITESPARSE_BLAS_dznrm2(result,n,X,incx,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ result = 0 ; \ if (ok) \ { \ result = SUITESPARSE_BLAS_DZNRM2 (&N_blas_int, X, &INCX_blas_int) ; \ } \ } float SUITESPARSE_BLAS_SCNRM2 ( // input: const SUITESPARSE_BLAS_INT *n, const void *X, const SUITESPARSE_BLAS_INT *incx ) ; #define SUITESPARSE_BLAS_scnrm2(result,n,X,incx,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ result = 0 ; \ if (ok) \ { \ result = SUITESPARSE_BLAS_SCNRM2 (&N_blas_int, X, &INCX_blas_int) ; \ } \ } //------------------------------------------------------------------------------ // larfg: generate Householder reflector //------------------------------------------------------------------------------ void SUITESPARSE_LAPACK_DLARFG ( // input: const SUITESPARSE_BLAS_INT *n, // input/output: double *alpha, double *X, // input: const SUITESPARSE_BLAS_INT *incx, // output: double *tau ) ; #define SUITESPARSE_LAPACK_dlarfg(n,alpha,X,incx,tau,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ if (ok) \ { \ SUITESPARSE_LAPACK_DLARFG (&N_blas_int, alpha, X, &INCX_blas_int, \ tau) ; \ } \ } void SUITESPARSE_LAPACK_SLARFG ( // input: const SUITESPARSE_BLAS_INT *n, // input/output: float *alpha, float *X, // input: const SUITESPARSE_BLAS_INT *incx, // output: float *tau ) ; #define SUITESPARSE_LAPACK_slarfg(n,alpha,X,incx,tau,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ if (ok) \ { \ SUITESPARSE_LAPACK_SLARFG (&N_blas_int, alpha, X, &INCX_blas_int, \ tau) ; \ } \ } void SUITESPARSE_LAPACK_ZLARFG ( // input: const SUITESPARSE_BLAS_INT *n, // input/output: void *alpha, void *X, // input: const SUITESPARSE_BLAS_INT *incx, // output: void *tau ) ; #define SUITESPARSE_LAPACK_zlarfg(n,alpha,X,incx,tau,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ if (ok) \ { \ SUITESPARSE_LAPACK_ZLARFG (&N_blas_int, alpha, X, &INCX_blas_int, \ tau) ; \ } \ } void SUITESPARSE_LAPACK_CLARFG ( // input: const SUITESPARSE_BLAS_INT *n, // input/output: void *alpha, void *X, // input: const SUITESPARSE_BLAS_INT *incx, // output: void *tau ) ; #define SUITESPARSE_LAPACK_clarfg(n,alpha,X,incx,tau,ok) \ { \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ; \ if (ok) \ { \ SUITESPARSE_LAPACK_CLARFG (&N_blas_int, alpha, X, &INCX_blas_int, \ tau) ; \ } \ } //------------------------------------------------------------------------------ // larf: apply Householder reflector //------------------------------------------------------------------------------ void SUITESPARSE_LAPACK_DLARF ( // input: const char *side, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const double *V, const SUITESPARSE_BLAS_INT *incv, const double *tau, // input/output: double *C, // input: const SUITESPARSE_BLAS_INT *ldc, // workspace: double *Work FCLEN ) ; #define SUITESPARSE_LAPACK_dlarf(side,m,n,V,incv,tau,C,ldc,Work,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCV_blas_int, incv, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ; \ if (ok) \ { \ SUITESPARSE_LAPACK_DLARF (side, &M_blas_int, &N_blas_int, V, \ &INCV_blas_int, tau, C, &LDC_blas_int, Work FCONE) ; \ } \ } void SUITESPARSE_LAPACK_SLARF ( // input: const char *side, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const float *V, const SUITESPARSE_BLAS_INT *incv, const float *tau, // input/output: float *C, // input: const SUITESPARSE_BLAS_INT *ldc, // workspace: float *Work FCLEN ) ; #define SUITESPARSE_LAPACK_slarf(side,m,n,V,incv,tau,C,ldc,Work,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCV_blas_int, incv, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ; \ if (ok) \ { \ SUITESPARSE_LAPACK_SLARF (side, &M_blas_int, &N_blas_int, V, \ &INCV_blas_int, tau, C, &LDC_blas_int, Work FCONE) ; \ } \ } void SUITESPARSE_LAPACK_ZLARF ( // input: const char *side, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const void *V, const SUITESPARSE_BLAS_INT *incv, const void *tau, // input/output: void *C, // input: const SUITESPARSE_BLAS_INT *ldc, // workspace: void *Work FCLEN ) ; #define SUITESPARSE_LAPACK_zlarf(side,m,n,V,incv,tau,C,ldc,Work,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCV_blas_int, incv, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ; \ if (ok) \ { \ SUITESPARSE_LAPACK_ZLARF (side, &M_blas_int, &N_blas_int, V, \ &INCV_blas_int, tau, C, &LDC_blas_int, Work FCONE) ; \ } \ } void SUITESPARSE_LAPACK_CLARF ( // input: const char *side, const SUITESPARSE_BLAS_INT *m, const SUITESPARSE_BLAS_INT *n, const void *V, const SUITESPARSE_BLAS_INT *incv, const void *tau, // input/output: void *C, // input: const SUITESPARSE_BLAS_INT *ldc, // workspace: void *Work FCLEN ) ; #define SUITESPARSE_LAPACK_clarf(side,m,n,V,incv,tau,C,ldc,Work,ok) \ { \ SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ; \ SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ; \ SUITESPARSE_TO_BLAS_INT (INCV_blas_int, incv, ok) ; \ SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ; \ if (ok) \ { \ SUITESPARSE_LAPACK_CLARF (side, &M_blas_int, &N_blas_int, V, \ &INCV_blas_int, tau, C, &LDC_blas_int, Work FCONE) ; \ } \ } #endif //------------------------------------------------------------------------------ // SuiteSparse_BLAS_library: return name of BLAS library found //------------------------------------------------------------------------------ // Returns the name of the BLAS library found by SuiteSparse_config const char *SuiteSparse_BLAS_library ( void ) ; //------------------------------------------------------------------------------ // SuiteSparse_BLAS_integer_size: return sizeof (SUITESPARSE_BLAS_INT) //------------------------------------------------------------------------------ size_t SuiteSparse_BLAS_integer_size ( void ) ; #ifdef __cplusplus } #endif #endif Matrix/src/SuiteSparse/SuiteSparse_config/Makefile0000644000175100001440000000041714576344042022041 0ustar hornikuserssources = SuiteSparse_config.c objects = $(sources:.c=.o) archive = SuiteSparse_config.a all : $(archive) $(archive) : $(objects) rm -f $@ $(AR) -cr $@ $(objects) $(RANLIB) $@ .c.o : $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $*.o clean : @rm -f $(objects) $(archive) Matrix/src/SuiteSparse/SuiteSparse_config/SuiteSparse_config.c0000644000175100001440000006001314561103552024330 0ustar hornikusers//------------------------------------------------------------------------------ // SuiteSparse_config/SuiteSparse_config.c: common utilites for SuiteSparse //------------------------------------------------------------------------------ // SuiteSparse_config, Copyright (c) 2012-2023, Timothy A. Davis. // All Rights Reserved. // SPDX-License-Identifier: BSD-3-clause //------------------------------------------------------------------------------ /* SuiteSparse configuration : memory manager and printf functions. */ #include "SuiteSparse_config.h" /* -------------------------------------------------------------------------- */ /* SuiteSparse_config : a static struct */ /* -------------------------------------------------------------------------- */ /* The SuiteSparse_config struct is indirectly available to all SuiteSparse functions and to all applications that use those functions. In v6.x and earlier, it was globally visible, but it is now hidden and accessible only by functions in this file (SuiteSparse v7.0.0 and later). It must be modified with care, particularly in a multithreaded context. Normally, the application will initialize this object once, via SuiteSparse_start, possibily followed by application-specific modifications if the applications wants to use alternative memory manager functions. The user can redefine these pointers at run-time to change the memory manager and printf function used by SuiteSparse. If -DNMALLOC is defined at compile-time, then no memory-manager is specified. You must define them at run-time, after calling SuiteSparse_start. If -DPRINT is defined a compile time, then printf is disabled, and SuiteSparse will not use printf. */ struct SuiteSparse_config_struct { void *(*malloc_func) (size_t) ; // pointer to malloc void *(*calloc_func) (size_t, size_t) ; // pointer to calloc void *(*realloc_func) (void *, size_t) ; // pointer to realloc void (*free_func) (void *) ; // pointer to free int (*printf_func) (const char *, ...) ; // pointer to printf double (*hypot_func) (double, double) ; // pointer to hypot int (*divcomplex_func) (double, double, double, double, double *, double *); } ; static struct SuiteSparse_config_struct SuiteSparse_config = { /* memory management functions */ #ifndef NMALLOC #ifdef MATLAB_MEX_FILE /* MATLAB mexFunction: */ mxMalloc, mxCalloc, mxRealloc, mxFree, #else /* standard ANSI C: */ malloc, calloc, realloc, free, #endif #else /* no memory manager defined; you must define one at run-time: */ NULL, NULL, NULL, NULL, #endif /* printf function */ #ifndef NPRINT #ifdef MATLAB_MEX_FILE /* MATLAB mexFunction: */ mexPrintf, #else #include Rprintf, #endif #else /* printf is disabled */ NULL, #endif hypot, // was SuiteSparse_hypot in v5 and earlier SuiteSparse_divcomplex } ; //------------------------------------------------------------------------------ // SuiteSparse_config_*_get methods //------------------------------------------------------------------------------ // Methods that return the contents of the SuiteSparse_config struct. void *(*SuiteSparse_config_malloc_func_get (void)) (size_t) { return (SuiteSparse_config.malloc_func) ; } void *(*SuiteSparse_config_calloc_func_get (void)) (size_t, size_t) { return (SuiteSparse_config.calloc_func) ; } void *(*SuiteSparse_config_realloc_func_get (void)) (void *, size_t) { return (SuiteSparse_config.realloc_func) ; } void (*SuiteSparse_config_free_func_get (void)) (void *) { return (SuiteSparse_config.free_func) ; } int (*SuiteSparse_config_printf_func_get (void)) (const char *, ...) { return (SuiteSparse_config.printf_func) ; } double (*SuiteSparse_config_hypot_func_get (void)) (double, double) { return (SuiteSparse_config.hypot_func) ; } int (*SuiteSparse_config_divcomplex_func_get (void)) (double, double, double, double, double *, double *) { return (SuiteSparse_config.divcomplex_func) ; } //------------------------------------------------------------------------------ // SuiteSparse_config_*_set methods //------------------------------------------------------------------------------ // Methods that set the contents of the SuiteSparse_config struct. void SuiteSparse_config_malloc_func_set (void *(*malloc_func) (size_t)) { SuiteSparse_config.malloc_func = malloc_func ; } void SuiteSparse_config_calloc_func_set (void *(*calloc_func) (size_t, size_t)) { SuiteSparse_config.calloc_func = calloc_func ; } void SuiteSparse_config_realloc_func_set (void *(*realloc_func) (void *, size_t)) { SuiteSparse_config.realloc_func = realloc_func ; } void SuiteSparse_config_free_func_set (void (*free_func) (void *)) { SuiteSparse_config.free_func = free_func ; } void SuiteSparse_config_printf_func_set (int (*printf_func) (const char *, ...)) { SuiteSparse_config.printf_func = printf_func ; } void SuiteSparse_config_hypot_func_set (double (*hypot_func) (double, double)) { SuiteSparse_config.hypot_func = hypot_func ; } void SuiteSparse_config_divcomplex_func_set (int (*divcomplex_func) (double, double, double, double, double *, double *)) { SuiteSparse_config.divcomplex_func = divcomplex_func ; } //------------------------------------------------------------------------------ // SuiteSparse_config_*_call methods //------------------------------------------------------------------------------ // Methods that directly call the functions in the SuiteSparse_config struct. // Note that there is no wrapper for the printf_func. void *SuiteSparse_config_malloc (size_t s) { return (SuiteSparse_config.malloc_func (s)) ; } void *SuiteSparse_config_calloc (size_t n, size_t s) { return (SuiteSparse_config.calloc_func (n, s)) ; } void *SuiteSparse_config_realloc (void *p, size_t s) { return (SuiteSparse_config.realloc_func (p, s)) ; } void SuiteSparse_config_free (void *p) { SuiteSparse_config.free_func (p) ; } double SuiteSparse_config_hypot (double x, double y) { return (SuiteSparse_config.hypot_func (x, y)) ; } int SuiteSparse_config_divcomplex ( double xr, double xi, double yr, double yi, double *zr, double *zi ) { return (SuiteSparse_config.divcomplex_func (xr, xi, yr, yi, zr, zi)) ; } /* -------------------------------------------------------------------------- */ /* SuiteSparse_start */ /* -------------------------------------------------------------------------- */ /* All applications that use SuiteSparse should call SuiteSparse_start prior to using any SuiteSparse function. Only a single thread should call this function, in a multithreaded application. Currently, this function is optional, since all this function currently does is to set the four memory function pointers to NULL (which tells SuiteSparse to use the default functions). In a multi- threaded application, only a single thread should call this function. Future releases of SuiteSparse might enforce a requirement that SuiteSparse_start be called prior to calling any SuiteSparse function. */ void SuiteSparse_start ( void ) { /* memory management functions */ #ifndef NMALLOC #ifdef MATLAB_MEX_FILE /* MATLAB mexFunction: */ SuiteSparse_config.malloc_func = mxMalloc ; SuiteSparse_config.calloc_func = mxCalloc ; SuiteSparse_config.realloc_func = mxRealloc ; SuiteSparse_config.free_func = mxFree ; #else /* standard ANSI C: */ SuiteSparse_config.malloc_func = malloc ; SuiteSparse_config.calloc_func = calloc ; SuiteSparse_config.realloc_func = realloc ; SuiteSparse_config.free_func = free ; #endif #else /* no memory manager defined; you must define one after calling SuiteSparse_start */ SuiteSparse_config.malloc_func = NULL ; SuiteSparse_config.calloc_func = NULL ; SuiteSparse_config.realloc_func = NULL ; SuiteSparse_config.free_func = NULL ; #endif /* printf function */ #ifndef NPRINT #ifdef MATLAB_MEX_FILE /* MATLAB mexFunction: */ SuiteSparse_config.printf_func = mexPrintf ; #else /* standard ANSI C: */ SuiteSparse_config.printf_func = printf ; #endif #else /* printf is disabled */ SuiteSparse_config.printf_func = NULL ; #endif /* math functions */ SuiteSparse_config.hypot_func = hypot ; // was SuiteSparse_hypot in v5 SuiteSparse_config.divcomplex_func = SuiteSparse_divcomplex ; } /* -------------------------------------------------------------------------- */ /* SuiteSparse_finish */ /* -------------------------------------------------------------------------- */ /* This currently does nothing, but in the future, applications should call SuiteSparse_start before calling any SuiteSparse function, and then SuiteSparse_finish after calling the last SuiteSparse function, just before exiting. In a multithreaded application, only a single thread should call this function. Future releases of SuiteSparse might use this function for any SuiteSparse-wide cleanup operations or finalization of statistics. */ void SuiteSparse_finish ( void ) { /* do nothing */ ; } /* -------------------------------------------------------------------------- */ /* SuiteSparse_malloc: malloc wrapper */ /* -------------------------------------------------------------------------- */ void *SuiteSparse_malloc /* pointer to allocated block of memory */ ( size_t nitems, /* number of items to malloc */ size_t size_of_item /* sizeof each item */ ) { void *p ; size_t size ; if (nitems < 1) nitems = 1 ; if (size_of_item < 1) size_of_item = 1 ; size = nitems * size_of_item ; if (size != ((double) nitems) * size_of_item) { /* size_t overflow */ p = NULL ; } else { p = (void *) (SuiteSparse_config.malloc_func) (size) ; } return (p) ; } /* -------------------------------------------------------------------------- */ /* SuiteSparse_calloc: calloc wrapper */ /* -------------------------------------------------------------------------- */ void *SuiteSparse_calloc /* pointer to allocated block of memory */ ( size_t nitems, /* number of items to calloc */ size_t size_of_item /* sizeof each item */ ) { void *p ; size_t size ; if (nitems < 1) nitems = 1 ; if (size_of_item < 1) size_of_item = 1 ; size = nitems * size_of_item ; if (size != ((double) nitems) * size_of_item) { /* size_t overflow */ p = NULL ; } else { p = (void *) (SuiteSparse_config.calloc_func) (nitems, size_of_item) ; } return (p) ; } /* -------------------------------------------------------------------------- */ /* SuiteSparse_realloc: realloc wrapper */ /* -------------------------------------------------------------------------- */ /* If p is non-NULL on input, it points to a previously allocated object of size nitems_old * size_of_item. The object is reallocated to be of size nitems_new * size_of_item. If p is NULL on input, then a new object of that size is allocated. On success, a pointer to the new object is returned, and ok is returned as 1. If the allocation fails, ok is set to 0 and a pointer to the old (unmodified) object is returned. */ void *SuiteSparse_realloc /* pointer to reallocated block of memory, or to original block if the realloc failed. */ ( size_t nitems_new, /* new number of items in the object */ size_t nitems_old, /* old number of items in the object */ size_t size_of_item, /* sizeof each item */ void *p, /* old object to reallocate */ int *ok /* 1 if successful, 0 otherwise */ ) { size_t size ; if (nitems_old < 1) nitems_old = 1 ; if (nitems_new < 1) nitems_new = 1 ; if (size_of_item < 1) size_of_item = 1 ; size = nitems_new * size_of_item ; if (size != ((double) nitems_new) * size_of_item) { /* size_t overflow */ (*ok) = 0 ; } else if (p == NULL) { /* a fresh object is being allocated */ p = SuiteSparse_malloc (nitems_new, size_of_item) ; (*ok) = (p != NULL) ; } else if (nitems_old == nitems_new) { /* the object does not change; do nothing */ (*ok) = 1 ; } else { /* change the size of the object from nitems_old to nitems_new */ void *pnew ; pnew = (void *) (SuiteSparse_config.realloc_func) (p, size) ; if (pnew == NULL) { if (nitems_new < nitems_old) { /* the attempt to reduce the size of the block failed, but the old block is unchanged. So pretend to succeed. */ (*ok) = 1 ; } else { /* out of memory */ (*ok) = 0 ; } } else { /* success */ p = pnew ; (*ok) = 1 ; } } return (p) ; } /* -------------------------------------------------------------------------- */ /* SuiteSparse_free: free wrapper */ /* -------------------------------------------------------------------------- */ void *SuiteSparse_free /* always returns NULL */ ( void *p /* block to free */ ) { if (p) { (SuiteSparse_config.free_func) (p) ; } return (NULL) ; } /* -------------------------------------------------------------------------- */ /* SuiteSparse_tic: return current wall clock time */ /* -------------------------------------------------------------------------- */ /* Returns the number of seconds (tic [0]) and nanoseconds (tic [1]) since some * unspecified but fixed time in the past. If no timer is installed, zero is * returned. A scalar double precision value for 'tic' could be used, but this * might cause loss of precision because clock_getttime returns the time from * some distant time in the past. Thus, an array of size 2 is used. * * The timer is enabled by default. To disable the timer, compile with * -DNTIMER. If enabled on a POSIX C 1993 system, the timer requires linking * with the -lrt library. * * example: * * double tic [2], r, s, t ; * SuiteSparse_tic (tic) ; // start the timer * // do some work A * t = SuiteSparse_toc (tic) ; // t is time for work A, in seconds * // do some work B * s = SuiteSparse_toc (tic) ; // s is time for work A and B, in seconds * SuiteSparse_tic (tic) ; // restart the timer * // do some work C * r = SuiteSparse_toc (tic) ; // s is time for work C, in seconds * * A double array of size 2 is used so that this routine can be more easily * ported to non-POSIX systems. The caller does not rely on the POSIX * include file. */ #if !defined ( SUITESPARSE_TIMER_ENABLED ) /* ---------------------------------------------------------------------- */ /* no timer */ /* ---------------------------------------------------------------------- */ void SuiteSparse_tic ( double tic [2] /* output, contents undefined on input */ ) { /* no timer installed */ tic [0] = 0 ; tic [1] = 0 ; } #elif defined ( _OPENMP ) /* ---------------------------------------------------------------------- */ /* OpenMP timer */ /* ---------------------------------------------------------------------- */ void SuiteSparse_tic ( double tic [2] /* output, contents undefined on input */ ) { tic [0] = omp_get_wtime ( ) ; tic [1] = 0 ; } #else /* ---------------------------------------------------------------------- */ /* POSIX timer */ /* ---------------------------------------------------------------------- */ #include void SuiteSparse_tic ( double tic [2] /* output, contents undefined on input */ ) { /* POSIX C 1993 timer, requires -lrt */ struct timespec t ; clock_gettime (CLOCK_MONOTONIC, &t) ; tic [0] = (double) (t.tv_sec) ; tic [1] = (double) (t.tv_nsec) ; } #endif /* -------------------------------------------------------------------------- */ /* SuiteSparse_toc: return time since last tic */ /* -------------------------------------------------------------------------- */ /* Assuming SuiteSparse_tic is accurate to the nanosecond, this function is * accurate down to the nanosecond for 2^53 nanoseconds since the last call to * SuiteSparse_tic, which is sufficient for SuiteSparse (about 104 days). If * additional accuracy is required, the caller can use two calls to * SuiteSparse_tic and do the calculations differently. */ double SuiteSparse_toc /* returns time in seconds since last tic */ ( double tic [2] /* input, not modified from last call to SuiteSparse_tic */ ) { double toc [2] ; SuiteSparse_tic (toc) ; return ((toc [0] - tic [0]) + 1e-9 * (toc [1] - tic [1])) ; } /* -------------------------------------------------------------------------- */ /* SuiteSparse_time: return current wallclock time in seconds */ /* -------------------------------------------------------------------------- */ /* This function might not be accurate down to the nanosecond. */ double SuiteSparse_time /* returns current wall clock time in seconds */ ( void ) { double toc [2] ; SuiteSparse_tic (toc) ; return (toc [0] + 1e-9 * toc [1]) ; } /* -------------------------------------------------------------------------- */ /* SuiteSparse_version: return the current version of SuiteSparse */ /* -------------------------------------------------------------------------- */ int SuiteSparse_version ( int version [3] ) { if (version != NULL) { version [0] = SUITESPARSE_MAIN_VERSION ; version [1] = SUITESPARSE_SUB_VERSION ; version [2] = SUITESPARSE_SUBSUB_VERSION ; } return (SUITESPARSE_VERSION) ; } //------------------------------------------------------------------------------ // SuiteSparse_hypot //------------------------------------------------------------------------------ // SuiteSparse_config v5 and earlier used SuiteSparse_hypot, defined below. // SuiteSparse_config v6 now uses the hypot method in , by default. // The hypot function appears in ANSI C99 and later, and SuiteSparse now // assumes ANSI C11. // s = hypot (x,y) computes s = sqrt (x*x + y*y) but does so more accurately. // The NaN cases for the double relops x >= y and x+y == x are safely ignored. // Source: Algorithm 312, "Absolute value and square root of a complex number," // P. Friedland, Comm. ACM, vol 10, no 10, October 1967, page 665. // This method below is kept for historical purposes. double SuiteSparse_hypot (double x, double y) { double s, r ; x = fabs (x) ; y = fabs (y) ; if (x >= y) { if (x + y == x) { s = x ; } else { r = y / x ; s = x * sqrt (1.0 + r*r) ; } } else { if (y + x == y) { s = y ; } else { r = x / y ; s = y * sqrt (1.0 + r*r) ; } } return (s) ; } //------------------------------------------------------------------------------ // SuiteSparse_divcomplex //------------------------------------------------------------------------------ // z = x/y where z, x, and y are complex. The real and imaginary parts are // passed as separate arguments to this routine. The NaN case is ignored // for the double relop yr >= yi. Returns 1 if the denominator is zero, // 0 otherwise. // // This uses ACM Algo 116, by R. L. Smith, 1962, which tries to avoid // underflow and overflow. // // z can be the same variable as x or y. // // Default value of the SuiteSparse_config.divcomplex_func pointer is // SuiteSparse_divcomplex. // // This function is identical to GB_divcomplex in GraphBLAS/Source/GB_math.h. // The only difference is the name of the function. int SuiteSparse_divcomplex ( double xr, double xi, // real and imaginary parts of x double yr, double yi, // real and imaginary parts of y double *zr, double *zi // real and imaginary parts of z ) { double tr, ti, r, den ; int yr_class = fpclassify (yr) ; int yi_class = fpclassify (yi) ; if (yi_class == FP_ZERO) { den = yr ; if (xi == 0) { tr = xr / den ; ti = 0 ; } else if (xr == 0) { tr = 0 ; ti = xi / den ; } else { tr = xr / den ; ti = xi / den ; } } else if (yr_class == FP_ZERO) { den = yi ; if (xr == 0) { tr = xi / den ; ti = 0 ; } else if (xi == 0) { tr = 0 ; ti = -xr / den ; } else { tr = xi / den ; ti = -xr / den ; } } else if (yi_class == FP_INFINITE && yr_class == FP_INFINITE) { if (signbit (yr) == signbit (yi)) { // r = 1 den = yr + yi ; tr = (xr + xi) / den ; ti = (xi - xr) / den ; } else { // r = -1 den = yr - yi ; tr = (xr - xi) / den ; ti = (xi + xr) / den ; } } else { if (fabs (yr) >= fabs (yi)) { r = yi / yr ; den = yr + r * yi ; tr = (xr + xi * r) / den ; ti = (xi - xr * r) / den ; } else { r = yr / yi ; den = r * yr + yi ; tr = (xr * r + xi) / den ; ti = (xi * r - xr) / den ; } } (*zr) = tr ; (*zi) = ti ; return (den == 0) ; } //------------------------------------------------------------------------------ // SuiteSparse_BLAS_library: return name of BLAS library found //------------------------------------------------------------------------------ // Returns the name of the BLAS library found by SuiteSparse_config const char *SuiteSparse_BLAS_library ( void ) { #if defined ( BLAS_Intel10_64ilp ) return ("Intel MKL 64ilp BLAS (64-bit integers)") ; #elif defined ( BLAS_Intel10_64lp ) return ("Intel MKL 64lp BLAS (32-bit integers)") ; #elif defined ( BLAS_Apple ) return ("Apple Accelerate Framework BLAS (32-bit integers)") ; #elif defined ( BLAS_Arm_ilp64_mp ) return ("ARM MP BLAS (64-bit integers)") ; #elif defined ( BLAS_Arm_mp ) return ("ARM MP BLAS (32-bit integers)") ; #elif defined ( BLAS_IBMESSL_SMP ) return ((sizeof (SUITESPARSE_BLAS_INT) == 8) ? "IBMESSL_SMP BLAS (64-bit integers)" : "IBMESSL_SMP BLAS (32-bit integers)") ; #elif defined ( BLAS_OpenBLAS ) return ((sizeof (SUITESPARSE_BLAS_INT) == 8) ? "OpenBLAS (64-bit integers)" : "OpenBLAS (32-bit integers)") ; #elif defined ( BLAS_FLAME ) return ((sizeof (SUITESPARSE_BLAS_INT) == 8) ? "FLAME (64-bit integers)" : "FLAME (32-bit integers)") ; #elif defined ( BLAS_Generic ) return ((sizeof (SUITESPARSE_BLAS_INT) == 8) ? "Reference BLAS (64-bit integers)" : "Reference BLAS (32-bit integers)") ; #else return ((sizeof (SUITESPARSE_BLAS_INT) == 8) ? "Other BLAS (64-bit integers)" : "Other BLAS (32-bit integers)") ; #endif } //------------------------------------------------------------------------------ // SuiteSparse_BLAS_integer: return size of BLAS integer //------------------------------------------------------------------------------ size_t SuiteSparse_BLAS_integer_size ( void ) { return (sizeof (SUITESPARSE_BLAS_INT)) ; } Matrix/src/validity.c0000644000175100001440000015330014575137654014337 0ustar hornikusers#include /* trunc */ #include "Mdefines.h" #include "validity.h" #define MK(_FORMAT_ ) mkString(_FORMAT_ ) #define MS(_FORMAT_, ...) Matrix_sprintf(_FORMAT_, __VA_ARGS__) #define RMK(_FORMAT_ ) \ return MK( _FORMAT_ ) #define RMS(_FORMAT_, ...) \ return MS(_FORMAT_, __VA_ARGS__) #define RMKMS(_FORMAT_, ...) \ return MK(MS(_FORMAT_, __VA_ARGS__)) #define FRMKMS(_FORMAT_, ...) \ do { \ Matrix_Free(work, lwork); \ RMKMS(_FORMAT_, __VA_ARGS__); \ } while (0) /* Slot validity methods =============================================== Called by various class validity methods (see below). */ char *Dim_validate(SEXP dim) { if (TYPEOF(dim) != INTSXP) RMS(_("'%s' slot is not of type \"%s\""), "Dim", "integer"); if (XLENGTH(dim) != 2) RMS(_("'%s' slot does not have length %d"), "Dim", 2); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; if (m == NA_INTEGER || n == NA_INTEGER) RMS(_("'%s' slot contains NA"), "Dim"); if (m < 0 || n < 0) RMS(_("'%s' slot has negative elements"), "Dim"); return NULL; } SEXP R_Dim_validate(SEXP dim) { char *msg = Dim_validate(dim); return (msg) ? mkString(msg) : ScalarLogical(1); } char *DimNames_validate(SEXP dimnames, int *pdim) { if (TYPEOF(dimnames) != VECSXP) RMS(_("'%s' slot is not a list"), "Dimnames"); if (XLENGTH(dimnames) != 2) RMS(_("'%s' slot does not have length %d"), "Dimnames", 2); /* Behave as do_matrix() from src/main/array.c: Dimnames[[i]] must be NULL or _coercible to_ character of length Dim[i] or 0 ... see R_Dimnames_fixup() below */ SEXP s; int i; R_xlen_t ns; for (i = 0; i < 2; ++i) { s = VECTOR_ELT(dimnames, i); if (s == R_NilValue) continue; if (!isVector(s)) RMS(_("%s[[%d]] is not NULL or a vector"), "Dimnames", i + 1); ns = XLENGTH(s); if (ns != pdim[i] && ns != 0) RMS(_("length of %s[[%d]] (%lld) is not equal to %s[%d] (%d)"), "Dimnames", i + 1, (long long) ns, "Dim" , i + 1, pdim[i]); } return NULL; } SEXP R_DimNames_validate(SEXP dimnames, SEXP dim) { char *msg = DimNames_validate(dimnames, INTEGER(dim)); return (msg) ? mkString(msg) : ScalarLogical(1); } SEXP R_DimNames_fixup(SEXP dimnames) { SEXP s; int i, fixup = 0; for (i = 0; i < 2 && !fixup; ++i) fixup = (s = VECTOR_ELT(dimnames, i)) != R_NilValue && (LENGTH(s) == 0 || TYPEOF(s) != STRSXP); if (!fixup) return dimnames; SEXP dimnames_ = PROTECT(allocVector(VECSXP, 2)); for (i = 0; i < 2; ++i) { if ((s = VECTOR_ELT(dimnames, i)) == R_NilValue || LENGTH(s) == 0) continue; if (TYPEOF(s) == STRSXP) PROTECT(s); else if (TYPEOF(s) == INTSXP && inherits(s, "factor")) PROTECT(s = asCharacterFactor(s)); else { PROTECT(s = coerceVector(s, STRSXP)); SET_ATTRIB(s, R_NilValue); SET_OBJECT(s, 0); } SET_VECTOR_ELT(dimnames_, i, s); UNPROTECT(1); /* s */ } s = getAttrib(dimnames, R_NamesSymbol); if (s != R_NilValue) { PROTECT(s); setAttrib(dimnames_, R_NamesSymbol, s); UNPROTECT(1); /* s */ } UNPROTECT(1); /* dimnames_ */ return dimnames_; } /* Class validity methods ============================================== NB: These assume that validity methods for superclasses have already been called via validObject() ... */ SEXP Matrix_validate(SEXP obj) { SEXP dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)); char *msg = Dim_validate(dim); if (!msg) { SEXP dimnames = PROTECT(GET_SLOT(obj, Matrix_DimNamesSym)); msg = DimNames_validate(dimnames, INTEGER(dim)); UNPROTECT(1); /* dimnames */ } UNPROTECT(1); /* dim */ return (msg) ? mkString(msg) : ScalarLogical(1); } SEXP MatrixFactorization_validate(SEXP obj) { return Matrix_validate(obj); } #define KINDMATRIX_VALIDATE(_PREFIX_, _SEXPTYPE_) \ SEXP _PREFIX_ ## Matrix_validate(SEXP obj) \ { \ SEXP x = GET_SLOT(obj, Matrix_xSym); \ if (TYPEOF(x) != _SEXPTYPE_) \ RMKMS(_("'%s' slot is not of type \"%s\""), "x", type2char(_SEXPTYPE_)); \ return ScalarLogical(1); \ } KINDMATRIX_VALIDATE(n, LGLSXP) KINDMATRIX_VALIDATE(l, LGLSXP) KINDMATRIX_VALIDATE(i, INTSXP) KINDMATRIX_VALIDATE(d, REALSXP) KINDMATRIX_VALIDATE(z, CPLXSXP) #undef KINDMATRIX_VALIDATE SEXP generalMatrix_validate(SEXP obj) { SEXP factors = GET_SLOT(obj, Matrix_factorsSym); if (TYPEOF(factors) != VECSXP) RMKMS(_("'%s' slot is not a list"), "factors"); if (XLENGTH(factors) > 0) { PROTECT(factors); SEXP nms = getAttrib(factors, R_NamesSymbol); UNPROTECT(1); /* factors */ if (nms == R_NilValue) RMKMS(_("'%s' slot has no '%s' attribute"), "factors", "names"); } return ScalarLogical(1); } SEXP symmetricMatrix_validate(SEXP obj) { SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) RMKMS(_("%s[1] != %s[2] (matrix is not square)"), "Dim", "Dim"); #ifdef ENFORCE_SYMMETRIC_DIMNAMES /* This check can be expensive when both rownames and colnames have nonzero length, and even more so when coercions to character are required ... Users can avoid the expense by setting at least one of rownames and colnames to NULL or by ensuring that they are the same object, as testing for pointer equality is fast ... */ # define ANY_TO_STRING(x) \ ((TYPEOF(x) == INTSXP && inherits(x, "factor")) \ ? asCharacterFactor(x) \ : coerceVector(x, STRSXP)) SEXP dn = PROTECT(GET_SLOT(obj, Matrix_DimNamesSym)), ndn = getAttrib(dn, R_NamesSymbol); UNPROTECT(1); /* dn */ const char *ndn0, *ndn1; if (ndn != R_NilValue && *(ndn0 = CHAR(STRING_ELT(ndn, 0))) != '\0' && *(ndn1 = CHAR(STRING_ELT(ndn, 1))) != '\0' && strcmp(ndn0, ndn1) != 0) RMKMS(_("%s[1] differs from %s[2]"), "Dimnames", "Dimnames"); if (n > 0) { /* NB: It is already known that the length of 'dn[[i]]' is 0 or 'n' */ SEXP rn, cn; if ((rn = VECTOR_ELT(dn, 0)) != R_NilValue && (cn = VECTOR_ELT(dn, 1)) != R_NilValue && LENGTH(rn) == n && LENGTH(cn) == n && rn != cn) { PROTECT(rn); PROTECT(cn); PROTECT(rn = ANY_TO_STRING(rn)); PROTECT(cn = ANY_TO_STRING(cn)); UNPROTECT(4); /* cn, rn */ if (!equal_character_vectors(rn, cn, n)) RMKMS(_("%s[1] differs from %s[2]"), "Dimnames", "Dimnames"); } } # undef ANY_TO_STRING #endif SEXP uplo = GET_SLOT(obj, Matrix_uploSym); if (TYPEOF(uplo) != STRSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "uplo", "character"); if (XLENGTH(uplo) != 1) RMKMS(_("'%s' slot does not have length %d"), "uplo", 1); const char *ul = CHAR(STRING_ELT(uplo, 0)); if (ul[0] == '\0' || ul[1] != '\0' || (ul[0] != 'U' && ul[0] != 'L')) RMKMS(_("'%s' slot is not \"%s\" or \"%s\""), "uplo", "U", "L"); return generalMatrix_validate(obj); } SEXP triangularMatrix_validate(SEXP obj) { SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) RMKMS(_("%s[1] != %s[2] (matrix is not square)"), "Dim", "Dim"); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); if (TYPEOF(uplo) != STRSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "uplo", "character"); if (XLENGTH(uplo) != 1) RMKMS(_("'%s' slot does not have length %d"), "uplo", 1); const char *ul = CHAR(STRING_ELT(uplo, 0)); if (ul[0] == '\0' || ul[1] != '\0' || (ul[0] != 'U' && ul[0] != 'L')) RMKMS(_("'%s' slot is not \"%s\" or \"%s\""), "uplo", "U", "L"); SEXP diag = GET_SLOT(obj, Matrix_diagSym); if (TYPEOF(diag) != STRSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "diag", "character"); if (XLENGTH(diag) != 1) RMKMS(_("'%s' slot does not have length %d"), "diag", 1); const char *di = CHAR(STRING_ELT(diag, 0)); if (di[0] == '\0' || di[1] != '\0' || (di[0] != 'N' && di[0] != 'U')) RMKMS(_("'%s' slot is not \"%s\" or \"%s\""), "diag", "N", "U"); return ScalarLogical(1); } SEXP unpackedMatrix_validate(SEXP obj) { SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)); UNPROTECT(2); /* dim, x */ int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; if (XLENGTH(x) != (Matrix_int_fast64_t) m * n) RMKMS(_("'%s' slot does not have length %s"), "x", "prod(Dim)"); return ScalarLogical(1); } SEXP packedMatrix_validate(SEXP obj) { SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), dim = PROTECT(GET_SLOT(obj, Matrix_DimSym)); UNPROTECT(2); /* dim, x */ int n = INTEGER(dim)[0]; if (XLENGTH(x) != n + ((Matrix_int_fast64_t) n * (n - 1)) / 2) RMKMS(_("'%s' slot does not have length %s"), "x", "Dim[1]*(Dim[1]+1)/2"); return ScalarLogical(1); } SEXP CsparseMatrix_validate(SEXP obj) { SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; SEXP p = PROTECT(GET_SLOT(obj, Matrix_pSym)), i = PROTECT(GET_SLOT(obj, Matrix_iSym)); UNPROTECT(2); /* i, p */ if (TYPEOF(p) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "p", "integer"); if (XLENGTH(p) - 1 != n) RMKMS(_("'%s' slot does not have length %s"), "p", "Dim[2]+1"); int *pp = INTEGER(p); if (pp[0] != 0) RMKMS(_("first element of '%s' slot is not 0"), "p"); int j; for (j = 1; j <= n; ++j) { if (pp[j] == NA_INTEGER) RMKMS(_("'%s' slot contains NA"), "p"); if (pp[j] < pp[j - 1]) RMKMS(_("'%s' slot is not nondecreasing"), "p"); if (pp[j] - pp[j - 1] > m) RMKMS(_("first differences of '%s' slot exceed %s"), "p", "Dim[1]"); } if (TYPEOF(i) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "i", "integer"); if (XLENGTH(i) < pp[n]) RMKMS(_("'%s' slot has length less than %s"), "i", "p[length(p)]"); int *pi = INTEGER(i), k, kend, ik, i0; for (j = 1, k = 0; j <= n; ++j) { kend = pp[j]; i0 = -1; while (k < kend) { ik = pi[k]; if (ik == NA_INTEGER) RMKMS(_("'%s' slot contains NA"), "i"); if (ik < 0 || ik >= m) RMKMS(_("'%s' slot has elements not in {%s}"), "i", "0,...,Dim[1]-1"); if (ik <= i0) RMKMS(_("'%s' slot is not increasing within columns"), "i"); i0 = ik; ++k; } } return ScalarLogical(1); } SEXP RsparseMatrix_validate(SEXP obj) { SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; SEXP p = PROTECT(GET_SLOT(obj, Matrix_pSym)), j = PROTECT(GET_SLOT(obj, Matrix_jSym)); UNPROTECT(2); /* j, p */ if (TYPEOF(p) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "p", "integer"); if (XLENGTH(p) - 1 != m) RMKMS(_("'%s' slot does not have length %s"), "p", "Dim[1]+1"); int *pp = INTEGER(p); if (pp[0] != 0) RMKMS(_("first element of '%s' slot is not 0"), "p"); int i; for (i = 1; i <= m; ++i) { if (pp[i] == NA_INTEGER) RMKMS(_("'%s' slot contains NA"), "p"); if (pp[i] < pp[i - 1]) RMKMS(_("'%s' slot is not nondecreasing"), "p"); if (pp[i] - pp[i - 1] > n) RMKMS(_("first differences of '%s' slot exceed %s"), "p", "Dim[2]"); } if (TYPEOF(j) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "j", "integer"); if (XLENGTH(j) < pp[m]) RMKMS(_("'%s' slot has length less than %s"), "j", "p[length(p)]"); int *pj = INTEGER(j), k, kend, jk, j0; for (i = 1, k = 0; i <= m; ++i) { kend = pp[i]; j0 = -1; while (k < kend) { jk = pj[k]; if (jk == NA_INTEGER) RMKMS(_("'%s' slot contains NA"), "j"); if (jk < 0 || jk >= n) RMKMS(_("'%s' slot has elements not in {%s}"), "j", "0,...,Dim[2]-1"); if (jk <= j0) RMKMS(_("'%s' slot is not increasing within rows"), "j"); j0 = jk; ++k; } } return ScalarLogical(1); } SEXP TsparseMatrix_validate(SEXP obj) { SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; SEXP i = PROTECT(GET_SLOT(obj, Matrix_iSym)), j = PROTECT(GET_SLOT(obj, Matrix_jSym)); UNPROTECT(2); /* j, i */ if (TYPEOF(i) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "i", "integer"); if (TYPEOF(j) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "j", "integer"); R_xlen_t nnz = XLENGTH(i); if (XLENGTH(j) != nnz) RMKMS(_("'%s' and '%s' slots do not have equal length"), "i", "j"); if (nnz > 0) { if (m == 0 || n == 0) RMKMS(_("'%s' slot has nonzero length but %s is 0"), "i", "prod(Dim)"); int *pi = INTEGER(i), *pj = INTEGER(j); while (nnz--) { if (*pi == NA_LOGICAL) RMKMS(_("'%s' slot contains NA"), "i"); if (*pj == NA_LOGICAL) RMKMS(_("'%s' slot contains NA"), "j"); if (*pi < 0 || *pi >= m) RMKMS(_("'%s' slot has elements not in {%s}"), "i", "0,...,Dim[1]-1"); if (*pj < 0 || *pj >= n) RMKMS(_("'%s' slot has elements not in {%s}"), "j", "0,...,Dim[2]-1"); ++pi; ++pj; } } return ScalarLogical(1); } SEXP diagonalMatrix_validate(SEXP obj) { SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) RMKMS(_("%s[1] != %s[2] (matrix is not square)"), "Dim", "Dim"); SEXP diag = GET_SLOT(obj, Matrix_diagSym); if (TYPEOF(diag) != STRSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "diag", "character"); if (XLENGTH(diag) != 1) RMKMS(_("'%s' slot does not have length %d"), "diag", 1); const char *di = CHAR(STRING_ELT(diag, 0)); if (di[0] == '\0' || di[1] != '\0' || (di[0] != 'N' && di[0] != 'U')) RMKMS(_("'%s' slot is not \"%s\" or \"%s\""), "diag", "N", "U"); int nonunit = di[0] == 'N'; SEXP x = GET_SLOT(obj, Matrix_xSym); if (nonunit) { if (XLENGTH(x) != n) RMKMS(_("'%s' slot is \"%s\" but '%s' slot does not have length %s"), "diag", "N", "x", "Dim[1]"); } else { if (XLENGTH(x) != 0) RMKMS(_("'%s' slot is \"%s\" but '%s' slot does not have length %s"), "diag", "U", "x", "0"); } return ScalarLogical(1); } SEXP indMatrix_validate(SEXP obj) { SEXP margin = GET_SLOT(obj, Matrix_marginSym); if (TYPEOF(margin) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "margin", "integer"); if (XLENGTH(margin) != 1) RMKMS(_("'%s' slot does not have length %d"), "margin", 1); int mg = INTEGER(margin)[0] - 1; if (mg != 0 && mg != 1) RMKMS(_("'%s' slot is not %d or %d"), "margin", 1, 2); SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[mg], n = pdim[!mg]; if (m > 0 && n == 0) { if (mg == 0) RMKMS(_("%s-by-%s %s invalid for positive '%s' when %s=%d"), "m", "0", "indMatrix", "m", "margin", 1); else RMKMS(_("%s-by-%s %s invalid for positive '%s' when %s=%d"), "0", "n", "indMatrix", "n", "margin", 2); } SEXP perm = GET_SLOT(obj, Matrix_permSym); if (TYPEOF(perm) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "perm", "integer"); if (XLENGTH(perm) != m) RMKMS(_("'%s' slot does not have length %s"), "perm", "Dim[margin]"); int *pperm = INTEGER(perm); while (m--) { if (*pperm == NA_INTEGER) RMKMS(_("'%s' slot contains NA"), "perm"); if (*pperm < 1 || *pperm > n) RMKMS(_("'%s' slot has elements not in {%s}"), "perm", "1,...,Dim[1+margin%%2]"); ++pperm; } return ScalarLogical(1); } SEXP pMatrix_validate(SEXP obj) { SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) RMKMS(_("%s[1] != %s[2] (matrix is not square)"), "Dim", "Dim"); if (n > 1) { SEXP perm = GET_SLOT(obj, Matrix_permSym); char *work; int lwork = n; Matrix_Calloc(work, lwork, char); int j, *pperm = INTEGER(perm); for (j = 0; j < n; ++j) { if (work[*pperm - 1]) FRMKMS(_("'%s' slot contains duplicates"), "perm"); work[*(pperm++) - 1] = 1; } Matrix_Free(work, lwork); } return ScalarLogical(1); } SEXP sCMatrix_validate(SEXP obj) { SEXP p = GET_SLOT(obj, Matrix_pSym); int *pp = INTEGER(p), n = (int) (XLENGTH(p) - 1); if (pp[n] > 0) { PROTECT(p); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); SEXP i = GET_SLOT(obj, Matrix_iSym); int *pi = INTEGER(i), j, k, kend; UNPROTECT(1); /* p */ if (ul == 'U') { for (j = 0, k = 0; j < n; ++j) { kend = pp[j + 1]; while (k < kend) { if (pi[k] > j) RMKMS(_("%s=\"%s\" but there are entries below the diagonal"), "uplo", "U"); ++k; } } } else { for (j = 0, k = 0; j < n; ++j) { kend = pp[j + 1]; while (k < kend) { if (pi[k] < j) RMKMS(_("%s=\"%s\" but there are entries above the diagonal"), "uplo", "L"); ++k; } } } } return ScalarLogical(1); } SEXP tCMatrix_validate(SEXP obj) { SEXP diag = GET_SLOT(obj, Matrix_diagSym); char di = *CHAR(STRING_ELT(diag, 0)); if (di == 'N') return sCMatrix_validate(obj); SEXP p = GET_SLOT(obj, Matrix_pSym); int *pp = INTEGER(p), n = (int) (XLENGTH(p) - 1); if (pp[n] > 0) { PROTECT(p); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); SEXP i = GET_SLOT(obj, Matrix_iSym); int *pi = INTEGER(i), j, k, kend; UNPROTECT(1); /* p */ if (ul == 'U') { for (j = 0, k = 0; j < n; ++j) { kend = pp[j + 1]; while (k < kend) { if (pi[k] > j) RMKMS(_("%s=\"%s\" but there are entries below the diagonal"), "uplo", "U"); if (pi[k] == j) RMKMS(_("%s=\"%s\" but there are entries on the diagonal"), "diag", "U"); ++k; } } } else { for (j = 0, k = 0; j < n; ++j) { kend = pp[j + 1]; while (k < kend) { if (pi[k] < j) RMKMS(_("%s=\"%s\" but there are entries above the diagonal"), "uplo", "L"); if (pi[k] == j) RMKMS(_("%s=\"%s\" but there are entries on the diagonal"), "diag", "U"); ++k; } } } } return ScalarLogical(1); } SEXP sRMatrix_validate(SEXP obj) { SEXP p = GET_SLOT(obj, Matrix_pSym); int *pp = INTEGER(p), m = (int) (XLENGTH(p) - 1); if (pp[m] > 0) { PROTECT(p); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); SEXP j = GET_SLOT(obj, Matrix_jSym); int *pj = INTEGER(j), i, k, kend; UNPROTECT(1); /* p */ if (ul == 'U') { for (i = 0, k = 0; i < m; ++i) { kend = pp[i + 1]; while (k < kend) { if (pj[k] < i) RMKMS(_("%s=\"%s\" but there are entries below the diagonal"), "uplo", "U"); ++k; } } } else { for (i = 0, k = 0; i < m; ++i) { kend = pp[i + 1]; while (k < kend) { if (pj[k] > i) RMKMS(_("%s=\"%s\" but there are entries above the diagonal"), "uplo", "L"); ++k; } } } } return ScalarLogical(1); } SEXP tRMatrix_validate(SEXP obj) { SEXP diag = GET_SLOT(obj, Matrix_diagSym); char di = *CHAR(STRING_ELT(diag, 0)); if (di == 'N') return sRMatrix_validate(obj); SEXP p = GET_SLOT(obj, Matrix_pSym); int *pp = INTEGER(p), m = (int) (XLENGTH(p) - 1); if (pp[m] > 0) { PROTECT(p); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); SEXP j = GET_SLOT(obj, Matrix_jSym); int *pj = INTEGER(j), i, k, kend; UNPROTECT(1); /* p */ if (ul == 'U') { for (i = 0, k = 0; i < m; ++i) { kend = pp[i + 1]; while (k < kend) { if (pj[k] < i) RMKMS(_("%s=\"%s\" but there are entries below the diagonal"), "uplo", "U"); if (pj[k] == i) RMKMS(_("%s=\"%s\" but there are entries on the diagonal"), "diag", "U"); ++k; } } } else { for (i = 0, k = 0; i < m; ++i) { kend = pp[i + 1]; while (k < kend) { if (pj[k] > i) RMKMS(_("%s=\"%s\" but there are entries above the diagonal"), "uplo", "L"); if (pj[k] == i) RMKMS(_("%s=\"%s\" but there are entries on the diagonal"), "diag", "U"); ++k; } } } } return ScalarLogical(1); } SEXP sTMatrix_validate(SEXP obj) { SEXP i = GET_SLOT(obj, Matrix_iSym); R_xlen_t nnz = XLENGTH(i); if (nnz > 0) { PROTECT(i); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); SEXP j = GET_SLOT(obj, Matrix_jSym); int *pi = INTEGER(i), *pj = INTEGER(j); UNPROTECT(1); /* i */ if (ul == 'U') { while (nnz--) if (*(pi++) > *(pj++)) RMKMS(_("%s=\"%s\" but there are entries below the diagonal"), "uplo", "U"); } else { while (nnz--) if (*(pi++) < *(pj++)) RMKMS(_("%s=\"%s\" but there are entries above the diagonal"), "uplo", "L"); } } return ScalarLogical(1); } SEXP tTMatrix_validate(SEXP obj) { SEXP diag = GET_SLOT(obj, Matrix_diagSym); char di = *CHAR(STRING_ELT(diag, 0)); if (di == 'N') return sTMatrix_validate(obj); SEXP i = GET_SLOT(obj, Matrix_iSym); R_xlen_t nnz = XLENGTH(i); if (nnz > 0) { PROTECT(i); SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); SEXP j = GET_SLOT(obj, Matrix_jSym); int *pi = INTEGER(i), *pj = INTEGER(j); UNPROTECT(1); /* i */ if (ul == 'U') { while (nnz--) { if (*pi > *pj) RMKMS(_("%s=\"%s\" but there are entries below the diagonal"), "uplo", "U"); if (*pi == *pj) RMKMS(_("%s=\"%s\" but there are entries on the diagonal"), "diag", "U"); ++pi; ++pj; } } else { while (nnz--) { if (*pi < *pj) RMKMS(_("%s=\"%s\" but there are entries above the diagonal"), "uplo", "L"); if (*pi == *pj) RMKMS(_("%s=\"%s\" but there are entries on the diagonal"), "diag", "U"); ++pi; ++pj; } } } return ScalarLogical(1); } SEXP xgCMatrix_validate(SEXP obj) { SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), i = PROTECT(GET_SLOT(obj, Matrix_iSym)); UNPROTECT(2); /* i, x */ if (XLENGTH(x) != XLENGTH(i)) RMKMS(_("'%s' and '%s' slots do not have equal length"), "i", "x"); return ScalarLogical(1); } SEXP xsCMatrix_validate(SEXP obj) { SEXP val = xgCMatrix_validate(obj); if (TYPEOF(val) != STRSXP) val = sCMatrix_validate(obj); return val; } SEXP xtCMatrix_validate(SEXP obj) { SEXP val = xgCMatrix_validate(obj); if (TYPEOF(val) != STRSXP) val = tCMatrix_validate(obj); return val; } SEXP xgRMatrix_validate(SEXP obj) { SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), j = PROTECT(GET_SLOT(obj, Matrix_jSym)); UNPROTECT(2); /* j, x */ if (XLENGTH(x) != XLENGTH(j)) RMKMS(_("'%s' and '%s' slots do not have equal length"), "j", "x"); return ScalarLogical(1); } SEXP xsRMatrix_validate(SEXP obj) { SEXP val = xgRMatrix_validate(obj); if (TYPEOF(val) != STRSXP) val = sRMatrix_validate(obj); return val; } SEXP xtRMatrix_validate(SEXP obj) { SEXP val = xgRMatrix_validate(obj); if (TYPEOF(val) != STRSXP) val = tRMatrix_validate(obj); return val; } SEXP xgTMatrix_validate(SEXP obj) { SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), i = PROTECT(GET_SLOT(obj, Matrix_iSym)); UNPROTECT(2); /* i, x */ if (XLENGTH(x) != XLENGTH(i)) RMKMS(_("'%s' and '%s' slots do not have equal length"), "i", "x"); return ScalarLogical(1); } SEXP xsTMatrix_validate(SEXP obj) { SEXP val = xgTMatrix_validate(obj); if (TYPEOF(val) != STRSXP) val = sTMatrix_validate(obj); return val; } SEXP xtTMatrix_validate(SEXP obj) { SEXP val = xgTMatrix_validate(obj); if (TYPEOF(val) != STRSXP) val = tTMatrix_validate(obj); return val; } SEXP dpoMatrix_validate(SEXP obj) { /* NB: Non-finite entries are "valid" because we consider crossprod(x) and tcrossprod(x) to be positive semidefinite even if 'x' contains non-finite entries (for speed) ... */ SEXP dim = GET_SLOT(obj, Matrix_DimSym); int j, n = INTEGER(dim)[0]; R_xlen_t n1a = (R_xlen_t) n + 1; /* Non-negative diagonal elements are necessary but _not_ sufficient */ SEXP x = GET_SLOT(obj, Matrix_xSym); double *px = REAL(x); for (j = 0; j < n; ++j, px += n1a) if (!ISNAN(*px) && *px < 0.0) RMK(_("matrix has negative diagonal elements")); return ScalarLogical(1); } SEXP dppMatrix_validate(SEXP obj) { /* NB: Non-finite entries are "valid" because we consider crossprod(x) and tcrossprod(x) to be positive semidefinite even if 'x' contains non-finite entries (for speed) ... */ SEXP dim = GET_SLOT(obj, Matrix_DimSym); int j, n = INTEGER(dim)[0]; SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); /* Non-negative diagonal elements are necessary but _not_ sufficient */ SEXP x = GET_SLOT(obj, Matrix_xSym); double *px = REAL(x); if (ul == 'U') { for (j = 0; j < n; px += (++j)+1) if (!ISNAN(*px) && *px < 0.0) RMK(_("matrix has negative diagonal elements")); } else { for (j = 0; j < n; px += n-(j++)) if (!ISNAN(*px) && *px < 0.0) RMK(_("matrix has negative diagonal elements")); } return ScalarLogical(1); } SEXP corMatrix_validate(SEXP obj) { SEXP dim = GET_SLOT(obj, Matrix_DimSym); int j, n = INTEGER(dim)[0]; R_xlen_t n1a = (R_xlen_t) n + 1; SEXP x = GET_SLOT(obj, Matrix_xSym); double *px = REAL(x); for (j = 0; j < n; ++j, px += n1a) if (ISNAN(*px) || *px != 1.0) RMK(_("matrix has nonunit diagonal elements")); SEXP sd = GET_SLOT(obj, Matrix_sdSym); if (TYPEOF(sd) != REALSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "sd", "double"); if (XLENGTH(sd) != n) RMKMS(_("'%s' slot does not have length %s"), "sd", "Dim[1]"); double *psd = REAL(sd); for (j = 0; j < n; ++j) if (!ISNAN(psd[j]) && psd[j] < 0.0) RMKMS(_("'%s' slot has negative elements"), "sd"); return ScalarLogical(1); } SEXP copMatrix_validate(SEXP obj) { SEXP dim = GET_SLOT(obj, Matrix_DimSym); int j, n = INTEGER(dim)[0]; SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); SEXP x = GET_SLOT(obj, Matrix_xSym); double *px = REAL(x); if (ul == 'U') { for (j = 0; j < n; px += (++j)+1) if (ISNAN(*px) || *px != 1.0) RMK(_("matrix has nonunit diagonal elements")); } else { for (j = 0; j < n; px += n-(j++)) if (ISNAN(*px) || *px != 1.0) RMK(_("matrix has nonunit diagonal elements")); } SEXP sd = GET_SLOT(obj, Matrix_sdSym); if (TYPEOF(sd) != REALSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "sd", "double"); if (XLENGTH(sd) != n) RMKMS(_("'%s' slot does not have length %s"), "sd", "Dim[1]"); double *psd = REAL(sd); for (j = 0; j < n; ++j) if (!ISNAN(psd[j]) && psd[j] < 0.0) RMKMS(_("'%s' slot has negative elements"), "sd"); return ScalarLogical(1); } SEXP sparseVector_validate(SEXP obj) { SEXP length = GET_SLOT(obj, Matrix_lengthSym); if (TYPEOF(length) != INTSXP && TYPEOF(length) != REALSXP) RMKMS(_("'%s' slot is not of type \"%s\" or \"%s\""), "length", "integer", "double"); if (XLENGTH(length) != 1) RMKMS(_("'%s' slot does not have length %d"), "length", 1); Matrix_int_fast64_t n; if (TYPEOF(length) == INTSXP) { int n_ = INTEGER(length)[0]; if (n_ == NA_INTEGER) RMKMS(_("'%s' slot is NA"), "length"); if (n_ < 0) RMKMS(_("'%s' slot is negative"), "length"); n = (Matrix_int_fast64_t) n_; } else { double n_ = REAL(length)[0]; if (ISNAN(n_)) RMKMS(_("'%s' slot is NA"), "length"); if (n_ < 0.0) RMKMS(_("'%s' slot is negative"), "length"); if (n_ > 0x1.0p+53) RMKMS(_("'%s' slot exceeds %s"), "length", "2^53"); n = (Matrix_int_fast64_t) n_; } SEXP i = GET_SLOT(obj, Matrix_iSym); if (TYPEOF(i) != INTSXP && TYPEOF(i) != REALSXP) RMKMS(_("'%s' slot is not of type \"%s\" or \"%s\""), "i", "integer", "double"); R_xlen_t nnz = XLENGTH(i); if (nnz > n) RMKMS(_("'%s' slot has length greater than '%s' slot"), "i", "length"); if (TYPEOF(i) == INTSXP) { int *pi = INTEGER(i), max = (n > INT_MAX) ? INT_MAX : (int) n, last = 0; while (nnz--) { if (*pi == NA_INTEGER) RMKMS(_("'%s' slot contains NA"), "i"); if (*pi < 1 || *pi > max) RMKMS(_("'%s' slot has elements not in {%s}"), "i", "1,...,length"); if (*pi <= last) RMKMS(_("'%s' slot is not increasing"), "i"); last = *(pi++); } } else { double *pi = REAL(i), max = (double) n, last = 0.0, tmp; while (nnz--) { if (ISNAN(*pi)) RMKMS(_("'%s' slot contains NA"), "i"); tmp = trunc(*(pi++)); if (tmp < 1.0 || tmp > max) RMKMS(_("'%s' slot has elements not in {%s} after truncation towards zero"), "i", "1,...,length"); if (tmp <= last) RMKMS(_("'%s' slot is not increasing after truncation towards zero"), "i"); last = tmp; } } return ScalarLogical(1); } #define KINDVECTOR_VALIDATE(_PREFIX_, _SEXPTYPE_) \ SEXP _PREFIX_ ## sparseVector_validate(SEXP obj) \ { \ SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), \ i = PROTECT(GET_SLOT(obj, Matrix_iSym)); \ UNPROTECT(2); /* i, x */ \ if (TYPEOF(x) != _SEXPTYPE_) \ RMKMS(_("'%s' slot is not of type \"%s\""), "x", type2char(_SEXPTYPE_)); \ if (XLENGTH(x) != XLENGTH(i)) \ RMKMS(_("'%s' and '%s' slots do not have equal length"), "i", "x"); \ return ScalarLogical(1); \ } KINDVECTOR_VALIDATE(l, LGLSXP) KINDVECTOR_VALIDATE(i, INTSXP) KINDVECTOR_VALIDATE(d, REALSXP) KINDVECTOR_VALIDATE(z, CPLXSXP) #undef KINDVECTOR_VALIDATE SEXP denseLU_validate(SEXP obj) { /* In R, we start by checking that 'obj' would be a valid dgeMatrix */ SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1], r = (m < n) ? m : n; SEXP perm = GET_SLOT(obj, Matrix_permSym); if (TYPEOF(perm) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "perm", "integer"); if (XLENGTH(perm) != r) RMKMS(_("'%s' slot does not have length %s"), "perm", "min(Dim)"); int *pperm = INTEGER(perm); while (r--) { if (*pperm == NA_INTEGER) RMKMS(_("'%s' slot contains NA"), "perm"); if (*pperm < 1 || *pperm > m) RMKMS(_("'%s' slot has elements not in {%s}"), "perm", "1,...,Dim[1]"); ++pperm; } return ScalarLogical(1); } SEXP sparseLU_validate(SEXP obj) { SEXP dim = GET_SLOT(obj, Matrix_DimSym), uplo, diag; int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) RMKMS(_("%s[1] != %s[2] (matrix is not square)"), "Dim", "Dim"); SEXP L = PROTECT(GET_SLOT(obj, Matrix_LSym)); PROTECT(dim = GET_SLOT(L, Matrix_DimSym)); PROTECT(uplo = GET_SLOT(L, Matrix_uploSym)); PROTECT(diag = GET_SLOT(L, Matrix_diagSym)); UNPROTECT(4); /* diag, uplo, dim, L */ pdim = INTEGER(dim); if (pdim[0] != n || pdim[1] != n) RMKMS(_("dimensions of '%s' slot are not identical to '%s'"), "L", "Dim"); if (*CHAR(STRING_ELT(uplo, 0)) == 'U') RMKMS(_("'%s' slot is upper (not lower) triangular"), "L"); if (*CHAR(STRING_ELT(diag, 0)) == 'N') { PROTECT(L); SEXP p = PROTECT(GET_SLOT(L, Matrix_pSym)), i = PROTECT(GET_SLOT(L, Matrix_iSym)), x = PROTECT(GET_SLOT(L, Matrix_xSym)); UNPROTECT(4); /* x, i, p, L */ int *pp = INTEGER(p), *pi = INTEGER(i), j, k, kend; double *px = REAL(x); for (j = 0, k = 0; j < n; ++j) { kend = pp[j + 1]; if (kend == k || pi[k] != j || px[k] != 1.0) RMKMS(_("'%s' slot has nonunit diagonal elements"), "L"); k = kend; } } SEXP U = PROTECT(GET_SLOT(obj, Matrix_USym)); PROTECT(dim = GET_SLOT(U, Matrix_DimSym)); PROTECT(uplo = GET_SLOT(U, Matrix_uploSym)); UNPROTECT(3); /* uplo, dim, U */ pdim = INTEGER(dim); if (pdim[0] != n || pdim[1] != n) RMKMS(_("dimensions of '%s' slot are not identical to '%s'"), "U", "Dim"); if (*CHAR(STRING_ELT(uplo, 0)) != 'U') RMKMS(_("'%s' slot is lower (not upper) triangular"), "U"); SEXP p = PROTECT(GET_SLOT(obj, Matrix_pSym)), q = PROTECT(GET_SLOT(obj, Matrix_qSym)); UNPROTECT(2); /* q, p */ if (TYPEOF(p) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "p", "integer"); if (TYPEOF(q) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "q", "integer"); if (XLENGTH(p) != n) RMKMS(_("'%s' slot does not have length %s"), "p", "Dim[1]"); if (XLENGTH(q) != n && XLENGTH(q) != 0) RMKMS(_("'%s' slot does not have length %s or length %s"), "q", "Dim[2]", "0"); char *work; int lwork = n; Matrix_Calloc(work, lwork, char); int j, *pp = INTEGER(p); for (j = 0; j < n; ++j) { if (*pp == NA_INTEGER) FRMKMS(_("'%s' slot contains NA"), "p"); if (*pp < 0 || *pp >= n) FRMKMS(_("'%s' slot has elements not in {%s}"), "p", "0,...,Dim[1]-1"); if (work[*pp]) FRMKMS(_("'%s' slot contains duplicates"), "p"); work[*(pp++)] = 1; } if (LENGTH(q) == n) { int *pq = INTEGER(q); for (j = 0; j < n; ++j) { if (*pq == NA_INTEGER) FRMKMS(_("'%s' slot contains NA"), "q"); if (*pq < 0 || *pq >= n) FRMKMS(_("'%s' slot has elements not in {%s}"), "q", "0,...,Dim[2]-1"); if (!work[*pq]) FRMKMS(_("'%s' slot contains duplicates"), "q"); work[*(pq++)] = 0; } } Matrix_Free(work, lwork); return ScalarLogical(1); } SEXP sparseQR_validate(SEXP obj) { /* MJ: assuming for simplicity that 'V' and 'R' slots are formally valid */ SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), m = pdim[0], n = pdim[1]; if (m < n) RMK(_("matrix has more columns than rows")); SEXP beta = GET_SLOT(obj, Matrix_betaSym); if (TYPEOF(beta) != REALSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "beta", "double"); if (XLENGTH(beta) != n) RMKMS(_("'%s' slot does not have length %s"), "beta", "Dim[2]"); SEXP p, i, q; int *pp, *pi, *pq, j, k, kend; SEXP V = PROTECT(GET_SLOT(obj, Matrix_VSym)); PROTECT(dim = GET_SLOT(V, Matrix_DimSym)); PROTECT(p = GET_SLOT(V, Matrix_pSym)); PROTECT(i = GET_SLOT(V, Matrix_iSym)); UNPROTECT(4); /* i, p, dim, V */ pdim = INTEGER(dim); int m0 = pdim[0]; if (m0 < m) RMKMS(_("'%s' slot has fewer than %s rows"), "V", "Dim[1]"); if (m0 > m + n) RMKMS(_("'%s' slot has more than %s rows"), "V", "Dim[1]+Dim[2]"); if (pdim[1] != n) RMKMS(_("'%s' slot does not have %s columns"), "V", "Dim[2]"); pp = INTEGER(p); pi = INTEGER(i); for (j = 0, k = 0; j < n; ++j) { kend = pp[j + 1]; if (k < kend) { if (pi[k] < j) RMKMS(_("'%s' slot must be lower trapezoidal but has entries above the diagonal"), "V"); } k = kend; } SEXP R = PROTECT(GET_SLOT(obj, Matrix_RSym)); PROTECT(dim = GET_SLOT(R, Matrix_DimSym)); PROTECT(p = GET_SLOT(R, Matrix_pSym)); PROTECT(i = GET_SLOT(R, Matrix_iSym)); UNPROTECT(4); /* i, p, dim, R */ pdim = INTEGER(dim); if (pdim[0] != m0) RMKMS(_("'%s' slot does not have %s row"), "R", "nrow(V)"); if (pdim[1] != n) RMKMS(_("'%s' slot does not have %s columns"), "R", "Dim[2]"); pp = INTEGER(p); pi = INTEGER(i); for (j = 0, k = 0; j < n; ++j) { kend = pp[j + 1]; if (k < kend) { if (pi[kend - 1] > j) RMKMS(_("'%s' slot must be upper trapezoidal but has entries below the diagonal"), "R"); #if 0 /* cs_house imposes diag(R) >= 0 in CSparse but not in CXSparse */ if (pi[kend - 1] == j && !ISNAN(px[kend - 1]) && px[kend - 1] < 0.0) RMKMS(_("'%s' slot has negative diagonal elements"), "R"); #endif } k = kend; } PROTECT(p = GET_SLOT(obj, Matrix_pSym)); PROTECT(q = GET_SLOT(obj, Matrix_qSym)); UNPROTECT(2); /* q, p */ if (TYPEOF(p) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "p", "integer"); if (TYPEOF(q) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "q", "integer"); if (XLENGTH(p) != m0) RMKMS(_("'%s' slot does not have length %s"), "p", "nrow(V)"); if (XLENGTH(q) != n && XLENGTH(q) != 0) RMKMS(_("'%s' slot does not have length %s or length %s"), "q", "Dim[2]", "0"); char *work; int lwork = m0; /* n <= m <= m0 */ Matrix_Calloc(work, lwork, char); pp = INTEGER(p); for (j = 0; j < m0; ++j) { if (*pp == NA_INTEGER) FRMKMS(_("'%s' slot contains NA"), "p"); if (*pp < 0 || *pp >= m0) FRMKMS(_("'%s' slot has elements not in {%s}"), "p", "0,...,nrow(V)-1"); if (work[*pp]) FRMKMS(_("'%s' slot contains duplicates"), "p"); work[*(pp++)] = 1; } if (LENGTH(q) == n) { pq = INTEGER(q); for (j = 0; j < n; ++j) { if (*pq == NA_INTEGER) FRMKMS(_("'%s' slot contains NA"), "q"); if (*pq < 0 || *pq >= n) FRMKMS(_("'%s' slot has elements not in {%s}"), "q", "0,...,Dim[2]-1"); if (!work[*pq]) FRMKMS(_("'%s' slot contains duplicates"), "q"); work[*(pq++)] = 0; } } Matrix_Free(work, lwork); return ScalarLogical(1); } SEXP BunchKaufman_validate(SEXP obj) { /* In R, we start by checking that 'obj' would be a valid dtrMatrix */ SEXP dim = GET_SLOT(obj, Matrix_DimSym); int n = INTEGER(dim)[0]; SEXP perm = GET_SLOT(obj, Matrix_permSym); if (TYPEOF(perm) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "perm", "integer"); if (XLENGTH(perm) != n) RMKMS(_("'%s' slot does not have length %s"), "perm", "Dim[1]"); int n_ = n, *pperm = INTEGER(perm); while (n_) { if (*pperm == NA_INTEGER) RMKMS(_("'%s' slot contains NA"), "perm"); if (*pperm < -n || *pperm == 0 || *pperm > n) RMKMS(_("'%s' slot has elements not in {%s}\\{%s}"), "perm", "-Dim[1],...,Dim[1]", "0"); if (*pperm > 0) { pperm += 1; n_ -= 1; } else if (n_ > 1 && *(pperm + 1) == *pperm) { pperm += 2; n_ -= 2; } else RMKMS(_("'%s' slot has unpaired negative elements"), "perm"); } return ScalarLogical(1); } SEXP pBunchKaufman_validate(SEXP obj) { /* In R, we start by checking that 'obj' would be a valid dtpMatrix */ return BunchKaufman_validate(obj); } SEXP Cholesky_validate(SEXP obj) { /* In R, we start by checking that 'obj' would be a valid dtrMatrix */ SEXP dim = GET_SLOT(obj, Matrix_DimSym); int j, n = INTEGER(dim)[0]; R_xlen_t n1a = (R_xlen_t) n + 1; /* Non-negative diagonal elements are necessary _and_ sufficient */ SEXP x = GET_SLOT(obj, Matrix_xSym); double *px = REAL(x); for (j = 0; j < n; ++j, px += n1a) if (!ISNAN(*px) && *px < 0.0) RMK(_("Cholesky factor has negative diagonal elements")); SEXP perm = GET_SLOT(obj, Matrix_permSym); if (TYPEOF(perm) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "perm", "integer"); if (XLENGTH(perm) != n && XLENGTH(perm) != 0) RMKMS(_("'%s' slot does not have length %s or length %s"), "perm", "Dim[1]", "0"); if (LENGTH(perm) == n) { char *work; int lwork = n; Matrix_Calloc(work, lwork, char); int *pperm = INTEGER(perm); for (j = 0; j < n; ++j) { if (*pperm == NA_INTEGER) FRMKMS(_("'%s' slot contains NA"), "perm"); if (*pperm < 0 || *pperm >= n) FRMKMS(_("'%s' slot has elements not in {%s}"), "perm", "0,...,Dim[1]-1"); if (work[*pperm]) FRMKMS(_("'%s' slot contains duplicates"), "perm"); work[*(pperm++)] = 1; } Matrix_Free(work, lwork); } return ScalarLogical(1); } SEXP pCholesky_validate(SEXP obj) { /* In R, we start by checking that 'obj' would be a valid dtpMatrix */ SEXP dim = GET_SLOT(obj, Matrix_DimSym); int j, n = INTEGER(dim)[0]; SEXP uplo = GET_SLOT(obj, Matrix_uploSym); char ul = *CHAR(STRING_ELT(uplo, 0)); /* Non-negative diagonal elements are necessary _and_ sufficient */ SEXP x = GET_SLOT(obj, Matrix_xSym); double *px = REAL(x); if (ul == 'U') { for (j = 0; j < n; px += (++j)+1) if (!ISNAN(*px) && *px < 0.0) RMK(_("Cholesky factor has negative diagonal elements")); } else { for (j = 0; j < n; px += n-(j++)) if (!ISNAN(*px) && *px < 0.0) RMK(_("Cholesky factor has negative diagonal elements")); } SEXP perm = GET_SLOT(obj, Matrix_permSym); if (TYPEOF(perm) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "perm", "integer"); if (XLENGTH(perm) != n && XLENGTH(perm) != 0) RMKMS(_("'%s' slot does not have length %s or length %s"), "perm", "Dim[1]", "0"); if (LENGTH(perm) == n) { char *work; int lwork = n; Matrix_Calloc(work, lwork, char); int *pperm = INTEGER(perm); for (j = 0; j < n; ++j) { if (*pperm == NA_INTEGER) FRMKMS(_("'%s' slot contains NA"), "perm"); if (*pperm < 0 || *pperm >= n) FRMKMS(_("'%s' slot has elements not in {%s}"), "perm", "0,...,Dim[1]-1"); if (work[*pperm]) FRMKMS(_("'%s' slot contains duplicates"), "perm"); work[*(pperm++)] = 1; } Matrix_Free(work, lwork); } return ScalarLogical(1); } SEXP CHMfactor_validate(SEXP obj) { SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) RMKMS(_("%s[1] != %s[2] (matrix is not square)"), "Dim", "Dim"); SEXP type = GET_SLOT(obj, install("type")); if (TYPEOF(type) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "type", "integer"); if (XLENGTH(type) != 6) RMKMS(_("'%s' slot does not have length %d"), "type", 6); int order = INTEGER(type)[0]; if (order < 0 || order > 4) RMKMS(_("%s[%d] (%s) is not in %s"), "type", 1, "cholmod_factor.ordering", "0:4"); SEXP colcount = GET_SLOT(obj, install("colcount")); if (TYPEOF(colcount) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "colcount", "integer"); if (XLENGTH(colcount) != n) RMKMS(_("'%s' slot does not have length %s"), "colcount", "Dim[2]"); int j, *pcolcount = INTEGER(colcount); for (j = 0; j < n; ++j) { if (pcolcount[j] == NA_INTEGER) RMKMS(_("'%s' slot contains NA"), "colcount"); if (pcolcount[j] < 0 || pcolcount[j] > n - j) RMKMS(_("%s is not in {%s}"), "colcount[j]", "0,...,Dim[1]-j+1"); } SEXP perm = GET_SLOT(obj, Matrix_permSym); if (TYPEOF(perm) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "perm", "integer"); if (order == 0) { if (XLENGTH(perm) != 0) RMKMS(_("'%s' slot does not have length %d"), "perm", 0); } else { if (XLENGTH(perm) != n) RMKMS(_("'%s' slot does not have length %s"), "perm", "Dim[1]"); char *work; int lwork = n; Matrix_Calloc(work, lwork, char); int *pperm = INTEGER(perm); for (j = 0; j < n; ++j) { if (*pperm == NA_INTEGER) FRMKMS(_("'%s' slot contains NA"), "perm"); if (*pperm < 0 || *pperm >= n) FRMKMS(_("'%s' slot has elements not in {%s}"), "perm", "0,...,Dim[1]-1"); if (work[*pperm]) FRMKMS(_("'%s' slot contains duplicates"), "perm"); work[*(pperm++)] = 1; } Matrix_Free(work, lwork); } return ScalarLogical(1); } SEXP CHMsimpl_validate(SEXP obj) { SEXP dim = GET_SLOT(obj, Matrix_DimSym); int n = INTEGER(dim)[0]; if (n == INT_MAX) RMKMS(_("%s is not representable as \"%s\""), "Dim[1]+1", "integer"); SEXP type = GET_SLOT(obj, install("type")); int *ptype = INTEGER(type), mono = ptype[3]; if (ptype[1] != 0 && ptype[1] != 1) RMKMS(_("%s[%d] (%s) is not %d or %d"), "type", 2, "cholmod_factor.is_ll", 0, 1); if (ptype[2] != 0) RMKMS(_("%s[%d] (%s) is not %d"), "type", 3, "cholmod_factor.is_super", 0); if (ptype[3] != 0 && ptype[3] != 1) RMKMS(_("%s[%d] (%s) is not %d or %d"), "type", 4, "cholmod_factor.is_monotonic", 0, 1); SEXP nxt = PROTECT(GET_SLOT(obj, install("nxt"))), prv = PROTECT(GET_SLOT(obj, install("prv"))), nz = PROTECT(GET_SLOT(obj, install("nz"))), p = PROTECT(GET_SLOT(obj, Matrix_pSym)), i = PROTECT(GET_SLOT(obj, Matrix_iSym)); UNPROTECT(5); /* i, p, nz, prv, nxt */ if (TYPEOF(nxt) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "nxt", "integer"); if (TYPEOF(prv) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "prv", "integer"); if (XLENGTH(nxt) - 2 != n) RMKMS(_("'%s' slot does not have length %s"), "nxt", "Dim[2]+2"); if (XLENGTH(prv) - 2 != n) RMKMS(_("'%s' slot does not have length %s"), "prv", "Dim[2]+2"); int *pnxt = INTEGER(nxt), *pprv = INTEGER(prv), j1 = pnxt[n + 1], j2 = pprv[n], count = n + 1; while (count--) { if (j1 < 0 || j1 > n) RMKMS(_("%s has elements not in {%s}"), "nxt[-(Dim[2]+1)]", "0,...,Dim[2]"); if (j2 < 0 || j2 > n + 1 || j2 == n) RMKMS(_("%s has elements not in {%s}\\{%s}"), "prv[-(Dim[2]+2)]", "0,...,Dim[2]+1", "Dim[2]"); if ((count > 1) && mono && (pnxt[j1] != j1 + 1 || pprv[j2] != j2 - 1)) RMKMS(_("%s is %d but columns are not stored in increasing order"), "type[4]", 1); if ((count >= 1) ? j1 == n : j1 != n) RMKMS(_("traversal of '%s' slot does not complete in exactly %s steps"), "nxt", "length(nxt)"); if ((count >= 1) ? j2 == n + 1 : j2 != n + 1) RMKMS(_("traversal of '%s' slot does not complete in exactly %s steps"), "prv", "length(prv)"); j1 = pnxt[j1]; j2 = pprv[j2]; } if (j1 != -1) RMKMS(_("%s is not %d"), "nxt[Dim[2]+1]", -1); if (j2 != -1) RMKMS(_("%s is not %d"), "prv[Dim[2]+2]", -1); if (TYPEOF(nz) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "nz", "integer"); if (XLENGTH(nz) != n) RMKMS(_("'%s' slot does not have length %s"), "nz", "Dim[2]"); int j, *pnz = INTEGER(nz); for (j = 0; j < n; ++j) { if (pnz[j] == NA_INTEGER) RMKMS(_("'%s' slot contains NA"), "nz"); if (pnz[j] < 1 || pnz[j] > n - j) RMKMS(_("%s is not in {%s}"), "nz[j]", "1,...,Dim[1]-j+1"); } if (TYPEOF(p) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "p", "integer"); if (XLENGTH(p) - 1 != n) RMKMS(_("'%s' slot does not have length %s"), "p", "Dim[2]+1"); j1 = pnxt[n + 1]; int *pp = INTEGER(p); if (pp[j1] != 0) RMKMS(_("column '%s' is stored first but %s is not 0"), "j", "p[j]"); for (j = 0; j < n; ++j) { j2 = pnxt[j1]; if (pp[j2] == NA_INTEGER) RMKMS(_("'%s' slot contains NA"), "p"); if (pp[j2] < pp[j1]) RMKMS(_("'%s' slot is not increasing when traversed in stored column order"), "p"); if (pp[j2] - pp[j1] < pnz[j1]) RMKMS(_("'%s' slot allocates fewer than %s elements for column '%s'"), "i", "nz[j]", "j"); if (pp[j2] - pp[j1] > n - j1) RMKMS(_("'%s' slot allocates more than %s elements for column '%s'"), "i", "Dim[2]-j+1", "j"); j1 = j2; } if (TYPEOF(i) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "i", "integer"); if (XLENGTH(i) != pp[n]) RMKMS(_("'%s' slot does not have length %s"), "i", "p[length(p)]"); int *pi = INTEGER(i), *pi_, k; j1 = pnxt[n + 1]; for (j = 0; j < n; ++j) { pi_ = pi + pp[j1]; if (pi_[0] != j1) RMKMS(_("first entry in column '%s' does not have row index '%s'"), "j", "j"); for (k = 1; k < pnz[j1]; ++k) { if (pi_[k] == NA_INTEGER) RMKMS(_("'%s' slot contains NA"), "i"); if (pi_[k] < 0 || pi_[k] >= n) RMKMS(_("'%s' slot has elements not in {%s}"), "i", "0,...,Dim[1]-1"); if (pi_[k] <= pi_[k - 1]) RMKMS(_("'%s' slot is not increasing within columns"), "i"); } j1 = pnxt[j1]; } return ScalarLogical(1); } SEXP CHMsuper_validate(SEXP obj) { SEXP dim = GET_SLOT(obj, Matrix_DimSym); int n = INTEGER(dim)[0]; SEXP type = GET_SLOT(obj, install("type")); int *ptype = INTEGER(type); if (ptype[1] != 1) RMKMS(_("%s[%d] (%s) is not %d"), "type", 2, "cholmod_factor.is_ll", 1); if (ptype[2] != 1) RMKMS(_("%s[%d] (%s) is not %d"), "type", 3, "cholmod_factor.is_super", 1); if (ptype[3] != 1) RMKMS(_("%s[%d] (%s) is not %d"), "type", 4, "cholmod_factor.is_monotonic", 1); if (ptype[4] < 0) RMKMS(_("%s[%d] (%s) is negative"), "type", 5, "cholmod_factor.maxcsize"); if (ptype[5] < 0) RMKMS(_("%s[%d] (%s) is negative"), "type", 6, "cholmod_factor.maxesize"); if (n > 0 && ptype[5] >= n) RMKMS(_("%s[%d] (%s) is not less than %s"), "type", 6, "cholmod_factor.maxesize", "Dim[1]"); /* FIXME: maxcsize and maxesize are well-defined properties of the factorization, so we should also test that the values are _correct_ ... see CHOLMOD/Supernodal/cholmod_super_symbolic.c */ SEXP super = PROTECT(GET_SLOT(obj, install("super"))), pi = PROTECT(GET_SLOT(obj, install("pi"))), px = PROTECT(GET_SLOT(obj, install("px"))), s = PROTECT(GET_SLOT(obj, install("s"))); UNPROTECT(4); /* s, px, pi, super */ if (TYPEOF(super) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "super", "integer"); R_xlen_t nsuper1a = XLENGTH(super); if (nsuper1a - 1 < ((n > 0) ? 1 : 0)) RMKMS(_("'%s' slot has length less than %d"), "super", 2); if (nsuper1a - 1 > n) RMKMS(_("'%s' slot has length greater than %s"), "super", "Dim[2]+1"); int k, nsuper = (int) (nsuper1a - 1), *psuper = INTEGER(super); if (psuper[0] != 0) RMKMS(_("first element of '%s' slot is not 0"), "super"); if (psuper[nsuper] != n) RMKMS(_("last element of '%s' slot is not %s"), "super", "Dim[2]"); for (k = 1; k <= nsuper; ++k) { if (psuper[k] == NA_INTEGER) RMKMS(_("'%s' slot contains NA"), "super"); if (psuper[k] <= psuper[k - 1]) RMKMS(_("'%s' slot is not increasing"), "super"); } if (TYPEOF(pi) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "pi", "integer"); if (TYPEOF(px) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "px", "integer"); if (XLENGTH(pi) != nsuper1a) RMKMS(_("'%s' and '%s' slots do not have equal length"), "pi", "super"); if (XLENGTH(px) != nsuper1a) RMKMS(_("'%s' and '%s' slots do not have equal length"), "px", "super"); int *ppi = INTEGER(pi), *ppx = INTEGER(px), nr, nc; if (ppi[0] != 0) RMKMS(_("first element of '%s' slot is not 0"), "pi"); if (ppx[0] != 0) RMKMS(_("first element of '%s' slot is not 0"), "px"); for (k = 1; k <= nsuper; ++k) { if (ppi[k] == NA_INTEGER) RMKMS(_("'%s' slot contains NA"), "pi"); if (ppx[k] == NA_INTEGER) RMKMS(_("'%s' slot contains NA"), "px"); if (ppi[k] <= ppi[k - 1]) RMKMS(_("'%s' slot is not increasing"), "pi"); if (ppx[k] <= ppx[k - 1]) RMKMS(_("'%s' slot is not increasing"), "px"); nr = ppi[k] - ppi[k - 1]; nc = psuper[k] - psuper[k - 1]; if (nr < nc) RMKMS(_("first differences of '%s' slot are less than those of '%s' slot"), "pi", "super"); if ((Matrix_int_fast64_t) nr * nc > INT_MAX) RMKMS(_("supernode lengths exceed %s"), "2^31-1"); if (ppx[k] - ppx[k - 1] != nr * nc) RMKMS(_("first differences of '%s' slot are not equal to supernode lengths"), "px"); } if (TYPEOF(s) != INTSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "s", "integer"); if (XLENGTH(s) != ppi[nsuper]) RMKMS(_("'%s' slot does not have length %s"), "s", "pi[length(pi)]"); int i, j, *ps = INTEGER(s); for (k = 1; k <= nsuper; ++k) { nr = ppi[k] - ppi[k-1]; nc = psuper[k] - (j = psuper[k-1]); for (i = 0; i < nr; ++i) { if (ps[i] == NA_INTEGER) RMKMS(_("'%s' slot contains NA"), "s"); if (ps[i] < 0 || ps[i] >= n) RMKMS(_("'%s' slot has elements not in {%s}"), "s", "0,...,Dim[1]-1"); if (i < nc) { if (ps[i] != j + i) RMKMS(_("'%s' slot is wrong within diagonal blocks (row and column indices do not coincide)"), "s"); } else { if (ps[i] <= ps[i-1]) RMKMS(_("'%s' slot is not increasing within supernodes"), "s"); } } ps += nr; } return ScalarLogical(1); } SEXP dCHMsimpl_validate(SEXP obj) { SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), p = PROTECT(GET_SLOT(obj, Matrix_pSym)), type = PROTECT(GET_SLOT(obj, install("type"))); UNPROTECT(3); /* type, p, x */ if (TYPEOF(x) != REALSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "x", "double"); int *pp = INTEGER(p), n = (int) (XLENGTH(p) - 1); if (XLENGTH(x) != pp[n]) RMKMS(_("'%s' slot does not have length %s"), "x", "p[length(p)]"); if (INTEGER(type)[1]) { int j; double *px = REAL(x); /* Non-negative diagonal elements are necessary _and_ sufficient */ for (j = 0; j < n; ++j) if (!ISNAN(px[pp[j]]) && px[pp[j]] < 0.0) RMK(_("Cholesky factor has negative diagonal elements")); } return ScalarLogical(1); } SEXP dCHMsuper_validate(SEXP obj) { SEXP x = PROTECT(GET_SLOT(obj, Matrix_xSym)), px = PROTECT(GET_SLOT(obj, install("px"))), pi = PROTECT(GET_SLOT(obj, install("pi"))), super = PROTECT(GET_SLOT(obj, install("super"))); UNPROTECT(4); /* super, pi, px, x */ if (TYPEOF(x) != REALSXP) RMKMS(_("'%s' slot is not of type \"%s\""), "x", "double"); int *ppx = INTEGER(px), nsuper = (int) (XLENGTH(px) - 1); if (XLENGTH(x) != ppx[nsuper]) RMKMS(_("'%s' slot does not have length %s"), "x", "px[length(px)]"); int *ppi = INTEGER(pi), *psuper = INTEGER(super), k, j, nc; double *pu = REAL(x), *pv; R_xlen_t nr1a; /* Non-negative diagonal elements are necessary _and_ sufficient */ for (k = 0; k < nsuper; ++k) { nc = psuper[k+1] - psuper[k]; nr1a = (R_xlen_t) (ppi[k+1] - ppi[k]) + 1; pv = pu + ppx[k]; for (j = 0; j < nc; ++j) { if (!ISNAN(*pv) && *pv < 0.0) RMK(_("Cholesky factor has negative diagonal elements")); pv += nr1a; } } return ScalarLogical(1); } SEXP Schur_validate(SEXP obj) { /* MJ: assuming for simplicity that 'Q' and 'T' slots are formally valid */ SEXP dim = GET_SLOT(obj, Matrix_DimSym); int *pdim = INTEGER(dim), n = pdim[0]; if (pdim[1] != n) RMKMS(_("%s[1] != %s[2] (matrix is not square)"), "Dim", "Dim"); SEXP Q = PROTECT(GET_SLOT(obj, Matrix_QSym)); dim = GET_SLOT(Q, Matrix_DimSym); pdim = INTEGER(dim); UNPROTECT(1); /* Q */ if (pdim[0] != n || pdim[1] != n) RMKMS(_("dimensions of '%s' slot are not identical to '%s'"), "Q", "Dim"); SEXP T = PROTECT(GET_SLOT(obj, Matrix_TSym)); dim = GET_SLOT(T, Matrix_DimSym); pdim = INTEGER(dim); UNPROTECT(1); /* T */ if (pdim[0] != n || pdim[1] != n) RMKMS(_("dimensions of '%s' slot are not identical to '%s'"), "T", "Dim"); SEXP v = GET_SLOT(obj, install("EValues")); SEXPTYPE tv = TYPEOF(v); if (tv != REALSXP && tv != CPLXSXP) RMKMS(_("'%s' slot is not of type \"%s\" or \"%s\""), "EValues", "double", "complex"); if (XLENGTH(v) != n) RMKMS(_("'%s' slot does not have length %s"), "EValues", "Dim[1]"); return ScalarLogical(1); } /* where 'cl' must be an element of VALID_NONVIRTUAL_MATRIX */ void validObject(SEXP obj, const char *cl) { #ifndef MATRIX_DISABLE_VALIDITY SEXP status; # define IS_VALID(_CLASS_) \ do { \ status = _CLASS_ ## _validate(obj); \ if (TYPEOF(status) == STRSXP) \ error(_("invalid class \"%s\" object: %s"), \ cl, CHAR(STRING_ELT(status, 0))); \ } while (0) #define IS_VALID_SPARSE(_C_) \ do { \ IS_VALID(_C_ ## sparseMatrix); \ if (cl[0] == 'n') { \ if (cl[1] == 's') \ IS_VALID(s ## _C_ ## Matrix); \ else if (cl[1] == 't') \ IS_VALID(t ## _C_ ## Matrix); \ } else { \ if (cl[1] == 'g') \ IS_VALID(xg ## _C_ ## Matrix); \ else if (cl[1] == 's') \ IS_VALID(xs ## _C_ ## Matrix); \ else if (cl[1] == 't') \ IS_VALID(xt ## _C_ ## Matrix); \ } \ } while (0) IS_VALID(Matrix); if ((cl[0] == 'i' && cl[1] == 'n' && cl[2] == 'd') || (cl[0] == 'p' && cl[1] != 'c')) { IS_VALID(indMatrix); if (cl[0] == 'p') IS_VALID(pMatrix); return; } const char *cl_ = cl; if (cl[0] == 'c') cl = "dpoMatrix"; else if (cl[0] == 'p' && cl[1] == 'c') cl = "dppMatrix"; if (cl[0] == 'n' && cl[2] != 'C' && cl[2] != 'R' && cl[2] != 'T') IS_VALID(nMatrix); else if (cl[0] == 'l') IS_VALID(lMatrix); else if (cl[0] == 'i') IS_VALID(iMatrix); else if (cl[0] == 'd') IS_VALID(dMatrix); else if (cl[0] == 'z') IS_VALID(zMatrix); if (cl[1] == 's' || cl[1] == 'p') IS_VALID(symmetricMatrix); else if (cl[1] == 't') IS_VALID(triangularMatrix); else if (cl[1] == 'd') { IS_VALID(diagonalMatrix); return; } if (cl[2] == 'C') IS_VALID_SPARSE(C); else if (cl[2] == 'R') IS_VALID_SPARSE(R); else if (cl[2] == 'T') IS_VALID_SPARSE(T); else if (cl[2] != 'p') { IS_VALID(unpackedMatrix); if (cl[1] == 'p') { IS_VALID(dpoMatrix); if (cl_[0] == 'c') IS_VALID(corMatrix); } } else { IS_VALID(packedMatrix); if (cl[1] == 'p') { IS_VALID(dppMatrix); if (cl_[0] == 'c') IS_VALID(copMatrix); } } # undef IS_VALID_SPARSE # undef IS_VALID #endif return; } Matrix/vignettes/0000755000175100001440000000000014576344040013553 5ustar hornikusersMatrix/vignettes/Comparisons.Rnw0000644000175100001440000002166314444514070016544 0ustar hornikusers\documentclass{article} \usepackage{myVignette} \usepackage[authoryear,round]{natbib} \bibliographystyle{plainnat} %%\VignetteIndexEntry{Comparisons of Least Squares calculation speeds} %%\VignetteDepends{Matrix,datasets,stats,utils} \begin{document} \SweaveOpts{engine=R,eps=FALSE,pdf=TRUE,width=5,height=3,strip.white=true,keep.source=TRUE} \setkeys{Gin}{width=\textwidth} \title{Comparing Least Squares Calculations} \author{Douglas Bates\\R Development Core Team\\\email{Douglas.Bates@R-project.org}} \date{\today} \maketitle \begin{abstract} Many statistics methods require one or more least squares problems to be solved. There are several ways to perform this calculation, using objects from the base R system and using objects in the classes defined in the \code{Matrix} package. We compare the speed of some of these methods on a very small example and on a example for which the model matrix is large and sparse. \end{abstract} <>= options(width=75) library(stats) # for R_DEFAULT_PACKAGES=NULL library(utils) # ditto @ \section{Linear least squares calculations} \label{sec:LeastSquares} Many statistical techniques require least squares solutions \begin{equation} \label{eq:LeastSquares} \widehat{\bm{\beta}}= \arg\min_{\bm{\beta}}\left\|\bm{y}-\bX\bm{\beta}\right\|^2 \end{equation} where $\bX$ is an $n\times p$ model matrix ($p\leq n$), $\bm{y}$ is $n$-dimensional and $\bm{\beta}$ is $p$ dimensional. Most statistics texts state that the solution to (\ref{eq:LeastSquares}) is \begin{equation} \label{eq:XPX} \widehat{\bm{\beta}}=\left(\bX\trans\bX\right)^{-1}\bX\trans\bm{y} \end{equation} when $\bX$ has full column rank (i.e. the columns of $\bX$ are linearly independent) and all too frequently it is calculated in exactly this way. \subsection{A small example} \label{sec:smallLSQ} As an example, let's create a model matrix, \code{mm}, and corresponding response vector, \code{y}, for a simple linear regression model using the \code{Formaldehyde} data. <>= data(Formaldehyde, package = "datasets") str(Formaldehyde) (m <- cbind(1, Formaldehyde$carb)) (yo <- Formaldehyde$optden) @ Using \code{t} to evaluate the transpose, \code{solve} to take an inverse, and the \code{\%*\%} operator for matrix multiplication, we can translate \ref{eq:XPX} into the \Slang{} as <>= solve(t(m) %*% m) %*% t(m) %*% yo @ On modern computers this calculation is performed so quickly that it cannot be timed accurately in \RR{} \footnote{From R version 2.2.0, \code{system.time()} has default argument \code{gcFirst = TRUE} which is assumed and relevant for all subsequent timings} <>= system.time(solve(t(m) %*% m) %*% t(m) %*% yo) @ and it provides essentially the same results as the standard \code{lm.fit} function that is called by \code{lm}. <>= dput(c(solve(t(m) %*% m) %*% t(m) %*% yo)) dput(unname(lm.fit(m, yo)$coefficients)) @ %$ \subsection{A large example} \label{sec:largeLSQ} For a large, ill-conditioned least squares problem, such as that described in \citet{koen:ng:2003}, the literal translation of (\ref{eq:XPX}) does not perform well. <>= library(Matrix) data(KNex, package = "Matrix") y <- KNex$y mm <- as(KNex$mm, "matrix") # full traditional matrix dim(mm) system.time(naive.sol <- solve(t(mm) %*% mm) %*% t(mm) %*% y) @ Because the calculation of a ``cross-product'' matrix, such as $\bX\trans\bX$ or $\bX\trans\bm{y}$, is a common operation in statistics, the \code{crossprod} function has been provided to do this efficiently. In the single argument form \code{crossprod(mm)} calculates $\bX\trans\bX$, taking advantage of the symmetry of the product. That is, instead of calculating the $712^2=506944$ elements of $\bX\trans\bX$ separately, it only calculates the $(712\cdot 713)/2=253828$ elements in the upper triangle and replicates them in the lower triangle. Furthermore, there is no need to calculate the inverse of a matrix explicitly when solving a linear system of equations. When the two argument form of the \code{solve} function is used the linear system \begin{equation} \label{eq:LSQsol} \left(\bX\trans\bX\right) \widehat{\bm{\beta}} = \bX\trans\by \end{equation} is solved directly. Combining these optimizations we obtain <>= system.time(cpod.sol <- solve(crossprod(mm), crossprod(mm,y))) all.equal(naive.sol, cpod.sol) @ On this computer (2.0 GHz Pentium-4, 1 GB Memory, Goto's BLAS, in Spring 2004) the crossprod form of the calculation is about four times as fast as the naive calculation. In fact, the entire crossprod solution is faster than simply calculating $\bX\trans\bX$ the naive way. <>= system.time(t(mm) %*% mm) @ Note that in newer versions of \RR{} and the BLAS library (as of summer 2007), \RR's \code{\%*\%} is able to detect the many zeros in \code{mm} and shortcut many operations, and is hence much faster for such a sparse matrix than \code{crossprod} which currently does not make use of such optimizations. This is not the case when \RR{} is linked against an optimized BLAS library such as GOTO or ATLAS. %% Also, for fully dense matrices, \code{crossprod()} indeed remains faster (by a factor of two, typically) independently of the BLAS library: <>= fm <- mm set.seed(11) fm[] <- rnorm(length(fm)) system.time(c1 <- t(fm) %*% fm) system.time(c2 <- crossprod(fm)) stopifnot(all.equal(c1, c2, tol = 1e-12)) @ % using stopifnot(.) to save output \subsection{Least squares calculations with Matrix classes} \label{sec:MatrixLSQ} The \code{crossprod} function applied to a single matrix takes advantage of symmetry when calculating the product but does not retain the information that the product is symmetric (and positive semidefinite). As a result the solution of (\ref{eq:LSQsol}) is performed using general linear system solver based on an LU decomposition when it would be faster, and more stable numerically, to use a Cholesky decomposition. The Cholesky decomposition could be used but it is rather awkward <>= system.time(ch <- chol(crossprod(mm))) system.time(chol.sol <- backsolve(ch, forwardsolve(ch, crossprod(mm, y), upper = TRUE, trans = TRUE))) stopifnot(all.equal(chol.sol, naive.sol)) @ The \code{Matrix} package uses the S4 class system \citep{R:Chambers:1998} to retain information on the structure of matrices from the intermediate calculations. A general matrix in dense storage, created by the \code{Matrix} function, has class \code{"dgeMatrix"} but its cross-product has class \code{"dpoMatrix"}. The \code{solve} methods for the \code{"dpoMatrix"} class use the Cholesky decomposition. <>= mm <- as(KNex$mm, "denseMatrix") class(crossprod(mm)) system.time(Mat.sol <- solve(crossprod(mm), crossprod(mm, y))) stopifnot(all.equal(naive.sol, unname(as(Mat.sol,"matrix")))) @ Furthermore, any method that calculates a decomposition or factorization stores the resulting factorization with the original object so that it can be reused without recalculation. <>= xpx <- crossprod(mm) xpy <- crossprod(mm, y) system.time(solve(xpx, xpy)) system.time(solve(xpx, xpy)) # reusing factorization @ The model matrix \code{mm} is sparse; that is, most of the elements of \code{mm} are zero. The \code{Matrix} package incorporates special methods for sparse matrices, which produce the fastest results of all. <>= mm <- KNex$mm class(mm) system.time(sparse.sol <- solve(crossprod(mm), crossprod(mm, y))) stopifnot(all.equal(naive.sol, unname(as(sparse.sol, "matrix")))) @ As with other classes in the \code{Matrix} package, the \code{dsCMatrix} retains any factorization that has been calculated although, in this case, the decomposition is so fast that it is difficult to determine the difference in the solution times. <>= xpx <- crossprod(mm) xpy <- crossprod(mm, y) system.time(solve(xpx, xpy)) system.time(solve(xpx, xpy)) @ \subsection*{Session Info} <>= toLatex(sessionInfo()) @ <>= if(identical(1L, grep("linux", R.version[["os"]]))) { ##----- Linux - only ---- Sys.procinfo <- function(procfile) { l2 <- strsplit(readLines(procfile),"[ \t]*:[ \t]*") r <- sapply(l2[sapply(l2, length) == 2], function(c2)structure(c2[2], names= c2[1])) attr(r,"Name") <- procfile class(r) <- "simple.list" r } Scpu <- Sys.procinfo("/proc/cpuinfo") Smem <- Sys.procinfo("/proc/meminfo") } # Linux only @ <>= if(identical(1L, grep("linux", R.version[["os"]]))) { ## Linux - only --- Scpu <- sfsmisc::Sys.procinfo("/proc/cpuinfo") Smem <- sfsmisc::Sys.procinfo("/proc/meminfo") print(Scpu[c("model name", "cpu MHz", "cache size", "bogomips")]) print(Smem[c("MemTotal", "SwapTotal")]) } @ <>= if(identical(1L, grep("linux", R.version[["os"]]))) { ## Linux - only --- print(Scpu[c("model name", "cpu MHz", "cache size", "bogomips")]) print(Smem[c("MemTotal", "SwapTotal")]) } @ \bibliography{Matrix} \end{document} Matrix/vignettes/Matrix.bib0000644000175100001440000003410412764547531015506 0ustar hornikusers@BOOK{R:Venables+Ripley:2000, AUTHOR = {William N. Venables and Brian D. Ripley}, TITLE = {S Programming}, PUBLISHER = {Springer}, YEAR = 2000, NOTE = {ISBN 0-387-98966-8}, URL = {http://www.stats.ox.ac.uk/pub/MASS3/Sprog/}, ABSTRACT = {This provides an in-depth guide to writing software in the S language which forms the basis of both the commercial S-PLUS and the Open Source R data analysis software systems.} } @BOOK{R:Chambers+Hastie:1992, AUTHOR = {John M. Chambers and Trevor J. Hastie}, TITLE = {Statistical Models in {S}}, PUBLISHER = {Chapman \& Hall}, YEAR = 1992, ADDRESS = {London}, ISBN = {0-412-83040-X}, ABSTRACT = {This is also called the ``\emph{White Book}'', and introduced S version 3, which added structures to facilitate statistical modeling in S. } } @Article{Rnews:Gentleman+Carey:2002, author = {Robert Gentleman and Vincent Carey}, title = {Bioconductor}, journal = {R News}, year = 2002, volume = 2, number = 1, pages = {11--16}, month = {March}, url = {https://CRAN.R-project.org/doc/Rnews/} } @article{Ke:Wang:2001, author = {Ke, Chunlei and Wang, Yuedong}, title = {Semiparametric nonlinear mixed-effects models and their applications}, year = {2001}, journal = {Journal of the American Statistical Association}, volume = {96}, number = {456}, pages = {1272--1298}, keywords = {NONLINEAR MIXED EFFECTS MODEL; Penalized likelihood; Repeated measures; SELF-MODELING NONLINEAR REGRESSION; Smoothing spline} } @Article{Lind:Bate:1988, author = {Lindstrom, Mary J. and Bates, Douglas M.}, title = {Newton-{R}aphson and {EM} algorithms for linear mixed-effects models for repeated-measures data ({C}orr: 94{V}89 p1572)}, year = {1988}, journal = {Journal of the American Statistical Association}, volume = {83}, pages = {1014--1022}, keywords = {Growth curve; Longitudinal data} } @ARTICLE{Atlas, AUTHOR = "R. Clint Whaley and Antoine Petitet and Jack J. Dongarra", TITLE = "Automated Empirical Optimization of Software and the {ATLAS} Project", JOURNAL = "Parallel Computing", VOLUME = "27", NUMBER = "1--2", PAGES = "3--35", YEAR = 2001, NOTE = "Also available as University of Tennessee LAPACK Working Note \#147, UT-CS-00-448, 2000 ({\tt www.netlib.org/lapack/lawns/lawn147.ps})" } @TechReport{GotosBLAS, author = {Kazushige Goto and Robert van de Geijn}, title = {On Reducing TLB Misses in Matrix Multiplication}, institution = {Department of Computer Sciences, U. of Texas at Austin}, year = 2002, number = {TR02-55} } @Misc{Taucs, author = {Sivan Toledo}, title = {Taucs: A Library of Sparse Linear Solvers}, howpublished = {http://www.tau.ac.il/~stoledo/taucs/}, year = 2003 } @Misc{Umfpack, author = {Tim Davis}, title = {UMFPACK: Unified Multifrontal Package}, howpublished = {http://www.cise.ufl.edu/research/sparse/umfpack}, year = 2003 } @misc{Cholmod, author = {Tim Davis}, title = {{CHOLMOD}: sparse supernodal {Cholesky} factorization and update/downdate}, howpublished = {http://www.cise.ufl.edu/research/sparse/cholmod}, year = 2005 } @Misc{CSparse, author = {Tim Davis}, title = {{CSparse}: a concise sparse matrix package}, howpublished = {http://www.cise.ufl.edu/research/sparse/CSparse}, year = 2005 } @Book{davis06:csparse_book, author = {Timothy A. Davis }, title = {Direct Methods for Sparse Linear Systems}, publisher = {SIAM}, year = 2006, series = {Fundamentals of Algorithms} } @Misc{Metis, author = {George Karapis}, title = {Metis: Family of Multilevel Partioning Algorithms}, howpublished = {http://www-users.cs.umn.edu/~karypis/metis/}, year = 2003 } @Book{Linpack, author = {Jack Dongarra and Cleve Moler and Bunch and G.W. Stewart}, title = {Linpack Users' Guide}, publisher = {SIAM}, year = 1979 } @Book{Lapack, author = {E. Anderson and Z. Bai and C. Bischof and S. Blackford and J. Demmel and J. Dongarra and J. Du Croz and A. Greenbaum and S. Hammarling and A. McKenney and D. Sorensen}, title = {LAPACK Users' Guide}, chapter = {}, publisher = {SIAM}, year = 1999, address = {Philadelphia, PA}, edition = {3rd} } @Book{bryk00:_hlm, author = {A. S. Bryk and S. W. Raudenbush and R. Congdon}, title = {{HLM} version 5}, publisher = {Scientific Software International, Inc.}, year = 2000, address = {Chicago} } @Article{demp:lair:rubi:1977, Journal = JRSSB, Volume = 39, Pages = {1--22}, Keywords = {Posterior mode}, Author = {A. P. Dempster and N. M. Laird and D. B. Rubin}, Title = {Maximum Likelihood From Incomplete Data Via the {EM} Algorithm}, Year = 1977 } @Book{denn:schn:1983, author = {J. E. Dennis and R. B. Schnabel}, title = {Numerical Methods for Unconstrained Optimization and Nonlinear Equations}, publisher = {Prentice-Hall}, year = 1983, address = {Englewood Cliffs, NJ} } @Book{dong:bunc:mole:stew:1979, publisher = "SIAM", address = "Philadelphia", author = "J. J. Dongarra and J. R. Bunch and C. B. Moler and G. W. Stewart", title = "Linpack Users' Guide", year = 1979 } @Book{goldstein98:_mlwin, author = {H. Goldstein and J. Rasbash and I. Plewis and D. Draper and W. Browne and M. Wang}, title = {A user's guide to {MLwiN}}, publisher = {University of London, Institute of Education}, year = 1998, address = {London} } @Book{golu:vanl:1996, author = {Golub, Gene H. and van Loan, Charles F.}, title = {Matrix Computations}, publisher = {Johns Hopkins}, year = 1996, edition = {3rd} } @Article{ harv:1974, author = {Harville, David A.}, title = {Bayesian Inference for Variance Components Using Only Error Contrasts}, journal = {Biometrika}, year = 1974, volume = 61, pages = {383--385}, keywords = {Maximum likelihood} } @Article{ lair:ware:1982, author = {Laird, Nan M. and Ware, James H.}, title = {Random-effects Models for Longitudinal Data}, journal = {Biometrics}, year = 1982, volume = 38, pages = {963--974}, keywords = {Variance components; Repeated measurements; Empirical Bayes; EM algorithm} } @Book{lapack:1992, publisher = "SIAM", address = "Philadelphia", author = "E. Anderson and Z. Bai and C. Bischof and J. Demmel and J. Dongarra and J. Du Croz and A. Greenbaum and S. Hammaring and A. McKenney and S. Ostrouchov and D. Sorensen", title = "Lapack Users' Guide", year = 1992 } @Article{liu:rubi:1994, author = {Liu, Chuanhai and Rubin, Donald B.}, title = {The {ECME} algorithm: {A} simple extension of {EM} and {ECM} with faster monotone convergence}, year = {1994}, journal = {Biometrika}, volume = {81}, pages = {633--648}, keywords = {Markov chain monte carlo; Incomplete data} } @article{patt:thom:1971, Author = {Patterson, H. D. and Thompson, R.}, Title = {Recovery of Interblock Information When Block Sizes Are Unequal}, Year = 1971, Journal = {Biometrika}, Volume = 58, Pages = {545--554}, Keywords = {Incomplete block design; Components of variance; Maximum likelihood; Design of experiments} } @phdthesis{pinh:1994, author = {Jos\'{e} C. Pinheiro}, title = {Topics in Mixed-Effects Models}, school = {University of Wisconsin}, year = 1994, address = {Madison, WI} } @Article{pinh:bate:1995, author = "Jos\'{e} C. Pinheiro and Douglas M. Bates", title = "Approximations to the Log-Likelihood Function in the Nonlinear Mixed-Effects Model", year = 1995, journal = "Journal of Computational and Graphical Statistics", volume = 4, number = 1, pages = "12--35" } @Article{ pinh:bate:1996, author = {Jos\'{e} C. Pinheiro and Douglas M. Bates}, title = {Unconstrained Parameterizations for Variance-Covariance Matrices}, journal = {Statistics and Computing}, year = 1996, volume = 6, pages = {289--296} } @Book{pinh:bate:2000, author = {Jos\'{e} C. Pinheiro and Douglas M. Bates}, title = {Mixed-Effects Models in {S} and {S-PLUS}}, year = 2000, pages = {528}, ISBN = {0-387-98957-9}, publisher = {Springer} } @Article{schn:koon:1985, Journal = {ACM Trans. Math. Software}, Volume = 11, Pages = {419--440}, Author = {R. B. Schnabel and J. E. Koontz and B. E. Weiss}, Title = {A modular system of algorithms for unconstrained minimization}, Year = 1985 } @book{snijders99:_multil_analy, author = {Tom Snijders and Roel Bosker}, title = {Multilevel Analysis: An introduction to basic and advanced multilevel analysis}, publisher = {Sage}, year = 1999, address = {London} } @book{this:1988, Author = {Thisted, R. A.}, Title = {Elements of Statistical Computing}, Year = 1988, Publisher = {Chapman \& Hall}, address = {London} } @Article{van:2000, author = {van Dyk, David A.}, title = {Fitting mixed-effects models using efficient {EM}-type algorithms}, year = {2000}, journal = {Journal of Computational and Graphical Statistics}, volume = {9}, number = {1}, pages = {78--98}, keywords = {EM algorithm; ECME algorithm; Gaussian hierarchical models; Posterior inference; PXEM algorithm; random-effects models; Reml; variance-component models; working parameters} } @misc{jfox:2002, author = {Fox, John}, title = {Linear Mixed Models -- Appendix to {An R and S-PLUS Companion to Applied Regression}}, year = 2002, month= {May}, url = {http://www.socsci.mcmaster.ca/jfox/Books/companion/appendix-mixed-models.pdf} } @book{roge:1980, Author = {Rogers, Gerald S.}, Title = {Matrix Derivatives}, Year = 1980, Publisher = {Marcell Dekker, Inc.}, address = {New York and Basel} } @TechReport{DebRoy:Bates:2003a, author = {Saikat DebRoy and Douglas M. Bates}, title = {Computational Methods for Single Level Linear Mixed-effects Models}, institution = {Department of Statistics, University of Wisconsin-Madison}, number = {1073}, year = 2003 } @TechReport{DebRoy:Bates:2003b, author = {Saikat DebRoy and Douglas M. Bates}, title = {Computational Methods for Multiple Level Linear Mixed-effects Models}, institution = {Department of Statistics, University of Wisconsin-Madison}, number = {1076}, year = 2003 } @Article{RaudenbushYangYosef:2000, author = {Stephen W. Raudenbush and Meng-Li Yang and Matheos Yosef}, title = {Maximum Likelihood for Generalized Linear Models With Nested Random Effects via High-Order, Multivariate {L}aplace Approximation}, journal = {J. Comput. Graph. Statist.}, year = 2000, volume = 9, number = 1, pages = {141--157} } @Book{goldstein87:_multil, author = {Goldstein, Harvey}, title = {Multilevel models in education and social research}, publisher = {Oxford University Press}, year = 1987 } @Book{raudenbush02:_hierar_linear_model, author = {Stephen W. Raudenbush and Anthony S. Bryk}, title = {Hierarchical Linear Models: Applications and Data Analysis Methods}, publisher = {Sage}, year = 2002, edition = {second}, ISBN = {0-7619-1904-X} } @BOOK{R:Chambers:1998, AUTHOR = {John M. Chambers}, TITLE = {Programming with Data}, PUBLISHER = {Springer}, YEAR = 1998, ADDRESS = {New York}, ISBN = {0-387-98503-4}, ABSTRACT = {This ``\emph{Green Book}'' describes version 4 of S, a major revision of S designed by John Chambers to improve its usefulness at every stage of the programming process.} } @article{Rodriguez:Goldman:1995, author = {Germ\'an Rodriguez and Noreen Goldman}, title = {An assessment of estimation procedures for multilevel models with binary responses}, year = {1995}, journal = {Journal of the Royal Statistical Society, Series A, General}, volume = {158}, pages = {73--89}, keywords = {Logistic regression; Random effects model; Software; Variance component} } @Article{koen:ng:2003, author = {Roger Koenker and Pin Ng}, title = {{SparseM}: A Sparse Matrix Package for {R}}, journal = {J. of Statistical Software}, year = 2003, volume = 8, number = 6 } @Book{Eispack, author = {Smith, B. T. and Boyle, J. M. and Dongarra, J. J. and Garbow, B. S. and Ikebe, Y. and Klema, V. C. and Moler, C. B.}, title = {Matrix Eigensystem Routines. EISPACK Guide}, publisher = {Springer-Verlag}, year = 1976, volume = 6, series = {Lecture Notes in Computer Science}, address = {New York} } @Article{bate:debr:2004, author = {Douglas M. Bates and Saikat DebRoy}, title = {Linear Mixed Models and Penalized Least Squares}, journal = {J. of Multivariate Analysis}, year = 2004, note = {to appear} } @Article{Rnews:Lockwood+Doran+Mccaffrey:2003, author = {J.R. Lockwood and Harold Doran and Daniel F. McCaffrey}, title = {Using R for Estimating Longitudinal Student Achievement Models}, journal = {R News}, year = 2003, volume = 3, number = 3, pages = {17--23}, month = {December}, url = {https://CRAN.R-project.org/doc/Rnews/} } @Article{Paterson:1991, author = {L. Paterson}, title = {Socio economic status and educational attainment: a multidimensional and multilevel study}, journal = {Evaluation and Research in Education}, year = 1991, volume = 5, pages = {97--121} } Matrix/vignettes/Design-issues.Rnw0000644000175100001440000002074614444514070016772 0ustar hornikusers\documentclass{article} % \usepackage{myVignette} \usepackage[authoryear,round]{natbib} \bibliographystyle{plainnat} \newcommand{\noFootnote}[1]{{\small (\textit{#1})}} \newcommand{\myOp}[1]{{$\left\langle\ensuremath{#1}\right\rangle$}} %% vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv %%\VignetteIndexEntry{Design Issues in Matrix package Development} %%\VignetteDepends{Matrix,utils} \SweaveOpts{engine=R,eps=FALSE,pdf=TRUE,width=5,height=3,strip.white=true,keep.source=TRUE} % ^^^^^^^^^^^^^^^^ \title{Design Issues in Matrix package Development} \author{Martin Maechler and Douglas Bates\\R Core Development Team \\\email{maechler@stat.math.ethz.ch}, \email{bates@r-project.org}} \date{Spring 2008; Aug~2022 ({\tiny typeset on \tiny\today})} % \begin{document} \maketitle \begin{abstract} This is a (\textbf{currently very incomplete}) write-up of the many smaller and larger design decisions we have made in organizing functionalities in the Matrix package. Classes: There's a rich hierarchy of matrix classes, which you can visualize as a set of trees whose inner (and ``upper'') nodes are \emph{virtual} classes and only the leaves are non-virtual ``actual'' classes. Functions and Methods: - setAs() - others \end{abstract} %% Note: These are explained in '?RweaveLatex' : <>= options(width=75) library(utils) # for R_DEFAULT_PACKAGES=NULL library(Matrix) @ \section{The Matrix class structures} \label{sec:classes} Take Martin's DSC 2007 talk to depict the Matrix class hierarchy; available from {\small \url{https://stat.ethz.ch/~maechler/R/DSC-2007_MatrixClassHierarchies.pdf}} . % ~/R/Meetings-Kurse-etc/2007-DSC/talk.tex Matrix-classes.Rnw --- --- --- %% \hrule[1pt]{\textwidth} From far, there are \textbf{three} separate class hierarchies, and every \pkg{Matrix} package matrix has an actual (or ``factual'') class inside these three hierarchies: % ~/R/Meetings-Kurse-etc/2007-DSC/Matrix-classes.Rnw More formally, we have three (\ 3 \ ) main ``class classifications'' for our Matrices, i.e.,\\ three ``orthogonal'' partitions of ``Matrix space'', and every Matrix object's class corresponds to an \emph{intersection} of these three partitions; i.e., in R's S4 class system: We have three independent inheritance schemes for every Matrix, and each such Matrix class is simply defined to \texttt{contain} three \emph{virtual} classes (one from each partitioning scheme), e.g, The three partioning schemes are \begin{enumerate} \item Content \texttt{type}: Classes \code{dMatrix}, \code{lMatrix}, \code{nMatrix}, (\code{iMatrix}, \code{zMatrix}) for entries of type \textbf{d}ouble, \textbf{l}ogical, patter\textbf{n} (and not yet \textbf{i}nteger and complex) Matrices. \code{nMatrix} only stores the \emph{location} of non-zero matrix entries (where as logical Matrices can also have \code{NA} entries!) \item structure: general, triangular, symmetric, diagonal Matrices \item sparsity: \code{denseMatrix}, \code{sparseMatrix} \end{enumerate} For example in the most used sparseMatrix class, \code{"dgCMatrix"}, the three initial letters \code{dgC} each codes for one of the three hierarchies: \begin{description} \item{d: } \textbf{d}ouble \item{g: } \textbf{g}eneral \item{C: } \textbf{C}sparseMatrix, where \textbf{C} is for \textbf{C}olumn-compressed. \end{description} Part of this is visible from printing \code{getClass("\emph{}")}: <>= getClass("dgCMatrix") @ Another example is the \code{"nsTMatrix"} class, where \code{nsT} stands for \begin{description} \item{n: } \textbf{n} is for ``patter\textbf{n}'', boolean content where only the \emph{locations} of the non-zeros need to be stored. \item{t: } \textbf{t}riangular matrix; either \textbf{U}pper, or \textbf{L}ower. \item{T: } \textbf{T}sparseMatrix, where \textbf{T} is for \textbf{T}riplet, the simplest but least efficient way to store a sparse matrix. \end{description} From R itself, via \code{getClass(.)}: <>= getClass("ntTMatrix") @ \subsection{Diagonal Matrices} \label{ssec:diagMat} The class of diagonal matrices is worth mentioning for several reasons. First, we have wanted such a class, because \emph{multiplication} methods are particularly simple with diagonal matrices. The typical constructor is \Rfun{Diagonal} whereas the accessor (as for traditional matrices), \Rfun{diag} simply returns the \emph{vector} of diagonal entries: <>= (D4 <- Diagonal(4, 10*(1:4))) str(D4) diag(D4) @ We can \emph{modify} the diagonal in the traditional way (via method definition for \Rfun{diag<-}): <>= diag(D4) <- diag(D4) + 1:4 D4 @ Note that \textbf{unit-diagonal} matrices (the identity matrices of linear algebra) with slot \code{diag = "U"} can have an empty \code{x} slot, very analogously to the unit-diagonal triangular matrices: <>= str(I3 <- Diagonal(3)) ## empty 'x' slot getClass("diagonalMatrix") ## extending "sparseMatrix" @ Originally, we had implemented diagonal matrices as \emph{dense} rather than sparse matrices. After several years it became clear that this had not been helpful really both from a user and programmer point of view. So now, indeed the \code{"diagonalMatrix"} class does also extend \code{"sparseMatrix"}, i.e., is a subclass of it. However, we do \emph{not} store explicitly where the non-zero entries are, and the class does \emph{not} extend any of the typical sparse matrix classes, \code{"CsparseMatrix"}, \code{"TsparseMatrix"}, or \code{"RsparseMatrix"}. Rather, the \code{diag()}onal (vector) is the basic part of such a matrix, and this is simply the \code{x} slot unless the \code{diag} slot is \code{"U"}, the unit-diagonal case, which is the identity matrix. Further note, e.g., from the \code{?$\,$Diagonal} help page, that we provide (low level) utility function \code{.sparseDiagonal()} with wrappers \code{.symDiagonal()} and \code{.trDiagonal()} which will provide diagonal matrices inheriting from \code{"CsparseMatrix"} which may be advantageous in \emph{some cases}, but less efficient in others, see the help page. \section{Matrix Transformations} \label{sec:trafos} \subsection{Coercions between Matrix classes} \label{ssec:coerce} You may need to transform Matrix objects into specific shape (triangular, symmetric), content type (double, logical, \dots) or storage structure (dense or sparse). Every useR should use \code{as(x, )} to this end, where \code{} is a \emph{virtual} Matrix super class, such as \code{"triangularMatrix"} \code{"dMatrix"}, or \code{"sparseMatrix"}. In other words, the user should \emph{not} coerce directly to a specific desired class such as \code{"dtCMatrix"}, even though that may occasionally work as well. Here is a set of rules to which the Matrix developers and the users should typically adhere: \begin{description} \item[Rule~1]: \code{as(M, "matrix")} should work for \textbf{all} Matrix objects \code{M}. \item[Rule~2]: \code{Matrix(x)} should also work for matrix like objects \code{x} and always return a ``classed'' Matrix. Applied to a \code{"matrix"} object \code{m}, \code{M. <- Matrix(m)} can be considered a kind of inverse of \code{m <- as(M, "matrix")}. For sparse matrices however, \code{M.} well be a \code{CsparseMatrix}, and it is often ``more structured'' than \code{M}, e.g., <>= (M <- spMatrix(4,4, i=1:4, j=c(3:1,4), x=c(4,1,4,8))) # dgTMatrix m <- as(M, "matrix") (M. <- Matrix(m)) # dsCMatrix (i.e. *symmetric*) @ \item[Rule~3]: All the following coercions to \emph{virtual} matrix classes should work:\\ \begin{enumerate} \item \code{as(m, "dMatrix")} \item \code{as(m, "lMatrix")} \item \code{as(m, "nMatrix")} \item \code{as(m, "denseMatrix")} \item \code{as(m, "sparseMatrix")} \item \code{as(m, "generalMatrix")} \end{enumerate} whereas the next ones should work under some assumptions: \begin{enumerate} \item \code{as(m1, "triangularMatrix")} \\ should work when \code{m1} is a triangular matrix, i.e. the upper or lower triangle of \code{m1} contains only zeros. \item \code{as(m2, "symmetricMatrix")} should work when \code{m2} is a symmetric matrix in the sense of \code{isSymmetric(m2)} returning \code{TRUE}. Note that this is typically equivalent to something like \code{isTRUE(all.equal(m2, t(m2)))}, i.e., the lower and upper triangle of the matrix have to be equal \emph{up to small numeric fuzz}. \end{enumerate} \end{description} \section{Session Info} <>= toLatex(sessionInfo()) @ %not yet %\bibliography{Matrix} \end{document} Matrix/vignettes/myVignette.sty0000644000175100001440000000666512070321331016445 0ustar hornikusers\RequirePackage{hyperref} \RequirePackage{url} \RequirePackage{amsmath} \RequirePackage{bm}%-> \bm (= bold math) \newcommand{\Slang}{\textsf{S} language} \newcommand{\RR}{\textsf{R}} \newcommand{\email}[1]{\href{mailto:#1}{\normalfont\texttt{#1}}} %- R programming markup \newcommand\code{\bgroup\@codex} \def\@codex#1{{\normalfont\ttfamily\hyphenchar\font=-1 #1}\egroup} \let\env=\code \let\command=\code \newcommand*{\Rfun}[1]{\code{#1()}\index{\RR~function #1}} \newcommand*{\class}[1]{\code{#1}\index{class #1}}% \newcommand*{\pkg}[1]{\code{#1}\index{\RR~package #1}} % \newcommand{\kbd}[1]{{\normalfont\texttt{#1}}} \newcommand{\key}[1]{{\normalfont\texttt{\uppercase{#1}}}} \newcommand\samp{`\bgroup\@noligs\@sampx} \def\@sampx#1{{\normalfont\texttt{#1}}\egroup'} \let\option=\samp \newcommand{\var}[1]{{\normalfont\textsl{#1}}} \newcommand{\file}[1]{{`\normalfont\textsf{#1}'}} \newcommand{\dfn}[1]{{\normalfont\textsl{#1}}} \newcommand{\acronym}[1]{{\normalfont\textsc{\lowercase{#1}}}} \newcommand{\strong}[1]{{\normalfont\fontseries{b}\selectfont #1}} \let\pkg=\strong % \RequirePackage{alltt} \newenvironment{example}{\begin{alltt}}{\end{alltt}} \newenvironment{smallexample}{\begin{alltt}\small}{\end{alltt}} \newenvironment{display}{\list{}{}\item\relax}{\endlist} \newenvironment{smallverbatim}{\small\verbatim}{\endverbatim} % This is already in ``Sweave'' -- but withOUT the fontsize=\small part !! %% \RequirePackage{fancyvrb} %% \DefineVerbatimEnvironment{Sinput}{Verbatim}{fontsize=\small,fontshape=sl} %% \DefineVerbatimEnvironment{Soutput}{Verbatim}{fontsize=\small} %% \DefineVerbatimEnvironment{Scode}{Verbatim}{fontsize=\small,fontshape=sl} % \newcommand{\FIXME}[1]{\marginpar{ \dots FIXME \emph{#1} \dots}} \newcommand{\TODO}[1]{\par\noindent\textsc{Todo:} \textit{#1}\par} % %% Matrix stuff : % \newcommand{\trans}{\ensuremath{^\mathsf{T}}} \newcommand{\bA}{\ensuremath{\bm{A}}} \newcommand{\bD}{\ensuremath{\bm{D}}} \newcommand{\bDelta}{\ensuremath{\bm{\Delta}}} \newcommand{\bI}{\ensuremath{\bm{I}}} \newcommand{\bL}{\ensuremath{\bm{L}}} \newcommand{\LXXi}[1]{\ensuremath{\bL_{\mathit{XX}({#1})}}} \newcommand{\LXX}{\ensuremath{\bL_\mathit{XX}}} \newcommand{\LXZi}[1]{\ensuremath{\bL_{\mathit{XZ}({#1})}}} \newcommand{\LXZ}{\ensuremath{\bL_\mathit{XZ}}} \newcommand{\LZZi}[1]{\ensuremath{\bL_{\mathit{ZZ}({#1})}}} \newcommand{\LZZ}{\ensuremath{\bL_\mathit{ZZ}}} \newcommand{\LZZoo}{\ensuremath{\bL_{\mathit{ZZ}11}}} \newcommand{\LZZot}{\ensuremath{\bL_{\mathit{ZZ}12}}} \newcommand{\LZZtt}{\ensuremath{\bL_{\mathit{ZZ}22}}} \newcommand{\bOmega}{\ensuremath{\bm{\Omega}}} \newcommand{\bPhi}{\ensuremath{\bm{\Phi}}} \newcommand{\bR}{\ensuremath{\bm{R}}} \newcommand{\bX}{\ensuremath{\bm{X}}} \newcommand{\bZ}{\ensuremath{\bm{Z}}} \newcommand{\bbeta}{\ensuremath{\bm{\beta}}} \newcommand{\bb}{\ensuremath{\bm{b}}} \newcommand{\beps}{\ensuremath{\bm{\epsilon}}} \newcommand{\dX}{\ensuremath{\bm{d}_{\mathit{X}}}} \newcommand{\dZ}{\ensuremath{\bm{d}_{\mathit{Z}}}} \newcommand{\dy}{\ensuremath{d_{\mathit{y}}}} \newcommand{\lyXi}[1]{\ensuremath{\bm{\ell}_{\mathit{yX}(#1)}}} \newcommand{\lyX}{\ensuremath{\bm{\ell}_\mathit{yX}}} \newcommand{\lyZi}[1]{\ensuremath{\bm{\ell}_{\mathit{yZ}(#1)}}} \newcommand{\lyZ}{\ensuremath{\bm{\ell}_\mathit{yZ}}} \newcommand{\lyyi}[1]{\ensuremath{\bm{\ell}_{\mathit{yy}(#1)}}} \newcommand{\lyy}{\ensuremath{\ell_\mathit{yy}}} \newcommand{\btheta}{\ensuremath{\bm{\theta}}} \newcommand{\by}{\ensuremath{\bm{y}}} \newcommand{\bzer}{\ensuremath{\bm{0}}} Matrix/vignettes/Intro2Matrix.Rnw0000644000175100001440000004461614444514070016614 0ustar hornikusers\documentclass{article} % \usepackage{myVignette} \usepackage{fullpage}% save trees ;-) \usepackage[authoryear,round]{natbib} \bibliographystyle{plainnat} \newcommand{\noFootnote}[1]{{\small (\textit{#1})}} \newcommand{\myOp}[1]{{$\left\langle\ensuremath{#1}\right\rangle$}} % %%\VignetteIndexEntry{2nd Introduction to the Matrix Package} %%\VignetteDepends{Matrix,utils} \SweaveOpts{engine=R,eps=FALSE,pdf=TRUE,width=7,height=4,strip.white=true,keep.source=TRUE} % ^^^^^^^^^^^^^^^^ \title{2nd Introduction to the Matrix package} \author{Martin Maechler and Douglas Bates\\ R Core Development Team \\\email{maechler@stat.math.ethz.ch}, \email{bates@r-project.org}} \date{September 2006 ({\tiny typeset on \tiny\today})} % \begin{document} \maketitle \begin{abstract} % \emph{\Large Why should you want to work with this package and what % does it do for you?} Linear algebra is at the core of many areas of statistical computing and from its inception the \Slang{} has supported numerical linear algebra via a matrix data type and several functions and operators, such as \code{\%*\%}, \code{qr}, \code{chol}, and \code{solve}. However, these data types and functions do not provide direct access to all of the facilities for efficient manipulation of dense matrices, as provided by the Lapack subroutines, and they do not provide for manipulation of sparse matrices. The \pkg{Matrix} package provides a set of S4 classes for dense and sparse matrices that extend the basic matrix data type. Methods for a wide variety of functions and operators applied to objects from these classes provide efficient access to BLAS (Basic Linear Algebra Subroutines), Lapack (dense matrix), CHOLMOD including AMD and COLAMD and \code{Csparse} (sparse matrix) routines. One notable characteristic of the package is that whenever a matrix is factored, the factorization is stored as part of the original matrix so that further operations on the matrix can reuse this factorization. \end{abstract} %% Note: These are explained in '?RweaveLatex' : <>= options(width=75) library(utils) # for R_DEFAULT_PACKAGES=NULL @ \section{Introduction} \label{sec:Intro} The most automatic way to use the \pkg{Matrix} package is via the \Rfun{Matrix} function which is very similar to the standard \RR\ function \Rfun{matrix}, @ <>= library(Matrix) M <- Matrix(10 + 1:28, 4, 7) M tM <- t(M) @ %def Such a matrix can be appended to (using \Rfun{cbind} or \Rfun{rbind}) or indexed, <>= (M2 <- cbind(-1, M)) M[2, 1] M[4, ] @ where the last two statements show customary matrix indexing, returning a simple numeric vector each\footnote{because there's an additional default argument to indexing, \code{drop = TRUE}. If you add \hbox{``\code{\ ,\ drop = FALSE}\ ''} you will get submatrices instead of simple vectors.}. We assign 0 to some columns and rows to ``sparsify'' it, and some \code{NA}s (typically ``missing values'' in data analysis) in order to demonstrate how they are dealt with; note how we can \emph{``subassign''} as usual, for classical \RR{} matrices (i.e., single entries or whole slices at once), @ <>= M2[, c(2,4:6)] <- 0 M2[2, ] <- 0 M2 <- rbind(0, M2, 0) M2[1:2,2] <- M2[3,4:5] <- NA @ and then coerce it to a sparse matrix, @ <>= sM <- as(M2, "sparseMatrix") 10 * sM identical(sM * 2, sM + sM) is(sM / 10 + M2 %/% 2, "sparseMatrix") @ %def where the last three calls show that multiplication by a scalar keeps sparcity, as does other arithmetic, but addition to a ``dense'' object does not, as you might have expected after some thought about ``sensible'' behavior: @ <>= sM + 10 @ %def Operations on our classed matrices include (componentwise) arithmetic ($+$, $-$, $*$, $/$, etc) as partly seen above, comparison ($>$, $\le$, etc), e.g., <>= Mg2 <- (sM > 2) Mg2 @ returning a logical sparse matrix. When interested in the internal \textbf{str}ucture, \Rfun{str} comes handy, and we have been using it ourselves more regulary than \Rfun{print}ing (or \Rfun{show}ing as it happens) our matrices; alternatively, \Rfun{summary} gives output similar to Matlab's printing of sparse matrices. @ <>= str(Mg2) summary(Mg2) @ As you see from both of these, \code{Mg2} contains ``extra zero'' (here \code{FALSE}) entries; such sparse matrices may be created for different reasons, and you can use \Rfun{drop0} to remove (``drop'') these extra zeros. This should \emph{never} matter for functionality, and does not even show differently for logical sparse matrices, but the internal structure is more compact: <>= Mg2 <- drop0(Mg2) str(Mg2@x) # length 13, was 16 @ For large sparse matrices, visualization (of the sparsity pattern) is important, and we provide \Rfun{image} methods for that, e.g., <>= data(CAex, package = "Matrix") print(image(CAex, main = "image(CAex)")) # print(.) needed for Sweave @ \smallskip Further, i.e., in addition to the above implicitly mentioned \code{"Ops"} operators (\code{+}, \code{*},\dots, \code{<=},\code{>},\dots, \code{\&} which all work with our matrices, notably in conjunction with scalars and traditional matrices), the \code{"Math"}-operations (such as \Rfun{exp}, \Rfun{sin} or \Rfun{gamma}) and \code{"Math2"} (\Rfun{round} etc) and the \code{"Summary"} group of functions, \Rfun{min}, \Rfun{range}, \Rfun{sum}, all work on our matrices as they should. Note that all these are implemented via so called \emph{group methods}, see e.g., \code{?Arith} in \RR. The intention is that sparse matrices remain sparse whenever sensible, given the matrix \emph{classes} and operators involved, but not content specifically. E.g., + gives even for the rare cases where it would be advantageous to get a result. These classed matrices can be ``indexed'' (more technically ``subset'') as traditional \Slang{} (and hence \RR) matrices, as partly seen above. This also includes the idiom \code{M [ M \myOp{\mathit{op}} \myOp{\mathrm{num}}~]} which returns simple vectors, @ <>= sM[sM > 2] sml <- sM[sM <= 2] sml @ %def and \emph{``subassign''}ment similarly works in the same generality as for traditional \Slang{} matrices. %% We have seen that already above! %% This was the 2005 - Introduction vignette's first section: \subsection{\pkg{Matrix} package for numerical linear algebra} \label{ssec:intro-linalg} Linear algebra is at the core of many statistical computing techniques and, from its inception, the \Slang{} has supported numerical linear algebra via a matrix data type and several functions and operators, such as \code{\%*\%}, \code{qr}, \code{chol}, and \code{solve}. %% Initially the numerical linear algebra functions in \RR{} called underlying Fortran routines from the Linpack~\citep{Linpack} and Eispack~\citep{Eispack} libraries but over the years most of these functions have been switched to use routines from the Lapack~\citep{Lapack} library which is the state-of-the-art implementation of numerical dense linear algebra. %% Furthermore, \RR{} can be configured to use accelerated BLAS (Basic Linear Algebra Subroutines), such as those from the Atlas~\citep{Atlas} project or other ones, see the \RR~manual ``Installation and Administration''. Lapack provides routines for operating on several special forms of matrices, such as triangular matrices and symmetric matrices. Furthermore, matrix decompositions like the QR decompositions produce multiple output components that should be regarded as parts of a single object. There is some support in \RR{} for operations on special forms of matrices (e.g. the \code{backsolve}, \code{forwardsolve} and \code{chol2inv} functions) and for special structures (e.g. a QR structure is implicitly defined as a list by the \code{qr}, \code{qr.qy}, \code{qr.qty}, and related functions) but it is not as fully developed as it could be. Also there is no direct support for sparse matrices in \RR{} although \citet{koen:ng:2003} have developed the \pkg{SparseM} package for sparse matrices based on SparseKit. The \pkg{Matrix} package provides S4 classes and methods for dense and sparse matrices. The methods for dense matrices use Lapack and BLAS. The sparse matrix methods use CHOLMOD~\citep{Cholmod}, CSparse~\citep{Csparse} and other parts (AMD, COLAMD) of Tim Davis' ``SuiteSparse'' collection of sparse matrix libraries, many of which also use BLAS. \TODO{\Rfun{triu}, \Rfun{tril}, \Rfun{diag}, ... and \command{as(.,.)} , but of course only when they've seen a few different ones.} \TODO{matrix operators include \code{\%*\%}, \Rfun{crossprod}, \Rfun{tcrossprod}, \Rfun{solve}} \TODO{\Rfun{expm} is the matrix exponential ... ...} \TODO{\Rfun{symmpart} and \Rfun{skewpart} compute the symmetric part, \code{(x + t(x))/2} and the skew-symmetric part, \code{(x - t(x))/2} of a matrix \code{x}.} \TODO{factorizations include \Rfun{Cholesky} (or \Rfun{chol}), \Rfun{lu}, \Rfun{qr} (not yet for dense)} \TODO{Although generally the result of an operation on dense matrices is a dgeMatrix, certain operations return matrices of special types.} \TODO{E.g. show the distinction between \code{t(mm) \%*\% mm} and \code{crossprod(mm)}.} % \bigskip % ... ... ... The following is the old \file{Introduction.Rnw} ... FIXME ... ... \bigskip \section{Matrix Classes} The \pkg{Matrix} package provides classes for real (stored as double precision), logical and so-called ``pattern'' (binary) dense and sparse matrices. There are provisions to also provide integer and complex (stored as double precision complex) matrices. Note that in \RR, \code{logical} means entries \code{TRUE}, \code{FALSE}, or \code{NA}. To store just the non-zero pattern for typical sparse matrix algorithms, the pattern matrices are \emph{binary}, i.e., conceptually just \code{TRUE} or \code{FALSE}. In \pkg{Matrix}, the pattern matrices all have class names starting with \code{"n"} (patter\textbf{n}). \subsection{Classes for dense matrices} \label{ssec:DenseClasses} For the sake of brevity, we restrict ourselves to the \emph{real} (\textbf{d}ouble) classes, but they are paralleled by \textbf{l}ogical and patter\textbf{n} matrices for all but the positive definite ones. \begin{description} \item[dgeMatrix] Real matrices in general storage mode \item[dsyMatrix] Symmetric real matrices in non-packed storage \item[dspMatrix] Symmetric real matrices in packed storage (one triangle only) \item[dtrMatrix] Triangular real matrices in non-packed storage \item[dtpMatrix] Triangular real matrices in packed storage (triangle only) \item[dpoMatrix] Positive semi-definite symmetric real matrices in non-packed storage \item[dppMatrix] \ \ ditto \ \ in packed storage \end{description} Methods for these classes include coercion between these classes, when appropriate, and coercion to the \code{matrix} class; methods for matrix multiplication (\code{\%*\%}); cross products (\code{crossprod}), matrix norm (\code{norm}); reciprocal condition number (\code{rcond}); LU factorization (\code{lu}) or, for the \code{poMatrix} class, the Cholesky decomposition (\code{chol}); and solutions of linear systems of equations (\code{solve}). %-- mentioned above already: % Further, group methods have been defined for the \code{Arith} (basic % arithmetic, including with scalar numbers) and the \code{Math} (basic % mathematical functions) group.. Whenever a factorization or a decomposition is calculated it is preserved as a (list) element in the \code{factors} slot of the original object. In this way a sequence of operations, such as determining the condition number of a matrix then solving a linear system based on the matrix, do not require multiple factorizations of the same matrix nor do they require the user to store the intermediate results. \subsection{Classes for sparse matrices} \label{sec:SparseClasses} Used for large matrices in which most of the elements are known to be zero (or \code{FALSE} for logical and binary (``pattern'') matrices). Sparse matrices are automatically built from \Rfun{Matrix} whenever the majority of entries is zero (or \code{FALSE} respectively). Alternatively, \Rfun{sparseMatrix} builds sparse matrices from their non-zero entries and is typically recommended to construct large sparse matrices, rather than direct calls of \Rfun{new}. \TODO{E.g. model matrices created from factors with a large number of levels} \TODO{ or from spline basis functions (e.g. COBS, package \pkg{cobs}), etc.} \TODO{Other uses include representations of graphs. indeed; good you mentioned it! particularly since we still have the interface to the \pkg{graph} package. I think I'd like to draw one graph in that article --- maybe the undirected graph corresponding to a crossprod() result of dimension ca. $50^2$} \TODO{Specialized algorithms can give substantial savings in amount of storage used and execution time of operations.} \TODO{Our implementation is based on the CHOLMOD and CSparse libraries by Tim Davis.} \subsection{Representations of sparse matrices} \label{ssec:SparseReps} \subsubsection{Triplet representation (\class{TsparseMatrix})} Conceptually, the simplest representation of a sparse matrix is as a triplet of an integer vector \code{i} giving the row numbers, an integer vector \code{j} giving the column numbers, and a numeric vector \code{x} giving the non-zero values in the matrix.\footnote{For efficiency reasons, we use ``zero-based'' indexing in the \pkg{Matrix} package, i.e., the row indices \code{i} are in \code{0:(nrow(.)-1)} and the column indices \code{j} accordingly.} In \pkg{Matrix}, the \class{TsparseMatrix} class is the virtual class of all sparse matrices in triplet representation. Its main use is for easy input or transfer to other classes. As for the dense matrices, the class of the \code{x} slot may vary, and the subclasses may be triangular, symmetric or unspecified (``general''), such that the \class{TsparseMatrix} class has several\footnote{the $3 \times 3$ actual subclasses of \class{TsparseMatrix} are the three structural kinds, namely \textbf{t}riangular, \textbf{s}ymmetric and \textbf{g}eneral, times three entry classes, \textbf{d}ouble, \textbf{l}ogical, and patter\textbf{n}.} `actual'' subclasses, the most typical (numeric, general) is \class{dgTMatrix}: <>= getClass("TsparseMatrix") # (i,j, Dim, Dimnames) slots are common to all getClass("dgTMatrix") @ Note that the \emph{order} of the entries in the \code{(i,j,x)} vectors does not matter; consequently, such matrices are not unique in their representation. \footnote{ Furthermore, there can be \emph{repeated} \code{(i,j)} entries with the customary convention that the corresponding \code{x} entries are \emph{added} to form the matrix element $m_{ij}$. } %% The triplet representation is row-oriented if elements in the same row %% were adjacent and column-oriented if elements in the same column were %% adjacent. \subsubsection{Compressed representations: \class{CsparseMatrix} and \class{RsparseMatrix}} For most sparse operations we use the compressed column-oriented representation (virtual class \class{CsparseMatrix}) (also known as ``csc'', ``compressed sparse column''). Here, instead of storing all column indices \code{j}, only the \emph{start} index of every column is stored. Analogously, there is also a compressed sparse row (csr) representation, which e.g. is used in in the \pkg{SparseM} package, and we provide the \class{RsparseMatrix} for compatibility and completeness purposes, in addition to basic coercion (\code({as(., \textit{})} between the classes. %% (column-oriented triplet) except that \code{i} (\code{j}) just stores %% the index of the first element in the row (column). (There are a %% couple of other details but that is the gist of it.) These compressed representations remove the redundant row (column) indices and provide faster access to a given location in the matrix because you only need to check one row (column). There are certain advantages \footnote{routines can make use of high-level (``level-3'') BLAS in certain sparse matrix computations} to csc in systems like \RR{}, Octave and Matlab where dense matrices are stored in column-major order, therefore it is used in sparse matrix libraries such as CHOLMOD or CSparse of which we make use. For this reason, the \class{CsparseMatrix} class and subclasses are the principal classes for sparse matrices in the \pkg{Matrix} package. The Matrix package provides the following classes for sparse matrices \FIXME{many more --- maybe explain naming scheme?} \begin{description} \item[dgTMatrix] general, numeric, sparse matrices in (a possibly redundant) triplet form. This can be a convenient form in which to construct sparse matrices. \item[dgCMatrix] general, numeric, sparse matrices in the (sorted) compressed sparse column format. \item[dsCMatrix] symmetric, real, sparse matrices in the (sorted) compressed sparse column format. Only the upper or the lower triangle is stored. Although there is provision for both forms, the lower triangle form works best with TAUCS. \item[dtCMatrix] triangular, real, sparse matrices in the (sorted) compressed sparse column format. \end{description} \TODO{Can also read and write the Matrix Market and read the Harwell-Boeing representations.} \TODO{Can convert from a dense matrix to a sparse matrix (or use the Matrix function) but going through an intermediate dense matrix may cause problems with the amount of memory required.} \TODO{similar range of operations as for the dense matrix classes.} \section{More detailed examples of ``Matrix'' operations} Have seen \texttt{drop0()} above, %(p.3); only with logical showe a nice double example (where you see ``.'' and ``0''). Show the use of \code{dim<-} for \emph{resizing} a (sparse) matrix. Maybe mention \Rfun{nearPD}. \TODO{Solve a sparse least squares problem and demonstrate memory / speed gain} \TODO{mention \code{lme4} and \Rfun{lmer}, maybe use one example to show the matrix sizes.} \section{Notes about S4 classes and methods implementation} Maybe we could % even here (for R News, not only for JSS) give some glimpses of implementations at least on the \RR{} level ones? \TODO{The class hierarchy: a non-trivial tree where only the leaves are ``actual'' classes.} \TODO{The main advantage of the multi-level hierarchy is that methods can often be defined on a higher (virtual class) level which ensures consistency [and saves from ``cut \& paste'' and forgetting things]} \TODO{Using Group Methods} \section{Session Info} <>= toLatex(sessionInfo()) @ \bibliography{Matrix} \end{document} Matrix/vignettes/Introduction.Rnw0000644000175100001440000001753412070262574016734 0ustar hornikusers\documentclass{article} \usepackage{myVignette} \usepackage[authoryear,round]{natbib} \bibliographystyle{plainnat} %%\VignetteIndexEntry{Introduction to the Matrix Package} %%\VignetteDepends{Matrix} \SweaveOpts{engine=R,eps=FALSE,pdf=TRUE,width=5,height=3,strip.white=true,keep.source=TRUE} \title{Introduction to the Matrix package --- as of Feb.~2005\footnote{ There's an unfinished ``2nd Introduction to the Matrix package'' which contains partly newer information, but is not at all self-contained. Eventually that will replace this one.}} \author{Douglas Bates\\R Core Development Group\\\email{bates@r-project.org}} \date{\today} \begin{document} \maketitle \begin{abstract} Linear algebra is at the core of many areas of statistical computing and from its inception the \Slang{} has supported numerical linear algebra via a matrix data type and several functions and operators, such as \code{\%*\%}, \code{qr}, \code{chol}, and \code{solve}. However, these data types and functions do not provide direct access to all of the facilities for efficient manipulation of dense matrices, as provided by the Lapack subroutines, and they do not provide for manipulation of sparse matrices. The \code{Matrix} package provides a set of S4 classes for dense and sparse matrices that extend the basic matrix data type. Methods for a wide variety of functions and operators applied to objects from these classes provide efficient access to BLAS (Basic Linear Algebra Subroutines), Lapack (dense matrix), TAUCS (sparse matrix) and UMFPACK (sparse matrix) routines. One notable characteristic of the package is that whenever a matrix is factored, the factorization is stored as part of the original matrix so that further operations on the matrix can reuse this factorization. \end{abstract} <>= options(width=75) @ \section{Introduction} \label{sec:Intro} Linear algebra is at the core of many statistical computing techniques and, from its inception, the \Slang{} has supported numerical linear algebra via a matrix data type and several functions and operators, such as \code{\%*\%}, \code{qr}, \code{chol}, and \code{solve}. Initially the numerical linear algebra functions in \RR{} called underlying Fortran routines from the Linpack~\citep{Linpack} and Eispack~\cite{Eispack} libraries but over the years most of these functions have been switched to use routines from the Lapack~\cite{Lapack} library. Furthermore, \RR{} can be configured to use accelerated BLAS (Basic Linear Algebra Subroutines), such as those from the Atlas~\cite{Atlas} project or Goto's BLAS~\cite{GotosBLAS}. Lapack provides routines for operating on several special forms of matrices, such as triangular matrices and symmetric matrices. Furthermore,matrix decompositions like the QR decompositions produce multiple output components that should be regarded as parts of a single object. There is some support in R for operations on special forms of matrices (e.g. the \code{backsolve}, \code{forwardsolve} and \code{chol2inv} functions) and for special structures (e.g. a QR structure is implicitly defined as a list by the \code{qr}, \code{qr.qy}, \code{qr.qty}, and related functions) but it is not as fully developed as it could be. Also there is no direct support for sparse matrices in R although \citet{koen:ng:2003} have developed a contributed package for sparse matrices based on SparseKit. The \code{Matrix} package provides S4 classes and methods for dense and sparse matrices. The methods for dense matrices use Lapack and BLAS. The sparse matrix methods use TAUCS~\citep{Taucs}, UMFPACK~\citep{Umfpack}, and Metis~\citep{Metis}. \section{Classes for dense matrices} \label{sec:DenseClasses} The \code{Matrix} package will provide classes for real (stored as double precision) and complex (stored as double precision complex) dense matrices. At present only the real classes have been implemented. These classes are \begin{description} \item[dgeMatrix] Real matrices in general storage mode \item[dsyMatrix] Symmetric real matrices in non-packed storage \item[dspMatrix] Symmetric real matrices in packed storage (one triangle only) \item[dtrMatrix] Triangular real matrices in non-packed storage \item[dtpMatrix] Triangular real matrices in packed storage (triangle only) \item[dpoMatrix] Positive semi-definite symmetric real matrices in non-packed storage \item[dppMatrix] \ \ ditto \ \ in packed storage \end{description} Methods for these classes include coercion between these classes, when appropriate, and coercion to the \code{matrix} class; methods for matrix multiplication (\code{\%*\%}); cross products (\code{crossprod}), matrix norm (\code{norm}); reciprocal condition number (\code{rcond}); LU factorization (\code{lu}) or, for the \code{poMatrix} class, the Cholesky decomposition (\code{chol}); and solutions of linear systems of equations (\code{solve}). Further, group methods have been defined for the \code{Arith} (basic arithmetic, including with scalar numbers) and the \code{Math} (basic mathematical functions) group.. Whenever a factorization or a decomposition is calculated it is preserved as a (list) element in the \code{factors} slot of the original object. In this way a sequence of operations, such as determining the condition number of a matrix then solving a linear system based on the matrix, do not require multiple factorizations of the same matrix nor do they require the user to store the intermediate results. \section{Classes for sparse matrices} \label{sec:SparseClasses} \subsection{Representations of sparse matrices} \label{ssec:SparseReps} Conceptually, the simplest representation of a sparse matrix is as a triplet of an integer vector \code{i} giving the row numbers, an integer vector \code{j} giving the column numbers, and a numeric vector \code{x} giving the non-zero values in the matrix. An S4 class definition might be \begin{Schunk} \begin{Sinput} setClass("dgTMatrix", representation(i = "integer", j = "integer", x = "numeric", Dim = "integer")) \end{Sinput} \end{Schunk} The triplet representation is row-oriented if elements in the same row were adjacent and column-oriented if elements in the same column were adjacent. The compressed sparse row (csr) (or compressed sparse column - csc) representation is similar to row-oriented triplet (column-oriented triplet) except that \code{i} (\code{j}) just stores the index of the first element in the row (column). (There are a couple of other details but that is the gist of it.) These compressed representations remove the redundant row (column) indices and provide faster access to a given location in the matrix because you only need to check one row (column). The preferred representation of sparse matrices in the SparseM package is csr. Matlab uses csc. We hope that Octave will also use this representation. There are certain advantages to csc in systems like R and Matlab where dense matrices are stored in column-major order. For example, Sivan Toledo's TAUCS~\cite{Taucs} library and Tim Davis's UMFPACK~\cite{Umfpack} library are both based on csc and can both use level-3 BLAS in certain sparse matrix computations. The Matrix package provides the following classes for sparse matrices \begin{description} \item[dgTMatrix] general, numeric, sparse matrices in (a possibly redundant) triplet form. This can be a convenient form in which to construct sparse matrices. \item[dgCMatrix] general, numeric, sparse matrices in the (sorted) compressed sparse column format. \item[dsCMatrix] symmetric, real, sparse matrices in the (sorted) compressed sparse column format. Only the upper or the lower triangle is stored. Although there is provision for both forms, the lower triangle form works best with TAUCS. \item[dtCMatrix] triangular, real, sparse matrices in the (sorted) compressed sparse column format. \end{description} \bibliography{Matrix} \end{document} Matrix/vignettes/sparseModels.Rnw0000644000175100001440000002553414444514070016711 0ustar hornikusers\documentclass{article} % \usepackage{fullpage} \usepackage{myVignette} \usepackage[authoryear,round]{natbib} \bibliographystyle{plainnat} \newcommand{\noFootnote}[1]{{\small (\textit{#1})}} \newcommand{\myOp}[1]{{$\left\langle\ensuremath{#1}\right\rangle$}} %%\VignetteIndexEntry{Sparse Model Matrices} %%\VignetteDepends{Matrix,MASS,datasets,grDevices,stats,utils} \title{Sparse Model Matrices} \author{Martin Maechler\\ R Core Development Team \\\email{maechler@R-project.org}} \date{July 2007, 2008 ({\tiny typeset on \tiny\today})} % \begin{document} \maketitle \SweaveOpts{engine=R, keep.source=TRUE} \SweaveOpts{eps=FALSE, pdf=TRUE, width=8, height=5.5, strip.white=true} \setkeys{Gin}{width=\textwidth} % \begin{abstract} % ............................ FIXME % \end{abstract} %% Note: These are explained in '?RweaveLatex' : <>= options(width=75) library(grDevices) # for R_DEFAULT_PACKAGES=NULL library(stats) # ditto library(utils) # ditto @ \section*{Introduction} Model matrices in the very widely used (generalized) linear models of statistics, (typically fit via \Rfun{lm} or \Rfun{glm} in \RR) are often practically sparse --- whenever categorical predictors, \code{factor}s in \RR, are used. %% FIXME: Introduce lm.fit.sparse() or not ? We show for a few classes of such linear models how to construct sparse model matrices using sparse matrix (S4) objects from the \pkg{Matrix} package, and typically \emph{without} using dense matrices in intermediate steps. %% only the latter is really novel, since "SparseM" (and others) %% have used the equivalent of %% as( model.matrix(.....), "sparseMatrix") \section{One factor: \texttt{y $\sim$ f1}} Let's start with an artifical small example: <>= (ff <- factor(strsplit("statistics_is_a_task", "")[[1]], levels=c("_",letters))) factor(ff) # drops the levels that do not occur f1 <- ff[, drop=TRUE] # the same, more transparently @ and now assume a model $$y_i = \mu + \alpha_{j(i)} + E_i,$$ for $i=1,\dots,n =$~\code{length(f1)}$= 20$, and $\alpha_{j(i)}$ with a constraint such as $\sum_j \alpha_j = 0$ (``sum'') or $\alpha_1 = 0$ (``treatment'') and $j(i) =$\code{as.numeric(f1[i])} being the level number of the $i$-th observation. For such a ``design'', the model is only estimable if the levels \code{c} and \code{k} are merged, and <>= levels(f1)[match(c("c","k"), levels(f1))] <- "ck" library(Matrix) Matrix(contrasts(f1)) # "treatment" contrasts by default -- level "_" = baseline Matrix(contrasts(C(f1, sum))) Matrix(contrasts(C(f1, helmert)), sparse=TRUE) # S-plus default; much less sparse @ where \Rfun{contrasts} is (conceptually) just one major ingredient in the well-known \Rfun{model.matrix} function to build the linear model matrix $\mathbf{X}$ of so-called ``dummy variables''. %% Since 2007, the \pkg{Matrix} package has been providing coercion from a \code{factor} object to a \code{sparseMatrix} one to produce the transpose of the model matrix corresponding to a model with that factor as predictor (and no intercept): <>= as(f1, "sparseMatrix") @ which is really almost the transpose of using the above sparsification of \Rfun{contrasts} (and arranging for nice printing), <>= printSpMatrix( t( Matrix(contrasts(f1))[as.character(f1) ,] ), col.names=TRUE) @ and that is the same as the ``sparsification'' of \Rfun{model.matrix}, apart from the column names (here transposed), <>= t( Matrix(model.matrix(~ 0+ f1))) # model with*OUT* intercept @ A more realistic small example is the \code{chickwts} data set, <>= data(chickwts, package = "datasets") str(chickwts)# a standard R data set, 71 x 2 x.feed <- as(chickwts$feed, "sparseMatrix") x.feed[ , (1:72)[c(TRUE,FALSE,FALSE)]] ## every 3rd column: @ % FIXME: Move this to ../../../MatrixModels/inst/doc/ ??? % ## Provisional (hence unexported) sparse lm.fit(): % Matrix:::lm.fit.sparse(x = t(x.feed), y = chickwts[,1]) %- for emacs: $ \section{One factor, one continuous: \texttt{y $\sim$ f1 + x}} To create the model matrix for the case of one factor and one continuous predictor---called ``analysis of covariance'' in the historical literature--- we can adopt the following simple scheme. %% Possible examples: %% - Puromycin %% - ToothGrowth %--- FIXME --- The final model matrix is the concatenation of: 1) create the sparse 0-1 matrix \code{m1} from the f1 main-effect 2) the single row/column 'x' == 'x' main-effect 3) replacing the values 1 in \code{m1@x} (the x-slot of the factor model matrix), by the values of \code{x} (our continuous predictor). \section{Two (or more) factors, main effects only: \texttt{y $\sim$ f1 + f2}} %% FIXME: 'warpbreaks' is smaller and more natural as fixed effect model! Let us consider the \code{warpbreaks} data set of 54 observations, <>= data(warpbreaks, package = "datasets") # a standard R data set str(warpbreaks) # 2 x 3 (x 9) balanced two-way with 9 replicates: xtabs(~ wool + tension, data = warpbreaks) @ %It is \emph{not} statistically sensible to assume that \code{Run} is a %fixed effect, however the example is handy to depict how a model matrix This example depicts how a model matrix would be built for the model \code{breaks ~ wool + tension}. Since this is a main effects model (no interactions), the desired model matrix is simply the concatenation of the model matrices of the main effects. There are two here, but the principle applies to general main effects of factors. The most sparse matrix is reached by \emph{not} using an intercept, (which would give an all-1-column) but rather have one factor fully coded (aka ``swallow'' the intercept), and all others being at \code{"treatment"} contrast, i.e., here, the \emph{transposed} model matrix, \code{tmm}, is <>= tmm <- with(warpbreaks, rbind(as(tension, "sparseMatrix"), as(wool, "sparseMatrix")[-1,,drop=FALSE])) print( image(tmm) ) # print(.) the lattice object @ \\ The matrices are even sparser when the factors have more than just two or three levels, e.g., for the morley data set, <>= data(morley, package = "datasets") # a standard R data set morley$Expt <- factor(morley$Expt) morley$Run <- factor(morley$Run) str(morley) t.mm <- with(morley, rbind(as(Expt, "sparseMatrix"), as(Run, "sparseMatrix")[-1,])) print( image(t.mm) ) # print(.) the lattice object @ %% Also see Doug's E-mail to R-help % From: "Douglas Bates" % Subject: Re: [R] Large number of dummy variables % Date: Mon, 21 Jul 2008 18:07:26 -0500 \section{Interactions of two (or more) factors,.....} %% Of course, this is *the* interesting part %% To form interactions, we would have to ``outer-multiply'' %% the single-factor model-matrices (after "[, -1]") In situations with more than one factor, particularly with interactions, the model matrix is currently not directly available via \pkg{Matrix} functions --- but we still show to build them carefully. The easiest---but not at memory resources efficient---way is to go via the dense \Rfun{model.matrix} result: <>= data(npk, package = "MASS") npk.mf <- model.frame(yield ~ block + N*P*K, data = npk) ## str(npk.mf) # the data frame + "terms" attribute m.npk <- model.matrix(attr(npk.mf, "terms"), data = npk) class(M.npk <- Matrix(m.npk)) dim(M.npk)# 24 x 13 sparse Matrix t(M.npk) # easier to display, column names readably displayed as row.names(t(.)) @ %% printSpMatrix(M.npk, col.names = "abb1") Another example was reported by a user on R-help (July 15, 2008, {\small \url{https://stat.ethz.ch/pipermail/r-help/2008-July/167772.html}}) about an ``aov error with large data set''. \begin{citation} % RAS: in my PDF, I don't see the first character I I'm looking to analyze a large data set: a within-Ss 2*2*1500 design with 20 Ss. However, aov() gives me an error. %, reproducible as follows: \end{citation} And gave the following code example (slightly edited): <>= id <- factor(1:20) a <- factor(1:2) b <- factor(1:2) d <- factor(1:1500) aDat <- expand.grid(id=id, a=a, b=b, d=d) aDat$y <- rnorm(length(aDat[, 1])) # generate some random DV data dim(aDat) # 120'000 x 5 (120'000 = 2*2*1500 * 20 = 6000 * 20) @ %% ^^^^^^^ MM: "fix" and generate much more interesting data and then continued with \begin{Sinput} m.aov <- aov(y ~ a*b*d + Error(id/(a*b*d)), data=aDat) \end{Sinput} \begin{citation}\sffamily which yields the following error:\\ \ttfamily Error in model.matrix.default(mt, mf, contrasts) :\\ allocMatrix: too many elements specified\\ \end{citation} to which he got the explanation by Peter Dalgaard that the formal model matrix involved was much too large in this case, and that PD assumed, \pkg{lme4} would be able to solve the problem. However, currently there would still be a big problem with using \pkg{lme4}, because of the many levels of \emph{fixed} effects: Specifically\footnote{the following is not run in \RR\ on purpose, rather just displayed here}, \begin{Sinput} dim(model.matrix( ~ a*b*d, data = aDat)) # 120'000 x 6000 \end{Sinput} where we note that $120'000 \times 6000 = 720 \textrm{mio}$, which is $720'000'000 * 8 / 2^{20} \approx 5500$ Megabytes. \emph{Unfortunately} \pkg{lme4} does \emph{not} use a sparse $X$-matrix for the fixed effects (yet), it just uses sparse matrices for the $Z$-matrix of random effects and sparse matrix operations for computations related to $Z$. Let us use a smaller factor \code{d} in order to investigate how sparse the $X$ matrix would be: <>= d2 <- factor(1:150) # 10 times smaller tmp2 <- expand.grid(id=id, a=a, b=b, d=d2) dim(tmp2) dim(mm <- model.matrix( ~ a*b*d, data=tmp2)) ## is 100 times smaller than original example class(smm <- Matrix(mm)) # automatically coerced to sparse round(object.size(mm) / object.size(smm), 1) @ shows that even for the small \code{d} here, the memory reduction would be more than an order of magnitude. \\ %% Reasons to fake here: %% 1) print() is needed for lattice -- but looks ugly, %% 2) the resulting pdf file is too large -- use png instead: <>= image(t(smm), aspect = 1/3, lwd=0, col.regions = "red") <>= png("sparseModels-X-sparse-image.png", width=6, height=3, units='in', res=150) print( <> ) dev.off() @ %%--NB: 'keep.source=FALSE' above is workaround-a-bug-in-R-devel-(2.13.x)--- \par\vspace*{-1ex} \centerline{% \includegraphics[width=1.1\textwidth]{sparseModels-X-sparse-image.png}} and working with the sparse instead of the dense model matrix is considerably faster as well, <>= x <- 1:600 system.time(y <- smm %*% x) ## sparse is much faster system.time(y. <- mm %*% x) ## than dense identical(as.matrix(y), y.) ## TRUE @ <>= toLatex(sessionInfo()) @ \end{document} Matrix/R/0000755000175100001440000000000014576344041011745 5ustar hornikusersMatrix/R/Cholesky.R0000644000175100001440000005156314575137654013674 0ustar hornikusers## METHODS FOR GENERIC: chol ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("chol", c(x = "generalMatrix"), function(x, uplo = "U", ...) { ch <- chol(forceSymmetric(x, uplo), ...) ch@Dimnames <- x@Dimnames # restore asymmetric 'Dimnames' ch }) setMethod("chol", c(x = "symmetricMatrix"), function(x, ...) chol(.M2kind(x, ","), ...)) setMethod("chol", c(x = "triangularMatrix"), function(x, uplo = "U", ...) { if(identical(uplo, x@uplo)) { ch <- chol(forceSymmetric(x, uplo), ...) ch@Dimnames <- x@Dimnames # restore asymmetric 'Dimnames' ch } else chol(forceDiagonal(x, x@diag), ...) }) setMethod("chol", c(x = "diagonalMatrix"), function(x, ...) chol(.M2kind(x, ","), ...)) setMethod("chol", c(x = "dsyMatrix"), function(x, pivot = FALSE, tol = -1, ...) { ch <- as(Cholesky(x, perm = pivot, tol = tol), "dtrMatrix") ch@Dimnames <- dimnames(x) if(ch@uplo != "U") t(ch) else ch }) setMethod("chol", c(x = "dspMatrix"), function(x, ...) { ch <- as(Cholesky(x), "dtpMatrix") ch@Dimnames <- dimnames(x) if(ch@uplo != "U") t(ch) else ch }) for(.cl in paste0("ds", c("C", "R", "T"), "Matrix")) setMethod("chol", c(x = .cl), function(x, pivot = FALSE, ...) { ch <- t(as(Cholesky(x, perm = pivot, LDL = FALSE, super = FALSE), "dtCMatrix")) # FIXME? give dtRMatrix, dtTMatrix? ch@Dimnames <- dimnames(x) ch }) rm(.cl) setMethod("chol", c(x = "ddiMatrix"), function(x, ...) { if(length(y <- x@x)) { if(is.na(min.y <- min(y)) || min.y < 0) stop(gettextf("%1$s(%2$s) is undefined: '%2$s' is not positive semidefinite", "chol", "x"), domain = NA) x@x <- sqrt(y) } x }) ## METHODS FOR GENERIC: Cholesky ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("Cholesky", c(A = "generalMatrix"), function(A, uplo = "U", ...) { ch <- Cholesky(forceSymmetric(A, uplo), ...) ch@Dimnames <- A@Dimnames # restore asymmetric 'Dimnames' ch }) setMethod("Cholesky", c(A = "symmetricMatrix"), function(A, ...) Cholesky(.M2kind(A, ","), ...)) setMethod("Cholesky", c(A = "triangularMatrix"), function(A, uplo = "U", ...) { ch <- Cholesky(forceSymmetric(A, uplo), ...) ch@Dimnames <- A@Dimnames # restore asymmetric 'Dimnames' ch }) setMethod("Cholesky", c(A = "diagonalMatrix"), function(A, ...) Cholesky(.M2kind(A, ","), ...)) setMethod("Cholesky", c(A = "dsyMatrix"), function(A, perm = TRUE, tol = -1, ...) .Call(dpoMatrix_trf, A, if(perm) 1L else 2L, perm, tol)) setMethod("Cholesky", c(A = "dspMatrix"), function(A, ...) .Call(dppMatrix_trf, A, 2L)) setMethod("Cholesky", c(A = "dsCMatrix"), function(A, perm = TRUE, LDL = !super, super = FALSE, Imult = 0, ...) .Call(dpCMatrix_trf, A, perm, LDL, super, Imult)) setMethod("Cholesky", c(A = "dsRMatrix"), function(A, ...) Cholesky(.tCRT(A), ...)) setMethod("Cholesky", c(A = "dsTMatrix"), function(A, ...) Cholesky(.M2C(A), ...)) setMethod("Cholesky", c(A = "ddiMatrix"), function(A, ...) { if(length(y <- A@x) && (is.na(min.y <- min(y)) || min.y < 0)) stop(gettextf("%1$s(%2$s) is undefined: '%2$s' is not positive semidefinite", "Cholesky", "x"), domain = NA) n <- (d <- A@Dim)[1L] r <- new("dCHMsimpl") r@Dim <- d r@Dimnames <- A@Dimnames r@colcount <- r@nz <- rep.int(1L, n) r@type <- c(0L, 0L, 0L, 1L, 0L, 0L) r@p <- 0:n r@i <- s <- seq.int(0L, length.out = n) r@x <- if(length(y)) y else rep.int(1, n) r@nxt <- c(seq_len(n), -1L, 0L) r@prv <- c(n + 1L, s, -1L) # @<- will error if n + 1L overflows r }) setMethod("Cholesky", c(A = "matrix"), function(A, uplo = "U", ...) { ch <- Cholesky(forceSymmetric(A, uplo), ...) if(!is.null(dn <- dimnames(A))) ch@Dimnames <- dn # restore asymmetric 'Dimnames' ch }) ## METHODS FOR GENERIC: chol2inv ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("chol2inv", c(x = "generalMatrix"), function(x, uplo = "U", ...) { d <- x@Dim if(d[1L] != d[2L]) stop("matrix is not square") chol2inv((if( uplo == "U") triu else tril)(x), ...) }) setMethod("chol2inv", c(x = "symmetricMatrix"), function(x, ...) chol2inv((if(x@uplo == "U") triu else tril)(x), ...)) setMethod("chol2inv", c(x = "triangularMatrix"), function(x, ...) chol2inv(.M2kind(x, ","), ...)) setMethod("chol2inv", c(x = "diagonalMatrix"), function(x, ...) chol2inv(.M2kind(x, ","), ...)) for(.cl in paste0("dt", c("r", "p"), "Matrix")) setMethod("chol2inv", c(x = .cl), function(x, ...) { if(x@diag != "N") x <- ..diagU2N(x) r <- .Call(Cholesky_solve, x, NULL) i <- if(x@uplo == "U") 2L else 1L r@Dimnames <- x@Dimnames[c(i, i)] r }) rm(.cl) for(.cl in paste0("dt", c("C", "R", "T"), "Matrix")) setMethod("chol2inv", c(x = .cl), function(x, ...) (if(x@uplo == "U") tcrossprod else crossprod)(solve(x))) rm(.cl) ## 'uplo' can affect the 'Dimnames' of the result here : setMethod("chol2inv", c(x = "ddiMatrix"), function(x, uplo = "U", ...) (if( uplo == "U") tcrossprod else crossprod)(solve(x))) ## METHODS FOR CLASS: p?Cholesky ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setAs("Cholesky", "dtrMatrix", function(from) { to <- new("dtrMatrix") to@Dim <- from@Dim to@uplo <- from@uplo to@x <- from@x to }) setAs("pCholesky", "dtpMatrix", function(from) { to <- new("dtpMatrix") to@Dim <- from@Dim to@uplo <- from@uplo to@x <- from@x to }) setMethod("diag", c(x = "Cholesky"), function(x = 1, nrow, ncol, names = TRUE) { d <- diag(as(x, "dtrMatrix"), names = FALSE) d * d }) setMethod("diag", c(x = "pCholesky"), function(x = 1, nrow, ncol, names = TRUE) { d <- diag(as(x, "dtpMatrix"), names = FALSE) d * d }) .def.unpacked <- .def.packed <- function(x, which, ...) { d <- x@Dim switch(which, "P1" =, "P1." = { r <- new("pMatrix") r@Dim <- d r@perm <- if(length(x@perm)) x@perm else seq_len(d[1L]) if(which == "P1.") r@margin <- 2L r }, "L" =, "L." =, "L1" =, "L1." = { r <- as(x, .CL) uplo <- x@uplo if(which == "L1" || which == "L1.") { r.ii <- diag(r, names = FALSE) r@x <- r@x / if(uplo == "U") .UP else .LO r@diag <- "U" } if((which == "L." || which == "L1.") == (uplo == "U")) r else t(r) }, "D" = { r <- new("ddiMatrix") r@Dim <- d r@x <- diag(x, names = FALSE) r }, stop(gettextf("'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", \"%3$s.\", \"%3$s1\", \"%3$s1.\", or \"%4$s\"", "which", "P", "L", "D"), domain = NA)) } body(.def.unpacked) <- do.call(substitute, list(body(.def.unpacked), list(.CL = "dtrMatrix", .UP = quote(r.ii), .LO = quote(rep(r.ii, each = d[1L]))))) body(.def.packed) <- do.call(substitute, list(body(.def.packed), list(.CL = "dtpMatrix", .UP = quote(r.ii[sequence.default(seq_len(d[1L]))]), .LO = quote(rep.int(r.ii, seq.int(to = 1L, by = -1L, length.out = d[1L])))))) setMethod("expand1", c(x = "Cholesky"), .def.unpacked) setMethod("expand1", c(x = "pCholesky"), .def.packed) rm(.def.unpacked, .def.packed) ## returning list(P1', L1, D, L1', P1) or list(P1', L, L', P1), ## where A = P1' L1 D L1' P1 = P1' L L' P1 and L = L1 sqrt(D) .def.unpacked <- .def.packed <- function(x, LDL = TRUE, ...) { d <- x@Dim dn <- x@Dimnames uplo <- x@uplo perm <- x@perm P <- new("pMatrix") P@Dim <- d P@Dimnames <- c(list(NULL), dn[2L]) P@margin <- 2L P@perm <- if(length(perm)) invertPerm(perm) else seq_len(d[1L]) P. <- P P.@Dimnames <- c(dn[1L], list(NULL)) P.@margin <- 1L X <- as(x, .CL) if(LDL) { L.ii <- diag(X, names = FALSE) X@x <- X@x / if(uplo == "U") .UP else .LO X@diag <- "U" } L <- if(uplo == "U") t(X) else X L. <- if(uplo == "U") X else t(X) if(LDL) { D <- new("ddiMatrix") D@Dim <- d D@x <- L.ii * L.ii list(P1. = P., L1 = L, D = D, L1. = L., P1 = P) } else list(P1. = P., L = L, L. = L., P1 = P) } body(.def.unpacked) <- do.call(substitute, list(body(.def.unpacked), list(.CL = "dtrMatrix", .UP = quote(L.ii), .LO = quote(rep(L.ii, each = d[1L]))))) body(.def.packed) <- do.call(substitute, list(body(.def.packed), list(.CL = "dtpMatrix", .UP = quote(L.ii[sequence.default(seq_len(d[1L]))]), .LO = quote(rep.int(L.ii, seq.int(to = 1L, by = -1L, length.out = d[1L])))))) ## returning list(L1, D, L1') or list(L, L'), where A = L1 D L1' = L L' setMethod("expand2", c(x = "Cholesky"), .def.unpacked) setMethod("expand2", c(x = "pCholesky"), .def.packed) rm(.def.unpacked, .def.packed) ## METHODS FOR CLASS: CHMfactor ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .CHM.is.perm <- function(x) !as.logical(x@type[1L]) .CHM.is.LDL <- function(x) !as.logical(x@type[2L]) .CHM.is.super <- function(x) as.logical(x@type[3L]) # Exported: isLDL <- function(x) { if(is(x, "CHMfactor")) .CHM.is.LDL(x) else stop(gettextf("'%s' does not inherit from virtual class %s", "x", "CHMfactor"), domain = NA) } setAs("CHMsimpl", "dtCMatrix", function(from) { nz <- from@nz k <- sequence.default(nz, from@p[seq_along(nz)] + 1L) to <- new("dtCMatrix") to@Dim <- from@Dim to@uplo <- "L" to@p <- c(0L, cumsum(nz)) to@i <- from@i[k] to@x <- from@x[k] to }) setAs("CHMsuper", "dgCMatrix", function(from) { super <- from@super pi <- from@pi b <- length(super) nr <- pi[-1L] - pi[-b] nc <- super[-1L] - super[-b] dp <- rep.int(nr, nc) to <- new("dgCMatrix") to@Dim <- from@Dim to@p <- c(0L, cumsum(dp)) to@i <- from@s[sequence.default(dp, rep.int(pi[-b] + 1L, nc))] to@x <- from@x to }) setMethod("diag", c(x = "CHMfactor"), function(x = 1, nrow, ncol, names = TRUE) .Call(CHMfactor_diag_get, x, TRUE)) setMethod("expand1", c(x = "CHMsimpl"), function(x, which, ...) { switch(which, "P1" =, "P1." = { r <- new("pMatrix") r@Dim <- d <- x@Dim r@perm <- if(length(x@perm)) x@perm + 1L else seq_len(d[1L]) if(which == "P1.") r@margin <- 2L r }, "L" =, "L." =, "L1" =, "L1." = { r <- as(x, "dtCMatrix") LDL. <- .CHM.is.LDL(x) if(which == "L1" || which == "L1.") { if(!LDL.) { r.ii <- diag(r, names = FALSE) r.p <- r@p r@x <- r@x / rep.int(r.ii , r.p[-1L] - r.p[-length(r.p)]) } diag(r) <- 1 } else if(LDL.) { r.ii <- diag(r, names = FALSE) r.p <- r@p if(anyNA(r.ii)) stop(gettextf("D[i,i] is NA, i=%d", which.max(is.na(r.ii))), domain = NA) if(min(r.ii) < 0) stop(gettextf("D[i,i] is negative, i=%d", which.max(r.ii < 0)), domain = NA) diag(r) <- 1 r@x <- r@x * rep.int(sqrt(r.ii), r.p[-1L] - r.p[-length(r.p)]) } if(which == "L" || which == "L1") r else t(r) }, "D" = { r <- new("ddiMatrix") r@Dim <- x@Dim r@x <- diag(x, names = FALSE) r }, stop(gettextf("'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", \"%3$s.\", \"%3$s1\", \"%3$s1.\", or \"%4$s\"", "which", "P", "L", "D"), domain = NA)) }) setMethod("expand1", c(x = "CHMsuper"), function(x, which, ...) { switch(which, "P1" =, "P1." = { r <- new("pMatrix") r@Dim <- d <- x@Dim r@perm <- if(length(x@perm)) x@perm + 1L else seq_len(d[1L]) if(which == "P1.") r@margin <- 2L r }, "L" =, "L." =, "L1" =, "L1." = { r <- as(x, "dgCMatrix") if(which == "L1" || which == "L1.") { r.ii <- diag(r, names = FALSE) r.p <- r@p r@x <- r@x / rep.int(r.ii, r.p[-1L] - r.p[-length(r.p)]) diag(r) <- 1 } if(which == "L" || which == "L1") r else t(r) }, "D" = { r <- new("ddiMatrix") r@Dim <- x@Dim r@x <- diag(x, names = FALSE) r }, stop(gettextf("'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", \"%3$s.\", \"%3$s1\", \"%3$s1.\", or \"%4$s\"", "which", "P", "L", "D"), domain = NA)) }) ## returning list(P1', L1, D, L1', P1) or list(P1', L, L', P1), ## where A = P1' L1 D L1' P1 = P1' L L' P1 and L = L1 sqrt(D) setMethod("expand2", c(x = "CHMsimpl"), function(x, LDL = TRUE, ...) { d <- x@Dim dn <- x@Dimnames perm <- x@perm P <- new("pMatrix") P@Dim <- d P@Dimnames <- c(list(NULL), dn[2L]) P@margin <- 2L P@perm <- if(length(perm)) invertPerm(perm, 0L, 1L) else seq_len(d[1L]) P. <- P P.@Dimnames <- c(dn[1L], list(NULL)) P.@margin <- 1L L <- as(x, "dtCMatrix") LDL. <- .CHM.is.LDL(x) if(!LDL && !LDL.) return(list(P1. = P., L = L, L. = t(L), P1 = P)) L.ii <- diag(L, names = FALSE) L.p <- L@p if(!LDL) { if(anyNA(L.ii)) stop(gettextf("D[i,i] is NA, i=%d", which.max(is.na(L.ii))), domain = NA) if(min(L.ii) < 0) stop(gettextf("D[i,i] is negative, i=%d", which.max(L.ii < 0)), domain = NA) diag(L) <- 1 L@x <- L@x * rep.int(sqrt(L.ii), L.p[-1L] - L.p[-length(L.p)]) return(list(P1. = P., L = L, L. = t(L), P1 = P)) } D <- new("ddiMatrix") D@Dim <- d if(LDL.) { diag(L) <- 1 D@x <- L.ii } else { L@x <- L@x / rep.int(L.ii , L.p[-1L] - L.p[-length(L.p)]) D@x <- L.ii * L.ii } list(P1. = P., L1 = L, D = D, L1. = t(L), P1 = P) }) ## returning list(P1', L1, D, L1', P1) or list(P1', L, L', P1), ## where A = P1' L1 D L1' P1 = P1' L L' P1 and L = L1 sqrt(D) setMethod("expand2", c(x = "CHMsuper"), function(x, LDL = TRUE, ...) { d <- x@Dim dn <- x@Dimnames perm <- x@perm P <- new("pMatrix") P@Dim <- d P@Dimnames <- c(list(NULL), dn[2L]) P@margin <- 2L P@perm <- if(length(perm)) invertPerm(perm, 0L, 1L) else seq_len(d[1L]) P. <- P P.@Dimnames <- c(dn[1L], list(NULL)) P.@margin <- 1L L <- as(x, "dgCMatrix") if(!LDL) return(list(P1. = P., L = L, L. = t(L), P1 = P)) L.ii <- diag(L, names = FALSE) L.p <- L@p L@x <- L@x / rep.int(L.ii, L.p[-1L] - L.p[-length(L.p)]) diag(L) <- 1 D <- new("ddiMatrix") D@Dim <- d D@x <- L.ii * L.ii list(P1. = P., L1 = L, D = D, L1. = t(L), P1 = P) }) ## returning list(P, L), where A = P' L L' P ## MJ: for backwards compatibility setMethod("expand", c(x = "CHMfactor"), function(x, ...) list(P = expand1(x, "P1"), L = expand1(x, "L"))) .updateCHMfactor <- function(object, parent, mult = 0) .Call(CHMfactor_update, object, parent, mult) setMethod("update", c(object = "CHMfactor"), function(object, parent, mult = 0, ...) { parent <- .M2kind(.M2C(parent), ",") if((shape <- .M.shape(parent)) != "s") { Matrix.message(gettextf("'%1$s' is not formally symmetric; factorizing tcrossprod(%1$s)", "parent"), domain = NA) if(shape == "t" && parent@diag != "N") parent <- ..diagU2N(parent) } .updateCHMfactor(object, parent, mult) }) .updownCHMfactor <- function(update, C, L) .Call(CHMfactor_updown, L, C, update) setMethod("updown", c(update = "character", C = "ANY", L = "ANY"), function(update, C, L) updown(identical(update, "+"), C, L)) setMethod("updown", c(update = "logical", C = "Matrix", L = "CHMfactor"), function(update, C, L) updown(update, .M2kind(.M2C(C), ","), L)) for(.cl in c("dgCMatrix", "dsCMatrix")) setMethod("updown", c(update = "logical", C = .cl, L = "CHMfactor"), function(update, C, L) { if(length(perm <- L@perm)) C <- C[perm + 1L, , drop = FALSE] .updownCHMfactor(update, C, L) }) rm(.cl) setMethod("updown", c(update = "logical", C = "dtCMatrix", L = "CHMfactor"), function(update, C, L) { if(C@diag != "N") C <- ..diagU2N(C) if(length(perm <- L@perm)) C <- C[perm + 1L, , drop = FALSE] .updownCHMfactor(update, C, L) }) setMethod("updown", c(update = "logical", C = "matrix", L = "CHMfactor"), function(update, C, L) updown(update, .m2sparse(C, ",gC"), L)) Matrix/R/show.R0000644000175100001440000005631414561451364013062 0ustar hornikusersprMatrix <- function(x, digits = getOption("digits"), maxp = getOption("max.print"), ...) { d <- dim(x) cl <- class(x) ## cld <- getClassDef(cl) tri <- extends(cl, "triangularMatrix") xtra <- if(tri && x@diag == "U") " (unitriangular)" else "" cat(sprintf('%d x %d Matrix of class "%s"%s\n', d[1], d[2], cl, xtra)) if(prod(d) <= maxp) { if(tri) prTriang(x, digits = digits, maxp = maxp) else print(as(x, "matrix"), digits = digits, max = maxp) } else { ## d[1] > maxp / d[2] >= nr : m <- as(x, "matrix") nr <- maxp %/% d[2] n2 <- ceiling(nr / 2) print(head(m, max(1, n2))) cat("\n ..........\n\n") print(tail(m, max(1, nr - n2))) cat("\n ..........\n\n") } ## DEBUG: cat("str(.):\n") ; str(x) invisible(x)# as print() S3 methods do } prTriang <- function(x, digits = getOption("digits"), maxp = getOption("max.print"), justify = "none", right = TRUE, ...) { ## modeled along stats:::print.dist upper <- x@uplo == "U" m <- as(x, "matrix") cf <- format(m, digits = digits, justify = justify) cf[if(upper) row(cf) > col(cf) else row(cf) < col(cf)] <- "." print(cf, quote = FALSE, right = right, max = maxp) invisible(x) } prDiag <- function(x, digits = getOption("digits"), justify = "none", right = TRUE, ...) { cf <- array(".", dim = x@Dim, dimnames = x@Dimnames) cf[row(cf) == col(cf)] <- vapply(diag(x), format, "", digits = digits, justify = justify) print(cf, quote = FALSE, right = right) invisible(x) } emptyColnames <- function(x, msg.if.not.empty = FALSE) { ## Useful for compact printing of (parts) of sparse matrices ## possibly dimnames(x) "==" NULL : if((nd <- length(d <- dim(x))) < 2L) return(x) nc <- d[2L] if(is.null(dn <- dimnames(x))) dn <- vector("list", nd) else if(msg.if.not.empty && is.character(cn <- dn[[2L]]) && any(nzchar(cn))) message(gettextf(" [[ suppressing %d column name%s %s ... ]]", nc, if(nc == 1L) "" else "s", paste0(sQuote(if(nc <= 3L) cn else cn[1:3]), collapse = ", ")), domain = NA) dn[[2L]] <- character(nc) dimnames(x) <- dn x } .formatSparseSimple <- function(m, asLogical = FALSE, digits = NULL, col.names, note.dropping.colnames = TRUE, dn = dimnames(m)) { stopifnot(is.logical(asLogical)) if(asLogical) cx <- array("N", dim(m), dimnames=dn) else { ## numeric (or --not yet implemented-- complex): cx <- apply(m, 2, format, digits=digits) if(is.null(dim(cx))) {# e.g. in 1 x 1 case dim(cx) <- dim(m) dimnames(cx) <- dn } } if (missing(col.names)) col.names <- { if(!is.null(cc <- getOption("sparse.colnames"))) cc else if(is.null(dn[[2]])) FALSE else { # has column names == dn[[2]] ncol(m) < 10 } } if(identical(col.names, FALSE)) cx <- emptyColnames(cx, msg.if.not.empty = note.dropping.colnames) else if(is.character(col.names)) { stopifnot(length(col.names) == 1) cn <- col.names switch(substr(cn, 1,3), "abb" = { iarg <- as.integer(sub("^[^0-9]*", '', cn)) colnames(cx) <- abbreviate(colnames(cx), minlength = iarg) }, "sub" = { iarg <- as.integer(sub("^[^0-9]*", '', cn)) colnames(cx) <- substr(colnames(cx), 1, iarg) }, stop(gettextf("invalid 'col.names' string: %s", cn), domain=NA)) } ## else: nothing to do for col.names == TRUE cx } ## NB: Want this to work also for logical or numeric traditional matrix 'x': formatSparseM <- function(x, zero.print = ".", align = c("fancy", "right"), m = as(x, "matrix"), asLogical = NULL, uniDiag = NULL, digits = NULL, cx, iN0, dn = dimnames(m)) { cld <- getClassDef(class(x)) if(is.null(asLogical)) { asLogical <- extends1of(cld, c("nsparseMatrix", "indMatrix", "lsparseMatrix")) || # simple TRUE/FALSE (extends(cld, "matrix") && is.logical(x)) # has NA and (non-)structural FALSE } if(missing(cx)) cx <- .formatSparseSimple(m, asLogical=asLogical, digits=digits, dn=dn) if(is.null(d <- dim(cx))) {# e.g. in 1 x 1 case d <- dim(cx) <- dim(m) dimnames(cx) <- dn } if(missing(iN0)) iN0 <- 1L + .Call(m_encodeInd, non0ind(x, cld), di = d, FALSE, FALSE) ## ne <- length(iN0) if(asLogical) { cx[m] <- "|" if(!extends(cld, "sparseMatrix")) x <- as(x,"sparseMatrix") if(anyFalse(x@x)) { ## any (x@x == FALSE) ## Careful for *non-sorted* Tsparse, e.g. from U-diag if(extends(cld, "TsparseMatrix")) { ## have no "fast uniqTsparse(): x <- as(x, "CsparseMatrix") cld <- getClassDef(class(x)) } F. <- is0(x@x) # the 'FALSE' ones ### FIXME: have iN0 already above -- *really* need the following ??? --FIXME-- ij <- non0.i(x, cld, uniqT=FALSE) if(extends(cld, "symmetricMatrix")) { ## also get "other" triangle notdiag <- ij[,1] != ij[,2] # but not the diagonals again ij <- rbind(ij, ij[notdiag, 2:1], deparse.level=0) F. <- c(F., F.[notdiag]) } iN0 <- 1L + .Call(m_encodeInd, ij, di = d, FALSE, FALSE) cx[iN0[F.]] <- ":" # non-structural FALSE (or "o", "," , "-" or "f")? } } else if(match.arg(align) == "fancy" && !is.integer(m)) { fi <- apply(m, 2, format.info) ## fi[3,] == 0 <==> not expo. ## now 'format' the zero.print by padding it with ' ' on the right: ## case 1: non-exponent: fi[2,] + as.logical(fi[2,] > 0) ## the column numbers of all 'zero' entries -- (*large*) cols <- 1L + (0:(prod(d)-1L))[-iN0] %/% d[1] pad <- ifelse(fi[3,] == 0, fi[2,] + as.logical(fi[2,] > 0), ## exponential: fi[2,] + fi[3,] + 4) ## now be efficient ; sprintf() is relatively slow ## and pad is much smaller than 'cols'; instead of "simply" ## zero.print <- sprintf("%-*s", pad[cols] + 1, zero.print) if(any(doP <- pad > 0)) { # ## only pad those that need padding - *before* expanding z.p.pad <- rep.int(zero.print, length(pad)) z.p.pad[doP] <- sprintf("%-*s", pad[doP] + 1, zero.print) zero.print <- z.p.pad[cols] } else zero.print <- rep.int(zero.print, length(cols)) } ## else "right" : nothing to do if(!asLogical && isTRUE(uniDiag)) { ## use "I" in diagonal -- pad correctly if(any(diag(x) != 1)) stop("uniDiag=TRUE, but not all diagonal entries are 1") D <- diag(cx) # use if(any((ir <- regexpr("1", D)) < 0)) { warning("uniDiag=TRUE, not all entries in diagonal coded as 1") } else { ir <- as.vector(ir) nD <- nchar(D, "bytes") ## replace "1..." by "I " (I plus blanks) substr(D, ir, nD) <- sprintf("I%*s", nD - ir, "") diag(cx) <- D } } cx[-iN0] <- zero.print cx } ## The `format()` method for sparse Matrices; ## also used inside sparseMatrix print()ing, ## exported as it might be useful directly. formatSpMatrix <- function(x, digits = NULL, maxp = 1e+09, # ~ 0.5 * .Machine$integer.max cld = getClassDef(class(x)), zero.print = ".", col.names, note.dropping.colnames = TRUE, uniDiag = TRUE, align = c("fancy", "right"), ...) { stopifnot(extends(cld, "sparseMatrix")) validObject(x) # have seen seg.faults for invalid objects d <- dim(x) unitD <- extends(cld, "triangularMatrix") && x@diag == "U" ## Will note it is *unit*-diagonal by using "I" instead of "1" if(unitD) x <- .Call(R_sparse_diag_U2N, x) if(maxp < 100) maxp <- 100L # "stop gap" if(prod(d) > maxp) { # "Large" => will be "cut" ## only coerce to dense that part which won't be cut : nr <- maxp %/% d[2] m <- as(x[1:max(1, nr), ,drop=FALSE], "matrix") } else { m <- as(x, "matrix") } dn <- dimnames(m) ## will be === dimnames(cx) binary <- extends(cld,"nsparseMatrix") || extends(cld, "indMatrix") # -> simple T / F logi <- binary || extends(cld,"lsparseMatrix") # has NA and (non-)structural FALSE cx <- .formatSparseSimple(m, asLogical = logi, digits=digits, col.names=col.names, note.dropping.colnames=note.dropping.colnames, dn=dn) if(is.logical(zero.print)) zero.print <- if(zero.print) "0" else " " if(binary) { cx[!m] <- zero.print cx[m] <- "|" } else { # non-binary ==> has 'x' slot ## show only "structural" zeros as 'zero.print', not all of them.. ## -> cannot use 'm' alone d <- dim(cx) ne <- length(iN0 <- 1L + .Call(m_encodeInd, non0ind(x, cld), di = d, FALSE, FALSE)) if(0 < ne && (logi || ne < prod(d))) { cx <- formatSparseM(x, zero.print, align, m=m, asLogical = logi, uniDiag = unitD & uniDiag, digits=digits, cx=cx, iN0=iN0, dn=dn) } else if (ne == 0)# all zeroes cx[] <- zero.print } cx } ## FIXME(?) -- ``merge this'' (at least ``synchronize'') with ## - - - prMatrix() from ./Auxiliaries.R ## FIXME: prTriang() in ./Auxiliaries.R should also get align = "fancy" printSpMatrix <- function(x, digits = NULL, maxp = max(100L, getOption("max.print")), cld = getClassDef(class(x)), zero.print = ".", col.names, note.dropping.colnames = TRUE, uniDiag = TRUE, col.trailer = "", align = c("fancy", "right"), ...) { stopifnot(extends(cld, "sparseMatrix")) cx <- formatSpMatrix(x, digits=digits, maxp=maxp, cld=cld, zero.print=zero.print, col.names=col.names, note.dropping.colnames=note.dropping.colnames, uniDiag=uniDiag, align=align) if(col.trailer != '') cx <- cbind(cx, col.trailer, deparse.level = 0) ## right = TRUE : cheap attempt to get better "." alignment print(cx, quote = FALSE, right = TRUE, max = maxp) invisible(x) } ##' The "real" show() / print() method, calling the above printSpMatrix(): printSpMatrix2 <- function(x, digits = NULL, maxp = max(100L, getOption("max.print")), zero.print = ".", col.names, note.dropping.colnames = TRUE, uniDiag = TRUE, suppRows = NULL, suppCols = NULL, col.trailer = if(suppCols) "......" else "", align = c("fancy", "right"), width = getOption("width"), fitWidth = TRUE, ...) { d <- dim(x) cl <- class(x) cld <- getClassDef(cl) xtra <- if(extends(cld, "triangularMatrix") && x@diag == "U") " (unitriangular)" else "" cat(sprintf('%d x %d sparse Matrix of class "%s"%s\n', d[1], d[2], cl, xtra)) setW <- !missing(width) && width > getOption("width") if(setW) { op <- options(width = width) ; on.exit( options(op) ) } if((isFALSE(suppRows) && isFALSE(suppCols)) || (!isTRUE(suppRows) && !isTRUE(suppCols) && prod(d) <= maxp)) { ## "small matrix" and supp* not TRUE : no rows or columns are suppressed if(missing(col.trailer) && is.null(suppCols)) suppCols <- FALSE # for default 'col.trailer' printSpMatrix(x, cld=cld, digits=digits, maxp=maxp, zero.print=zero.print, col.names=col.names, note.dropping.colnames=note.dropping.colnames, uniDiag=uniDiag, col.trailer=col.trailer, align=align) } else { ## d[1] > maxp / d[2] >= nr : -- this needs [,] working: validObject(x) sTxt <- c(" ", gettext("in show(); maybe adjust options(max.print=, width=)"), "\n ..............................\n") useW <- width - (format.info(d[1], digits=digits)[1] + 3+1) ## == width - space for the largest row label : "[,] " ## Suppress rows and/or columns in printing ... ## ---------------------------------------- but which exactly depends on format ## Determining number of columns - first assuming all zeros : ". . "..: 2 chars/column ## i.e., we get the *maximal* numbers of columns to keep, nc : if(is.null(suppCols)) # i.e., "it depends" .. suppCols <- (d[2] * 2 > useW) # used in 'col.trailer' default nCc <- 1 + nchar(col.trailer, "width") if(suppCols) { nc <- (useW - nCc) %/% 2 x <- x[ , 1:nc, drop = FALSE] } else nc <- d[2] nr <- maxp %/% nc # if nc becomes smaller, nr will become larger (!) if(is.null(suppRows)) suppRows <- (nr < d[1]) if(suppRows) { n2 <- ceiling(nr / 2) nr1 <- min(d[1], max(1L, n2)) #{rows} in 1st part nr2 <- max(1L, nr-n2) #{rows} in 2nd part nr <- nr1+nr2 # total #{rows} to be printed if(fitWidth) { ## one iteration of improving the width, by "fake printing" : cM <- formatSpMatrix(x[seq_len(nr1), , drop = FALSE], digits=digits, maxp=maxp, zero.print=zero.print, col.names=col.names, align=align, note.dropping.colnames=note.dropping.colnames, uniDiag=FALSE) ## width needed (without the 'col.trailer's 'nCc'): matW <- nchar(capture.output(print(cM, quote=FALSE, right=FALSE))[[1]]) needW <- matW + (if(suppCols) nCc else 0) if(needW > useW) { ## need more width op <- options(width = width+(needW-useW)) if(!setW) on.exit( options(op) ) } } printSpMatrix(x[seq_len(nr1), , drop=FALSE], digits=digits, maxp=maxp, zero.print=zero.print, col.names=col.names, note.dropping.colnames=note.dropping.colnames, uniDiag=uniDiag, col.trailer = col.trailer, align=align) suppTxt <- if(suppCols) gettextf("suppressing %d columns and %d rows", d[2]-nc , d[1]-nr) else gettextf("suppressing %d rows", d[1]-nr) cat("\n ..............................", "\n ........", suppTxt, sTxt, sep='') ## tail() automagically uses "[..,]" rownames: printSpMatrix(tail(x, nr2), digits=digits, maxp=maxp, zero.print=zero.print, col.names=col.names, note.dropping.colnames=note.dropping.colnames, uniDiag=FALSE, col.trailer = col.trailer, align=align) } else if(suppCols) { printSpMatrix(x[ , 1:nc , drop = FALSE], digits=digits, maxp=maxp, zero.print=zero.print, col.names=col.names, note.dropping.colnames=note.dropping.colnames, uniDiag=uniDiag, col.trailer = col.trailer, align=align) cat("\n .....", gettextf("suppressing %d columns", d[2]-nc), sTxt, sep='') } else stop("logic programming error in printSpMatrix2(), please report") invisible(x) } } prSpVector <- function(x, digits = getOption("digits"), maxp = getOption("max.print"), zero.print = ".", ...) { cld <- getClassDef(class(x)) stopifnot(extends(cld, "sparseVector"), maxp >= 1) if(is.logical(zero.print)) zero.print <- if(zero.print) "0" else " " ## kind <- .M.kindC(cld) ## has.x <- kind != "n" n <- x@length if(n > 0) { if(n > maxp) { ## n > maxp =: nn : will cut length of what we'll display : x <- head(x, maxp) n <- maxp } xi <- x@i is.n <- extends(cld, "nsparseVector") logi <- is.n || extends(cld, "lsparseVector") cx <- if(logi) rep.int("N", n) else character(n) cx[if(length(xi)) -xi else TRUE] <- zero.print cx[xi] <- if(is.n) "|" else if(logi) c(":", "|")[x@x + 1L] else ## numeric (or --not yet-- complex): 'has.x' in any cases format(x@x, digits = digits) ## right = TRUE : cheap attempt to get better "." alignment print(cx, quote = FALSE, right = TRUE, max = maxp) } invisible(x) # TODO? in case of n > maxp, "should" return original x } ## METHODS FOR GENERIC: show ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("show", c(object = "denseMatrix"), function(object) prMatrix(object)) setMethod("show", c(object = "sparseMatrix"), function(object) printSpMatrix2(object)) setMethod("show", c(object = "diagonalMatrix"), function(object) { d <- dim(object) cl <- class(object) cat(sprintf('%d x %d diagonal matrix of class "%s"', d[1L], d[2L], cl)) if(d[1L] < 50) { cat("\n") prDiag(object) } else { cat(", with diagonal entries\n") show(diag(object)) invisible(object) } }) setMethod("show", c(object = "MatrixFactorization"), function(object) { cat("matrix factorization of ") str(object) }) setMethod("show", c(object = "CholeskyFactorization"), function(object) { cat("Cholesky factorization of ") str(object) }) setMethod("show", c(object = "BunchKaufmanFactorization"), function(object) { cat("Bunch-Kaufman factorization of ") str(object) }) setMethod("show", c(object = "SchurFactorization"), function(object) { cat("Schur factorization of ") str(object) }) setMethod("show", c(object = "LU"), function(object) { cat("LU factorization of ") str(object) }) setMethod("show", c(object = "QR"), function(object) { cat("QR factorization of ") str(object) }) setMethod("show", c(object = "sparseVector"), function(object) { n <- object@length cl <- class(object) cat(sprintf("sparse vector (nnz/length = %d/%.0f) of class \"%s\"\n", length(object@i), as.double(n), cl)) maxp <- max(1, getOption("max.print")) if(n <= maxp) prSpVector(object, maxp = maxp) else { ## n > maxp : will cut length of what we'll display : ## cannot easily show head(.) & tail(.) because of ## "[1] .." printing of tail prSpVector(head(object, maxp), maxp = maxp) cat(" ............................\n", " ........suppressing ", n - maxp, " entries in show(); maybe adjust options(max.print=)\n", " ............................\n\n", sep = "") } invisible(object) }) ## METHODS FOR GENERIC: print ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("print", c(x = "sparseMatrix"), printSpMatrix2) setMethod("print", c(x = "diagonalMatrix"), prDiag) ## METHODS FOR GENERIC: format ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("format", c(x = "sparseMatrix"), formatSpMatrix) ## METHODS FOR GENERIC: summary ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("summary", c(object = "sparseMatrix"), function(object, uniqT = FALSE, ...) { d <- object@Dim ## return a data frame (int, int, {double|logical}) : r <- as.data.frame(mat2triplet(object, uniqT = uniqT)) attr(r, "header") <- sprintf("%d x %d sparse Matrix of class \"%s\", with %d entries", d[1L], d[2L], class(object), nrow(r)) class(r) <- c("sparseSummary", oldClass(r)) r }) setMethod("summary", c(object = "diagonalMatrix"), function(object, ...) { d <- object@Dim r <- summary(object@x, ...) attr(r, "header") <- sprintf("%d x %d diagonal Matrix of class \"%s\"", d[1L], d[2L], class(object)) class(r) <- c("diagSummary", class(r)) r }) print.sparseSummary <- print.diagSummary <- function (x, ...) { cat(attr(x, "header"), "\n", sep = "") NextMethod() invisible(x) } Matrix/R/models.R0000644000175100001440000005324614575137654013376 0ustar hornikusers#### Utilities for Sparse Model Matrices ## > from <- factor(sample(c(1:100, NA), size = 1e+04, replace = TRUE, ## + prob = rep.int(c(1, 20), c(100L, 1L)))) ## > microbenchmark::microbenchmark( ## + Matrix:::fac2sparse1(from, drop.unused.levels = FALSE), ## + Matrix:::fac2sparse2(from, drop.unused.levels = FALSE), ## + Matrix:::fac2sparse (from, drop.unused.levels = FALSE), ## + times = 10000L) ## Unit: microseconds ## expr min lq mean median uq max neval ## Matrix:::fac2sparse1(from, drop.unused.levels = FALSE) 94.997 105.001 118.6117 107.789 110.413 4439.111 10000 ## Matrix:::fac2sparse2(from, drop.unused.levels = FALSE) 538.289 586.341 643.7947 595.197 602.700 43128.556 10000 ## Matrix:::fac2sparse (from, drop.unused.levels = FALSE) 163.139 185.115 221.7241 190.117 193.889 44887.784 10000 if(FALSE) { ## The "first" version, no longer used: fac2sparse1 <- function(from, to = c("d", "i", "l", "n", "z"), drop.unused.levels = FALSE) { ## factor(-like) --> sparseMatrix {also works for integer, character} fact <- if (drop.unused.levels) factor(from) else as.factor(from) levs <- levels(fact) n <- length(fact) to <- match.arg(to) ## MM: using new() and then assigning slots has efficiency "advantage" ## of *not* validity checking res <- new(paste0(to, "gCMatrix")) res@i <- as.integer(fact) - 1L # 0-based res@p <- 0:n res@Dim <- c(length(levs), n) res@Dimnames <- list(levs, NULL) if(to != "n") res@x <- rep.int(switch(to, "d" = 1., "i" = 1L, "l" = TRUE, "z" = 1+0i), n) res } ## The "second" version, no longer used: ## * this one handles NAs correctly but may be slightly less efficient ## than fac2sparse1() above fac2sparse2 <- function(from, to = c("d", "i", "l", "n", "z"), drop.unused.levels = TRUE, repr = c("C", "T", "R"), giveCsparse) { ## factor(-like) --> sparseMatrix {also works for integer, character} fact <- if (drop.unused.levels) factor(from) else as.factor(from) levs <- levels(fact) n <- length(fact) to <- match.arg(to) i <- as.integer(fact) - 1L ## 0-based indices df <- data.frame(i = i, j = if(n) 0:(n-1L) else integer())[!is.na(i),] if(to != "n") df$x <- rep.int(switch(to, "d" = 1., "i" = 1L, "l" = TRUE, "z" = 1+0i), nrow(df)) T <- do.call(new, c(list(Class = paste0(to, "gTMatrix"), Dim = c(length(levs), n), Dimnames = list(levs, names(fact))), df)) ## silent, back compatible (not yet warning about 'giveCsparse' deprecation): repr <- if(missing(repr) && !missing(giveCsparse)) if(giveCsparse) "C" else "T" else match.arg(repr) switch(repr, "C" = .M2C(T), "T" = T,# TsparseMatrix "R" = .M2R(T)) } } # if(FALSE) ## The "third" version, dealing with NAs _and_ fast: fac2sparse <- function(from, to = c("d", "l", "n"), # no "i" or "z" yet drop.unused.levels = TRUE, repr = c("C", "R", "T"), giveCsparse) { cl <- ".g.Matrix" substr(cl, 1L, 1L) <- to <- match.arg(to) substr(cl, 3L, 3L) <- repr <- if(!missing(repr) || missing(giveCsparse)) match.arg(repr) else if(giveCsparse) "C" else "T" ## Arguments are valid: _now_ allocate from <- if(drop.unused.levels && is.factor(from)) factor(from) else as.factor(from) n <- length(from) lv <- levels(from) nlv <- length(lv) res <- new(cl) res@Dim <- c(nlv, n) res@Dimnames <- list(lv, names(from)) i. <- switch(repr, "C" = { not.na <- !is.na(from) res@p <- c(0L, cumsum(not.na)) res@i <- as.integer(from)[not.na] - 1L }, "R" = { res@p <- c(0L, cumsum(tabulate(from, nlv))) res@j <- order(from, na.last = NA) - 1L }, "T" = { which.not.na <- which(!is.na(from)) res@i <- as.integer(from)[which.not.na] - 1L res@j <- which.not.na - 1L } ) if(to != "n") res@x <- rep.int(switch(to, "d" = 1, "l" = TRUE, "i" = 1L, "z" = 1+0i), length(i.)) res } setAs("factor", "sparseMatrix", function(from) fac2sparse(from, to = "d")) ## FIXME? support factor->[dlnCRT]sparseMatrix? ##' fac2Sparse() := fac2sparse w/ contrasts ##' ##' @param from factor of which we want the "contrasted" (indicator) ##' design matrix ##' @param to character string specifying the response type ##' @param drop.unused.level logical indicating if non-present factor ##' levels should be dropped, via factor(from) ##' @param factorPatt12 logical vector fp[] of length 2 ##' fp[1] : give contrasted t(X); fp[2] : give "dummy" t(X) [=fac2sparse()] ##' @param contrasts.arg character string or NULL or (coercible to) ##' sparseMatrix, specifying the contrast ##' ##' @return a list of length two, each with the corresponding t(model matrix), ##' when the corresponding factorPatt12 is true. fac2Sparse <- function(from, to = c("d", "l", "n"), # no "i" or "z" yet drop.unused.levels = TRUE, repr = c("C", "R", "T"), giveCsparse, factorPatt12, contrasts.arg = NULL) { stopifnot(is.logical(factorPatt12), length(factorPatt12) == 2L) if(!any(factorPatt12)) return(list(NULL, NULL)) # nothing to do m <- fac2sparse(from, to = to, drop.unused.levels = drop.unused.levels, repr = repr, giveCsparse = giveCsparse) list(if(factorPatt12[1L]) { ## contrasted coding, using 'contrasts.arg' if(is.null(contrasts.arg)) contrasts.arg <- getOption("contrasts")[[if(is.ordered(from)) "ordered" else "unordered"]] crossprod(if(is.character(contrasts.arg)) { ## calling contr.*() with level names directly: contr <- get(contrasts.arg, mode = "function") contr(m@Dimnames[[1L]], sparse = TRUE) } else as(contrasts.arg, "sparseMatrix"), m) }, if(factorPatt12[2L]) ## uncontrasted ("dummy") coding m ) } ## Cut and paste from stats:::deparse2() in stats/R/models.R deparse2 <- function(x) paste(deparse(x, width.cutoff = 500L, backtick = !is.symbol(x) && is.language(x)), collapse = " ") ## Cut and paste from stats:::model.matrix.default() in stats/R/models.R, ## with some adaptation, most notably at the very end where we do _not_ ## call the C-level utility of 'stats' sparse.model.matrix <- function(object, data = environment(object), contrasts.arg = NULL, xlev = NULL, transpose = FALSE, drop.unused.levels = FALSE, row.names = TRUE, sep = "", verbose = FALSE, ...) { t <- if(missing(data)) terms(object) else terms(object, data=data) if (is.null(attr(data, "terms"))) data <- model.frame(object, data, xlev=xlev) else { reorder <- match(vapply(attr(t, "variables"), deparse2, "")[-1L], names(data)) if (anyNA(reorder)) stop("model frame and formula mismatch in sparse.model.matrix()") if(!identical(reorder, seq_len(ncol(data)))) data <- data[,reorder, drop=FALSE] } int <- attr(t, "response") if(length(data)) { contr.funs <- as.character(getOption("contrasts")) namD <- names(data) ## turn any character columns into factors for(i in namD) if(is.character(data[[i]])) data[[i]] <- factor(data[[i]]) isF <- vapply(data, function(x) is.factor(x) || is.logical(x), NA) isF[int] <- FALSE isOF <- vapply(data, is.ordered, NA) for(nn in namD[isF]) # drop response if(is.null(attr(data[[nn]], "contrasts"))) contrasts(data[[nn]]) <- contr.funs[1 + isOF[nn]] ## it might be safer to have numerical contrasts: ## get(contr.funs[1 + isOF[nn]])(nlevels(data[[nn]])) if (!is.null(contrasts.arg)) { if (!is.list(contrasts.arg)) warning("non-list contrasts argument ignored") else { ## contrasts.arg is a list if (is.null(namC <- names(contrasts.arg))) stop("'contrasts.arg' argument must be named") for (nn in namC) { if (is.na(ni <- match(nn, namD))) warning(gettextf("variable '%s' is absent, its contrast will be ignored", nn), domain = NA) else { ca <- contrasts.arg[[nn]] ## contrasts(*, ncol(m)) <- m works also ## for function||character 'm' in R >= 4.2, ## which supports how.many=NULL if(is.matrix(ca) || is(ca, "Matrix")) contrasts(data[[ni]], ncol(ca)) <- ca else contrasts(data[[ni]]) <- ca } } } } ## non-null contrasts.arg } else { # no rhs terms ('~1', or '~0'): internal model.matrix needs some variable isF <- FALSE data[["x"]] <- raw(nrow(data)) } ## ## ans <- .External2(C_modelmatrix, t, data) ## if(any(isF)) ## attr(ans, "contrasts") <- lapply(data[isF], attr, "contrasts") ## ## if(verbose) { cat("model.spmatrix(t, data, ...) with t =\n") str(t, give.attr = FALSE) } ans <- model.spmatrix(trms = t, mf = data, transpose = transpose, drop.unused.levels = drop.unused.levels, row.names = row.names, sep = sep, verbose = verbose) ## MJ: hmm ... our tests require that this "slot" exists, ## even in the empty case, i.e., !any(isF) ... why? attr(ans, "contrasts") <- lapply(data[isF], attr, "contrasts") ## ans } # sparse.model.matrix ##' Produce the t(Z); Z = "design matrix" of (X : Y), where ##' --- t(Z) : aka rowwise -version : "r" ##' ##' @title sparse model matrix for 2-way interaction ##' @param X and Y either are numeric matrices {maybe 1-column} ##' @param Y or "as(, sparseM)" {dgCMatrix} ##' @param do.names logical ##' @param forceSparse logical ##' @return ##' @author Martin Maechler .sparse.interaction.2 <- # formerly sparse2int() function(X, Y, do.names = TRUE, forceSparse = FALSE, verbose = FALSE) { ### FIXME -- the X[rep(..), ] * Y[rep(..), ] construct can become HUGE, even for sparse X[],Y[] ### ----- --> Matrix bug #1330 and ~/R/MM/Pkg-ex/Matrix/sparse-matrix-fix.R ## MJ: Moreover, as(, "sparseMatrix") is a dgCMatrix, ## for which row-indexing is already rather inefficient ... FIXME? sx <- isS4(X) sy <- isS4(Y) nx <- (dx <- dim(X))[1L] ny <- (dy <- dim(Y))[1L] if(verbose) cat(sprintf(".sparse.interaction.2(%s[%d], %s[%d])\n", if(sx) "" else "", nx, if(sy) "" else "", ny)) if(do.names) { dnx <- dimnames(X) dny <- dimnames(Y) } dimnames(X) <- dimnames(Y) <- list(NULL, NULL) r <- if(sx && sy) { ## 'X' and 'Y' are dgCMatrix (if(ny == 1L) X else X[rep.int(seq_len(nx), times = ny), ]) * (if(nx == 1L) Y else Y[rep (seq_len(ny), each = nx), ]) } else if (sx) { ## 'X' is a dgCMatrix, 'Y' is a numeric matrix if(ny <= 1L) { ## FIXME: a similar trick would be applicable for ny > 1 r <- X dp <- X@p[-1L] - X@p[-(dx[2L]+1L)] ## stopifnot(all(dp %in% 0:1)) r@x <- Y[dp == 1L] * X@x r } else { X[rep.int(seq_len(nx), times = ny), ] * (if(nx == 1L) Y else Y[rep (seq_len(ny), each = nx), ]) } } else if(sy) { ## 'X' is a numeric matrix, 'Y' is a dgCMatrix if(nx <= 1L) { ## FIXME: a similar trick would be applicable for nx > 1 r <- Y dp <- Y@p[-1L] - Y@p[-(dy[2L]+1L)] ## stopifnot(all(dp %in% 0:1)) r@x <- X[dp == 1L] * Y@x r } else { (if(ny == 1L) X else X[rep.int(seq_len(nx), times = ny), ]) * Y[rep (seq_len(ny), each = nx), ] } } else { ## 'X' and 'Y' are numeric matrices r <- (if(ny == 1L) X else X[rep.int(seq_len(nx), times = ny), ]) * (if(nx == 1L) Y else Y[rep (seq_len(ny), each = nx), ]) if(forceSparse) .m2sparse(r, "dgC") else r } ## FIXME: This 'names' business needs a good solution ... ## but maybe "up in the caller" ... if(do.names && !is.null(dim(r)) && !is.null(rnx <- dnx[[1L]]) && !is.null(rny <- dny[[1L]])) dimnames(r)[[1L]] <- outer(rnx, rny, paste, sep = ":") r } # .sparse.interaction.2 ##' Sparse Model Matrix for a (high order) interaction term A:B:x:C ##' ##' @param rList list(.) of (transposed) single-factor model matrices, ##' belonging to, say, factors a, b, c,... ##' @param do.names ##' @param forceSparse ##' @param verbose ##' @return the model matrix corresponding to a:b:... .sparse.interaction.N <- # formerly sparseInt.r() function(rList, do.names = TRUE, forceSparse = FALSE, verbose = FALSE) { if((n <- length(rList)) == 0L) return(NULL) # caller beware if(verbose) cat(sprintf(".sparse.interaction.N([%d], fS=%s): is.mat=(%s)\n", n, forceSparse, paste0(symnum(vapply(rList, is.matrix, NA)), collapse = "")), sep = "") r <- rList[[1L]] if(n > 1L) for(i in 2:n) r <- .sparse.interaction.2(r, rList[[i]], forceSparse = forceSparse, do.names = do.names, verbose = verbose) if(!forceSparse) r else if(!isS4(r)) .m2sparse(r, "dgC") else if(is(r, "denseMatrix")) .dense2sparse(r, "C") else r } # .sparse.interaction.N ## MJ: unused if(FALSE) { is.model.frame <- function(x) { ## Purpose: check if x is a "valid" model.frame ## ------------------------------------------------------------ ## Author: Martin Maechler, Date: 3 Jul 2009 is.data.frame(x) && !is.null(tms <- attr(x, "terms")) && inherits(tms, "terms") && ## is.terms() would be better inherits(tms, "formula") && is.matrix(attr(tms, "factors")) && is.language(vv <- attr(tms, "variables")) && vv[[1]] == as.symbol("list") && all(vapply(as.list(vv[-1]), as.character, "") %in% colnames(x)) ## all((vars <- sapply(as.list(vv[-1]), as.character)) %in% colnames(x)) ## and we could go on testing vars } } ## MJ ##' Create a sparse model matrix from a model frame. ##' ##' @title Sparse Model Matrix from Model Frame ##' @param trms a "terms" object ##' @param mf a data frame, typically resulting from model.frame() ##' @param transpose logical indicating if X' = t(X) {is faster!} ##' or X should be returned ##' @param drop.unused.levels logical indicating if unused factor ##' levels should be dropped ##' @param row.names ##' @return sparse matrix (class "dgCMatrix") ##' @author Martin Maechler model.spmatrix <- function(trms, mf, transpose=FALSE, drop.unused.levels = FALSE, row.names=TRUE, sep="", verbose=FALSE) { ## Author: Martin Maechler, Date: 7 Jul 2009 ## mf is a model frame or a "simple" data.frame [after reorder !] stopifnot(is.data.frame(mf)) n <- nrow(mf) if(row.names) rnames <- row.names(mf) ## mf: make into list, dropping all attributes (but the names) ### FIXME: for poly(., 5) mf has a 5-column matrix as "one column" => looses names here fnames <- names(mf <- unclass(mf)) attributes(mf) <- list(names = fnames) if(length(factorPattern <- attr(trms, "factors"))) { d <- dim(factorPattern) nVar <- d[1] nTrm <- d[2] n.fP <- dimnames(factorPattern) fnames <- n.fP[[1]] # == names of variables {incl. "F(var)"} in the model Names <- n.fP[[2]] # == colnames == names of terms: "a", "b:c", ... } else { ## degenerate, e.g. 'Y ~ 1' nVar <- nTrm <- 0L fnames <- Names <- character(0) } ## all the "variables in the model" are also in "mf", including "sin(x)"; ## actually, ..../src/main/model.c even assumes stopifnot((m <- length(mf)) >= nVar) if(verbose) cat(sprintf("model.spmatrix(): (n=%d, nVar=%d (m=%d), nTrm=%d)\n", n, nVar,m, nTrm)) if(m > nVar) mf <- mf[seq_len(nVar)] stopifnot(fnames == names(mf), allow.logical0 = TRUE) noVar <- nVar == 0 ##>> this seems wrong; we use 1:nVar for indexing mf[] below .. ##>> if(noVar) nVar <- 1L # (as in ~/R/D/r-devel/R/src/main/model.c) ## Note: "character" variables have been changed to factor in the caller; ## hence: both factor and *logical* should be dealt as factor : is.f <- if(noVar) logical(0) else vapply(mf, function(.) is.factor(.) | is.logical(.), NA) indF <- which(is.f) if(verbose) { cat(" --> indF =\n"); print(indF) } hasInt <- attr(trms, "intercept") == 1 ## the degree of interaction: ## intOrder <- attr(trms, "order") ## if(!hasInt && length(indF)) { ## change the '1' of the first factor into a '2' : if(any(i1 <- factorPattern[indF, ] == 1)) ## replace at the first '1' location: factorPattern[indF,][which.max(i1)] <- 2L else {} ## nothing to do } ## Convert "factors" to "Rowwise- sparseMatrix ("dummy"-matrix) ----------- ## Result: a list of sparse model matrices for the "factor"s : f.matr <- structure(vector("list", length = length(indF)), names = fnames[indF]) i.f <- 0 ## ---- For each variable in the model ------------------- for(i in seq_len(nVar)) { nam <- fnames[i] f <- mf[[i]] if(is.f[i]) { fp <- factorPattern[i,] ## == factorPattern[nam,] contr <- attr(f, "contrasts") f.matr[[(i.f <- i.f + 1)]] <- # a list of 2 lapply(fac2Sparse(f, to = "d", drop.unused.levels=drop.unused.levels, factorPatt12 = 1:2 %in% fp, contrasts.arg = contr), function(s) { if(!is.null(s)) { ## for some contr.*(), have lost rownames; hmm.. if(is.null(rn <- rownames(s))) rn <- seq_len(nrow(s)) rownames(s) <- paste(nam, rn, sep = sep) } s }) } else { ## continuous variable --> "matrix" - for all of them if(any(iA <- (cl <- class(f)) == "AsIs")) # drop "AsIs" class class(f) <- if(length(cl) > 1L) cl[!iA] nr <- if(is.matrix(f)) nrow(f <- t(f)) else (dim(f) <- c(1L, length(f)))[1] if(is.null(rownames(f))) rownames(f) <- if(nr == 1) nam else paste(nam, seq_len(nr), sep=sep) mf[[i]] <- f } } if(verbose) { cat(" ---> f.matr list :\n") str(f.matr, max.level = as.integer(verbose)) fNms <- format(dQuote(Names)) dim.string <- gsub('5', as.character(floor(1+log10(n))), " -- concatenating (r, rj): dim = (%5d,%5d) | (%5d,%5d)\n") } ## FIXME: do all this in C -- getR <- function(N) # using 'nm' if(!is.null(r <- f.matr[[N]])) r[[factorPattern[N, nm]]] else mf[[N]] vNms <- "(Intercept)"[hasInt] counts <- integer(nTrm) r <- if(hasInt) ## column of 1's - as sparse new("dgCMatrix", i = 0:(n-1L), p = c(0L, n), Dim = c(n, 1L), x = rep.int(1, n)) else new("dgCMatrix", Dim = c(n, 0L)) if(transpose) r <- t(r) iTrm <- seq_len(nTrm) for(j in iTrm) { ## j-th term nm <- Names[j] if(verbose) cat(sprintf("term[%2d] %s .. ", j, fNms[j])) nmSplits <- strsplit(nm, ":", fixed=TRUE)[[1]] ## NOTA BENE: This can be very slow when many terms are involved ## FIXME ??? why does it use *much* memory in those cases ?? rj <- .sparse.interaction.N(lapply(nmSplits, getR), do.names = TRUE, forceSparse = TRUE, verbose = verbose) # or just (verbose >= 2) if(verbose) cat(sprintf(dim.string, nrow(r), ncol(r), nrow(rj),ncol(rj))) ## fast version of cbind2() / rbind2(), w/o checks, dimnames, etc r <- if(transpose) rbind.Matrix(r, rj ) else cbind.Matrix(r, t(rj)) ## if(verbose) cat(" [Ok]\n") vNms <- c(vNms, dimnames(rj)[[1]]) counts[j] <- nrow(rj) } rns <- if(row.names) rnames dimnames(r) <- if(transpose) list(vNms, rns) else list(rns, vNms) attr(r, "assign") <- c(if(hasInt) 0L, rep(iTrm, counts)) r } ## model.spmatrix() Matrix/R/image.R0000644000175100001440000001377014561451364013163 0ustar hornikusers## METHODS FOR GENERIC: image ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## NB: currently going via dgTMatrix in all cases, ## which is not so inefficient, as levelplot() ## needs 'i' and 'j' anyway .image.dgT <- function(x, xlim = c(1, di[2L]), ylim = c(di[1L], 1), aspect = "iso", sub = sprintf("Dimensions: %d x %d", di[1L], di[2L]), xlab = "Column", ylab = "Row", cuts = 15, useRaster = FALSE, useAbs = NULL, colorkey = !useAbs, col.regions = NULL, lwd = NULL, border.col = NULL, ...) { ## 'at' can remain missing and be passed to levelplot di <- x@Dim xx <- x@x empty.x <- length(xx) == 0L && length(x) > 0L if(empty.x) { # workaround having "empty" matrix xx <- 0 x@i <- x@j <- 0L } if(missing(useAbs)) ## use abs() when all values are non-neg useAbs <- if(empty.x) FALSE else min(xx, na.rm = TRUE) >= 0 else if(useAbs) xx <- abs(xx) ## rx <- range(xx, finite = TRUE) ## FIXME: make use of 'cuts' now ## and call levelplot() with 'at = ', ## making sure 0 is included and matching ## *exactly* - rather than approximately if(is.null(col.regions)) { l.col <- empty.x || diff(rx <- range(xx, finite = TRUE)) == 0 col.regions <- if(useAbs) { grey(if(l.col) 0.9 else seq(from = 0.7, to = 0, length.out = 100L)) } else if(l.col) "gray90" else { ## no abs(.), rx[1] < 0 typically nn <- 100 n0 <- min(nn, max(0, round((0 - rx[1L])/(rx[2L]-rx[1L]) * nn))) col.regions <- c(colorRampPalette(c("blue3", "gray80"))(n0), colorRampPalette(c("gray75","red3"))(nn - n0)) } } if(!is.null(lwd) && !(is.numeric(lwd) && all(lwd >= 0))) # allow lwd=0 stop("'lwd' must be NULL or non-negative numeric") stopifnot(length(xlim) == 2L, length(ylim) == 2L) ## ylim: the rows count from top to bottom: ylim <- sort(ylim, decreasing = TRUE) if(all(xlim == round(xlim))) xlim <- xlim + c(-0.5, +0.5) if(all(ylim == round(ylim))) ylim <- ylim + c(+0.5, -0.5) # decreasing! panel <- if(useRaster) panel.levelplot.raster else { function(x, y, z, subscripts, at, ..., col.regions) { x <- as.numeric(x[subscripts]) y <- as.numeric(y[subscripts]) ## ## FIXME: use level.colors() here and 'at' from above -- ## ----- look at 'zcol' in panel.levelplot() numcol <- length(at) - 1L num.r <- length(col.regions) col.regions <- if(num.r <= numcol) rep_len(col.regions, numcol) else col.regions[1 + ((1:numcol-1)*(num.r-1)) %/% (numcol-1)] zcol <- rep.int(NA_integer_, length(z)) for(i in seq_along(col.regions)) zcol[!is.na(x) & !is.na(y) & !is.na(z) & at[i] <= z & z < at[i+1L]] <- i zcol <- zcol[subscripts] if(any(subscripts)) { ## the line-width used in grid.rect() inside ## levelplot()'s panel for the *border* of the ## rectangles: levelplot()panel has lwd= 0.01: ## Here: use "smart" default ! if(is.null(lwd)) { wh <- current.viewport()[c("width", "height")] ## wh : current viewport dimension in pixel wh <- (par("cra") / par("cin")) * c(convertWidth(wh$width, "inches", valueOnly = TRUE), convertHeight(wh$height, "inches", valueOnly = TRUE)) pSize <- wh/di ## size of one matrix-entry in pixels pA <- prod(pSize) # the "area" p1 <- min(pSize) lwd <- ## crude for now if(p1 < 2 || pA < 6) 0.01 # effectively 0 else if(p1 >= 4) 1 else if(p1 > 3) 0.5 else 0.2 ## browser() Matrix.message("rectangle size ", paste(round(pSize, 1L), collapse = " x "), " [pixels]; --> lwd :", formatC(lwd)) } else stopifnot(is.numeric(lwd), all(lwd >= 0)) # allow 0 if(is.null(border.col) && lwd < 0.01) # no border border.col <- NA grid.rect(x = x, y = y, width = 1, height = 1, default.units = "native", ## FIXME?: allow 'gp' to be passed via '...' !! gp = gpar(fill = col.regions[zcol], lwd = lwd, col = border.col)) } } } # panel <- if(useRaster) ... levelplot(xx ~ (x@j + 1L) * (x@i + 1L), # no 'data' sub = sub, xlab = xlab, ylab = ylab, xlim = xlim, ylim = ylim, aspect = aspect, colorkey = colorkey, col.regions = col.regions, cuts = cuts, par.settings = list(background = list(col = "transparent")), panel = panel, ...) } setMethod("image", c(x = "dgTMatrix"), .image.dgT) setMethod("image", c(x = "Matrix"), function(x, ...) { if(.M.kind(x) == "z") stop(gettextf("%s(<%s>) is not yet implemented", "image", "zMatrix"), domain = NA) image(.M2kind(.M2gen(.M2T(x)), "d"), ...) }) setMethod("image", c(x = "CHMfactor"), function(x, ...) image(.M2gen(.M2T(expand1(x, "L"))), ...)) rm(.image.dgT) Matrix/R/nnzero.R0000644000175100001440000000637514561451364013417 0ustar hornikusers## METHODS FOR GENERIC: nnzero ## * used to retrieve number of nonzero elements, ## i.e., number of elements excl. both structural and non-structural zeros ## * like MATLAB's nnz() but more sophisticated due to handling of NA ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## na.counted: ## FALSE ... NA is treated as zero and so excluded from count ## TRUE ... NA is treated as nonzero and so included in count ## NA ... NA is indeterminate (could be zero or nonzero) hence count is NA sparseDefault <- function(x) length(x) > 2 * nnzero(x, na.counted = TRUE) .sparseDefault <- function(x) length(x) > 2 * .nnzero(x, na.counted = TRUE) ## For logical, integer, double, and complex vectors .nnzero <- function(x, na.counted = NA, nnzmax = length(x)) .Call(R_nnz, x, na.counted, nnzmax) ## For any class with methods for 'is.na' and '!=' .nnzero.fallback <- function(x, na.counted = NA) sum(if(is.na(na.counted)) x != 0 else if(na.counted) is.na(x) | x != 0 else !is.na(x) & x != 0) .nnzero.dispatching <- function(x, na.counted = NA) switch(typeof(x), logical =, integer =, double =, complex = .nnzero, .nnzero.fallback)(x, na.counted) setMethod("nnzero", c(x = "ANY"), .nnzero.fallback) setMethod("nnzero", c(x = "vector"), .nnzero.dispatching) setMethod("nnzero", c(x = "denseMatrix"), function(x, na.counted = NA) { d <- x@Dim if(any(d == 0L)) return(0L) if(.M.kind(x) == "n") na.counted <- TRUE if((shape <- .M.shape(x)) != "g") x <- .M2packed(x) N <- .nnzero(x@x, na.counted) switch(shape, "g" = N, "s" = N + N - .nnzero(diag(x, names = FALSE), na.counted), "t" = if(x@diag == "N") N else N + d[1L] - .nnzero(x@x[indDiag(d[1L], upper = x@uplo == "U", packed = TRUE)], na.counted)) }) setMethod("nnzero", c(x = "sparseMatrix"), function(x, na.counted = NA) { d <- x@Dim if(any(d == 0L)) return(0L) N <- switch(.M.repr(x), "C" = x@p[d[2L]+1L], "R" = x@p[d[1L]+1L], "T" = length((x <- aggregateT(x))@i)) if(.M.kind(x) != "n") N <- .nnzero(x@x, na.counted, N) switch(.M.shape(x), "g" = N, "s" = N + N - .nnzero(diag(x, names = FALSE), na.counted), "t" = if(x@diag == "N") N else N + d[1L]) }) setMethod("nnzero", c(x = "diagonalMatrix"), function(x, na.counted = NA) { if(x@diag != "N") x@Dim[1L] else { y <- x@x if(.M.kind(x) == "n" && anyNA(y)) y <- y | is.na(y) .nnzero(y, na.counted) } }) setMethod("nnzero", c(x = "indMatrix"), function(x, na.counted = NA) length(x@perm)) setMethod("nnzero", c(x = "CHMfactor"), function(x, na.counted = NA) nnzero(as(x, "CsparseMatrix"), na.counted)) rm(.nnzero.dispatching) Matrix/R/index.R0000644000175100001440000001776714575137654013232 0ustar hornikusers## METHODS FOR CLASS: indMatrix ## index matrices, i.e., matrices with standard unit vectors ## for all rows _or_ all columns ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .perm2ind <- function(perm, n, margin = 1L, check.p = 0L) { if(mode(perm) != "numeric") stop(gettextf("'%s' is not of type \"%s\" or \"%s\"", "perm", "integer", "double"), domain = NA) else if((m <- length(perm)) == 0L) perm <- integer(0L) else if(anyNA(r <- range(perm))) stop(gettextf("'%s' contains NA", "perm"), domain = NA) else if(r[1L] < 1L) stop(gettextf("'%s' has elements less than %d", "perm", 1L), domain = NA) else if(m > .Machine$integer.max || (is.double(perm) && trunc(r[2L]) > .Machine$integer.max)) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) else { perm <- as.integer(perm); r <- as.integer(r) } if(m.n <- missing(n)) n <- if(m == 0L) 0L else r[2L] else if(mode(n) != "numeric" || length(n) != 1L || is.na(n) || n < 0L) stop(gettextf("'%s' is not a non-negative number", "n"), domain = NA) else if(is.double(n) && trunc(n) > .Machine$integer.max) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) else if(r[2L] > as.integer(n)) stop(gettextf("'%s' has elements exceeding '%s'", "perm", "n"), domain = NA) else n <- as.integer(n) if(mode(margin) != "numeric" || length(margin) != 1L || is.na(margin) || (margin != 1L && margin != 2L)) stop(gettextf("'%s' is not %d or %d", "margin", 1L, 2L), domain = NA) give.p <- check.p >= 1L && m == n && (m == 0L || (all(r == c(1L, m)) && !anyDuplicated.default(perm))) if(check.p >= 2L && !give.p) stop(gettextf("'%s' is not a permutation of seq_len(%s)", "perm", if(m.n) "max(perm, 0)" else "n"), domain = NA) J <- new(if(give.p) "pMatrix" else "indMatrix") nms <- names(perm) if(margin == 1L) { J@Dim <- c(m, n) J@Dimnames = list(nms, if(give.p) nms) } else { J@Dim <- c(n, m) J@Dimnames = list(if(give.p) nms, nms) J@margin <- 2L } J@perm <- perm J } setAs("numeric", "indMatrix", function(from) .perm2ind(from)) ## FIXME: deprecate this method and export more general function .perm2ind setAs("list", "indMatrix", function(from) do.call(.perm2ind, unname(from))) setAs("nsparseMatrix", "indMatrix", function(from) { from <- .M2gen(from) J <- new("indMatrix") J@Dim <- from@Dim J@Dimnames <- from@Dimnames from. <- .M2R(from) p <- from.@p m <- length(p) - 1L if(all(p == 0:m)) { J@perm <- from.@j + 1L return(J) } from. <- .M2C(from) p <- from.@p n <- length(p) - 1L if(all(p == 0:n)) { J@perm <- from.@i + 1L J@margin <- 2L return(J) } stop("matrix must have exactly one entry in each row or column") }) setMethod("band", c(x = "indMatrix"), function(x, k1, k2, ...) band(.M2kind(x, "n"), k1, k2, ...)) setMethod("triu", c(x = "indMatrix"), function(x, k = 0L, ...) triu(.M2kind(x, "n"), k, ...)) setMethod("tril", c(x = "indMatrix"), function(x, k = 0L, ...) tril(.M2kind(x, "n"), k, ...)) setMethod("diag", c(x = "indMatrix"), function(x = 1, nrow, ncol, names = TRUE) { if((m <- min(x@Dim)) == 0L) return(logical(0L)) i <- seq_len(m) r <- x@perm[i] == i if(names && !any(vapply(dn <- x@Dimnames, is.null, NA)) && identical(nms <- dn[[1L]][i], dn[[2L]][i])) names(r) <- nms r }) setMethod("diag<-", c(x = "indMatrix"), function(x, value) `diag<-`(.M2kind(x, "n"), value)) setMethod("t", c(x = "indMatrix"), function(x) { r <- new("indMatrix") r@Dim <- x@Dim[2:1] r@Dimnames = x@Dimnames[2:1] r@perm <- x@perm if(x@margin == 1L) r@margin <- 2L r }) setMethod("forceSymmetric", c(x = "indMatrix", uplo = "missing"), function(x, uplo) forceSymmetric(.M2kind(x, "n"))) setMethod("forceSymmetric", c(x = "indMatrix", uplo = "character"), function(x, uplo) forceSymmetric(.M2kind(x, "n"), uplo)) setMethod("symmpart", c(x = "indMatrix"), function(x) symmpart(.M2kind(x, "d"))) setMethod("skewpart", c(x = "indMatrix"), function(x) skewpart(.M2kind(x, "d"))) setMethod("isDiagonal", c(object = "indMatrix"), function(object) { d <- object@Dim if((n <- d[2L]) != d[1L]) return(FALSE) all(object@perm == seq_len(n)) }) setMethod("isTriangular", c(object = "indMatrix"), function(object, upper = NA, ...) { d <- object@Dim if((n <- d[2L]) != d[1L]) return(FALSE) if(object@margin == 1L) { i <- seq_len(n) j <- object@perm } else { i <- object@perm j <- seq_len(n) } if(is.na(upper)) { if(all(j >= i)) return(`attr<-`(TRUE, "kind", "U")) if(all(i <= j)) return(`attr<-`(TRUE, "kind", "L")) FALSE } else if(upper) { all(j >= i) } else { all(i <= j) } }) setMethod("isSymmetric", c(object = "indMatrix"), function(object, checkDN = TRUE, ...) { d <- object@Dim if((n <- d[2L]) != d[1L]) return(FALSE) if(checkDN) { ca <- function(check.attributes = TRUE, ...) check.attributes if(ca(...) && !isSymmetricDN(object@Dimnames)) return(FALSE) } perm <- object@perm all(perm[perm] == seq_len(n)) }) ## METHODS FOR CLASS: pMatrix ## permutation matrices, i.e., matrices with standard unit vectors ## for all rows _and_ all columns ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## MJ: could export without dot .changeMargin <- function(x) { x@margin <- if(x@margin == 1L) 2L else 1L x@perm <- invertPerm(x@perm) x } setAs("numeric", "pMatrix", function(from) .perm2ind(from, check.p = 2L)) setAs("nsparseMatrix", "pMatrix", function(from) { d <- from@Dim if((n <- d[1L]) != d[2L]) stop(gettextf("attempt to coerce non-square matrix to %s", "pMatrix"), domain = NA) from <- .M2gen(from) J <- new("pMatrix") J@Dim <- d J@Dimnames <- from@Dimnames from. <- .M2R(from) p <- from.@p m <- length(p) - 1L if(all(p == 0:m) && !anyDuplicated.default(j <- from.@j)) { J@perm <- j + 1L return(J) } from. <- .M2C(from) p <- from.@p n <- length(p) - 1L if(all(p == 0:n) && !anyDuplicated.default(i <- from.@i)) { J@perm <- i + 1L J@margin <- 2L return(J) } stop("matrix must have exactly one entry in each row and column") }) setAs("indMatrix", "pMatrix", function(from) new("pMatrix", from)) setMethod("t", c(x = "pMatrix"), function(x) { r <- new("pMatrix") r@Dim <- x@Dim r@Dimnames = x@Dimnames[2:1] r@perm <- x@perm if(x@margin == 1L) r@margin <- 2L r }) Matrix/R/coerce-SparseM.R0000644000175100001440000000642114565441013014676 0ustar hornikusers## METHODS ENHANCING PACKAGE: sparseM ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## ~~~~ COERCIONS FROM SparseM TO Matrix ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## Natural pairs setAs("matrix.csc", "dgCMatrix", function(from) new("dgCMatrix", Dim = from@dimension, p = from@ia - 1L, i = from@ja - 1L, x = from@ra)) setAs("matrix.csr", "dgRMatrix", function(from) new("dgRMatrix", Dim = from@dimension, p = from@ia - 1L, j = from@ja - 1L, x = from@ra)) setAs("matrix.coo", "dgTMatrix", function(from) new("dgTMatrix", Dim = from@dimension, i = from@ia - 1L, j = from@ja - 1L, x = from@ra)) ## Remaining matrix.c(sc|sr|oo) to dgCMatrix setAs("matrix.csr", "dgCMatrix", function(from) .M2C(as(from, "dgRMatrix"))) setAs("matrix.coo", "dgCMatrix", function(from) .M2C(as(from, "dgTMatrix"))) ## Each matrix.c(sc|sr|oo) to each [CRT]sparseMatrix setAs("matrix.csc", "CsparseMatrix", function(from) as(from, "dgCMatrix")) setAs("matrix.csc", "RsparseMatrix", function(from) .M2R(as(from, "dgCMatrix"))) setAs("matrix.csc", "TsparseMatrix", function(from) .M2T(as(from, "dgCMatrix"))) setAs("matrix.csr", "CsparseMatrix", function(from) .M2C(as(from, "dgRMatrix"))) setAs("matrix.csr", "RsparseMatrix", function(from) as(from, "dgRMatrix")) setAs("matrix.csr", "TsparseMatrix", function(from) .M2T(as(from, "dgRMatrix"))) setAs("matrix.coo", "CsparseMatrix", function(from) .M2C(as(from, "dgTMatrix"))) setAs("matrix.coo", "RsparseMatrix", function(from) .M2R(as(from, "dgTMatrix"))) setAs("matrix.coo", "TsparseMatrix", function(from) as(from, "dgTMatrix")) ## Each matrix.c(sc|sr|oo) to sparseMatrix, Matrix ("easy") ## NB: favouring column format over row format setAs("matrix.csc", "sparseMatrix", function(from) as(from, "CsparseMatrix")) setAs("matrix.csr", "sparseMatrix", function(from) as(from, "CsparseMatrix")) setAs("matrix.coo", "sparseMatrix", function(from) as(from, "TsparseMatrix")) setAs("matrix.csc", "Matrix", function(from) as(from, "CsparseMatrix")) setAs("matrix.csr", "Matrix", function(from) as(from, "CsparseMatrix")) setAs("matrix.coo", "Matrix", function(from) as(from, "TsparseMatrix")) ## ~~~~ COERCIONS FROM Matrix TO SparseM ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## Natural pairs setAs("dgCMatrix", "matrix.csc", function(from) new("matrix.csc", dimension = from@Dim, ia = from@p + 1L, ja = from@i + 1L, ra = from@x)) setAs("dgRMatrix", "matrix.csr", function(from) new("matrix.csr", dimension = from@Dim, ia = from@p + 1L, ja = from@j + 1L, ra = from@x)) setAs("dgTMatrix", "matrix.coo", function(from) new("matrix.coo", dimension = from@Dim, ia = from@i + 1L, ja = from@j + 1L, ra = from@x)) ## Everything else setAs("Matrix", "matrix.csc", function(from) as(as(as(as(from, "dMatrix"), "generalMatrix"), "CsparseMatrix"), "matrix.csc")) setAs("Matrix", "matrix.csr", function(from) as(as(as(as(from, "dMatrix"), "generalMatrix"), "RsparseMatrix"), "matrix.csr")) setAs("Matrix", "matrix.coo", function(from) as(as(as(as(from, "dMatrix"), "generalMatrix"), "TsparseMatrix"), "matrix.coo")) Matrix/R/objects.R0000644000175100001440000000607614574054152013531 0ustar hornikusers## if strict=FALSE then gives "...Matrix" or ".sparseVector" or "" ## if strict= TRUE then may also give one of these: ## "dpoMatrix", "dppMatrix", "corMatrix", "copMatrix", "pMatrix" .M.nonvirtual <- function(x, strict = FALSE) .Call(R_Matrix_nonvirtual, x, strict) ## "[nlidz]" for Matrix, sparseVector, logical, integer, double, complex 'x'; ## otherwise "" .M.kind <- function(x) .Call(R_Matrix_kind , x) ## "[gshtdi]" for Matrix, sparseVector 'x'; otherwise "" .M.shape <- function(x) .Call(R_Matrix_shape, x) ## "[upCRTdi]" for Matrix 'x'; otherwise "" .M.repr <- function(x) .Call(R_Matrix_repr , x) .isMatrix <- function(x) nzchar(cl <- .M.nonvirtual(x)) && substr(cl, 4L, 4L) == "M" .isVector <- function(x) nzchar(cl <- .M.nonvirtual(x)) && substr(cl, 4L, 4L) != "M" .isUnpacked <- function(x) .M.repr(x) == "u" .isPacked <- function(x) .M.repr(x) == "p" .isC <- function(x) .M.repr(x) == "C" .isR <- function(x) .M.repr(x) == "R" .isT <- function(x) .M.repr(x) == "T" .isDiagonal <- function(x) .M.repr(x) == "d" .isInd <- function(x) .M.repr(x) == "i" .isDense <- function(x) any(.M.repr(x) == c("u", "p")) .isSparse <- function(x) any(.M.repr(x) == c("C", "R", "T", "d", "i")) .isCRT <- function(x) any(.M.repr(x) == c("C", "R", "T")) ## for .type.kind[.M.kind(x)]: .type.kind <- c("n" = "logical", "l" = "logical", "i" = "integer", "d" = "double", "z" = "complex") ## for .kind.type[ typeof(x)]: .kind.type <- c("logical" = "l", "integer" = "i", "double" = "d", "complex" = "z") extends1of <- function(class, classes, ...) { if(is.character(class)) class <- getClassDef(class[[1L]]) for(cl in classes) if(extends(class, cl, ...)) return(TRUE) FALSE } MatrixClass <- function(cl, cld = getClassDef(cl), ...Matrix = TRUE, dropVirtual = TRUE, ...) { if(!is.character(cl) || length(cl) != 1L || is.na(cl)) stop("'cl' is not a character string") if(is.null(pkg <- cld@package) && is.null(pkg <- attr(cl, "package"))) return(character(0L)) if(identical(pkg, "Matrix") && (!...Matrix || grepl("^[nlidz](ge|sy|sp|tr|tp|di|[gst][CRT])Matrix$", cl))) return(cl) r <- .selectSuperClasses(cld@contains, dropVirtual = dropVirtual, namesOnly = TRUE, ...) if(length(r) == 0L) return(character(0L)) while({ r1 <- Recall(r[1L], ...Matrix = ...Matrix, dropVirtual = dropVirtual, ...) length(r1) == 0L && length(r) > 1L }) r <- r[-1L] r1 } class2 <- function(cl, kind = "l") sub("^[nlidz]", kind, MatrixClass(cl)) copyClass <- function(from, to.class, sNames = intersect(slotNames(to.class), slotNames(from)), check = TRUE) { to <- new(to.class) if(check) for(nm in sNames) slot(to, nm) <- slot(from, nm) else for(nm in sNames) attr(to, nm) <- attr(from, nm) to } Matrix/R/zzz.R0000644000175100001440000005571414561451364012742 0ustar hornikusers## ~~~~ VERSION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Matrix.Version <- function() { n <- .Call(R_Matrix_version) v <- .mapply(function(n, p, b, class) { r <- integer(p) while (p > 0L) { r[p] <- tmp <- n %% b n <- (n - tmp) %/% b p <- p - 1L } v <- list(r) class(v) <- c(class, "numeric_version") v }, list(n = n, p = c(3L, 1L, 3L), b = c(256L, 10L, 256L), class = list("package_version", NULL, NULL)), NULL) names(v) <- names(n) v } ## ~~~~ PACKAGE ENVIRONMENTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## Recording default values of Matrix.* options .MatrixEnv <- new.env(parent = emptyenv(), hash = FALSE) ## Storing settings from 'cholmod_common' .CholmodCommonEnv <- new.env(parent = emptyenv()) ## ~~~~ NAMESPACE HOOKS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .onLoad <- function(libname, pkgname) { ## For backwards compatibility with earlier versions of R, ## at least until x.y.z if we have Depends: R (>= x.y.z) Mns <- parent.env(environment()) if(!environmentIsLocked(Mns)) { ## Namespace not locked yet, but being defensive here Rv <- getRversion() if(Rv < "4.4.0") { assign("%||%", envir = Mns, inherits = FALSE, function(x, y) if(is.null(x)) y else x) if(Rv < "4.1.3") { assign("...names", envir = Mns, inherits = FALSE, function() eval(quote(names(list(...))), sys.frame(-1L))) if(Rv < "4.0.0") { assign("deparse1", envir = Mns, inherits = FALSE, function(expr, collapse = " ", width.cutoff = 500L, ...) paste(deparse(expr, width.cutoff, ...), collapse = collapse)) assign("sequence.default", envir = Mns, inherits = FALSE, function(nvec, from = 1L, by = 1L, ...) { if(length(nvec) == 0L) return(integer(0L)) else if(length(from) == 0L || length(by) == 0L) stop(gettextf("'%s' has length 0 but '%s' does not", if(length(from) == 0L) "from" else "by", "nvec"), domain = NA) unlist(.mapply(seq.int, list(from = as.integer(from), by = as.integer(by), length.out = as.integer(nvec)), NULL), recursive = FALSE, use.names = FALSE) }) assign("tryInvokeRestart", envir = Mns, inherits = FALSE, function(r, ...) tryCatch(invokeRestart(r, ...), error = function(e) invisible(NULL))) } # Rv < "4.0.0" } # Rv < "4.1.3" } # Rv < "4.4.0" } ## verbose: ## logical/integer (but often supplied as double), ## deciding _if_ conditions are signaled v <- as.integer(Sys.getenv("R_MATRIX_VERBOSE", "0")) assign("verbose", if(is.na(v)) 0L else v, envir = .MatrixEnv) ## warn: ## logical/integer (but often supplied as double), ## deciding _what_ conditions are signaled ## (0=message, 1=warning, 2=error) w <- as.integer(Sys.getenv("R_MATRIX_WARN", "0")) assign("warn", if(is.na(w)) 0L else w, envir = .MatrixEnv) ## ambiguityNotes: ## show S4 method dispatch ambiguity notes if TRUE aN <- as.logical(Sys.getenv("R_MATRIX_AMBIGUITY_NOTES", "false")) aN <- (!is.na(aN) && aN) || !is.null(getOption("ambiguousMethodSelection")) assign("ambiguityNotes", aN, envir = .MatrixEnv) if(!aN) options(ambiguousMethodSelection = # ?methods::testInheritedMethods `environment<-`(function(cond) NULL, emptyenv())) ## warnDeprecatedCoerce: ## <=0 ... no conditions signaled ## 1 ... persistent warning ## >=2 ... persistent error ## NA ... one-time message { d(g.|.C)Matrix } or warning { others } wDC <- as.integer(Sys.getenv("R_MATRIX_WARN_DEPRECATED_COERCE", NA)) assign("warnDeprecatedCoerce", wDC, envir = .MatrixEnv) ## warnSqrtDefault: ## <=0 ... no conditions signaled ## 1 ... persistent warning ## >=2 ... persistent error ## NA ... one-time warning wSD <- as.integer(Sys.getenv("R_MATRIX_WARN_SQRT_DEFAULT", NA)) assign("warnSqrtDefault", wSD, envir = .MatrixEnv) .Call(R_cholmod_common_envini, .CholmodCommonEnv) NULL } .onUnload <- function(libpath) { library.dynam.unload("Matrix", libpath) if(!.MatrixEnv[["ambiguityNotes"]]) options(ambiguousMethodSelection = NULL) NULL } ## ~~~~ DEPRECATED ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ..2dge <- function(from) { .Deprecated(new = ".M2gen(*, \"d\") or .m2dense(*, \"dge\")", package = "Matrix") if(isS4(from)) .M2gen(from, "d") else .m2dense(from, "dge") } .C2nC <- function(from, isTri) { .Deprecated(new = ".M2kind", package = "Matrix") .M2kind(from, "n") } .T2Cmat <- function(from, isTri) { .Deprecated(new = ".M2C", package = "Matrix") .M2C(from) } .asmatrix <- function(x) { .Deprecated(new = "as(., \"matrix\")", package = "Matrix") as(x, "matrix") } .dense2sy <- function(from, ...) { .Deprecated(new = ".M2sym", package = "Matrix") .M2sym(from, ...) } .diag2mat <- function(from) { .Deprecated(new = ".M2m", package = "Matrix") .M2m(from) } .diag2sT <- function(from, uplo = "U", kind = ".", drop0 = TRUE) { .Deprecated(new = ".diag2sparse", package = "Matrix") r <- .diag2sparse(from, kind, "s", "T", uplo) if(drop0) r <- .drop0(r) r } .diag2tT <- function(from, uplo = "U", kind = ".", drop0 = TRUE) { .Deprecated(new = ".diag2sparse", package = "Matrix") to <- .diag2sparse(from, kind, "t", "T", uplo) if(drop0) to <- .drop0(to) to } .dsy2dsp <- function(from) { .Deprecated(new = ".M2packed", package = "Matrix") .M2packed(from) } .dsy2mat <- function(from, keep.dimnames = TRUE) { .Deprecated(new = ".M2m", package = "Matrix") to <- .M2m(from) if(!keep.dimnames) dimnames(to) <- NULL to } .dxC2mat <- function(from, chkUdiag) { .Deprecated(new = ".M2m", package = "Matrix") .M2m(from) } .m2dgC <- function(from) { .Deprecated(new = ".m2sparse", package = "Matrix") .m2sparse(from, "dgC") } .m2lgC <- function(from) { .Deprecated(new = ".m2sparse", package = "Matrix") .m2sparse(from, "lgC") } .m2ngC <- function(from) { .Deprecated(new = ".m2sparse", package = "Matrix") if(anyNA(from)) stop(gettextf("attempt to coerce matrix with NA to %s", "ngCMatrix"), domain = NA) .m2sparse(from, "ngC") } .m2ngCn <- function(from, na.is.not.0 = FALSE) { .Deprecated(new = ".m2sparse", package = "Matrix") if(!na.is.not.0 && anyNA(from)) stop(gettextf("attempt to coerce matrix with NA to %s", "ngCMatrix"), domain = NA) .m2sparse(from, "ngC") } .m2ngTn <- function(from, na.is.not.0 = FALSE) { .Deprecated(new = ".m2sparse", package = "Matrix") if(!na.is.not.0 && anyNA(from)) stop(gettextf("attempt to coerce matrix with NA to %s", "ngTMatrix"), domain = NA) .m2sparse(from, "ngT") } .n2dgT <- function(from) { .Deprecated(new = ".M2kind", package = "Matrix") .M2kind(from, "d") } .nC2d <- function(from) { .Deprecated(new = ".M2kind", package = "Matrix") .M2kind(from, "d") } .nC2l <- function(from) { .Deprecated(new = ".M2kind", package = "Matrix") .M2kind(from, "l") } .dense2m <- .sparse2m <- function(from) { if(FALSE) { .Deprecated(new = ".M2m", package = "Matrix") } .M2m(from) } .dense2v <- .sparse2v <- function(from) { if(FALSE) { .Deprecated(new = ".M2v", package = "Matrix") } .M2v(from) } .dense2kind <- function(from, kind) { if(FALSE) { .Deprecated(new = ".M2kind", package = "Matrix") } .M2kind(from, kind) } .sparse2kind <- function(from, kind, drop0 = FALSE) { if(FALSE) { .Deprecated(new = ".M2kind", package = "Matrix") } .M2kind(if(drop0) .drop0(from) else from, kind) } .dense2g <- .sparse2g <- function(from, kind = ".") { if(FALSE) { .Deprecated(new = ".M2gen", package = "Matrix") } .M2gen(from, kind) } .CR2RC <- function(from) { if(.M.repr(from) != "C") { if(FALSE) { .Deprecated(new = ".M2C", package = "Matrix") } .M2C(from) } else { if(FALSE) { .Deprecated(new = ".M2R", package = "Matrix") } .M2R(from) } } .CR2T <- function(from) { if(FALSE) { .Deprecated(new = ".M2T", package = "Matrix") } .M2T(from) } .T2CR <- function(from, Csparse = TRUE) { if(Csparse) { if(FALSE) { .Deprecated(new = ".M2C", package = "Matrix") } .M2C(from) } else { if(FALSE) { .Deprecated(new = ".M2R", package = "Matrix") } .M2R(from) } } .tCR2RC <- function(from) { if(FALSE) { .Deprecated(new = ".tCRT", package = "Matrix") } .tCRT(from) } uniqTsparse <- function(x, class.x = class(x)) { if(FALSE) { .Deprecated(new = "asUniqueT", package = "Matrix") } asUniqueT(x, isT = extends(class.x, "TsparseMatrix")) } .SuiteSparse_version <- function() { if(FALSE) { .Deprecated(new = "Matrix.Version", package = "Matrix") } Matrix.Version()[["suitesparse"]] } ## Utility for Matrix.DeprecatedCoerce(); see below .as.via.virtual <- function(Class1, Class2, from = quote(from)) { if(!isClassDef(Class1)) Class1 <- getClassDef(Class1) if(!isClassDef(Class2)) Class2 <- getClassDef(Class2) if(!grepl("^[dln](di|ge|tr|sy|tp|sp|[gts][CRT])Matrix$", Class2@className)) stop("invalid 'Class2'") contains1 <- names(Class1@contains) contains2 <- names(Class2@contains) virtual <- list(c("dMatrix", "lMatrix", "nMatrix"), c("generalMatrix", "triangularMatrix", "symmetricMatrix"), c("CsparseMatrix", "RsparseMatrix", "TsparseMatrix", "diagonalMatrix", "unpackedMatrix", "packedMatrix")) to <- from for(v in virtual) { if(any(m <- match(v, contains2, 0L) > 0L)) { v1 <- v[m][1L] if(match(v1, contains1, 0L) == 0L) to <- call("as", to, v1) } } to } Matrix.DeprecatedCoerce <- function(Class1, Class2) { if(!isClassDef(Class1)) Class1 <- getClassDef(Class1) if(!isClassDef(Class2)) Class2 <- getClassDef(Class2) w <- getOption("Matrix.warnDeprecatedCoerce", .MatrixEnv[["warnDeprecatedCoerce"]]) if(is.atomic(w) && length(w) == 1L && ((w.na <- is.na(w <- as.integer(w))) || w > 0L)) { cln1 <- Class1@className cln2 <- Class2@className old <- sprintf("as(<%s>, \"%s\")", cln1, cln2) new <- deparse1(.as.via.virtual(Class1, Class2, quote(.))) if(w.na) on.exit(options(Matrix.warnDeprecatedCoerce = 0L)) if(w.na && grepl("d(g.|.C)Matrix", cln2)) { cond <- tryCatch(.Deprecated(old = old, new = new, package = "Matrix"), deprecatedWarning = identity) message(conditionMessage(cond), domain = NA) } else { if(!w.na && w > 1L) { oop <- options(warn = 2L) on.exit(options(oop)) } .Deprecated(old = old, new = new, package = "Matrix") } } invisible(NULL) } ## "Granular" coercions available in Matrix 1.4-1, ## all candidates for deprecation in Matrix 1.5-0: if(FALSE) { stopifnot(packageVersion("Matrix") == "1.4.1") dput(lapply(grep("to=\"[dln](di|ge|tr|sy|tp|sp|[gts][CRT])Matrix\"", capture.output(showMethods("coerce")), value = TRUE), function(s) unname(eval(str2lang(paste0("c(", s, ")")))))) } ## Note: Allow as(*, "dpoMatrix") to check for pos.(semi)definite-ness .from.to <- list(c("ddenseMatrix", "dgeMatrix"), c("ddiMatrix", "dgCMatrix"), c("ddiMatrix", "dgeMatrix"), c("ddiMatrix", "dtCMatrix"), c("dgCMatrix", "dgeMatrix"), c("dgCMatrix", "dgTMatrix"), c("dgCMatrix", "dsCMatrix"), c("dgCMatrix", "dtCMatrix"), c("dgCMatrix", "lgCMatrix"), c("dgCMatrix", "ngCMatrix"), c("dgeMatrix", "dgCMatrix"), c("dgeMatrix", "dgTMatrix"), c("dgeMatrix", "dspMatrix"), c("dgeMatrix", "dsTMatrix"), c("dgeMatrix", "dsyMatrix"), c("dgeMatrix", "dtrMatrix"), c("dgeMatrix", "lgeMatrix"), c("dgTMatrix", "dgCMatrix"), c("dgTMatrix", "dgeMatrix"), c("dgTMatrix", "dsTMatrix"), c("dgTMatrix", "dtCMatrix"), c("dgTMatrix", "dtTMatrix"), c("dsCMatrix", "dgCMatrix"), c("dsCMatrix", "dgeMatrix"), c("dsCMatrix", "dgTMatrix"), c("dsCMatrix", "dsRMatrix"), c("dsCMatrix", "dsTMatrix"), c("dsCMatrix", "dsyMatrix"), c("dsCMatrix", "lsCMatrix"), c("dsCMatrix", "nsCMatrix"), c("dspMatrix", "dsyMatrix"), c("dspMatrix", "lspMatrix"), c("dsTMatrix", "dgeMatrix"), c("dsTMatrix", "dgTMatrix"), c("dsTMatrix", "dsCMatrix"), c("dsTMatrix", "dsyMatrix"), c("dsTMatrix", "lsTMatrix"), c("dsyMatrix", "dsCMatrix"), c("dsyMatrix", "dspMatrix"), c("dsyMatrix", "dsTMatrix"), c("dsyMatrix", "lsyMatrix"), c("dtCMatrix", "dgCMatrix"), c("dtCMatrix", "dgeMatrix"), c("dtCMatrix", "dgTMatrix"), c("dtCMatrix", "dsCMatrix"), c("dtCMatrix", "dtrMatrix"), c("dtCMatrix", "dtTMatrix"), c("dtCMatrix", "ltCMatrix"), c("dtCMatrix", "ntCMatrix"), c("dtpMatrix", "dtrMatrix"), c("dtpMatrix", "dtTMatrix"), c("dtpMatrix", "ltpMatrix"), c("dtrMatrix", "dtpMatrix"), c("dtrMatrix", "ltrMatrix"), c("dtTMatrix", "dgeMatrix"), c("dtTMatrix", "dgTMatrix"), c("dtTMatrix", "dtCMatrix"), c("dtTMatrix", "dtrMatrix"), c("indMatrix", "ngeMatrix"), c("indMatrix", "ngTMatrix"), c("lgCMatrix", "dgCMatrix"), c("lgCMatrix", "lgeMatrix"), c("lgCMatrix", "lgTMatrix"), c("lgCMatrix", "ltCMatrix"), c("lgeMatrix", "dgeMatrix"), c("lgeMatrix", "lgCMatrix"), c("lgeMatrix", "lgTMatrix"), c("lgeMatrix", "lspMatrix"), c("lgeMatrix", "lsyMatrix"), c("lgeMatrix", "ltpMatrix"), c("lgeMatrix", "ltrMatrix"), c("lgTMatrix", "dgTMatrix"), c("lgTMatrix", "lgCMatrix"), c("lgTMatrix", "lgeMatrix"), c("lgTMatrix", "lsCMatrix"), c("lgTMatrix", "ltTMatrix"), c("lMatrix", "dgCMatrix"), c("lsCMatrix", "dsCMatrix"), c("lsCMatrix", "lgCMatrix"), c("lsCMatrix", "lgTMatrix"), c("lsCMatrix", "lsTMatrix"), c("lspMatrix", "dspMatrix"), c("lspMatrix", "lgeMatrix"), c("lspMatrix", "lsyMatrix"), c("lsTMatrix", "lgCMatrix"), c("lsTMatrix", "lgTMatrix"), c("lsTMatrix", "lsCMatrix"), c("lsTMatrix", "lsyMatrix"), c("lsyMatrix", "dsyMatrix"), c("lsyMatrix", "lgeMatrix"), c("lsyMatrix", "lspMatrix"), c("ltCMatrix", "lgCMatrix"), c("ltCMatrix", "ltTMatrix"), c("ltpMatrix", "dtpMatrix"), c("ltpMatrix", "lgeMatrix"), c("ltpMatrix", "ltrMatrix"), c("ltrMatrix", "dtrMatrix"), c("ltrMatrix", "lgeMatrix"), c("ltrMatrix", "ltpMatrix"), c("ltTMatrix", "dtTMatrix"), c("ltTMatrix", "lgCMatrix"), c("ltTMatrix", "lgTMatrix"), c("ltTMatrix", "ltCMatrix"), c("ltTMatrix", "ltrMatrix"), ## c("matrix.coo", "dgCMatrix"), c("matrix.coo", "dgTMatrix"), ## c("matrix.csc", "dgCMatrix"), c("matrix.csr", "dgCMatrix"), ## c("matrix.csr", "dgRMatrix"), ## c("matrix", "dgCMatrix"), c("matrix", "dgeMatrix"), c("matrix", "dgRMatrix"), c("matrix", "dgTMatrix"), c("matrix", "dsCMatrix"), c("matrix", "dspMatrix"), c("matrix", "dsTMatrix"), c("matrix", "dsyMatrix"), c("matrix", "dtCMatrix"), c("matrix", "dtpMatrix"), c("matrix", "dtrMatrix"), c("matrix", "dtTMatrix"), c("matrix", "lgCMatrix"), c("matrix", "lgeMatrix"), c("matrix", "lgTMatrix"), c("matrix", "lsCMatrix"), c("matrix", "lspMatrix"), c("matrix", "lsyMatrix"), c("matrix", "ltCMatrix"), c("matrix", "ltpMatrix"), c("matrix", "ltrMatrix"), c("matrix", "ltTMatrix"), c("matrix", "ngCMatrix"), c("matrix", "ngeMatrix"), c("matrix", "ngTMatrix"), c("matrix", "nspMatrix"), c("matrix", "nsyMatrix"), c("matrix", "ntCMatrix"), c("matrix", "ntpMatrix"), c("matrix", "ntrMatrix"), c("matrix", "ntTMatrix"), c("ngCMatrix", "dgCMatrix"), c("ngCMatrix", "lgCMatrix"), c("ngCMatrix", "ntCMatrix"), c("ngeMatrix", "dgeMatrix"), c("ngeMatrix", "lgeMatrix"), c("ngeMatrix", "ngCMatrix"), c("ngeMatrix", "ngTMatrix"), c("ngeMatrix", "nspMatrix"), c("ngeMatrix", "nsyMatrix"), c("ngeMatrix", "ntpMatrix"), c("ngeMatrix", "ntrMatrix"), c("ngTMatrix", "dgTMatrix"), c("ngTMatrix", "lgeMatrix"), c("ngTMatrix", "lgTMatrix"), c("ngTMatrix", "ngCMatrix"), c("ngTMatrix", "ngeMatrix"), c("ngTMatrix", "ntTMatrix"), c("nsCMatrix", "dsCMatrix"), c("nsCMatrix", "lsCMatrix"), c("nsCMatrix", "ngCMatrix"), c("nsCMatrix", "nsTMatrix"), c("nspMatrix", "dspMatrix"), c("nspMatrix", "lspMatrix"), c("nspMatrix", "ngeMatrix"), c("nspMatrix", "nsyMatrix"), c("nsTMatrix", "dsTMatrix"), c("nsTMatrix", "ngCMatrix"), c("nsTMatrix", "ngTMatrix"), c("nsTMatrix", "nsCMatrix"), c("nsTMatrix", "nsyMatrix"), c("nsyMatrix", "dsyMatrix"), c("nsyMatrix", "lsyMatrix"), c("nsyMatrix", "ngeMatrix"), c("nsyMatrix", "nspMatrix"), c("ntCMatrix", "dtCMatrix"), c("ntCMatrix", "ltCMatrix"), c("ntCMatrix", "ngCMatrix"), c("ntpMatrix", "dtpMatrix"), c("ntpMatrix", "ltpMatrix"), c("ntpMatrix", "ngeMatrix"), c("ntpMatrix", "ntrMatrix"), c("ntrMatrix", "dtrMatrix"), c("ntrMatrix", "ltrMatrix"), c("ntrMatrix", "ngeMatrix"), c("ntrMatrix", "ntpMatrix"), c("ntTMatrix", "dtTMatrix"), c("ntTMatrix", "ngCMatrix"), c("ntTMatrix", "ngTMatrix"), c("ntTMatrix", "ntCMatrix"), c("ntTMatrix", "ntrMatrix"), c("numLike", "dgeMatrix"), c("RsparseMatrix", "dgeMatrix")) .def.template <- function(from) { cd1 <- getClassDef(.FROM) cd2 <- getClassDef(.TO) Matrix.DeprecatedCoerce(cd1, cd2); to <- .CALL if(identical(as.character(class(to)), .TO)) return(to) ## Coercion via virtual generated a _subclass_ of the target class to.strict <- new(.TO) for (nm in slotNames(cd2)) slot(to.strict, nm) <- slot(to, nm) to.strict } for (.f.t in .from.to) { .f <- .f.t[1L] .t <- .f.t[2L] .def <- .def.template .env <- list(.FROM = .f, .TO = .t, .CALL = .as.via.virtual(.f, .t)) body(.def) <- do.call(substitute, list(body(.def), .env)) setAs(.f, .t, .def) } rm(.from.to, .f.t, .f, .t, .def.template, .def, .env) setAs("CHMfactor", "Matrix", function(from) { if(FALSE) { .Deprecated(old = "as(, \"Matrix\")", new = "expand1(., \"L\")", package = "Matrix") } expand1(from, "L") }) setAs("CHMfactor", "dMatrix", function(from) { if(FALSE) { .Deprecated(old = "as(, \"dMatrix\")", new = "expand1(., \"L\")", package = "Matrix") } expand1(from, "L") }) setAs("CHMfactor", "dsparseMatrix", function(from) { if(FALSE) { .Deprecated(old = "as(, \"dsparseMatrix\")", new = "expand1(., \"L\")", package = "Matrix") } expand1(from, "L") }) setAs("CHMfactor", "sparseMatrix", function(from) { if(FALSE) { .Deprecated(old = "as(, \"sparseMatrix\")", new = "expand1(., \"L\")", package = "Matrix") } expand1(from, "L") }) setAs("CHMfactor", "CsparseMatrix", function(from) { if(FALSE) { .Deprecated(old = "as(, \"CsparseMatrix\")", new = "expand1(., \"L\")", package = "Matrix") } expand1(from, "L") }) setAs("CHMfactor", "RsparseMatrix", function(from) { if(FALSE) { .Deprecated(old = "as(, \"RsparseMatrix\")", new = "as(expand1(., \"L\"), \"RsparseMatrix\")", package = "Matrix") } as(expand1(from, "L"), "RsparseMatrix") }) setAs("CHMfactor", "TsparseMatrix", function(from) { if(FALSE) { .Deprecated(old = "as(, \"TsparseMatrix\")", new = "as(expand1(., \"L\"), \"TsparseMatrix\")", package = "Matrix") } as(expand1(from, "L"), "TsparseMatrix") }) setAs("CHMfactor", "triangularMatrix", function(from) { if(FALSE) { .Deprecated(old = "as(, \"triangularMatrix\")", new = "as(expand1(., \"L\"), \"triangularMatrix\")", package = "Matrix") } as(expand1(from, "L"), "triangularMatrix") }) setAs("CHMfactor", "pMatrix", function(from) { if(FALSE) { .Deprecated(old = "as(, \"pMatrix\")", new = "expand1(., \"P1\")", package = "Matrix") } expand1(from, "P1") }) setMethod("chol2inv", c(x = "CHMfactor"), function(x, ...) { if(FALSE) { .Deprecated(old = "chol2inv()", new = "solve(.)", package = "Matrix") } solve(x) }) ## ~~~~ DEFUNCT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cBind <- function(..., deparse.level = 1) .Defunct(new = "cbind", package = "Matrix") rBind <- function(..., deparse.level = 1) .Defunct(msg = "rbind", package = "Matrix") Matrix/R/lu.R0000644000175100001440000003126714575137654012532 0ustar hornikusers## METHODS FOR GENERIC: lu ## pivoted LU factorization, returning denseLU or sparseLU ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("lu", c(x = "matrix"), function(x, ...) lu(.m2dense(x, ",ge"), ...)) setMethod("lu", c(x = "denseMatrix"), function(x, ...) lu(.M2kind(x, ","), ...)) setMethod("lu", c(x = "dgeMatrix"), function(x, warnSing = TRUE, ...) .Call(dgeMatrix_trf, x, as.logical(warnSing))) setMethod("lu", c(x = "dsyMatrix"), function(x, cache = TRUE, ...) { if(!is.null(ch <- x@factors[["denseLU"]])) return(ch) r <- lu(.M2gen(x), ...) if(cache) .set.factor(x, "denseLU", r) else r }) setMethod("lu", c(x = "dspMatrix"), function(x, cache = TRUE, ...) { if(!is.null(ch <- x@factors[["denseLU"]])) return(ch) r <- lu(.M2gen(x), ...) if(cache) .set.factor(x, "denseLU", r) else r }) for(.cl in c("dtrMatrix", "dtpMatrix")) setMethod("lu", c(x = .cl), function(x, ...) { if(x@uplo == "U" || x@diag == "U") { r <- new("denseLU") r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames r@perm <- seq_len(d[1L]) r@x <- .M2gen(x)@x r } else lu(.M2gen(x), ...) }) rm(.cl) setMethod("lu", c(x = "sparseMatrix"), function(x, ...) lu(.M2kind(.M2C(x), ","), ...)) setMethod("lu", c(x = "dgCMatrix"), function(x, errSing = TRUE, order = NA_integer_, tol = 1, ...) .Call(dgCMatrix_trf, x, order, tol, errSing)) setMethod("lu", c(x = "dsCMatrix"), function(x, cache = TRUE, ...) { if(!is.null(ch <- x@factors[["sparseLU"]])) return(ch) r <- lu(.M2gen(x), ...) if(cache) .set.factor(x, "sparseLU", r) else r }) setMethod("lu", c(x = "dtCMatrix"), function(x, ...) { if((upper <- x@uplo == "U") || x@diag == "U") { n <- (d <- x@Dim)[1L] r <- new("sparseLU") y <- new("dtCMatrix") y@Dim <- d y@uplo <- if(upper) "L" else "U" y@diag <- "U" y@p <- integer(n + 1L) r@Dim <- d r@Dimnames <- x@Dimnames r@L <- if(upper) y else x r@U <- if(upper) x else y r@p <- r@q <- seq.int(from = 0L, length.out = n) } else lu(.M2gen(x), ...) }) setMethod("lu", c(x = "dgRMatrix"), function(x, cache = TRUE, ...) { if(!is.null(ch <- x@factors[["sparseLU"]])) return(ch) r <- lu(.M2C(x), ...) if(cache) .set.factor(x, "sparseLU", r) else r }) setMethod("lu", c(x = "dsRMatrix"), function(x, cache = TRUE, ...) { if(!is.null(ch <- x@factors[["sparseLU"]])) return(ch) r <- lu(.M2gen(.tCRT(x)), ...) if(cache) .set.factor(x, "sparseLU", r) else r }) setMethod("lu", c(x = "dtRMatrix"), function(x, ...) { if((upper <- x@uplo == "U") || x@diag == "U") { n <- (d <- x@Dim)[1L] r <- new("sparseLU") y <- new("dtCMatrix") y@Dim <- d y@uplo <- if(upper) "L" else "U" y@diag <- "U" y@p <- integer(n + 1L) r@Dim <- d r@Dimnames <- x@Dimnames r@L <- if(upper) y else .M2C(x) r@U <- if(upper) .M2C(x) else y r@p <- r@q <- seq.int(from = 0L, length.out = n) } else lu(.M2gen(.M2C(x)), ...) }) setMethod("lu", c(x = "dgTMatrix"), function(x, cache = TRUE, ...) { if(!is.null(ch <- x@factors[["sparseLU"]])) return(ch) r <- lu(.M2C(x), ...) if(cache) .set.factor(x, "sparseLU", r) else r }) setMethod("lu", c(x = "dsTMatrix"), function(x, cache = TRUE, ...) { if(!is.null(ch <- x@factors[["sparseLU"]])) return(ch) r <- lu(.M2gen(.M2C(x)), ...) if(cache) .set.factor(x, "sparseLU", r) else r }) setMethod("lu", c(x = "dtTMatrix"), function(x, ...) { if((upper <- x@uplo == "U") || x@diag == "U") { n <- (d <- x@Dim)[1L] r <- new("sparseLU") y <- new("dtCMatrix") y@Dim <- d y@uplo <- if(upper) "L" else "U" y@diag <- "U" y@p <- integer(n + 1L) r@Dim <- d r@Dimnames <- x@Dimnames r@L <- if(upper) y else .M2C(x) r@U <- if(upper) .M2C(x) else y r@p <- r@q <- seq.int(from = 0L, length.out = n) r } else lu(.M2gen(.M2C(x)), ...) }) setMethod("lu", c(x = "diagonalMatrix"), function(x, ...) { x <- .M2kind(x, ",") n <- (d <- x@Dim)[1L] L <- new("dtCMatrix") r <- new("sparseLU") L@Dim <- d L@uplo <- "L" L@diag <- "U" L@p <- integer(n + 1L) r@L <- L if(x@diag == "N") { L@diag <- "N" L@p <- seq.int(from = 0L, length.out = n + 1L) L@x <- x@x } r@U <- L r@Dim <- d r@Dimnames <- x@Dimnames r@p <- r@q <- seq.int(from = 0L, length.out = n) r }) ## METHODS FOR CLASS: denseLU ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## TODO: we have C-level functions that do this, but no R interface .mkL <- function(x, m, n) { if(m == n) x else if(m < n) x[seq_len(prod(m, m))] else { x[seq.int(from = 1L, by = m + 1, length.out = n)] <- 1 if(n > 1L) { nvec <- seq_len(n - 1L) from <- seq.int(from = m + 1, by = m, length.out = n - 1L) x[sequence.default(nvec, from)] <- 0 } x } } .mkU <- function(x, m, n) { if(m == n) x else if(m > n) { nvec <- rep.int(n, n) from <- seq.int(from = 1L, by = m, length.out = n) x[sequence.default(nvec, from)] } else { if(m > 1L) { nvec <- seq.int(to = 1L, by = -1L, length.out = m - 1L) from <- seq.int(from = 2L, by = m + 1, length.out = m - 1L) x[sequence.default(nvec, from)] <- 0 } x } } setAs("denseLU", "dgeMatrix", function(from) { to <- new("dgeMatrix") to@Dim <- from@Dim to@x <- from@x to }) setMethod("expand1", c(x = "denseLU"), function(x, which, ...) { d <- x@Dim m <- d[1L] n <- d[2L] switch(which, "P1" =, "P1." = { r <- new("pMatrix") r@Dim <- c(m, m) r@perm <- asPerm(x@perm, n = m) if(which == "P1.") r@margin <- 2L r }, "L" = { if(m <= n) { r <- new("dtrMatrix") r@Dim <- c(m, m) r@uplo <- "L" r@diag <- "U" } else { r<- new("dgeMatrix") r@Dim <- d } r@x <- .mkL(x@x, m, n) r }, "U" = { if (m >= n) { r <- new("dtrMatrix") r@Dim <- c(n, n) } else { r <- new("dgeMatrix") r@Dim <- d } r@x <- .mkU(x@x, m, n) r }, stop(gettextf("'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", or \"%4$s\"", "which", "P", "L", "U"), domain = NA)) }) ## returning list(P1', L, U), where A = P1' L U setMethod("expand2", c(x = "denseLU"), function(x, ...) { d <- x@Dim dn <- x@Dimnames m <- d[1L] n <- d[2L] P1. <- new("pMatrix") P1.@Dim <- c(m, m) P1.@Dimnames <- c(dn[1L], list(NULL)) P1.@perm <- invertPerm(asPerm(x@perm, n = m)) if(m <= n) { L <- new("dtrMatrix") L@Dim <- c(m, m) L@uplo <- "L" L@diag <- "U" } else { L <- new("dgeMatrix") L@Dim <- d } L@x <- .mkL(x@x, m, n) if (m >= n) { U <- new("dtrMatrix") U@Dim <- c(n, n) } else { U <- new("dgeMatrix") U@Dim <- d } U@Dimnames <- c(list(NULL), dn[2L]) U@x <- .mkU(x@x, m, n) list(P1. = P1., L = L, U = U) }) ## returning list(L, U, P), where A = P L U ## MJ: for backwards compatibility setMethod("expand", c(x = "denseLU"), function(x, ...) { r <- expand2(x)[c(2L, 3L, 1L)] names(r) <- c("L", "U", "P") NN <- list(NULL, NULL) for(i in 1:3) r[[i]]@Dimnames <- NN r }) ## METHODS FOR CLASS: sparseLU ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("expand1", c(x = "sparseLU"), function(x, which, ...) { switch(which, "P1" =, "P1." = { r <- new("pMatrix") r@Dim <- x@Dim r@perm <- x@p + 1L if(which == "P1.") r@margin <- 2L r }, "P2" =, "P2." = { r <- new("pMatrix") r@Dim <- d <- x@Dim r@perm <- if(length(x@q)) x@q + 1L else seq_len(d[1L]) if(which == "P2") r@margin <- 2L r }, "L" = x@L, "U" = x@U, stop(gettextf("'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%2$s2\", \"%2$s2.\", \"%3$s\", or \"%4$s\"", "which", "P", "L", "U"), domain = NA)) }) ## returning list(P1', L, U, P2'), where A = P1' L U P2' setMethod("expand2", c(x = "sparseLU"), function(x, ...) { d <- x@Dim dn <- x@Dimnames p1 <- x@p p2 <- x@q P1. <- new("pMatrix") P1.@Dim <- d P1.@Dimnames <- c(dn[1L], list(NULL)) P1.@perm <- invertPerm(p1, 0L, 1L) P2. <- new("pMatrix") P2.@Dim <- d P2.@Dimnames <- c(list(NULL), dn[2L]) P2.@margin <- 2L P2.@perm <- if(length(p2)) invertPerm(p2, 0L, 1L) else seq_len(d[1L]) list(P1. = P1., L = x@L, U = x@U, P2. = P2.) }) ## returning list(P, L, U, Q), where A = P' L U Q ## MJ: for backwards compatibility setMethod("expand", c(x = "sparseLU"), function(x, ...) { d <- x@Dim dn <- x@Dimnames p <- x@p + 1L q <- x@q + 1L if(length(p) && !is.null(rn <- dn[[1L]])) dn[[1L]] <- rn[p] if(length(q) && !is.null(cn <- dn[[2L]])) dn[[2L]] <- cn[q] P <- new("pMatrix") P@Dim <- d P@perm <- p Q <- new("pMatrix") Q@Dim <- d Q@perm <- if(length(q)) q else seq_len(d[1L]) L <- x@L L@Dimnames <- c(dn[1L], list(NULL)) U <- x@U U@Dimnames <- c(list(NULL), dn[2L]) list(P = P, L = L, U = U, Q = Q) }) Matrix/R/vector.R0000644000175100001440000002132314575137654013404 0ustar hornikusers## METHODS FOR CLASS: sparseVector (virtual) ## sparse vectors ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("diff", c(x = "sparseVector"), ## Mostly cut and paste of base::diff.default : function(x, lag = 1L, differences = 1L, ...) { if(length(lag) != 1L || length(differences) != 1L || lag < 1L || differences < 1L) stop(gettextf("'%s' and '%s' must be positive integers", "lag", "differences"), domain = NA) if(lag * differences >= length(x)) return(x[0L]) i1 <- -seq_len(lag) for(i in seq_len(differences)) x <- x[i1] - x[-length(x):-(length(x) - lag + 1L)] x }) setMethod("mean", c(x = "sparseVector"), function(x, trim = 0, na.rm = FALSE, ...) { kind <- .M.kind(x) if(kind == "z" && trim > 0) stop("trimmed means are not defined for complex data") n <- length(x) if(kind != "n" && n > 0L && anyNA(x@x)) { if(!na.rm) return(NA_real_) n <- n - sum(is.na(x@x)) } if(n == 0L) return(if(kind == "z") NaN * 0i else NaN) if(kind == "n") { nnz <- length(x@i) if(trim <= 0) return(nnz / n) ntrim <- trunc(n * min(trim, 0.5)) if(nnz < ntrim) 0 else if(nnz == ntrim) { if(n - 2 * ntrim > 0) 0 else 0.5 } else { if(n - 2 * ntrim > 0) (nnz - ntrim - max(ntrim - (n - nnz), 0)) / (n - 2 * ntrim) else 1 } } else { if(trim <= 0) return(sum(x@x, na.rm = na.rm) / n) ntrim <- trunc(n * min(trim, 0.5)) x <- .V.sort(x, na.last = NA)[(ntrim + 1):(n - ntrim)] sum(x@x) / length(x) } }) .V.rep.each <- function(x, each) { each <- as.double(each) if(length(each) != 1L) { warning(gettextf("first element used of '%s' argument", "each"), domain = NA) each <- each[1L] } if(!is.finite(each) || each <= -1) stop(gettextf("invalid '%s' argument", "each"), domain = NA) if(each < 1) return(x[0L]) if(each < 2) return(x) n <- length(x) each <- trunc(each) if(n * each > 0x1p+53) stop(gettextf("%s length cannot exceed %s", "sparseVector", "2^53"), domain = NA) else if(n * each > .Machine$integer.max) { a <- as.double one <- 1 } else { each <- as.integer(each) a <- as.integer one <- 1L } x@length <- n * each x@i <- rep(each * (a(x@i) - one), each = each) + seq_len(each) if(.M.kind(x) != "n") x@x <- rep(x@x, each = each) x } .V.rep.int <- function(x, times) { times <- as.double(times) if(length(times) != 1L) { ## FIXME: support length(times) == length(x) warning(gettextf("first element used of '%s' argument", "times"), domain = NA) times <- times[1L] } if(!is.finite(times) || times <= -1) stop(gettextf("invalid '%s' argument", "times"), domain = NA) if(times < 1) return(x[0L]) if(times < 2) return(x) n <- length(x) times <- trunc(times) if(n * times > 0x1p+53) stop(gettextf("%s length cannot exceed %s", "sparseVector", "2^53"), domain = NA) else if(n * times > .Machine$integer.max) { a <- as.double zero <- 0 } else { times <- as.integer(times) a <- as.integer zero <- 0L } x@length <- n * times x@i <- rep(a(seq.int(from = zero, by = n, length.out = times)), each = length(x@i)) + x@i if(.M.kind(x) != "n") x@x <- rep.int(x@x, times) x } .V.rep.len <- function(x, length.out) { length.out <- as.double(length.out) if(length(length.out) != 1L) { warning(gettextf("first element used of '%s' argument", "length.out"), domain = NA) length.out <- length.out[1L] } if(!is.finite(length.out) || length.out <= -1) stop(gettextf("invalid '%s' argument", "length.out"), domain = NA) if(length.out > 0x1p+53) stop(gettextf("%s length cannot exceed %s", "sparseVector", "2^53"), domain = NA) n <- length(x) length.out <- if(length.out - 1 < .Machine$integer.max) as.integer(length.out) else trunc(length.out) if(length.out > n && n > 0L) { x <- .V.rep.int(x, ceiling(length.out / n)) n <- length(x) } x@length <- length.out if(length.out < n) { head <- x@i <= length.out x@i <- x@i[head] if(.M.kind(x) != "n") x@x <- x@x[head] } else if(length.out > n && n == 0L) { x@i <- seq_len(length.out) if(.M.kind(x) != "n") x@x <- rep.int(x@x[NA_integer_], length.out) } x } setMethod("rep", c(x = "sparseVector"), function(x, times, length.out, each, ...) { if(!missing(each)) x <- .V.rep.each(x, each) if(!missing(length.out)) x <- .V.rep.len (x, length.out) else if(!missing(times)) x <- .V.rep.int (x, times) x }) .V.sort <- function(x, decreasing = FALSE, na.last = NA, ...) { nnz <- length(x@i) if(nnz == 0L) return(x) n <- length(x) kind <- .M.kind(x) if(kind == "n") { x@i <- if(decreasing) seq_len(nnz) else seq.int(to = n, length.out = nnz) return(x) } x@x <- y <- sort.int(x@x, na.last = na.last, decreasing = decreasing, ...) if(!is.na(na.last)) nna <- if(anyNA(y)) sum(is.na(y)) else 0L else { x@length <- n <- n - (nnz - length(y)) nna <- 0L nnz <- length(y) } nnn <- switch(kind, "l" = nnz - nna, "i" = sum(y >= 0L, na.rm = TRUE), "d" = sum(y >= 0 , na.rm = TRUE), "z" = { arg <- Arg(y) hpi <- 0.5 * pi sum(arg > -hpi & arg <= hpi, na.rm = TRUE) }, stop("should never happen ...")) if(nna > 0L && decreasing != na.last) nnn <- nnn + nna x@i <- if(nnn < nnz) { if(decreasing) c(seq_len(nnn), seq.int(to = n, length.out = nnz - nnn)) else c(seq_len(nnz - nnn), seq.int(to = n, length.out = nnn)) } else { if(decreasing) seq_len(nnn) else seq.int(to = n, length.out = nnn) } x } if(FALSE) { ## MJ: once 'sort' becomes implicit generic in package 'methods' : setMethod("sort", c(x = "sparseVector"), .V.sort) ## TODO: parallel method for internal generic 'xtfrm' } setMethod("t", c(x = "sparseVector"), function(x) .tCRT(.V2C(x))) setMethod("toeplitz", c(x = "sparseVector"), function(x, symmetric = TRUE, repr = c("C", "R", "T"), giveCsparse, ...) { n <- length(x) if(n > .Machine$integer.max) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) nn <- c(n, n) r <- spV2M(x[as.integer(abs(.col(nn) - .row(nn))) + 1L], nrow = n, ncol = n, symmetric = symmetric, check = FALSE) repr <- # keep in sync with sparseMatrix if(missing(giveCsparse)) match.arg(repr) else if(!missing(repr)) { warning(gettextf("'%s' is deprecated; using '%s' instead", "giveCsparse", "repr"), domain = NA) match.arg(repr) } else if(giveCsparse) { "C" } else { warning(gettextf("'%s' is deprecated; setting %s=\"%s\"", "giveCsparse", "repr", "T"), domain = NA) "T" } switch(repr, "C" = .M2C(r), "R" = .M2R(r), "T" = r) }) Matrix/R/posdef.R0000644000175100001440000001235514574054152013355 0ustar hornikusers## METHODS FOR CLASS: dpoMatrix, dppMatrix ## dense symmetric positive semidefinite matrices ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## Operations such as rounding can lose positive semidefiniteness ## but not symmetry, hence: .indefinite <- function(x) { cl <- .M.nonvirtual(x, TRUE) if(any(cl == c("dpoMatrix", "corMatrix"))) as(x, "dsyMatrix") else if(any(cl == c("dppMatrix", "copMatrix"))) as(x, "dspMatrix") else x } .dsy2dpo <- .dsp2dpp <- function(from) { if(is.null(tryCatch(Cholesky(from, perm = FALSE), error = function(e) NULL))) stop("not a positive definite matrix (and positive semidefiniteness is not checked)") to <- new(.CLASS) to@Dim <- from@Dim to@Dimnames <- from@Dimnames to@uplo <- from@uplo to@x <- from@x to@factors <- from@factors to } body(.dsy2dpo)[[3L]][[3L]][[2L]] <- "dpoMatrix" body(.dsp2dpp)[[3L]][[3L]][[2L]] <- "dppMatrix" setAs("dppMatrix", "dpoMatrix", function(from) unpack(from)) setAs("dpoMatrix", "dppMatrix", function(from) pack(from)) setAs("dsyMatrix", "dpoMatrix", .dsy2dpo) setAs("dspMatrix", "dppMatrix", .dsp2dpp) setAs("Matrix", "dpoMatrix", function(from) .dsy2dpo(.M2unpacked(.M2sym(.M2kind(from, "d"))))) setAs("Matrix", "dppMatrix", function(from) .dsp2dpp(.M2packed (.M2sym(.M2kind(from, "d"))))) setAs("matrix", "dpoMatrix", function(from) { storage.mode(from) <- "double" .dsy2dpo(.M2sym(from)) }) setAs("matrix", "dppMatrix", function(from) { storage.mode(from) <- "double" .dsp2dpp(pack(from, symmetric = TRUE)) }) ## METHODS FOR CLASS: corMatrix, copMatrix ## dense correlation matrices ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .dpo2cor <- function(from) { if(!is.null(to <- from@factors$correlation)) return(to) sd <- sqrt(diag(from, names = FALSE)) to <- new("corMatrix") to@Dim <- d <- from@Dim to@Dimnames <- from@Dimnames to@uplo <- from@uplo to@sd <- sd n <- d[1L] x <- from@x / sd / rep(sd, each = n) x[indDiag(n)] <- 1 to@x <- x .set.factor(from, "correlation", to) } .dpp2cop <- function(from) { if(!is.null(to <- from@factors$correlation)) return(to) sd <- sqrt(diag(from, names = FALSE)) to <- new("copMatrix") to@Dim <- d <- from@Dim to@Dimnames <- from@Dimnames to@uplo <- uplo <- from@uplo to@sd <- sd n <- d[1L] u <- uplo == "U" if(u) { r <- seq_len(n) s <- 1L } else { r <- seq.int(to = 1L, by = -1L, length.out = n) s <- seq_len(n) } x <- from@x / rep.int(sd, r) / sd[sequence.default(r, s)] x[indDiag(n, upper = u, packed = TRUE)] <- 1 to@x <- x .set.factor(from, "correlation", to) } setAs("copMatrix", "corMatrix", function(from) unpack(from)) setAs("corMatrix", "copMatrix", function(from) pack(from)) setAs("dpoMatrix", "corMatrix", .dpo2cor) setAs("dppMatrix", "copMatrix", .dpp2cop) setAs("dsyMatrix", "corMatrix", function(from) .dpo2cor(.dsy2dpo(from))) setAs("dspMatrix", "copMatrix", function(from) .dpp2cop(.dsp2dpp(from))) setAs("Matrix", "corMatrix", function(from) .dpo2cor(.dsy2dpo(.M2unpacked(.M2sym(.M2kind(from, "d")))))) setAs("Matrix", "copMatrix", function(from) .dpp2cop(.dsp2dpp(.M2packed (.M2sym(.M2kind(from, "d")))))) setAs("matrix", "corMatrix", function(from) { storage.mode(from) <- "double" .dpo2cor (.dsy2dpo(.M2sym(from))) }) setAs("matrix", "copMatrix", function(from) { storage.mode(from) <- "double" .dpp2cop(.dsp2dpp(pack(from, symmetric = TRUE))) }) ## METHODS FOR GENERIC: cov2cor ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("cov2cor", c(V = "unpackedMatrix"), function(V) { d <- V@Dim if(d[1L] != d[2L] || .M.kind(V) == "z") stop(gettextf("'%s' is not a square numeric matrix", "V"), domain = NA) as(forceSymmetric(V), "corMatrix") }) setMethod("cov2cor", c(V = "packedMatrix"), function(V) { d <- V@Dim if(d[1L] != d[2L] || .M.kind(V) == "z") stop(gettextf("'%s' is not a square numeric matrix", "V"), domain = NA) as(forceSymmetric(V), "copMatrix") }) setMethod("cov2cor", c(V = "sparseMatrix"), function(V) { d <- V@Dim if(d[1L] != d[2L] || .M.kind(V) == "z") stop(gettextf("'%s' is not a square numeric matrix", "V"), domain = NA) dn <- symDN(V@Dimnames) V <- .M2kind(V, "d") V.ii <- diag(V, names = FALSE) if(length(V.ii) > 0L && is.na(m <- min(V.ii)) || m <= 0) warning(gettextf("diag(%s) has non-positive or non-finite entries; finite result is doubtful", "V"), domain = NA) D <- Diagonal(x = sqrt(1/V.ii)) r <- forceSymmetric(D %*% V %*% D) diag(r) <- 1 r@Dimnames <- dn r }) Matrix/R/subassign.R0000644000175100001440000017177714575137654014123 0ustar hornikusers## METHODS FOR GENERIC: [<- ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## GOAL: automate method definitions and eventually replace the ones ## collected below ... ## ## need to write C-level functions ## ## *_subassign_1ary (x, i, value) ## *_subassign_1ary_mat(x, i, value) ## *_subassign_2ary (x, i, j, value) ## ## for * = unpackedMatrix,packedMatrix, ## CsparseMatrix,RsparseMatrix,TsparseMatrix, ## diagonalMatrix,indMatrix if(FALSE) { # TODO .subassign.invalid <- function(value) { if(is.object(i)) gettextf("invalid subassignment value class \"%s\"", class(i)[1L]) else gettextf("invalid subassignment value type \"%s\"", typeof(i)) } .subassign.1ary <- function(x, i, value) { } ..subassign.1ary <- function(x, i, value) { } .subassign.1ary.mat <- function(x, i, value) { } ..subassign.1ary.mat <- function(x, i, value) { } .subassign.2ary <- function(x, i, j, value) { } ..subassign.2ary <- function(x, i, j, value) { } setMethod("[<-", c(x = "Matrix", i = "missing", j = "missing", value = "ANY"), function(x, i, j, ..., value) { if(missing(value)) stop("missing subassignment value") na <- nargs() if(na <= 4L) ## x[], x[, ] <- value .subassign.1ary(x, , value) else ## x[, , ], etc. <- value stop("incorrect number of dimensions") }) setMethod("[<-", c(x = "Matrix", i = "index", j = "missing", value = "ANY"), function(x, i, j, ..., value) { if(missing(value)) stop("missing subassignment value") na <- nargs() if(na == 3L) ## x[i=] <- value .subassign.1ary(x, i, value) else if(na == 4L) ## x[i=, ], x[, i=] <- value .subassign.2ary(x, i, , value) else ## x[i=, , ], etc. <- value stop("incorrect number of dimensions") }) setMethod("[<-", c(x = "Matrix", i = "missing", j = "index", value = "ANY"), function(x, i, j, ..., value) { if(missing(value)) stop("missing subassignment value") na <- nargs() if(na == 3L) ## x[j=] <- value .subassign.1ary(x, j, value) else if(na == 4L) ## x[j=, ], x[, j=] <- value .subassign.2ary(x, , j, value) else ## x[, j=, ], etc. <- value stop("incorrect number of dimensions") }) setMethod("[<-", c(x = "Matrix", i = "index", j = "index", value = "ANY"), function(x, i, j, ..., value) { if(missing(value)) stop("missing subassignment value") na <- nargs() if(na == 4L) ## x[i=, j=], x[j=, i=] <- value .subassign.2ary(x, i, j, value) else ## x[i=, j=, ], etc. <- value stop("incorrect number of dimensions") }) for(.cl in c("matrix", "nMatrix", "lMatrix")) setMethod("[<-", c(x = "Matrix", i = .cl, j = "missing", value = "ANY"), function(x, i, j, ..., value) { if(missing(value)) stop("missing subassignment value") na <- nargs() if(na == 3L) ## x[i=] <- value .subassign.1ary.mat(x, i, value) else if(na == 4L) ## x[i=, ], x[, i=] <- value .subassign.2ary(x, i, , value) else ## x[i=, , ], etc. <- value stop("incorrect number of dimensions") }) rm(.cl) setMethod("[<-", c(x = "Matrix", i = "NULL", j = "ANY", value = "ANY"), function(x, i, j, ..., value) { i <- integer(0L) callGeneric() }) setMethod("[<-", c(x = "Matrix", i = "ANY", j = "NULL", value = "ANY"), function(x, i, j, ..., value) { j <- integer(0L) callGeneric() }) setMethod("[<-", c(x = "Matrix", i = "NULL", j = "NULL", value = "ANY"), function(x, i, j, ..., value) { i <- integer(0L) j <- integer(0L) callGeneric() }) setMethod("[<-", c(x = "sparseVector", i = "missing", j = "missing", value = "ANY"), function(x, i, j, ..., value) { if(missing(value)) stop("missing subassignment value") if(nargs() > 3L) stop("incorrect number of dimensions") if(isS4(value)) { if(!.isVector(value)) stop(.subassign.invalid(value), domain = NA) } else value <- switch(typeof(value), "logical" =, "integer" =, "double" =, "complex" = .m2V(value), stop(.subassign.invalid(value), domain = NA)) n.x <- length(x) n.value <- length(value) if(n.x > 0L && n.value == 0L) stop("replacement has length zero") k.x <- .M2kind(x) k.value <- .M2kind(value) if(k.x != k.value) { map <- `names<-`(1:5, c("n", "l", "i", "d", "z")) if(map[[k.value]] < map[[k.x]]) value <- .V2kind(value, k.x) } if(n.value == 0L) return(value) if(n.x %% n.value != 0L) warning("number of items to replace is not a multiple of replacement length") .V.rep.len(value, n.x) }) setMethod("[<-", c(x = "sparseVector", i = "index", j = "missing", value = "ANY"), function(x, i, j, ..., value) { if(missing(value)) stop("missing subassignment value") if(nargs() > 3L) stop("incorrect number of dimensions") if(isS4(value)) { if(!.isVector(value)) stop(.subassign.invalid(value), domain = NA) } else value <- switch(typeof(value), "logical" =, "integer" =, "double" =, "complex" = .m2V(value), stop(.subassign.invalid(value), domain = NA)) switch(typeof(i), "logical" = {}, "integer" = {}, "double" = {}, stop(.subscript.invalid(value), domain = NA)) k.x <- .M2kind(x) k.value <- .M2kind(value) if(k.x != k.value) { map <- `names<-`(1:5, c("n", "l", "i", "d", "z")) if(map[[k.x]] < map[[k.value]]) x <- .V2kind(x, k.value) } ## TODO }) setMethod("[<-", c(x = "sparseVector", i = "nsparseVector", j = "missing", value = "ANY"), function(x, i, j, ..., drop = TRUE) { if(missing(value)) stop("missing subassignment value") if(nargs() > 3L) stop("incorrect number of dimensions") x[.subscript.recycle(i, length(x), TRUE)] <- value x }) setMethod("[<-", c(x = "sparseVector", i = "lsparseVector", j = "missing", value = "ANY"), function(x, i, j, ..., drop = TRUE) { if(missing(value)) stop("missing subassignment value") if(nargs() > 3L) stop("incorrect number of dimensions") x[.subscript.recycle(i, length(x), FALSE)] <- value x }) setMethod("[<-", c(x = "sparseVector", i = "NULL", j = "ANY", value = "ANY"), function(x, i, j, ..., value) { i <- integer(0L) callGeneric() }) } # TODO ## ==== Matrix ========================================================= ## A[ ij ] <- value, where ij is (i,j) 2-column matrix : ## ---------------- ## The cheap general method, now only used for "pMatrix","indMatrix" ## sparse all use .TM.repl.i.mat() ## NOTE: need '...' below such that setMethod() does ## not use .local() such that nargs() will work correctly: .M.repl.i.2col <- function (x, i, j, ..., value) { nA <- nargs() if(nA == 3) { ## M [ cbind(ii,jj) ] <- value or M [ Lmat ] <- value if(!is.integer(nc <- ncol(i))) stop(".M.repl.i.2col(): 'i' has no integer column number;\n should never happen; please report") else if(!is.numeric(i) || nc != 2) stop("such indexing must be by logical or 2-column numeric matrix") if(is.logical(i)) { message(".M.repl.i.2col(): drop 'matrix' case ...") ## c(i) : drop "matrix" to logical vector return( callGeneric(x, i=c(i), value=value) ) } if(!is.integer(i)) storage.mode(i) <- "integer" if(any(i < 0)) stop("negative values are not allowed in a matrix subscript") if(anyNA(i)) stop("NAs are not allowed in subscripted assignments") if(any(i0 <- (i == 0))) # remove them i <- i[ - which(i0, arr.ind = TRUE)[,"row"], ] ## now have integer i >= 1 m <- nrow(i) ## mod.x <- .type.kind[.M.kind(x)] if(length(value) > 0 && m %% length(value) != 0) warning("number of items to replace is not a multiple of replacement length") ## recycle: value <- rep_len(value, m) i1 <- i[,1] i2 <- i[,2] if(m > 2) message("m[ ] <- v: inefficiently treating single elements") ## inefficient -- FIXME -- (also loses "symmetry" unnecessarily) for(k in seq_len(m)) x[i1[k], i2[k]] <- value[k] x } else stop(gettextf("nargs() = %d. Extraneous illegal arguments inside '[ .. ]' ?", nA), domain = NA) } setMethod("[<-", c(x = "Matrix", i = "matrix", j = "missing", value = "replValue"), .M.repl.i.2col) ## Three catch-all methods ... would be very inefficient for sparse* ## --> extra methods in ./sparseMatrix.R setMethod("[<-", c(x = "Matrix", i = "missing", j = "ANY", value = "Matrix"), function(x, i, j, ..., value) callGeneric(x=x, , j=j, value = as.vector(value))) setMethod("[<-", c(x = "Matrix", i = "ANY", j = "missing", value = "Matrix"), function(x, i, j, ..., value) if(nargs() == 3) callGeneric(x=x, i=i, value = as.vector(value)) else callGeneric(x=x, i=i, , value = as.vector(value))) setMethod("[<-", c(x = "Matrix", i = "ANY", j = "ANY", value = "Matrix"), function(x, i, j, ..., value) callGeneric(x=x, i=i, j=j, value = as.vector(value))) setMethod("[<-", c(x = "Matrix", i = "missing", j = "ANY", value = "matrix"), function(x, i, j, ..., value) callGeneric(x=x, , j=j, value = c(value))) setMethod("[<-", c(x = "Matrix", i = "ANY", j = "missing", value = "matrix"), function(x, i, j, ..., value) if(nargs() == 3) callGeneric(x=x, i=i, value = c(value)) else callGeneric(x=x, i=i, , value = c(value))) setMethod("[<-", c(x = "Matrix", i = "ANY", j = "ANY", value = "matrix"), function(x, i, j, value) callGeneric(x=x, i=i, j=j, value = c(value))) ## M [ ] <- value; used notably for x = "CsparseMatrix" .repl.i.lDMat <- function (x, i, j, ..., value) `[<-`(x, i=which(as.vector(i)), value=value) setMethod("[<-", c(x = "Matrix", i = "ldenseMatrix", j = "missing", value = "replValue"), .repl.i.lDMat) setMethod("[<-", c(x = "Matrix", i = "ndenseMatrix", j = "missing", value = "replValue"), .repl.i.lDMat) rm(.repl.i.lDMat) .repl.i.lSMat <- function (x, i, j, ..., value) `[<-`(x, i=which(as(i, "sparseVector")), value=value) setMethod("[<-", c(x = "Matrix", i = "lsparseMatrix", j = "missing", value = "replValue"), .repl.i.lSMat) setMethod("[<-", c(x = "Matrix", i = "nsparseMatrix", j = "missing", value = "replValue"), .repl.i.lSMat) rm(.repl.i.lSMat) ## (ANY,ANY,ANY) is used when no `real method' is implemented : setMethod("[<-", c(x = "Matrix", i = "ANY", j = "ANY", value = "ANY"), function (x, i, j, value) { if(!is.atomic(value)) stop(gettextf("RHS 'value' (class %s) matches 'ANY', but must match matrix class %s", class(value), class(x)), domain = NA) else stop("not-yet-implemented 'Matrix[<-' method") }) ## ==== denseMatrix ==================================================== ## x[] <- value : setMethod("[<-", c(x = "denseMatrix", i = "missing", j = "missing", value = "ANY"),## double/logical/... function (x, value) { x <- .M2gen(x) x@x[] <- value validObject(x)# check if type and lengths above match x }) ## FIXME: 1) These are far from efficient ## ----- setMethod("[<-", c(x = "denseMatrix", i = "index", j = "missing", value = "replValue"), function (x, i, j, ..., value) { r <- as(x, "matrix") ## message("`[<-` with nargs()= ",nargs()) if((na <- nargs()) == 3) r[i] <- value else if(na == 4) r[i, ] <- value else stop(gettextf("invalid nargs()= %d", na), domain=NA) .m2dense(r, paste0(.M.kind(x), "ge")) }) setMethod("[<-", c(x = "denseMatrix", i = "missing", j = "index", value = "replValue"), function (x, i, j, ..., value) { r <- as(x, "matrix") r[, j] <- value .m2dense(r, paste0(.M.kind(x), "ge")) }) setMethod("[<-", c(x = "denseMatrix", i = "index", j = "index", value = "replValue"), function (x, i, j, ..., value) { r <- as(x, "matrix") r[i, j] <- value as_denseClass(r, class(x)) ## was as(r, class(x)) }) setMethod("[<-", c(x = "denseMatrix", i = "matrix", # 2-col.matrix j = "missing", value = "replValue"), function(x, i, j, ..., value) { r <- as(x, "matrix") r[ i ] <- value .m2dense(r, paste0(.M.kind(x), "ge")) }) ## ==== sparseMatrix =================================================== ## x[] <- value : setMethod("[<-", c(x = "sparseMatrix", i = "missing", j = "missing", value = "ANY"),## double/logical/... function (x, i, j,..., value) { if(all0(value)) { # be faster cld <- getClassDef(class(x)) x <- diagU2N(x, cl = cld) for(nm in intersect(nsl <- names(cld@slots), c("x", "i","j", "factors"))) length(slot(x, nm)) <- 0L if("p" %in% nsl) x@p <- rep.int(0L, ncol(x)+1L) } else { ## typically non-sense: assigning to full sparseMatrix x[TRUE] <- value } x }) ## Do not use as.vector() (see ./Matrix.R ) for sparse matrices : setMethod("[<-", c(x = "sparseMatrix", i = "missing", j = "ANY", value = "sparseMatrix"), function (x, i, j, ..., value) callGeneric(x=x, , j=j, value=as(value, "sparseVector"))) setMethod("[<-", c(x = "sparseMatrix", i = "ANY", j = "missing", value = "sparseMatrix"), function (x, i, j, ..., value) if(nargs() == 3) callGeneric(x=x, i=i, value=as(value, "sparseVector")) else callGeneric(x=x, i=i, , value=as(value, "sparseVector"))) setMethod("[<-", c(x = "sparseMatrix", i = "ANY", j = "ANY", value = "sparseMatrix"), function (x, i, j, ..., value) callGeneric(x=x, i=i, j=j, value=as(value, "sparseVector"))) ## ==== CsparseMatrix ================================================== ## workhorse for "[<-" -- for d*, l*, and n..C-sparse matrices : ## --------- ----- replCmat <- function (x, i, j, ..., value) { di <- dim(x) dn <- dimnames(x) iMi <- missing(i) jMi <- missing(j) na <- nargs() Matrix.message("replCmat[x,i,j,..,val] : nargs()=", na, "; ", if(iMi || jMi) sprintf("missing (i,j) = (%d,%d)", iMi, jMi), .M.level = 2) if(na == 3L) { ## vector (or 2-col) indexing M[i] <- v : includes M[TRUE] <- v or M[] <- v ! x <- .M2T(x) x[i] <- value # may change class, e.g., from dtT* to dgT* cl.C <- sub(".Matrix$", "CMatrix", class(x)) if(.hasSlot(x, "x") && any0(x@x)) ## drop all values that "happen to be 0" drop0(x, is.Csparse = FALSE) else as_CspClass(x, cl.C) } else ## nargs() == 4 : replCmat4(x, i1 = if(iMi) seq.int(from = 0L, length.out = di[1L]) else .ind.prep2(i, 1L, di, dn), i2 = if(jMi) seq.int(from = 0L, length.out = di[2L]) else .ind.prep2(j, 2L, di, dn), iMi = iMi, jMi = jMi, value = value) } ## replCmat replCmat4 <- function(x, i1, i2, iMi, jMi, value, spV = is(value, "sparseVector")) { dind <- c(length(i1), length(i2)) # dimension of replacement region lenRepl <- prod(dind) lenV <- length(value) if(lenV == 0) { if(lenRepl != 0L) stop("nothing to replace with") return(x) } ## else: lenV := length(value) is > 0 if(lenRepl %% lenV != 0L) stop("number of items to replace is not a multiple of replacement length") if(lenV > lenRepl) stop("too many replacement values") clx <- class(x) clDx <- getClassDef(clx) # extends() , is() etc all use the class definition ## keep "symmetry" if changed here: x.sym <- extends(clDx, "symmetricMatrix") if(x.sym) { ## only half the indices are there.. ## using array() for large dind is a disaster... mkArray <- if(spV) # TODO: room for improvement function(v, dim) spV2M(v, dim[1L], dim[2L]) else array x.sym <- (dind[1L] == dind[2L] && all(i1 == i2) && (lenRepl == 1L || lenV == 1L || isSymmetric(mkArray(value, dim=dind)))) ## x.sym : result is *still* symmetric x <- .M2gen(x) ## but do *not* redefine clx! } else if(extends(clDx, "triangularMatrix")) { xU <- x@uplo == "U" r.tri <- ((any(dind == 1) || dind[1L] == dind[2L]) && if(xU) max(i1) <= min(i2) else max(i2) <= min(i1)) if(r.tri) { ## result is *still* triangular if(any(i1 == i2)) # diagonal will be changed x <- diagU2N(x) # keeps class (!) } else { # go to "generalMatrix" and (do not redefine clx!) and continue x <- .M2gen(x) # was as(x, paste0(.M.kind(x), "gCMatrix")) } } ## Temporary hack for debugging --- remove eventually -- FIXME : ## see also MATRIX_SUBASSIGN_VERBOSE in ../src/t_Csparse_subassign.c if(!is.null(v <- getOption("Matrix.subassign.verbose")) && v) { op <- options(Matrix.verbose = 2); on.exit(options(op)) ## the "hack" to signal "verbose" to the C code: if(i1[1L] != 0L) i1[1L] <- -i1[1L] else warning("i1[1] == 0 ==> C-level verbosity will not happen!") } if(extends(clDx, "dMatrix")) { has.x <- TRUE x <- .Call(dCsparse_subassign, if(clx %in% c("dgCMatrix", "dtCMatrix")) x else .M2gen(x), # must get "dgCMatrix" i1, i2, as(value, "sparseVector")) } else if(extends(clDx, "lMatrix")) { has.x <- TRUE x <- .Call(lCsparse_subassign, if(clx %in% c("lgCMatrix", "ltCMatrix")) x else .M2gen(x), # must get "lgCMatrix" i1, i2, as(value, "sparseVector")) } else if(extends(clDx, "nMatrix")) { has.x <- FALSE x <- .Call(nCsparse_subassign, if(clx %in% c("ngCMatrix", "ntCMatrix"))x else .M2gen(x), # must get "ngCMatrix" i1, i2, as(value, "sparseVector")) } else if(extends(clDx, "iMatrix")) { has.x <- TRUE x <- .Call(iCsparse_subassign, if(clx %in% c("igCMatrix", "itCMatrix"))x else .M2gen(x), # must get "igCMatrix" i1, i2, as(value, "sparseVector")) } else if(extends(clDx, "zMatrix")) { has.x <- TRUE x <- .Call(zCsparse_subassign, if(clx %in% c("zgCMatrix", "ztCMatrix"))x else .M2gen(x), # must get "zgCMatrix" i1, i2, ## here we only want zsparseVector {to not have to do this in C}: as(value, "zsparseVector")) } else { ## use "old" code ... ## does this happen ? ==> if(identical(Sys.getenv("USER"),"maechler"))## does it still happen? __ FIXME __ stop("using \"old code\" part in Csparse subassignment") ## else warning("using\"old code\" part in Csparse subassignment\n >>> please report to Matrix-authors@r-project.org", immediate. = TRUE) xj <- .Call(Matrix_expand_pointers, x@p) sel <- (!is.na(match(x@i, i1)) & !is.na(match( xj, i2))) has.x <- "x" %in% slotNames(clDx)# === slotNames(x), ## has.x <==> *not* nonzero-pattern == "nMatrix" if(has.x && sum(sel) == lenRepl) { ## all entries to be replaced are non-zero: ## need indices instead of just 'sel', for, e.g., A[2:1, 2:1] <- v non0 <- cbind(match(x@i[sel], i1), match(xj [sel], i2), deparse.level=0L) iN0 <- 1L + .Call(m_encodeInd, non0, di = dind, orig1=TRUE, checkBounds=FALSE) has0 <- if(spV) length(value@i) < lenV else any(value[!is.na(value)] == 0) if(lenV < lenRepl) value <- rep_len(value, lenRepl) ## Ideally we only replace them where value != 0 and drop the value==0 ## ones; FIXME: see Davis(2006) "2.7 Removing entries", p.16, e.g. use cs_dropzeros() ## but really could be faster and write something like cs_drop_k(A, k) ## v0 <- 0 == value ## if (lenRepl == 1) and v0 is TRUE, the following is not doing anything ##- --> ./Tsparse.R and its replTmat() ## x@x[sel[!v0]] <- value[!v0] x@x[sel] <- as.vector(value[iN0]) if(.hasSlot(x, "factors") && length(x@factors)) # drop cached ones x@factors <- list() if(has0) x <- .drop0(x) return(if(x.sym) as_CspClass(x, clx) else x) } ## else go via Tsparse.. {FIXME: a waste! - we already have 'xj' ..} ## and inside Tsparse... the above i1, i2,..., sel are *all* redone! ## Happens too often {not anymore, I hope!} ## Matrix.message("wasteful C -> T -> C in replCmat(x,i,j,v) for [i,j] <- v") x <- as(x, "TsparseMatrix") if(iMi) x[ ,i2+1L] <- value else if(jMi) x[i1+1L, ] <- value else x[i1+1L,i2+1L] <- value if(.hasSlot(x, "factors") && length(x@factors)) # drop cached ones x@factors <- list() }# else{ not using new memory-sparse code if(has.x && any0(x@x)) ## drop all values that "happen to be 0" as_CspClass(drop0(x), clx) else as_CspClass(x, clx) } ## replCmat4 setMethod("[<-", c(x = "CsparseMatrix", i = "index", j = "missing", value = "replValue"), replCmat) setMethod("[<-", c(x = "CsparseMatrix", i = "missing", j = "index", value = "replValue"), replCmat) setMethod("[<-", c(x = "CsparseMatrix", i = "index", j = "index", value = "replValue"), replCmat) ### When the RHS 'value' is a sparseVector, now can use replCmat as well setMethod("[<-", c(x = "CsparseMatrix", i = "missing", j = "index", value = "sparseVector"), replCmat) setMethod("[<-", c(x = "CsparseMatrix", i = "index", j = "missing", value = "sparseVector"), replCmat) setMethod("[<-", c(x = "CsparseMatrix", i = "index", j = "index", value = "sparseVector"), replCmat) rm(replCmat) ## A[ ij ] <- value, where ij is (i,j) 2-column matrix setMethod("[<-", c(x = "CsparseMatrix", i = "matrix", j = "missing", value = "replValue"), function(x, i, j, ..., value) ## goto Tsparse modify and convert back: as(.TM.repl.i.mat(as(x, "TsparseMatrix"), i=i, value=value), "CsparseMatrix")) ## more in ./sparseMatrix.R (and ./Matrix.R ) setMethod("[<-", c(x = "CsparseMatrix", i = "Matrix", j = "missing", value = "replValue"), function(x, i, j, ..., value) ## goto Tsparse modify and convert back: as(.TM.repl.i.mat(as(x, "TsparseMatrix"), i=i, value=value), "CsparseMatrix")) ## ==== RsparseMatrix ================================================== setMethod("[<-", c(x = "RsparseMatrix", i = "index", j = "missing", value = "replValue"), function (x, i, j, ..., value) replTmat(.M2T(x), i=i, , value=value)) setMethod("[<-", c(x = "RsparseMatrix", i = "missing", j = "index", value = "replValue"), function (x, i, j, ..., value)# extra " , ": want nargs() == 4 replTmat(.M2T(x), , j=j, value=value)) setMethod("[<-", c(x = "RsparseMatrix", i = "index", j = "index", value = "replValue"), function (x, i, j, ..., value) replTmat(.M2T(x), i=i, j=j, value=value)) setMethod("[<-", c(x = "RsparseMatrix", i = "index", j = "missing", value = "sparseVector"), function (x, i, j, ..., value) { if(nargs() == 3L) replTmat(.M2T(x), i=i, value=value) # x[i] <- v else replTmat(.M2T(x), i=i, , value=value) # x[i, ] <- v }) setMethod("[<-", c(x = "RsparseMatrix", i = "missing", j = "index", value = "sparseVector"), function (x, i, j, ..., value)# extra " , ": want nargs() == 4 replTmat(.M2T(x), , j=j, value=value)) setMethod("[<-", c(x = "RsparseMatrix", i = "index", j = "index", value = "sparseVector"), function (x, i, j, ..., value) replTmat(.M2T(x), i=i, j=j, value=value)) setMethod("[<-", c(x = "RsparseMatrix", i = "matrix", j = "missing", value = "replValue"), function (x, i, j, ..., value) { if(nargs() == 3L) .TM.repl.i.mat(.M2T(x), i=i, value=value) else replTmat(.M2T(x), i=as.vector(i), , value=value) }) ## ==== TsparseMatrix ================================================== ##' a simplified "subset" of intI() below int2i <- function(i, n) { if(any(i < 0L)) { if(any(i > 0L)) stop("you cannot mix negative and positive indices") seq_len(n)[i] } else { if(length(i) && max(i, na.rm=TRUE) > n) stop(gettextf("index larger than maximal %d", n), domain=NA) if(any(z <- i == 0)) i <- i[!z] i } } intI <- function(i, n, dn, give.dn = TRUE) { ## Purpose: translate numeric | logical | character index ## into 0-based integer ## ---------------------------------------------------------------------- ## Arguments: i: index vector (numeric | logical | character) ## n: array extent { == dim(.) [margin] } ## dn: character col/rownames or NULL { == dimnames(.)[[margin]] } ## ---------------------------------------------------------------------- ## Author: Martin Maechler, Date: 23 Apr 2007 has.dn <- !is.null.DN(dn) DN <- has.dn && give.dn if(is.numeric(i) || is(i, "numeric")) { # inherits(, "numeric") is FALSE storage.mode(i) <- "integer" if(anyNA(i)) stop("'NA' indices are not (yet?) supported for sparse Matrices") if(any(i < 0L)) { if(any(i > 0L)) stop("you cannot mix negative and positive indices") i0 <- (0:(n - 1L))[i] } else { if(length(i) && max(i, na.rm=TRUE) > n) # base has "subscript out of bounds": stop(gettextf("index larger than maximal %d", n), domain=NA) if(any(z <- i == 0)) i <- i[!z] i0 <- i - 1L # transform to 0-indexing } if(DN) dn <- dn[i] } else if (is.logical(i) || inherits(i, "logical")) { if(length(i) > n) stop(gettextf("logical subscript too long (%d, should be %d)", length(i), n), domain=NA) if(anyNA(i)) stop("'NA' indices are not (yet?) supported for sparse Matrices") i0 <- (0:(n - 1L))[i] if(DN) dn <- dn[i] } else { ## character if(!has.dn) stop("no 'dimnames[[.]]': cannot use character indexing") i0 <- match(i, dn) if(anyNA(i0)) stop("invalid character indexing") if(DN) dn <- dn[i0] i0 <- i0 - 1L } if(!give.dn) i0 else list(i0 = i0, dn = dn) } ## {intI} .ind.prep <- function(xi, intIlist, iDup = duplicated(i0), anyDup = any(iDup)) { ## Purpose: do the ``common things'' for "*gTMatrix" indexing for 1 dim. ## and return match(.,.) + li = length of corresponding dimension ## ## xi = "x@i" ; intIlist = intI(i, dim(x)[margin], ....) i0 <- intIlist$i0 stopifnot(is.numeric(i0))# cheap fast check (i0 may have length 0 !) m <- match(xi, i0, nomatch=0) if(anyDup) { # assuming anyDup <- any(iDup <- duplicated(i0)) ## i0i: where in (non-duplicated) i0 are the duplicated ones i0i <- match(i0[iDup], i0) i.x <- which(iDup) - 1L jm <- lapply(i0i, function(.) which(. == m)) } c(list(m = m, li = length(i0), i0 = i0, anyDup = anyDup, dn = intIlist$dn), ## actually, iDup is rarely needed in calling code if(anyDup) list(iDup = iDup, i0i = i0i, i.x = i.x, jm = unlist(jm), i.xtra = rep.int(i.x, lengths(jm)))) } ## {.ind.prep} ##' ##' Do the ``common things'' for "*gTMatrix" sub-assignment ##' for 1 dimension, 'margin' , ##'
##' @title Indexing Preparation ##' @param i "index" ##' @param margin in {1,2}; ##' @param di = dim(x) { used when i is not character } ##' @param dn = dimnames(x) ##' @return match(.,.) + li = length of corresponding dimension ##' difference to .ind.prep(): use 1-indices; no match(xi,..), no dn at end ##' @author Martin Maechler .ind.prep2 <- function(i, margin, di, dn) intI(i, n = di[margin], dn = dn[[margin]], give.dn = FALSE) ### FIXME: make this `very fast' for the very very common case of ### ----- M[i,j] <- v with i,j = length-1-numeric; v= length-1 number ### *and* M[i,j] == 0 previously ## ## FIXME(2): keep in sync with replCmat() in ./Csparse.R ## FIXME(3): It's terribly slow when used e.g. from diag(M[,-1]) <- value ## ----- which has "workhorse" M[,-1] <- ## ## workhorse for "[<-" : replTmat <- function (x, i, j, ..., value) { ## NOTE: need '...', i.e., exact signature such that setMethod() ## does not use .local() such that nargs() will work correctly: di <- dim(x) dn <- dimnames(x) iMi <- missing(i) jMi <- missing(j) ## "FIXME": could pass this (and much ? more) when this function would not *be* a ## method but be *called* from methods clDv <- getClassDef(class(value)) spV <- extends(clDv, "sparseVector") ## own version of all0() that works both for sparseVector and atomic vectors: .all0 <- function(v) if(spV) length(v@i) == 0 else all0(v) delayedAssign("value.not.logical", !(if(spV) { extends1of(clDv, "lsparseVector", "nsparseVector") } else { is.logical(value) || is.logical(as.vector(value)) })) na <- nargs() if(na == 3) { ## i = vector indexing M[i] <- v, e.g., M[TRUE] <- v or M[] <- v ! Matrix.message("diagnosing replTmat(x,i,j,v): nargs()= 3; ", if(iMi | jMi) sprintf("missing (i,j) = (%d,%d)", iMi,jMi)) if(iMi) stop("internal bug: missing 'i' in replTmat(): please report") if(is.character(i)) stop("[ ] indexing not allowed: forgot a \",\" ?") if(is.matrix(i)) stop("internal bug: matrix 'i' in replTmat(): please report") ## Now: have M[i] <- v with vector logical or "integer" i : ## Tmatrix maybe non-unique, have an entry split into a sum of several ones: if(!is(x,"generalMatrix")) { cl <- class(x) x <- .M2gen(x) Matrix.message("'sub-optimal sparse 'x[i] <- v' assignment: Coercing class ", cl," to ",class(x)) } nr <- di[1] x <- aggregateT(x) x.i <- .Call(m_encodeInd2, x@i, x@j, di=di, FALSE, FALSE) n <- prod(di) i <- if(is.logical(i)) { # full-size logical indexing if(n) { if(isTRUE(i)) # shortcut 0:(n-1) else { if(length(i) < n) i <- rep_len(i, n) (0:(n-1))[i] # -> 0-based index vector as well {maybe LARGE!} } } else integer(0) } else { ## also works with *negative* indices etc: int2i(as.integer(i), n) - 1L ## 0-based indices [to match m_encodeInd2()] } clx <- class(x) clDx <- getClassDef(clx) # extends(), is() etc all use the class definition has.x <- "x" %in% slotNames(clDx) # === slotNames(x) if(!has.x && # <==> "n.TMatrix" ((iNA <- any(ina <- is.na(value))) || value.not.logical)) { if(value.not.logical) value <- as.logical(value) if(iNA) { value[ina] <- TRUE warning( gettextf("x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced; NA |--> TRUE.", dQuote(clx)), domain=NA) } else warning( gettextf("x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.", dQuote(clx)), domain=NA) } ## now have 0-based indices x.i (entries) and i (new entries) ## the simplest case: if(.all0(value)) { ## just drop the non-zero entries if(!all(sel <- is.na(match(x.i, i)))) { ## non-zero there x@i <- x@i[sel] x@j <- x@j[sel] if(has.x) x@x <- x@x[sel] if(.hasSlot(x, "factors") && length(x@factors)) # drop cached ones x@factors <- list() } return(x) } m <- length(i) if(length(value) != m) { ## use recycling rules if(m %% length(value) != 0) warning("number of items to replace is not a multiple of replacement length") value <- rep_len(value, m) } ## With duplicated entries i, only use the last ones! if(id <- anyDuplicated(i, fromLast=TRUE)) { i <- i[-id] value <- value[-id] if(any(id <- duplicated(i, fromLast=TRUE))) { nd <- -which(id) i <- i[nd] value <- value[nd] } } ## matching existing non-zeros and new entries; isE := "is Existing" ## isE <- i %in% x.i; mi <- {matching i's} isE <- !is.na(mi <- match(i, x.i)) ## => mi[isE] entries in (i,j,x) to be set to new value[]s ## 1) Change the matching non-zero entries if(has.x) x@x[mi[isE]] <- as(value[isE], class(x@x)) else if(any0(value[isE])) { ## "n.TMatrix" : remove (i,j) where value is FALSE get0 <- !value[isE] ## x[i,j] is TRUE, should become FALSE i.rm <- - mi[isE][get0] x@i <- x@i[i.rm] x@j <- x@j[i.rm] } ## 2) add the new non-zero entries i <- i[!isE] xv <- value[!isE] ## --- Be be efficient when 'value' is sparse : if(length(notE <- which(isN0(xv)))) { # isN0(): non-0's; NAs counted too xv <- xv[notE] i <- i[notE] if(has.x) { x@x <- c(x@x, as(xv, class(x@x))) } else { # n.TMatrix : assign (i,j) only where value is TRUE: i <- i[xv] } x@i <- c(x@i, i %% nr) x@j <- c(x@j, i %/% nr) } if(.hasSlot(x, "factors") && length(x@factors)) # drop cached ones x@factors <- list() return(x) } ## {nargs = 3; x[ii] <- value } ## nargs() == 4 : x[i,j] <- value ## -------------------------------------------------------------------------- lenV <- length(value) Matrix.message(".. replTmat(x,i,j,v): nargs()= 4; cl.(x)=", class(x),"; len.(value)=", lenV,"; ", if(iMi | jMi) sprintf("missing (i,j) = (%d,%d)", iMi,jMi), .M.level = 2)# level 1 gives too many messages ## FIXME: use 'abIndex' or a better algorithm, e.g. if(iMi) i1 <- if(iMi) 0:(di[1] - 1L) else .ind.prep2(i, 1, di, dn) i2 <- if(jMi) 0:(di[2] - 1L) else .ind.prep2(j, 2, di, dn) dind <- c(length(i1), length(i2)) # dimension of replacement region lenRepl <- prod(dind) if(lenV == 0) { if(lenRepl != 0) stop("nothing to replace with") else return(x) } ## else: lenV := length(value) is > 0 if(lenRepl %% lenV != 0) stop("number of items to replace is not a multiple of replacement length") if(!spV && lenRepl > 2^16) { # (somewhat arbitrary cutoff) value <- as(value, "sparseVector")# so that subsequent rep(.) are fast spV <- TRUE } ## Now deal with duplicated / repeated indices: "last one wins" if(!iMi && any(dup <- duplicated(i1, fromLast = TRUE))) { ## duplicated rows keep <- !dup i1 <- i1[keep] ## keep is "internally" recycled below {and that's important: it is dense!} lenV <- length(value <- rep_len(value, lenRepl)[keep]) dind[1] <- length(i1) lenRepl <- prod(dind) } if(!jMi && any(dup <- duplicated(i2, fromLast = TRUE))) { ## duplicated columns iDup <- which(dup) ## The following is correct, but rep(keep,..) can be *HUGE* ## keep <- !dup ## i2 <- i2[keep] ## lenV <- length(value <- rep_len(value, lenRepl)[rep(keep, each=dind[1])]) ## solution: sv[-i] is efficient for sparseVector: i2 <- i2[- iDup] nr <- dind[1] iDup <- rep((iDup - 1)*nr, each=nr) + seq_len(nr) lenV <- length(value <- rep_len(value, lenRepl)[-iDup]) dind[2] <- length(i2) lenRepl <- prod(dind) } clx <- class(x) clDx <- getClassDef(clx) # extends() , is() etc all use the class definition stopifnot(extends(clDx, "TsparseMatrix")) ## Tmatrix maybe non-unique, have an entry split into a sum of several ones: x <- aggregateT(x) toGeneral <- r.sym <- FALSE if(extends(clDx, "symmetricMatrix")) { ## using array() for large dind is a disaster... mkArray <- if(spV) # TODO: room for improvement function(v, dim) spV2M(v, dim[1],dim[2]) else array r.sym <- (dind[1] == dind[2] && all(i1 == i2) && (lenRepl == 1 || lenV == 1 || isSymmetric(mkArray(value, dim=dind)))) if(r.sym) { ## result is *still* symmetric --> keep symmetry! xU <- x@uplo == "U" # later, we will consider only those indices above / below diagonal: } else toGeneral <- TRUE } else if(extends(clDx, "triangularMatrix")) { xU <- x@uplo == "U" r.tri <- ((any(dind == 1) || dind[1] == dind[2]) && if(xU) max(i1) <= min(i2) else max(i2) <= min(i1)) if(r.tri) { ## result is *still* triangular if(any(i1 == i2)) # diagonal will be changed x <- diagU2N(x) # keeps class (!) } else toGeneral <- TRUE } if(toGeneral) { # go to "generalMatrix" and continue Matrix.message("M[i,j] <- v : coercing symmetric M[] into non-symmetric") x <- .M2gen(x) clDx <- getClassDef(clx <- class(x)) } ## TODO (efficiency): replace 'sel' by 'which(sel)' get.ind.sel <- function(ii,ij) (match(x@i, ii, nomatch = 0L) & match(x@j, ij, nomatch = 0L)) ## sel[k] := TRUE iff k-th non-zero entry (typically x@x[k]) is to be replaced sel <- get.ind.sel(i1,i2) has.x <- "x" %in% slotNames(clDx) # === slotNames(x) ## the simplest case: for all Tsparse, even for i or j missing if(.all0(value)) { ## just drop the non-zero entries if(any(sel)) { ## non-zero there x@i <- x@i[!sel] x@j <- x@j[!sel] if(has.x) x@x <- x@x[!sel] if(.hasSlot(x, "factors") && length(x@factors)) # drop cached ones x@factors <- list() } return(x) } ## else -- some( value != 0 ) -- if(lenV > lenRepl) stop("too many replacement values") ## now have lenV <= lenRepl if(!has.x && # <==> "n.TMatrix" ((iNA <- anyNA(value)) || value.not.logical)) warning(if(iNA) gettextf("x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE.", dQuote(clx)) else gettextf("x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.", dQuote(clx)), domain=NA) ## another simple, typical case: if(lenRepl == 1) { if(spV && has.x) value <- as(value, "vector") if(any(sel)) { ## non-zero there if(has.x) x@x[sel] <- value } else { ## new non-zero x@i <- c(x@i, i1) x@j <- c(x@j, i2) if(has.x) x@x <- c(x@x, value) } if(.hasSlot(x, "factors") && length(x@factors)) # drop cached ones x@factors <- list() return(x) } ### Otherwise, for large lenRepl, we get into trouble below if(lenRepl > 2^20) { # (somewhat arbitrary cutoff) ## FIXME: just for testing !! ## if(identical(Sys.getenv("USER"),"maechler") ## if(lenRepl > 2) { # __________ ___ JUST for testing! _______________ if(!isTRUE(getOption("Matrix.quiet"))) message(gettextf("x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrix"), domain = NA) return(replCmat4(.M2C(x), i1, i2, iMi=iMi, jMi=jMi, value = if(spV) value else as(value, "sparseVector"), spV = TRUE)) } ## if(r.sym) # value already adjusted, see above ## lenRepl <- length(value) # shorter (since only "triangle") if(!r.sym && lenV < lenRepl) value <- rep_len(value, lenRepl) ## now: length(value) == lenRepl {but value is sparseVector if it's "long" !} ## value[1:lenRepl]: which are structural 0 now, which not? ## v0 <- is0(value) ## - replaced by using isN0(as.vector(.)) on a typical small subset value[.] ## --> more efficient for sparse 'value' & large 'lenRepl' : ## FIXME [= FIXME(3) above]: ## ----- The use of seq_len(lenRepl) below is *still* inefficient ## (or impossible e.g. when lenRepl == 50000^2) ## and the vN0 <- isN0(as.vector(value[iI0])) is even more ... ## One idea: use "abIndex", (a very efficient storage of index vectors which are ## a concatenation of only a few arithmetic seq()ences use.abI <- isTRUE(getOption("Matrix.use.abIndex")) ## This 'use.abI' should later depend on the *dimension* of things ! ##>>> But for that, we need to implement the following abIndex - "methods": ##>>> [-n], [ ] , intersect(, ) ## and for intersect(): typically sort(), unique() & similar iI0 <- if(use.abI) abIseq1(1L, lenRepl) else seq_len(lenRepl) if(any(sel)) { ## the 0-based indices of non-zero entries -- WRT to submatrix iN0 <- 1L + .Call(m_encodeInd2, match(x@i[sel], i1), match(x@j[sel], i2), di = dind, orig1=TRUE, FALSE) ## 1a) replace those that are already non-zero with non-0 values vN0 <- isN0(value[iN0]) if(any(vN0) && has.x) { vv0 <- which(vN0) x@x[sel][vv0] <- as.vector(value[iN0[vv0]]) } ## 1b) replace non-zeros with 0 --> drop entries if(!all(vN0)) { ##-> ii will not be empty ii <- which(sel)[which(!vN0)] # <- vN0 may be sparseVector if(has.x) x@x <- x@x[-ii] x@i <- x@i[-ii] x@j <- x@j[-ii] } iI0 <- if(length(iN0) < lenRepl) iI0[-iN0] ## else NULL # == complementInd(non0, dind) } if(length(iI0)) { if(r.sym) { ## should only set new entries above / below diagonal, i.e., ## subset iI0 such as to contain only above/below .. iSel <- if(use.abI) abIindTri(dind[1], upper=xU, diag=TRUE) else indTri(dind[1], upper=xU, diag=TRUE) ## select also the corresponding triangle of values ### TODO for "abIndex" -- note we KNOW that both iI0 and iSel ### are strictly increasing : iI0 <- intersect(iI0, iSel) } full <- length(iI0) == lenRepl vN0 <- if(spV) ## "sparseVector" (if(full) value else value[iI0])@i else which(isN0(if(full) value else value[iI0])) if(length(vN0)) { ## 2) add those that were structural 0 (where value != 0) iIN0 <- if(full) vN0 else iI0[vN0] ij0 <- decodeInd(iIN0 - 1L, nr = dind[1]) x@i <- c(x@i, i1[ij0[,1] + 1L]) x@j <- c(x@j, i2[ij0[,2] + 1L]) if(has.x) x@x <- c(x@x, as.vector(value[iIN0])) } } if(.hasSlot(x, "factors") && length(x@factors)) # drop cached ones x@factors <- list() x } ## end{replTmat} ## A[ ij ] <- value, where ij is a matrix; typically (i,j) 2-column matrix : ## ---------------- ./Matrix.R has a general cheap method ## This one should become as fast as possible -- is also used from Csparse.R -- .TM.repl.i.mat <- function (x, i, j, ..., value) { nA <- nargs() if(nA != 3) stop(gettextf("nargs() = %d should never happen; please report.", nA), domain=NA) ## else: nA == 3 i.e., M [ cbind(ii,jj) ] <- value or M [ Lmat ] <- value if(is.logical(i)) { Matrix.message(".TM.repl.i.mat(): drop 'matrix' case ...", .M.level=2) ## c(i) : drop "matrix" to logical vector x[as.vector(i)] <- value return(x) } else if(extends1of(cli <- getClassDef(class(i)), c("lMatrix", "nMatrix"))) { Matrix.message(".TM.repl.i.mat(): \"lMatrix\" case ...", .M.level=2) i <- which(as(i, if(extends(cli, "sparseMatrix")) "sparseVector" else "vector")) ## x[i] <- value ; return(x) return(`[<-`(x,i, value=value)) } else if(extends(cli, "Matrix")) { # "dMatrix" or "iMatrix" if(ncol(i) != 2) stop("such indexing must be by logical or 2-column numeric matrix") i <- as(i, "matrix") } else if(!is.numeric(i) || ncol(i) != 2) stop("such indexing must be by logical or 2-column numeric matrix") if(!is.integer(i)) storage.mode(i) <- "integer" if(any(i < 0)) stop("negative values are not allowed in a matrix subscript") if(anyNA(i)) stop("NAs are not allowed in subscripted assignments") if(any(i0 <- (i == 0))) # remove them i <- i[ - which(i0, arr.ind = TRUE)[,"row"], ] if(length(attributes(i)) > 1) # more than just 'dim'; simplify: will use identical attributes(i) <- list(dim = dim(i)) ## now have integer i >= 1 m <- nrow(i) if(m == 0) return(x) if(length(value) == 0) stop("nothing to replace with") ## mod.x <- .type.kind[.M.kind(x)] if(length(value) != m) { ## use recycling rules if(m %% length(value) != 0) warning("number of items to replace is not a multiple of replacement length") value <- rep_len(value, m) } clx <- class(x) clDx <- getClassDef(clx) # extends() , is() etc all use the class definition stopifnot(extends(clDx, "TsparseMatrix")) di <- dim(x) nr <- di[1] nc <- di[2] i1 <- i[,1] i2 <- i[,2] if(any(i1 > nr)) stop(gettextf("row indices must be <= nrow(.) which is %d", nr), domain=NA) if(any(i2 > nc)) stop(gettextf("column indices must be <= ncol(.) which is %d", nc), domain=NA) ## Tmatrix maybe non-unique, have an entry split into a sum of several ones: x <- aggregateT(x) toGeneral <- FALSE isN <- extends(clDx, "nMatrix") if(r.sym <- extends(clDx, "symmetricMatrix")) { ## Tests to see if the assignments are symmetric as well r.sym <- all(i1 == i2) if(!r.sym) { # do have *some* Lower or Upper entries iL <- i1 > i2 iU <- i1 < i2 r.sym <- sum(iL) == sum(iU) # same number if(r.sym) { iLord <- order(i1[iL], i2[iL]) iUord <- order(i2[iU], i1[iU]) # row <-> col. ! r.sym <- { identical(i[iL, , drop=FALSE][iLord,], i[iU, 2:1, drop=FALSE][iUord,]) && all(value[iL][iLord] == value[iU][iUord]) } } } if(r.sym) { ## result is *still* symmetric --> keep symmetry! ## now consider only those indices above / below diagonal: useI <- if(x@uplo == "U") i1 <= i2 else i2 <= i1 i <- i[useI, , drop=FALSE] value <- value[useI] } else toGeneral <- TRUE } else if(extends(clDx, "triangularMatrix")) { r.tri <- all(if(x@uplo == "U") i1 <= i2 else i2 <= i1) if(r.tri) { ## result is *still* triangular if(any(ieq <- i1 == i2)) { # diagonal will be changed if(x@diag == "U" && all(ieq) && all(value == if(isN) TRUE else as1(x@x))) ## only diagonal values are set to 1 -- i.e. unchanged return(x) x <- diagU2N(x) # keeps class (!) } } else toGeneral <- TRUE } if(toGeneral) { # go to "generalMatrix" and continue Matrix.message("M[ij] <- v : coercing symmetric M[] into non-symmetric") x <- .M2gen(x) clDx <- getClassDef(clx <- class(x)) } ii.v <- .Call(m_encodeInd, i, di, orig1=TRUE, checkBounds = TRUE) if(id <- anyDuplicated(ii.v, fromLast=TRUE)) { Matrix.message("M[ij] <- v : duplicate ij-entries; using last") ii.v <- ii.v [-id] value <- value[-id] if(any(id <- duplicated(ii.v, fromLast=TRUE))) { nd <- -which(id) ii.v <- ii.v [nd] value <- value[nd] } } ii.x <- .Call(m_encodeInd2, x@i, x@j, di, FALSE, FALSE) m1 <- match(ii.v, ii.x) i.repl <- !is.na(m1) # those that need to be *replaced* if(isN) { ## no 'x' slot isN <- is.logical(value) # will result remain "nMatrix" ? if(!isN) x <- .M2kind(x, "d") } has.x <- !isN ## isN <===> "remains pattern matrix" <===> has no 'x' slot if(any(i.repl)) { ## some to replace at matching (@i, @j) if(has.x) x@x[m1[i.repl]] <- value[i.repl] else { # nMatrix ; eliminate entries that are set to FALSE; keep others if(any(isF <- is0(value[i.repl]))) { ii <- m1[i.repl][isF] x@i <- x@i[ -ii] x@j <- x@j[ -ii] } } } if(any(i.new <- !i.repl & isN0(value))) { ## some new entries i.j <- decodeInd(ii.v[i.new], nr) x@i <- c(x@i, i.j[,1]) x@j <- c(x@j, i.j[,2]) if(has.x) x@x <- c(x@x, value[i.new]) } if(.hasSlot(x, "factors") && length(x@factors)) # drop cached ones x@factors <- list() x } ## end{.TM.repl.i.mat} setMethod("[<-", c(x = "TsparseMatrix", i = "index", j = "missing", value = "replValue"), replTmat) setMethod("[<-", c(x = "TsparseMatrix", i = "missing", j = "index", value = "replValue"), replTmat) setMethod("[<-", c(x = "TsparseMatrix", i = "index", j = "index", value = "replValue"), replTmat) setMethod("[<-", c(x = "TsparseMatrix", i = "matrix", j = "missing", value = "replValue"), .TM.repl.i.mat) setMethod("[<-", c(x = "TsparseMatrix", i = "Matrix", j = "missing", value = "replValue"), .TM.repl.i.mat) ### When the RHS 'value' is a sparseVector, now can use replTmat as well setMethod("[<-", c(x = "TsparseMatrix", i = "missing", j = "index", value = "sparseVector"), replTmat) setMethod("[<-", c(x = "TsparseMatrix", i = "index", j = "missing", value = "sparseVector"), replTmat) setMethod("[<-", c(x = "TsparseMatrix", i = "index", j = "index", value = "sparseVector"), replTmat) ## ==== diagonalMatrix ================================================= ## When you assign to a diagonalMatrix, the result should be ## diagonal or sparse --- replDiag <- function(x, i, j, ..., value) { ## FIXME: if (i == j) && isSymmetric(value) then -- want symmetricMatrix result! -- or diagMatrix x <- .diag2sparse(x, ".", "g", "C") # was ->TsparseMatrix till 2012-07 if(missing(i)) x[, j] <- value else if(missing(j)) { ## x[i , ] <- v *OR* x[i] <- v na <- nargs() ## message("diagnosing replDiag() -- nargs()= ", na) if(na == 4L) x[i, ] <- value else if(na == 3L) x[i] <- value else stop(gettextf("Internal bug: nargs()=%d; please report", na), domain=NA) } else x[i,j] <- value ## TODO: the following is a bit expensive; have cases above e.g. [i,] where ## ----- we could check *much* faster : if(isDiagonal(x)) forceDiagonal(x) else if(isSymmetric(x)) forceSymmetric(x) else if(!(it <- isTriangular(x))) x else if(attr(it, "kind") == "U") triu(x) else tril(x) } setMethod("[<-", c(x = "diagonalMatrix", i = "index", j = "index", value = "replValue"), replDiag) setMethod("[<-", c(x = "diagonalMatrix", i = "index", j = "missing", value = "replValue"), function(x,i,j, ..., value) { ## message("before replDiag() -- nargs()= ", nargs()) if(nargs() == 3L) replDiag(x, i=i, value=value) else ## nargs() == 4 : replDiag(x, i=i, , value=value) }) setMethod("[<-", c(x = "diagonalMatrix", i = "missing", j = "index", value = "replValue"), function(x,i,j, ..., value) replDiag(x, j=j, value=value)) ## x[] <- value : setMethod("[<-", c(x = "diagonalMatrix", i = "missing", j = "missing", value = "ANY"), function(x,i,j, ..., value) { if(all0(value)) { # be faster r <- new(paste0(.M.kind(x), "tTMatrix")) # of all "0" r@Dim <- x@Dim r@Dimnames <- x@Dimnames r } else { ## typically non-sense: assigning to full sparseMatrix x[TRUE] <- value x } }) setMethod("[<-", c(x = "diagonalMatrix", i = "matrix", # 2-col.matrix j = "missing", value = "replValue"), function(x,i,j, ..., value) { if(ncol(i) == 2L) { if(all((ii <- i[,1L]) == i[,2L])) { ## replace in diagonal only if(x@diag == "U") { one <- as1(x@x) if(any(value != one | is.na(value))) { x@diag <- "N" x@x <- rep.int(one, x@Dim[1L]) } else return(x) } x@x[ii] <- value x } else { ## no longer diagonal, but remain sparse: ### FIXME: use uplo="U" or uplo="L" (or *not* "triangularMatrix") ### depending on LE <- i <= j ### all(LE) // all(!LE) // remaining cases x <- .diag2sparse(x, ".", "t", "C") # was ->TsparseMatrix x[i] <- value x } } else { # behave as "base R": use as if vector x <- as(x, "matrix") x[i] <- value Matrix(x) } }) ## value = "sparseMatrix": setMethod("[<-", c(x = "diagonalMatrix", i = "missing", j = "index", value = "sparseMatrix"), function (x, i, j, ..., value) callGeneric(x=x, , j=j, value=as(value, "sparseVector"))) setMethod("[<-", c(x = "diagonalMatrix", i = "index", j = "missing", value = "sparseMatrix"), function (x, i, j, ..., value) callGeneric(x=x, i=i, , value=as(value, "sparseVector"))) setMethod("[<-", c(x = "diagonalMatrix", i = "index", j = "index", value = "sparseMatrix"), function (x, i, j, ..., value) callGeneric(x=x, i=i, j=j, value=as(value, "sparseVector"))) ## value = "sparseVector": setMethod("[<-", c(x = "diagonalMatrix", i = "missing", j = "index", value = "sparseVector"), replDiag) setMethod("[<-", c(x = "diagonalMatrix", i = "index", j = "missing", value = "sparseVector"), replDiag) setMethod("[<-", c(x = "diagonalMatrix", i = "index", j = "index", value = "sparseVector"), replDiag) ## ==== indMatrix ====================================================== .indMatrix.sub <- function(x, i, j, ..., value) { x <- as(x, "TsparseMatrix") callGeneric() } for (.i in c("missing", "index")) for (.j in c("missing", "index")) setMethod("[<-", c(x = "indMatrix", i = .i, j = .j, value = "ANY"), .indMatrix.sub) rm(.indMatrix.sub, .i, .j) ## ==== sparseVector =================================================== ## This is a simplified intI() -- for sparseVector indexing: intIv <- function(i, n, cl.i = getClassDef(class(i))) { ### Note: undesirable to use this for negative indices; ### ---- using seq_len(n) below means we are NON-sparse ... ### Fixed, for "x[i] with negative i" at least. ## Purpose: translate numeric | logical index into 1-based integer ## -------------------------------------------------------------------- ## Arguments: i: index vector (numeric | logical) *OR* sparseVector ## n: array extent { == length(.) } if(missing(i)) seq_len(n) else if(extends(cl.i, "numeric")) { ## not ok, when max(i) > .Machine$integer.max ! storage.mode(i) <- "integer" int2i(i,n) ##-> ./Tsparse.R } else if (extends(cl.i, "logical")) { seq_len(n)[i] } else if(extends(cl.i, "nsparseVector")) { i@i # the indices are already there ! } else if(extends(cl.i, "lsparseVector")) { i@i[i@x] # "drop0", i.e. FALSE; NAs ok } else if (extends(cl.i, "sparseVector")) { ## 'i'sparse, 'd'sparse (etc) as.integer(i@x[i@i]) } else stop("index must be numeric, logical or sparseVector for indexing sparseVectors") } ## intIv() replSPvec <- function (x, i, value) { n <- x@length ii <- intIv(i, n) lenRepl <- length(ii) if(!lenRepl) return(x) ## else: lenRepl = length(ii) > 0 lenV <- length(value) if(lenV == 0) stop("nothing to replace with") ## else: lenV := length(value) > 0 if(lenRepl %% lenV != 0) stop("number of items to replace is not a multiple of replacement length") if(anyDuplicated(ii)) { ## multiple *replacement* indices: last one wins ## TODO: in R 2.6.0 use duplicate(*, fromLast=TRUE) ir <- lenRepl:1 keep <- match(ii, ii[ir]) == ir ii <- ii[keep] lenV <- length(value <- rep(value, length.out = lenRepl)[keep]) lenRepl <- length(ii) } has.x <- .hasSlot(x, "x")## has "x" slot m <- match(x@i, ii, nomatch = 0) sel <- m > 0L ## the simplest case if(all0(value)) { ## just drop the non-zero entries if(any(sel)) { ## non-zero there x@i <- x@i[!sel] if(has.x) x@x <- x@x[!sel] } return(x) } ## else -- some( value != 0 ) -- if(lenV > lenRepl) stop("too many replacement values") else if(lenV < lenRepl) value <- rep(value, length.out = lenRepl) ## now: length(value) == lenRepl > 0 v0 <- is0(value) ## value[1:lenRepl]: which are structural 0 now, which not? v.sp <- inherits(value, "sparseVector") if(any(sel)) { ## indices of non-zero entries -- WRT to subvector iN0 <- m[sel] ## == match(x@i[sel], ii) ## 1a) replace those that are already non-zero with new val. vN0 <- !v0[iN0] if(any(vN0) && has.x) { vs <- value[iN0[vN0]] x@x[sel][vN0] <- if(v.sp) sp2vec(vs, mode=typeof(x@x)) else vs } ## 1b) replace non-zeros with 0 --> drop entries if(any(!vN0)) { i <- which(sel)[!vN0] if(has.x) x@x <- x@x[-i] x@i <- x@i[-i] } iI0 <- if(length(iN0) < lenRepl) seq_len(lenRepl)[-iN0] # else NULL } else iI0 <- seq_len(lenRepl) if(length(iI0) && any(vN0 <- !v0[iI0])) { ## 2) add those that were structural 0 (where value != 0) ij0 <- iI0[vN0] ii <- c(x@i, ii[ij0]) # new x@i, must be sorted: iInc <- sort.list(ii) x@i <- ii[iInc] if(has.x) # new @x, sorted along '@i': x@x <- c(x@x, if(v.sp) sp2vec(value[ij0], mode=typeof(x@x)) else value[ij0] )[iInc] } x } setMethod("[<-", c(x = "sparseVector", i = "index", j = "missing", value = "ANY"), replSPvec) setMethod("[<-", c(x = "sparseVector", i = "sparseVector", j = "missing", value = "ANY"), ## BTW, the important case: 'i' a *logical* sparseVector replSPvec) Matrix/R/perm.R0000644000175100001440000000111114467055256013033 0ustar hornikusersinvertPerm <- function(p, off = 1L, ioff = 1L) .Call(R_invertPerm, as.integer(p), as.integer(off), as.integer(ioff)) signPerm <- function(p, off = 1L) .Call(R_signPerm, as.integer(p), as.integer(off)) isPerm <- function(p, off = 1L) .Call(R_isPerm, as.integer(p), as.integer(off)) asPerm <- function(pivot, off = 1L, ioff = 1L, n = length(pivot)) .Call(R_asPerm, as.integer(pivot), as.integer(off), as.integer(ioff), as.integer(n)) invPerm <- function(p, zero.p = FALSE, zero.res = FALSE) invertPerm(p, if(zero.p) 0L else 1L, if(zero.res) 0L else 1L) Matrix/R/all.equal.R0000644000175100001440000001644114565476715013770 0ustar hornikusers## METHODS FOR GENERIC: all.equal ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .V.a.e <- function(target, current, ...) { if((l1 <- length(target)) != (l2 <- length(current))) return(paste0("length(target) is ", l1, ", length(current) is ", l2)) if(is.integer(l1) || l1 <= .Machine$integer.max) { i1 <- as.integer( target@i) i2 <- as.integer(current@i) } else { i1 <- trunc( target@i) i2 <- trunc(current@i) } x1 <- if(.hasSlot( target, "x")) target@x else rep.int(TRUE, length(i1)) x2 <- if(.hasSlot(current, "x")) current@x else rep.int(TRUE, length(i2)) if(!identical(i1, i2)) { i3 <- sort.int(unique.default(c(i1, i2))) x1 <- replace(vector(typeof(x1), length(i3)), match(i1, i3, 0L), x1) x2 <- replace(vector(typeof(x2), length(i3)), match(i2, i3, 0L), x2) } all.equal(x1, x2, ...) } .M.attributes <- function(x, exclude.informal, exclude.factors) { a <- attributes(x) if(isS4(x) && exclude.informal) a <- a[.slotNames(a)] if(length(a) == 0L) return(NULL) exclude <- if(!isS4(x)) c("class", "dim", "dimnames") else if(.isMatrix(x)) c("class", "Dim", "Dimnames", switch(.M.repr(x), "C" = c("p", "i", if(.M.kind(x) != "n") "x"), "R" = c("p", "j", if(.M.kind(x) != "n") "x"), "T" = c("i", "j", if(.M.kind(x) != "n") "x"), "d" = , "u" = , "p" = "x", "i" = "perm"), switch(.M.shape(x), "g" = if(exclude.factors) "factors", "s" = c("uplo", if(exclude.factors) "factors"), "t" = c("uplo", "diag"), "d" = "diag", "i" = if(exclude.factors) "factors")) else "class" nms <- names(a) i <- match(nms, exclude, 0L) == 0L if(any(i)) a[sort.int(nms[i])] else NULL } .M.attr.all.equal <- function(target, current, check.type, check.class, check.attributes, check.factors, ...) { msg <- msg. <- NULL if(check.type && !identical(t1 <- typeof(target), t2 <- typeof(current))) msg <- c(msg, paste0("typeof(target) is ", deparse(t1), ", typeof(current) is ", deparse(t2))) if(check.class && !identical(c1 <- class(target), c2 <- class(current))) msg <- c(msg, paste0( "class(target) is ", deparse(c1), ", class(current) is ", deparse(c2))) if(is.na(check.attributes) || check.attributes) { if(!isTRUE(ae <- all.equal.raw(dim(target), dim(current), ...))) msg <- c(msg, paste0("dim: < ", ae, " >")) if(!isTRUE(ae <- all.equal.list(dimnames( target) %||% list(NULL, NULL), dimnames(current) %||% list(NULL, NULL), ...))) msg <- c(msg, paste0("dimnames: < ", ae, " >")) a1 <- .M.attributes( target, is.na(check.attributes), !check.factors) a2 <- .M.attributes(current, is.na(check.attributes), !check.factors) if(!((is.null(a1) && is.null(a2)) || isTRUE(ae <- all.equal.list(a1, a2, ...)))) msg <- msg. <- c(msg, paste0("Attributes: < ", ae, " >")) } list(msg, is.null(msg) != is.null(msg.)) } .M.all.equal <- function(target, current, check.type = check.class, check.class = TRUE, check.attributes = TRUE, check.factors = FALSE, ...) { msg <- .M.attr.all.equal(target, current, check.type = check.type, check.class = check.class, check.attributes = check.attributes, check.factors = check.factors, ...) if(!msg[[2L]]) { ae <- if(.isVector( target) || .isSparse( target) || .isVector(current) || .isSparse(current)) { v1 <- as( target, "sparseVector") v2 <- as(current, "sparseVector") ae <- .V.a.e(v1, v2, ...) } else { v1 <- as( target, "vector") v2 <- as(current, "vector") ae <- all.equal(v1, v2, ...) } if(!isTRUE(ae)) return(c(msg[[1L]], ae)) } if(is.null(msg[[1L]])) TRUE else msg[[1L]] } setMethod("all.equal", c(target = "Matrix", current = "vector"), .M.all.equal) setMethod("all.equal", c(target = "vector", current = "Matrix"), .M.all.equal) setMethod("all.equal", c(target = "Matrix", current = "Matrix"), .M.all.equal) ## And for completeness: setMethod("all.equal", c(target = "Matrix", current = "sparseVector"), .M.all.equal) .V.attributes <- function(x, exclude.informal) { a <- attributes(x) if(isS4(x) && exclude.informal) a <- a[.slotNames(a)] if(length(a) == 0L) return(NULL) exclude <- if(.isVector(x)) c("class", "length", "i", if(.M.kind(x) != "n") "x") else "class" nms <- names(a) i <- match(nms, exclude, 0L) == 0L if(any(i)) a[sort.int(nms[i])] else NULL } .V.attr.all.equal <- function(target, current, check.type, check.class, check.attributes, ...) { msg <- msg. <- NULL if(check.type && !identical(t1 <- typeof(target), t2 <- typeof(current))) msg <- c(msg, paste0("typeof(target) is ", deparse(t1), ", typeof(current) is ", deparse(t2))) if(check.class && !identical(c1 <- class(target), c2 <- class(current))) msg <- c(msg, paste0( "class(target) is ", deparse(c1), ", class(current) is ", deparse(c2))) if(is.na(check.attributes) || check.attributes) { if((l1 <- length(target)) != (l2 <- length(current))) msg <- c(msg, paste0("length(target) is ", l1, ", length(current) is ", l2)) a1 <- .V.attributes( target, is.na(check.attributes)) a2 <- .V.attributes(current, is.na(check.attributes)) if(!((is.null(a1) && is.null(a2)) || isTRUE(ae <- all.equal.list(a1, a2, ...)))) msg <- msg. <- c(msg, paste0("Attributes: < ", ae, " >")) } list(msg, is.null(msg) != is.null(msg.)) } .V.all.equal <- function(target, current, check.type = check.class, check.class = TRUE, check.attributes = TRUE, ...) { msg <- .V.attr.all.equal(target, current, check.type = check.type, check.class = check.class, check.attributes = check.attributes, ...) if(!msg[[2L]]) { if(.isVector( target) || .isSparse( target) || .isVector(current) || .isSparse(current)) { v1 <- as( target, "sparseVector") v2 <- as(current, "sparseVector") ae <- .V.a.e(v1, v2, ...) } else { v1 <- as( target, "vector") v2 <- as(current, "vector") ae <- all.equal(v1, v2, ...) } if(!isTRUE(ae)) return(c(msg[[1L]], ae)) } if(is.null(msg[[1L]])) TRUE else msg[[1L]] } setMethod("all.equal", c(target = "sparseVector", current = "vector"), .V.all.equal) setMethod("all.equal", c(target = "vector", current = "sparseVector"), .V.all.equal) setMethod("all.equal", c(target = "sparseVector", current = "sparseVector"), .V.all.equal) ## And for completeness: setMethod("all.equal", c(target = "sparseVector", current = "Matrix"), .V.all.equal) Matrix/R/coerce-graph.R0000644000175100001440000001416414565441013014430 0ustar hornikusers## METHODS ENHANCING PACKAGE: graph ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## README: These need package 'graph', from which we do not import, ## _on purpose_. Hence we must use graph:: in case 'graph' ## is only loaded, not attached ... ## NB: undirected graph <==> symmetric matrix ## ~~~~ UTILITIES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## NB: These may no longer be needed in future versions of 'graph' graph.has.weights <- function(g) "weight" %in% names(graph::edgeDataDefaults(g)) graph.non.1.weights <- function(g) any(unlist(graph::edgeData(g, attr = "weight")) != 1) graph.wgtMatrix <- function(g) { ## Purpose: work around "graph" package's as(g, "matrix") bug ## ---------------------------------------------------------------------- ## Arguments: g: an object inheriting from (S4) class "graph" ## ---------------------------------------------------------------------- ## Author: Martin Maechler, based on Seth Falcon's code; Date: 12 May 2006 ## MM: another buglet for the case of "no edges": if(graph::numEdges(g) == 0) { p <- length(nd <- graph::nodes(g)) return( matrix(0, p,p, dimnames = list(nd, nd)) ) } ## Usual case, when there are edges: if(has.w <- graph.has.weights(g)) { ## graph.non.1.weights(g) : w <- unlist(graph::edgeData(g, attr = "weight")) has.w <- any(w != 1) } ## now 'has.w' is TRUE iff there are weights != 1 m <- as(g, "matrix") ## now is a 0/1 - matrix (instead of 0/wgts) with the 'graph' bug if(has.w) { ## fix it if needed tm <- t(m) tm[tm != 0] <- w t(tm) } else m } graph2T <- function(from, use.weights = graph.has.weights(from) && graph.non.1.weights(from)) { nd <- graph::nodes(from); dnms <- list(nd,nd) dm <- rep.int(length(nd), 2) edge2i <- function(e) { ## return (0-based) row indices 'i' rep.int(0:(dm[1]-1L), lengths(e)) } if(use.weights) { eWts <- graph::edgeWeights(from); names(eWts) <- NULL i <- edge2i(eWts) To <- unlist(lapply(eWts, names)) j <- as.integer(match(To,nd)) - 1L # columns indices (0-based) ## symm <- symm && : improbable ## if(symm) new("dsTMatrix", .....) else new("dgTMatrix", i = i, j = j, x = unlist(eWts), Dim = dm, Dimnames = dnms) } else { ## no weights: 0/1 matrix -> pattern edges <- lapply(from@edgeL[nd], "[[", "edges") symm <- graph::edgemode(from) == "undirected" if(symm)# each edge appears twice; keep upper triangle only edges <- lapply(seq_along(edges), function(i) {e <- edges[[i]]; e[e >= i]}) i <- edge2i(edges) j <- as.integer(unlist(edges)) - 1L # column indices (0-based) ## if(symm) { # symmetric: ensure upper triangle ## tmp <- i ## flip <- i > j ## i[flip] <- j[flip] ## j[flip] <- tmp[flip] ## new("nsTMatrix", i = i, j = j, Dim = dm, Dimnames = dnms, ## uplo = "U") ## } else { ## new("ngTMatrix", i = i, j = j, Dim = dm, Dimnames = dnms) ## } new(if(symm) "nsTMatrix" else "ngTMatrix", i = i, j = j, Dim = dm, Dimnames = dnms)# uplo = "U" is default } } T2graph <- function(from, need.uniq = !isUniqueT(from), edgemode = NULL) { d <- dim(from) if((n <- d[1L]) != d[2L]) stop("only square matrices can be used as graph incidence matrices") if(n == 0L) return(new("graphNEL")) if(is.null(rn <- dimnames(from)[[1]])) rn <- as.character(1:n) if(need.uniq) ## Need to 'uniquify' the triplets! from <- .M2T(.M2C(from)) if(is.null(edgemode)) edgemode <- if(isSymmetric(from)) { # either "symmetricMatrix" or otherwise ##-> undirected graph: every edge only once! if(!is(from, "symmetricMatrix")) { ## a general matrix which happens to be symmetric ## ==> remove the double indices from <- tril(from) } "undirected" } else { "directed" } ## every edge is there only once, either upper or lower triangle ft1 <- cbind(rn[from@i + 1L], rn[from@j + 1L]) graph::ftM2graphNEL(ft1, W = if(.hasSlot(from,"x")) as.numeric(from@x), V = rn, edgemode = edgemode) } ## ~~~~ COERCIONS FROM graph TO Matrix ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setAs("graphAM", "TsparseMatrix", function(from) { symm <- graph::edgemode(from) == "undirected" && isSymmetric(from@adjMat) if(graph.has.weights(from)) .m2sparse(graph.wgtMatrix(from), if(symm) "dsT" else "dgT") else ## no weights: 0/1 matrix -> pattern .m2sparse( as(from, "matrix"), if(symm) "nsT" else "ngT") }) setAs("graphNEL", "TsparseMatrix", function(from) graph2T(from)) setAs("graph", "CsparseMatrix", function(from) .M2C(graph2T(as(from, "graphNEL")))) setAs("graph", "RsparseMatrix", function(from) .M2R(graph2T(as(from, "graphNEL")))) setAs("graph", "TsparseMatrix", function(from) graph2T(as(from, "graphNEL")) ) setAs("graph", "sparseMatrix", function(from) .M2C(graph2T(as(from, "graphNEL")))) setAs("graph", "Matrix", function(from) .M2C(graph2T(as(from, "graphNEL")))) ## ~~~~ COERCIONS FROM Matrix TO graph ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## NB: Since we have a method for TsparseMatrix (below), the method ## for Matrix can assume that 'from' is _not_ a TsparseMatrix, ## and therefore expect that as(from, "TsparseMatrix") is "unique" setAs("TsparseMatrix", "graphNEL", function(from) T2graph( from )) setAs("Matrix", "graphNEL", function(from) T2graph(.M2T(from), need.uniq = FALSE)) setAs("Matrix", "graph", function(from) T2graph(.M2T(from), need.uniq = FALSE)) Matrix/R/HBMM.R0000644000175100001440000002004014574651323012611 0ustar hornikusers## Utilities for the Harwell-Boeing and MatrixMarket formats readone <- function(ln, iwd, nper, conv) { ln <- gsub("D", "E", ln) inds <- seq(0, by = iwd, length.out = nper + 1) (conv)(substring(ln, 1 + inds[-length(inds)], inds[-1])) } readmany <- function(conn, nlines, nvals, fmt, conv) { if (!grep("[[:digit:]]+[DEFGI][[:digit:]]+", fmt)) stop("Not a valid format") Iind <- regexpr('[DEFGI]', fmt) nper <- as.integer(substr(fmt, regexpr('[[:digit:]]+[DEFGI]', fmt), Iind - 1)) iwd <- as.integer(substr(fmt, Iind + 1, regexpr('[\\.\\)]', fmt) - 1)) rem <- nvals %% nper full <- nvals %/% nper ans <- vector("list", nvals %/% nper) for (i in seq_len(full)) ans[[i]] <- readone(readLines(conn, 1, ok = FALSE), iwd, nper, conv) if (!rem) return(unlist(ans)) c(unlist(ans), readone(readLines(conn, 1, ok = FALSE), iwd, rem, conv)) } readHB <- function(file) { if (is.character(file)) file <- if (file == "") stdin() else file(file) if (!inherits(file, "connection")) stop("'file' must be a character string or connection") if (!isOpen(file)) { open(file) on.exit(close(file)) } hdr <- readLines(file, 4, ok = FALSE) ## Title <- sub('[[:space:]]+$', '', substr(hdr[1], 1, 72)) ## Key <- sub('[[:space:]]+$', '', substr(hdr[1], 73, 80)) ## totln <- as.integer(substr(hdr[2], 1, 14)) ptrln <- as.integer(substr(hdr[2], 15, 28)) indln <- as.integer(substr(hdr[2], 29, 42)) valln <- as.integer(substr(hdr[2], 43, 56)) rhsln <- as.integer(substr(hdr[2], 57, 70)) if (!(t1 <- substr(hdr[3], 1, 1)) %in% c('C', 'R', 'P')) stop(gettextf("Invalid storage type: %s", t1), domain=NA) if (t1 != 'R') stop("Only numeric sparse matrices allowed") ## _FIXME: Patterns should also be allowed if (!(t2 <- substr(hdr[3], 2, 2)) %in% c('H', 'R', 'S', 'U', 'Z')) stop(gettextf("Invalid storage format: %s", t2), domain=NA) if (!(t3 <- substr(hdr[3], 3, 3)) %in% c('A', 'E')) stop(gettextf("Invalid assembled indicator: %s", t3), domain=NA) nr <- as.integer(substr(hdr[3], 15, 28)) nc <- as.integer(substr(hdr[3], 29, 42)) nz <- as.integer(substr(hdr[3], 43, 56)) ## nel <- as.integer(substr(hdr[3], 57, 70)) ptrfmt <- toupper(sub('[[:space:]]+$', '', substr(hdr[4], 1, 16))) indfmt <- toupper(sub('[[:space:]]+$', '', substr(hdr[4], 17, 32))) valfmt <- toupper(sub('[[:space:]]+$', '', substr(hdr[4], 33, 52))) ## rhsfmt <- toupper(sub('[[:space:]]+$', '', substr(hdr[4], 53, 72))) if (!is.na(rhsln) && rhsln > 0) readLines(file, 1, ok = FALSE) # h5 ptr <- readmany(file, ptrln, nc + 1, ptrfmt, as.integer) ind <- readmany(file, indln, nz, indfmt, as.integer) vals <- readmany(file, valln, nz, valfmt, as.numeric) if (t2 == 'S') new("dsCMatrix", uplo = "L", p = ptr - 1L, i = ind - 1L, x = vals, Dim = c(nr, nc)) else new("dgCMatrix", p = ptr - 1L, i = ind - 1L, x = vals, Dim = c(nr, nc)) } readMM <- function(file) { if (is.character(file)) file <- if(file == "") stdin() else file(file) if (!inherits(file, "connection")) stop("'file' must be a character string or connection") if (!isOpen(file)) { open(file) on.exit(close(file)) } scan1 <- function(what, ...) scan(file, nmax = 1, what = what, quiet = TRUE, ...) if (scan1(character()) != "%%MatrixMarket")# hdr stop("file is not a MatrixMarket file") if (!(typ <- tolower(scan1(character()))) %in% "matrix") stop(gettextf("type '%s' not recognized", typ), domain = NA) if (!(repr <- tolower(scan1(character()))) %in% c("coordinate", "array")) stop(gettextf("representation '%s' not recognized", repr), domain = NA) elt <- tolower(scan1(character())) if (!elt %in% c("real", "complex", "integer", "pattern")) stop(gettextf("element type '%s' not recognized", elt), domain = NA) sym <- tolower(scan1(character())) if (!sym %in% c("general", "symmetric", "skew-symmetric", "hermitian")) stop(gettextf("symmetry form '%s' not recognized", sym), domain = NA) nr <- scan1(integer(), comment.char = "%") nc <- scan1(integer()) nz <- scan1(integer()) checkIJ <- function(els) { if((nz. <- length(els$i)) < nz) warning(gettextf("readMM(): expected %d entries but found only %d", nz, nz.), call. = FALSE, domain = NA) if(any(is.na(els$i) | els$i < 1L | els$i > nr)) stop(gettextf("readMM(): row indices 'i' are not in 1:nrow[=%d]", nr), call. = FALSE, domain = NA) if(any(is.na(els$j) | els$j < 1L | els$j > nc)) stop(gettextf("readMM(): column indices 'j' are not in 1:ncol[=%d]", nc), call. = FALSE, domain = NA) } if (repr == "coordinate") { switch(elt, "real" = , "integer" = { ## TODO: the "integer" element type should be returned as ## an object of an "iMatrix" subclass--once there are els <- scan(file, nmax = nz, quiet = TRUE, what= list(i= integer(), j= integer(), x= numeric())) checkIJ(els) switch(sym, "general" = { new("dgTMatrix", Dim = c(nr, nc), i = els$i - 1L, j = els$j - 1L, x = els$x) }, "symmetric" = { new("dsTMatrix", uplo = "L", Dim = c(nr, nc), i = els$i - 1L, j = els$j - 1L, x = els$x) }, "skew-symmetric" = { stop("symmetry form 'skew-symmetric' not yet implemented for reading") ## FIXME: use dgT... but must expand the (i,j,x) slots! new("dgTMatrix", uplo = "L", Dim = c(nr, nc), i = els$i - 1L, j = els$j - 1L, x = els$x) }, "hermitian" = { stop("symmetry form 'hermitian' not yet implemented for reading") }, ## otherwise (not possible; just defensive programming): stop(gettextf("symmetry form '%s' is not yet implemented", sym), domain = NA) ) }, "pattern" = { els <- scan(file, nmax = nz, quiet = TRUE, what = list(i = integer(), j = integer())) checkIJ(els) switch(sym, "general" = { new("ngTMatrix", Dim = c(nr, nc), i = els$i - 1L, j = els$j - 1L) }, "symmetric" = { new("nsTMatrix", uplo = "L", Dim = c(nr, nc), i = els$i - 1L, j = els$j - 1L) }, "skew-symmetric" = { stop("symmetry form 'skew-symmetric' not yet implemented for reading") ## FIXME: use dgT... but must expand the (i,j,x) slots! new("ngTMatrix", uplo = "L", Dim = c(nr, nc), i = els$i - 1L, j = els$j - 1L) }, "hermitian" = { stop("symmetry form 'hermitian' not yet implemented for reading") }, ## otherwise (not possible; just defensive programming): stop(gettextf("symmetry form '%s' is not yet implemented", sym), domain = NA) ) }, "complex" = { stop("element type 'complex' not yet implemented") }, ## otherwise (not possible currently): stop(gettextf("'%s()' is not yet implemented for element type '%s'", "readMM", elt), domain = NA)) } else stop(gettextf("'%s()' is not yet implemented for representation '%s'", "readMM", repr), domain = NA) } setMethod("writeMM", c(obj = "CsparseMatrix"), function(obj, file, ...) .Call(Csparse_writeMM, obj, path.expand(as.character(file)))) setMethod("writeMM", c(obj = "sparseMatrix"), function(obj, file, ...) writeMM(.M2C(obj), file, ...)) Matrix/R/matmult.R0000644000175100001440000017174314575137654013601 0ustar hornikusersmatmultDim <- function(d.a, d.b, type = 1L) { ## Return the 'dim' of the product indicated by 'type': ## type 1: a %*% b ## 2: t(a) %*% b { crossprod} ## 3: a %*% t(b) {tcrossprod} ## after asserting that ncol() == nrow() i.a <- 1L + (type != 2L) i.b <- 1L + (type == 3L) if(d.a[i.a] != d.b[i.b]) stop("non-conformable arguments") c(d.a[-i.a], d.b[-i.b]) } matmultDN <- function(dn.a, dn.b, type = 1L) ## Return the 'dimnames' of the product indicated by 'type': ## type 1: a %*% b ## 2: t(a) %*% b { crossprod} ## 3: a %*% t(b) {tcrossprod} c(if(is.null(dn.a)) list(NULL) else dn.a[2L - (type != 2L)], if(is.null(dn.b)) list(NULL) else dn.b[2L - (type == 3L)]) ## METHODS FOR GENERIC: %*% ## NB: x %*% y == t(t(y) %*% t(x)) ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for(.cl in c("Matrix", "sparseVector")) { setMethod("%*%", c(x = .cl, y = "ANY"), function(x, y) x %*% (if(length(dim(y)) == 2L) as.matrix else as.vector)(y)) setMethod("%*%", c(x = "ANY", y = .cl), function(x, y) (if(length(dim(x)) == 2L) as.matrix else as.vector)(x) %*% y) } ## .... denseMatrix .................................................... setMethod("%*%", c(x = "denseMatrix", y = "denseMatrix"), function(x, y) .Call(R_dense_matmult, x, y, FALSE, FALSE)) for(.cl in c("matrix", "vector")) { setMethod("%*%", c(x = "denseMatrix", y = .cl), function(x, y) .Call(R_dense_matmult, x, y, FALSE, FALSE)) setMethod("%*%", c(x = .cl, y = "denseMatrix"), function(x, y) .Call(R_dense_matmult, x, y, FALSE, FALSE)) } ## .... CsparseMatrix .................................................. setMethod("%*%", c(x = "CsparseMatrix", y = "CsparseMatrix"), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, FALSE)) setMethod("%*%", c(x = "CsparseMatrix", y = "RsparseMatrix"), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, FALSE)) setMethod("%*%", c(x = "CsparseMatrix", y = "TsparseMatrix"), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, FALSE)) for(.cl in c("denseMatrix", "matrix", "vector")) { setMethod("%*%", c(x = "CsparseMatrix", y = .cl), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, FALSE)) setMethod("%*%", c(x = .cl, y = "CsparseMatrix"), function(x, y) .Call(R_sparse_matmult, y, x, TRUE, TRUE, TRUE, FALSE)) } ## .... RsparseMatrix .................................................. setMethod("%*%", c(x = "RsparseMatrix", y = "CsparseMatrix"), function(x, y) .Call(R_sparse_matmult, y, x, TRUE, TRUE, TRUE, FALSE)) setMethod("%*%", c(x = "RsparseMatrix", y = "RsparseMatrix"), function(x, y) .Call(R_sparse_matmult, y, x, TRUE, TRUE, TRUE, FALSE)) setMethod("%*%", c(x = "RsparseMatrix", y = "TsparseMatrix"), function(x, y) .Call(R_sparse_matmult, y, x, TRUE, TRUE, TRUE, FALSE)) for(.cl in c("denseMatrix", "matrix", "vector")) { setMethod("%*%", c(x = "RsparseMatrix", y = .cl), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, FALSE)) setMethod("%*%", c(x = .cl, y = "RsparseMatrix"), function(x, y) .Call(R_sparse_matmult, y, x, TRUE, TRUE, TRUE, FALSE)) } ## .... TsparseMatrix .................................................. setMethod("%*%", c(x = "TsparseMatrix", y = "CsparseMatrix"), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, FALSE)) setMethod("%*%", c(x = "TsparseMatrix", y = "RsparseMatrix"), function(x, y) .Call(R_sparse_matmult, y, x, TRUE, TRUE, TRUE, FALSE)) setMethod("%*%", c(x = "TsparseMatrix", y = "TsparseMatrix"), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, FALSE)) for(.cl in c("denseMatrix", "matrix", "vector")) { setMethod("%*%", c(x = "TsparseMatrix", y = .cl), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, FALSE)) setMethod("%*%", c(x = .cl, y = "TsparseMatrix"), function(x, y) .Call(R_sparse_matmult, y, x, TRUE, TRUE, TRUE, FALSE)) } ## .... diagonalMatrix ................................................. setMethod("%*%", c(x = "diagonalMatrix", y = "diagonalMatrix"), function(x, y) { r <- new("ddiMatrix") r@Dim <- matmultDim(x@Dim, y@Dim, type = 1L) r@Dimnames <- matmultDN(x@Dimnames, y@Dimnames, type = 1L) xu <- x@diag != "N" yu <- y@diag != "N" if(xu && yu) r@diag <- "U" else { if(!xu) { xii <- x@x if(.M.kind(x) == "n" && anyNA(xii)) xii <- xii | is.na(xii) } if(!yu) { yii <- y@x if(.M.kind(y) == "n" && anyNA(yii)) yii <- yii | is.na(yii) } r@x <- if(xu) as.double(yii) else if(yu) as.double(xii) else as.double(xii * yii) } r }) for(.cl in c("CsparseMatrix", "RsparseMatrix", "TsparseMatrix", "denseMatrix", "matrix", "vector")) { setMethod("%*%", c(x = "diagonalMatrix", y = .cl), function(x, y) .Call(R_diagonal_matmult, x, y, FALSE, FALSE, FALSE)) setMethod("%*%", c(x = .cl, y = "diagonalMatrix"), function(x, y) .Call(R_diagonal_matmult, x, y, FALSE, FALSE, FALSE)) } ## .... indMatrix ...................................................... setMethod("%*%", c(x = "indMatrix", y = "indMatrix"), function(x, y) { mx <- x@margin my <- y@margin px <- x@perm py <- y@perm r <- new(if(mx == my) "indMatrix" else if(mx == 1L) "dgeMatrix" else "dgTMatrix") r@Dim <- matmultDim(x@Dim, y@Dim, type = 1L) r@Dimnames <- matmultDN(x@Dimnames, y@Dimnames, type = 1L) if(mx == my) r@perm <- if(mx == 1L) py[px] else { r@margin <- 2L; px[py] } else if(mx == 1L) r@x <- as.double(px == rep(py, each = length(px))) else { r@i <- px - 1L r@j <- py - 1L r@x <- rep.int(1, length(px)) } r }) setMethod("%*%", c(x = "indMatrix", y = "Matrix"), function(x, y) { if(x@margin != 1L) return(.M2kind(x, "d") %*% y) matmultDim(x@Dim, y@Dim, type = 1L) r <- .M2kind(y[x@perm, , drop = FALSE], ",") r@Dimnames <- matmultDN(x@Dimnames, dimnames(y), type = 1L) r }) setMethod("%*%", c(x = "Matrix", y = "indMatrix"), function(x, y) { if(y@margin == 1L) return(x %*% .M2kind(y, "d")) matmultDim(x@Dim, y@Dim, type = 1L) r <- .M2kind(x[, y@perm, drop = FALSE], ",") r@Dimnames <- matmultDN(dimnames(x), y@Dimnames, type = 1L) r }) setMethod("%*%", c(x = "indMatrix", y = "matrix"), function(x, y) { if(x@margin != 1L) return(.M2kind(x, "d") %*% y) matmultDim(x@Dim, dim(y), type = 1L) r <- .m2dense(y[x@perm, , drop = FALSE], ",ge") r@Dimnames <- matmultDN(x@Dimnames, dimnames(y), type = 1L) r }) setMethod("%*%", c(x = "matrix", y = "indMatrix"), function(x, y) { if(y@margin == 1L) return(x %*% .M2kind(y, "d")) matmultDim(dim(x), y@Dim, type = 1L) r <- .m2dense(x[, y@perm, drop = FALSE], ",ge") r@Dimnames <- matmultDN(dimnames(x), y@Dimnames, type = 1L) r }) setMethod("%*%", c(x = "indMatrix", y = "vector"), function(x, y) { if(x@margin != 1L) return(.M2kind(x, "d") %*% y) k <- (d <- x@Dim)[2L] r <- if(k == length(y)) .m2dense(y[x@perm], ",ge") else if(k == 1L) .m2dense(matrix(y, d[1L], length(y), byrow = TRUE), ",ge") else stop("non-conformable arguments") r@Dimnames <- c(x@Dimnames[1L], list(NULL)) r }) setMethod("%*%", c(x = "vector", y = "indMatrix"), function(x, y) { if(y@margin == 1L) return(x %*% .M2kind(y, "d")) k <- (d <- y@Dim)[1L] r <- if(k == length(x)) .m2dense(x[y@perm], ",ge", trans = TRUE) else if(k == 1L) .m2dense(matrix(x, length(x), d[2L]), ",ge") else stop("non-conformable arguments") r@Dimnames <- c(list(NULL), y@Dimnames[2L]) r }) ## .... pMatrix ........................................................ setMethod("%*%", c(x = "pMatrix", y = "pMatrix"), function(x, y) { r <- new("pMatrix") r@Dim <- matmultDim(x@Dim, y@Dim, type = 1L) r@Dimnames <- matmultDN(x@Dimnames, y@Dimnames, type = 1L) r@perm <- if(y@margin == 1L) y@perm[if(x@margin == 1L) x@perm else invertPerm(x@perm)] else { r@margin <- 2L (if(x@margin == 1L) invertPerm(x@perm) else x@perm)[y@perm] } r }) setMethod("%*%", c(x = "pMatrix", y = "indMatrix"), function(x, y) { r <- new("indMatrix") r@Dim <- matmultDim(x@Dim, y@Dim, type = 1L) r@Dimnames <- matmultDN(x@Dimnames, y@Dimnames, type = 1L) r@perm <- if(y@margin == 1L) y@perm[if(x@margin == 1L) x@perm else invertPerm(x@perm)] else { r@margin <- 2L (if(x@margin == 1L) invertPerm(x@perm) else x@perm)[y@perm] } r }) setMethod("%*%", c(x = "indMatrix", y = "pMatrix"), function(x, y) { r <- new("indMatrix") r@Dim <- matmultDim(x@Dim, y@Dim, type = 1L) r@Dimnames <- matmultDN(x@Dimnames, y@Dimnames, type = 1L) r@perm <- if(x@margin == 1L) (if(y@margin == 1L) y@perm else invertPerm(y@perm))[x@perm] else { r@margin <- 2L x@perm[if(y@margin == 1L) invertPerm(x@perm) else y@perm] } r }) setMethod("%*%", c(x = "pMatrix", y = "Matrix"), function(x, y) { matmultDim(x@Dim, y@Dim, type = 1L) perm <- if(x@margin == 1L) x@perm else invertPerm(x@perm) r <- .M2kind(y[perm, , drop = FALSE], ",") r@Dimnames <- matmultDN(x@Dimnames, dimnames(y), type = 1L) r }) setMethod("%*%", c(x = "Matrix", y = "pMatrix"), function(x, y) { matmultDim(x@Dim, y@Dim, type = 1L) perm <- if(y@margin == 1L) invertPerm(y@perm) else y@perm r <- .M2kind(x[, perm, drop = FALSE], ",") r@Dimnames <- matmultDN(dimnames(x), y@Dimnames, type = 1L) r }) setMethod("%*%", c(x = "pMatrix", y = "matrix"), function(x, y) { matmultDim(x@Dim, dim(y), type = 1L) perm <- if(x@margin == 1L) x@perm else invertPerm(x@perm) r <- .m2dense(y[perm, , drop = FALSE], ",ge") r@Dimnames <- matmultDN(x@Dimnames, dimnames(y), type = 1L) r }) setMethod("%*%", c(x = "matrix", y = "pMatrix"), function(x, y) { matmultDim(dim(x), y@Dim, type = 1L) perm <- if(y@margin == 1L) invertPerm(y@perm) else y@perm r <- .m2dense(x[, perm, drop = FALSE], ",ge") r@Dimnames <- matmultDN(dimnames(x), y@Dimnames, type = 1L) r }) setMethod("%*%", c(x = "pMatrix", y = "vector"), function(x, y) { k <- x@Dim[2L] r <- if(k == length(y)) { perm <- if(x@margin == 1L) x@perm else invertPerm(x@perm) .m2dense(y[perm], ",ge") } else if(k == 1L) .m2dense(y, ",ge", trans = TRUE) else stop("non-conformable arguments") r@Dimnames <- c(x@Dimnames[1L], list(NULL)) r }) setMethod("%*%", c(x = "vector", y = "pMatrix"), function(x, y) { k <- y@Dim[1L] r <- if(k == length(x)) { perm <- if(y@margin == 1L) invertPerm(y@perm) else y@perm .m2dense(x[perm], ",ge", trans = TRUE) } else if(k == 1L) .m2dense(x, ",ge") else stop("non-conformable arguments") r@Dimnames <- c(list(NULL), y@Dimnames[2L]) r }) ## .... sparseVector ................................................... setMethod("%*%", c(x = "sparseVector", y = "sparseVector"), function(x, y) if((nx <- length(x)) == 1L) .tCRT(.V2C(x * y)) else if(nx == length(y)) ## else if((ny <- length(y)) == 1L) ## .V2C(x * y) ## else if(nx == ny) .m2sparse(sum(x * y), ",gR") else stop("non-conformable arguments")) for(.cl in c("Matrix", "matrix")) { setMethod("%*%", c(x = "sparseVector", y = .cl), function(x, y) if((k <- dim(y)[1L]) == length(x)) .tCRT(.V2C(x)) %*% y else if(k == 1L) .V2C(x) %*% y else stop("non-conformable arguments")) setMethod("%*%", c(x = .cl, y = "sparseVector"), function(x, y) if((k <- dim(x)[2L]) == length(y)) x %*% .V2C(y) else if(k == 1L) x %*% .tCRT(.V2C(y)) else stop("non-conformable arguments")) } setMethod("%*%", c(x = "sparseVector", y = "vector"), function(x, y) if((nx <- length(x)) == 1L) .m2dense(.V2v(x * y), ",ge", trans = TRUE) else if(nx == length(y)) ## else if((ny <- length(y)) == 1L) ## .m2dense(.V2v(x * y), ",ge") ## else if(nx == ny) .m2dense(sum(x * y), ",ge") else stop("non-conformable arguments")) setMethod("%*%", c(x = "vector", y = "sparseVector"), function(x, y) if((nx <- length(x)) == 1L) .m2dense(.V2v(x * y), ",ge", trans = TRUE) else if(nx == length(y)) ## else if((ny <- length(y)) == 1L) ## .m2dense(.V2v(x * y), ",ge") ## else if(nx == ny) .m2dense(sum(x * y), ",ge") else stop("non-conformable arguments")) ## METHODS FOR GENERIC: %&% ## NB: x %*% y == t(t(y) %*% t(x)) ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("%&%", c(x = "ANY", y = "ANY"), function(x, y) (if(length(dim(x)) == 2L) as.matrix else as.vector)(x) %&% (if(length(dim(y)) == 2L) as.matrix else as.vector)(y)) for(.cl in c("Matrix", "sparseVector", "matrix", "vector")) { setMethod("%&%", c(x = .cl, y = "ANY"), function(x, y) x %&% (if(length(dim(y)) == 2L) as.matrix else as.vector)(y)) setMethod("%&%", c(x = "ANY", y = .cl), function(x, y) (if(length(dim(x)) == 2L) as.matrix else as.vector)(x) %&% y) } setMethod("%&%", c(x = "matrix", y = "matrix"), function(x, y) .m2sparse(x, "ngC") %&% .m2sparse(y, "ngC")) setMethod("%&%", c(x = "matrix", y = "vector"), function(x, y) .m2sparse(x, "ngC") %&% y ) setMethod("%&%", c(x = "vector", y = "matrix"), function(x, y) x %&% .m2sparse(y, "ngC")) setMethod("%&%", c(x = "vector", y = "vector"), function(x, y) { r <- if((nx <- length(x)) == 1L) .m2sparse(x, "ngC") %&% .m2sparse(y, "ngR", trans = TRUE) else if(nx == length(y)) ## else if((ny <- length(y)) == 1L || nx == ny) .m2sparse(x, "ngR", trans = TRUE) %&% .m2sparse(y, "ngC") else stop("non-conformable arguments") r@Dimnames <- list(NULL, NULL) r }) ## .... denseMatrix .................................................... setMethod("%&%", c(x = "denseMatrix", y = "denseMatrix"), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, TRUE)) for(.cl in c("matrix", "vector")) { setMethod("%&%", c(x = "denseMatrix", y = .cl), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, TRUE)) setMethod("%&%", c(x = .cl, y = "denseMatrix"), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, TRUE)) } ## .... CsparseMatrix .................................................. setMethod("%&%", c(x = "CsparseMatrix", y = "CsparseMatrix"), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, TRUE)) setMethod("%&%", c(x = "CsparseMatrix", y = "RsparseMatrix"), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, TRUE)) setMethod("%&%", c(x = "CsparseMatrix", y = "TsparseMatrix"), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, TRUE)) for(.cl in c("denseMatrix", "matrix", "vector")) { setMethod("%&%", c(x = "CsparseMatrix", y = .cl), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, TRUE)) setMethod("%&%", c(x = .cl, y = "CsparseMatrix"), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, TRUE)) } ## .... RsparseMatrix .................................................. setMethod("%&%", c(x = "RsparseMatrix", y = "CsparseMatrix"), function(x, y) .Call(R_sparse_matmult, y, x, TRUE, TRUE, TRUE, TRUE)) setMethod("%&%", c(x = "RsparseMatrix", y = "RsparseMatrix"), function(x, y) .Call(R_sparse_matmult, y, x, TRUE, TRUE, TRUE, TRUE)) setMethod("%&%", c(x = "RsparseMatrix", y = "TsparseMatrix"), function(x, y) .Call(R_sparse_matmult, y, x, TRUE, TRUE, TRUE, TRUE)) for(.cl in c("denseMatrix", "matrix", "vector")) { setMethod("%&%", c(x = "RsparseMatrix", y = .cl), function(x, y) .Call(R_sparse_matmult, y, x, TRUE, TRUE, TRUE, TRUE)) setMethod("%&%", c(x = .cl, y = "RsparseMatrix"), function(x, y) .Call(R_sparse_matmult, y, x, TRUE, TRUE, TRUE, TRUE)) } ## .... TsparseMatrix .................................................. setMethod("%&%", c(x = "TsparseMatrix", y = "CsparseMatrix"), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, TRUE)) setMethod("%&%", c(x = "TsparseMatrix", y = "RsparseMatrix"), function(x, y) .Call(R_sparse_matmult, y, x, TRUE, TRUE, TRUE, TRUE)) setMethod("%&%", c(x = "TsparseMatrix", y = "TsparseMatrix"), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, TRUE)) for(.cl in c("denseMatrix", "matrix", "vector")) { setMethod("%&%", c(x = "TsparseMatrix", y = .cl), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, TRUE)) setMethod("%&%", c(x = .cl, y = "TsparseMatrix"), function(x, y) .Call(R_sparse_matmult, x, y, FALSE, FALSE, FALSE, TRUE)) } ## .... diagonalMatrix ................................................. setMethod("%&%", c(x = "diagonalMatrix", y = "diagonalMatrix"), function(x, y) { r <- new("ndiMatrix") r@Dim <- matmultDim(x@Dim, y@Dim, type = 1L) r@Dimnames <- matmultDN(x@Dimnames, y@Dimnames, type = 1L) xu <- x@diag != "N" yu <- y@diag != "N" if(xu && yu) r@diag <- "U" else r@x <- if(xu) as.logical(y@x) else if(yu) as.logical(x@x) else x@x & y@x r }) for(.cl in c("CsparseMatrix", "RsparseMatrix", "TsparseMatrix", "denseMatrix", "matrix", "vector")) { setMethod("%&%", c(x = "diagonalMatrix", y = .cl), function(x, y) .Call(R_diagonal_matmult, x, y, FALSE, FALSE, TRUE)) setMethod("%&%", c(x = .cl, y = "diagonalMatrix"), function(x, y) .Call(R_diagonal_matmult, x, y, FALSE, FALSE, TRUE)) } ## .... indMatrix ...................................................... setMethod("%&%", c(x = "indMatrix", y = "indMatrix"), function(x, y) { mx <- x@margin my <- y@margin px <- x@perm py <- y@perm r <- new(if(mx == my) "indMatrix" else if(mx == 1L) "ngeMatrix" else "ngTMatrix") r@Dim <- matmultDim(x@Dim, y@Dim, type = 1L) r@Dimnames <- matmultDN(x@Dimnames, y@Dimnames, type = 1L) if(mx == my) r@perm <- if(mx == 1L) py[px] else { r@margin <- 2L; px[py] } else if(mx == 1L) r@x <- px == rep(py, each = length(px)) else { r@i <- px - 1L r@j <- py - 1L } r }) setMethod("%&%", c(x = "indMatrix", y = "Matrix"), function(x, y) { if(x@margin != 1L) return(.M2kind(x, "n") %&% y) matmultDim(x@Dim, y@Dim, type = 1L) r <- .M2kind(y[x@perm, , drop = FALSE], "n") r@Dimnames <- matmultDN(x@Dimnames, dimnames(y), type = 1L) r }) setMethod("%&%", c(x = "Matrix", y = "indMatrix"), function(x, y) { if(y@margin == 1L) return(x %&% .M2kind(y, "n")) matmultDim(x@Dim, y@Dim, type = 1L) r <- .M2kind(x[, y@perm, drop = FALSE], "n") r@Dimnames <- matmultDN(dimnames(x), y@Dimnames, type = 1L) r }) setMethod("%&%", c(x = "indMatrix", y = "matrix"), function(x, y) { if(x@margin != 1L) return(.M2kind(x, "n") %&% y) matmultDim(x@Dim, dim(y), type = 1L) r <- .m2dense(y[x@perm, , drop = FALSE], "nge") r@Dimnames <- matmultDN(x@Dimnames, dimnames(y), type = 1L) r }) setMethod("%&%", c(x = "matrix", y = "indMatrix"), function(x, y) { if(y@margin == 1L) return(x %&% .M2kind(y, "n")) matmultDim(dim(x), y@Dim, type = 1L) r <- .m2dense(x[, y@perm, drop = FALSE], "nge") r@Dimnames <- matmultDN(dimnames(x), y@Dimnames, type = 1L) r }) setMethod("%&%", c(x = "indMatrix", y = "vector"), function(x, y) { if(x@margin != 1L) return(.M2kind(x, "n") %&% y) k <- (d <- x@Dim)[2L] r <- if(k == length(y)) .m2dense(y[x@perm], "nge") else if(k == 1L) .m2dense(matrix(y, d[1L], length(y), byrow = TRUE), "nge") else stop("non-conformable arguments") r@Dimnames <- c(x@Dimnames[1L], list(NULL)) r }) setMethod("%&%", c(x = "vector", y = "indMatrix"), function(x, y) { if(y@margin == 1L) return(x %&% .M2kind(y, "n")) k <- (d <- y@Dim)[1L] r <- if(k == length(x)) .m2dense(x[y@perm], "nge", trans = TRUE) else if(k == 1L) .m2dense(matrix(x, length(x), d[2L]), "nge") else stop("non-conformable arguments") r@Dimnames <- c(list(NULL), y@Dimnames[2L]) r }) ## .... pMatrix ........................................................ setMethod("%&%", c(x = "pMatrix", y = "pMatrix"), function(x, y) { r <- new("pMatrix") r@Dim <- matmultDim(x@Dim, y@Dim, type = 1L) r@Dimnames <- matmultDN(x@Dimnames, y@Dimnames, type = 1L) r@perm <- if(y@margin == 1L) y@perm[if(x@margin == 1L) x@perm else invertPerm(x@perm)] else { r@margin <- 2L (if(x@margin == 1L) invertPerm(x@perm) else x@perm)[y@perm] } r }) setMethod("%&%", c(x = "pMatrix", y = "indMatrix"), function(x, y) { r <- new("indMatrix") r@Dim <- matmultDim(x@Dim, y@Dim, type = 1L) r@Dimnames <- matmultDN(x@Dimnames, y@Dimnames, type = 1L) r@perm <- if(y@margin == 1L) y@perm[if(x@margin == 1L) x@perm else invertPerm(x@perm)] else { r@margin <- 2L (if(x@margin == 1L) invertPerm(x@perm) else x@perm)[y@perm] } r }) setMethod("%&%", c(x = "indMatrix", y = "pMatrix"), function(x, y) { r <- new("indMatrix") r@Dim <- matmultDim(x@Dim, y@Dim, type = 1L) r@Dimnames <- matmultDN(x@Dimnames, y@Dimnames, type = 1L) r@perm <- if(x@margin == 1L) (if(y@margin == 1L) y@perm else invertPerm(y@perm))[x@perm] else { r@margin <- 2L x@perm[if(y@margin == 1L) invertPerm(x@perm) else y@perm] } r }) setMethod("%&%", c(x = "pMatrix", y = "Matrix"), function(x, y) { matmultDim(x@Dim, y@Dim, type = 1L) perm <- if(x@margin == 1L) x@perm else invertPerm(x@perm) r <- .M2kind(y[perm, , drop = FALSE], "n") r@Dimnames <- matmultDN(x@Dimnames, dimnames(y), type = 1L) r }) setMethod("%&%", c(x = "Matrix", y = "pMatrix"), function(x, y) { matmultDim(x@Dim, y@Dim, type = 1L) perm <- if(y@margin == 1L) invertPerm(y@perm) else y@perm r <- .M2kind(x[, perm, drop = FALSE], "n") r@Dimnames <- matmultDN(dimnames(x), y@Dimnames, type = 1L) r }) setMethod("%&%", c(x = "pMatrix", y = "matrix"), function(x, y) { matmultDim(x@Dim, dim(y), type = 1L) perm <- if(x@margin == 1L) x@perm else invertPerm(x@perm) r <- .m2dense(y[perm, , drop = FALSE], "nge") r@Dimnames <- matmultDN(x@Dimnames, dimnames(y), type = 1L) r }) setMethod("%&%", c(x = "matrix", y = "pMatrix"), function(x, y) { matmultDim(dim(x), y@Dim, type = 1L) perm <- if(y@margin == 1L) invertPerm(y@perm) else y@perm r <- .m2dense(x[, perm, drop = FALSE], "nge") r@Dimnames <- matmultDN(dimnames(x), y@Dimnames, type = 1L) r }) setMethod("%&%", c(x = "pMatrix", y = "vector"), function(x, y) { k <- x@Dim[2L] r <- if(k == length(y)) { perm <- if(x@margin == 1L) x@perm else invertPerm(x@perm) .m2dense(y[perm], "nge") } else if(k == 1L) .m2dense(y, "nge", trans = TRUE) else stop("non-conformable arguments") r@Dimnames <- c(x@Dimnames[1L], list(NULL)) r }) setMethod("%&%", c(x = "vector", y = "pMatrix"), function(x, y) { k <- y@Dim[1L] r <- if(k == length(x)) { perm <- if(y@margin == 1L) invertPerm(y@perm) else y@perm .m2dense(x[perm], "nge", trans = TRUE) } else if(k == 1L) .m2dense(x, "nge") else stop("non-conformable arguments") r@Dimnames <- c(list(NULL), y@Dimnames[2L]) r }) ## .... sparseVector ................................................... setMethod("%&%", c(x = "sparseVector", y = "sparseVector"), function(x, y) { x <- .V2kind(.drop0(x, isM = FALSE), "n") y <- .V2kind(.drop0(y, isM = FALSE), "n") if((nx <- length(x)) == 1L) { if(length(x@i) == 0L) y@i <- integer(0L) .tCRT(.V2C(y)) } else if(nx == length(y)) ## } else if((ny <- length(y)) == 1L) { ## if(length(y@i)) ## x@i <- integer(0L) ## .V2C(x) ## } else if(nx == ny) .m2sparse(any(match(x@i, y@i, 0L)), "ngR") else stop("non-conformable arguments") }) for(.cl in c("Matrix", "matrix")) { setMethod("%&%", c(x = "sparseVector", y = .cl), function(x, y) { x <- .V2kind(.drop0(x, isM = FALSE), "n") if((k <- dim(y)[1L]) == length(x)) .tCRT(.V2C(x)) %&% y else if(k == 1L) .V2C(x) %&% y else stop("non-conformable arguments") }) setMethod("%&%", c(x = .cl, y = "sparseVector"), function(x, y) { y <- .V2kind(.drop0(y, isM = FALSE), "n") if((k <- dim(x)[2L]) == length(y)) x %&% .V2C(y) else if(k == 1L) x %&% .tCRT(.V2C(y)) else stop("non-conformable arguments") }) } setMethod("%&%", c(x = "sparseVector", y = "vector"), function(x, y) .V2kind(.drop0(x, isM = FALSE), "n") %&% .m2V(y, "n")) setMethod("%&%", c(x = "vector", y = "sparseVector"), function(x, y) .m2V(x, "n") %&% .V2kind(.drop0(y, isM = FALSE), "n")) ## METHODS FOR GENERIC: crossprod ## NB: t(x) %*% y == t(t(y) %*% x) ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for(.cl in c("Matrix", "sparseVector")) { setMethod("crossprod", c(x = .cl, y = "ANY"), function(x, y = NULL, ...) crossprod(x, (if(length(dim(y)) == 2L) as.matrix else as.vector)(y), ...)) setMethod("crossprod", c(x = "ANY", y = .cl), function(x, y = NULL, ...) crossprod((if(length(dim(x)) == 2L) as.matrix else as.vector)(x), y, ...)) } ## .... denseMatrix .................................................... setMethod("crossprod", c(x = "denseMatrix", y = "missing"), function(x, y = NULL, boolArith = NA, ...) if(if(is.na(boolArith)) .M.kind(x) == "n" else boolArith) .Call(R_sparse_matmult, x, y, TRUE, FALSE, FALSE, TRUE) else .Call(R_dense_matmult, x, y, TRUE, FALSE)) setMethod("crossprod", c(x = "denseMatrix", y = "denseMatrix"), function(x, y = NULL, boolArith = NA, ...) if(if(is.na(boolArith)) .M.kind(x) == "n" && .M.kind(y) == "n" else boolArith) .Call(R_sparse_matmult, x, y, TRUE, FALSE, FALSE, TRUE) else .Call(R_dense_matmult, x, y, TRUE, FALSE)) for(.cl in c("matrix", "vector")) { setMethod("crossprod", c(x = "denseMatrix", y = .cl), function(x, y = NULL, boolArith = NA, ...) if(!is.na(boolArith) && boolArith) .Call(R_sparse_matmult, x, y, TRUE, FALSE, FALSE, TRUE) else .Call(R_dense_matmult, x, y, TRUE, FALSE)) setMethod("crossprod", c(x = .cl, y = "denseMatrix"), function(x, y = NULL, boolArith = NA, ...) if(!is.na(boolArith) && boolArith) .Call(R_sparse_matmult, x, y, TRUE, FALSE, FALSE, TRUE) else .Call(R_dense_matmult, x, y, TRUE, FALSE)) } ## .... CsparseMatrix .................................................. setMethod("crossprod", c(x = "CsparseMatrix", y = "missing"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, TRUE, FALSE, FALSE, boolArith)) setMethod("crossprod", c(x = "CsparseMatrix", y = "CsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, TRUE, FALSE, FALSE, boolArith)) setMethod("crossprod", c(x = "CsparseMatrix", y = "RsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, TRUE, FALSE, FALSE, boolArith)) setMethod("crossprod", c(x = "CsparseMatrix", y = "TsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, TRUE, FALSE, FALSE, boolArith)) for(.cl in c("denseMatrix", "matrix", "vector")) { setMethod("crossprod", c(x = "CsparseMatrix", y = .cl), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, TRUE, FALSE, FALSE, boolArith)) setMethod("crossprod", c(x = .cl, y = "CsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, y, x, TRUE, FALSE, TRUE, boolArith)) } ## .... RsparseMatrix .................................................. setMethod("crossprod", c(x = "RsparseMatrix", y = "missing"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, TRUE, FALSE, TRUE, boolArith)) setMethod("crossprod", c(x = "RsparseMatrix", y = "CsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, y, x, TRUE, FALSE, TRUE, boolArith)) setMethod("crossprod", c(x = "RsparseMatrix", y = "RsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, y, x, TRUE, FALSE, TRUE, boolArith)) setMethod("crossprod", c(x = "RsparseMatrix", y = "TsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, y, x, TRUE, FALSE, TRUE, boolArith)) for(.cl in c("denseMatrix", "matrix", "vector")) { setMethod("crossprod", c(x = "RsparseMatrix", y = .cl), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, TRUE, FALSE, FALSE, boolArith)) setMethod("crossprod", c(x = .cl, y = "RsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, y, x, TRUE, FALSE, TRUE, boolArith)) } ## .... TsparseMatrix .................................................. setMethod("crossprod", c(x = "TsparseMatrix", y = "missing"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, TRUE, FALSE, FALSE, boolArith)) setMethod("crossprod", c(x = "TsparseMatrix", y = "CsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, TRUE, FALSE, FALSE, boolArith)) setMethod("crossprod", c(x = "TsparseMatrix", y = "RsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, TRUE, FALSE, FALSE, boolArith)) setMethod("crossprod", c(x = "TsparseMatrix", y = "TsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, TRUE, FALSE, FALSE, boolArith)) for(.cl in c("denseMatrix", "matrix", "vector")) { setMethod("crossprod", c(x = "TsparseMatrix", y = .cl), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, TRUE, FALSE, FALSE, boolArith)) setMethod("crossprod", c(x = .cl, y = "TsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, y, x, TRUE, FALSE, TRUE, boolArith)) } ## .... diagonalMatrix ................................................. setMethod("crossprod", c(x = "diagonalMatrix", y = "missing"), function(x, y = NULL, boolArith = NA, ...) { boolArith <- !is.na(boolArith) && boolArith r <- new(if(boolArith) "ndiMatrix" else "ddiMatrix") r@Dim <- x@Dim r@Dimnames <- x@Dimnames[c(2L, 2L)] if(x@diag != "N") r@diag <- "U" else { xii <- x@x r@x <- if(boolArith) as.logical(xii) else { if(.M.kind(x) == "n" && anyNA(xii)) xii <- xii | is.na(xii) as.double(xii * xii) } } r }) setMethod("crossprod", c(x = "diagonalMatrix", y = "diagonalMatrix"), function(x, y = NULL, boolArith = NA, ...) (if(!is.na(boolArith) && boolArith) `%&%` else `%*%`)(t(x), y)) for(.cl in c("CsparseMatrix", "RsparseMatrix", "TsparseMatrix", "denseMatrix", "matrix", "vector")) { setMethod("crossprod", c(x = "diagonalMatrix", y = .cl), function(x, y = NULL, boolArith = NA, ...) .Call(R_diagonal_matmult, x, y, TRUE, FALSE, boolArith)) setMethod("crossprod", c(x = .cl, y = "diagonalMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_diagonal_matmult, x, y, TRUE, FALSE, boolArith)) } ## .... indMatrix ...................................................... setMethod("crossprod", c(x = "indMatrix", y = "missing"), function(x, y = NULL, boolArith = NA, ...) { if(x@margin != 1L) return(tcrossprod(t(x), boolArith = boolArith, ...)) boolArith <- !is.na(boolArith) && boolArith tt <- tabulate(x@perm, x@Dim[2L]) r <- new(if(boolArith) "ndiMatrix" else "ddiMatrix") r@Dim <- x@Dim[c(2L, 2L)] r@Dimnames <- x@Dimnames[c(2L, 2L)] r@x <- if(boolArith) as.logical(tt) else as.double(tt) r }) for(.cl in c("Matrix", "matrix", "vector")) setMethod("crossprod", c(x = "indMatrix", y = .cl), function(x, y = NULL, boolArith = NA, ...) (if(!is.na(boolArith) && boolArith) `%&%` else `%*%`)(t(x), y)) setMethod("crossprod", c(x = "Matrix", y = "indMatrix"), function(x, y = NULL, boolArith = NA, ...) { matmultDim(x@Dim, y@Dim, type = 2L) l <- if(!is.na(boolArith) && boolArith) "n" else "," if(y@margin == 1L) r <- crossprod(x, .M2kind(y, l), boolArith = boolArith, ...) else { r <- .M2kind(t(x)[, y@perm, drop = FALSE], l) r@Dimnames <- matmultDN(dimnames(x), y@Dimnames, type = 2L) } r }) setMethod("crossprod", c(x = "matrix", y = "indMatrix"), function(x, y = NULL, boolArith = NA, ...) { matmultDim(dim(x), y@Dim, type = 2L) l <- if(!is.na(boolArith) && boolArith) "n" else "," if(y@margin == 1L) r <- crossprod(x, .M2kind(y, l), boolArith = boolArith, ...) else { r <- .m2dense(t(x)[, y@perm, drop = FALSE], paste0(l, "ge")) r@Dimnames <- matmultDN(dimnames(x), y@Dimnames, type = 2L) } r }) setMethod("crossprod", c(x = "vector", y = "indMatrix"), function(x, y = NULL, boolArith = NA, ...) { if(y@Dim[1L] != length(x)) stop("non-conformable arguments") l <- if(!is.na(boolArith) && boolArith) "n" else "," if(y@margin == 1L) r <- crossprod(x, .M2kind(y, l), boolArith = boolArith, ...) else { r <- .m2dense(x[y@perm], paste0(l, "ge"), trans = TRUE) r@Dimnames <- c(list(NULL), y@Dimnames[2L]) } r }) ## .... pMatrix ........................................................ setMethod("crossprod", c(x = "pMatrix", y = "missing"), function(x, y = NULL, boolArith = NA, ...) { boolArith <- !is.na(boolArith) && boolArith r <- new(if(boolArith) "ndiMatrix" else "ddiMatrix") r@Dim <- x@Dim r@Dimnames <- x@Dimnames[c(2L, 2L)] r@diag <- "U" r }) setMethod("crossprod", c(x = "pMatrix", y = "pMatrix"), function(x, y = NULL, boolArith = NA, ...) { r <- new("pMatrix") r@Dim <- matmultDim(x@Dim, y@Dim, type = 2L) r@Dimnames <- matmultDN(x@Dimnames, y@Dimnames, type = 2L) r@perm <- if(y@margin == 1L) y@perm[if(x@margin == 1L) invertPerm(x@perm) else x@perm] else { r@margin <- 2L (if(x@margin == 1L) x@perm else invertPerm(x@perm))[y@perm] } r }) setMethod("crossprod", c(x = "Matrix", y = "pMatrix"), function(x, y = NULL, boolArith = NA, ...) { matmultDim(x@Dim, y@Dim, type = 2L) l <- if(!is.na(boolArith) && boolArith) "n" else "," perm <- if(y@margin == 1L) invertPerm(y@perm) else y@perm r <- .M2kind(t(x)[, perm, drop = FALSE], l) r@Dimnames <- matmultDN(dimnames(x), y@Dimnames, type = 2L) r }) setMethod("crossprod", c(x = "matrix", y = "pMatrix"), function(x, y = NULL, boolArith = NA, ...) { matmultDim(dim(x), y@Dim, type = 2L) l <- if(!is.na(boolArith) && boolArith) "n" else "," perm <- if(y@margin == 1L) invertPerm(y@perm) else y@perm r <- .m2dense(t(x)[, perm, drop = FALSE], paste0(l, "ge")) r@Dimnames <- matmultDN(dimnames(x), y@Dimnames, type = 2L) r }) setMethod("crossprod", c(x = "vector", y = "pMatrix"), function(x, y = NULL, boolArith = NA, ...) { if(y@Dim[1L] != length(x)) stop("non-conformable arguments") l <- if(!is.na(boolArith) && boolArith) "n" else "," perm <- if(y@margin == 1L) invertPerm(y@perm) else y@perm r <- .m2dense(x[perm], paste0(l, "ge"), trans = TRUE) r@Dimnames <- c(list(NULL), y@Dimnames[2L]) r }) ## .... sparseVector ................................................... setMethod("crossprod", c(x = "sparseVector", y = "missing"), function(x, y = NULL, boolArith = NA, ...) if(if(is.na(boolArith)) .M.kind(x) == "n" else boolArith) { if(!is.na(boolArith)) x <- .V2kind(.drop0(x, isM = FALSE), "n") .m2sparse(length(x@i) > 0L, "nsR") } else .m2sparse(sum(x * x), ",sR")) setMethod("crossprod", c(x = "sparseVector", y = "sparseVector"), function(x, y = NULL, boolArith = NA, ...) if(if(is.na(boolArith)) .M.kind(x) == "n" && .M.kind(y) == "n" else boolArith) { if(!is.na(boolArith)) { x <- .V2kind(.drop0(x, isM = FALSE), "n") y <- .V2kind(.drop0(y, isM = FALSE), "n") } if((nx <- length(x)) == 1L) { if(length(x@i) == 0L) y@i <- integer(0L) .tCRT(.V2C(y)) } else if(nx == length(y)) .m2sparse(any(match(x@i, y@i, 0L)), "ngR") else stop("non-conformable arguments") } else { if((nx <- length(x)) == 1L) .tCRT(.V2C(x * y)) else if(nx == length(y)) .m2sparse(sum(x * y), ",gR") else stop("non-conformable arguments") }) for(.cl in c("Matrix", "matrix")) { setMethod("crossprod", c(x = "sparseVector", y = .cl), function(x, y = NULL, boolArith = NA, ...) crossprod(.tCRT(.V2C(x)), y, boolArith = boolArith, ...)) setMethod("crossprod", c(x = .cl, y = "sparseVector"), function(x, y = NULL, boolArith = NA, ...) if(dim(x)[1L] == length(y)) crossprod(x, .V2C(y) , boolArith = boolArith, ...) else crossprod(x, .tCRT(.V2C(y)), boolArith = boolArith, ...)) } setMethod("crossprod", c(x = "sparseVector", y = "vector"), function(x, y = NULL, boolArith = NA, ...) if(!is.na(boolArith) && boolArith) { x <- .V2kind(.drop0(x, isM = FALSE), "n") y <- .m2V(y, "n") if((nx <- length(x)) == 1L) { if(length(x@i) == 0L) y@i <- integer(0L) .tCRT(.V2C(y)) } else if(nx == length(y)) .m2sparse(any(match(x@i, y@i, 0L)), "ngR") else stop("non-conformable arguments") } else { if((nx <- length(x)) == 1L) .m2dense(.V2v(x * y), ",ge", trans = TRUE) else if(nx == length(y)) .m2dense(sum(x * y), ",ge") else stop("non-conformable arguments") }) setMethod("crossprod", c(x = "vector", y = "sparseVector"), function(x, y = NULL, boolArith = NA, ...) if(!is.na(boolArith) && boolArith) { x <- .m2V(x, "n") y <- .V2kind(.drop0(y, isM = FALSE), "n") if((nx <- length(x)) == 1L) { if(length(x@i) == 0L) y@i <- integer(0L) .tCRT(.V2C(y)) } else if(nx == length(y)) .m2sparse(any(match(x@i, y@i, 0L)), "ngR") else stop("non-conformable arguments") } else { if((nx <- length(x)) == 1L) .m2dense(.V2v(x * y), ",ge", trans = TRUE) else if(nx == length(y)) .m2dense(sum(x * y), ",ge") else stop("non-conformable arguments") }) ## METHODS FOR GENERIC: tcrossprod ## NB: x %*% t(y) == t(y %*% t(x)) ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for(.cl in c("Matrix", "sparseVector")) { setMethod("tcrossprod", c(x = .cl, y = "ANY"), function(x, y = NULL, ...) tcrossprod(x, (if(length(dim(y)) == 2L) as.matrix else as.vector)(y), ...)) setMethod("tcrossprod", c(x = "ANY", y = .cl), function(x, y = NULL, ...) tcrossprod((if(length(dim(x)) == 2L) as.matrix else as.vector)(x), y, ...)) } ## .... denseMatrix .................................................... setMethod("tcrossprod", c(x = "denseMatrix", y = "missing"), function(x, y = NULL, boolArith = NA, ...) if(if(is.na(boolArith)) .M.kind(x) == "n" else boolArith) .Call(R_sparse_matmult, x, y, FALSE, TRUE, FALSE, TRUE) else .Call(R_dense_matmult, x, y, FALSE, TRUE)) setMethod("tcrossprod", c(x = "denseMatrix", y = "denseMatrix"), function(x, y = NULL, boolArith = NA, ...) if(if(is.na(boolArith)) .M.kind(x) == "n" && .M.kind(y) == "n" else boolArith) .Call(R_sparse_matmult, x, y, FALSE, TRUE, FALSE, TRUE) else .Call(R_dense_matmult, x, y, FALSE, TRUE)) for(.cl in c("matrix", "vector")) { setMethod("tcrossprod", c(x = "denseMatrix", y = .cl), function(x, y = NULL, boolArith = NA, ...) if(!is.na(boolArith) && boolArith) .Call(R_sparse_matmult, x, y, FALSE, TRUE, FALSE, TRUE) else .Call(R_dense_matmult, x, y, FALSE, TRUE)) setMethod("tcrossprod", c(x = .cl, y = "denseMatrix"), function(x, y = NULL, boolArith = NA, ...) if(!is.na(boolArith) && boolArith) .Call(R_sparse_matmult, x, y, FALSE, TRUE, FALSE, TRUE) else .Call(R_dense_matmult, x, y, FALSE, TRUE)) } ## .... CsparseMatrix .................................................. setMethod("tcrossprod", c(x = "CsparseMatrix", y = "missing"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, FALSE, TRUE, FALSE, boolArith)) setMethod("tcrossprod", c(x = "CsparseMatrix", y = "CsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, FALSE, TRUE, FALSE, boolArith)) setMethod("tcrossprod", c(x = "CsparseMatrix", y = "RsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, FALSE, TRUE, FALSE, boolArith)) setMethod("tcrossprod", c(x = "CsparseMatrix", y = "TsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, FALSE, TRUE, FALSE, boolArith)) for(.cl in c("denseMatrix", "matrix", "vector")) { setMethod("tcrossprod", c(x = "CsparseMatrix", y = .cl), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, FALSE, TRUE, FALSE, boolArith)) setMethod("tcrossprod", c(x = .cl, y = "CsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, y, x, FALSE, TRUE, TRUE, boolArith)) } ## .... RsparseMatrix .................................................. setMethod("tcrossprod", c(x = "RsparseMatrix", y = "missing"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, FALSE, TRUE, TRUE, boolArith)) setMethod("tcrossprod", c(x = "RsparseMatrix", y = "CsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, y, x, FALSE, TRUE, TRUE, boolArith)) setMethod("tcrossprod", c(x = "RsparseMatrix", y = "RsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, y, x, FALSE, TRUE, TRUE, boolArith)) setMethod("tcrossprod", c(x = "RsparseMatrix", y = "TsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, y, x, FALSE, TRUE, TRUE, boolArith)) for(.cl in c("denseMatrix", "matrix", "vector")) { setMethod("tcrossprod", c(x = "RsparseMatrix", y = .cl), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, FALSE, TRUE, FALSE, boolArith)) setMethod("tcrossprod", c(x = .cl, y = "RsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, y, x, FALSE, TRUE, TRUE, boolArith)) } ## .... TsparseMatrix .................................................. setMethod("tcrossprod", c(x = "TsparseMatrix", y = "missing"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, FALSE, TRUE, FALSE, boolArith)) setMethod("tcrossprod", c(x = "TsparseMatrix", y = "CsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, FALSE, TRUE, FALSE, boolArith)) setMethod("tcrossprod", c(x = "TsparseMatrix", y = "RsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, FALSE, TRUE, FALSE, boolArith)) setMethod("tcrossprod", c(x = "TsparseMatrix", y = "TsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, FALSE, TRUE, FALSE, boolArith)) for(.cl in c("denseMatrix", "matrix", "vector")) { setMethod("tcrossprod", c(x = "TsparseMatrix", y = .cl), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, x, y, FALSE, TRUE, FALSE, boolArith)) setMethod("tcrossprod", c(x = .cl, y = "TsparseMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_sparse_matmult, y, x, FALSE, TRUE, TRUE, boolArith)) } ## .... diagonalMatrix ................................................. setMethod("tcrossprod", c(x = "diagonalMatrix", y = "missing"), function(x, y = NULL, boolArith = NA, ...) { boolArith <- !is.na(boolArith) && boolArith r <- new(if(boolArith) "ndiMatrix" else "ddiMatrix") r@Dim <- x@Dim r@Dimnames <- x@Dimnames[c(1L, 1L)] if(x@diag != "N") r@diag <- "U" else { xii <- x@x r@x <- if(boolArith) as.logical(xii) else { if(.M.kind(x) == "n" && anyNA(xii)) xii <- xii | is.na(xii) as.double(xii * xii) } } r }) setMethod("tcrossprod", c(x = "diagonalMatrix", y = "diagonalMatrix"), function(x, y = NULL, boolArith = NA, ...) (if(!is.na(boolArith) && boolArith) `%&%` else `%*%`)(x, t(y))) for(.cl in c("CsparseMatrix", "RsparseMatrix", "TsparseMatrix", "denseMatrix", "matrix", "vector")) { setMethod("tcrossprod", c(x = "diagonalMatrix", y = .cl), function(x, y = NULL, boolArith = NA, ...) .Call(R_diagonal_matmult, x, y, FALSE, TRUE, boolArith)) setMethod("tcrossprod", c(x = .cl, y = "diagonalMatrix"), function(x, y = NULL, boolArith = NA, ...) .Call(R_diagonal_matmult, x, y, FALSE, TRUE, boolArith)) } ## .... indMatrix ...................................................... setMethod("tcrossprod", c(x = "indMatrix", y = "missing"), function(x, y = NULL, boolArith = TRUE, ...) { if(x@margin != 1L) return(crossprod(t(x), boolArith = boolArith, ...)) boolArith <- !is.na(boolArith) && boolArith r <- new(if(boolArith) "ngeMatrix" else "dgeMatrix") r@Dim <- x@Dim[c(1L, 1L)] r@Dimnames <- x@Dimnames[c(1L, 1L)] r@x <- as.vector(`storage.mode<-`( .M2m(x), if(boolArith) "logical" else "double")[, x@perm]) r }) for(.cl in c("Matrix", "matrix", "vector")) setMethod("tcrossprod", c(x = .cl, y = "indMatrix"), function(x, y = NULL, boolArith = NA, ...) (if(!is.na(boolArith) && boolArith) `%&%` else `%*%`)(x, t(y))) setMethod("tcrossprod", c(x = "indMatrix", y = "Matrix"), function(x, y = NULL, boolArith = NA, ...) { matmultDim(x@Dim, y@Dim, type = 3L) l <- if(!is.na(boolArith) && boolArith) "n" else "," if(y@margin != 1L) r <- tcrossprod(.M2kind(x, l), y, boolArith = boolArith, ...) else { r <- .M2kind(t(y)[x@perm, , drop = FALSE], l) r@Dimnames <- matmultDN(x@Dimnames, dimnames(y), type = 3L) } r }) setMethod("tcrossprod", c(x = "indMatrix", y = "matrix"), function(x, y = NULL, boolArith = NA, ...) { matmultDim(x@Dim, dim(y), type = 3L) l <- if(!is.na(boolArith) && boolArith) "n" else "," if(y@margin != 1L) r <- tcrossprod(.M2kind(x, l), y, boolArith = boolArith, ...) else { r <- .m2dense(t(y)[x@perm, , drop = FALSE], paste0(l, "ge")) r@Dimnames <- matmultDN(x@Dimnames, dimnames(y), type = 3L) } r }) setMethod("tcrossprod", c(x = "indMatrix", y = "vector"), function(x, y = NULL, boolArith = NA, ...) { d <- x@Dim m <- d[1L] k <- d[2L] if(k != (if(m == 1L) length(y) else 1L)) stop("non-conformable arguments") boolArith <- !is.na(boolArith) && boolArith h <- if(boolArith) isN0 else as.double r <- new(if(boolArith) "ngeMatrix" else "dgeMatrix") r@Dim <- d <- c(m, if(m == 1L) 1L else length(y)) r@Dimnames <- c(x@Dimnames[1L], list(NULL)) r@x <- if(m == 1L) { if(x@margin == 1L) h(y[x@perm]) else (if(boolArith) any else sum)(h(y)) } else { if(x@margin == 1L) as.vector(matrix(h(y), m, length(y), byrow = TRUE)) else { tmp <- array(if(boolArith) FALSE else 0, d) tmp[y@perm, ] <- h(y) dim(tmp) <- NULL tmp } } r }) ## .... pMatrix ........................................................ setMethod("tcrossprod", c(x = "pMatrix", y = "missing"), function(x, y = NULL, boolArith = NA, ...) { boolArith <- !is.na(boolArith) && boolArith r <- new(if(boolArith) "ndiMatrix" else "ddiMatrix") r@Dim <- x@Dim r@Dimnames <- x@Dimnames[c(1L, 1L)] r@diag <- "U" r }) setMethod("tcrossprod", c(x = "pMatrix", y = "pMatrix"), function(x, y = NULL, boolArith = NA, ...) { r <- new("pMatrix") r@Dim <- matmultDim(x@Dim, y@Dim, type = 2L) r@Dimnames <- matmultDN(x@Dimnames, y@Dimnames, type = 2L) r@perm <- if(y@margin != 1L) y@perm[if(x@margin == 1L) x@perm else invertPerm(x@perm)] else { r@margin <- 2L (if(x@margin == 1L) invertPerm(x@perm) else x@perm)[y@perm] } r }) setMethod("tcrossprod", c(x = "pMatrix", y = "Matrix"), function(x, y = NULL, boolArith = NA, ...) { matmultDim(x@Dim, y@Dim, type = 3L) l <- if(!is.na(boolArith) && boolArith) "n" else "," perm <- if(x@margin == 1L) x@perm else invertPerm(x@perm) r <- .M2kind(t(y)[perm, , drop = FALSE], l) r@Dimnames <- matmultDN(x@Dimnames, dimnames(y), type = 3L) r }) setMethod("tcrossprod", c(x = "pMatrix", y = "matrix"), function(x, y = NULL, boolArith = NA, ...) { matmultDim(x@Dim, dim(y), type = 3L) l <- if(!is.na(boolArith) && boolArith) "n" else "," perm <- if(x@margin == 1L) x@perm else invertPerm(x@perm) r <- .m2dense(t(y)[perm, , drop = FALSE], paste0(l, "ge")) r@Dimnames <- matmultDN(x@Dimnames, dimnames(y), type = 3L) r }) setMethod("tcrossprod", c(x = "pMatrix", y = "vector"), function(x, y = NULL, boolArith = NA, ...) { if(x@Dim[2L] != 1L || length(y) != 1L) stop("non-conformable arguments") l <- if(!is.na(boolArith) && boolArith) "n" else "," r <- .m2dense(y, paste0(l, "ge"), trans = TRUE) r@Dimnames <- c(x@Dimnames[1L], list(NULL)) r }) ## .... sparseVector ................................................... setMethod("tcrossprod", c(x = "sparseVector", y = "missing"), function(x, y = NULL, boolArith = NA, ...) tcrossprod(.V2C(x), boolArith = boolArith, ...)) setMethod("tcrossprod", c(x = "sparseVector", y = "sparseVector"), function(x, y = NULL, boolArith = NA, ...) (if(if(is.na(boolArith)) .M.kind(x) == "n" && .M.kind(y) == "n" else boolArith) `%&%` else `%*%`)(x, .tCRT(.V2C(y)))) for(.cl in c("Matrix", "matrix")) { setMethod("tcrossprod", c(x = "sparseVector", y = .cl), function(x, y = NULL, boolArith = NA, ...) { x <- if(dim(y)[2L] == length(x)) .tCRT(.V2C(x)) else .V2C(x) tcrossprod(x, y, boolArith = boolArith, ...) }) setMethod("tcrossprod", c(x = .cl, y = "sparseVector"), function(x, y = NULL, boolArith = NA, ...) { y <- if(dim(x)[1L] == 1L) .tCRT(.V2C(y)) else .V2C(y) tcrossprod(x, y, boolArith = boolArith, ...) }) } setMethod("tcrossprod", c(x = "sparseVector", y = "vector"), function(x, y = NULL, boolArith = NA, ...) { r <- if(!is.na(boolArith) && boolArith) x %&% .m2sparse(y, "ngR", trans = TRUE) else x %*% .m2dense (y, ",ge", trans = TRUE) r@Dimnames <- list(NULL, NULL) r }) setMethod("tcrossprod", c(x = "vector", y = "sparseVector"), function(x, y = NULL, boolArith = NA, ...) (if(!is.na(boolArith) && boolArith) `%&%` else `%*%`)(x, .tCRT(.V2C(y)))) rm(.cl) Matrix/R/subscript.R0000644000175100001440000006434314563762457014133 0ustar hornikusers## METHODS FOR GENERIC: [ ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .subscript.invalid <- function(i) { if(is.object(i)) gettextf("invalid subscript class \"%s\"", class(i)[1L]) else gettextf("invalid subscript type \"%s\"", typeof(i)) } .subscript.recycle <- function(i, n, pattern) { ## Return integer or double vector corresponding ## to [nl]sparseVector 'i' recycled to length 'n' : if(length(i.i <- i@i) == 0L) integer(0L) else if((i.length <- length(i)) >= n) { if(i.length > n) { if(n < 0x1p+53) { if(i.i[length(i.i)] >= n + 1) i.i[i.i >= n + 1] <- NA } else { if(i.i[length(i.i)] > n) i.i[i.i > n] <- NA } } if(pattern) i.i else i.i[i@x] } else { r <- ceiling(n / i.length) n. <- r * i.length i.i <- if(n. <= .Machine$integer.max) rep.int(as.integer(i.i), r) + rep(seq.int(from = 0L, by = as.integer(i.length), length.out = r), each = length(i.i)) else if(i.i[length(i.i)] + (r - 1) * i.length <= 0x1p+53) rep.int(as.double(i.i), r) + rep(seq.int(from = 0, by = as.double(i.length), length.out = r), each = length(i.i)) else stop(gettextf("recycled %s would have maximal index exceeding %s", "[nl]sparseVector", "2^53"), domain = NA) if(pattern) { if(n. > n) i.i[ i.i <= n] else i.i } else { if(n. > n) i.i[i@x & i.i <= n] else i.i[i@x] } } } ## x[i] where 'i' is NULL or any vector or sparseVector .subscript.1ary <- function(x, i) { x.length <- prod(x@Dim) if(is.null(i)) i <- integer(0L) else if(isS4(i)) { if(!.isVector(i)) stop(.subscript.invalid(i), domain = NA) kind <- .M.kind(i) if((pattern <- kind == "n") || kind == "l") { ## [nl]sparseVector i <- .subscript.recycle(i, x.length, pattern) return(..subscript.1ary(x, i, unsorted = !pattern && anyNA(i))) } i <- i@x } switch(typeof(i), double = { r <- min(1, i, na.rm = TRUE) if(r < 1) i <- if(r <= -1) seq_len(x.length)[i] # FIXME else i[i >= 1] ..subscript.1ary(x, i) }, integer = { r <- min(1L, i, na.rm = TRUE) if(r < 1L) i <- if(r <= -1L) seq_len(x.length)[i] # FIXME else i[i >= 1L] ..subscript.1ary(x, i) }, logical = { if((i.length <- length(i)) && !is.na(a <- all(i)) && a) { if(i.length <= x.length) as.vector(x) else c(as.vector(x), rep.int(NA, i.length - x.length)) } else .subscript.1ary(x, .m2V(i)) # recursively }, character = { rep.int(if(.hasSlot(x, "x")) x@x[NA_integer_] else NA, length(i)) }, stop(.subscript.invalid(i), domain = NA)) } ## x[i] where 'i' is vector of type "integer" or "double" ## with elements greater than or equal to 1 (or NA) ..subscript.1ary <- function(x, i, shape = .M.shape(x), repr = .M.repr(x), unsorted = is.unsorted(i)) { if(!any(repr == c("C", "R", "T"))) return(.Call(R_subscript_1ary, x, i)) if(shape == "t" && x@diag != "N") x <- ..diagU2N(x) if(shape == "s" || repr == "R") { x.length <- prod(d <- x@Dim) if(x.length < 0x1p+53) { r <- max(x.length, i, na.rm = TRUE) if(r >= x.length + 1) i[i >= x.length + 1] <- NA } else if(is.double(i)) { r <- max(0x1p+53, i, na.rm = TRUE) if(r > 0x1p+53) { if(any(i > 0x1p+53 && i <= x.length, na.rm = TRUE)) ## could be avoided in C, which has 64-bit integers : warning(gettextf("subscripts exceeding %s replaced with NA", "2^53"), domain = NA) i[i > 0x1p+53] <- NA } } i1s <- i - 1L m <- d[1L] i. <- as.integer(i1s %% m) if(shape == "s") { j. <- as.integer(i1s %/% m) op <- if(x@uplo == "U") `>` else `<` if(length(w <- which(op(i., j.)))) { i.. <- i.[w] j.. <- j.[w] if(repr == "R") i.[w] <- j.. if(x.length > .Machine$integer.max) m <- as.double(m) i[w] <- m * i.. + j.. + 1L unsorted <- TRUE # Bug #6839 } } } o <- if(repr == "R") order(i., i) else if(is.na(unsorted) || unsorted) sort.list(i) else return(.Call(R_subscript_1ary, x, i)) if(is.unsorted(o)) { s <- .Call(R_subscript_1ary, x, i[o]) s[o] <- s s } else .Call(R_subscript_1ary, x, i) } ## x[i] where 'i' is any array or Matrix .subscript.1ary.mat <- function(x, i) { if(isS4(i)) { if(!.isMatrix(i)) stop(.subscript.invalid(i), domain = NA) if((logic <- any(.M.kind(i) == c("n", "l"))) || i@Dim[2L] != 2L) { if(logic && all(i@Dim) && !is.na(a <- all(i)) && a) { x <- as.vector(x) if((i.length <- length(i)) <= (x.length <- length(x))) return(x) else return(c(x, rep.int(NA, i.length - x.length))) } i <- if(.isDense(i)) .M2v(i) else .M2V(i) return(.subscript.1ary(x, i)) } i <- as(i, "matrix") } else if(is.logical(i) || length(di <- dim(i)) != 2L || di[2L] != 2L) return(.subscript.1ary(x, i)) switch(typeof(i), double =, integer = { storage.mode(i) <- "integer" if(min(1L, i, na.rm = TRUE) < 1L) stop("negative values are not allowed in a matrix subscript") dx <- x@Dim m <- dx[1L] n <- dx[2L] if(m == n) { if(max(n, i, na.rm = TRUE) > n) stop("subscript out of bounds") } else { if(max(m, i[, 1L], na.rm = TRUE) > m || max(n, i[, 2L], na.rm = TRUE) > n) stop("subscript out of bounds") } ## * rows containing 0 are deleted ## * rows containing NA are kept ## * rows containing both 0 and NA are handled ## according to value in first column if(is.na(a <- all(i. <- i[, 1L])) || !a) i <- i[i. > 0L, , drop = FALSE] if(!all(j. <- i[, 2L], na.rm = TRUE)) i <- i[j. > 0L, , drop = FALSE] ..subscript.1ary.mat(x, i) }, character = { dnx <- dimnames(x) m <- c(match(i[, 1L], dnx[[1L]]), match(i[, 2L], dnx[[2L]])) dim(m) <- di if(any(!rowSums(is.na(i)) & rowSums(is.na(m)))) ## error if character row contains zero NA and ## integer row contains at least one NA, ## indicating non-match that should not be ignored stop("subscript out of bounds") ..subscript.1ary.mat(x, m) }, stop(.subscript.invalid(i), domain = NA)) } ## x[i] where 'i' is a 2-column matrix of type "integer" ## with i[, 1L] in 1:m (or NA) and i[, 2L] in 1:n (or NA) ..subscript.1ary.mat <- function(x, i, shape = .M.shape(x), repr = .M.repr(x)) { if(!any(repr == c("C", "R", "T"))) return(.Call(R_subscript_1ary_mat, x, i)) if(shape == "t" && x@diag != "N") x <- ..diagU2N(x) i. <- i[, 1L] j. <- i[, 2L] if(shape == "s") { op <- if(x@uplo == "U") `>` else `<` if(length(w <- which(op(i., j.)))) { i[w, ] <- i[w, 2:1] i. <- i[, 1L] j. <- i[, 2L] } } o <- if(repr == "R") { if(anyNA(j.)) i.[is.na(j.)] <- NA order(i., j.) } else { if(anyNA(i.)) j.[is.na(i.)] <- NA order(j., i.) } if(is.unsorted(o)) { s <- .Call(R_subscript_1ary_mat, x, i[o, , drop = FALSE]) s[o] <- s s } else .Call(R_subscript_1ary_mat, x, i) } ## x[i, j, drop] where 'i' and 'j' are NULL or any vector .subscript.2ary <- function(x, i, j, drop) { d <- x@Dim l <- list(if(missing(i)) NULL else if(is.null(i)) integer(0L) else i, if(missing(j)) NULL else if(is.null(j)) integer(0L) else j) for(pos in 1:2) { if(!is.null(k <- l[[pos]])) { l[pos] <- list( switch(typeof(k), double = { r <- d[pos] if(max(r, k, na.rm = TRUE) >= r + 1) stop("subscript out of bounds") if(min(1, k, na.rm = TRUE) < 1) seq_len(r)[k] else as.integer(k) }, integer = { r <- d[pos] if(max(r, k, na.rm = TRUE) > r) stop("subscript out of bounds") if(min(1L, k, na.rm = TRUE) < 1L) seq_len(r)[k] else k }, logical = { r <- d[pos] if(length(k) > r) stop("logical subscript too long") if(length(k) && !is.na(a <- all(k)) && a) NULL else seq_len(r)[k] }, character = { if(length(k) == 0L) integer(0L) else if(is.null(nms <- dimnames(x)[[pos]]) || anyNA(k <- match(k, nms))) stop("subscript out of bounds") else k }, stop(.subscript.invalid(k), domain = NA))) } } if(is.double(lengths(l, use.names = FALSE))) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) ..subscript.2ary(x, l[[1L]], l[[2L]], drop = drop[1L]) } ## x[i, j, drop] where 'i' and 'j' are vectors of type "integer" ## of length not exceeding 2^31-1 with 'i' in 1:m (or NA) and 'j' ## in 1:n (or NA) ... NULL => missing ..subscript.2ary <- function(x, i, j, drop) { if(is.null(i) && is.null(j)) r <- x else { r <- .Call(R_subscript_2ary, x, i, j) dn <- dimnames(x) if(!(is.null(i) || is.null(rn <- dn[[1L]]))) dn[1L] <- list(if(length(i)) rn[i] else NULL) if(!(is.null(j) || is.null(cn <- dn[[2L]]))) dn[2L] <- list(if(length(j)) cn[j] else NULL) r@Dimnames <- dn } if((is.na(drop) || drop) && any(r@Dim == 1L)) drop(as(r, "matrix")) else r } setMethod("[", c(x = "Matrix", i = "missing", j = "missing", drop = "missing"), function(x, i, j, ..., drop = TRUE) { na <- nargs() if(na == 2L) ## x[] x else if(na == 3L) ## x[, ] drop(x) else ## x[, , ], etc. stop("incorrect number of dimensions") }) setMethod("[", c(x = "Matrix", i = "missing", j = "missing", drop = "logical"), function(x, i, j, ..., drop = TRUE) { na <- nargs() if(na < 4L) ## x[drop=], x[, drop=], x[drop=, ] x else if(na == 4L) ## x[, , drop=], x[, drop=, ], x[drop=, , ] if(is.na(drop <- drop[1L]) || drop) drop(x) else x else ## x[, , , drop=], etc. stop("incorrect number of dimensions") }) setMethod("[", c(x = "Matrix", i = "index", j = "missing", drop = "missing"), function(x, i, j, ..., drop = TRUE) { na <- nargs() if(na == 2L) ## x[i=] .subscript.1ary(x, i) else if(na == 3L) ## x[i=, ], x[, i=] .subscript.2ary(x, i, , drop = TRUE) else ## x[i=, , ], etc. stop("incorrect number of dimensions") }) setMethod("[", c(x = "Matrix", i = "index", j = "missing", drop = "logical"), function(x, i, j, ..., drop = TRUE) { na <- nargs() if(na == 3L) ## x[i=, drop=] .subscript.1ary(x, i) else if(na == 4L) ## x[i=, , drop=], x[, i=, drop=] .subscript.2ary(x, i, , drop = drop) else ## x[i=, , , drop=], etc. stop("incorrect number of dimensions") }) setMethod("[", c(x = "Matrix", i = "missing", j = "index", drop = "missing"), function(x, i, j, ..., drop = TRUE) { na <- nargs() if(na == 2L) ## x[j=] .subscript.1ary(x, j) else if(na == 3L) ## x[j=, ], x[, j=] .subscript.2ary(x, , j, drop = TRUE) else ## x[, j=, ], etc. stop("incorrect number of dimensions") }) setMethod("[", c(x = "Matrix", i = "missing", j = "index", drop = "logical"), function(x, i, j, ..., drop = TRUE) { na <- nargs() if(na == 3L) ## x[j=, drop=] .subscript.1ary(x, j) else if(na == 4L) ## x[j=, , drop=], x[, j=, drop=] .subscript.2ary(x, , j, drop = drop) else ## x[, j=, , drop=], etc. stop("incorrect number of dimensions") }) setMethod("[", c(x = "Matrix", i = "index", j = "index", drop = "missing"), function(x, i, j, ..., drop = TRUE) { na <- nargs() if(na == 3L) ## x[i=, j=], x[j=, i=] .subscript.2ary(x, i, j, drop = TRUE) else ## x[i=, j=, ], etc. stop("incorrect number of dimensions") }) setMethod("[", c(x = "Matrix", i = "index", j = "index", drop = "logical"), function(x, i, j, ..., drop = TRUE) { na <- nargs() if(na == 4L) ## x[i=, j=, drop=], x[j=, i=, drop=] .subscript.2ary(x, i, j, drop = drop) else ## x[i=, j=, , drop=], etc. stop("incorrect number of dimensions") }) for(.cl in c("matrix", "nMatrix", "lMatrix")) setMethod("[", c(x = "Matrix", i = .cl, j = "missing", drop = "missing"), function(x, i, j, ..., drop = TRUE) { na <- nargs() if(na == 2L) ## x[i=] .subscript.1ary.mat(x, i) else if(na == 3L) ## x[i=, ], x[, i=] .subscript.2ary(x, i, , drop = TRUE) else ## x[i=, , ], etc. stop("incorrect number of dimensions") }) rm(.cl) setMethod("[", c(x = "Matrix", i = "NULL", j = "ANY", drop = "ANY"), function(x, i, j, ..., drop = TRUE) { i <- integer(0L) callGeneric() }) setMethod("[", c(x = "Matrix", i = "ANY", j = "NULL", drop = "ANY"), function(x, i, j, ..., drop = TRUE) { j <- integer(0L) callGeneric() }) setMethod("[", c(x = "Matrix", i = "NULL", j = "NULL", drop = "ANY"), function(x, i, j, ..., drop = TRUE) { i <- integer(0L) j <- integer(0L) callGeneric() }) setMethod("[", c(x = "sparseVector", i = "missing", j = "missing", drop = "missing"), function(x, i, j, ..., drop = TRUE) { if(nargs() != 2L) stop("incorrect number of dimensions") x }) setMethod("[", c(x = "sparseVector", i = "index", j = "missing", drop = "missing"), function(x, i, j, ..., drop = TRUE) { if(nargs() != 2L) stop("incorrect number of dimensions") x.length <- length(x) pattern <- .M.kind(x) == "n" switch(typeof(i), double = { r <- min(1, i, na.rm = TRUE) if(r <= -1) { if(r <= -x.length - 1) i <- i[i > -x.length - 1] r <- max(-1, i) if(is.na(r) || r >= 1) stop("only zeros may be mixed with negative subscripts") if(r > -1) i <- i[i <= -1] d <- unique.default(sort.int(-trunc(i))) k <- match(x@i, d, 0L) == 0L x@length <- length(x) - length(d) x@i <- { tmp <- x@i[k] tmp - findInterval(tmp, d) # !! } if(!pattern) x@x <- x@x[k] } else { if(r < 1) i <- i[i >= 1] if(max(0, i, na.rm = TRUE) >= x.length + 1) i[i >= x.length + 1] <- NA if((a <- anyNA(i)) && pattern) { x <- .V2kind(x, "l") pattern <- FALSE } j <- match(trunc(i), x@i, 0L) x@length <- length(i) x@i <- if(!a) which(j != 0L) else { i. <- is.na(i) j[i.] <- NA which(j != 0L | i.) } if(!pattern) x@x <- x@x[j] } x }, integer = { r <- min(1L, i, na.rm = TRUE) if(r <= -1L) { if(r < -x.length) i <- i[i >= -x.length] r <- max(-1L, i) if(is.na(r) || r >= 1L) stop("only zeros may be mixed with negative subscripts") if(r > -1L) i <- i[i <= -1L] d <- unique.default(sort.int(-i)) k <- is.na(match(x@i, d)) x@length <- length(x) - length(d) x@i <- { tmp <- x@i[k] tmp - findInterval(tmp, d) # !! } if(!pattern) x@x <- x@x[k] } else { if(r < 1L) i <- i[i >= 1L] if(max(0L, i, na.rm = TRUE) > x.length) i[i > x.length] <- NA if((a <- anyNA(i)) && pattern) { x <- .V2kind(x, "l") pattern <- FALSE } j <- match(i, x@i, 0L) x@length <- length(i) x@i <- if(!a) which(j != 0L) else { i. <- is.na(i) j[i.] <- NA which(j != 0L | i.) } if(!pattern) x@x <- x@x[j] } x }, logical = { if((i.length <- length(i)) && !is.na(a <- all(i)) && a) { if(i.length > x.length) { if(pattern) x <- .V2kind(x, "l") x@length <- i.length x@i <- c(x@i, (x.length + 1):i.length) x@x <- c(x@x, rep.int(NA, i.length - x.length)) } x } else x[.m2V(i)] # recursively }, stop(.subscript.invalid(i), domain = NA)) }) setMethod("[", c(x = "sparseVector", i = "nsparseVector", j = "missing", drop = "missing"), function(x, i, j, ..., drop = TRUE) { if(nargs() != 2L) stop("incorrect number of dimensions") x[.subscript.recycle(i, length(x), TRUE)] }) setMethod("[", c(x = "sparseVector", i = "lsparseVector", j = "missing", drop = "missing"), function(x, i, j, ..., drop = TRUE) { if(nargs() != 2L) stop("incorrect number of dimensions") x[.subscript.recycle(i, length(x), FALSE)] }) setMethod("[", c(x = "sparseVector", i = "NULL", j = "ANY", drop = "ANY"), function(x, i, j, ..., drop = TRUE) { i <- integer(0L) callGeneric() }) ## METHODS FOR GENERIC: head ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("head", c(x = "Matrix"), head.matrix) setMethod("head", c(x = "sparseVector"), function(x, n = 6L, ...) { stopifnot(is.numeric(n), length(n) == 1L, !is.na(n)) len <- length(x) n <- if(n < 0L) max(len + n, 0L) else min(n, len) if(n >= len) return(x) nnz <- length(i <- x@i) x@length <- n <- if(is.integer(i)) as.integer(n) else trunc(n) if(nnz > 0L && i[nnz] > n) { pattern <- .M.kind(x) == "n" if(i[1L] > n) { x@i <- integer(0L) if(!pattern) x@x <- x@x[0L] } else { ii <- 1L:(which.max(i > n) - 1L) x@i <- i[ii] if(!pattern) x@x <- x@x[ii] } } x }) ## METHODS FOR GENERIC: tail ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("tail", c(x = "Matrix"), tail.matrix) setMethod("tail", c(x = "sparseVector"), function(x, n = 6L, ...) { stopifnot(is.numeric(n), length(n) == 1L, !is.na(n)) len <- length(x) n <- if(n < 0L) max(len + n, 0L) else min(n, len) if(n >= len) return(x) nnz <- length(i <- x@i) x@length <- n <- if(is.integer(i)) as.integer(n) else trunc(n) if(nnz > 0L && i[1L] <= (k <- len - n)) { pattern <- .M.kind(x) == "n" if(i[nnz] <= k) { x@i <- integer(0L) if(!pattern) x@x <- x@x[0L] } else { ii <- which.min(i <= k):nnz x@i <- i[ii] - k if(!pattern) x@x <- x@x[ii] } } x }) Matrix/R/construct.R0000644000175100001440000006675314511521056014125 0ustar hornikusersMatrix <- function(data = NA, nrow = 1, ncol = 1, byrow = FALSE, dimnames = NULL, sparse = NULL, doDiag = TRUE, forceCheck = FALSE) { i.M <- i.sM <- i.dM <- i.sV <- i.m <- FALSE mnrow <- missing(nrow) mncol <- missing(ncol) if(isS4(data)) { cld <- getClassDef(class(data)) i.M <- extends(cld, "Matrix") if(i.M) { i.sM <- extends(cld, "sparseMatrix") i.dM <- i.sM && extends(cld, "diagonalMatrix") } else if(extends(cld, "sparseVector")) { ## need to transmit missingness to 'spV2M' call. <- quote(spV2M(x = data, nrow =, ncol =, byrow = byrow)) if(!mnrow) call.[[3L]] <- quote(nrow) if(!mncol) call.[[4L]] <- quote(ncol) data <- eval(call.) i.M <- i.sM <- i.sV <- forceCheck <- TRUE } } else { i.m <- is.matrix(data) } if(!i.M) { ## validate non-Matrix 'data', throwing type errors _early_ if(is.object(data)) { if(i.m) class(data) <- NULL # retaining 'dim' else data <- as.vector(data) } mode. <- mode(data) kind <- switch(mode., numeric = "d", logical = "l", stop("invalid 'data'")) } if(i.M || i.m) { ## 'data' is a Matrix or a numeric or logical matrix ## without a 'class' attribute if(!i.sV && !(mnrow && mncol && missing(byrow))) warning("'nrow', 'ncol', 'byrow' disregarded for [mM]atrix 'data'") if(!is.null(dimnames)) dimnames(data) <- dimnames if(is.null(sparse)) sparse <- sparseDefault(data) if(i.M) { ## return early in these cases: if(i.dM) ## !doDiag has been documented to result in a coercion to ## symmetricMatrix; we must use diag2*() below because the ## "usual" as(, "(Csparse|unpacked)Matrix") ## inherits from triangularMatrix, _not_ symmetricMatrix return(if(doDiag) data else if(sparse) .diag2sparse(data, ".", "s", "C", "U") else .diag2dense(data, ".", "s", FALSE, "U")) if(!forceCheck) return(if(i.sM == sparse) data else if(sparse) as(data, "CsparseMatrix") else as(data, "unpackedMatrix")) } } else { ## 'data' is a numeric or logical vector or non-matrix array ## without a 'class' attribute if(length(data) == 1L && !is.na(data) && data == 0 && (is.null(sparse) || sparse)) { ## Matrix(0, ...): sparseMatrix unless sparse=FALSE ## MJ: we should _try_ to behave as R's do_matrix() ## in the edge cases ... integer overflow is "OK" ## since anyNA(Dim) is caught by validity methods if(mnrow == mncol) { nrow <- as.integer(nrow) ncol <- as.integer(ncol) } else if(mnrow) { ncol <- as.integer(ncol) if(ncol == 0L) stop("data is too long") nrow <- as.integer(ceiling(1 / ncol)) } else { nrow <- as.integer(nrow) if(nrow == 0L) stop("data is too long") ncol <- as.integer(ceiling(1 / nrow)) } square <- nrow == ncol if(is.null(dimnames)) dimnames <- list(NULL, NULL) if(square && doDiag) return(new(paste0(kind, "diMatrix"), Dim = c(nrow, ncol), Dimnames = dimnames, x = vector(mode., nrow))) data <- new(paste0(kind, if(square) "s" else "g", "CMatrix"), Dim = c(nrow, ncol), Dimnames = dimnames, p = integer(ncol + 1)) i.M <- i.sM <- sparse <- TRUE } else { ## usual case: vector|array->matrix data <- .External(Mmatrix, data, nrow, ncol, byrow, dimnames, mnrow, mncol) if(is.null(sparse)) sparse <- sparseDefault(data) i.m <- TRUE } } ## 'data' is a Matrix (but _not_ a diagonalMatrix) or a ## numeric or logical matrix without a 'class' attribute if(doDiag && isDiagonal(data)) ## as(<[mM]atrix>, "diagonalMatrix") uses check = TRUE (a waste) return(forceDiagonal(data)) if(i.m || i.sM != sparse) { data <- as(data, if(sparse) "CsparseMatrix" else "unpackedMatrix") if(i.m) ## as(, "CsparseMatrix"), as(, "unpackedMatrix") ## already check for symmetric, triangular structure return(data) } if(!is(data, "generalMatrix")) data else if(isSymmetric(data)) forceSymmetric(data) else if(!(it <- isTriangular(data))) data else if(attr(it, "kind") == "U") triu(data) else tril(data) } sparseMatrix <- function(i, j, p, x, dims, dimnames, symmetric = FALSE, triangular = FALSE, index1 = TRUE, repr = c("C", "R", "T"), giveCsparse, check = TRUE, use.last.ij = FALSE) { if((m.i <- missing(i)) + (m.j <- missing(j)) + (m.p <- missing(p)) != 1L) stop("exactly one of 'i', 'j', and 'p' must be missing from call") if(symmetric && triangular) stop("use Diagonal() to construct diagonal (symmetric && triangular) sparse matrices") index1 <- as.logical(index1) # allowing {0,1} repr <- # keep in sync with toeplitz() ## NB: prior to 2020-05, we had 'giveCsparse' {T->"C" [default], F->"T"} ## but no 'repr' ... the following is to remain backwards compatible if(missing(giveCsparse)) match.arg(repr) else if(!missing(repr)) { warning("'giveCsparse' is deprecated; using 'repr' instead") match.arg(repr) ## } else { ## repr <- if(giveCsparse) "C" else "T" ## warning(gettextf("'giveCsparse' is deprecated; setting repr=\"%s\" for you", repr), ## domain = NA) ## } } else if(giveCsparse) { ## NOT YET: ## warning("'giveCsparse' is deprecated; setting repr=\"C\" for you") "C" } else { warning("'giveCsparse' is deprecated; setting repr=\"T\" for you") "T" } if(!m.p) { p <- as.integer(p) if((n.p <- length(p)) == 0L || anyNA(p) || p[1L] != 0L || any((dp <- p[-1L] - p[-n.p]) < 0L)) stop("'p' must be a nondecreasing vector c(0, ...)") if((n.dp <- length(dp)) > .Machine$integer.max) stop("dimensions cannot exceed 2^31-1") i. <- rep.int(seq.int(from = 0L, length.out = n.dp), dp) if(m.i) i <- i. else j <- i. } if(!m.i) i <- if(index1) as.integer(i) - 1L else as.integer(i) # need 0-index if(!m.j) j <- if(index1) as.integer(j) - 1L else as.integer(j) # need 0-index rij <- cbind(if(n.i <- length(i)) range(i) else 0:-1, if(n.j <- length(j)) range(j) else 0:-1, deparse.level = 0L) if(anyNA(rij)) stop("'i' and 'j' must not contain NA") # and not overflow if(any(rij[1L, ] < 0L)) stop("'i' and 'j' must be ", if(index1) "positive" else "non-negative") dims <- if(!missing(dims)) { if(length(dims) != 2L || any(is.na(dims) | dims < 0L | dims >= .Machine$integer.max + 1)) stop("invalid 'dims'") if(any(dims - 1L < rij[2L, ])) stop("'dims' must contain all (i,j) pairs") as.integer(dims) } else if(symmetric || triangular) rep.int(max(rij), 2L) + 1L else rij[2L, ] + 1L kind <- if(m.x <- missing(x)) "n" else if(is.integer(x)) "d" else .M.kind(x) shape <- if(symmetric) { if(dims[1L] != dims[2L]) stop("symmetric matrix must be square") "s" } else if(triangular) { if(dims[1L] != dims[2L]) stop("triangular matrix must be square") "t" } else "g" r <- new(paste0(kind, shape, "TMatrix")) r@Dim <- dims if(!missing(dimnames) && !is.null(dimnames)) r@Dimnames <- if(is.character(validDN(dimnames, dims))) dimnames else fixupDN(dimnames) # needs a valid argument if((symmetric || triangular) && all(i >= j)) r@uplo <- "L" # else "U", the prototype if(!m.x) { if(is.integer(x)) x <- as.double(x) if((n.x <- length(x)) > 0L && n.x != n.i) { if(n.x < n.i) { if(n.i %% n.x != 0L) warning(if(m.i) "p[length(p)] " else "length(i) ", "is not an integer multiple of length(x)") x <- rep_len(x, n.i) # recycle } else if(n.x == 1L) x <- x[0L] # tolerate length(i) = 0, length(x) = 1 else stop("length(x) must not exceed ", if(m.i) "p[length(p)]" else "length(i)") } if(use.last.ij && n.i == n.j && anyDuplicated.matrix(ij <- cbind(i, j, deparse.level = 0L), fromLast = TRUE)) { which.not.dup <- which(!duplicated(ij, fromLast = TRUE)) i <- i[which.not.dup] j <- j[which.not.dup] x <- x[which.not.dup] } r@x <- x } r@i <- i r@j <- j if(check) validObject(r) switch(repr, "C" = .M2C(r), "T" = r, "R" = .M2R(r), ## should never happen: stop("invalid 'repr'; must be \"C\", \"R\", or \"T\"")) } spMatrix <- function(nrow, ncol, i = integer(0L), j = integer(0L), x = double(0L)) new(paste0(if(is.integer(x)) "d" else .M.kind(x), "gTMatrix"), Dim = c(as.integer(nrow), as.integer(ncol)), i = as.integer(i) - 1L, j = as.integer(j) - 1L, x = if(is.integer(x)) as.double(x) else x) Diagonal <- function(n, x = NULL, names = FALSE) { nx <- length(x) if(missing(n)) n <- nx else if(!is.numeric(n) || length(n) != 1L || is.na(n) || n < 0L) stop("'n' must be a non-negative integer") if(is.double(n) && n >= .Machine$integer.max + 1) stop("dimensions cannot exceed 2^31-1") n <- as.integer(n) # discarding attributes if(is.null(x)) { r <- new("ddiMatrix") r@diag <- "U" if(n > 0L) { r@Dim <- c(n, n) if(is.character(names) && length(names) == n) r@Dimnames <- list(names, names) } return(r) } if(is.object(x)) stop(gettextf("'x' has unsupported class \"%s\"", class(x)[1L]), domain = NA) names.x <- names(x) # keeping for later r <- new(switch(typeof(x), ## discarding attributes, incl. 'dim' and 'names' logical = { x <- as.logical(x); "ldiMatrix" }, integer =, double = { x <- as.double(x); "ddiMatrix" }, stop(gettextf("'x' has unsupported type \"%s\"", typeof(x)), domain = NA))) if(n == 0L) return(r) if(nx != 1L) r@x <- if(nx == n) x else if(nx > 0L) rep_len(x, n) else stop("attempt to recycle 'x' of length 0 to length 'n' (n > 0)") else if(is.na(x) || x != 1) r@x <- rep.int(x, n) else r@diag <- "U" r@Dim <- c(n, n) if(is.character(names)) { if(length(names) == n) r@Dimnames <- list(names, names) } else if(isTRUE(names) && !is.null(names.x)) { names.x <- rep_len(names.x, n) # we know length(names.x) > 0L r@Dimnames <- list(names.x, names.x) } r } .sparseDiagonal <- function(n, x = NULL, uplo = "U", shape = "t", unitri = TRUE, kind, cols) { if(missing(n)) n <- length(x) else if(!is.numeric(n) || length(n) != 1L || is.na(n) || n < 0L) stop("'n' must be a non-negative integer") if(is.double(n) && n >= .Machine$integer.max + 1) stop("dimensions cannot exceed 2^31-1") n <- nj <- as.integer(n) # stripping attributes if(!(missing(shape) || (is.character(shape) && length(shape) == 1L && !is.na(shape) && any(shape == c("g", "t", "s"))))) stop("'shape' must be one of \"g\", \"t\", \"s\"") if(!((m.kind <- missing(kind)) || (is.character(kind) && length(kind) == 1L && !is.na(kind) && any(kind == c("d", "l", "n"))))) stop("'kind' must be one of \"d\", \"l\", \"n\"") if(m.kind || kind != "n") { if(is.null(x)) x <- if(m.kind) { kind <- "d"; 1 } else switch(kind, d = 1, l = TRUE) else if(is.object(x)) stop(gettextf("'x' has unsupported class \"%s\"", class(x)[1L]), domain = NA) else { kind. <- switch(typeof(x), ## discarding attributes, incl. 'dim' in array case logical = { x <- as.logical(x); "l" }, integer =, double = { x <- as.double(x); "d" }, stop(gettextf("'x' has unsupported type \"%s\"", typeof(x)), domain = NA)) if(m.kind) kind <- kind. else if(kind != kind.) { warning(gettextf("mismatch between typeof(x)=\"%s\" and kind=\"%s\"; using kind=\"%s\"", typeof(x), kind, kind.), domain = NA) kind <- kind. } } } if(!(m.cols <- missing(cols))) { if(!is.numeric(cols)) stop("'cols' must be numeric") else if((nj <- length(cols)) > 0L && (n == 0L || anyNA(rj <- range(cols)) || rj[1L] < 0L || rj[2L] >= n)) stop("'cols' has elements not in seq(0, length.out = n)") else { cols <- as.integer(cols) shape <- "g" } } r <- new(paste0(kind, shape, "CMatrix")) r@Dim <- c(n, nj) if(shape != "g") { if(!missing(uplo)) { if(is.character(uplo) && length(uplo) == 1L && !is.na(uplo) && any(uplo == c("U", "L"))) r@uplo <- uplo else stop("'uplo' must be \"U\" or \"L\"") } if(shape == "t" && unitri && (kind == "n" || (!anyNA(x) && all(if(kind == "l") x else x == 1)))) { r@diag <- "U" r@p <- integer(nj + 1) return(r) } } if(nj > 0L) { r@p <- 0:nj r@i <- if(m.cols) 0:(nj - 1L) else cols if(kind != "n") { x <- if((nx <- length(x)) == n) x else if(nx > 0L) rep_len(x, n) else stop("attempt to recycle 'x' of length 0 to length 'n' (n > 0)") r@x <- if(m.cols) x else x[1L + cols] } } r } .trDiagonal <- function(n, x = NULL, uplo = "U", unitri = TRUE, kind) .sparseDiagonal(n, x, uplo, shape = "t", unitri = unitri, kind = kind) .symDiagonal <- function(n, x = NULL, uplo = "U", kind) .sparseDiagonal(n, x, uplo, shape = "s", kind = kind) .bdiag <- function(lst) { if(!is.list(lst)) stop("'lst' must be a list") if((n <- length(lst)) == 0L) return(new("dgTMatrix")) if(n == 1L) return(.M2T(asCspN(lst[[1L]]))) ### FIXME? this is _slow_ when 'lst' is list of 75000 3-by-3 dense matrices lst <- unname(lapply(lst, function(x) .M2T(asCspN(x)))) cl <- vapply(lst, class, "") kind <- substr(cl, 1L, 1L) # "n", "l", or "d" shape <- substr(cl, 2L, 2L) # "g", "s", or "t" if(!(any(kind == (kind. <- "d")) || any(kind == (kind. <- "l")))) kind. <- "n" else if(any(z <- kind == "n")) lst[z] <- lapply(lst[z], .sparse2kind, kind.) shape. <- if(all(symmetric <- shape == "s")) "s" else if(all(shape == "t")) "t" else "g" if(shape. != "g") { uplo <- vapply(lst, slot, "", "uplo") # "U" or "L" if(shape. == "s") uplo. <- if(all(z <- uplo == "U")) "U" else if(!any(z)) "L" else { uplo.. <- if(2 * sum(z) >= n) { z <- !z; "U" } else "L" lst[z] <- lapply(lst[z], .tCRT) uplo.. } else if(any(uplo != (uplo. <- uplo[1L]))) shape. <- "g" } i_off <- c(0L, cumsum(vapply(lst, function(x) x@Dim[1L], 0L))) j_off <- c(0L, cumsum(vapply(lst, function(x) x@Dim[2L], 0L))) r <- new(paste0(kind., shape., "TMatrix")) r@Dim <- r@Dim <- c(i_off[n + 1L], j_off[n + 1L]) if(shape. == "g") lst[symmetric] <- lapply(lst[symmetric], .sparse2g) else r@uplo <- uplo. r@i <- unlist(lapply(seq_len(n), function(k) i_off[k] + lst[[k]]@i), FALSE, FALSE) r@j <- unlist(lapply(seq_len(n), function(k) j_off[k] + lst[[k]]@j), FALSE, FALSE) if(kind. != "n") r@x <- unlist(lapply(lst, slot, "x"), FALSE, FALSE) r } bdiag <- function(...) { if((n <- ...length()) == 0L) new("dgCMatrix") else if(n > 1L) .M2C(.bdiag(list(...))) else if(!is.list(x <- ..1)) as(x, "CsparseMatrix") else if(length(x) == 1L) as(x[[1L]], "CsparseMatrix") else .M2C(.bdiag(x)) } bandSparse <- function(n, m = n, k, diagonals, symmetric = FALSE, repr = "C", giveCsparse = (repr == "C")) { ## Purpose: Compute a band-matrix by speciyfying its (sub-)diagonal(s) ## ---------------------------------------------------------------------- ## Arguments: (n,m) : Matrix dimension ## k : integer vector of "diagonal numbers", with identical ## meaning as in band(*, k) ## diagonals: (optional!) list of (sub/super)diagonals ## symmetric: if TRUE, specify only upper or lower triangle; ## ---------------------------------------------------------------------- ## Author: Martin Maechler, Date: 20 Feb 2009, 22:42 if(use.x <- !missing(diagonals)) # when specified, must be matrix or list diag.isMat <- is.matrix(diagonals) len.k <- length(k) stopifnot(!use.x || is.list(diagonals) || diag.isMat, k == as.integer(k), n == as.integer(n), m == as.integer(m)) k <- as.integer(k) n <- as.integer(n) m <- as.integer(m) stopifnot(n >= 0, m >= 0, -n+1 <= (mik <- min(k)), (mak <- max(k)) <= m - 1) if(missing(repr) && !giveCsparse) { warning("'giveCsparse' has been deprecated; setting 'repr = \"T\"' for you") repr <- "T" } else if(!missing(repr) && !missing(giveCsparse)) warning("'giveCsparse' has been deprecated; will use 'repr' instead") if(use.x) { if(diag.isMat) { if(ncol(diagonals) != len.k) stop(gettextf("'diagonals' matrix must have %d columns (= length(k) )", len.k), domain=NA) getD <- function(j) diagonals[,j] } else { ## is.list(diagonals): if(length(diagonals) != len.k) stop(gettextf("'diagonals' must have the same length (%d) as 'k'", len.k), domain=NA) getD <- function(j) diagonals[[j]] } } sqr <- n == m if(symmetric) { if(!sqr) stop("matrix can only be symmetric if square, but n != m") if(mik < 0 && mak > 0) stop("for symmetric band matrix, only specify upper or lower triangle\n hence, all k must have the same sign") } else tri <- sqr && sign(mik)*sign(mak) >= 0 # triangular result dims <- c(n,m) k.lengths <- ## This is a bit "ugly"; I got the cases "by inspection" if(n >= m) { ifelse(k >= m-n, m - pmax(0,k), n+k) } else { ## n < m (?? k >= -n+1 always !!) ifelse(k >= -n+1, n + pmin(0,k), m-k) } i <- j <- integer(sum(k.lengths)) if(use.x) x <- if(len.k > 0) # carefully getting correct type/mode rep.int(getD(1)[1], length(i)) off.i <- 0L for(s in seq_len(len.k)) { kk <- k[s] ## *is* integer l.kk <- k.lengths[s] ## == length of (sub-)diagonal kk ii1 <- seq_len(l.kk) ind <- ii1 + off.i if(kk >= 0) { i[ind] <- ii1 j[ind] <- ii1 + kk } else { ## k < 0 i[ind] <- ii1 - kk j[ind] <- ii1 } if(use.x) { xx <- getD(s) if(length(xx) < l.kk) warning(gettextf("the %d-th (sub)-diagonal (k = %d) is too short; filling with NA's", s, kk), domain=NA) x[ind] <- xx[ii1] } off.i <- off.i + l.kk } if(symmetric) { ## we should have smarter sparseMatrix() UpLo <- if(min(k) >= 0) "U" else "L" T <- if(use.x) { if(is.integer(x)) x <- as.double(x) cc <- paste0(.M.kind(x), "sTMatrix") new(cc, i= i-1L, j= j-1L, x = x, Dim= dims, uplo=UpLo) } else new("nsTMatrix", i= i-1L, j= j-1L, Dim= dims, uplo=UpLo) switch(repr, "C" = .M2C(T), "T" = T, "R" = .M2R(T), stop("invalid 'repr'; must be \"C\", \"T\", or \"R\"")) } else { ## not symmetric, possibly triangular if(use.x) sparseMatrix(i=i, j=j, x=x, dims=dims, triangular=tri, repr=repr) else sparseMatrix(i=i, j=j, dims=dims, triangular=tri, repr=repr) } } rsparsematrix <- function(nrow, ncol, density, nnz = round(density * maxE), symmetric = FALSE, rand.x = function(n) signif(rnorm(n), 2L), ...) { maxE <- if(symmetric) nrow*(nrow+1)/2 else nrow*ncol stopifnot((nnz <- as.integer(nnz)) >= 0, nrow >= 0, ncol >= 0, nnz <= maxE) ## sampling with*out* replacement (replace=FALSE !): ijI <- -1L + if(symmetric) sample(indTri(nrow, diag=TRUE), nnz) else sample.int(maxE, nnz) ## i,j below correspond to ij <- decodeInd(code, nr) : if(is.null(rand.x)) sparseMatrix(i = ijI %% nrow, j = ijI %/% nrow, index1 = FALSE, symmetric = symmetric, dims = c(nrow, ncol), ...) else sparseMatrix(i = ijI %% nrow, j = ijI %/% nrow, x = rand.x(nnz), index1 = FALSE, symmetric = symmetric, dims = c(nrow, ncol), ...) } Hilbert <- function(n) { n <- as.integer(n) i <- seq_len(n) new("dpoMatrix", Dim = c(n, n), x = c(1/outer(i - 1L, i, `+`))) } spV2M <- function(x, nrow, ncol, byrow = FALSE, check = TRUE, symmetric = FALSE) { if(check && !is(x, "sparseVector")) stop("'x' must inherit from \"sparseVector\"") if(!missing(ncol)) { ncol <- as.integer(ncol) if(ncol < 0) stop("'ncol' must be >= 0") } if(!missing(nrow)) { nrow <- as.integer(nrow) if(nrow < 0) stop("'nrow' must be >= 0") } n <- length(x) if(symmetric) { if(missing(nrow)) stop("Must specify 'nrow' when 'symmetric' is true") if(!missing(ncol) && nrow != ncol) stop("'nrow' and 'ncol' must be the same when 'symmetric' is true") ## otherwise ncol will not used at all when (symmetric) if(check && as.double(nrow)^2 != n) stop("'x' must have length nrow^2 when 'symmetric' is true") ## x <- x[indTri(nrow, upper=TRUE, diag=TRUE)] } else if(missing(nrow)) { nrow <- as.integer( if(missing(ncol)) { ## both missing: --> (n x 1) ncol <- 1L n } else { if(n %% ncol != 0) warning("'ncol' is not a factor of length(x)") as.integer(ceiling(n / ncol)) }) } else if(missing(ncol)) { ncol <- if(symmetric) nrow else { if(n %% nrow != 0) warning("'nrow' is not a factor of length(x)") as.integer(ceiling(n / nrow)) } } else { ## both nrow and ncol specified n.n <- as.double(ncol) * nrow # no integer overflow if(n.n < n) stop("nrow * ncol < length(x)", domain = NA) if(n.n != n) warning("nrow * ncol != length(x)", domain = NA) } ## now nrow * ncol >= n (or 'symmetric') ## ~~~~~~~~~~~~~~~~ kind <- .M.kind(x) # "d", "n", "l", "i", "z", ... has.x <- kind != "n" clStem <- if(symmetric) "sTMatrix" else "gTMatrix" ## "careful_new()" : cNam <- paste0(kind, clStem) chngCl <- is.null(newCl <- getClassDef(cNam)) if(chngCl) { ## e.g. "igTMatrix" is not yet implemented if(kind == "z") stop(gettextf("Class %s is not yet implemented", dQuote(cNam)), domain = NA) ## coerce to "double": newCl <- getClassDef(paste0("d", clStem)) } r <- new(newCl, Dim = c(nrow, ncol)) ## now "compute" the (i,j,x) slots given x@(i,x) i0 <- x@i - 1L if(byrow) { ## need as.integer(.) since @ i can be double j <- as.integer(i0 %% ncol) i <- as.integer(i0 %/% ncol) } else { ## default{byrow = FALSE} i <- as.integer(i0 %% nrow) j <- as.integer(i0 %/% nrow) } if(has.x) x <- if(chngCl) as.numeric(x@x) else x@x if(symmetric) { ## using uplo = "U" i0 <- i <= j ## i.e., indTri(nrow, upper=TRUE, diag=TRUE) i <- i[i0] j <- j[i0] if(has.x) x <- x[i0] } r@j <- j r@i <- i if(has.x) r@x <- x r } .sparseV2Mat <- function(from) spV2M(from, nrow = from@length, ncol = 1L, check = FALSE) sp2vec <- function(x, mode = .type.kind[.M.kind(x)]) { ## sparseVector -> vector has.x <- .hasSlot(x, "x")## has "x" slot m.any <- (mode == "any") if(m.any) mode <- if(has.x) mode(x@x) else "logical" else if(has.x) # is.() is much faster than inherits() | is(): xxOk <- switch(mode, "double" = is.double(x@x), "logical" = is.logical(x@x), "integer" = is.integer(x@x), "complex" = is.complex(x@x), ## otherwise (does not happen with default 'mode'): inherits(x@x, mode)) r <- vector(mode, x@length) r[x@i] <- if(has.x) { if(m.any || xxOk) x@x else as(x@x, mode) } else TRUE r } newSpV <- function(class, x, i, length, drop0 = TRUE, checkSort = TRUE) { if(has.x <- !missing(x)) { if(length(x) == 1 && (li <- length(i)) != 1) ## recycle x : x <- rep.int(x, li) if(drop0 && isTRUE(any(x0 <- x == 0))) { keep <- is.na(x) | !x0 x <- x[keep] i <- i[keep] } } if(checkSort && is.unsorted(i)) { ii <- sort.list(i) if(has.x) x <- x[ii] i <- i[ii] } if(has.x) new(class, x = x, i = i, length = length) else new(class, i = i, length = length) } newSpVec <- function(class, x, prev) newSpV(class = class, x = x, i = prev@i, length = prev@length) sparseVector <- function(x, i, length) newSpV(class = paste0(if(missing(x)) "n" else .M.kind(x), "sparseVector"), x = x, i = i, length = length) Matrix/R/qr.R0000644000175100001440000003153114561451364012516 0ustar hornikusers## METHODS FOR GENERIC: qr ## pivoted QR factorization of dense and sparse matrices ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## MJ: Well, I'd very much like to _not_ truncate by default ... ## not least because qr.qy and qr.qty should remain inverses ... .qr.rank.def.truncating <- TRUE .qr.rank.def.warn <- function(qr) { if(m0 <- qr@V@Dim[1L] - qr@Dim[1L]) warning(gettextf("matrix is structurally rank deficient; using augmented matrix with additional %d row(s) of zeros", m0), domain = NA) m0 } setMethod("qr", c(x = "sparseMatrix"), function(x, ...) qr(.M2gen(.M2C(x), ","), ...)) setMethod("qr", c(x = "dgCMatrix"), function(x, order = 3L, ...) { r <- .Call(dgCMatrix_orf, x, order, TRUE) .qr.rank.def.warn(r) r }) ## METHODS FOR CLASS: sparseQR ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("expand1", c(x = "sparseQR"), function(x, which, ...) { .qr.rank.def.warn(x) R <- x@R d <- R@Dim m <- d[1L] n <- d[2L] switch(which, "P1" =, "P1." = { r <- new("pMatrix") r@Dim <- c(m, m) r@perm <- x@p + 1L if(which == "P1.") r@margin <- 2L r }, "P2" =, "P2." = { r <- new("pMatrix") r@Dim <- c(n, n) r@perm <- if(length(x@q)) x@q + 1L else seq_len(n) if(which == "P2") r@margin <- 2L r }, "Q" = .Call(sparseQR_matmult, x, NULL, 6L, TRUE, NULL), "Q1" = .Call(sparseQR_matmult, x, NULL, 6L, FALSE, NULL), "R" = R, "R1" = triu(if(m == n) R else R[seq_len(n), , drop = FALSE]), stop(gettextf("'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%2$s2\", \"%2$s2.\", \"%3$s\", \"%3$s1\", \"%4$s\", or \"%4$s1\"", "which", "P", "Q", "R"), domain = NA)) }) ## returning list(P1', Q, R, P2'), where A = P1' Q R P2' setMethod("expand2", c(x = "sparseQR"), function(x, complete = FALSE, ...) { m0 <- .qr.rank.def.warn(x) R <- x@R d <- R@Dim m <- d[1L] n <- d[2L] dn <- x@Dimnames if(m0 && !is.null(dn[[1L]])) length(dn[[1L]]) <- m Q <- .Call(sparseQR_matmult, x, NULL, 6L, complete, NULL) if(!complete && n < m) R <- R[seq_len(n), , drop = FALSE] p1 <- x@p p2 <- x@q P1. <- new("pMatrix", Dim = c(m, m), Dimnames = c(dn[1L], list(NULL)), margin = 1L, perm = invertPerm(p1, 0L, 1L)) P2. <- new("pMatrix", Dim = c(n, n), Dimnames = c(list(NULL), dn[2L]), margin = 2L, perm = if(length(p2)) invertPerm(p2, 0L, 1L) else seq_len(n)) if(complete) list(P1. = P1., Q = Q, R = R, P2. = P2.) else list(P1. = P1., Q1 = Q, R1 = triu(R), P2. = P2.) }) setMethod("qr.Q", c(qr = "sparseQR"), function(qr, complete = FALSE, Dvec) { m0 <- .qr.rank.def.warn(qr) if(missing(Dvec)) Dvec <- NULL else { storage.mode(Dvec) <- "double" if(length(Dvec) != qr@V@Dim[if(complete) 1L else 2L]) stop(gettextf("'%s' has the wrong length", "Dvec"), domain = NA) } Q <- .Call(sparseQR_matmult, qr, NULL, 4L, complete, Dvec) dn <- c(qr@Dimnames[1L], list(NULL)) if(!is.null(rn <- dn[[1L]])) { if(m0) length(rn) <- length(rn) + m0 if(is.unsorted(p1 <- qr@p, strictly = TRUE)) rn <- rn[p1 + 1L] dn[[1L]] <- rn } Q@Dimnames <- dn if(m0 && .qr.rank.def.truncating) { i <- seq_len(Q@Dim[1L] - m0) Q <- if(complete) Q[i, i, drop = FALSE] else Q[i, , drop = FALSE] } Q }) qrR <- function(qr, complete = FALSE, backPermute = TRUE, row.names = TRUE) { m0 <- .qr.rank.def.warn(qr) R <- qr@R d <- R@Dim m <- d[1L] n <- d[2L] dn <- qr@Dimnames p2 <- qr@q + 1L p2.uns <- is.unsorted(p2, strictly = TRUE) # FALSE if length is 0 if(!row.names) dn <- c(list(NULL), dn[2L]) else if(m0 && !is.null(rn <- dn[[1L]])) length(dn[[1L]]) <- length(rn) + m0 if(p2.uns && !is.null(cn <- dn[[2L]])) dn[[2L]] <- cn[p2] R@Dimnames <- dn R <- if(!complete && n < m) { if(backPermute && p2.uns) R[seq_len(n), invertPerm(p2), drop = FALSE] else R[seq_len(n), , drop = FALSE] } else { if(backPermute && p2.uns) R[, invertPerm(p2), drop = FALSE] else R } if(m0 && .qr.rank.def.truncating && complete) R <- R[seq_len(m - m0), , drop = FALSE] if(complete || backPermute) R else triu(R) } setMethod("qr.R", c(qr = "sparseQR"), function(qr, complete = FALSE, backPermute = FALSE, ...) qrR(qr, complete = complete, backPermute = backPermute, row.names = FALSE)) ## https://stat.ethz.ch/pipermail/r-devel/2023-June/082649.html setMethod("qr.X", c(qr = "sparseQR"), function(qr, complete = FALSE, ncol) { m0 <- .qr.rank.def.warn(qr) R <- qr@R d <- R@Dim m <- d[1L] n <- d[2L] if(missing(ncol)) ncol <- if(complete) m else min(m, n) else { ncol <- as.integer(ncol) if(ncol < 0L || ncol > m) stop(gettextf("invalid '%s': not in %d:%d", "ncol", 0L, m), domain = NA) } p2 <- qr@q + 1L p2.uns <- is.unsorted(p2, strictly = TRUE) # FALSE if length is 0 if(p2.uns && ncol < n) stop(gettextf("need greater '%s' as pivoting occurred", "ncol"), domain = NA) else if(ncol < n) R <- R[, seq_len(ncol), drop = FALSE] else if(ncol > n) { Rp <- R@p Ri <- R@i Rx <- R@x Rnnz <- Rp[length(Rp)] R@Dim[2L] <- ncol R@p <- c(Rp, Rnnz + seq_len(ncol - n)) R@i <- c(if(length(Ri) == Rnnz) Ri else Ri[seq_len(Rnnz)], n:(ncol - 1L)) R@x <- c(if(length(Rx) == Rnnz) Rx else Rx[seq_len(Rnnz)], rep.int(1, ncol - n)) } r <- .Call(sparseQR_matmult, qr, .sparse2dense(R), 4L, NA, NULL) if(p2.uns) { j <- invertPerm(p2) if(ncol > n) j <- c(j, (n + 1L):ncol) r <- r[, j, drop = FALSE] } dn <- qr@Dimnames if(m0 && !is.null(rn <- dn[[1L]])) length(dn[[1L]]) <- length(rn) + m0 if(!is.null(cn <- dn[[2L]]) && length(cn) != ncol) length(dn[[2L]]) <- ncol r@Dimnames <- dn if(m0 && .qr.rank.def.truncating) { i <- seq_len(r@Dim[1L] - m0) r <- if(ncol > length(j)) r[i, i, drop = FALSE] else r[i, , drop = FALSE] } r }) .qr.y0 <- function(y, m0) { d <- y@Dim d[1L] <- (m <- d[1L]) + m0 dn <- y@Dimnames if(!is.null(dn[[1L]])) length(dn[[1L]]) <- d[1L] y0 <- new("dgeMatrix") y0@Dim <- d y0@Dimnames <- dn y0@x <- as.double(`[<-`(array(0, d), seq_len(m), , y@x)) y0 } setMethod("qr.coef", c(qr = "sparseQR", y = "dgeMatrix"), function(qr, y) { if(m0 <- .qr.rank.def.warn(qr)) y <- .qr.y0(y, m0) r <- .Call(sparseQR_matmult, qr, y, 0L, NA, NULL) r@Dimnames <- c(qr@Dimnames[2L], y@Dimnames[2L]) r }) setMethod("qr.coef", c(qr = "sparseQR", y = "vector"), function(qr, y) drop(qr.coef(qr, .m2dense(y, ",ge")))) setMethod("qr.coef", c(qr = "sparseQR", y = "matrix"), function(qr, y) qr.coef(qr, .m2dense(y, ",ge"))) setMethod("qr.coef", c(qr = "sparseQR", y = "Matrix"), function(qr, y) qr.coef(qr, .m2dense(.M2m(y), ",ge"))) setMethod("qr.fitted", c(qr = "sparseQR", y = "dgeMatrix"), function(qr, y, k = qr$rank) { if(m0 <- .qr.rank.def.warn(qr)) y <- .qr.y0(y, m0) r <- .Call(sparseQR_matmult, qr, y, 1L, NA, NULL) r@Dimnames <- y@Dimnames if(m0 && .qr.rank.def.truncating) r <- r[seq_len(r@Dim[1L] - m0), , drop = FALSE] r }) setMethod("qr.fitted", c(qr = "sparseQR", y = "vector"), function(qr, y, k = qr$rank) drop(qr.fitted(qr, .m2dense(y, ",ge")))) setMethod("qr.fitted", c(qr = "sparseQR", y = "matrix"), function(qr, y, k = qr$rank) qr.fitted(qr, .m2dense(y, ",ge"))) setMethod("qr.fitted", c(qr = "sparseQR", y = "Matrix"), function(qr, y, k = qr$rank) qr.fitted(qr, .m2dense(.M2m(y), ",ge"))) setMethod("qr.resid", c(qr = "sparseQR", y = "dgeMatrix"), function(qr, y) { if(m0 <- .qr.rank.def.warn(qr)) y <- .qr.y0(y, m0) r <- .Call(sparseQR_matmult, qr, y, 2L, NA, NULL) r@Dimnames <- y@Dimnames if(m0 && .qr.rank.def.truncating) r <- r[seq_len(r@Dim[1L] - m0), , drop = FALSE] r }) setMethod("qr.resid", c(qr = "sparseQR", y = "vector"), function(qr, y) drop(qr.resid(qr, .m2dense(y, ",ge")))) setMethod("qr.resid", c(qr = "sparseQR", y = "matrix"), function(qr, y) qr.resid(qr, .m2dense(y, ",ge"))) setMethod("qr.resid", c(qr = "sparseQR", y = "Matrix"), function(qr, y) qr.resid(qr, .m2dense(.M2m(y), ",ge"))) setMethod("qr.qty", c(qr = "sparseQR", y = "dgeMatrix"), function(qr, y) { if(m0 <- .qr.rank.def.warn(qr)) y <- .qr.y0(y, m0) r <- .Call(sparseQR_matmult, qr, y, 3L, NA, NULL) r@Dimnames <- c(list(NULL), y@Dimnames[2L]) if(m0 && .qr.rank.def.truncating) r <- r[seq_len(r@Dim[1L] - m0), , drop = FALSE] r }) setMethod("qr.qty", c(qr = "sparseQR", y = "vector"), function(qr, y) drop(qr.qty(qr, .m2dense(y, ",ge")))) setMethod("qr.qty", c(qr = "sparseQR", y = "matrix"), function(qr, y) qr.qty(qr, .m2dense(y, ",ge"))) setMethod("qr.qty", c(qr = "sparseQR", y = "Matrix"), function(qr, y) qr.qty(qr, .m2dense(.M2m(y), ",ge"))) setMethod("qr.qy", c(qr = "sparseQR", y = "dgeMatrix"), function(qr, y) { if(m0 <- .qr.rank.def.warn(qr)) y <- .qr.y0(y, m0) r <- .Call(sparseQR_matmult, qr, y, 4L, NA, NULL) dn <- c(qr@Dimnames[1L], y@Dimnames[2L]) if(!is.null(rn <- dn[[1L]])) { if(m0) length(rn) <- length(rn) + m0 if(is.unsorted(p1 <- qr@p, strictly = TRUE)) rn <- rn[p1 + 1L] dn[[1L]] <- rn } r@Dimnames <- dn if(m0 && .qr.rank.def.truncating) r <- r[seq_len(r@Dim[1L] - m0), , drop = FALSE] r }) setMethod("qr.qy", c(qr = "sparseQR", y = "vector"), function(qr, y) drop(qr.qy(qr, .m2dense(y, ",ge")))) setMethod("qr.qy", c(qr = "sparseQR", y = "matrix"), function(qr, y) qr.qy(qr, .m2dense(y, ",ge"))) setMethod("qr.qy", c(qr = "sparseQR", y = "Matrix"), function(qr, y) qr.qy(qr, .m2dense(.M2m(y), ",ge"))) Matrix/R/diagonal.R0000644000175100001440000001301614575137654013660 0ustar hornikusers## METHODS FOR CLASS: diagonalMatrix (virtual) ## diagonal matrices ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("band", c(x = "diagonalMatrix"), function(x, k1, k2, ...) { if(k1 <= 0L && k2 >= 0L) return(x) r <- new(.M.nonvirtual(x)) r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames r@x <- vector(typeof(x@x), d[1L]) r }) setMethod("triu", c(x = "diagonalMatrix"), function(x, k = 0L, ...) { if(k <= 0L) return(x) r <- new(.M.nonvirtual(x)) r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames r@x <- vector(typeof(x@x), d[1L]) r }) setMethod("tril", c(x = "diagonalMatrix"), function(x, k = 0L, ...) { if(k >= 0L) return(x) r <- new(.M.nonvirtual(x)) r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames r@x <- vector(typeof(x@x), d[1L]) r }) setMethod("diag", c(x = "diagonalMatrix"), function(x = 1, nrow, ncol, names = TRUE) { kind <- .M.kind(x) r <- if(x@diag != "N") { one <- switch(kind, "n" = , "l" = TRUE, "i" = 1L, "d" = 1, "z" = 1+0i) rep.int(one, x@Dim[1L]) } else { y <- x@x if(kind == "n" && anyNA(y)) y | is.na(y) else y } if(names && !any(vapply(dn <- x@Dimnames, is.null, NA)) && { i <- seq_len(min(x@Dim)) identical(nms <- dn[[1L]][i], dn[[2L]][i]) }) names(r) <- nms r }) setMethod("diag<-", c(x = "diagonalMatrix"), function(x, value) { n <- x@Dim[2L] nv <- length(value) if(nv != 1L && nv != n) stop("replacement diagonal has wrong length") x@x <- if(is.logical(x@x)) switch(typeof(value), logical = rep_len(value, n), integer =, double = { x <- .M2kind(x, "d") rep_len(as.double(x), n) }, stop(gettextf("replacement diagonal has incompatible type \"%s\"", typeof(value)), domain = NA)) else switch(typeof(value), logical =, integer =, double = rep_len(as.double(value), n), stop(gettextf("replacement diagonal has incompatible type \"%s\"", typeof(value)), domain = NA)) x@diag <- "N" x }) setMethod("t", c(x = "diagonalMatrix"), function(x) { x@Dimnames <- x@Dimnames[2:1]; x }) setMethod("forceSymmetric", c(x = "diagonalMatrix", uplo = "missing"), function(x, uplo) .diag2sparse(x, ".", "s", "C", "U")) setMethod("forceSymmetric", c(x = "diagonalMatrix", uplo = "character"), function(x, uplo) .diag2sparse(x, ".", "s", "C", uplo)) setMethod("symmpart", c(x = "diagonalMatrix"), function(x) { kind <- .M.kind(x) r <- new(if(kind == "z") "zdiMatrix" else "ddiMatrix") r@Dim <- x@Dim r@Dimnames <- symDN(x@Dimnames) if(x@diag != "N") r@diag <- "U" else { y <- x@x r@x <- switch(kind, "n" = as.double(y | is.na(y)), "l" = , "i" = , "d" = as.double(y), "z" = complex(real = Re(y), imaginary = 0)) } r }) setMethod("skewpart", c(x = "diagonalMatrix"), function(x) { kind <- .M.kind(x) r <- new(if(kind == "z") "zdiMatrix" else "ddiMatrix") r@Dim <- d <- x@Dim r@Dimnames <- symDN(x@Dimnames) r@x <- if(kind == "z") { if(x@diag != "N") complex(d[1L]) else complex(real = 0, imaginary = Im(x@x)) } else double(d[1L]) r }) setMethod("isDiagonal", c(object = "diagonalMatrix"), function(object) TRUE) setMethod("isTriangular", c(object = "diagonalMatrix"), function(object, upper = NA, ...) if(is.na(upper)) `attr<-`(TRUE, "kind", "U") else TRUE) setMethod("isSymmetric", c(object = "diagonalMatrix"), function(object, checkDN = TRUE, ...) { if(checkDN) { ca <- function(check.attributes = TRUE, ...) check.attributes if(ca(...) && !isSymmetricDN(object@Dimnames)) return(FALSE) } .M.kind(object) != "z" || object@diag != "N" || { x <- object@x; isTRUE(all.equal.numeric(x, Conj(x), ...)) } }) Matrix/R/sparse.R0000644000175100001440000001377114575137654013407 0ustar hornikusers## METHODS FOR CLASS: sparseMatrix, [CRT]sparseMatrix (virtual) ## sparse matrices, in some cases restricted to CSC, CSR, triplet ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .sparse.band <- function(x, k1, k2, ...) .Call(R_sparse_band, x, k1, k2) .sparse.triu <- function(x, k = 0L, ...) .Call(R_sparse_band, x, k, NULL) .sparse.tril <- function(x, k = 0L, ...) .Call(R_sparse_band, x, NULL, k) .sparse.diag.get <- function(x = 1, nrow, ncol, names = TRUE) .Call(R_sparse_diag_get, x, names) .sparse.diag.set <- function(x, value) .Call(R_sparse_diag_set, x, value) .sparse.t <- function(x) .Call(R_sparse_transpose, x, FALSE) .sparse.fS1 <- function(x, uplo) .Call(R_sparse_force_symmetric, x, NULL) .sparse.fS2 <- function(x, uplo) .Call(R_sparse_force_symmetric, x, uplo) .sparse.symmpart <- function(x) .Call(R_sparse_symmpart, x) .sparse.skewpart <- function(x) .Call(R_sparse_skewpart, x) .sparse.is.di <- function(object) .Call(R_sparse_is_diagonal, object) .sparse.is.tr <- function(object, upper = NA, ...) .Call(R_sparse_is_triangular, object, upper) .sparse.is.sy <- function(object, checkDN = TRUE, ...) { if(checkDN) { ca <- function(check.attributes = TRUE, ...) check.attributes checkDN <- ca(...) } .Call(R_sparse_is_symmetric, object, checkDN) } .sparse.is.sy.dz <- function(object, checkDN = TRUE, tol = 100 * .Machine$double.eps, ...) { ## backwards compatibility: don't check DN if check.attributes=FALSE if(checkDN) { ca <- function(check.attributes = TRUE, ...) check.attributes checkDN <- ca(...) } ## be very fast when requiring exact symmetry if(tol <= 0) return(.Call(R_sparse_is_symmetric, object, checkDN)) ## pretest: is it square? d <- object@Dim if((n <- d[2L]) != d[1L]) return(FALSE) ## pretest: are DN symmetric in the sense of validObject()? if(checkDN && !isSymmetricDN(object@Dimnames)) return(FALSE) if(n == 0L) return(TRUE) ## now handling an n-by-n [dz]g[CRT]Matrix, n >= 1: Cj <- if(is.complex(object@x)) Conj else identity ae <- function(check.attributes, ...) { ## discarding possible user-supplied check.attributes all.equal(..., check.attributes = FALSE) } isTRUE(ae(target = .M2V( object ), current = .M2V(Cj(t(object))), tolerance = tol, ...)) } setMethod("diff", c(x = "sparseMatrix"), ## Mostly cut and paste of base::diff.default : function(x, lag = 1L, differences = 1L, ...) { if(length(lag) != 1L || length(differences) != 1L || lag < 1L || differences < 1L) stop(gettextf("'%s' and '%s' must be positive integers", "lag", "differences"), domain = NA) if(lag * differences >= x@Dim[1L]) return(x[0L]) i1 <- -seq_len(lag) for(i in seq_len(differences)) { m <- x@Dim[1L] x <- x[i1, , drop = FALSE] - x[-m:-(m - lag + 1L), , drop = FALSE] } x }) setMethod("mean", c(x = "sparseMatrix"), function(x, ...) mean(as(x, "sparseVector"), ...)) setMethod("rep", c(x = "sparseMatrix"), function(x, ...) rep(as(x, "sparseVector"), ...)) for(.cl in paste0(c("C", "R", "T"), "sparseMatrix")) { setMethod("band" , c(x = .cl), .sparse.band) setMethod("triu" , c(x = .cl), .sparse.triu) setMethod("tril" , c(x = .cl), .sparse.tril) setMethod("diag" , c(x = .cl), .sparse.diag.get) setMethod("diag<-", c(x = .cl), .sparse.diag.set) setMethod("t" , c(x = .cl), .sparse.t) setMethod("forceSymmetric", c(x = .cl, uplo = "missing"), .sparse.fS1) setMethod("forceSymmetric", c(x = .cl, uplo = "character"), .sparse.fS2) setMethod("symmpart", c(x = .cl), .sparse.symmpart) setMethod("skewpart", c(x = .cl), .sparse.skewpart) setMethod("isSymmetric" , c(object = .cl), .sparse.is.sy) setMethod("isTriangular", c(object = .cl), .sparse.is.tr) setMethod("isDiagonal" , c(object = .cl), .sparse.is.di) } .sparse.subclasses <- names(getClassDef("sparseMatrix")@subclasses) for(.cl in grep("^[dz][gt][CRT]Matrix$", .sparse.subclasses, value = TRUE)) setMethod("isSymmetric" , c(object = .cl), .sparse.is.sy.dz) rm(.cl, .sparse.subclasses) rm(list = c(grep("^[.]sparse[.](band|tri[ul]|diag[.](get|set)|t|fS[12]|symmpart|skewpart|is[.](sy|tr|di)([.]dz)?)$", ls(all.names = TRUE), value = TRUE))) if(FALSE) ### FIXME: This would *NOT* be needed, if as.matrix() was a no-op ; ### ----- and then, base::scale() -> base::scale.default() would work "magically" already.. scale.sparseMatrix <- function(x, center = FALSE, scale = TRUE) { if(center) warning("a sparseMatrix should rarely be centered: will not be sparse anymore") ## x <- as.matrix(x) ## This rest is *identically* == base :: scale.default : nc <- ncol(x) if (is.logical(center)) { if (center) { center <- colMeans(x, na.rm=TRUE) x <- sweep(x, 2L, center, check.margin=FALSE) } } else if (is.numeric(center) && (length(center) == nc)) x <- sweep(x, 2L, center, check.margin=FALSE) else stop("length of 'center' must equal the number of columns of 'x'") if (is.logical(scale)) { if (scale) { f <- function(v) { v <- v[!is.na(v)] sqrt(sum(v^2) / max(1, length(v) - 1L)) } scale <- apply(x, 2L, f) x <- sweep(x, 2L, scale, "/", check.margin=FALSE) } } else if (is.numeric(scale) && length(scale) == nc) x <- sweep(x, 2L, scale, "/", check.margin=FALSE) else stop("length of 'scale' must equal the number of columns of 'x'") if(is.numeric(center)) attr(x, "scaled:center") <- center if(is.numeric(scale)) attr(x, "scaled:scale") <- scale x } Matrix/R/is.na.R0000644000175100001440000003202714561451364013105 0ustar hornikusers## METHODS FOR GENERIC: anyNA ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("anyNA", c(x = "denseMatrix"), function(x, recursive = FALSE) { cl <- .M.nonvirtual(x) if(substr(cl, 1L, 1L) == "n") return(FALSE) if((shape <- substr(cl, 2L, 2L)) == "g") anyNA(x@x) else { if(shape == "t" && x@diag != "N") { x@diag <- "N" if(anyNA(diag(x, names = FALSE))) diag(x) <- TRUE } anyNA(pack(x)@x) } }) setMethod("anyNA", c(x = "sparseMatrix"), function(x, recursive = FALSE) .M.kind(x) != "n" && anyNA(x@x)) setMethod("anyNA", c(x = "diagonalMatrix"), function(x, recursive = FALSE) .M.kind(x) != "n" && length(y <- x@x) > 0L && anyNA(y)) setMethod("anyNA", c(x = "indMatrix"), function(x, recursive = FALSE) FALSE) setMethod("anyNA", c(x = "sparseVector"), function(x, recursive = FALSE) .M.kind(x) != "n" && anyNA(x@x)) ## METHODS FOR GENERIC: is.na ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("is.na", c(x = "denseMatrix"), function(x) { cl <- .M.nonvirtual(x) never <- substr(cl, 1L, 1L) == "n" substr(cl, 1L, 1L) <- "n" r <- new(cl) r@Dim <- x@Dim r@Dimnames <- x@Dimnames if((shape <- substr(cl, 2L, 2L)) != "g") { r@uplo <- x@uplo if(!never && shape == "t" && x@diag != "N") { x@diag <- "N" if(anyNA(diag(x, names = FALSE))) diag(x) <- TRUE } } r@x <- if(never) logical(length(x@x)) else is.na(x@x) r }) setMethod("is.na", c(x = "sparseMatrix"), function(x) { cl <- .M.nonvirtual(x) never <- substr(cl, 1L, 1L) == "n" substr(cl, 1L, 1L) <- if(never) "n" else "l" r <- new(cl) r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames if(substr(cl, 2L, 2L) != "g") r@uplo <- x@uplo if(never) { switch(substr(cl, 3L, 3L), "C" = { r@p <- integer(d[2L] + 1) }, "R" = { r@p <- integer(d[1L] + 1) }) r } else { switch(substr(cl, 3L, 3L), "C" = { r@p <- x@p; r@i <- x@i }, "R" = { r@p <- x@p; r@j <- x@j }, "T" = { r@i <- x@i; r@j <- x@j }) r@x <- is.na(x@x) .M2kind(.drop0(r), "n") } }) setMethod("is.na", c(x = "diagonalMatrix"), function(x) { r <- new("ndiMatrix") r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames r@x <- if(x@diag != "N" || .M.kind(x) == "n") logical(d[1L]) else is.na(x@x) r }) setMethod("is.na", c(x = "indMatrix"), function(x) { m <- x@margin r <- new(if(m == 1L) "ngRMatrix" else "ngCMatrix") r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames r@p <- integer(d[m] + 1) r }) setMethod("is.na", c(x = "sparseVector"), function(x) { r <- new("nsparseVector") r@length <- x@length if(.M.kind(x) != "n") r@i <- x@i[is.na(x@x)] r }) ## METHODS FOR GENERIC: is.nan ## NB: mostly parallel to is.na, completely parallel to is.infinite ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("is.nan", c(x = "denseMatrix"), function(x) { cl <- .M.nonvirtual(x) never <- switch(substr(cl, 1L, 1L), "d" = , "z" = FALSE, TRUE) substr(cl, 1L, 1L) <- "n" r <- new(cl) r@Dim <- x@Dim r@Dimnames <- x@Dimnames if((shape <- substr(cl, 2L, 2L)) != "g") { r@uplo <- x@uplo if(!never && shape == "t" && x@diag != "N") { x@diag <- "N" if(any(is.nan(diag(x, names = FALSE)))) diag(x) <- TRUE } } r@x <- if(never) logical(length(x@x)) else is.nan(x@x) r }) setMethod("is.nan", c(x = "sparseMatrix"), function(x) { cl <- .M.nonvirtual(x) never <- switch(substr(cl, 1L, 1L), "d" = , "z" = FALSE, TRUE) substr(cl, 1L, 1L) <- if(never) "n" else "l" r <- new(cl) r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames if(substr(cl, 2L, 2L) != "g") r@uplo <- x@uplo if(never) { switch(substr(cl, 3L, 3L), "C" = { r@p <- integer(d[2L] + 1) }, "R" = { r@p <- integer(d[1L] + 1) }) r } else { switch(substr(cl, 3L, 3L), "C" = { r@p <- x@p; r@i <- x@i }, "R" = { r@p <- x@p; r@j <- x@j }, "T" = { r@i <- x@i; r@j <- x@j }) r@x <- is.nan(x@x) .M2kind(.drop0(r), "n") } }) setMethod("is.nan", c(x = "diagonalMatrix"), function(x) { r <- new("ndiMatrix") r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames r@x <- if(x@diag != "N") logical(d[1L]) else switch(.M.kind(x), "d" = , "z" = is.nan(x@x), logical(d[1L])) r }) setMethod("is.nan", c(x = "indMatrix"), function(x) { m <- x@margin r <- new(if(m == 1L) "ngRMatrix" else "ngCMatrix") r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames r@p <- integer(d[m] + 1) r }) setMethod("is.nan", c(x = "sparseVector"), function(x) { r <- new("nsparseVector") r@length <- x@length switch(.M.kind(x), "d" = , "z" = { r@i <- x@i[is.nan(x@x)] }) r }) ## METHODS FOR GENERIC: is.infinite ## NB: mostly parallel to is.na, completely parallel to is.nan ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("is.infinite", c(x = "denseMatrix"), function(x) { cl <- .M.nonvirtual(x) never <- switch(substr(cl, 1L, 1L), "d" = , "z" = FALSE, TRUE) substr(cl, 1L, 1L) <- "n" r <- new(cl) r@Dim <- x@Dim r@Dimnames <- x@Dimnames if((shape <- substr(cl, 2L, 2L)) != "g") { r@uplo <- x@uplo if(!never && shape == "t" && x@diag != "N") { x@diag <- "N" if(any(is.infinite(diag(x, names = FALSE)))) diag(x) <- TRUE } } r@x <- if(never) logical(length(x@x)) else is.infinite(x@x) r }) setMethod("is.infinite", c(x = "sparseMatrix"), function(x) { cl <- .M.nonvirtual(x) never <- switch(substr(cl, 1L, 1L), "d" = , "z" = FALSE, TRUE) substr(cl, 1L, 1L) <- if(never) "n" else "l" r <- new(cl) r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames if(substr(cl, 2L, 2L) != "g") r@uplo <- x@uplo if(never) { switch(substr(cl, 3L, 3L), "C" = { r@p <- integer(d[2L] + 1) }, "R" = { r@p <- integer(d[1L] + 1) }) r } else { switch(substr(cl, 3L, 3L), "C" = { r@p <- x@p; r@i <- x@i }, "R" = { r@p <- x@p; r@j <- x@j }, "T" = { r@i <- x@i; r@j <- x@j }) r@x <- is.infinite(x@x) .M2kind(.drop0(r), "n") } }) setMethod("is.infinite", c(x = "diagonalMatrix"), function(x) { r <- new("ndiMatrix") r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames r@x <- if(x@diag != "N") logical(d[1L]) else switch(.M.kind(x), "d" = , "z" = is.infinite(x@x), logical(d[1L])) r }) setMethod("is.infinite", c(x = "indMatrix"), function(x) { m <- x@margin r <- new(if(m == 1L) "ngRMatrix" else "ngCMatrix") r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames r@p <- integer(d[m] + 1) r }) setMethod("is.infinite", c(x = "sparseVector"), function(x) { r <- new("nsparseVector") r@length <- x@length switch(.M.kind(x), "d" = , "z" = { r@i <- x@i[is.infinite(x@x)] }) r }) ## METHODS FOR GENERIC: is.finite ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("is.finite", c(x = "denseMatrix"), function(x) { cl <- .M.nonvirtual(x) always <- substr(cl, 1L, 1L) == "n" packed <- substr(cl, 3L, 3L) == "p" if((shape <- substr(cl, 2L, 2L)) != "s") r <- new("ngeMatrix") else { r <- new(if(!packed) "nsyMatrix" else "nspMatrix") r@uplo <- x@uplo } r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames r@x <- if(shape != "t") { if(always) rep.int(TRUE, length(x@x)) else is.finite(x@x) } else { if(always) rep.int(TRUE, prod(d)) else if(!packed) { tmp <- is.finite(x@x) tmp[indTri(d[1L], x@uplo != "U", x@diag != "N", FALSE)] <- TRUE tmp } else { tmp <- rep.int(TRUE, prod(d)) tmp[indTri(d[1L], x@uplo == "U", TRUE, FALSE)] <- is.finite(x@x) if(x@diag != "N") { dim(tmp) <- d diag(tmp) <- TRUE dim(tmp) <- NULL } tmp } } r }) setMethod("is.finite", c(x = "sparseMatrix"), function(x) { cl <- .M.nonvirtual(x) always <- substr(cl, 1L, 1L) == "n" if(substr(cl, 2L, 2L) != "s") r <- new("ngeMatrix") else { r <- new("nsyMatrix") r@uplo <- x@uplo } r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames tmp <- rep.int(TRUE, prod(d)) if(!always && !all(k <- is.finite(x@x))) { if(substr(cl, 3L, 3L) != "T") { x <- .M2T(x) if(length(k) > length(x@x)) # was overallocated k <- is.finite(x@x) } i <- c(x@i, x@j) + 1L dim(i) <- c(length(k), 2L) dim(tmp) <- d tmp[i] <- k dim(tmp) <- NULL } r@x <- tmp r }) setMethod("is.finite", c(x = "diagonalMatrix"), function(x) { r <- new("nsyMatrix") r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames tmp <- rep.int(TRUE, prod(d)) if(x@diag == "N" && .M.kind(x) != "n" && !all(k <- is.finite(x@x))) { dim(tmp) <- d diag(tmp) <- k dim(tmp) <- NULL } r@x <- tmp r }) setMethod("is.finite", c(x = "indMatrix"), function(x) { r <- new("ngeMatrix") r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames r@x <- rep.int(TRUE, prod(d)) r }) setMethod("is.finite", c(x = "sparseVector"), function(x) { r <- rep.int(TRUE, x@length) if(.M.kind(x) != "n") r[x@i[!is.finite(x@x)]] <- FALSE r }) Matrix/R/nearPD.R0000644000175100001440000001122314466777721013255 0ustar hornikusers## Copyright (C) 2007-2019 Martin Maechler ## ## nearcor.R : ## Copyright (C) 2007 Jens Oehlschlägel ## ## 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. ## ## A copy of the GNU General Public License is available at ## https://www.R-project.org/Licenses/ nearPD <- ## Computes the nearest correlation matrix to an approximate ## correlation matrix, i.e. not positive semidefinite. function(x # n-by-n approx covariance/correlation matrix , corr = FALSE, keepDiag = FALSE , base.matrix = FALSE # if TRUE return "base matrix" otherwise "dpoMatrix" , do2eigen = TRUE # if TRUE do a sfsmisc::posdefify() eigen step , doSym = FALSE # symmetrize after tcrossprod() , doDykstra = TRUE # do use Dykstra's correction , only.values = FALSE# if TRUE simply return lambda[j]. , ensureSymmetry = !isSymmetric(x)# so user can set to FALSE iff she knows.. , eig.tol = 1e-6 # defines relative positiveness of eigenvalues compared to largest , conv.tol = 1e-7 # convergence tolerance for algorithm , posd.tol = 1e-8 # tolerance for enforcing positive definiteness , maxit = 100L # maximum number of iterations allowed , conv.norm.type = "I" , trace = FALSE # set to TRUE (or 1 ..) to trace iterations ) { if(ensureSymmetry) { ## only if needed/wanted ... ## message("applying nearPD() to symmpart(x)") x <- symmpart(x) } n <- ncol(x) if(keepDiag) diagX0 <- diag(x) if(doDykstra) { ## D_S should be like x, but filled with '0' -- following also works for 'Matrix': D_S <- x; D_S[] <- 0 } X <- x iter <- 0L ; converged <- FALSE; conv <- Inf while (iter < maxit && !converged) { Y <- X if(doDykstra) R <- Y - D_S ## project onto PSD matrices X_k = P_S (R_k) e <- eigen(if(doDykstra) R else Y, symmetric = TRUE) ## Q <- e$vectors d <- e$values ## D <- diag(d) ## create mask from relative positive eigenvalues p <- d > eig.tol*d[1] if(!any(p)) stop("Matrix seems negative semi-definite") ## use p mask to only compute 'positive' part Q <- Q[,p, drop = FALSE] ## X <- Q %*% D[p,p,drop = FALSE] %*% t(Q) --- more efficiently : X <- tcrossprod(Q * rep(d[p], each=nrow(Q)), Q) if(doDykstra) ## update Dykstra's correction D_S = \Delta S_k D_S <- X - R ## project onto symmetric and possibly 'given diag' matrices: if(doSym) X <- (X + t(X))/2 if(corr) diag(X) <- 1 else if(keepDiag) diag(X) <- diagX0 conv <- norm(Y-X, conv.norm.type) / norm(Y, conv.norm.type) iter <- iter + 1L if (trace) cat(sprintf("iter %3d : #{p}=%d, ||Y-X|| / ||Y||= %11g\n", iter, sum(p), conv)) converged <- (conv <= conv.tol) } if(!converged) warning(gettextf("'nearPD()' did not converge in %d iterations", iter), domain = NA) ## force symmetry is *NEVER* needed, we have symmetric X here! ## X <- (X + t(X))/2 if(do2eigen || only.values) { ## begin from posdefify(sfsmisc) e <- eigen(X, symmetric = TRUE) d <- e$values Eps <- posd.tol * abs(d[1]) if (d[n] < Eps) { d[d < Eps] <- Eps if(!only.values) { Q <- e$vectors o.diag <- diag(X) X <- Q %*% (d * t(Q)) D <- sqrt(pmax(Eps, o.diag)/diag(X)) X[] <- D * X * rep(D, each = n) } } if(only.values) return(d) ## unneeded(?!): X <- (X + t(X))/2 if(corr) diag(X) <- 1 else if(keepDiag) diag(X) <- diagX0 } ## end from posdefify(sfsmisc) r <- if(base.matrix) X else new("dpoMatrix", Dim = c(n, n), Dimnames = dimnames(x) %||% list(NULL, NULL), x = as.vector(X)) structure(list(mat = r, eigenvalues = d, corr = corr, normF = norm(x - X, "F"), iterations = iter, rel.tol = conv, converged = converged), class = "nearPD") } Matrix/R/Schur.R0000644000175100001440000001221214574651323013154 0ustar hornikusers## METHODS FOR GENERIC: Schur ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("Schur", c(x = "dgeMatrix"), function(x, vectors = TRUE, ...) { if(length(x.x <- x@x) && !all(is.finite(range(x.x)))) stop(gettextf("'%s' has non-finite values", "x"), domain = NA) cl <- .Call(dgeMatrix_sch, x, vectors, TRUE) if(all(cl$WI == 0)) { vals <- cl$WR T <- triu(cl$T) } else { vals <- complex(real = cl$WR, imaginary = cl$WI) T <- .m2dense(cl$T, ",ge") } if(vectors) new("Schur", Dim = x@Dim, Dimnames = x@Dimnames, Q = .m2dense(cl$Z, ",ge"), T = T, EValues = vals) else list(T = T, EValues = vals) }) setMethod("Schur", c(x = "dsyMatrix"), function(x, vectors = TRUE, ...) { e <- eigen(x, symmetric = TRUE, only.values = !vectors) vals <- as.double(e$values) T <- new("ddiMatrix", Dim = x@Dim, x = vals) if(vectors) new("Schur", Dim = x@Dim, Dimnames = symDN(x@Dimnames), Q = .m2dense(e$vectors, ",ge"), T = T, EValues = vals) else list(T = T, EValues = vals) }) setMethod("Schur", c(x = "matrix"), function(x, vectors = TRUE, ...) { ## FIXME: wrong for complex, but package 'control' seems to ## rely on the complex->double coercion (!?) storage.mode(x) <- "double" if(length(x) && !all(is.finite(range(x)))) stop(gettextf("'%s' has non-finite values", "x"), domain = NA) cl <- .Call(dgeMatrix_sch, x, vectors, FALSE) vals <- if(all(cl$WI == 0)) cl$WR else complex(real = cl$WR, imaginary = cl$WI) if(vectors) list(Q = cl$Z, T = cl$T, EValues = vals) else list(T = cl$T, EValues = vals) }) ## FIXME: don't coerce from sparse to dense setMethod("Schur", c(x = "generalMatrix"), function(x, vectors = TRUE, ...) Schur(.M2unpacked(.M2kind(x, ",")), vectors, ...)) ## FIXME: don't coerce from sparse to dense setMethod("Schur", c(x = "symmetricMatrix"), function(x, vectors = TRUE, ...) Schur(.M2unpacked(.M2kind(x, ",")), vectors, ...)) setMethod("Schur", c(x = "triangularMatrix"), function(x, vectors = TRUE, ...) { x <- .M2kind(x, ",") n <- (d <- x@Dim)[1L] if(n == 0L) x@uplo <- "U" else if(.M.kind(x) != "n" && !all(is.finite(range(x)))) stop(gettextf("'%s' has non-finite values", "x"), domain = NA) vals <- diag(x, names = FALSE) if(x@uplo == "U") { if(vectors) { Q <- new("ddiMatrix", Dim = d, diag = "U") new("Schur", Dim = d, Dimnames = x@Dimnames, Q = Q, T = x, EValues = vals) } else list(T = x, EValues = vals) } else { perm <- n:1L vals <- vals[perm] T <- triu(x[perm, perm, drop = FALSE]) if(vectors) { Q <- new("pMatrix", Dim = d, perm = perm) new("Schur", Dim = d, Dimnames = x@Dimnames, Q = Q, T = T, EValues = vals) } else list(T = x, EValues = vals) } }) setMethod("Schur", c(x = "diagonalMatrix"), function(x, vectors = TRUE, ...) { x <- .M2kind(x, ",") d <- x@Dim if(x@diag != "N") { vals <- rep.int(1, d[1L]) T <- new("ddiMatrix", Dim = d, diag = "U") } else { vals <- x@x if(length(vals) && !all(is.finite(range(vals)))) stop(gettextf("'%s' has non-finite values", "x"), domain = NA) T <- new("ddiMatrix", Dim = d, x = vals) } if(vectors) { Q <- new("ddiMatrix", Dim = d, diag = "U") new("Schur", Dim = d, Dimnames = x@Dimnames, Q = Q, T = T, EValues = vals) } else list(T = T, EValues = vals) }) ## METHODS FOR CLASS: Schur ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("expand1", c(x = "Schur"), function(x, which, ...) switch(which, "Q" = x@Q, "T" = x@T, "Q." = t(x@Q), stop(gettextf("'%1$s' is not \"%2$s\", \"%3$s\", or \"%2$s.\"", "which", "Q", "T"), domain = NA))) setMethod("expand2", c(x = "Schur"), function(x, ...) { Q <- x@Q Q. <- t(Q) dn <- x@Dimnames Q @Dimnames <- c(dn[1L], list(NULL)) Q.@Dimnames <- c(list(NULL), dn[2L]) list(Q = Q, T = x@T, Q. = Q.) }) Matrix/R/rankMatrix.R0000644000175100001440000001427214516234475014221 0ustar hornikusers#### Determine *the* rank of a matrix #### -------------------------------- ## ## As this is not such a well-defined problem as people think, ## we provide *some* possibilities here, including the Matlab one. ## ## Ideas by Martin Maechler (April 2007) and Ravi Varadhan (October 2007) qr2rankMatrix <- function(qr, tol = NULL, isBqr = is.qr(qr), do.warn=TRUE) { ## NB: 1) base::qr(*, LAPACK = TRUE/FALSE) differ via attr(.,"useLAPACK") ## 2) if LAPACK=TRUE, .$rank is useless (always = full rank) ## ## return ( . ) : if(isBqr && !isTRUE(attr(qr, "useLAPACK"))) qr$rank else { diagR <- if(isBqr) # hence "useLAPACK" here diag(qr$qr) # faster than, but equivalent to diag(qr.R(q.r)) else ## ==> assume Matrix::qr() i.e., currently "sparseQR" ## FIXME: Here, we could be quite a bit faster, ## by not returning the full sparseQR, but just ## doing the following in C, and return the rank. diag(qr@R) if(anyNA(diagR) || !all(is.finite(diagR))) { if(do.warn) { ifi <- is.finite(diagR) warning(gettextf( "qr2rankMatrix(.): QR with only %d out of %d finite diag(R) entries", sum(ifi), length(ifi))) } ## return NA_integer_ ## alternative: gives *too* small rank in typical cases ## reduce the maximal rank by omitting all non-finite entries: ## diagR <- diagR[is.finite(diagR)] ## if(length(diagR) == 0) ## return(NA_integer_) } else { diagR <- abs(diagR) # sign( diag(R) ) are *not* coerced to positive ## declare those entries to be zero that are < tol*max(.) if((mdi <- max(diagR, na.rm=TRUE)) > 0) { if(!is.numeric(tol)) { ## d := dim(x) extracted from qr, in both (dense and sparse) qr() cases d <- dim(if(isBqr) qr$qr else qr) tol <- max(d) * .Machine$double.eps } sum(diagR >= tol * mdi) ## was sum(diag(q.r@R) != 0) } else 0L # for 0-matrix or all NaN or negative diagR[] } } ## else {Lapack or sparseQR} } rankMatrix <- function(x, tol = NULL, method = c("tolNorm2", "qr.R", "qrLINPACK", "qr", "useGrad", "maybeGrad"), sval = svd(x, 0,0)$d, warn.t = TRUE, warn.qr = TRUE) { ## Purpose: rank of a matrix ``as Matlab'' or "according to Ravi V" ## ---------------------------------------------------------------------- ## Arguments: x: a numerical matrix, maybe non-square ## tol: numerical tolerance (compared to singular values) ## sval: vector of non-increasing singular values of x ## (pass as argument if already known) ## ---------------------------------------------------------------------- ## Author: Martin Maechler, Date: 7 Apr 2007, 16:16 ## ---------------------------------------------------------------------- ## ## maybeGrad (Ravi V.): This algorithm determines the rank based on the ## "gradient" of the ## absolute, singular values, rather than enforcing a rigid ## tolerance criterion, ## ## Author: Ravi Varadhan, Date: 22 October 2007 // Tweaks: MM, Oct.23 ## ---------------------------------------------------------------------- stopifnot(length(d <- dim(x)) == 2) p <- min(d) ## miss.meth <- missing(method) method <- match.arg(method) if(useGrad <- (method %in% c("useGrad", "maybeGrad"))) { stopifnot(length(sval) == p) if(p > 1) stopifnot(diff(sval) <= 0) # must be sorted non-increasingly: max = s..[1] if(sval[1] == 0) { ## <==> all singular values are zero <==> Matrix = 0 <==> rank = 0 useGrad <- FALSE method <- eval(formals()[["method"]])[[1]] } else { ln.av <- log(abs(sval)) if(any(s0 <- sval == 0)) ln.av[s0] <- - .Machine$double.xmax # so we get diff() == 0 diff1 <- diff(ln.av) if(method == "maybeGrad") { grad <- (min(ln.av) - max(ln.av)) / p useGrad <- !is.na(grad) && p > 1 && min(diff1) <= min(-3, 10 * grad) }# ------- } } if(!useGrad) { x.dense <- is.numeric(x) || is(x,"denseMatrix") ## "qr" is allowed for backcompatibility [change @ 2013-11-24] if((Meth <- method) == "qr") method <- if(x.dense) "qrLINPACK" else "qr.R" else Meth <- substr(method, 1,2) if(Meth == "qr") { if(is.null(tol)) tol <- max(d) * .Machine$double.eps } else { ## (Meth != "qr"), i.e. "tolNorm2" if(is.null(tol)) { if(!x.dense && missing(sval) && prod(d) >= 100000L) warning(gettextf( "rankMatrix(, method = '%s') coerces to dense matrix. Probably should rather use method = 'qr' !?", method), immediate.=TRUE, domain=NA) ## the "Matlab" default: if(p > 1) stopifnot(diff(sval) <= 0) #=> sval[1]= max(sval) tol <- max(d) * .Machine$double.eps } else stopifnot((tol <- as.numeric(tol)[[1]]) >= 0) } } structure(## rank : if(useGrad) which.min(diff1) else if(Meth == "qr") { if((do.t <- (d[1L] < d[2L])) && warn.t) warning(gettextf( "rankMatrix(x, method='qr'): computing t(x) as nrow(x) < ncol(x)")) q.r <- qr(if(do.t) t(x) else x, tol=tol, LAPACK = method != "qrLINPACK") qr2rankMatrix(q.r, tol=tol, isBqr = x.dense, do.warn = warn.qr) } else if(sval[1] > 0) sum(sval >= tol * sval[1]) else 0L, ## "tolNorm2" "method" = method, "useGrad" = useGrad, "tol" = if(useGrad) NA else tol) } ## Ravi's plot of the absolute singular values: if(FALSE) { ## if (plot.eigen) { plot(abs(sval), type = "b", xlab = "Index", xaxt = "n", log = "y", ylab = "|singular value| [log scaled]") axis(1, at = unique(c(axTicks(1), rank, p))) abline(v = rank, lty = 3) mtext(sprintf("rank = %d (used %s (%g))", rank, if(use.grad)"'gradient'" else "fixed tol.", if(use.grad) min(diff1) else tol)) } Matrix/R/abstract.R0000644000175100001440000005666614575137654013727 0ustar hornikusers#### Methods for the "abIndex" := ``abstract Index'' class ### Note: this partly builds on ideas and code from Jens Oehlschlaegel, ### ---- as implemented (in the GPL'ed part of) package 'ff'. ## Basic idea: a vector x of integer indices often has long stretches ## i, i+1, i+2, ... such that diff(x) has stretches of '1'. ## Now keep x[1] =: first and diff(x) =: d, ## and use rle() to encode d. Here, use a C version for rle() rleMaybe <- function(i, force = FALSE) { ## TODO: move all this to a new C fnc., still keeping the *_i() and *_d() if(is.na(force <- as.logical(force))) stop("'force' must be (coercable to) TRUE or FALSE") int <- is.integer(i) || is.logical(i) || { i. <- suppressWarnings(as.integer(i)) if(r <- isTRUE(all(is.na(i) | i. == i))) i <- i. r } ## if(int), 'i' will be coerced to integer on C level ##N R-devel codetools get FP again: ##N Matrix.rle <- if(int) Matrix_rle_i else Matrix_rle_d ##N .Call(Matrix.rle, i, force) if(int) Matrix_rle_d <- Matrix_rle_i .Call(Matrix_rle_d, i, force) } .rle <- function(lengths, values) structure(list(lengths = lengths, values = values), class = "rle") ##' @param x ##' ##' @return diff(x), giving '0' for 'Inf - Inf' or similar .diff <- function(x) { ## TODO: considerably faster in C if((n <- length(x)) <= 1) return(x[0]) r <- (x1 <- x[-1]) - (x2 <- x[-n]) if(any(ina <- is.na(r))) r[ina & (x1 == x2 | (is.na(x1) & is.na(x2)))] <- 0 r } ##' @param from: logical or numeric vector ##' ##' @return an "abIndex" vector, "semantically equivalent" to 'from' vec2abI <- function(from, force = FALSE) { ans <- new("abIndex") r <- rleMaybe(.diff(from), force=force)## .diff(): also work for rep(Inf, *) if(is.null(r)) { ## no "compression" ans@kind <- if(is.integer(from)) "int32" else "double" ans@x <- from } else { ans@kind <- "rleDiff" ## ans@x <- integer(0) # <- prototype does that ans@rleD <- new("rleDiff", first = from[1], rle = r) } ans } ## "abIndex" version of indDiag(n) === which(diag(n) == 1) -> ./Auxiliaries.R abIindDiag <- function(n) { ## cumsum(c(1L, rep.int(n+1L, n-1))) stopifnot((n <- as.integer(n)) >= 1) rl <- if(n == 1) .rle(n[0],n[0]) else .rle(n-1L, n+1L) new("abIndex", kind = "rleDiff", rleD = new("rleDiff", first = 1, rle = rl)) } ## "abIndex" version of indTri(n) ... --> ./Auxiliaries.R abIindTri <- function(n, upper = TRUE, diag = FALSE) { ## Indices of strict upper/lower triangular part ## == which(upper.tri(diag(n), diag=diag) or ## which(lower.tri(diag(n), diag=diag) -- but as abIndex stopifnot(length(n) == 1, n == (n. <- as.integer(n)), (n <- n.) >= 0) if(n <= 2) { vec2abI( if(n == 0) integer(0) else if(n == 1) { if(diag) 1L else integer(0) } else { ## n == 2 v <- if(upper) 3L else 2L if(diag) c(1L, v, 4L) else v }) } else { ## n >= 3 [also for n == 2 && diag (==TRUE)] : ## First, compute the 'diff(.)' of the result [fast, using integers] n. <- if(diag) n else n - 1L n1 <- n. - 1L tt <- if(diag) 2L else 3L mk1s <- function(n,m) as.vector(rbind(1L, n:m)) mks1 <- function(n,m) as.vector(rbind(n:m, 1L)) rl <- .rle(lengths= if(upper) mk1s(1L,n1) else mks1(n1,1L), values = if(upper) mks1(n, tt) else mk1s(tt, n)) frst <- if(diag) 1L else if(upper) n+1L else 2L new("abIndex", kind = "rleDiff", rleD = new("rleDiff", first = frst, rle = rl)) } } setAs("numeric", "abIndex", function(from) vec2abI(from)) setAs("logical", "abIndex", function(from) vec2abI(from)) setMethod("show", c(object = "rleDiff"), function(object) { cat(sprintf(## first can be 'NULL' --> cannot use %g " RLE difference (class 'rleDiff'): first = %s, \"rle\":%s", format(object@first), if(length(rl <- object@rle)) "\n" else " ")) print(rl, prefix = " ") invisible(object) }) setMethod("show", c(object = "abIndex"), function(object) { knd <- object@kind cat(sprintf( "Abstract Index vector (class 'abIndex') of length %.0f, kind \"%s\"\n", length(object), knd)) if(knd == "rleDiff") { ### FIXME: show something like this is equivalent to c(2:10, 13:34, ...) cat(" and slot \"rleD\":\n") show(object@rleD) } else { cat(" and \"x\" slot\n") show(object@x) } invisible(object) }) ##' Constructor of "abIndex" version of n:m ##' @param from ##' @param to ##' ##' @return an "abIndex" object semantically equivalent to from:to abIseq1 <- function(from = 1, to = 1) { stopifnot(length(from) == 1L, length(to) == 1L) to <- to - from new("abIndex", kind="rleDiff", rleD = new("rleDiff", first = as.integer(from), rle = .rle(lengths = abs(to),# <- double : maybe > .Machine$integer.max values = as.integer(sign(to))))) } ## an "abIndex" version of seq(), i.e. seq.default(): abIseq <- function(from = 1, to = 1, by = ((to - from)/(length.out - 1)), length.out = NULL, along.with = NULL) { if((One <- nargs() == 1L) && !missing(from)) { lf <- length(from) return(if(mode(from) == "numeric" && lf == 1L) abIseq1(1L, from) else if(lf) abIseq1(1L, lf) else new("abIndex")) } if(!missing(along.with)) { length.out <- length(along.with) if(One) return(if(length.out) abIseq1(1L, length.out) else new("abIndex")) } else if(!missing(length.out)) length.out <- ceiling(length.out) if(is.null(length.out)) if(missing(by)) abIseq1(from,to) else { # dealing with 'by' del <- to - from if(del == 0 && to == 0) return(as(to, "abIndex")) n <- del/by if(!(length(n) && is.finite(n))) { if(length(by) && by == 0 && length(del) && del == 0) return(as(from, "abIndex")) stop("invalid (to - from)/by in seq(.)") } if(n < 0L) stop("wrong sign in 'by' argument") if(n > .Machine$integer.max) stop("'by' argument is much too small") dd <- abs(del)/max(abs(to), abs(from)) if (dd < 100*.Machine$double.eps) return(from) n <- as.integer(n + 1e-7) x <- from + abIseq1(0L,n) * by ## correct for overshot because of fuzz -- FIXME: need pmin() for "abIndex": if(by > 0) pmin(x, to) else pmax(x, to) } else if(!is.finite(length.out) || length.out < 0L) stop("length must be non-negative number") else if(length.out == 0L) new("abIndex") else if (One) abIseq1(1L, length.out) else if(missing(by)) { # if(from == to || length.out < 2) by <- 1 if(missing(to)) to <- from + length.out - 1L if(missing(from)) from <- to - length.out + 1L if(length.out > 2L) if(from == to) rep2abI(from, length.out) ## rep.int(from, length.out) else c(as(from,"abIndex"), from + abIseq1(1L, length.out - 2L) * by, to) else as(c(from, to)[seq_len(length.out)],"abIndex") } else if(missing(to)) from + abIseq1(0L, length.out - 1L) * by else if(missing(from)) to - abIseq1(length.out - 1L, 0L) * by else stop("too many arguments") } ##' rep.int(x, times) " as abIndex " ##' @param x numeric vector ##' @param times integer (valued) scalar: the number of repetitions ##' ##' @return an "abIndex" vector rep2abI <- function(x, times) { r <- new("abIndex") if((n <- length(x)) == 0) return(r) if(n == 1) { # clear case for compression r@kind <- "rleDiff" rD <- new("rleDiff") rD@first <- x[1L] rD@rle <- .rle(lengths = times - 1L, values = 0L) r@rleD <- rD } else { ## n >= 2 .. check if compression is worth it: ## .. say if compression of x itself is worth {FIXME? optimal cutoff} rr <- rleMaybe(.diff(x)) if(is.null(rr)) { r@kind <- if(is.integer(x)) "int32" else "double" r@x <- rep.int(x, times) } else { r@kind <- "rleDiff" rD <- new("rleDiff") rD@first <- x[1L] Dx <- x[1L] - x[length(x)] N <- (length(rr$lengths) + 1L)*times rD@rle <- .rle(lengths = rep.int(c(rr$lengths, 1L), times)[-N], values = rep.int(c(rr$values, Dx), times)[-N]) r@rleD <- rD } } r } combine_rleD <- function(rleList, m = length(rleList)) { ## Combine list of "rleDiff"s into a new one -- for c(..) ## auxiliary (and main working horse) for c.abIndex() ### TODO: really should do this in C i1 <- unlist(lapply(rleList, slot, "first")) rles <- lapply(rleList, slot, "rle") ## the list of vectors of 'lengths' and 'values' : lens <- lapply(rles, `[[`, "lengths") vals <- lapply(rles, `[[`, "values") ## the 'ends' are needed for the "jump sizes" in between: ends2 <- function(x) # related to ends.rleD() above x@first + c(0, with(x@rle, sum(lengths*values))) ends <- unlist(lapply(rleList, ends2))[-c(1, 2*m)] ii <- 2L*seq_len(m - 1) d.ends <- ends[ii] - ends[ii-1L] ## llen1 <- unlist(lapply(lens, length)) + 1L ## n <- sum(llen1) n <- m + sum(lengths(lens, use.names=FALSE)) ## comb(): intersperse x2[[j]] between lis[[j] & lis[[j+1]] : comb <- function(lis, x2) unlist(mapply(c, lis, x2, SIMPLIFY=FALSE, USE.NAMES=FALSE)) n.len <- comb(lens, 1L)[-n] n.val <- comb(vals, c(d.ends,NA))[-n] new("rleDiff", first = i1[1], rle = .rle(lengths = n.len, values = n.val)) } ## {combine_rleD} ## For now -- S4 method on c(), i.e., setMethod("c", ...) ## seems "difficult", and this works "magically" ## when the first argument is an abIndex : c.abIndex <- function(...) { m <- length(list(...)) if(m <= 1) return(if(m == 0) new("abIndex") else as(..1, "abIndex")) ## else: have length m >= 2 labi <- lapply(list(...), as, Class = "abIndex") knd <- unlist(lapply(labi, slot, "kind")) ## Convention: Result kind should be the 'kind' of the first neq.k <- knd != (k1 <- knd[1]) if(any(neq.k)) { if(all(not.rD <- knd != "rleDiff")) { ## either "double" or "int32" .. using 'x' k1 <- "double" ## and it will just work to c(.) the 'x' slots } else { warning("c(,..) of different kinds, coercing all to 'rleDiff'") labi[not.rD] <- lapply(labi[not.rD], function(av) vec2abI(av@x, force=TRUE)) k1 <- "rleDiff" } } switch(k1, "rleDiff" = { new("abIndex", kind="rleDiff", rleD = combine_rleD(lapply(labi, slot, "rleD"), m)) }, "double" =, "int32" = { new("abIndex", kind = k1, x = do.call(c, lapply(labi, slot, "x"))) }) } setMethod("length", c(x = "abIndex"), function(x) if(identical(x@kind, "rleDiff")) sum(x@rleD@rle$lengths)+ 1L else length(x@x)) abI2num <- function(from) { switch(from@kind, "rleDiff" = { x <- from@rleD ## as inverse.rle(): cumsum(c(x@first, rep.int(x@rle$values, x@rle$lengths))) }, "int32" =, "double" = from@x) } setAs("abIndex", "numeric", abI2num) setAs("abIndex", "vector", abI2num) setAs("abIndex", "integer", function(from) as.integer(abI2num(from))) ## for S3 lovers and back-compatibility: setMethod("as.integer", c(x = "abIndex"), function(x, ...) as.integer(abI2num(x))) setMethod("as.numeric", c(x = "abIndex"), function(x, ...) abI2num(x)) setMethod("as.vector" , c(x = "abIndex"), function(x, mode = "any") as.vector(abI2num(x), mode)) ## Need max(), min(), all( == ) any( == ) ## ---> Groups "Summary" and "Compare" (maybe all "Ops") ## For that, we really need "[" and/or "rep"() methods -- TODO -- ## setMethod("[", c(x = "abIndex", i = "index"), function (x, i, j, ..., drop) { switch(x@kind, "rleDiff" = { ## FIXME ## intIv() in ./sparseVector.R -- not memory-efficient (??) ## n <- length(x) ## ii <- intIv(i, n) ## ii : 1-based integer indices ## d <- x@rleD ## Now work with the equivalent of ## cumsum(c(d@first, rep.int(d@rle$values, d@rle$lengths))) stop("[i] is not yet implemented") }, "int32" =, "double" = ## as it's not rle-packed, can remain simple: x@x[i]) }) ##' Endpoints of all linear stretches -- auxiliary for range(.) ##' @param x an "rleDiff" object ##' ##' @return numeric vector of end points of all linear stretches of x. ends.rleD <- function(x) { rl <- x@rle stopifnot(length(lens <- rl$lengths) == length(vals <- rl$values)) cumsum(c(x@first, lens*vals)) } ##' Collapse or "uniquify" an 'rle' object, i.e., ##' 1) drop 'lengths' 0 parts ##' 2) *merge* adjacent parts where 'values' are the same ##' ##' @param x an "rle" object ##' ##' @return an "rle" object, a "unique" version of the input 'x' rleCollapse <- function(x) { ## TODO: faster (and simpler!) in C ## TODO(2): move this to 'R base' L <- x$lengths V <- x$values chng <- FALSE if((chng <- any(i0 <- L == 0))) { ## drop 0 'lengths' parts L <- L[!i0] ; V <- V[!i0] } ## FIXME: This is not elegant nor efficient: while(any(i0 <- diff(V) == 0)) { ## merge adjacent parts with same values if(!chng) chng <- TRUE ## fix one stretch (and repeat), starting at ii0 and total length 1+ li0 ii0 <- which.max(i0)# index of first TRUE li0 <- if((l0 <- length(i0)) <= ii0) 1 else which.min(!i0[ii0:l0]) stopifnot(li0 >= 1)## <- for now L[ii0] <- sum(L[ii0+(0:li0)]) ii <- -(ii0 + seq_len(li0)) L <- L[ii] V <- V[ii] } if(chng) { x$lengths <- L ; x$values <- V } x } ## {rleCollapse} setMethod("drop", c(x = "abIndex"), function(x) { if(x@kind == "rleDiff") x@rleD@rle <- rleCollapse(x@rleD@rle) x }) ## Summary: { max, min, range, prod, sum, any, all } : ## have 'summGener1' := those without prod, sum setMethod("Summary", c(x = "abIndex"), function(x, ..., na.rm) { switch(x@kind, "rleDiff" = { d <- x@rleD if(.Generic %in% c("range","min","max")) { callGeneric(ends.rleD(d), ..., na.rm=na.rm) } else { ## "sum", "prod" : switch(.Generic, "all" = { ## these often, but *not* always come in pairs ## en <- ends.rleD(d) ## so maybe it does not really help! stop("all() is not yet implemented") ## all(c(d@first, d@rle$values), ..., na.rm=na.rm) }, "any" = any(c(d@first, d@rle$values), ..., na.rm=na.rm), "sum" = { stop("sum() is not yet implemented") }, "prod"= { stop("prod() is not yet implemented") }) } }, "int32" =, "double" = callGeneric(x@x, ..., na.rm = na.rm) ) }) ### "Ops" := sub-groups "Arith", "Compare", and "Logic" ## ## For now (*), only "Arith" does make sense ## --> keep "Ops" undefined and define "Arith" : ## ---- ## (*) : TODO: logical <-> abIndex --> "Compare" etc as well setMethod("Ops", c(e1 = "abIndex", e2 = "abIndex"), function(e1, e2) { .bail.out.2(.Generic, class(e1), class(e2)) }) setMethod("Ops", c(e1 = "abIndex", e2 = "ANY"), function(e1, e2) { .bail.out.2(.Generic, class(e1), class(e2)) }) setMethod("Ops", c(e1 = "ANY", e2 = "abIndex"), function(e1, e2) { .bail.out.2(.Generic, class(e1), class(e2)) }) setMethod("Arith", c(e1 = "abIndex", e2 = "abIndex"), function(e1, e2) { l1 <- length(e1) l2 <- length(e2) mM <- range(l1,l2) stop("not yet implemented") ## FIXME ------------------ if(mM[1] != mM[2]) { ## lengths differ if(mM[1] %% mM[2] != 0) ## identical warning as in main/arithmetic.c warning("longer object length\n\tis not a multiple of shorter object length") if(l1 < l2) { } else { ## l1 > l2 } } switch(e1@kind, "rleDiff" = { }, "int32" =, "double" = { }) }) ## numLike = {numeric, logical}: setMethod("Arith", c(e1 = "abIndex", e2 = "numLike"), function(e1, e2) { if(!length(e1)) return(e1) if(e1@kind != "rleDiff") { # no compression e1@x <- callGeneric(e1@x, e2) if(e1@kind != "double" && is.double(e1@x)) e1@kind <- "double" return(e1) } if(length(e2) == 1) { ## scalar if(is.na(e2)) return(rep2abI(e2, length(e1))) ## else 'e2' is not NA and scalar switch(.Generic, "+" =, "-" = { e1@rleD@first <- callGeneric(e1@rleD@first, e2) e1 }, "*" = { e1@rleD@first <- e1@rleD@first * e2 r <- e1@rleD@rle$values * e2 if(is0(e2) && all0(r)) { ## result all 0: collapse e1@rleD@rle$values <- r[1L] e1@rleD@rle$lengths <- sum(e1@rleD@rle$lengths) } else ## normal case e1@rleD@rle$values <- r e1 }, "/" = { if(is0(e2) ## division by 0 && length(unique(sign(ends.rleD(e1@rleD)))) > 1) { ## at least one subsequence contains 0, i.e., changes sign: warning("x / 0 for an x with sign-change\n no longer representable as 'rleDiff'") return(vec2abI(abI2num(e1) / 0)) } e1@rleD@first <- e1@rleD@first / e2 e1@rleD@rle$values <- e1@rleD@rle$values / e2 e1 }, "^" = { if(e2 == 1) e1 else vec2abI(abI2num(e1) ^ e2) }, "%%" = , "%/%" = vec2abI(callGeneric(abI2num(e1), e2))) } else ## length(e2) != 1 callGeneric(e1, as(e2, "abIndex")) }) setMethod("Arith", c(e1 = "numLike", e2 = "abIndex"), function(e1, e2) { if(!length(e2)) return(e2) if(e2@kind != "rleDiff") { # no compression e2@x <- callGeneric(e1, e2@x) if(e2@kind != "double" && is.double(e2@x)) e2@kind <- "double" return(e2) } if(length(e1) == 1) { ## scalar if(is.na(e1)) return(rep2abI(e1, length(e2))) ## else 'e1' is not NA and scalar switch(.Generic, "+" = { e2@rleD@first <- e1 + e2@rleD@first e2 }, "-" = { e2@rleD@first <- e1 - e2@rleD@first e2@rleD@rle$values <- -e2@rleD@rle$values e2 }, "*" = { e2@rleD@first <- e1 * e2@rleD@first r <- e1 * e2@rleD@rle$values if(is0(e1) && all0(r)) { ## result all 0: collapse e2@rleD@rle$values <- r[1L] e2@rleD@rle$lengths <- sum(e2@rleD@rle$lengths) } else ## normal case e2@rleD@rle$values <- r e2 }, "/" = , "^" =, "%%" = , "%/%" = vec2abI(callGeneric(e1, abI2num(e2)))) } else ## length(e1) != 1 callGeneric(as(e1, "abIndex"), e2) }) setMethod("is.na", c(x = "abIndex"), function(x) { if(x@kind != "rleDiff") is.na(x@x) else { rd <- x@rleD rl <- rd@rle len <- 1+ sum(L <- rl$lengths) if(is.na(rd@first)) rep.int(TRUE, len) else { ## interesting case V <- rl$values if(!any(ina <- is.na(V))) rep.int(FALSE, len) else { ## at least one V is NA --> "x" is NA from then on: k <- match(TRUE,ina) # the first one l1 <- 1+ sum(L[seq_len(k-1)]) c(rep.int(FALSE, l1), rep.int(TRUE, len - l1)) } } } }) ## TODO ?? "is.nan" analogously ?? ## setMethod("is.finite", c(x = "abIndex"), function(x) { if(x@kind != "rleDiff") is.finite(x@x) else { rd <- x@rleD rl <- rd@rle len <- 1+ sum(L <- rl$lengths) if(!is.finite(rd@first)) rep.int(FALSE, len) else { ## interesting case V <- rl$values if(all(iFin <- is.finite(V))) rep.int(TRUE, len) else { ## at least one V is +- Inf --> "x" is Inf/NaN from there k <- match(FALSE,iFin) # the first non-finite one l1 <- 1+ sum(L[seq_len(k-1)]) c(rep.int(TRUE, l1), rep.int(FALSE, len - l1)) } } } }) setMethod("is.infinite", c(x = "abIndex"), function(x) { if(x@kind != "rleDiff") is.infinite(x@x) else { rd <- x@rleD rl <- rd@rle len <- 1+ sum(L <- rl$lengths) if(is.infinite(rd@first)) rep.int(TRUE, len) else { ## interesting case V <- rl$values if(!any(iInf <- is.infinite(V))) rep.int(FALSE, len) else { ## at least one V is +- Inf --> "x" is Inf/NaN from there k <- match(TRUE,iInf) # the first one l1 <- 1+ sum(L[seq_len(k-1)]) ## FIXME? do *not* consider 'NaN' (changing TRUE to FALSE): c(rep.int(FALSE, l1), rep.int(TRUE, len - l1)) } } } }) all.equal.abI <- function(target, current, ...) { if(!is(target, "abIndex") || !is(current, "abIndex")) return(paste0("target is ", data.class(target), ", current is ", data.class(current))) lt <- length(target) lc <- length(current) if(lt != lc) paste0("abIndex", ": lengths (", lt, ", ", lc, ") differ") else if(target@kind == current@kind) { all.equal.default(target, current, ...) } else ## different 'kinds' -- take "easy" exit: all.equal(abI2num(target), abI2num(current), ...) } ## {all.equal.abI} setMethod("all.equal", c(target = "abIndex", current = "abIndex"), all.equal.abI) setMethod("all.equal", c(target = "abIndex", current = "numLike"), function(target, current, ...) all.equal.abI(target, as(current, "abIndex"), ...)) setMethod("all.equal", c(target = "numLike", current = "abIndex"), function(target, current, ...) all.equal.abI(as(target, "abIndex"), current, ...)) ## Then I want something like get.ind.sel(.) [ ./Tsparse.R ] working, ## i.e. possibly match(i, , nomatch = 0) setAs("seqMat", "numeric", function(from) { do.call(c, lapply(seq_len(ncol(from)), function(j) seq(from=from[1L,j], to = from[2L,j]))) }) setAs("numeric", "seqMat", function(from) as(as(from, "abIndex"), "seqMat")) setAs("abIndex", "seqMat", function(from) { n <- length(from) d <- from@rleD va <- d@rle$values le <- d@rle$lengths m <- length(le) ## Now work the 'ends' are cumsum(c(d@first, le * va)) ## we need to care for the "length 1" stretches: if(any(nonPair <- le[2* seq_len(m2 <- m %/% 2)] != 1)) { m2 + n + va + nonPair # <- "dummy" using "unused" ## an "easy" (but not so efficient when 'm' is "large") ## way would be to "make these" into pairs, then work for that case... } ## use ~/R/MM/Pkg-ex/Matrix/abIndex-experi.R for trying things ... stop(" --> is not yet implemented") }) setAs("seqMat", "abIndex", function(from) { stop(" --> is not yet implemented") }) Matrix/R/dim.R0000644000175100001440000001443314575137654012657 0ustar hornikusersvalidDim <- function(dim) .Call(R_Dim_validate, dim) validDimGetsValue <- function(value, mn) { if(mode(value) != "numeric") gettextf("assigned dimensions are not of type \"%s\" or \"%s\"", "integer", "double") else if(length(value) != 2L) gettextf("assigned dimensions do not have length %d", 2L) else if(anyNA(value)) gettext("assigned dimensions are NA") else if(any(value < 0L)) gettext("assigned dimensions are negative") else if(is.double(value) && any(trunc(value) > .Machine$integer.max)) gettextf("assigned dimensions exceed %s", "2^31-1") else if((p <- prod(value)) != mn) gettextf("assigned dimensions [product %.0f] do not match object length [%.0f]", p, as.double(mn)) else TRUE } validDN <- function(dn, dim) .Call(R_DimNames_validate, dn, dim) fixupDN <- function(dn) .Call(R_DimNames_fixup, dn) fixupDN.if.valid <- function(dn, dim) { if(is.character(s <- validDim(dim)) || is.character(s <- validDN(dn, dim))) stop(s, domain = NA) fixupDN(dn) } symDN <- function(dn) .Call(R_symDN, dn) symmetrizeDN <- function(x) { if(isS4(x)) # assuming is(x, "Matrix") `dimnames<-`(x, symDN(x@Dimnames)) else if(!is.null(dn <- dimnames(x))) # assuming list of length 2 `dimnames<-`(x, symDN(dn)) else x } isSymmetricDN <- function(dn) .Call(R_DimNames_is_symmetric, dn) is.null.DN <- function(dn) { if(is.null(dn)) return(TRUE) if(!is.null(names(dn))) names(dn) <- NULL ch0 <- character(0L) identical(dn, list(NULL, NULL)) || identical(dn, list( ch0, NULL)) || identical(dn, list(NULL, ch0)) || identical(dn, list( ch0, ch0)) } ## METHODS FOR GENERIC: dim ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("dim", c(x = "Matrix"), function(x) x@Dim) setMethod("dim", c(x = "MatrixFactorization"), function(x) x@Dim) ## METHODS FOR GENERIC: dim<- ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("dim<-", c(x = "denseMatrix"), function(x, value) { if(is.character(s <- validDimGetsValue(value, prod(d <- x@Dim)))) stop(s, domain = NA) value <- as.integer(value) if(all(value == d)) return(x) r <- .M2gen(x) r@Dim <- value if(length(r@factors)) r@factors <- list() r }) setMethod("dim<-", c(x = "sparseMatrix"), function(x, value) { if(is.character(s <- validDimGetsValue(value, prod(d <- x@Dim)))) stop(s, domain = NA) value <- as.integer(value) if(all(value == d)) return(x) r <- spV2M(.M2V(x), nrow = value[1L], ncol = value[2L]) switch(.M.repr(x), "C" = .M2C(r), "R" = .M2R(r), r) }) setMethod("dim<-", c(x = "sparseVector"), function(x, value) { if(is.character(s <- validDimGetsValue(value, length(x)))) stop(s, domain = NA) value <- as.integer(value) spV2M(x, nrow = value[1L], ncol = value[2L]) }) ## METHODS FOR GENERIC: length ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("length", c(x = "Matrix"), function(x) if((r <- prod(x@Dim)) > .Machine$integer.max) r else as.integer(r)) setMethod("length", c(x = "MatrixFactorization"), function(x) if((r <- prod(x@Dim)) > .Machine$integer.max) r else as.integer(r)) setMethod("length", c(x = "sparseVector"), function(x) if(is.integer(r <- x@length)) r else if(r - 1 <= .Machine$integer.max) as.integer(r) else trunc(r)) ## METHODS FOR GENERIC: dimnames ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("dimnames", c(x = "Matrix"), function(x) x@Dimnames) setMethod("dimnames", c(x = "symmetricMatrix"), function(x) symDN(x@Dimnames)) setMethod("dimnames", c(x = "MatrixFactorization"), function(x) x@Dimnames) ## METHODS FOR GENERIC: dimnames<- ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("dimnames<-", c(x = "Matrix", value = "NULL"), function(x, value) { x@Dimnames <- list(NULL, NULL) x }) for(.cl in c("generalMatrix", "symmetricMatrix")) setMethod("dimnames<-", c(x = .cl, value = "NULL"), function(x, value) { if(length(x@factors)) x@factors <- list() x@Dimnames <- list(NULL, NULL) x }) rm(.cl) setMethod("dimnames<-", c(x = "MatrixFactorization", value = "NULL"), function(x, value) { x@Dimnames <- list(NULL, NULL) x }) setMethod("dimnames<-", c(x = "Matrix", value = "list"), function(x, value) { x@Dimnames <- fixupDN.if.valid(value, x@Dim) x }) for(.cl in c("generalMatrix", "symmetricMatrix")) setMethod("dimnames<-", c(x = .cl, value = "list"), function(x, value) { if(length(x@factors)) x@factors <- list() x@Dimnames <- fixupDN.if.valid(value, x@Dim) x }) rm(.cl) setMethod("dimnames<-", c(x = "MatrixFactorization", value = "list"), function(x, value) { x@Dimnames <- fixupDN.if.valid(value, x@Dim) x }) ## METHODS FOR GENERIC: unname ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("unname", c(obj = "Matrix"), function(obj, force = FALSE) { obj@Dimnames <- list(NULL, NULL) obj }) setMethod("unname", c(obj = "MatrixFactorization"), function(obj, force = FALSE) { obj@Dimnames <- list(NULL, NULL) obj }) ## METHODS FOR GENERIC: drop ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("drop", c(x = "Matrix"), function(x) if(any(x@Dim == 1L)) drop(.M2m(x)) else x) Matrix/R/KhatriRao.R0000644000175100001440000000541414461537243013761 0ustar hornikusers# Efficient Khatri-Rao product for large sparse matrices # Assumes two matrices in CsparseMatrix format # Written by Michael Cysouw ## MM: there's a "public" Matlab version, at ## http://www.mathworks.com/matlabcentral/fileexchange/28872-khatri-rao-product/content/kr.m ## with documentation ## ## % Khatri-Rao product. ## ## % kr(A,B) returns the Khatri-Rao product of two matrices A and B, of ## % dimensions I-by-K and J-by-K respectively. The result is an I*J-by-K ## % matrix formed by the matching columnwise Kronecker products, i.e. ## % the k-th column of the Khatri-Rao product is defined as ## % kron(A(:,k),B(:,k)). KhatriRao <- function(X, Y = X, FUN = "*", sparseY = TRUE, make.dimnames = FALSE) { stopifnot((p <- ncol(X)) == ncol(Y)) ## TODO? speedup when X = Diagonal() X <- asCspN(X) # not-U-diag CsparseMatrix --> can use @x, @p, @i ## xn, yn; number of non-zero values per column xn <- diff(X@p) n1 <- nrow(X); n2 <- nrow(Y) if(sparseY) { Y <- asCspN(Y) yn <- diff(yp <- Y@p) ## both of length p } else { if(!is.matrix(Y)) Y <- as.matrix(Y)# needed e.g. in c(Y) below) yn <- rep(n2, p) } newp <- as.integer(diffinv(xn*yn)) ## indices for new values ## dense: = newp <- as.integer(diffinv(xn*nrow(Y))) xn.yp <- xn[ as.logical(yn) ] # xn "where" Y is present yj <- if(sparseY) .Call(Matrix_expand_pointers, yp)## as(Y,"TsparseMatrix")@j else rep(seq(p)-1L, each = n2) yj <- factor(yj) # for split() below non0 <- length(xn.yp) > 0L && any(xn.yp != 0L) rep.yn <- rep.int(yn, xn) i1 <- rep.int(X@i, rep.yn) i2 <- if(non0) { if(sparseY) unlist(rep(split.default(Y@i,yj), xn.yp), use.names=FALSE) else rep.int(seq.int(n2)-1L, p) } else integer() newi <- i1*n2 + i2 dim <- as.integer(c(n1*n2, p)) dns <- if (make.dimnames) { ## this is not good enough: dnx, dny may be NULL list(as.vector(outer(rownames(Y),rownames(X), FUN = "paste", sep = ":")), colnames(X)) } else list(NULL,NULL) if((nX <- is(X, "nMatrix")) & (nY <- is(Y, "nMatrix"))) new("ngCMatrix", Dim=dim, Dimnames=dns, i = newi, p = newp) else { ## at least one of 'X' and 'Y' has an "x" slot: if(nX) X <- .M2gen(.M2kind(X, "l")) x1 <- rep.int(X@x, rep.yn) x2 <- if(non0) { if(nY && sparseY) Y <- .M2gen(.M2kind(X, "l")) yx <- if(sparseY) Y@x else c(Y) unlist(rep(split.default(yx, yj), xn.yp), use.names=FALSE) } else if(nY) logical() else (if(sparseY) Y@x else c(Y))[0] if(!is.double(x1)) x1 <- as.double(x1) ## or if we had "igCMatrix" ... new("dgCMatrix", Dim=dim, Dimnames=dns, i = newi, p = newp, x = match.fun(FUN) (x1,x2)) } } Matrix/R/Summary.R0000644000175100001440000001461314561451364013533 0ustar hornikusers## METHODS FOR GENERIC: Summary (group) ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## > getGroupMembers("Summary") ## [1] "max" "min" "range" "prod" "sum" "any" "all" ## NB: Summary depends on the existence, _not_ count, of zeros and ones. ## The only exception is 'sum' which ignores zeros and counts ones. setMethod("Summary", c(x = "denseMatrix"), function(x, ..., na.rm = FALSE) { ## Avoid wrong overflow : if(.Generic == "sum") return(sum (.Call(R_dense_sum , x, na.rm), ..., na.rm = na.rm)) if(.Generic == "prod") return(prod(.Call(R_dense_prod, x, na.rm), ..., na.rm = na.rm)) cl <- .M.nonvirtual(x) kind <- substr(cl, 1L, 1L) shape <- substr(cl, 2L, 2L) repr <- substr(cl, 3L, 3L) zero <- switch(kind, "n" = , "l" = FALSE, "i" = 0L, "d" = 0, "z" = 0+0i) if(shape != "g") { if(repr != "p") x <- .M2packed(x) if(shape == "t" && x@diag != "N") diag(x) <- TRUE # copying, sadly } n <- x@Dim[2L] y <- x@x y1 <- if(kind != "n" || !anyNA(y)) y else y | is.na(y) y2 <- if(shape == "t" && n > 1L) zero get(.Generic, mode = "function")(y1, y2, ..., na.rm = na.rm) }) setMethod("Summary", c(x = "sparseMatrix"), function(x, ..., na.rm = FALSE) { ## Avoid wrong overflow : if(.Generic == "sum") return(sum (.Call(R_sparse_sum , x, na.rm), ..., na.rm = na.rm)) if(.Generic == "prod") return(prod(.Call(R_sparse_prod, x, na.rm), ..., na.rm = na.rm)) cl <- .M.nonvirtual(x) kind <- substr(cl, 1L, 1L) shape <- substr(cl, 2L, 2L) repr <- substr(cl, 3L, 3L) switch(kind, "n" = , "l" = { zero <- FALSE; one <- TRUE }, "i" = { zero <- 0L ; one <- 1L }, "d" = { zero <- 0 ; one <- 1 }, "z" = { zero <- 0+0i ; one <- 1+0i }) ## Handle overallocation (hopefully rare ...) : if(repr == "T") { x <- aggregateT(x) nnz <- length(x@i) } else { nnz <- { p <- x@p; p[length(p)] } if(length(if(repr == "C") x@i else x@j) > nnz) { h <- seq_len(nnz) if(repr == "C") x@i <- x@i[h] else x@j <- x@j[h] if(kind != "n") x@x <- x@x[h] } } n <- (d <- x@Dim)[2L] nnz.max <- if(shape == "s") 0.5 * (prod(d) + n) else prod(d) y1 <- if(kind != "n") x@x else if(nnz > 0L) TRUE else logical(0L) y2 <- if(nnz < nnz.max) zero y3 <- if(n > 0L && shape == "t" && x@diag != "N") one get(.Generic, mode = "function")(y1, y2, y3, ..., na.rm = na.rm) }) setMethod("Summary", c(x = "diagonalMatrix"), function(x, ..., na.rm = FALSE) { kind <- .M.kind(x) switch(kind, "n" = , "l" = { zero <- FALSE; one <- TRUE }, "i" = { zero <- 0L ; one <- 1L }, "d" = { zero <- 0 ; one <- 1 }, "z" = { zero <- 0+0i ; one <- 1+0i }) n <- x@Dim[2L] y1 <- if(x@diag == "N") { y <- x@x if(kind != "n") { if(.Generic == "prod" && n > 1L) ## Avoid wrong overflow : c(y[1L], zero, y[-1L]) else y } else if(!anyNA(y)) y else y | is.na(y) } y2 <- if(n > 1L) zero y3 <- if(x@diag != "N") { if(.Generic == "sum") one * n else if(n > 0L) one else one[0L] } get(.Generic, mode = "function")(y1, y2, y3, ..., na.rm = na.rm) }) setMethod("Summary", c(x = "indMatrix"), function(x, ..., na.rm = FALSE) { nnz <- length(x@perm) y1 <- if(.Generic == "sum") nnz else if(nnz > 0L) TRUE else logical(0L) y2 <- if(nnz < prod(x@Dim)) FALSE get(.Generic, mode = "function")(y1, y2, ..., na.rm = na.rm) }) setMethod("Summary", c(x = "sparseVector"), function(x, ..., na.rm = FALSE) { kind <- .M.kind(x) zero <- switch(kind, "n" = , "l" = FALSE, "i" = 0L, "d" = 0, "z" = 0+0i) nnz <- length(i <- x@i) nnz.max <- length(x) y1 <- if(kind != "n") { y <- x@x if(.Generic == "prod" && nnz > 0L && nnz < nnz.max) { ## Avoid wrong overflow : if(i[1L] > 1L) c(zero, y) else if(nnz >= (q <- which.min(i == seq_along(i)))) c(y[1L:(q - 1L)], zero, y[q:nnz]) else y } else y } else if(.Generic == "sum") nnz else if(nnz > 0L) TRUE else logical(0L) y2 <- if(nnz < nnz.max) zero get(.Generic, mode = "function")(y1, y2, ..., na.rm = na.rm) }) Matrix/R/00_Generic.R0000644000175100001440000000550414575137654013760 0ustar hornikusers## NB: Here, we do _not_ define generic versions of functions that: ## * are already (S3) generic in their package of origin ## (e.g., isSymmetric), because our first setMethod call ## will define a correct (S4) generic function automatically ## * already have _implicit_ generic definitions in package ## methods (e.g., qr.R); see methods/R/makeBasicFunsList.R setGeneric("%&%", function(x, y) standardGeneric("%&%")) setGeneric("BunchKaufman", function(x, ...) standardGeneric("BunchKaufman")) setGeneric("Cholesky", function(A, ...) standardGeneric("Cholesky")) setGeneric("Schur", function(x, vectors = TRUE, ...) standardGeneric("Schur"), signature = "x") setGeneric("band", function(x, k1, k2, ...) standardGeneric("band"), signature = "x") setGeneric("expand", function(x, ...) standardGeneric("expand")) setGeneric("expand1", function(x, which, ...) standardGeneric("expand1"), signature = "x") setGeneric("expand2", function(x, ...) standardGeneric("expand2")) setGeneric("expm", function(x) standardGeneric("expm")) setGeneric("facmul", function(x, factor, y, trans = FALSE, left = TRUE, ...) standardGeneric("facmul"), signature = c("x", "y")) setGeneric("forceSymmetric", function(x, uplo) standardGeneric("forceSymmetric")) setGeneric("isDiagonal", function(object) standardGeneric("isDiagonal")) setGeneric("isTriangular", function(object, upper = NA, ...) standardGeneric("isTriangular"), signature = "object") setGeneric("lu", function(x, ...) standardGeneric("lu")) setGeneric("nnzero", function(x, na.counted = NA) standardGeneric("nnzero"), signature = "x") setGeneric("pack", function(x, ...) standardGeneric("pack")) setGeneric("skewpart", function(x) standardGeneric("skewpart")) setGeneric("symmpart", function(x) standardGeneric("symmpart")) setGeneric("tril", function(x, k = 0L, ...) standardGeneric("tril"), signature = "x") setGeneric("triu", function(x, k = 0L, ...) standardGeneric("triu"), signature = "x") setGeneric("unpack", function(x, ...) standardGeneric("unpack")) setGeneric("updown", function(update, C, L) standardGeneric("updown")) setGeneric("writeMM", function(obj, file, ...) standardGeneric("writeMM")) Matrix/R/BunchKaufman.R0000644000175100001440000000771114561451364014441 0ustar hornikusers## METHODS FOR GENERIC: BunchKaufman ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("BunchKaufman", c(x = "dsyMatrix"), function(x, warnSing = TRUE, ...) .Call(dsyMatrix_trf, x, as.logical(warnSing))) setMethod("BunchKaufman", c(x = "dspMatrix"), function(x, warnSing = TRUE, ...) .Call(dspMatrix_trf, x, as.logical(warnSing))) setMethod("BunchKaufman", c(x = "matrix"), function(x, uplo = "U", ...) BunchKaufman(.m2dense(x, ",sy", uplo), ...)) ## METHODS FOR CLASS: p?BunchKaufman ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setAs("BunchKaufman", "dtrMatrix", function(from) { to <- new("dtrMatrix") to@Dim <- from@Dim to@uplo <- from@uplo to@x <- from@x to }) setAs("pBunchKaufman", "dtpMatrix", function(from) { to <- new("dtpMatrix") to@Dim <- from@Dim to@uplo <- from@uplo to@x <- from@x to }) .def.unpacked <- .def.packed <- function(x, which, ...) { r <- .Call(BunchKaufman_expand, x, .PACKED) b <- length(r) - 1L switch(which, "DU" =, "DL" = { if(!endsWith(which, x@uplo)) stop(gettextf("%s=\"%s\" invalid for %s@uplo=\"%s\"", "which", which, "x", x@uplo), domain = NA) r[[b + 1L]] }, "U" =, "U." =, "L" =, "L." = { if(!startsWith(which, x@uplo)) stop(gettextf("%s=\"%s\" invalid for %s@uplo=\"%s\"", "which", which, "x", x@uplo), domain = NA) if(b > 0L) { m <- r[[b]] if(b > 1L) for(i in (b - 1L):1L) m <- r[[i]] %*% m if(endsWith(which, ".")) t(m) else m } else { m <- new("ddiMatrix") m@Dim <- x@Dim m@diag <- "U" m } }, stop(gettextf("'%s' is not \"%1$s\", \"D%1$s\", or \"%1$s.\"", "which", x@uplo), domain = NA)) } body(.def.unpacked) <- do.call(substitute, list(body(.def.unpacked), list(.PACKED = FALSE))) body(.def.packed) <- do.call(substitute, list(body(.def.packed ), list(.PACKED = TRUE))) setMethod("expand1", c(x = "BunchKaufman"), .def.unpacked) setMethod("expand1", c(x = "pBunchKaufman"), .def.packed) rm(.def.unpacked, .def.packed) .def.unpacked <- .def.packed <- function(x, complete = FALSE, ...) { r <- .Call(BunchKaufman_expand, x, .PACKED) b <- length(r) - 1L if(complete) { if(b > 0L) r <- c(r, lapply(r[b:1L], t)) } else { if(b > 0L) { m <- r[[b]] if(b > 1L) for(i in (b - 1L):1L) m <- r[[i]] %*% m r <- list(m, r[[b + 1L]], t(m)) } else { m <- new("ddiMatrix") m@Dim <- x@Dim m@diag <- "U" r <- list(m, r[[1L]], m) } names(r) <- if(x@uplo == "U") c("U", "DU", "U.") else c("L", "DL", "L.") } dn <- x@Dimnames if(length(r) == 1L) r[[1L]]@Dimnames <- dn else { r[[1L]]@Dimnames <- c(dn[1L], list(NULL)) r[[length(r)]]@Dimnames <- c(list(NULL), dn[2L]) } r } body(.def.unpacked) <- do.call(substitute, list(body(.def.unpacked), list(.PACKED = FALSE))) body(.def.packed) <- do.call(substitute, list(body(.def.packed ), list(.PACKED = TRUE))) ## returning ## list(U, DU, U') where A = U DU U' and U = P[b] U[b] ... P[1] U[1] ## OR ## list(L, DL, L') where A = L DL L' and L = P[1] L[1] ... P[b] L[b] setMethod("expand2", c(x = "BunchKaufman"), .def.unpacked) setMethod("expand2", c(x = "pBunchKaufman"), .def.packed) rm(.def.unpacked, .def.packed) Matrix/R/coerce.R0000644000175100001440000005037414561451364013342 0ustar hornikusers## METHODS FOR GENERIC: coerce, as.* ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .M2kind <- function(from, kind = ".", sparse = NA) .Call(R_Matrix_as_kind, from, kind, sparse) .M2gen <- function(from, kind = ".") .Call(R_Matrix_as_general, from, kind) ..M2gen <- function(from) # for setAs() .Call(R_Matrix_as_general, from, ".") .M2sym <- function(from, ...) { if(isSymmetric(from, ...)) forceSymmetric(from) else stop("matrix is not symmetric; consider forceSymmetric(.) or symmpart(.)") } ..M2sym <- .M2sym # for setAs() formals(..M2sym) <- formals(..M2sym)[-2L] body(..M2sym)[[2L]][[2L]] <- body(..M2sym)[[2L]][[2L]][-3L] .M2tri <- function(from, ...) { if(!(it <- isTriangular(from, ...))) stop("matrix is not triangular; consider triu(.) or tril(.)") else if(attr(it, "kind") == "U") triu(from) else tril(from) } ..M2tri <- .M2tri # for setAs() formals(..M2tri) <- formals(..M2tri)[-2L] body(..M2tri)[[2L]][[2L]][[2L]][[2L]][[3L]] <- body(..M2tri)[[2L]][[2L]][[2L]][[2L]][[3L]][-3L] .M2diag <- function(from) { if (!isDiagonal(from)) stop("matrix is not diagonal; consider Diagonal(x=diag(.))") forceDiagonal(from) } .M2v <- function(from) .Call(R_Matrix_as_vector, from) .M2m <- function(from) .Call(R_Matrix_as_matrix, from) .M2unpacked <- function(from) .Call(R_Matrix_as_unpacked, from) .M2packed <- function(from) .Call(R_Matrix_as_packed, from) .M2C <- function(from) .Call(R_Matrix_as_Csparse, from) .M2R <- function(from) .Call(R_Matrix_as_Rsparse, from) .M2T <- function(from) .Call(R_Matrix_as_Tsparse, from) .sparse2dense <- function(from, packed = FALSE) .Call(R_sparse_as_dense, from, packed) .diag2dense <- function(from, kind = ".", shape = "t", packed = FALSE, uplo = "U") .Call(R_diagonal_as_dense, from, kind, shape, packed, uplo) .ind2dense <- function(from, kind = "n") .Call(R_index_as_dense, from, kind) .dense2sparse <- function(from, repr = "C") .Call(R_dense_as_sparse, from, repr) .diag2sparse <- function(from, kind = ".", shape = "t", repr = "C", uplo = "U") .Call(R_diagonal_as_sparse, from, kind, shape, repr, uplo) .ind2sparse <- function(from, kind = "n", repr = ".") .Call(R_index_as_sparse, from, kind, repr) .m2dense <- function(from, class = ".ge", uplo = "U", diag = "N", trans = FALSE) .Call(R_matrix_as_dense, from, class, uplo, diag, trans) .m2dense.checking <- function(from, kind = ".", ...) { switch(typeof(from), logical =, integer =, double = NULL, stop(gettextf("invalid type \"%s\" in '%s'", typeof(from), ".m2dense.checking"), domain = NA)) if(kind != ".") { ## These must happen before isSymmetric() call storage.mode(from) <- switch(kind, n =, l = "logical", d = "double", stop(gettextf("invalid %s=\"%s\" to '%s'", "kind", kind, ".m2dense.checking"), domain = NA)) if(kind == "n" && anyNA(from)) from[is.na(from)] <- TRUE } if(isSymmetric(from, ...)) .m2dense(from, paste0(kind, "sy"), "U", NULL) else if(it <- isTriangular(from)) .m2dense(from, paste0(kind, "tr"), attr(it, "kind"), "N") else .m2dense(from, paste0(kind, "ge"), NULL, NULL) } .m2sparse <- function(from, class = ".gC", uplo = "U", diag = "N", trans = FALSE) .Call(R_matrix_as_sparse, from, class, uplo, diag, trans) .m2sparse.checking <- function(from, kind = ".", repr = "C", ...) { switch(typeof(from), logical =, integer =, double = NULL, stop(gettextf("invalid type \"%s\" in '%s'", typeof(from), ".m2sparse.checking"), domain = NA)) if(kind != ".") { ## These must happen before isSymmetric() call storage.mode(from) <- switch(kind, n =, l = "logical", d = "double", stop(gettextf("invalid %s=\"%s\" to '%s'", "kind", kind, ".m2sparse.checking"), domain = NA)) if(kind == "n" && anyNA(from)) from[is.na(from)] <- TRUE } if(isSymmetric(from, ...)) .m2sparse(from, paste0(kind, "s", repr), "U", NULL) else if(it <- isTriangular(from)) .m2sparse(from, paste0(kind, "t", repr), attr(it, "kind"), "N") else .m2sparse(from, paste0(kind, "g", repr), NULL, NULL) } .V2kind <- function(from, kind = ".") { if(kind == ".") return(from) kind. <- .M.kind(from) if(kind == ",") kind <- if(kind. == "z") "z" else "d" if(kind == kind.) return(from) to <- new(paste0(kind, "sparseVector")) to@length <- from@length to@i <- from@i if(kind != "n") to@x <- if(kind. == "n") rep.int(switch(kind, "l" = TRUE, "i" = 1L, "d" = 1, "z" = 1+0i), length(from@i)) else as.vector(from@x, typeof(to@x)) to } .V2v <- function(from) { if(.M.kind(from) != "n") { to <- vector(typeof(from@x), from@length) to[from@i] <- from@x } else { to <- logical(from@length) to[from@i] <- TRUE } to } .V2m <- function(from) { if(is.double(m <- length(from))) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) to <- .V2v(from) dim(to) <- c(m, 1L) to } .V2a <- function(from) { if(is.double(m <- length(from))) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) to <- .V2v(from) dim(to) <- m to } .V2unpacked <- function(from) { if(is.double(m <- length(from))) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) kind <- .M.kind(from) to <- new(paste0(if(kind == "i") "d" else kind, "geMatrix")) to@Dim <- c(m, 1L) to@x <- replace(vector(typeof(to@x), m), from@i, if(kind == "n") TRUE else from@x) to } .V2C <- function(from) { if(is.double(m <- length(from))) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) kind <- .M.kind(from) to <- new(paste0(if(kind == "i") "d" else kind, "gCMatrix")) to@Dim <- c(m, 1L) to@p <- c(0L, length(from@i)) to@i <- as.integer(from@i) - 1L if(kind != "n") to@x <- if(kind == "i") as.double(from@x) else from@x to } .V2R <- function(from) { if(is.double(m <- length(from))) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) kind <- .M.kind(from) to <- new(paste0(if(kind == "i") "d" else kind, "gRMatrix")) to@Dim <- c(m, 1L) to@p <- c(0L, cumsum(replace(logical(m), from@i, TRUE))) to@j <- integer(length(from@i)) if(kind != "n") to@x <- if(kind == "i") as.double(from@x) else from@x to } .V2T <- function(from) { if(is.double(m <- length(from))) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) kind <- .M.kind(from) to <- new(paste0(if(kind == "i") "d" else kind, "gTMatrix")) to@Dim <- c(m, 1L) to@i <- as.integer(from@i) - 1L to@j <- integer(length(from@i)) if(kind != "n") to@x <- if(kind == "i") as.double(from@x) else from@x to } ## FIXME: define R_Matrix_as_sparseVector in ../src/coerce.c and use here .M2V <- function(from) { repr <- .M.repr(from) if(repr == "u" || repr == "p") return(.Call( v2spV, .M2v(from))) if(repr == "C" || repr == "R") return(.Call(CR2spV, from )) if(repr == "T") return(.Call(CR2spV, .M2C(from))) if(repr != "d" && repr != "i") { if(is.object(from)) stop(gettextf("invalid class \"%s\" in '%s'", class(from)[1L], ".M2V"), domain = NA) else stop(gettextf("invalid type \"%s\" in '%s'", typeof(from), ".M2V"), domain = NA) } d <- from@Dim m <- d[1L] n <- d[2L] mn <- prod(d) if(mn <= .Machine$integer.max) mn <- as.integer(mn) else if(mn > 0x1p+53) stop(gettextf("%s length cannot exceed %s", "sparseVector", "2^53"), domain = NA) kind <- .M.kind(from) to <- new(paste0(kind, "sparseVector")) to@length <- mn to@i <- if(repr == "d") { if(kind == "n" && from@diag == "N") indDiag(n)[from@x | is.na(from@x)] else indDiag(n) } else if(is.integer(mn)) { if(from@margin == 1L) seq.int(to = 0L, by = 1L, length.out = m) + from@perm * m else seq.int(from = 0L, by = m, length.out = n) + from@perm } else { if(from@margin == 1L) seq.int( to = 0, by = 1, length.out = m) + from@perm * as.double(m) else seq.int(from = 0, by = as.double(m), length.out = n) + as.double(from@perm) } if(kind != "n") to@x <- if(from@diag == "N") from@x else rep.int(switch(kind, "l" = TRUE, "i" = 1L, "d" = 1, "z" = 1+0i), n) to } .m2V <- function(from, kind = ".") { to <- .Call(v2spV, from) if(kind == ".") to else { to. <- new(paste0(kind, "sparseVector")) to.@length <- to@length to.@i <- to@i if(kind != "n") to.@x <- as.vector(to@x, typeof(to.@x)) to. } } ## ==== To vector ====================================================== ## Need 'base' functions calling as.*() to dispatch to our S4 methods: if (FALSE) { ## 2023-08-10: breaks iGraphMatch, mcmcsae, mcompanion ## which define proper subclasses of Matrix not extending ## any of _our_ proper subclasses of Matrix as.matrix.Matrix <- function(x, ...) .M2m(x) as.array.Matrix <- function(x, ...) .M2m(x) } else { as.matrix.Matrix <- function(x, ...) as(x, "matrix") as.array.Matrix <- function(x, ...) as(x, "matrix") setAs("Matrix", "matrix", .M2m) } as.matrix.sparseVector <- function(x, ...) .V2m(x) as.array.sparseVector <- function(x, ...) .V2a(x) setMethod("as.vector" , c(x = "Matrix"), function(x, mode = "any") as.vector(.M2v(x), mode)) setMethod("as.matrix" , c(x = "Matrix"), as.matrix.Matrix) setMethod("as.array" , c(x = "Matrix"), as.array.Matrix) setMethod("as.logical", c(x = "Matrix"), function(x, ...) as.logical(.M2v(x))) setMethod("as.integer", c(x = "Matrix"), function(x, ...) as.integer(.M2v(x))) setMethod("as.numeric", c(x = "Matrix"), function(x, ...) as.numeric(.M2v(x))) setMethod("as.complex", c(x = "Matrix"), function(x, ...) as.complex(.M2v(x))) setMethod("as.vector" , c(x = "sparseVector"), function(x, mode = "any") as.vector(.V2v(x), mode)) setMethod("as.matrix" , c(x = "sparseVector"), as.matrix.sparseVector) setMethod("as.array" , c(x = "sparseVector"), as.array.sparseVector) setMethod("as.logical", c(x = "sparseVector"), function(x, ...) as.logical(.V2v(x))) setMethod("as.integer", c(x = "sparseVector"), function(x, ...) as.integer(.V2v(x))) setMethod("as.numeric", c(x = "sparseVector"), function(x, ...) as.numeric(.V2v(x))) setMethod("as.complex", c(x = "sparseVector"), function(x, ...) as.complex(.V2v(x))) ## ==== To Matrix ====================================================== setAs("sparseVector", "Matrix", .V2C) setAs("matrix", "Matrix", function(from) { if(isDiagonal(from)) forceDiagonal(from) else if(.sparseDefault(from)) .m2sparse.checking(from, ".", "C") else .m2dense.checking(from, ".") }) setAs("vector", "Matrix", function(from) { if(is.object(from) && length(dim(from)) == 2L) # e.g., data.frame as(as.matrix(from), "Matrix") else if(.sparseDefault(from)) .m2sparse(from, ".gC") else .m2dense(from, ".ge") }) setAs( "ANY", "Matrix", function(from) as(as(from, "matrix"), "Matrix")) if(FALSE) { ## MJ: not yet ... existing as(, "Matrix") must become defunct first setAs("MatrixFactorization", "Matrix", function(from) { n <- length(x <- expand2(from)) to <- x[[1L]] if(n >= 2L) for(i in 2L:n) to <- to %*% x[[i]] to }) } ## ==== To sparseVector ================================================ setAs("Matrix", "sparseVector", function(from) .M2V(from)) setAs("matrix", "sparseVector", function(from) .m2V(from)) setAs("vector", "sparseVector", function(from) .m2V(from)) setAs( "ANY", "sparseVector", function(from) as(as.vector(from), "sparseVector")) ## ==== To "kind" ====================================================== setAs("Matrix", "nMatrix", function(from) .M2kind(from, "n", NA)) setAs("Matrix", "lMatrix", function(from) .M2kind(from, "l", NA)) setAs("Matrix", "dMatrix", function(from) .M2kind(from, "d", NA)) setAs("Matrix", "ndenseMatrix", function(from) .M2kind(from, "n", FALSE)) setAs("Matrix", "ldenseMatrix", function(from) .M2kind(from, "l", FALSE)) setAs("Matrix", "ddenseMatrix", function(from) .M2kind(from, "d", FALSE)) setAs("Matrix", "nsparseMatrix", function(from) .M2kind(from, "n", TRUE)) setAs("Matrix", "lsparseMatrix", function(from) .M2kind(from, "l", TRUE)) setAs("Matrix", "dsparseMatrix", function(from) .M2kind(from, "d", TRUE)) setAs("matrix", "nMatrix", function(from) { if(.sparseDefault(from)) .m2sparse.checking(from, "n", "C") else .m2dense.checking(from, "n") }) setAs("matrix", "lMatrix", function(from) { if(isDiagonal(from)) forceDiagonal(`storage.mode<-`(from, "logical")) else if(.sparseDefault(from)) .m2sparse.checking(from, "l", "C") else .m2dense.checking(from, "l") }) setAs("matrix", "dMatrix", function(from) { if(isDiagonal(from)) forceDiagonal(`storage.mode<-`(from, "double")) else if(.sparseDefault(from)) .m2sparse.checking(from, "d", "C") else .m2dense.checking(from, "d") }) setAs("matrix", "ndenseMatrix", function(from) .m2dense.checking(from, "n")) setAs("matrix", "ldenseMatrix", function(from) .m2dense.checking(from, "l")) setAs("matrix", "ddenseMatrix", function(from) .m2dense.checking(from, "d")) setAs("matrix", "nsparseMatrix", function(from) .m2sparse.checking(from, "n", "C")) setAs("matrix", "lsparseMatrix", function(from) .m2sparse.checking(from, "l", "C")) setAs("matrix", "dsparseMatrix", function(from) .m2sparse.checking(from, "d", "C")) setAs("vector", "nMatrix", function(from) { if(.sparseDefault(from)) .m2sparse(from, "ngC") else .m2dense(from, "nge") }) setAs("vector", "lMatrix", function(from) { if(.sparseDefault(from)) .m2sparse(from, "lgC") else .m2dense(from, "lge") }) setAs("vector", "dMatrix", function(from) { if(.sparseDefault(from)) .m2sparse(from, "dgC") else .m2dense(from, "dge") }) setAs("vector", "ndenseMatrix", function(from) .m2dense(from, "nge")) setAs("vector", "ldenseMatrix", function(from) .m2dense(from, "lge")) setAs("vector", "ddenseMatrix", function(from) .m2dense(from, "dge")) setAs("vector", "nsparseMatrix", function(from) .m2sparse(from, "ngC")) setAs("vector", "lsparseMatrix", function(from) .m2sparse(from, "lgC")) setAs("vector", "dsparseMatrix", function(from) .m2sparse(from, "dgC")) setAs("sparseVector", "nsparseVector", function(from) .V2kind(from, "n")) setAs("sparseVector", "lsparseVector", function(from) .V2kind(from, "l")) setAs("sparseVector", "isparseVector", function(from) .V2kind(from, "i")) setAs("sparseVector", "dsparseVector", function(from) .V2kind(from, "d")) setAs("sparseVector", "zsparseVector", function(from) .V2kind(from, "z")) setAs("vector", "nsparseVector", function(from) .m2V(from, "n")) setAs("vector", "lsparseVector", function(from) .m2V(from, "l")) setAs("vector", "isparseVector", function(from) .m2V(from, "i")) setAs("vector", "dsparseVector", function(from) .m2V(from, "d")) setAs("vector", "zsparseVector", function(from) .m2V(from, "z")) ## ==== To "shape" ===================================================== ..m2gen <- function(from) .m2dense(from, ".ge") setAs( "Matrix", "generalMatrix", ..M2gen) setAs( "matrix", "generalMatrix", ..m2gen) setAs( "vector", "generalMatrix", ..m2gen) setAs("sparseVector", "generalMatrix", .V2C) setAs("Matrix", "symmetricMatrix", ..M2sym) setAs("matrix", "symmetricMatrix", ..M2sym) setAs("Matrix", "triangularMatrix", ..M2tri) setAs("matrix", "triangularMatrix", ..M2tri) rm(..m2gen) setAs("diagonalMatrix", "symmetricMatrix", function(from) { if(!isSymmetricDN(from@Dimnames)) stop("matrix is not symmetric; consider forceSymmetric(.) or symmpart(.)") .diag2sparse(from, ".", "s", "C", "U") }) setAs("diagonalMatrix", "triangularMatrix", function(from) .diag2sparse(from, ".", "t", "C", "U")) ## ==== To "representation" ============================================ setAs("Matrix", "denseMatrix", .M2unpacked) setAs("Matrix", "unpackedMatrix", .M2unpacked) setAs("Matrix", "packedMatrix", .M2packed) setAs("Matrix", "sparseMatrix", .M2C) setAs("Matrix", "CsparseMatrix", .M2C) setAs("Matrix", "RsparseMatrix", .M2R) setAs("Matrix", "TsparseMatrix", .M2T) ## Do test for structure: ## FIXME: wrongly assumes that methods are defined for pack() ... setAs("generalMatrix", "packedMatrix", function(from) pack(from)) setAs("matrix", "denseMatrix", function(from) .m2dense.checking(from, ".")) setAs("matrix", "unpackedMatrix", function(from) .m2dense.checking(from, ".")) setAs("matrix", "packedMatrix", function(from) pack(from)) setAs("matrix", "sparseMatrix", function(from) .m2sparse.checking(from, ".", "C")) setAs("matrix", "CsparseMatrix", function(from) .m2sparse.checking(from, ".", "C")) setAs("matrix", "RsparseMatrix", function(from) .m2sparse.checking(from, ".", "R")) setAs("matrix", "TsparseMatrix", function(from) .m2sparse.checking(from, ".", "T")) ## Many people want this coercion to be available and fast: setAs("matrix", "dgCMatrix", function(from) .m2sparse(from, "dgC")) setAs("vector", "denseMatrix", function(from) if(is.object(from) && length(dim(from)) == 2L) # e.g., data.frame as(as.matrix(from), "denseMatrix") else .m2dense(from, ".ge")) setAs("vector", "unpackedMatrix", function(from) .m2dense(from, ".ge")) setAs("vector", "sparseMatrix", function(from) if(is.object(from) && length(dim(from)) == 2L) # e.g., data.frame as(as.matrix(from), "sparseMatrix") else .m2sparse(from, ".gC")) setAs("vector", "CsparseMatrix", function(from) .m2sparse(from, ".gC")) setAs("vector", "RsparseMatrix", function(from) .m2sparse(from, ".gR")) setAs("vector", "TsparseMatrix", function(from) .m2sparse(from, ".gT")) setAs("ANY", "denseMatrix", function(from) as(as(from, "matrix"), "denseMatrix")) setAs("ANY", "sparseMatrix", function(from) as(as(from, "matrix"), "sparseMatrix")) setAs("sparseVector", "denseMatrix", .V2unpacked) setAs("sparseVector", "unpackedMatrix", .V2unpacked) setAs("sparseVector", "sparseMatrix", .V2C) setAs("sparseVector", "CsparseMatrix", .V2C) setAs("sparseVector", "RsparseMatrix", .V2R) setAs("sparseVector", "TsparseMatrix", .V2T) setAs("Matrix", "diagonalMatrix", .M2diag) setAs("matrix", "diagonalMatrix", .M2diag) setAs("Matrix", "indMatrix", function(from) as(as(from, "nsparseMatrix"), "indMatrix")) setAs("matrix", "indMatrix", function(from) as(as(from, "nsparseMatrix"), "indMatrix")) setAs("Matrix", "pMatrix", function(from) as(as(from, "nsparseMatrix"), "pMatrix")) setAs("matrix", "pMatrix", function(from) as(as(from, "nsparseMatrix"), "pMatrix")) Matrix/R/dense.R0000644000175100001440000001723514575137654013207 0ustar hornikusers## METHODS FOR CLASS: denseMatrix (virtual) ## dense matrices with unpacked _or_ packed storage ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .dense.band <- function(x, k1, k2, ...) .Call(R_dense_band, x, k1, k2) .dense.triu <- function(x, k = 0L, ...) .Call(R_dense_band, x, k, NULL) .dense.tril <- function(x, k = 0L, ...) .Call(R_dense_band, x, NULL, k) .dense.diag.get <- function(x = 1, nrow, ncol, names = TRUE) .Call(R_dense_diag_get, x, names) .dense.diag.set <- function(x, value) .Call(R_dense_diag_set, x, value) .dense.t <- function(x) .Call(R_dense_transpose, x) .dense.fS1 <- function(x, uplo) .Call(R_dense_force_symmetric, x, NULL) .dense.fS2 <- function(x, uplo) .Call(R_dense_force_symmetric, x, uplo) .dense.symmpart <- function(x) .Call(R_dense_symmpart, x) .dense.skewpart <- function(x) .Call(R_dense_skewpart, x) .dense.is.di <- function(object) .Call(R_dense_is_diagonal, object) .dense.is.tr <- function(object, upper = NA, ...) .Call(R_dense_is_triangular, object, upper) .dense.is.sy <- function(object, checkDN = TRUE, ...) { if(checkDN) { ca <- function(check.attributes = TRUE, ...) check.attributes checkDN <- ca(...) } .Call(R_dense_is_symmetric, object, checkDN) } .dense.is.sy.dz <- function(object, checkDN = TRUE, tol = 100 * .Machine$double.eps, tol1 = 8 * tol, ...) { ## backwards compatibility: don't check DN if check.attributes=FALSE if(checkDN) { ca <- function(check.attributes = TRUE, ...) check.attributes checkDN <- ca(...) } ## be very fast when requiring exact symmetry if(tol <= 0) return(.Call(R_dense_is_symmetric, object, checkDN)) ## pretest: is it square? d <- object@Dim if((n <- d[2L]) != d[1L]) return(FALSE) ## pretest: are DN symmetric in the sense of validObject()? if(checkDN && !isSymmetricDN(object@Dimnames)) return(FALSE) if(n == 0L) return(TRUE) object <- .M2gen(object) ## now handling n-by-n [dz]geMatrix, n >= 1: Cj <- if(is.complex(object@x)) Conj else identity ae <- function(check.attributes, ...) { ## discarding possible user-supplied check.attributes all.equal.numeric(..., check.attributes = FALSE) } ## pretest: outermost rows ~= outermost columns? ## (fast for large asymmetric) if(length(tol1)) { i. <- if(n <= 4L) 1L:n else c(1L, 2L, n - 1L, n) for(i in i.) if(!isTRUE(ae(target = object[i, ], current = Cj(object[, i]), tolerance = tol1, ...))) return(FALSE) } isTRUE(ae(target = object @x, current = Cj(t(object))@x, tolerance = tol, ...)) } setMethod("diff", c(x = "denseMatrix"), ## Mostly cut and paste of base::diff.default : function(x, lag = 1L, differences = 1L, ...) { if(length(lag) != 1L || length(differences) != 1L || lag < 1L || differences < 1L) stop(gettextf("'%s' and '%s' must be positive integers", "lag", "differences"), domain = NA) if(lag * differences >= x@Dim[1L]) return(x[0L]) i1 <- -seq_len(lag) for(i in seq_len(differences)) { m <- x@Dim[1L] x <- x[i1, , drop = FALSE] - x[-m:-(m - lag + 1L), , drop = FALSE] } x }) setMethod("mean", c(x = "denseMatrix"), function(x, ...) mean.default(.M2v(x), ...)) setMethod("rep", c(x = "denseMatrix"), function(x, ...) rep(.M2v(x), ...)) setMethod("band" , c(x = "denseMatrix"), .dense.band) setMethod("triu" , c(x = "denseMatrix"), .dense.triu) setMethod("tril" , c(x = "denseMatrix"), .dense.tril) setMethod("diag" , c(x = "denseMatrix"), .dense.diag.get) setMethod("diag<-", c(x = "denseMatrix"), .dense.diag.set) setMethod("t" , c(x = "denseMatrix"), .dense.t) setMethod("forceSymmetric", c(x = "denseMatrix", uplo = "missing"), .dense.fS1) setMethod("forceSymmetric", c(x = "denseMatrix", uplo = "character"), .dense.fS2) setMethod("symmpart", c(x = "denseMatrix"), .dense.symmpart) setMethod("skewpart", c(x = "denseMatrix"), .dense.skewpart) setMethod("isSymmetric" , c(object = "denseMatrix"), .dense.is.sy) setMethod("isTriangular", c(object = "denseMatrix"), .dense.is.tr) setMethod("isDiagonal" , c(object = "denseMatrix"), .dense.is.di) .dense.subclasses <- names(getClassDef("denseMatrix")@subclasses) for (.cl in grep("^[dz](ge|tr|tp)Matrix$", .dense.subclasses, value = TRUE)) setMethod("isSymmetric" , c(object = .cl), .dense.is.sy.dz) rm(.cl, .dense.subclasses) ## METHODS FOR CLASS: unpackedMatrix (virtual) ## dense matrices with unpacked storage ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("unpack", c(x = "packedMatrix"), function(x, ...) .Call(R_dense_as_unpacked, x)) setMethod("pack", c(x = "packedMatrix"), function(x, ...) x) ## METHODS FOR CLASS: packedMatrix (virtual) ## dense matrices with packed storage ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .uM.pack <- function(x, ...) .Call(R_dense_as_packed, x, NULL, NULL) .uM.pack.ge <- function(x, symmetric = NA, upperTri = NA, ...) { if(((sna <- is.na(symmetric)) || symmetric) && isSymmetric(x, ...)) .Call(R_dense_as_packed, x, "U", NULL) else if((sna || !symmetric) && (it <- isTriangular(x, upper = upperTri))) { uplo <- if(is.na(upperTri)) attr(it, "kind") else if(upperTri) "U" else "L" .Call(R_dense_as_packed, x, uplo, "N") } else { if(sna) stop("matrix is not symmetric or triangular") else if(symmetric) stop("matrix is not symmetric") else stop("matrix is not triangular") } } setMethod("unpack", c(x = "unpackedMatrix"), function(x, ...) x) setMethod("pack", c(x = "unpackedMatrix"), .uM.pack) .uM.subclasses <- names(getClassDef("unpackedMatrix")@subclasses) for(.cl in grep("^.geMatrix$", .uM.subclasses, value = TRUE)) setMethod("pack", c(x = .cl), .uM.pack.ge) rm(.cl, .uM.subclasses) ## METHODS FOR CLASS: matrix ## traditional matrices, which really are "dense" ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .m.pack <- .uM.pack.ge body(.m.pack)[[2L]][[3L]] <- quote(.m2dense(x, ".sp", "U")) body(.m.pack)[[2L]][[4L]][[3L]][[3L]] <- quote(.m2dense(x, ".tp", uplo)) setMethod("unpack", c(x = "matrix"), function(x, ...) .m2dense.checking(x, ".")) setMethod("pack", c(x = "matrix"), .m.pack) setMethod("band", c(x = "matrix"), .dense.band) setMethod("triu", c(x = "matrix"), .dense.triu) setMethod("tril", c(x = "matrix"), .dense.tril) setMethod("forceSymmetric", c(x = "matrix", uplo = "missing"), function(x, uplo) .m2dense(x, ".sy", "U")) setMethod("forceSymmetric", c(x = "matrix", uplo = "character"), function(x, uplo) .m2dense(x, ".sy", uplo)) setMethod("symmpart", c(x = "matrix"), function(x) symmetrizeDN(0.5 * (x + t(x)))) setMethod("skewpart", c(x = "matrix"), function(x) symmetrizeDN(0.5 * (x - t(x)))) setMethod("isTriangular", c(object = "matrix"), .dense.is.tr) setMethod("isDiagonal" , c(object = "matrix"), .dense.is.di) rm(.uM.pack, .uM.pack.ge, .m.pack, list = c(grep("^[.]dense[.](band|tri[ul]|diag[.](get|set)|t|fS[12]|symmpart|skewpart|is[.](sy|tr|di)([.]dz)?)$", ls(all.names = TRUE), value = TRUE))) Matrix/R/condest.R0000644000175100001440000003234112070371667013533 0ustar hornikusers#### This is a "translation" of GNU octave's #### ~/src/octave-3.2.4/scripts/linear-algebra/condest.m #### and ~/src/octave-3.2.4/scripts/linear-algebra/onenormest.m #### which have identical copyright and references (see below): #### ##__\begin{copyright clause}______________________________________________ ## Copyright (C) 2007, 2008, 2009 Regents of the University of California ## ## This file is part of Octave. ## ## 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 3 of the License, 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 Octave; see the file COPYING. If not, see ## . ## Code originally licensed under ## ## Copyright (c) 2007, Regents of the University of California ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted provided that the following conditions ## are met: ## ## * Redistributions of source code must retain the above copyright ## notice, this list of conditions and the following disclaimer. ## ## * Redistributions in binary form must reproduce the above ## copyright notice, this list of conditions and the following ## disclaimer in the documentation and/or other materials provided ## with the distribution. ## ## * Neither the name of the University of California, Berkeley nor ## the names of its contributors may be used to endorse or promote ## products derived from this software without specific prior ## written permission. ## ## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' ## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A ## PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ## SUCH DAMAGE. ## Author: Jason Riedy ## Keywords: linear-algebra norm estimation ## Version: 0.2 ##__\end{copyright clause}________________________________________________ condest <- function(A, t = min (n, 5), normA = norm(A, "1"), silent = FALSE, quiet = TRUE) { ## Octave has further optional args and "calling sequences" ## may be implement at a later time point ## if(length(d <- dim(A)) != 2 || (n <- d[1]) != d[2]) stop("'A' must be a square matrix") luA <- lu(A) i.n <- seq_len(n) isSparse <- is(A, "sparseMatrix") if(isSparse) { ### FIXME: if A is not a Matrix, but already a "CHMfactor" as resulting from ### Cholesky() , then we can procede more efficiently , notably ### because of the solve(A, b, system = ".*") options ! ## luA = "sparseLU": slots (L, U, p,q, Dim); ## expand(luA) == list(P, L, U, Q) <----> A = P' L U Q ## where P A == A[p +1,] and A Q' == A[, q +1] ## <==> A^(-1) x = Q' U^-1 L^-1 P x = Q'y ## and A^(-T) x =(Q' U^-1 L^-1 P)' x = P' L^-T U^-T Q x = P'z q. <- q.i <- luA@q + 1L; q.i[q.i] <- i.n p. <- p.i <- luA@p + 1L; p.i[p.i] <- i.n ## q.i := inv(q.) & p.i := inv(p.), the inverse permutations Ut <- t(luA@U) Lt <- t(luA@L) f.solve <- function(x) solve(luA@U, solve(luA@L, x[p.,]))[q.i,] f.solve_t <- function(x) solve(Lt, solve(Ut, x[q.,]))[p.i,] ##Oct [L, U, P, Pc] = lu (A); ##Oct solve = @(x) Pc' * (U \ (L \ (P * x))); ##Oct solve_t = @(x) P' * (L' \ (U' \ (Pc * x))); } else { ## luA is "denseLU" : e.A <- expand(luA) ## == list(L, U, P), where A = PLU p. <- p.i <- luA@perm; p.i[p.i] <- i.n ## p.i := inv(p.), the inverse permutation Ut <- t(e.A$U) Lt <- t(e.A$L) ## A = PLU <--> A^{-1} x = U^-1 L^-1 P x ## A^{-T} x = (U^-1 L^-1 P)' x = P' L^-T U^-T x = P'z f.solve <- function(x) solve(e.A$U, solve(e.A$L, x[p.,])) f.solve_t <- function(x) solve(Lt, solve(Ut, x))[p.i,] ##Oct [L, U, P] = lu (A); ##Oct solve = @(x) U \ (L \ (P*x)); ##Oct solve_t = @(x) P' * (L' \ (U' \ x)); } n1.res <- ## onenormest (A^{-1}, t=t) -- of course,that's *NOT* what we want onenormest (A.x = f.solve, At.x = f.solve_t, t=t, n=n, quiet=quiet, silent=silent) ## [Ainv_norm, v, w] = onenormest (solve, solve_t, n, t); w <- n1.res[["w"]] list(est = normA * n1.res[["est"]], v = w / sum(abs(w))) # sum(|w|) = norm(w, "1") } ## %!demo ## %! N = 100; ## %! A = randn (N) + eye (N); ## %! condest (A) ## %! [L,U,P] = lu (A); ## %! condest (A, @(x) U\ (L\ (P*x)), @(x) P'*(L'\ (U'\x))) ## %! condest (@(x) A*x, @(x) A'*x, @(x) U\ (L\ (P*x)), @(x) P'*(L'\ (U'\x)), N) ## %! norm (inv (A), 1) * norm (A, 1) ### Yes, these test bounds are really loose. There's ### enough randomization to trigger odd cases with hilb(). ## %!test ## %! N = 6; ## %! A = hilb (N); ## %! cA = condest (A); ## %! cA_test = norm (inv (A), 1) * norm (A, 1); ## %! assert (cA, cA_test, -2^-8); ## %!test ## %! N = 6; ## %! A = hilb (N); ## %! solve = @(x) A\x; solve_t = @(x) A'\x; ## %! cA = condest (A, solve, solve_t); ## %! cA_test = norm (inv (A), 1) * norm (A, 1); ## %! assert (cA, cA_test, -2^-8); ## %!test ## %! N = 6; ## %! A = hilb (N); ## %! apply = @(x) A*x; apply_t = @(x) A'*x; ## %! solve = @(x) A\x; solve_t = @(x) A'\x; ## %! cA = condest (apply, apply_t, solve, solve_t, N); ## %! cA_test = norm (inv (A), 1) * norm (A, 1); ## %! assert (cA, cA_test, -2^-6); ## %!test ## %! N = 12; ## %! A = hilb (N); ## %! [rcondA, v] = condest (A); ## %! x = A*v; ## %! assert (norm(x, inf), 0, eps); ##------------ onenormest ------------------------------------------ onenormest <- function(A, t = min(n, 5), A.x, At.x, n, silent = FALSE, quiet = silent, iter.max = 10, eps = 4* .Machine$double.eps) { mi.A <- missing(A) mi.A.x <- missing(A.x) mi.At.x <- missing(At.x) no.A.x <- mi.A.x || !is.function(A.x) no.At.x <- mi.At.x || !is.function(At.x) if(mi.A && (no.A.x || no.At.x)) stop("must either specify 'A' or the functions 'A.x' and 'At.x'") if(!mi.A && (!mi.A.x || !mi.At.x)) warning("when 'A' is specified, 'A.x' and 'At.x' are disregarded") if(mi.A) { stopifnot(is.numeric(n), length(n) == 1, n == round(n), n >= 0) } else { ## using 'A' if(length(d <- dim(A)) != 2 || (n <- d[1]) != d[2]) stop("'A' must be a square matrix") rm(d) } stopifnot(is.numeric(t), length(t) == 1, t >= 1, iter.max >= 1) ## Initial test vectors X. X <- matrix(runif(n*t), n,t) # X = rand (n, t); ## scale X to have column sums == 1 : X <- X / rep(colSums(X), each=n) ## Track if a vertex has been visited. been_there <- logical(n) # zeros (n, 1); I.t <- diag(nrow = t) ## To check if the estimate has increased. est_old <- 0 ## Normalized vector of signs. S <- matrix(0, n, t) for(iter in 1:(iter.max + 1)) { Y <- if(mi.A) A.x(X) else A %*% X ## is n x t ## Find the initial estimate as the largest A*x. ## [est, imax] = max (sum (abs (Y), 1)) imax <- which.max(cY <- colSums(abs(Y))) est <- cY[imax] if (est > est_old || iter == 2) w <- Y[, imax] if (iter >= 2 && est < est_old) { ## No improvement, so stop. est <- est_old break } est_old <- est S_old <- S if (iter > iter.max) { ## Gone too far. Stop. if(!silent) warning(gettextf("not converged in %d iterations", iter.max), domain = NA) break } S <- sign (Y) ## n x t ## Test if any of S are approximately parallel to previous S ## vectors or current S vectors. If everything is parallel, ## stop. Otherwise, replace any parallel vectors with ## rand{-1,+1}. partest <- apply(abs(crossprod(S_old, S) - n) < eps*n, 2, any) if (all(partest)) { ## All the current vectors are parallel to old vectors. ## We've hit a cycle, so stop. if(!quiet) message("hit a cycle (1) -- stop iterations") break } if (any(partest)) { ## Some vectors are parallel to old ones and are cycling, ## but not all of them. Replace the parallel vectors with ## rand{-1,+1}. numpar <- sum (partest) replacements <- matrix(sample(c(-1,1), n*numpar,replace=TRUE), n, numpar) S[,partest] <- replacements } ## Now test for parallel vectors within S. partest <- apply(crossprod(S) - I.t == n, 2, any) if (any(partest)) { numpar <- sum(partest) replacements <- matrix(sample(c(-1,1), n*numpar,replace=TRUE), n, numpar) S[,partest] <- replacements } Z <- if(mi.A) At.x(S) else crossprod(A, S) ## -- n x t ## Now find the largest non-previously-visted index per vector. ## h = max(2, abs(Z)) ## -- n x t h <- pmax.int(2, as(abs(Z),"matrix")); dim(h) <- dim(Z) ## -- n x t ## [mh, mhi] = max (h) : for each column h[,j]: ## mh[j] = max(h[,j]); mhi = argmax(..) mhi <- apply(h, 2, which.max) ## mh <- h[cbind(mhi,1:t)] if (iter >= 2 && all(mhi == imax)) { ## (mhi == imax) : in octave this is only true when it's for all() ## Hit a cycle, stop. if(!quiet) message("hit a cycle (2) -- stop iterations") break } ## [h, ind] = sort (h, 'descend'): r <- apply(h, 2, sort.int, decreasing=TRUE, index.return=TRUE) #-> list h <- sapply(r, `[[`, "x") ind <- sapply(r, `[[`, "ix") #-> n x t {each column = permutation of 1:n} if (t > 1) { firstind <- ind[1:t] if (all (been_there[firstind])) { ## Visited all these before, so stop. break } ind <- ind[!been_there[ind]] ##-> now ind is a simple vector if(length(ind) < t) { ## There aren't enough new vectors, so we're practically ## in a cycle. Stop. if(!quiet) message("not enough new vecs -- stop iterations") break } } ## Visit the new indices. X <- matrix(0, n, t) X[cbind(ind[1:t], 1:t)] <- 1 ## for(zz in 1:t) X[ind[zz],zz] <- 1 been_there [ind[1:t]] <- TRUE } ## for(iter ...) ## The estimate est and vector w are set in the loop above. The ## vector v selects the imax column of A. v <- integer(n) v[imax] <- 1L list(est=est, v=v, w=w, iter=iter) }## {onenormest} ## %!demo ## %! N = 100; ## %! A = randn(N) + eye(N); ## %! [L,U,P] = lu(A); ## %! nm1inv = onenormest(@(x) U\(L\(P*x)), @(x) P'*(L'\(U'\x)), N, 30) ## %! norm(inv(A), 1) ## %!test ## %! N = 10; ## %! A = ones (N); ## %! [nm1, v1, w1] = onenormest (A); ## %! [nminf, vinf, winf] = onenormest (A', 6); ## %! assert (nm1, N, -2*eps); ## %! assert (nminf, N, -2*eps); ## %! assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps) ## %! assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps) ## %!test ## %! N = 10; ## %! A = ones (N); ## %! [nm1, v1, w1] = onenormest (@(x) A*x, @(x) A'*x, N, 3); ## %! [nminf, vinf, winf] = onenormest (@(x) A'*x, @(x) A*x, N, 3); ## %! assert (nm1, N, -2*eps); ## %! assert (nminf, N, -2*eps); ## %! assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps) ## %! assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps) ## %!test ## %! N = 5; ## %! A = hilb (N); ## %! [nm1, v1, w1] = onenormest (A); ## %! [nminf, vinf, winf] = onenormest (A', 6); ## %! assert (nm1, norm (A, 1), -2*eps); ## %! assert (nminf, norm (A, inf), -2*eps); ## %! assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps) ## %! assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps) ## ## Only likely to be within a factor of 10. ## %!test ## %! N = 100; ## %! A = rand (N); ## %! [nm1, v1, w1] = onenormest (A); ## %! [nminf, vinf, winf] = onenormest (A', 6); ## %! assert (nm1, norm (A, 1), -.1); ## %! assert (nminf, norm (A, inf), -.1); ## %! assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps) ## %! assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps) Matrix/R/Ops.R0000644000175100001440000027505514575137654012660 0ustar hornikusers## METHODS FOR GENERIC: Ops = {Arith, Compare, Logic} (group) ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## > getGroupMembers("Ops") ## [1] "Arith" "Compare" "Logic" ## > getGroupMembers("Arith") ## [1] "+" "-" "*" "^" "%%" "%/%" "/" ## > getGroupMembers("Compare") ## [1] "==" ">" "<" "!=" "<=" ">=" ## > getGroupMembers("Logic") # excluding unary "!" -> ./not.R ## [1] "&" "|" if(FALSE) { ## vvvv MJ: for _after_ 1.6-2, ditto ./(Arith|Compare|Logic).R .Ops.invalid <- function(x) { if(is.object(x)) gettextf("invalid class \"%s\" in '%s' method", class(x)[1L], "Ops") else gettextf("invalid type \"%s\" in '%s' method", typeof(x), "Ops") } for(.cl in c("Matrix", "sparseVector")) { setMethod("Ops", c(e1 = .cl, e2 = "ANY"), function(e1, e2) if(any(typeof(e2) == c("logical", "integer", "double"))) { if(is.matrix(e2)) callGeneric(e1, unclass(e2)) else callGeneric(e2, as.vector(e2)) } else stop(.Ops.invalid(e2), domain = NA)) setMethod("Ops", c(e1 = "ANY", e2 = .cl), function(e1, e2) if(any(typeof(e1) == c("logical", "integer", "double"))) { if(is.matrix(e1)) callGeneric(unclass(e1), e2) else callGeneric(as.vector(e1), e2) } else stop(.Ops.invalid(e1), domain = NA)) setMethod("Ops", c(e1 = .cl, e2 = "NULL"), function(e1, e2) callGeneric(e1, logical(0L))) setMethod("Ops", c(e1 = "NULL", e2 = .cl), function(e1, e2) callGeneric(logical(0L), e2)) ## MJ: OK, but I'd prefer to handle all "matrix" as ".geMatrix" setMethod("Ops", c(e1 = .cl, e2 = "matrix"), function(e1, e2) if(any(typeof(e2) == c("logical", "integer", "double"))) callGeneric(e1, Matrix(e2)) else stop(.Ops.invalid(e2), domain = NA)) ## MJ: OK, but I'd prefer to handle all "matrix" as ".geMatrix" setMethod("Ops", c(e1 = "matrix", e2 = .cl), function(e1, e2) if(any(typeof(e1) == c("logical", "integer", "double"))) callGeneric(Matrix(e1), e2) else stop(.Ops.invalid(e1), domain = NA)) } rm(.cl) ## ^^^^ MJ: for _after_ 1.6-2, ditto ./(Arith|Compare|Logic).R } .Ops.checkDim <- function(d.a, d.b) { if(any(d.a != d.b)) stop(gettextf("non-conformable matrix dimensions in %s", deparse(sys.call(sys.parent()))), call. = FALSE, domain = NA) d.a } .Ops.checkDimNames <- function(dn.a, dn.b, useFirst = TRUE, check = FALSE) { ## behave as described in ?Arithmetic nullDN <- list(NULL, NULL) h.a <- !identical(nullDN, dn.a) h.b <- !identical(nullDN, dn.b) if(h.a || h.b) { if(useFirst) { if(!h.a) dn.b else dn.a } else { if (!h.b) dn.a else if(!h.a) dn.b else { ## both have non-trivial dimnames r <- dn.a # "default" result for(j in 1:2) if(!is.null(dn <- dn.b[[j]])) { if(is.null(r[[j]])) r[[j]] <- dn else if(check && !identical(r[[j]], dn)) warning(gettextf("dimnames [%d] mismatch in %s", j, deparse(sys.call(sys.parent()))), call. = FALSE, domain = NA) } r } } } else nullDN } ## cache them [rather in package 'methods' ??] .ArithGenerics <- getGroupMembers("Arith") if(FALSE) { # unused .CompareGenerics <- getGroupMembers("Compare") .LogicGenerics <- getGroupMembers("Logic") } ### Design decision for *sparseMatrix*: ### work via Csparse since Tsparse are not-unique (<-> slots not compatible) ### -- 0 -- (not dense *or* sparse) ----------------------------------- ##-------- originally from ./Matrix.R -------------------- ## Some ``Univariate'' "Arith" (univariate := 2nd argument 'e2' is missing) setMethod("+", c(e1 = "Matrix", e2 = "missing"), function(e1,e2) e1) ## "fallback": setMethod("-", c(e1 = "Matrix", e2 = "missing"), function(e1, e2) { warning("inefficient method used for \"- e1\"") 0 - e1 }) setMethod("-", c(e1 = "denseMatrix", e2 = "missing"), function(e1, e2) { e1@x <- -e1@x if(.hasSlot(e1, "factors") && length(e1@factors)) e1@factors <- list() e1 }) setMethod("-", c(e1 = "diagonalMatrix", e2 = "missing"), function(e1, e2) { kind <- .M.kind(e1) r <- new(if(kind == "z") "zdiMatrix" else "ddiMatrix") r@Dim <- d <- e1@Dim r@Dimnames <- e1@Dimnames r@x <- if(e1@diag != "N") rep.int(if(kind == "z") -1+0i else -1, d[1L]) else -(if(kind == "n") e1@x | is.na(e1@x) else e1@x) r }) ## old-style matrices are made into new ones setMethod("Ops", c(e1 = "Matrix", e2 = "matrix"), function(e1, e2) callGeneric(e1, Matrix(e2))) setMethod("Ops", c(e1 = "matrix", e2 = "Matrix"), function(e1, e2) callGeneric(Matrix(e1), e2)) ## Note: things like callGeneric(Matrix(e1, sparse=is(e2,"sparseMatrix")), e2)) ## may *not* be better: e.g. Matrix(.) can give *diagonal* instead of sparse ## NULL should be treated as logical(0) {which often will be coerced to numeric(0)}: setMethod("Ops", c(e1 = "Matrix", e2 = "NULL"), function(e1, e2) callGeneric(e1, logical())) setMethod("Ops", c(e1 = "NULL", e2 = "Matrix"), function(e1, e2) callGeneric(logical(), e2)) setMethod("Ops", c(e1 = "Matrix", e2 = "ANY"), function(e1, e2) if(is.object(e2) && is.matrix(e2)) callGeneric(e1, unclass(e2)) # e.g., for "table" else .bail.out.2(.Generic, class(e1), class(e2))) setMethod("Ops", c(e1 = "ANY", e2 = "Matrix"), function(e1, e2) if(is.object(e1) && is.matrix(e1)) callGeneric(unclass(e1), e2) # e.g., for "table" else .bail.out.2(.Generic, class(e1), class(e2))) ## "General principle" ## - - - - - - - - - ## For "Arith" it is sufficient (though not optimal, once we have "iMatrix"!) ## to define "dMatrix" methods and coerce all other "[nli]Matrix" to "dMatrix" setMethod("Arith", c(e1 = "Matrix", e2 = "Matrix"), function(e1, e2) callGeneric(as(e1, "dMatrix"), as(e2, "dMatrix"))) ## For "Compare", this would be feasible too, but is clearly suboptimal, ## particularly for "==" and "!=" ## and for "lMatrix" and "nMatrix" should not coerce at all if(FALSE) setMethod("Compare", c(e1 = "Matrix", e2 = "Matrix"), function(e1, e2) { if(is.na(match(.Generic, c("==", "!=")))) callGeneric(as(e1, "dMatrix"), as(e2, "dMatrix")) else { ## no coercion needed for "==" or "!=" ## ## what now ? <<<<<<<<<<< FIXME >>>>>>>>> .bail.out.2(.Generic, class(e1), class(e2)) } }) ## Working entirely on "matching" x slot: ## can be done for matching-dim "*geMatrix", and also ## matching-{dim + uplo} for *packed* (only!) symmetric+triangular .Ops.via.x <- function(e1, e2) { .Ops.checkDim(dim(e1), dim(e2)) e1@x <- callGeneric(e1@x, e2@x) if(.hasSlot(e1, "factors") && length(e1@factors)) e1@factors <- list() e1 } ###-------- originally from ./dMatrix.R -------------------- ## ## Note that there extra methods for o ! ## ## "Compare" -> returning logical Matrices; .Cmp.swap() is in ./Auxiliaries.R setMethod("Compare", c(e1 = "numeric", e2 = "dMatrix"), .Cmp.swap) setMethod("Compare", c(e1 = "logical", e2 = "dMatrix"), .Cmp.swap) setMethod("Compare", c(e1 = "numeric", e2 = "lMatrix"), .Cmp.swap) setMethod("Compare", c(e1 = "logical", e2 = "lMatrix"), .Cmp.swap) setMethod("Compare", c(e1 = "numeric", e2 = "nMatrix"), .Cmp.swap) setMethod("Compare", c(e1 = "logical", e2 = "nMatrix"), .Cmp.swap) ## This is parallel to Logic.Mat.atomic() below ---> __keep parallel__ ! Cmp.Mat.atomic <- function(e1, e2) { ## result will inherit from "lMatrix" n1 <- prod(d <- e1@Dim) cl <- class(e1) if((l2 <- length(e2)) == 0) return(if(n1 == 0) as(e1, "lMatrix") else as.logical(e2)) ## else if(n1 && n1 < l2) stop(sprintf("dim [product %d] do not match the length of object [%d]", n1, l2)) cl1 <- getClassDef(cl) slots1 <- names(cl1@slots) has.x <- any("x" == slots1)# *fast* check for "x" slot presence if(l2 > 1 && has.x) return(if(n1 == 0) { sNms <- .slotNames(e1) r <- copyClass(e1, class2(cl,"l"), sNames = sNms[sNms != "x"], check = FALSE) r@x <- callGeneric(e1@x, e2) r } else # cannot simply compare e2, e1@x -> use another method callGeneric(e1, Matrix(e2, nrow=d[1], ncol=d[2])) ) ## else Udg <- extends(cl1, "triangularMatrix") && e1@diag == "U" r0 <- callGeneric(0, e2) r <- callGeneric(if(has.x) e1@x else TRUE, e2) ## Udg: append the diagonal at *end*, as diagU2N(): r. <- if(Udg) c(r, callGeneric(..diag.x(e1), e2)) else r ## trivial case first (beware of NA) if(isTRUE(all(r0) && all(r.))) { r <- new(if(d[1] == d[2]) "lsyMatrix" else "lgeMatrix") r@Dim <- d r@Dimnames <- e1@Dimnames r@x <- rep.int(TRUE, n1) } else if(extends(cl1, "denseMatrix")) { full <- !.isPacked(e1) # << both "dtr" and "dsy" are 'full' if(full || allFalse(r0) || extends(cl1, "symmetricMatrix")) { isTri <- extends(cl1, "triangularMatrix") ## FIXME? using copyClass() to copy "relevant" slots r <- new(class2(cl, "l"), x = r, Dim = d, Dimnames = e1@Dimnames) if(extends(cl1, "symmetricMatrix")) { r@uplo <- e1@uplo } else if(isTri) { r@uplo <- e1@uplo r@diag <- e1@diag } } else { ## packed matrix with structural 0 and r0 is not all FALSE: ##--> result cannot be packed anymore ## [dense & packed & not symmetric ] ==> must be "dtp*" : if(!extends(cl1, "dtpMatrix")) stop("internal bug in \"Compare\" method (Cmp.Mat.atomic); please report") rx <- rep_len(r0, n1) rx[indTri(d[1], upper = (e1@uplo == "U"), diag=TRUE)] <- r. r <- new("lgeMatrix", x = rx, Dim = d, Dimnames = e1@Dimnames) } } else { ##---- e1 is(. , sparseMatrix) ----------------- ## FIXME: remove this test eventually if(extends(cl1, "diagonalMatrix")) stop("Cmp.Mat.atomic() should not be called for diagonalMatrix") remainSparse <- allFalse(r0) ## <==> things remain sparse if(Udg) { # e1 *is* unit-diagonal (triangular sparse) r1 <- callGeneric(1, e2) Udg <- all(r1) # maybe Unit-diagonal (sparse) result ## if(!remainSparse) we'll use non0ind() which *has* unit-diag. indices at end ## if(Udg && remainSparse) { } else { ## result will not be unit-diagonal sparse e1 <- .diagU2N(e1, cl = cl1) # otherwise, result is U-diag ## FIXME? rather ## if(extends1of(cl1, c("CsparseMatrix", "RsparseMatrix","TsparseMatrix")) { if(extends(cl1, "CsparseMatrix")) { ## repeat computation if e1 has changed r. <- callGeneric(if(has.x) e1@x else TRUE, e2) } } } if(remainSparse) { if(!anyNA(r) && ((Ar <- all(r)) || !any(r))) { lClass <- class2(cl, "l") # is "lsparse*" r <- new(lClass) r@Dim <- d r@Dimnames <- e1@Dimnames if(Ar) { # 'TRUE' instead of 'x': same sparsity: for(n in intersect(c("i","j","p","uplo","diag"), slots1)) slot(r, n) <- slot(e1, n) n <- if(has.x) length(e1@x) else if(any("p" == slots1)) e1@p[d[2]+1L] else length(e1@i) r@x <- rep.int(TRUE, n) } else { ## !any(r): all FALSE: keep empty 'r' matrix ## but may need a valid 'pointer' slot: if(extends(lClass, "CsparseMatrix")) r@p <- rep.int(0L, 1+ncol(r)) else if(extends(lClass, "RsparseMatrix")) r@p <- rep.int(0L, 1+nrow(r)) } } else { # some TRUE, FALSE, NA : go via unique 'Tsparse' M <- asUniqueT(e1) nCl <- class2(class(M), 'l') # logical Tsparse sN <- slotNames(nCl) ## copy "the other slots" (important for "tr"/"sym"): r <- copyClass(M, nCl, sNames = sN[is.na(match(sN, "x"))]) r@x <- callGeneric(if(has.x) M@x else 1, e2) if(extends(cl1, "CsparseMatrix")) r <- .M2C(r) else if(extends(cl1, "RsparseMatrix")) r <- .M2R(r) } } else { ## non sparse result; triangularity also gone, typically lClass <- if(extends(cl1, "symmetricMatrix")) "lsyMatrix" else "lgeMatrix" Matrix.message(sprintf("sparse to dense (%s) coercion in '%s' -> %s", lClass, .Generic, "Cmp.Mat.atomic"), .M.level = 2) rx <- rep_len(r0, n1) ## Here, we assume that 'r.' and the indices align (!) encI <- .Call(m_encodeInd, non0ind(e1, cl1, uniqT=FALSE, xtendSymm=FALSE), di = d, orig1=FALSE, checkBounds=FALSE) rx[1L + encI] <- r. r <- new(lClass, x = rx, Dim = d, Dimnames = e1@Dimnames) } } r } setMethod("Compare", c(e1 = "dMatrix", e2 = "numeric"), Cmp.Mat.atomic) setMethod("Compare", c(e1 = "dMatrix", e2 = "logical"), Cmp.Mat.atomic) setMethod("Compare", c(e1 = "lMatrix", e2 = "numeric"), Cmp.Mat.atomic) setMethod("Compare", c(e1 = "lMatrix", e2 = "logical"), Cmp.Mat.atomic) setMethod("Compare", c(e1 = "nMatrix", e2 = "numeric"), Cmp.Mat.atomic) setMethod("Compare", c(e1 = "nMatrix", e2 = "logical"), Cmp.Mat.atomic) rm(Cmp.Mat.atomic) ## "xMatrix <-> work with 'x' slot {was originally just for "Compare"}: ## ------- {also used for "Arith"}: Ops.x.x <- function(e1, e2) { d <- .Ops.checkDim(dim(e1), dim(e2)) if((dens1 <- extends(c1 <- class(e1), "denseMatrix"))) gen1 <- extends(c1, "generalMatrix") if((dens2 <- extends(c2 <- class(e2), "denseMatrix"))) gen2 <- extends(c2, "generalMatrix") if(dens1 && dens2) { ## both inherit from ddense* geM <- TRUE if(!gen1) { if(!gen2) { ## consider preserving "triangular" / "symmetric" geM <- FALSE le <- prod(d) isPacked <- function(x) length(x@x) < le Mclass <- if(extends(c1, "symmetricMatrix") && extends(c2, "symmetricMatrix")) { if(e1@uplo != e2@uplo) ## one is upper, one is lower e2 <- t(e2) if((p1 <- isPacked(e1)) | (p2 <- isPacked(e2))) { ## at least one is packed if(p1 != p2) { ## one is not packed --> *do* pack it: if(p1) e2 <- pack(e2) else e1 <- pack(e1) } "spMatrix" } else "syMatrix" } else if(extends(c1, "triangularMatrix") && extends(c2, "triangularMatrix")) { geM <- e1@uplo != e2@uplo || isN0(callGeneric(0,0)) if(!geM) { if(e1@diag == "U") e1 <- ..diagU2N(e1) if(e2@diag == "U") e2 <- ..diagU2N(e2) p1 <- isPacked(e1) p2 <- isPacked(e2) if(p1 || p2) { ## at least one is packed if(p1 != p2) { ## one is not packed --> *do* pack it: if(p1) e2 <- pack(e2) else e1 <- pack(e1) } "tpMatrix" } else "trMatrix" } } else { ## not symmetric, not triangular ==> "general" geM <- TRUE } if(geM) e2 <- .M2gen(e2) } if(geM) e1 <- .M2gen(e1) # was "dgeMatrix" } else { ## gen1 if(!gen2) e2 <- .M2gen(e2) } ## now, in all cases @x should be matching & correct ## {only "uplo" part is used} r <- callGeneric(e1@x, e2@x) if(is.integer(r)) ## as "igeMatrix" does not yet exist! r <- as.double(r) kr <- .M.kind(r) if(geM) new(paste0(kr, "geMatrix"), x = r, Dim = d, Dimnames = e1@Dimnames) else new(paste0(kr, Mclass), x = r, Dim = d, Dimnames = e1@Dimnames, uplo = e1@uplo) } else { r <- if(!dens1 && !dens2) ## both e1 _and_ e2 are sparse. ## Now (new method dispatch, 2009-01) *does* happen ## even though we have o methods callGeneric(as(e1, "CsparseMatrix"), as(e2, "CsparseMatrix")) else if(dens1 && !dens2) ## go to dense callGeneric(e1, as(e2, "denseMatrix")) else ## if(!dens1 && dens2) callGeneric(as(e1, "denseMatrix"), e2) if(!is(r, "sparseMatrix") && sparseDefault(r)) as(r, "sparseMatrix") else r } } setMethod("Ops", c(e1 = "dMatrix", e2 = "dMatrix"), Ops.x.x) setMethod("Ops", c(e1 = "lMatrix", e2 = "lMatrix"), Ops.x.x) ## n*: for "Arith" go via dMatrix, for "Logic" via "lMatrix" setMethod("Compare", c(e1 = "nMatrix", e2 = "nMatrix"), Ops.x.x) ## l o d : depends on *kind* of Ops -- but Ops.x.x works on slots - correctly: setMethod("Ops", c(e1="lMatrix", e2="dMatrix"), Ops.x.x) setMethod("Ops", c(e1="dMatrix", e2="lMatrix"), Ops.x.x) ## lMatrix & nMatrix ... probably should also just use "Matrix" ? ## ## Hmm, the coercion should differ, depending on subgroup ("Logic", "Arith",..) ## --> try to get rid of these setMethod("Ops", c(e1="lMatrix", e2="numeric"), function(e1, e2) callGeneric(as(e1,"dMatrix"), e2)) setMethod("Ops", c(e1="numeric", e2="lMatrix"), function(e1, e2) callGeneric(e1, as(e2,"dMatrix"))) setMethod("Ops", c(e1="nMatrix", e2="numeric"), function(e1, e2) callGeneric(as(e1,"dMatrix"), e2)) setMethod("Ops", c(e1="numeric", e2="nMatrix"), function(e1, e2) callGeneric(e1, as(e2,"dMatrix"))) ## setMethod("Ops", c(e1="Matrix", e2="logical"), ## function(e1,e2) callGeneric(as(e1,"lMatrix"), e2)) ## setMethod("Ops", c(e1="logical", e2="Matrix"), ## function(e1,e2) callGeneric(e1, as(e2,"lMatrix"))) ## "dpoMatrix" / "dppMatrix" : ## Positive-definiteness is lost with all "Ops" but some "Arith" cases for(cl in c("numeric", "logical")) { # "complex", "raw" : basically "replValue" setMethod("Arith", c(e1 = cl, e2 = "dpoMatrix"), function(e1, e2) { if(!(l1 <- length(e1))) double(0L) else if(l1 == 1 && any(.Generic == c("*","/","+")) && (e1 > 0)) { e2@x <- callGeneric(e1, e2@x) if(length(e2@factors)) e2@factors <- list() e2 # remains "dpo" } else callGeneric(e1, as(e2, "dsyMatrix")) }) setMethod("Arith", c(e1 = cl, e2 = "dppMatrix"), function(e1, e2) { if(!(l1 <- length(e1))) double(0L) else if(l1 == 1 && any(.Generic == c("*","/","+")) && (e1 > 0)) { e2@x <- callGeneric(e1, e2@x) if(length(e2@factors)) e2@factors <- list() e2 # remains "dpp" } else callGeneric(e1, as(e2, "dspMatrix")) }) setMethod("Arith", c(e1 = "dpoMatrix", e2 = cl), function(e1, e2) { if(!(l2 <- length(e2))) double(0L) else if(l2 == 1 && any(.Generic == c("*","/","+")) && (e2 > 0)) { e1@x <- callGeneric(e1@x, e2) if(length(e1@factors)) e1@factors <- list() e1 # remains "dpo" } else callGeneric(as(e1, "dsyMatrix"), e2) }) setMethod("Arith", c(e1 = "dppMatrix", e2 = cl), function(e1, e2) { if(!(l2 <- length(e2))) double(0L) else if(l2 == 1 && any(.Generic == c("*","/","+")) && (e2 > 0)) { e1@x <- callGeneric(e1@x, e2) if(length(e1@factors)) e1@factors <- list() e1 # remains "dpp" } else callGeneric(as(e1, "dspMatrix"), e2) }) setMethod("Ops", c(e1 = cl, e2 = "dpoMatrix"), function(e1, e2) callGeneric(e1, as(e2, "dsyMatrix"))) setMethod("Ops", c(e1 = cl, e2 = "dppMatrix"), function(e1, e2) callGeneric(e1, as(e2, "dspMatrix"))) setMethod("Ops", c(e1 = "dpoMatrix", e2 = cl), function(e1, e2) callGeneric(as(e1, "dsyMatrix"), e2)) setMethod("Ops", c(e1 = "dppMatrix", e2 = cl), function(e1, e2) callGeneric(as(e1, "dspMatrix"), e2)) }# for(cl...) ### -- I -- dense ----------------------------------------------------------- ##-------- originally from ./dgeMatrix.R -------------------- ## ----- only work with NAMESPACE importFrom(methods, ..) setMethod("Arith", c(e1 = "dgeMatrix", e2 = "dgeMatrix"), ## "+", "-", "*", "^", "%%", "%/%", "/" function(e1, e2) { ## NB: triangular, symmetric, etc may need own method d1 <- e1@Dim d2 <- e2@Dim eqD <- d1 == d2 if(!eqD[1]) stop("Matrices must have same number of rows for arithmetic") same.dim <- eqD[2] x1 <- e1@x x2 <- e2@x if(same.dim) { d <- d1 dn <- .Ops.checkDimNames(dimnames(e1), dimnames(e2)) } else { # nrows differ ----> maybe recycling if(d2[2] %% d1[2] == 0) { # nrow(e2) is a multiple x1 <- rep.int(x1, d2[2] %/% d1[2]) d <- d2 dn <- e2@Dimnames } else if(d1[2] %% d2[2] == 0) { # nrow(e1) is a multiple x2 <- rep.int(x2, d1[2] %/% d2[2]) d <- d1 dn <- e1@Dimnames } else stop(gettextf("number of rows are not compatible for %s", .Generic), domain = NA) } new("dgeMatrix", Dim = d, Dimnames = dn, x = callGeneric(x1, x2)) }) A.M.n <- function(e1, e2) { d <- e1@Dim le <- length(e2) if(le == 0) { if(prod(d) == 0) new(class2(class(e1), "d"), Dim = d, Dimnames = e1@Dimnames) else as.numeric(e2) } else if(le == 1 || le == d[1] || any(prod(d) == c(le, 0L))) { ## matching dim e1@x <- callGeneric(e1@x, as.vector(e2)) if(length(e1@factors)) e1@factors <- list() e1 } else stop("length of 2nd arg does not match dimension of first") } setMethod("Arith", c(e1 = "dgeMatrix", e2 = "numeric"), A.M.n) setMethod("Arith", c(e1 = "dgeMatrix", e2 = "logical"), A.M.n) setMethod("Arith", c(e1 = "dgeMatrix", e2 = "sparseVector"), A.M.n) A.n.M <- function(e1, e2) { d <- e2@Dim le <- length(e1) if(le == 0) { if(prod(d) == 0) new(class2(class(e2), "d"), Dim = d, Dimnames = e2@Dimnames) else as.numeric(e1) } else if(le == 1 || le == d[1] || any(prod(d) == c(le, 0L))) { ## matching dim e2@x <- callGeneric(as.vector(e1), e2@x) if(length(e2@factors)) e2@factors <- list() e2 } else stop("length of 1st arg does not match dimension of 2nd") } setMethod("Arith", c(e1 = "numeric", e2 = "dgeMatrix"), A.n.M) setMethod("Arith", c(e1 = "logical", e2 = "dgeMatrix"), A.n.M) setMethod("Arith", c(e1 = "sparseVector", e2 = "dgeMatrix"), A.n.M) ## rm(A.M.n, A.n.M) ##-------- originally from ./ddenseMatrix.R -------------------- ## Cheap version: work via "dgeMatrix" and use the group methods there: if(FALSE)## preserve "symmetric", "triangular", --> rather use Ops.x.x setMethod("Arith", c(e1 = "ddenseMatrix", e2 = "ddenseMatrix"), function(e1, e2) callGeneric(as(e1, "generalMatrix"), as(e2, "generalMatrix"))) .Arith.denseM.atom <- function(e1, e2) { ## since e1 = "dgeMatrix" has its own method, we have ## either symmetric or triangular ! n1 <- prod(d <- e1@Dim) le <- length(e2 <- as.vector(e2)) if(n1 && n1 < le) stop(sprintf("dim [product %d] do not match the length of object [%d]", n1, le)) if(le == 0) { if(prod(d) == 0) new(class2(class(e1), "d"), Dim = d, Dimnames = e1@Dimnames) else as.numeric(e2) } else if(le == 1 || le == d[1] || any(prod(d) == c(le, 0L))) { ## matching dim if(is(e1, "triangularMatrix")) { r0 <- callGeneric(0, e2) if(all0(r0)) { # result remains triangular if(e1@diag == "U" && !all(1 == callGeneric(1,e2))) e1 <- diagU2N(e1) e1@x <- callGeneric(e1@x, e2) e1 } else { ## result *general* callGeneric(.M2gen(e1), e2) } } else { ## symmetric if(le == 1) { ## result remains symmetric e1@x <- callGeneric(e1@x, e2) if(length(e1@factors)) e1@factors <- list() e1 } else { ## (le == d[1] || prod(d) == le) ## *might* remain symmetric, but 'x' may contain garbage ## *testing* for symmetry is also a bit expensive ==> simple: callGeneric(.M2gen(e1), e2) } } } else stop("length of 2nd arg does not match dimension of first") } setMethod("Arith", c(e1 = "ddenseMatrix", e2 = "numeric"), .Arith.denseM.atom) setMethod("Arith", c(e1 = "ddenseMatrix", e2 = "logical"), .Arith.denseM.atom) setMethod("Arith", c(e1 = "ddenseMatrix", e2 = "sparseVector"), .Arith.denseM.atom) rm(.Arith.denseM.atom) .Arith.atom.denseM <- function(e1, e2) { d <- e2@Dim ## note that e2 is either symmetric or triangular here le <- length(e1 <- as.vector(e1)) if(le == 0) { if(prod(d) == 0) new(class2(class(e2), "d"), Dim = d, Dimnames = e2@Dimnames) else as.numeric(e1) } else if(le == 1 || le == d[1] || any(prod(d) == c(le, 0L))) { ## matching dim if(is(e2, "triangularMatrix")) { r0 <- callGeneric(e1, 0) if(all0(r0)) { # result remains triangular if(e2@diag == "U" && !all(1 == callGeneric(e1,1))) e2 <- diagU2N(e2) e2@x <- callGeneric(e1, e2@x) e2 } else { # result *general* callGeneric(e1, .M2gen(e2)) } } else { ## symmetric if(le == 1) { # result remains symmetric e2@x <- callGeneric(e1, e2@x) if(length(e2@factors)) e2@factors <- list() e2 } else { ## (le == d[1] || prod(d) == le) ## *might* remain symmetric, but 'x' may contain garbage ## *testing* for symmetry is also a bit expensive ==> simple: callGeneric(e1, .M2gen(e2)) } } } else stop("length of 1st arg does not match dimension of 2nd") } setMethod("Arith", c(e1 = "numeric", e2 = "ddenseMatrix"), .Arith.atom.denseM) setMethod("Arith", c(e1 = "logical", e2 = "ddenseMatrix"), .Arith.atom.denseM) setMethod("Arith", c(e1 = "sparseVector", e2 = "ddenseMatrix"), .Arith.atom.denseM) rm(.Arith.atom.denseM) ## "Logic" ## ------- ##-------- originally from ./ldenseMatrix.R -------------------- ## These all had "Logic", now also for "Compare", ## but "Arith" differs: result will be "dgeMatrix' : .Ops2dge.via.x <- function(e1,e2) { .Ops.checkDim(dim(e1), dim(e2)) r <- copyClass(e1, "dgeMatrix", sNames = c("Dim","Dimnames")) r@x <- as.numeric(callGeneric(e1@x, e2@x)) r } setMethod("Compare", c(e1="lgeMatrix", e2="lgeMatrix"), .Ops.via.x) setMethod("Logic", c(e1="lgeMatrix", e2="lgeMatrix"), .Ops.via.x) setMethod("Arith", c(e1="lgeMatrix", e2="lgeMatrix"), .Ops2dge.via.x) setMethod("Compare", c(e1="ngeMatrix", e2="ngeMatrix"), .Ops.via.x) setMethod("Logic", c(e1="ngeMatrix", e2="ngeMatrix"), .Ops.via.x) setMethod("Arith", c(e1="ngeMatrix", e2="ngeMatrix"), .Ops2dge.via.x) rm(.Ops.via.x, .Ops2dge.via.x) ## nMatrix -> lMatrix conversions when "the other" is not nMatrix ## Use Ops.x.x unless both are sparse setMethod("Ops", c(e1="dMatrix", e2="dMatrix"), Ops.x.x) setMethod("Ops", c(e1="lMatrix", e2="lMatrix"), Ops.x.x) setMethod("Ops", c(e1="nMatrix", e2="nMatrix"), Ops.x.x) setMethod("Ops", c(e1="nMatrix", e2="lMatrix"), Ops.x.x) setMethod("Ops", c(e1="lMatrix", e2="nMatrix"), Ops.x.x) setMethod("Ops", c(e1="nMatrix", e2="dMatrix"), Ops.x.x) setMethod("Ops", c(e1="dMatrix", e2="nMatrix"), Ops.x.x) rm(Ops.x.x) ## ... both are sparse: cannot use Ops.x.x setMethod("Ops", c(e1="nsparseMatrix", e2="lsparseMatrix"), function(e1,e2) callGeneric(.M2kind(e1, "l"), e2)) setMethod("Ops", c(e1="lsparseMatrix", e2="nsparseMatrix"), function(e1,e2) callGeneric(e1, .M2kind(e2, "l"))) setMethod("Ops", c(e1="nsparseMatrix", e2="dsparseMatrix"), function(e1,e2) callGeneric(.M2kind(e1, "l"), e2)) setMethod("Ops", c(e1="dsparseMatrix", e2="nsparseMatrix"), function(e1,e2) callGeneric(e1, .M2kind(e2, "l"))) ## For "Arith" go to "d*", not "l*": {the above, replaced "l by "d : setMethod("Arith", c(e1="nsparseMatrix", e2="lsparseMatrix"), function(e1,e2) callGeneric(.M2kind(e1, "d"), e2)) setMethod("Arith", c(e1="lsparseMatrix", e2="nsparseMatrix"), function(e1,e2) callGeneric(e1, .M2kind(e2, "d"))) setMethod("Arith", c(e1="nsparseMatrix", e2="dsparseMatrix"), function(e1,e2) callGeneric(.M2kind(e1, "d"), e2)) setMethod("Arith", c(e1="dsparseMatrix", e2="nsparseMatrix"), function(e1,e2) callGeneric(e1, .M2kind(e2, "d"))) if(FALSE) { ##-- not yet --------- ## New: for both "nsparseMatrix", *preserve* nsparse* -- via Tsp -- "nTsparseMatrix" setMethod("Ops", c(e1 = "nsparseMatrix", e2 = "nsparseMatrix"), function(e1, e2) callGeneric(as(e1, "TsparseMatrix"), as(e2, "TsparseMatrix"))) Ops.nT.nT <- function(e1,e2) { d <- .Ops.checkDim(dim(e1), dim(e2)) ## e1, e2 are nTsparse, i.e., inheriting from "ngTMatrix", "ntTMatrix", "nsTMatrix" gen1 <- extends(cD1 <- getClassDef(class(e1)), "generalMatrix") gen2 <- extends(cD2 <- getClassDef(class(e2)), "generalMatrix") sym1 <- !gen1 && extends(cD1, "symmetricMatrix") sym2 <- !gen2 && extends(cD2, "symmetricMatrix") tri1 <- !gen1 && !sym1 tri2 <- !gen2 && !sym2 G <- gen1 && gen2 S <- sym1 && sym2 && e1@uplo == e2@uplo T <- tri1 && tri2 && e1@uplo == e2@uplo } setMethod("Ops", c(e1="nTsparseMatrix", e2="nTsparseMatrix"), Ops.nT.nT) }##--- not yet ------------- ## Have this for "Ops" already above ## setMethod("Logic", c(e1 = "logical", e2 = "Matrix"), ## function(e1, e2) callGeneric(e1, as(e2, "lMatrix"))) ## setMethod("Logic", c(e1 = "Matrix", e2 = "logical"), ## function(e1, e2) callGeneric(as(e1, "lMatrix"), e2)) .ll <- function(e1, e2) callGeneric(as(e1,"lMatrix"), as(e2, "lMatrix")) setMethod("Logic", c(e1 = "nMatrix", e2 = "Matrix"), .ll) setMethod("Logic", c(e1 = "Matrix", e2 = "nMatrix"), .ll) setMethod("Logic", c(e1 = "nMatrix", e2 = "nMatrix"), .ll) rm(.ll) ### "ANY" here means "any non-Matrix" (since "Ops"(ANY) has already bailout above): setMethod("Logic", c(e1 = "ANY", e2 = "Matrix"), function(e1, e2) callGeneric(as.logical(e1), as(e2, "lMatrix"))) setMethod("Logic", c(e1 = "Matrix", e2 = "ANY"), function(e1, e2) callGeneric(as(e1, "lMatrix"), as.logical(e2))) ## "swap RHS and LHS" and use the method below -- can do this, since ## "Logic" := { "&" , "|" } and both are commutative for(Mcl in c("lMatrix","nMatrix","dMatrix")) for(cl in c("logical", "numeric", "sparseVector")) setMethod("Logic", c(e1 = cl, e2 = Mcl), function(e1,e2) callGeneric(e2, e1)) ## conceivably "numeric" could use callGeneric(e2, as.logical(e1)) ## but that's not useful at the moment, since Logic.Mat.atomic() does as.logical() ## This is parallel to Cmp.Mat.atomic() above ---> __keep parallel__ ! Logic.Mat.atomic <- function(e1, e2) { ## result will typically be "like" e1: l2 <- length(e2 <- as.logical(e2)) n1 <- prod(d <- e1@Dim) if(n1 && n1 < l2) stop(sprintf("dim [product %d] do not match the length of object [%d]", n1, l2)) if(.Generic == "&" && l2 && allTrue (e2)) return(as(e1, "lMatrix")) if(.Generic == "|" && l2 && allFalse(e2)) return(as(e1, "lMatrix")) cl <- class(e1) if(l2 == 0) return(if(n1 == 0) as(e1, "lMatrix") else as.logical(e2)) ## else cl1 <- getClassDef(cl) slots1 <- names(cl1@slots) has.x <- any("x" == slots1)# *fast* check for "x" slot presence if(l2 > 1 && has.x) return(if(n1 == 0) { sNms <- .slotNames(e1) r <- copyClass(e1, class2(cl, "l"), sNames = sNms[sNms != "x"], check = FALSE) r@x <- callGeneric(e1@x, e2) r } else # cannot simply compare e2, e1@x -> use another method callGeneric(e1, Matrix(e2, nrow=d[1], ncol=d[2])) ) ## else Udg <- extends(cl1, "triangularMatrix") && e1@diag == "U" r0 <- callGeneric(0, e2) r <- callGeneric(if(has.x) e1@x else TRUE, e2) ## Udg: append the diagonal at *end*, as diagU2N(): r. <- if(Udg) c(r, callGeneric(..diag.x(e1), e2)) else r ## trivial case first (beware of NA) if(isTRUE(all(r0) && all(r.))) { r <- new(if(d[1] == d[2]) "lsyMatrix" else "lgeMatrix") r@Dim <- d r@Dimnames <- e1@Dimnames r@x <- rep.int(TRUE, n1) } else if(extends(cl1, "denseMatrix")) { full <- !.isPacked(e1) # << both "dtr" and "dsy" are 'full' if(full || allFalse(r0) || extends(cl1, "symmetricMatrix")) { isTri <- extends(cl1, "triangularMatrix") ## FIXME? using copyClass() to copy "relevant" slots r <- new(class2(cl, "l"), x = r, Dim = d, Dimnames = e1@Dimnames) if(extends(cl1, "symmetricMatrix")) { r@uplo <- e1@uplo } else if(isTri) { r@uplo <- e1@uplo r@diag <- e1@diag } } else { ## packed matrix with structural 0 and r0 is not all FALSE: ##--> result cannot be packed anymore ## [dense & packed & not symmetric ] ==> must be "ltp*" : if(!extends(cl1, "ltpMatrix")) stop("internal bug in \"Logic\" method (Logic.Mat.atomic); please report") rx <- rep_len(r0, n1) rx[indTri(d[1], upper = (e1@uplo == "U"), diag=TRUE)] <- r. r <- new("lgeMatrix", x = rx, Dim = d, Dimnames = e1@Dimnames) } } else { ##---- e1 is(. , sparseMatrix) ----------------- ## FIXME: remove this test eventually if(extends(cl1, "diagonalMatrix")) stop("Logic.Mat.atomic() should not be called for diagonalMatrix") remainSparse <- allFalse(r0) ## <==> things remain sparse if(Udg) { # e1 *is* unit-diagonal (triangular sparse) r1 <- callGeneric(1, e2) Udg <- all(r1) # maybe Unit-diagonal (sparse) result ## if(!remainSparse) we'll use non0ind() which *has* unit-diag. indices at end ## if(Udg && remainSparse) { } else { ## result will not be unit-diagonal sparse e1 <- .diagU2N(e1, cl = cl1) # otherwise, result is U-diag ## FIXME? rather ## if(extends1of(cl1, c("CsparseMatrix", "RsparseMatrix","TsparseMatrix")) { if(extends(cl1, "CsparseMatrix")) { ## repeat computation if e1 has changed r. <- callGeneric(if(has.x) e1@x else TRUE, e2) } } } if(remainSparse) { if(!anyNA(r) && ((Ar <- all(r)) || !any(r))) { lClass <- class2(cl, "l") # is "lsparse*" r <- new(lClass) r@Dim <- d r@Dimnames <- e1@Dimnames if(Ar) { # 'TRUE' instead of 'x': same sparsity: for(n in intersect(c("i","j","p","uplo","diag"), slots1)) slot(r, n) <- slot(e1, n) n <- if(has.x) length(e1@x) else if(any("p" == slots1)) e1@p[d[2]+1L] else length(e1@i) r@x <- rep.int(TRUE, n) } else { ## !any(r): all FALSE: keep empty 'r' matrix ## but may need a valid 'pointer' slot: if(extends(lClass, "CsparseMatrix")) r@p <- rep.int(0L, 1+ncol(r)) else if(extends(lClass, "RsparseMatrix")) r@p <- rep.int(0L, 1+nrow(r)) } } else { # some TRUE, FALSE, NA : go via unique 'Tsparse' M <- asUniqueT(e1) nCl <- class2(class(M), 'l') # logical Tsparse sN <- slotNames(nCl) ## copy "the other slots" (important for "tr"/"sym"): r <- copyClass(M, nCl, sNames = sN[is.na(match(sN, c("x","factors")))]) r@x <- callGeneric(if(has.x) M@x else TRUE, e2) if(extends(cl1, "CsparseMatrix")) r <- .M2C(r) else if(extends(cl1, "RsparseMatrix")) r <- .M2R(r) } } else { ## non sparse result lClass <- if(extends(cl1, "symmetricMatrix")) "lsyMatrix" else "lgeMatrix" Matrix.message(sprintf("sparse to dense (%s) coercion in '%s' -> %s", lClass, .Generic, "Logic.Mat.atomic"), .M.level = 2) rx <- rep_len(r0, n1) ## Here, we assume that 'r.' and the indices align (!) encI <- .Call(m_encodeInd, non0ind(e1, cl1, uniqT=FALSE, xtendSymm=FALSE), di = d, orig1=FALSE, checkBounds=FALSE) rx[1L + encI] <- r. r <- new(lClass, x = rx, Dim = d, Dimnames = e1@Dimnames) } } r } for(Mcl in c("lMatrix","nMatrix","dMatrix")) for(cl in c("logical", "numeric", "sparseVector")) setMethod("Logic", c(e1 = Mcl, e2 = cl), Logic.Mat.atomic) rm(Logic.Mat.atomic, Mcl, cl) ### -- II -- sparse ---------------------------------------------------------- Ops.x.x.via.d <- function(e1, e2) callGeneric(.M2kind(e1, "d"), .M2kind(e2, "d")) ## Have lgC o lgC and then lgT o lgT Logic - quite similarly - ## also lsC o * and ltC o * : ## Here's the common functionality .do.Logic.lsparse <- function(e1,e2, d, dn, isOR, ij1, ij2) { ## NB non-diagonalMatrix := Union{ general, symmetric, triangular} gen1 <- extends(cD1 <- getClassDef(class(e1)), "generalMatrix") gen2 <- extends(cD2 <- getClassDef(class(e2)), "generalMatrix") sym1 <- !gen1 && extends(cD1, "symmetricMatrix") sym2 <- !gen2 && extends(cD2, "symmetricMatrix") tri1 <- !gen1 && !sym1 tri2 <- !gen2 && !sym2 G <- gen1 && gen2 S <- sym1 && sym2 && e1@uplo == e2@uplo T <- tri1 && tri2 && e1@uplo == e2@uplo if(T && e1@diag != e2@diag) { ## one is "U" the other "N" if(e1@diag == "U") e1 <- diagU2N(e1) else ## (e2@diag == "U" e2 <- diagU2N(e2) shape <- "t" } else if(!G && !S && !T) { ## e.g. one symmetric, one general ## coerce to generalMatrix and go : if(!gen1) e1 <- .M2gen(e1) if(!gen2) e2 <- .M2gen(e2) shape <- "g" } else { shape <- if(T) "t" else if(S) "s" else "g" } ii <- WhichintersectInd(ij1, ij2, di=d) I1 <- ii[[1]] ; has1 <- length(I1) > 0 I2 <- ii[[2]] ; has2 <- length(I2) > 0 ## 1) common indices i <- ij1[I1, 1] j <- ij1[I1, 2] if(isOR) { ## i.e. .Generic == "|" i.e. not "&" x <- e1@x[I1] | e2@x[I2] ## 2) "e1 o FALSE": x2 <- if(has1) e1@x[- I1] else e1@x # == callGeneric(e1@x[- I1], FALSE) ## 3) "0 o e1": x3 <- if(has2) e2@x[- I2] else e2@x # == callGeneric(FALSE, e2@x[- I2]) i <- c(i, if(has1) ij1[-I1, 1] else ij1[, 1], if(has2) ij2[-I2, 1] else ij2[, 1]) j <- c(j, if(has1) ij1[-I1, 2] else ij1[, 2], if(has2) ij2[-I2, 2] else ij2[, 2]) x <- c(x, x2, x3) } else { ## AND x <- e1@x[I1] & e2@x[I2] } if(any(!(x. <- x | is.na(x)))) { ## drop 'FALSE's i <- i[x.] j <- j[x.] x <- x[x.] } if(shape == "g") new("lgTMatrix", Dim = d, Dimnames = dn, i = i, j = j, x = x) else new(paste0("l",shape,"TMatrix"), Dim = d, Dimnames = dn, i = i, j = j, x = x, uplo = e1@uplo) } Logic.lCMat <- function(e1, e2, isOR) { stopifnot(is.logical(isOR)) d <- .Ops.checkDim(dim(e1), dim(e2)) dn <- .Ops.checkDimNames(dimnames(e1), dimnames(e2)) ## Very easy case first : if(identical(e1@i, e2@i) && identical(e1@p, e2@p)) { e1@x <- if(isOR) e1@x | e2@x else e1@x & e2@x if(.hasSlot(e1, "factors") && length(e1@factors)) e1@factors <- list() return(e1) } ## else : .M2C(.do.Logic.lsparse(e1, e2, d = d, dn = dn, isOR = isOR, ij1 = .Call(compressed_non_0_ij, e1, TRUE), ij2 = .Call(compressed_non_0_ij, e2, TRUE))) } m.Logic.lCMat <- function(e1, e2) Logic.lCMat(e1, e2, isOR = .Generic == "|") Logic.lTMat <- function(e1,e2) { d <- .Ops.checkDim(dim(e1), dim(e2)) dn <- .Ops.checkDimNames(dimnames(e1), dimnames(e2)) ## Very easy case first : if(identical(e1@i, e2@i) && identical(e1@j, e2@j)) { e1@x <- callGeneric(e1@x, e2@x) if(.hasSlot(e1, "factors") && length(e1@factors)) e1@factors <- list() return(e1) } ## else : cld <- getClassDef(class(e1)) .do.Logic.lsparse(e1, e2, d = d, dn = dn, isOR = .Generic == "|", ij1 = non0ind(e1, cld), ij2 = non0ind(e2, cld)) } setMethod("Logic", c(e1="lgCMatrix", e2="lgCMatrix"), m.Logic.lCMat) setMethod("Logic", c(e1="lgTMatrix", e2="lgTMatrix"), Logic.lTMat) rm(m.Logic.lCMat, Logic.lTMat) setMethod("Logic", c(e1 = "lsCMatrix", e2 = "lsCMatrix"), function(e1, e2) { if(e1@uplo == e2@uplo) Logic.lCMat(e1, e2, isOR = .Generic == "|") else Logic.lCMat(e1, t(e2), isOR = .Generic == "|") }) setMethod("Logic", c(e1 = "ltCMatrix", e2 = "ltCMatrix"), function(e1, e2) { isOR <- .Generic == "|" if(e1@uplo == e2@uplo) { if(e1@diag == e2@diag) ## both "N" or both "U" (!) Logic.lCMat(e1, e2, isOR=isOR) else if(e1@diag == "U") Logic.lCMat(diagU2N(e1), e2, isOR=isOR) else ## e1@diag == "N" *and* e2@diag == "U" Logic.lCMat(e1, diagU2N(e2), isOR=isOR) } else { ## differing triangle (upper *and* lower): if(isOR) # both triangles => "general" Logic.lCMat(.M2gen(e1), .M2gen(e2), isOR=TRUE) else { ## have '&': all FALSE apart from diagonal d <- .Ops.checkDim(dim(e1), dim(e2)) .diag2sparse(new("ldiMatrix", Dim = d, x = get(.Generic)(diag(e1), diag(e2))), kind = ".", shape = "t", repr = "C", uplo = e1@uplo) } } }) ## Now the other "Ops" for the "lgT" and "lgC" cases: setMethod("Arith", c(e1="lgCMatrix", e2="lgCMatrix"), Ops.x.x.via.d) setMethod("Arith", c(e1="lgTMatrix", e2="lgTMatrix"), Ops.x.x.via.d) rm(Ops.x.x.via.d) ## More generally: Arith: l* and n* via d* setMethod("Arith", c(e1="lsparseMatrix", e2="Matrix"), function(e1, e2) callGeneric(.M2kind(e1, "d"), as(e2,"dMatrix"))) setMethod("Arith", c(e1="Matrix", e2="lsparseMatrix"), function(e1, e2) callGeneric(as(e1,"dMatrix"), .M2kind(e2, "d"))) setMethod("Arith", c(e1="nsparseMatrix", e2="Matrix"), function(e1, e2) callGeneric(.M2kind(e1, "d"), as(e2,"dMatrix"))) setMethod("Arith", c(e1="Matrix", e2="nsparseMatrix"), function(e1, e2) callGeneric(as(e1,"dMatrix"), .M2kind(e2, "d"))) ## for(cl in c("numeric", "logical")) # "complex", "raw" : basically "replValue" for(Mcl in c("lMatrix", "nMatrix")) { setMethod("Arith", c(e1=Mcl, e2=cl), function(e1, e2) callGeneric(as(e1, "dMatrix"), e2)) setMethod("Arith", c(e1=cl, e2=Mcl), function(e1, e2) callGeneric(e1, as(e2,"dMatrix"))) } rm(cl, Mcl) ## FIXME: These are really too cheap: currently almost all go via dgC*() : ## setMethod("Compare", c(e1="lgCMatrix", e2="lgCMatrix"), ## setMethod("Compare", c(e1="lgTMatrix", e2="lgTMatrix"), ## setMethod("Compare", c(e1="lsparseMatrix", e2="lsparseMatrix"), ## function(e1, e2) callGeneric(as(e1, "dgCMatrix"), ## as(e2, "dgCMatrix"))) ##. Have "Ops" below which only goes *conditionally* via Csparse ##.setMethod("Compare", c(e1="lsparseMatrix", e2="lsparseMatrix"), ##. function(e1, e2) callGeneric(as(e1, "CsparseMatrix"), ##. as(e2, "CsparseMatrix"))) ## setMethod("Compare", c(e1="lgTMatrix", e2="lgTMatrix"), ## function(e1, e2) callGeneric(as(e1, "dgCMatrix"), ## as(e2, "dgCMatrix"))) ###--- Sparse ... ---------- setMethod("Ops", c(e1="lsparseMatrix", e2="lsparseMatrix"), function(e1,e2) callGeneric(as(e1, "CsparseMatrix"), as(e2, "CsparseMatrix"))) setMethod("Logic", c(e1="lsparseMatrix", e2="ldenseMatrix"), function(e1,e2) callGeneric(as(e1, "generalMatrix"), as(e2, "sparseMatrix"))) setMethod("Logic", c(e1="ldenseMatrix", e2="lsparseMatrix"), function(e1,e2) callGeneric(as(e1, "sparseMatrix"), as(e2, "generalMatrix"))) setMethod("Logic", c(e1="lsparseMatrix", e2="lsparseMatrix"), function(e1,e2) { if(!is(e1,"generalMatrix")) callGeneric(as(.M2gen(e1), "CsparseMatrix"), e2) else if(!is(e2,"generalMatrix")) callGeneric(e1, as(.M2gen(e2), "CsparseMatrix")) else # both are general, i.e. lg[CRT] callGeneric(as(e1, "CsparseMatrix"), as(e2, "CsparseMatrix")) }) ## FIXME: also want (symmetric o symmetric) , (triangular o triangular) ## ----- setMethod("Arith", c(e1 = "dsCMatrix", e2 = "dsCMatrix"), function(e1, e2) { Matrix.message("suboptimal 'Arith' implementation of 'dsC* o dsC*'") forceSymmetric(callGeneric(.M2gen(e1), .M2gen(e2))) }) ##-------- originally from ./dgCMatrix.R -------------------- .Arith.Csparse <- function(e1, e2, Generic, class., triangular = FALSE, check.dimnames = TRUE) { ## Generic is one of "+", "-", "*", "^", "%%", "%/%", "/" ## triangular: TRUE iff e1,e2 are triangular _and_ e1@uplo == e2@uplo d <- .Ops.checkDim(dim(e1), dim(e2)) dn <- .Ops.checkDimNames(dimnames(e1), dimnames(e2), check = check.dimnames) if(triangular) { ## need these for the 'x' slots in any case e1 <- .Call(R_sparse_diag_U2N, e1) e2 <- .Call(R_sparse_diag_U2N, e2) ## slightly more efficient than non0.i() or non0ind(): ij1 <- .Call(compressed_non_0_ij, e1, isC=TRUE) ij2 <- .Call(compressed_non_0_ij, e2, isC=TRUE) newTMat <- function(i,j,x) new("dtTMatrix", Dim = d, Dimnames = dn, i = i, j = j, x = x, uplo = e1@uplo) } else { cld <- getClassDef(class.) ij1 <- non0ind(e1, cld) ij2 <- non0ind(e2, cld) newTMat <- function(i,j,x) new("dgTMatrix", Dim = d, Dimnames = dn, i = i, j = j, x = x) } switch(Generic, "+" = , "-" = { ## care for over-allocated 'x' slot: nc1 <- d[2] + 1L if((nz <- e1@p[nc1]) < length(e1@x)) e1@x <- e1@x[seq_len(nz)] if((nz <- e2@p[nc1]) < length(e2@x)) e2@x <- e2@x[seq_len(nz)] ## special "T" convention: repeated entries are *summed* .M2C(newTMat(i = c(ij1[,1], ij2[,1]), j = c(ij1[,2], ij2[,2]), x = if(Generic == "+") c(e1@x, e2@x) else c(e1@x, - e2@x))) }, "*" = { ## X * 0 == 0 * X == 0 --> keep common non-0 ii <- WhichintersectInd(ij1, ij2, di=d) ij <- ij1[ii[[1]], , drop = FALSE] .M2C(newTMat(i = ij[,1], j = ij[,2], x = e1@x[ii[[1]]] * e2@x[ii[[2]]])) }, "^" = { ii <- WhichintersectInd(ij1, ij2, di=d) ## 3 cases: ## 1) X^0 := 1 (even for X=0) ==> dense ## 2) 0^Y := 0 for Y != 0 ===== ## 3) x^y : ## FIXME: dgeM[cbind(i,j)] <- V is not yet possible ## nor dgeM[ i_vect ] <- V ## r <- as(e2, "dgeMatrix") ## ... r <- as(e2, "matrix") Yis0 <- is0(r) r[complementInd(ij1, dim=d)] <- 0 ## 2) r[1L + ij2[ii[[2]], , drop=FALSE]] <- e1@x[ii[[1]]] ^ e2@x[ii[[2]]] ## 3) r[Yis0] <- 1 ## 1) if(triangular) .m2dense(r, "dtr", e1@uplo, "N") else .m2dense(r, "dge", NULL, NULL) }, "%%" = , "%/%" = , "/" = ## 0 op 0 |-> NaN => dense { get(Generic)(as(e1, "unpackedMatrix"), e2) }) # end{switch(..)} } setMethod("Arith", c(e1 = "dgCMatrix", e2 = "dgCMatrix"), function(e1,e2) .Arith.Csparse(e1,e2, .Generic, class.= "dgCMatrix")) setMethod("Arith", c(e1 = "dtCMatrix", e2 = "dtCMatrix"), function(e1, e2) { U1 <- e1@uplo ## will the result definitely be triangular? isTri <- U1 == e2@uplo && .Generic != "^" if(isTri) .Arith.Csparse(e1,e2, .Generic, class. = "dtCMatrix", triangular = TRUE) else # lowerTri o upperTri: |--> "all 0" {often} -- FIXME? .Arith.Csparse(.M2gen(e1), .M2gen(e2), .Generic, class.= "dgCMatrix") }) ## TODO : Consider going a level up, and do this for all "Ops" ## ## NB: For "dgCMatrix" have special method ==> this is for dsC*, lgC*, ... ## now also for Tsparse etc {*must* as method directly: "callGeneric()"} .Arith.CM.atom <- function(e1, e2) { if(length(e2) == 1) { ## e.g., Mat ^ a f0 <- callGeneric(0, e2) if(is0(f0)) { ## remain sparse, symm., tri.,... e1 <- .M2kind(e1, "d") if(!extends(cld <- getClassDef(class(e1)), "CsparseMatrix")) cld <- getClassDef(class(e1 <- as(e1, "CsparseMatrix"))) if(extends(cld, "triangularMatrix") && e1@diag == "U" && !all(1 == callGeneric(1, e2))) e1 <- .diagU2N(e1, cld) e1@x <- callGeneric(e1@x, e2) if(.hasSlot(e1, "factors") && length(e1@factors)) e1@factors <- list() return(e1) } } ## all other (potentially non-sparse) cases: give up symm, tri,.. callGeneric(as(.M2gen(.M2kind(e1, "d")), "CsparseMatrix"), e2) } ## The same, e1 <-> e2 : .Arith.atom.CM <- function(e1, e2) { if(length(e1) == 1) { f0 <- callGeneric(e1, 0) if(is0(f0)) { e2 <- .M2kind(e2, "d") if(!extends(cld <- getClassDef(class(e2)), "CsparseMatrix")) cld <- getClassDef(class(e2 <- as(e2, "CsparseMatrix"))) if(extends(cld, "triangularMatrix") && e2@diag == "U" && !all(1 == callGeneric(e1, 1))) e2 <- .diagU2N(e2, cld) e2@x <- callGeneric(e1, e2@x) if(.hasSlot(e2, "factors") && length(e2@factors)) e2@factors <- list() return(e2) } } callGeneric(e1, as(.M2gen(.M2kind(e2, "d")), "CsparseMatrix")) } setMethod("Arith", c(e1 = "CsparseMatrix", e2 = "numeric"), .Arith.CM.atom) setMethod("Arith", c(e1 = "numeric", e2 = "CsparseMatrix"), .Arith.atom.CM) ##' compute indices for recycling of length 'len' ##' to match sparseMatrix 'spM' .Ops.recycle.ind <- function(spM, len) { n <- prod(d <- dim(spM)) if(n && n < len) stop("vector too long in Matrix - vector operation") if(n %% len != 0) ## identical warning as in main/arithmetic.c warning("longer object length\n\tis not a multiple of shorter object length") ## TODO(speedup!): construction of [1L + in0 %%len] via one .Call() in0 <- .Call(m_encodeInd, .Call(compressed_non_0_ij, spM, TRUE), d, FALSE, FALSE) 1L + in0 %% len } A.M.n <- function(e1, e2) { if((l2 <- length(e2)) == 0) # return 0-vector of e1's kind, as matrix()+<0> return(if(length(e1)) vector(.type.kind[.M.kind(e1)]) else e1) is0f <- is0(f0 <- callGeneric(0, e2)) # if(all(is0f)) { ## result keeps sparseness structure of e1 if(l2 > 1) { # "recycle" e2 "carefully" e2 <- e2[.Ops.recycle.ind(e1, len = l2)] } e1@x <- callGeneric(e1@x, e2) if(length(e1@factors)) e1@factors <- list() e1 } else if(mean(is0f) > 7/8) { ## remain sparse ['7/8' is *somewhat* arbitrary] if(l2 > 1) ## as not all callGeneric(0, e2) is 0, e2 is typically sparse callGeneric(e1, as(e2, "sparseVector")) else { ## l2 == 1: e2 is "scalar" e1@x <- callGeneric(e1@x, e2) if(length(e1@factors)) e1@factors <- list() e1 } } else { ## non-sparse, since '0 o e2' is not (all) 0 r <- as(e1, "matrix") if(l2 == 1) { r[] <- f0 r[non0ind(e1, getClassDef("dgCMatrix")) + 1L] <- callGeneric(e1@x, e2) .m2dense(r, "dge", NULL, NULL) } else { .m2dense(callGeneric(r, e2), "dge", NULL, NULL) } } } setMethod("Arith", c(e1 = "dgCMatrix", e2 = "numeric"), A.M.n) setMethod("Arith", c(e1 = "dgCMatrix", e2 = "logical"), A.M.n) ## coercing to "general*" / "dgC*" would e.g. lose symmetry of 'S * 3' setMethod("Arith", c(e1 = "dsparseMatrix", e2 = "numeric"), .Arith.CM.atom) setMethod("Arith", c(e1 = "dsparseMatrix", e2 = "logical"), .Arith.CM.atom) A.n.M <- function(e1, e2) { if((l1 <- length(e1)) == 0) ## return 0-vector of e2's kind, as <0> + matrix() return(if(length(e2)) vector(.type.kind[.M.kind(e2)]) else e2) is0f <- is0(f0 <- callGeneric(e1, 0)) if(all(is0f)) { ## result keeps sparseness structure of e2 if(l1 > 1) { # "recycle" e1 "carefully" e1 <- e1[.Ops.recycle.ind(e2, len = l1)] } e2@x <- callGeneric(e1, e2@x) if(length(e2@factors)) e2@factors <- list() e2 } else if(mean(is0f) > 7/8) { ## remain sparse ['7/8' is *somewhat* arbitrar if(l1 > 1) ## as not all callGeneric(e1, 0) is 0, e1 is typically sparse callGeneric(as(e1, "sparseVector"), e2) else { ## l1 == 1: e1 is "scalar" e2@x <- callGeneric(e1, e2@x) if(length(e2@factors)) e2@factors <- list() e2 } } else { ## non-sparse, since '0 o e2' is not (all) 0 r <- as(e2, "matrix") if(l1 == 1) { r[] <- f0 r[non0ind(e2, getClassDef("dgCMatrix")) + 1L] <- callGeneric(e1, e2@x) .m2dense(r, "dge", NULL, NULL) } else { .m2dense(callGeneric(e1, r), "dge", NULL, NULL) } } } setMethod("Arith", c(e1 = "numeric", e2 = "dgCMatrix"), A.n.M) setMethod("Arith", c(e1 = "logical", e2 = "dgCMatrix"), A.n.M) ## coercing to "general*" / "dgC*" would e.g. lose symmetry of '3 * S' setMethod("Arith", c(e1 = "numeric", e2 = "dsparseMatrix"), .Arith.atom.CM) setMethod("Arith", c(e1 = "logical", e2 = "dsparseMatrix"), .Arith.atom.CM) rm(A.M.n, A.n.M, .Arith.atom.CM, .Arith.CM.atom) ##-------- originally from ./dgTMatrix.R -------------------- ## Uses the triplet convention of *adding* entries with same (i,j): setMethod("+", c(e1 = "dgTMatrix", e2 = "dgTMatrix"), function(e1, e2) { .Ops.checkDim(dim(e1), dim(e2)) new("dgTMatrix", i = c(e1@i, e2@i), j = c(e1@j, e2@j), x = c(e1@x, e2@x), Dim = e1@Dim, Dimnames = e1@Dimnames) }) ##-------- originally from ./Csparse.R -------------------- setMethod("Arith", c(e1 = "CsparseMatrix", e2 = "CsparseMatrix"), function(e1, e2) { ## go via "symmetric" if both are symmetric, etc... s1 <- .M.shape(e1) s2 <- .M.shape(e2) ## as(*, "d.CMatrix") is deprecated: ## viaCl <- paste0("d", if(s1 == s2) s1 else "g", "CMatrix") if(s1 != s2) ## go via "general" callGeneric(.M2gen(.M2kind(e1, "d")), .M2gen(.M2kind(e2, "d"))) else callGeneric(.M2kind(e1, "d"), .M2kind(e2, "d")) }) setMethod("Logic", c(e1 = "CsparseMatrix", e2 = "CsparseMatrix"), ## go via "symmetric" if both are symmetric, etc... function(e1, e2) { s1 <- .M.shape(e1) s2 <- .M.shape(e2) ## as(*, "d.CMatrix") is deprecated: ## viaCl <- paste0("l", if(s1 == s2) s1 else "g", "CMatrix") if(s1 != s2) ## go via "general" callGeneric(.M2gen(.M2kind(e1, "l")), .M2gen(.M2kind(e2, "l"))) else callGeneric(.M2kind(e1, "l"), .M2kind(e2, "l")) }) setMethod("Compare", c(e1 = "CsparseMatrix", e2 = "CsparseMatrix"), function(e1, e2) { d <- .Ops.checkDim(dim(e1), dim(e2)) ## How do the "0" or "FALSE" entries compare? ## Depends if we have an "EQuality RELation" or not: EQrel <- switch(.Generic, "==" =, "<=" =, ">=" = TRUE, "!=" =, "<" =, ">" = FALSE) if(EQrel) { ## The (0 op 0) or (FALSE op FALSE) comparison gives TRUE ## -> result becomes *dense*; the following may be suboptimal return(callGeneric(.sparse2dense(e1), .sparse2dense(e2))) } ## else: INequality: 0 op 0 gives FALSE ---> remain sparse! cD1 <- getClassDef(class(e1)) cD2 <- getClassDef(class(e2)) Matrix.message(sprintf("Compare -- \"%s\" %s \"%s\" :\n", cD1@className, .Generic, cD2@className), .M.level = 2) ## NB non-diagonalMatrix := Union{ general, symmetric, triangular} gen1 <- extends(cD1, "generalMatrix") gen2 <- extends(cD2, "generalMatrix") sym1 <- !gen1 && extends(cD1, "symmetricMatrix") sym2 <- !gen2 && extends(cD2, "symmetricMatrix") tri1 <- !gen1 && !sym1 tri2 <- !gen2 && !sym2 G <- gen1 && gen2 S <- sym1 && sym2 && e1@uplo == e2@uplo T <- tri1 && tri2 && e1@uplo == e2@uplo if(T && e1@diag != e2@diag) { ## one is "U" the other "N" if(e1@diag == "U") e1 <- diagU2N(e1) else ## (e2@diag == "U" e2 <- diagU2N(e2) shape <- "t" } else if(!G && !S && !T) { ## e.g. one symmetric, one general ## coerce to generalMatrix and go : if(!gen1) e1 <- .M2gen(e1) if(!gen2) e2 <- .M2gen(e2) shape <- "g" } else { shape <- if(T) "t" else if(S) "s" else "g" } dn <- .Ops.checkDimNames(dimnames(e1), dimnames(e2)) ## ^^ FIXME: for 'S'; allow staying ## the result object: newC <- sub("^.", "l", MatrixClass(class(e1))) ## FIXME: "n" result when e1 & e2 are "n", ## or even whenever possible r <- new(newC) e1is.n <- extends(cD1, "nMatrix") e2is.n <- extends(cD2, "nMatrix") ## Easy case: identical sparsity pattern if(identical(e1@i, e2@i) && identical(e1@p, e2@p)) { if(e1is.n) { if(e2is.n) ## non-equality of identical pattern matrices: ## all FALSE r@p <- rep.int(0L, d[2]+1L) # and r@i, r@x remain empty else { # e1 pattern, e2@x rx <- callGeneric(TRUE, e2@x) if(allFalse(rx)) r@p <- rep.int(0L, d[2]+1L) # r@i, r@x remain empty else { r@x <- rx r@i <- e2@i r@p <- e2@p } } } else if(e2is.n) { ## e1@x, e2 pattern rx <- callGeneric(e1@x, TRUE) if(allFalse(rx)) r@p <- rep.int(0L, d[2]+1L) # and r@i, r@x remain empty else { r@x <- rx r@i <- e1@i r@p <- e1@p } } else { # both have 'x' slot r@x <- callGeneric(e1@x, e2@x) ## and all others are '0 op 0' which give FALSE r@i <- e1@i r@p <- e1@p } r@Dim <- d r@Dimnames <- dn r } else { ## now the 'x' slots ``match'' insofar as they are for the ## same "space" (triangle for tri* and symm*; else rectangle) ## not non0ind() which gives more; ## want only those which correspond to 'x' slot ij1 <- .Call(compressed_non_0_ij, e1, TRUE) ij2 <- .Call(compressed_non_0_ij, e2, TRUE) ii <- WhichintersectInd(ij1, ij2, di=d) I1 <- ii[[1]]; has1 <- length(I1) > 0 I2 <- ii[[2]]; has2 <- length(I2) > 0 ## potentially could be faster for 'nsparse' ## but this is simple: e1x <- if(e1is.n) rep.int(1L, length(e1@i)) else e1@x e2x <- if(e2is.n) rep.int(1L, length(e2@i)) else e2@x ## 1) common x <- callGeneric(e1x[I1], e2x[I2]) ## 2) "e1 o 0": x2 <- callGeneric(if(has1) e1x[- I1] else e1x, 0) ## 3) "0 o e2": x3 <- callGeneric(0, if(has2) e2x[- I2] else e2x) i <- c(ij1[I1, 1], if(has1) ij1[-I1, 1] else ij1[, 1], if(has2) ij2[-I2, 1] else ij2[, 1]) j <- c(ij1[I1, 2], if(has1) ij1[-I1, 2] else ij1[, 2], if(has2) ij2[-I2, 2] else ij2[, 2]) x <- c(x, x2, x3) if(any(i0x <- is0(x))) { # drop 'FALSE's n0 <- !i0x i <- i[n0] j <- j[n0] x <- x[n0] } .M2C(if(e1is.n && e2is.n) new(paste0("n",shape,"TMatrix"), Dim = d, Dimnames = dn, i = i, j = j) else if(!S && !T) new(paste0("l",shape,"TMatrix"), Dim = d, Dimnames = dn, i = i, j = j, x = x) else # S or T new(paste0("l",shape,"TMatrix"), Dim = d, Dimnames = dn, i = i, j = j, x = x, uplo = e1@uplo)) } }) ##-------- originally from ./sparseMatrix.R -------------------- ## "Arith" short cuts / exceptions setMethod("-", c(e1 = "sparseMatrix", e2 = "missing"), function(e1, e2) { e1 <- diagU2N(e1) e1@x <- -e1@x if(.hasSlot(e1, "factors") && length(e1@factors)) e1@factors <- list() e1 }) ## with the following exceptions: setMethod("-", c(e1 = "nsparseMatrix", e2 = "missing"), function(e1, e2) -.M2kind(e1, "d")) setMethod("-", c(e1 = "indMatrix", e2 = "missing"), function(e1, e2) -as(e1, "dsparseMatrix")) ## Group method "Arith" ## have CsparseMatrix methods above ## which may preserve "symmetric", "triangular" -- simply defer to those: setMethod("Ops", c(e1 = "sparseMatrix", e2 = "nsparseMatrix"), function(e1, e2) callGeneric(as(e1, "CsparseMatrix"), .M2kind(e2, "l"))) setMethod("Ops", c(e1 = "nsparseMatrix", e2 = "sparseMatrix"), function(e1, e2) callGeneric(.M2kind(e1, "l"), as(e2, "CsparseMatrix"))) ## these were 'Arith', now generalized: if(FALSE) { ## just shifts the ambiguity warnings .. ## o more complicated - against PITA disambiguation warnings: setMethod("Ops", c(e1 = "TsparseMatrix", e2 = "TsparseMatrix"), function(e1, e2) callGeneric(as(e1, "CsparseMatrix"), as(e2, "CsparseMatrix"))) setMethod("Ops", c(e1 = "TsparseMatrix", e2 = "CsparseMatrix"), function(e1, e2) callGeneric(as(e1, "CsparseMatrix"), e2)) setMethod("Ops", c(e1 = "CsparseMatrix", e2 = "TsparseMatrix"), function(e1, e2) callGeneric(e1, as(e2, "CsparseMatrix"))) } ## catch the rest: Rsparse* and T* o R* setMethod("Ops", c(e1 = "sparseMatrix", e2 = "sparseMatrix"), function(e1, e2) callGeneric(as(e1, "CsparseMatrix"), as(e2, "CsparseMatrix"))) setMethod("Ops", c(e1 = "sparseMatrix", e2 = "numeric"), function(e1, e2) callGeneric(as(e1, "CsparseMatrix"), e2)) setMethod("Ops", c(e1 = "numeric", e2 = "sparseMatrix"), function(e1, e2) callGeneric(e1, as(e2, "CsparseMatrix"))) ## setMethod("Compare", c(e1 = "sparseMatrix", e2 = "sparseMatrix"), ## function(e1, e2) callGeneric(as(e1, "CsparseMatrix"), ## as(e2, "CsparseMatrix"))) ###-------- sparseVector ------------- ###-------- ============ ------------- ## Catch all remaining setMethod("Ops", c(e1 = "sparseVector", e2 = "ANY"), function(e1, e2) .bail.out.2(.Generic, class(e1), class(e2))) setMethod("Ops", c(e1 = "ANY", e2 = "sparseVector"), function(e1, e2) .bail.out.2(.Generic, class(e1), class(e2))) ## 1) spVec o (sp)Vec : ------------- ## FIXME: ## 2. o should also happen directly and ## |-> sparse for o = {'*', "/", '&&', '==', ... setMethod("Ops", c(e1 = "sparseVector", e2 = "vector"), function(e1, e2) { if(is.object(e2) || is.array(e2) || is.recursive(e2)) stop(gettextf("invalid class \"%s\" object in '%s' method", data.class(e2), "Ops"), domain = NA) if(length(e2) == 1) { ## scalar ------ special case - "fast" if(all0(callGeneric(FALSE, e2))) { # result remains sparse if(is(e1, "nsparseVector")) { # no 'x' slot, i.e. all TRUE r <- callGeneric(TRUE, e2) if(is.logical(r)) { if(isTRUE(all(r))) # (could be NA) e1 # result unchanged else newSpVec("lsparseVector", x = r, e1) } else { newSpVec(paste0(if(is.integer(r)) "i" else "d", "sparseVector"), x = r, e1) } } else { # has x slot r <- callGeneric(e1@x, e2) if(identical(class(r), class(e1@x))) { e1@x <- r e1 } else { newSpVec(paste0(.M.kind(r), "sparseVector"), x = r, e1) } } } else ## non-sparse result callGeneric(sp2vec(e1), e2) } else ## e2 is not scalar callGeneric(e1, as(e2, "sparseVector")) }) setMethod("Ops", c(e1 = "vector", e2 = "sparseVector"), function(e1, e2) { if(is.object(e1) || is.array(e1) || is.recursive(e1)) stop(gettextf("invalid class \"%s\" object in '%s' method", data.class(e1), "Ops"), domain = NA) if(length(e1) == 1) { ## scalar ------ special case - "fast" if(all0(callGeneric(e1, FALSE))) { # result remains sparse if(is(e2, "nsparseVector")) { # no 'x' slot, i.e. all TRUE r <- callGeneric(e1, TRUE) if(is.logical(r)) { if(isTRUE(all(r))) # (could be NA) e2 # result unchanged else newSpVec("lsparseVector", x = r, e2) } else { newSpVec(paste0(if(is.integer(r)) "i" else "d", "sparseVector"), x = r, e2) } } else { # has x slot r <- callGeneric(e1, e2@x) if(identical(class(r), class(e2@x))) { e2@x <- r e2 } else { newSpVec(paste0(.M.kind(r), "sparseVector"), x = r, e2) } } } else ## non-sparse result callGeneric(e1, sp2vec(e2)) } else ## e1 is not scalar callGeneric(as(e1, "sparseVector"), e2) }) Ops.spV.spV <- function(e1, e2) { n1 <- e1@length n2 <- e2@length if(!n1 || !n2) ## return 0-length : return(if(is.na(match(.Generic, .ArithGenerics))) logical() else numeric()) ## else n1, n2 >= 1 : if(n1 != n2) { if(n1 < n2) { n <- n1 ; N <- n2 } else { n <- n2 ; N <- n1 } if(n == 1L) { # simple case, do not really recycle if(n1 < n2) return(callGeneric(sp2vec(e1), e2)) else return(callGeneric(e1, sp2vec(e2))) } ## else : 2 <= n < N if(N %% n != 0) warning("longer object length is not a multiple of shorter object length") ## recycle the shorter one if(n1 < n2) { e1 <- rep(e1, length.out = N) } else { e2 <- rep(e2, length.out = N) } } else { ## n1 == n2 N <- n1 } ## ---- e1 & e2 now are both of length 'N' ---- ## First check the (0 o 0) result is1n <- extends(class(e1), "nsparseVector") is2n <- extends(class(e2), "nsparseVector") r00 <- callGeneric(if(is1n) FALSE else as0(e1@x), if(is2n) FALSE else as0(e2@x)) if(is0(r00)) { ## -> sparseVector e1x <- if(is1n) TRUE else e1@x e2x <- if(is2n) TRUE else e2@x sp <- .setparts(e1@i, e2@i) ## Idea: Modify 'e2' and return it : new.x <- c(callGeneric(e1x[sp[["ix.only"]]], 0), # e1-only callGeneric(0, e2x[sp[["iy.only"]]]), # e2-only callGeneric(e1x[sp[["my"]]], # common to both e2x[sp[["mx"]]])) i. <- c(sp[["x.only"]], sp[["y.only"]], sp[["int"]]) cl2x <- typeof(e2x) ## atomic "class"es - can use in is(), as(), too: if(!is2n && is(new.x, cl2x)) { i. <- sort.int(i., method = "quick", index.return=TRUE) e2@x <- as(new.x, cl2x)[i.$ix] e2@i <- i.$x e2 } else { newSpV(paste0(.kind.type[typeof(new.x)],"sparseVector"), x = new.x, i = i., length = e2@length) } } else { ## 0 o 0 is NOT in {0 , FALSE} --> "dense" result callGeneric(sp2vec(e1), sp2vec(e2)) } } ## {Ops.spV.spV} ## try to use it in all cases setMethod("Ops", c(e1 = "sparseVector", e2 = "sparseVector"), Ops.spV.spV) ## was function(e1, e2) .bail.out.2(.Generic, class(e1), class(e2))) setMethod("Arith", c(e1 = "sparseVector", e2 = "sparseVector"), function(e1, e2) callGeneric(as(e1, "dsparseVector"), as(e2, "dsparseVector"))) setMethod("Arith", c(e1 = "dsparseVector", e2 = "dsparseVector"), Ops.spV.spV) ## "Arith" exception (shortcut) setMethod("-", c(e1 = "dsparseVector", e2 = "missing"), function(e1) { e1@x <- -e1@x ; e1 }) setMethod("Logic", c(e1 = "sparseVector", e2 = "sparseVector"), ## FIXME: this is suboptimal for "nsparseVector" !! function(e1, e2) callGeneric(as(e1, "lsparseVector"), as(e2, "lsparseVector"))) setMethod("Logic", c(e1 = "lsparseVector", e2 = "lsparseVector"), Ops.spV.spV) ## "nsparse" have no 'x' slot --> version of Ops.spV.spV.. ## -------- but also for (nsp.. o lsp..) etc, when lsp... has no NA if(FALSE) ### FIXME setMethod("Logic", c(e1 = "nsparseVector", e2 = "nsparseVector"), function(e1, e2) { .bail.out.2(.Generic, class(e1), class(e2)) }) rm(Ops.spV.spV) ## 2) spVec o [Mm]atrix : ------------- Ops.M.spV <- function(e1, e2) { d <- e1@Dim n1 <- prod(d) n2 <- e2@length if(n1 != n2) { if(n1 && n1 < n2) { # 0-extent matrix + vector is fine stop(sprintf("dim [product %d] do not match the length of object [%d]", n1, n2)) } ## else n1 > n2 [vector] N <- n1 if(n2 == 1) ## simple case, do not really recycle return(callGeneric(e1, sp2vec(e2))) if(N %% n2 != 0) warning("longer object length is not a multiple of shorter object length") ## else : 2 <= n < N --- recycle the vector e2 <- rep(e2, length.out = N) } else { ## n1 == n2 N <- n1 } ## ---- e1 & e2 now are both of length 'N' ---- dim(e2) <- d #-> sparseMatrix (!) callGeneric(e1, e2) }## {Ops.M.spV} Ops.spV.M <- function(e1, e2) { n1 <- e1@length d <- e2@Dim n2 <- prod(d) if(n2 != n1) { if(n2 && n2 < n1) { # vector + 0-extent matrix is fine stop(sprintf("dim [product %d] do not match the length of object [%d]", n2, n1)) } ## else n2 > n1 [vector] N <- n2 if(n1 == 1) ## simple case, do not really recycle return(callGeneric(sp2vec(e1), e2)) if(N %% n1 != 0) warning("longer object length is not a multiple of shorter object length") ## else : 2 <= n < N --- recycle the vector e1 <- rep(e1, length.out = N) } else { ## n2 == n1 N <- n2 } ## ---- e2 & e1 now are both of length 'N' ---- dim(e1) <- d #-> sparseMatrix (!) callGeneric(e1, e2) }## {Ops.spV.M} ## try to use it in all cases setMethod("Ops", c(e1 = "Matrix", e2 = "sparseVector"), Ops.M.spV) setMethod("Ops", c(e1 = "sparseVector", e2 = "Matrix"), Ops.spV.M) rm(Ops.M.spV, Ops.spV.M) ###---------------- diagonalMatrix ---------------------- .diag2tT.smart <- function(from, x, kind = ".") { shape <- .M.shape(x) uplo <- if(shape == "t") x@uplo else "U" .diag2sparse(from, kind, "t", "T", uplo) } .diag2T.smart <- function(from, x, kind = ".") { shape <- .M.shape(x) uplo <- if(shape == "s" || shape == "t") x@uplo else "U" .diag2sparse(from, kind, if(shape == "s") "s" else "t", "T", uplo) } .diag.x <- function(m) if(m@diag != "N") rep.int(as1(m@x), m@Dim[1L]) else m@x ..diag.x <- function(m) rep.int(as1(m@x), m@Dim[1L]) ## Use as S4 method for several signatures ==> using callGeneric() diagOdiag <- function(e1,e2) { ## result should also be diagonal _ if possible _ r <- callGeneric(.diag.x(e1), .diag.x(e2)) # error if not "compatible" ## Check what happens with non-diagonals, i.e. (0 o 0), (FALSE o 0), ...: r00 <- callGeneric(if(is.numeric(e1@x)) 0 else FALSE, if(is.numeric(e2@x)) 0 else FALSE) if(is0(r00)) { ## r00 == 0 or FALSE --- result *is* diagonal if(is.numeric(r)) { # "double" *or* "integer" if(!is.double(r)) r <- as.double(r) if(is.double(e2@x)) { e2@x <- r e2@diag <- "N" return(e2) } if(!is.double(e1@x)) ## e.g. e1, e2 are logical; e1 <- .M2kind(e1, "d") } else if(is.logical(r)) e1 <- .M2kind(e1, "l") else stop(gettextf("intermediate 'r' is of type %s", typeof(r)), domain=NA) e1@x <- r e1@diag <- "N" e1 } else { ## result not diagonal, but at least symmetric: ## e.g., m == m isNum <- (is.numeric(r) || is.numeric(r00)) isLog <- (is.logical(r) || is.logical(r00)) Matrix.message("exploding o into dense matrix", .M.level = 2) d <- e1@Dim n <- d[1L] stopifnot(length(r) == n) if(isNum && !is.double(r)) r <- as.double(r) ## faster (?) than m <- matrix(r00,n,n); diag(m) <- r ; as.vector(m) xx <- rbind(r, matrix(r00,n,n), deparse.level=0L)[seq_len(n*n)] newcl <- paste0(if(isNum) "d" else if(isLog) { if(!anyNA(r) && !anyNA(r00)) "n" else "l" } else stop("not yet implemented .. please report"), "syMatrix") new(newcl, Dim = e1@Dim, Dimnames = e1@Dimnames, x = xx) } } ### This would be *the* way, but we get tons of "ambiguous method dispatch" ## we use this hack instead of signature x = "diagonalMatrix" : diCls <- names(getClassDef("diagonalMatrix")@subclasses) if(FALSE) { setMethod("Ops", c(e1 = "diagonalMatrix", e2 = "diagonalMatrix"), diagOdiag) } else { ## These are just for method disambiguation: for(c1 in diCls) for(c2 in diCls) setMethod("Ops", c(e1 = c1, e2 = c2), diagOdiag) rm(c1, c2) } rm(diagOdiag) ## diagonal o triangular |--> triangular ## diagonal o symmetric |--> symmetric ## {also when other is sparse: do these "here" -- ## before conversion to sparse, since that loses "diagonality"} diagOtri <- function(e1,e2) { ## result must be triangular r <- callGeneric(d1 <- .diag.x(e1), diag(e2)) # error if not "compatible" ## Check what happens with non-diagonals, i.e. (0 o 0), (FALSE o 0), ...: e1.0 <- if(is.numeric(d1)) 0 else FALSE r00 <- callGeneric(e1.0, if(.n2 <- is.numeric(e2[0L])) 0 else FALSE) if(is0(r00)) { ## r00 == 0 or FALSE --- result *is* triangular diag(e2) <- r ## check what happens "in the triangle" e2.2 <- if(.n2) 2 else TRUE if(!callGeneric(e1.0, e2.2) == e2.2) { # values "in triangle" can change: n <- dim(e2)[1L] it <- indTri(n, upper = (e2@uplo == "U")) e2[it] <- callGeneric(e1.0, e2[it]) } e2 } else { ## result not triangular ---> general rr <- as(e2, "generalMatrix") diag(rr) <- r rr } } setMethod("Ops", c(e1 = "diagonalMatrix", e2 = "triangularMatrix"), diagOtri) rm(diagOtri) ## For the reverse, Ops == "Arith" | "Compare" | "Logic" ## 'Arith' := '"+"', '"-"', '"*"', '"^"', '"%%"', '"%/%"', '"/"' setMethod("Arith", c(e1 = "triangularMatrix", e2 = "diagonalMatrix"), function(e1, e2) { ## this must only trigger for *dense* e1 switch(.Generic, "+" = `diag<-`(e1, as.double(diag(e1, names=FALSE) + .diag.x(e2))), "-" = `diag<-`(e1, as.double(diag(e1, names=FALSE) - .diag.x(e2))), "*" = { n <- e2@Dim[1L] d2 <- if(e2@diag == "U") { # unit-diagonal d <- rep.int(as1(e2@x), n) e2@x <- d e2@diag <- "N" d } else e2@x e2@x <- diag(e1) * d2 e2 }, "^" = { ## will be dense ( as ^ 0 == 1 ): e1 ^ .diag2dense(e2, ".", "g", FALSE) }, ## otherwise: callGeneric(e1, .diag2T.smart(e2, e1))) }) ## Compare --> 'swap' (e.g. e1 < e2 <==> e2 > e1 ): setMethod("Compare", c(e1 = "triangularMatrix", e2 = "diagonalMatrix"), .Cmp.swap) ## '&' and "|' are commutative: setMethod("Logic", c(e1 = "triangularMatrix", e2 = "diagonalMatrix"), function(e1, e2) callGeneric(e2, e1)) ## For almost everything else, diag* shall be treated "as sparse" : ## These are cheap implementations via coercion ## For disambiguation --- define this for "sparseMatrix" , then for "ANY"; ## and because we can save an .M.kind() call, we use this explicit ## "hack" for all diagonalMatrix *subclasses* instead of just "diagonalMatrix" : ## ## ddi*: setMethod("Ops", c(e1 = "ddiMatrix", e2 = "sparseMatrix"), function(e1,e2) callGeneric(.diag2T.smart(e1, e2, kind = "d"), e2)) setMethod("Ops", c(e1 = "sparseMatrix", e2 = "ddiMatrix"), function(e1,e2) callGeneric(e1, .diag2T.smart(e2, e1, kind = "d"))) ## ldi* setMethod("Ops", c(e1 = "ldiMatrix", e2 = "sparseMatrix"), function(e1,e2) callGeneric(.diag2T.smart(e1, e2, kind = "l"), e2)) setMethod("Ops", c(e1 = "sparseMatrix", e2 = "ldiMatrix"), function(e1,e2) callGeneric(e1, .diag2T.smart(e2, e1, kind = "l"))) ## Ops: Arith --> numeric : "dMatrix" ## Compare --> logical ## Logic --> logical: "lMatrix" ## Other = "numeric" : stay diagonal if possible ## ddi*: Arith: result numeric, potentially ddiMatrix for(arg2 in c("numeric","logical")) setMethod("Arith", c(e1 = "ddiMatrix", e2 = arg2), function(e1,e2) { n <- e1@Dim[1L] if(length(e2) == 0L) return(if(n) numeric() else e1) f0 <- callGeneric(0, e2) if(all0(f0)) { # remain diagonal if(e1@diag == "U") { if(any((r <- callGeneric(1, e2)) != 1)) { e1@diag <- "N" e1@x[seq_len(n)] <- r # possibly recycling r } ## else: result = e1 (is "U" diag) } else if(n) { L1 <- (le <- length(e2)) == 1L r <- callGeneric(e1@x, e2) ## "future fixme": if we have idiMatrix, and r is 'integer', use idiMatrix e1@x[] <- if(L1) r else r[1L + ((n+1)*(0:(n-1L))) %% le] } e1 } else callGeneric(.diag2tT.smart(e1, e2, kind = "d"), e2) }) rm(arg2) for(arg1 in c("numeric","logical")) setMethod("Arith", c(e1 = arg1, e2 = "ddiMatrix"), function(e1,e2) { n <- e2@Dim[1L] if(length(e1) == 0L) return(if(n) numeric() else e2) f0 <- callGeneric(e1, 0) if(all0(f0)) { # remain diagonal if(e2@diag == "U") { if(any((r <- callGeneric(e1, 1)) != 1)) { e2@diag <- "N" e2@x[seq_len(n)] <- r # possibly recycling r } ## else: result = e2 (is "U" diag) } else { L1 <- (le <- length(e1)) == 1L r <- callGeneric(e1, e2@x) ## "future fixme": if we have idiMatrix, and r is 'integer', use idiMatrix e2@x[] <- if(L1) r else r[1L + ((n+1)*(0:(n-1L))) %% le] } e2 } else callGeneric(e1, .diag2tT.smart(e2, e1, kind = "d")) }) rm(arg1) ## ldi* Arith --> result numeric, potentially ddiMatrix for(arg2 in c("numeric","logical")) setMethod("Arith", c(e1 = "ldiMatrix", e2 = arg2), function(e1,e2) { n <- e1@Dim[1L] if(length(e2) == 0L) return(if(n) numeric() else copyClass(e1, "ddiMatrix", c("diag", "Dim", "Dimnames"), check=FALSE)) f0 <- callGeneric(0, e2) if(all0(f0)) { # remain diagonal E <- copyClass(e1, "ddiMatrix", c("diag", "Dim", "Dimnames"), check=FALSE) ## storage.mode(E@x) <- "double" if(e1@diag == "U") { if(any((r <- callGeneric(1, e2)) != 1)) { E@diag <- "N" E@x[seq_len(n)] <- r # possibly recycling r } ## else: result = E (is "U" diag) } else if(n) { L1 <- (le <- length(e2)) == 1L r <- callGeneric(e1@x, e2) ## "future fixme": if we have idiMatrix, and r is 'integer', use idiMatrix E@x[seq_len(n)] <- if(L1) r else r[1L + ((n+1)*(0:(n-1L))) %% le] } E } else callGeneric(.diag2tT.smart(e1, e2, kind = "l"), e2) }) rm(arg2) for(arg1 in c("numeric","logical")) setMethod("Arith", c(e1 = arg1, e2 = "ldiMatrix"), function(e1,e2) { n <- e2@Dim[1L] if(length(e1) == 0L) return(if(n) numeric() else copyClass(e2, "ddiMatrix", c("diag", "Dim", "Dimnames"), check=FALSE)) f0 <- callGeneric(e1, 0) if(all0(f0)) { # remain diagonal E <- copyClass(e2, "ddiMatrix", c("diag", "Dim", "Dimnames"), check=FALSE) ## storage.mode(E@x) <- "double" if(e2@diag == "U") { if(any((r <- callGeneric(e1, 1)) != 1)) { E@diag <- "N" E@x[seq_len(n)] <- r # possibly recycling r } ## else: result = E (is "U" diag) } else if(n) { L1 <- (le <- length(e1)) == 1L r <- callGeneric(e1, e2@x) ## "future fixme": if we have idiMatrix, ## and r is 'integer', use idiMatrix E@x[seq_len(n)] <- if(L1) r else r[1L + ((n+1)*(0:(n-1L))) %% le] } E } else callGeneric(e1, .diag2tT.smart(e2, e1, kind = "l")) }) rm(arg1) ## ddi*: for "Ops" without "Arith": or --> result logical, potentially ldi ## ## Note that ("numeric", "ddiMatrix") is simply swapped, e.g., if(FALSE) { selectMethod("<", c("numeric","lMatrix"))# Compare selectMethod("&", c("numeric","lMatrix"))# Logic } ## so we don't need to define a method here : for(arg2 in c("numeric","logical")) setMethod("Ops", c(e1 = "ddiMatrix", e2 = arg2), function(e1,e2) { n <- e1@Dim[1L] if(length(e2) == 0L) return(if(n) logical() else copyClass(e1, "ldiMatrix", c("diag", "Dim", "Dimnames"), check=FALSE)) f0 <- callGeneric(0, e2) if(all0(f0)) { # remain diagonal E <- copyClass(e1, "ldiMatrix", c("diag", "Dim", "Dimnames"), check=FALSE) ## storage.mode(E@x) <- "logical" if(e1@diag == "U") { if(any((r <- callGeneric(1, e2)) != 1)) { E@diag <- "N" E@x[seq_len(n)] <- r # possibly recycling r } ## else: result = E (is "U" diag) } else if(n) { L1 <- (le <- length(e2)) == 1L r <- callGeneric(e1@x, e2) ## "future fixme": if we have idiMatrix, ### and r is 'integer', use idiMatrix E@x[seq_len(n)] <- if(L1) r else r[1L + ((n+1)*(0:(n-1L))) %% le] } E } else callGeneric(.diag2tT.smart(e1, e2, kind = "d"), e2) }) rm(arg2) ## ldi*: for "Ops" without "Arith": or --> result logical, potentially ldi for(arg2 in c("numeric","logical")) setMethod("Ops", c(e1 = "ldiMatrix", e2 = arg2), function(e1,e2) { n <- e1@Dim[1L] if(length(e2) == 0L) return(if(n) logical() else e1) f0 <- callGeneric(FALSE, e2) if(all0(f0)) { # remain diagonal if(e1@diag == "U") { if(any((r <- callGeneric(TRUE, e2)) != 1)) { e1@diag <- "N" e1@x[seq_len(n)] <- r # possibly recycling r } ## else: result = e1 (is "U" diag) } else if(n) { L1 <- (le <- length(e2)) == 1L r <- callGeneric(e1@x, e2) ## "future fixme": if we have idiMatrix, ## and r is 'integer', use idiMatrix e1@x[] <- if(L1) r else r[1L + ((n+1)*(0:(n-1L))) %% le] } e1 } else callGeneric(.diag2tT.smart(e1, e2, kind = "l"), e2) }) rm(arg2) ## Not {"sparseMatrix", "numeric} : {"denseMatrix", "matrix", ... } for(other in c("ANY", "Matrix", "dMatrix")) { ## ddi*: setMethod("Ops", c(e1 = "ddiMatrix", e2 = other), function(e1,e2) callGeneric(.diag2T.smart(e1, e2, kind="d"), e2)) setMethod("Ops", c(e1 = other, e2 = "ddiMatrix"), function(e1,e2) callGeneric(e1, .diag2T.smart(e2, e1, kind="d"))) ## ldi*: setMethod("Ops", c(e1 = "ldiMatrix", e2 = other), function(e1,e2) callGeneric(.diag2T.smart(e1, e2, kind="l"), e2)) setMethod("Ops", c(e1 = other, e2 = "ldiMatrix"), function(e1,e2) callGeneric(e1, .diag2T.smart(e2, e1, kind="l"))) } rm(other) ## Direct subclasses of "denseMatrix": currently ddenseMatrix, ldense... : if(FALSE) # now also contains "geMatrix" dense.subCl <- local({ dM.scl <- getClassDef("denseMatrix")@subclasses names(dM.scl)[vapply(dM.scl, slot, 0, "distance") == 1] }) dense.subCl <- paste0(c("d","l","n"), "denseMatrix") for(DI in diCls) { dMeth <- if(extends(DI, "dMatrix")) function(e1,e2) callGeneric(.diag2T.smart(e1, e2, kind = "d"), e2) else # "lMatrix", the only other kind for now function(e1,e2) callGeneric(.diag2T.smart(e1, e2, kind = "l"), e2) for(c2 in c(dense.subCl, "Matrix")) { for(Fun in c("*", "&")) { setMethod(Fun, c(e1 = DI, e2 = c2), function(e1,e2) callGeneric(e1, Diagonal(x = diag(e2)))) setMethod(Fun, c(e1 = c2, e2 = DI), function(e1,e2) callGeneric(Diagonal(x = diag(e1)), e2)) } setMethod("^", c(e1 = c2, e2 = DI), function(e1,e2) callGeneric(Diagonal(x = diag(e1)), e2)) for(Fun in c("%%", "%/%", "/")) ## 0 0 |--> NaN for these. setMethod(Fun, c(e1 = DI, e2 = c2), dMeth) } } rm(dense.subCl, DI, dMeth, c2, Fun) Matrix/R/not.R0000644000175100001440000000334014561451364012671 0ustar hornikusers## METHODS FOR GENERIC: ! (not) ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("!", c(x = "Matrix"), function(x) !.M2kind(x, "l")) setMethod("!", c(x = "sparseVector"), function(x) !.V2kind(x, "l")) setMethod("!", c(x = "ndenseMatrix"), function(x) { if(.M.shape(x) == "t") x <- .M2gen(x) x@x <- { y <- x@x; if(anyNA(y)) !(y | is.na(y)) else !y } x }) setMethod("!", c(x = "ldenseMatrix"), function(x) { if(.M.shape(x) == "t") x <- .M2gen(x) x@x <- !x@x x }) setMethod("!", c(x = "nsparseMatrix"), function(x) { x <- .sparse2dense(if(.M.shape(x) == "t") .M2gen(x) else x) x@x <- !x@x x }) setMethod("!", c(x = "lsparseMatrix"), function(x) { x <- .sparse2dense(if(.M.shape(x) == "t") .M2gen(x) else x) x@x <- !x@x x }) setMethod("!", c(x = "ndiMatrix"), function(x) { if(x@diag == "N" && anyNA(y <- x@x)) x@x <- y | is.na(y) x <- .diag2dense(x, ".", "g") x@x <- !x@x x }) setMethod("!", c(x = "ldiMatrix"), function(x) { x <- .diag2dense(x, ".", "g") x@x <- !x@x x }) setMethod("!", c(x = "nsparseVector"), function(x) !.V2v(x)) setMethod("!", c(x = "lsparseVector"), function(x) !.V2v(x)) setMethod("!", c(x = "indMatrix"), function(x) { x <- .ind2dense(x) x@x <- !x@x x }) Matrix/R/Auxiliaries.R0000644000175100001440000003702214574651323014355 0ustar hornikusers#### "Namespace private" Auxiliaries such as method functions #### (called from more than one place --> need to be defined early) is0 <- function(x) !(is.na(x) | x) isN0 <- function(x) is.na(x) | x is1 <- function(x) !is.na(x) & x == 1L isN1 <- function(x) is.na(x) | x != 1L allTrue <- function(x) !is.na(a <- all( x)) && a allFalse <- function(x) if(is.atomic(x)) .Call(R_all0, x) else !is.na(a <- any( x)) && !a all0 <- function(x) if(is.atomic(x)) .Call(R_all0, x) else !is.na(a <- all(!x)) && a anyFalse <- function(x) if(is.atomic(x)) .Call(R_any0, x) else !is.na(a <- all( x)) && !a any0 <- function(x) if(is.atomic(x)) .Call(R_any0, x) else !is.na(a <- any(!x)) && a ## NB: change to using 'typeof' when we define iMatrix as1 <- function(x, mode. = mode(x)) switch(mode., "logical" = TRUE, "integer" = 1L, "double" = , "numeric" = 1, "complex" = 1+0i, stop(gettextf("invalid mode \"%s\"", mode.), domain = NA)) ## NB: change to using 'typeof' when we define iMatrix as0 <- function(x, mode. = mode(x)) switch(mode., "logical" = FALSE, "integer" = 0L, "double" = , "numeric" = 0, "complex" = 0+0i, stop(gettextf("invalid mode \"%s\"", mode.), domain = NA)) .bail.out.2 <- function(name, cl1, cl2) stop(gettextf("%s(<%s>, <%s>) is not yet implemented; ask maintainer(\"%s\") to implement the missing method", name, cl1[1L], cl2[1L], "Matrix"), call. = FALSE, domain = NA) Matrix.verbose <- function() getOption("Matrix.verbose", .MatrixEnv[["verbose"]]) Matrix.warn <- function() getOption("Matrix.warn", .MatrixEnv[["warn"]]) ## MJ: or maybe a general one? if(FALSE) { Matrix.getOption <- function(x, default = .Matrix.Env[[x]]) getOption(paste0("Matrix.", x), default) } ## MJ Matrix.message <- function(..., .M.level = 1, call. = FALSE, domain = NULL) { if(Matrix.verbose() >= .M.level) { m <- if((w <- Matrix.warn()) < 1) function(..., call., domain) message(..., domain = domain) else if(w < 2) warning else stop m(..., call. = call., domain = domain) } } ## MJ: Implement forceTriangular() and export this and that? ## MJ: Notably this provides a model for (maybe, in the future) allowing ## forceSymmetric() ... by truncating the "too long" dimension. forceDiagonal <- function(x, diag = NA_character_) { y <- diag(x, names = FALSE) # FIXME? don't allocate if diag == "U" cl <- switch(typeof(y), logical = { if(is.na(diag)) diag <- if(!is.na(a <- all(y )) && a) "U" else "N" if(.M.kind(x) == "n") "ndiMatrix" else "ldiMatrix" }, integer = { if(is.na(diag)) diag <- if(!is.na(a <- all(y == 1L )) && a) "U" else "N" storage.mode(y) <- "double" "ddiMatrix" }, ## integer = ## { ## if(is.na(diag)) ## diag <- ## if(!is.na(a <- all(y == 1L )) && a) "U" else "N" ## "idiMatrix" ## }, double = { if(is.na(diag)) diag <- if(!is.na(a <- all(y == 1 )) && a) "U" else "N" "ddiMatrix" }, complex = stop(gettextf("complex %s not yet implemented", "diagonalMatrix"), domain = NA), ## complex = ## { ## if(is.na(diag)) ## diag <- ## if(!is.na(a <- all(y == 1+0i)) && a) "U" else "N" ## "zdiMatrix" ## }, stop(gettextf("cannot coerce matrix of type \"%s\" to %s", typeof(y), "diagonalMatrix"), domain = NA)) n <- length(y) d <- dim(x) dn <- dimnames(x) %||% list(NULL, NULL) if(any(d > n)) { d <- c(n, n) w <- if(d[1L] > n) 1L else 2L if(!is.null(dnw <- dn[[w]])) dn[[w]] <- dnw[seq_len(n)] } new(cl, Dim = d, Dimnames = dn, diag = diag, x = if(diag == "N") y else y[FALSE]) } .tCRT <- function(x, lazy = TRUE) .Call(R_sparse_transpose, x, lazy) .drop0 <- function(x, tol = 0, isM = TRUE) { if(isM) return(.Call(R_sparse_drop0, x, tol)) ## TODO: write sparseVector code in C and respecting 'tol' if(.M.kind(x) == "n") return(x) x.x <- x@x k <- which(is.na(x.x) | x.x) if(length(k)) { x@i <- x@i[k] x@x <- x.x[k] } x } drop0 <- function(x, tol = 0, is.Csparse = NA, give.Csparse = TRUE) { tryCoerce <- if(give.Csparse) is.na(is.Csparse) || !is.Csparse else if(.M.kind(x) != "n") !.isCRT(x) else if(all(.M.repr(x) != c("C", "R", "T", "i"))) TRUE else return(x) # n[gst][CRT]Matrix or indMatrix if(tryCoerce) x <- if(isS4(x)) .M2C(x) else .m2sparse.checking(x, ".", "C") .Call(R_sparse_drop0, x, as.double(tol)) } indDiag <- function(n, upper = TRUE, packed = FALSE) .Call(R_index_diagonal, n, packed, upper) indTri <- function(n, upper = TRUE, diag = FALSE, packed = FALSE) .Call(R_index_triangle, n, packed, upper, diag) ## For sparseness handling, return a ## 2-column (i,j) matrix of 0-based indices of non-zero entries: ##' the workhorse for non0ind(.), but occasionally used directly non0.i <- function(M, cM = class(M), uniqT = TRUE) { cld <- getClassDef(cM) if(extends(cld, "CsparseMatrix")) .Call(compressed_non_0_ij, M, TRUE) else if(extends(cld, "RsparseMatrix")) .Call(compressed_non_0_ij, M, FALSE) else if(extends(cld, "TsparseMatrix")) { if(uniqT && !isUniqueT(M)) .Call(compressed_non_0_ij, .M2C(M), TRUE) else cbind(M@i, M@j, deparse.level = 0L) } else if(extends(cld, "diagonalMatrix")) { i <- seq.int(from = 0L, length.out = M@Dim[1L]) if(M@diag == "N") i <- i[isN0(M@x)] cbind(i, i, deparse.level = 0L) } else if(extends(cld, "indMatrix")) { perm <- M@perm i <- seq.int(from = 0L, length.out = length(perm)) if(M@margin == 1L) cbind(i, perm - 1L, deparse.level = 0L) else cbind(perm - 1L, i, deparse.level = 0L) } else stop(gettextf("non0.i() not yet implemented for class %s", dQuote(cM)), domain = NA) } ##' the "more versatile / user" function (still not exported): non0ind <- function(x, cld = getClassDef(class(x)), uniqT = TRUE, xtendSymm = TRUE, check.Udiag = TRUE) { if(is.numeric(x)) { n <- length(x) return(if(n == 0L) integer(0L) else if(is.matrix(x)) arrayInd(seq_len(n)[isN0(x)], dim(x)) - 1L else (0:(n-1L))[isN0(x)]) } stopifnot(extends(cld, "sparseMatrix")) ij <- non0.i(x, cld, uniqT = uniqT) if(xtendSymm && extends(cld, "symmetricMatrix")) { ## also get "other" triangle, but not the diagonal again notdiag <- ij[, 1L] != ij[, 2L] rbind(ij, ij[notdiag, 2:1], deparse.level = 0L) } else if(check.Udiag && extends(cld, "triangularMatrix") && x@diag == "U") { i <- seq.int(from = 0L, length.out = x@Dim[1L]) rbind(ij, cbind(i, i, deparse.level = 0L), deparse.level = 0L) } else ij } ##' Decode "encoded" (i,j) indices back to cbind(i,j) ##' This is the inverse of encodeInd(.) ##' ##' @title Decode "Encoded" (i,j) Indices ##' @param code integer in 0:((n x m - 1) <==> encodeInd(.) result ##' @param nr the number of rows ##' @return ##' @author Martin Maechler decodeInd <- function(code, nr) cbind(as.integer(code %% nr), as.integer(code %/% nr), deparse.level = 0L) complementInd <- function(ij, dim, orig1=FALSE, checkBnds=FALSE) { ## Purpose: Compute the complement of the 2-column 0-based ij-matrix ## but as 1-based indices n <- prod(dim) if(n == 0L) return(integer(0L)) seq_len(n)[-(1L + .Call(m_encodeInd, ij, dim, orig1, checkBnds))] } WhichintersectInd <- function(ij1, ij2, di, orig1=FALSE, checkBnds=FALSE) { ## from 2-column (i,j) matrices where i \in {0,.., nrow-1}, ## find *where* common entries are in ij1 & ij2 m1 <- match(.Call(m_encodeInd, ij1, di, orig1, checkBnds), .Call(m_encodeInd, ij2, di, orig1, checkBnds)) ni <- !is.na(m1) list(which(ni), m1[ni]) } anyDuplicatedT <- function(x, ...) { mn <- prod(d <- x@Dim) if(mn <= .Machine$integer.max) anyDuplicated.default( x@j * d[1L] + x@i, ...) else if(mn <= 0x1p+53) anyDuplicated.default(as.double(x@j) * d[1L] + x@i, ...) else anyDuplicated.default(.mapply(c, list(x@i, x@j), NULL), ...) } isUniqueT <- function(x, byrow = FALSE, isT = is(x, "TsparseMatrix")) isT && !is.unsorted(if(byrow) order(x@i, x@j) else order(x@j, x@i), strictly = TRUE) asUniqueT <- function(x, byrow = FALSE, isT = is(x, "TsparseMatrix")) if(isUniqueT(x, byrow, isT)) x else .M2T(if(byrow) .M2R(x) else .M2C(x)) aggregateT <- function(x) .Call(Tsparse_aggregate, x) mat2triplet <- function(x, uniqT = FALSE) { T <- as(x, "TsparseMatrix") if(uniqT) T <- asUniqueT(T, isT = TRUE) if(is(T, "nsparseMatrix")) list(i = T@i + 1L, j = T@j + 1L) else list(i = T@i + 1L, j = T@j + 1L, x = T@x) } .validateCsparse <- function(x, sort.if.needed = FALSE) { if(sort.if.needed) .Call(CsparseMatrix_validate_maybe_sorting, x) else .Call(CsparseMatrix_validate, x) } dmperm <- function(x, nAns = 6L, seed = 0L) { ## NB: result is determined entirely by nonzero pattern of 'x' stopifnot(length(nAns <- as.integer(nAns)) == 1L, any(nAns == 2L * (1L:3L)), length(seed <- as.integer(seed)) == 1L, any(seed == -1L:1L)) x <- if(isS4(x)) .M2gen(.M2C(x), "n") else .m2sparse(x, "ngC") .Call(Csparse_dmperm, x, nAns, seed) } ## (matrix|denseMatrix)->denseMatrix as similar as possible to "target" as_denseClass <- function(x, cl, cld = getClassDef(cl)) { kind <- .M.kind(x) cl <- .M.nonvirtual(new(cld)) if(cl == "indMatrix") cl <- "ngeMatrix" symmetric <- substr(cl, 2L, 2L) == "s" && isSymmetric(x) triangular <- !symmetric && substr(cl, 2L, 2L) == "t" && (it <- isTriangular(x)) packed <- (symmetric || triangular) && substr(cl, 3L, 3L) == "p" if(isS4(x)) { r <- if(symmetric || triangular) .M2kind(if(symmetric) forceSymmetric(x) else if(attr(it, "kind") == "U") triu(x) else tril(x), kind) else .M2gen(x, kind) if(packed) pack(r) else r } else if(symmetric) .m2dense(x, paste0(kind, "s", if(packed) "p" else "y"), "U", NULL) else if(triangular) .m2dense(x, paste0(kind, "t", if(packed) "p" else "r"), attr(it, "kind"), "N") else .m2dense(x, paste0(kind, "ge")) } ## (matrix|sparseMatrix)->CsparseMatrix as similar as possible to "target" as_CspClass <- function(x, cl, cld = getClassDef(cl)) { kind <- .M.kind(x) cl <- .M.nonvirtual(new(cld)) if(cl == "indMatrix") cl <- "ngeMatrix" symmetric <- substr(cl, 2L, 2L) == "s" && isSymmetric(x) triangular <- !symmetric && substr(cl, 2L, 2L) == "t" && (it <- isTriangular(x)) if(isS4(x)) { r <- if(symmetric || triangular) .M2kind(if(symmetric) forceSymmetric(x) else if(attr(it, "kind") == "U") triu(x) else tril(x), kind) else .M2gen(x, kind) .M2C(r) } else if(symmetric) .m2sparse(x, paste0(kind, "sC"), "U", NULL) else if(triangular) .m2sparse(x, paste0(kind, "tC"), attr(it, "kind"), "N") else .m2sparse(x, paste0(kind, "gC")) } ## as(<[Mm]atrix>, ) asCspN <- function(x) .Call(R_sparse_diag_U2N, as(x, "CsparseMatrix")) diagU2N <- function (x, cl = getClassDef(class(x)), checkDense = FALSE) { if(extends(cl, "triangularMatrix") && x@diag == "U") .diagU2N(x, cl = cl, checkDense = checkDense) else x } .diagU2N <- function(x, cl = getClassDef(class(x)), checkDense = FALSE) { if(!checkDense && extends(cl, "denseMatrix")) x <- as(x, "CsparseMatrix") ..diagU2N(x) } ..diagU2N <- function(x) { diag(x) <- TRUE x } diagN2U <- function(x, cl = getClassDef(class(x)), checkDense = FALSE) { if(extends(cl, "triangularMatrix") && x@diag == "N") .diagN2U(x, cl = cl, checkDense = checkDense) else x } .diagN2U <- function(x, cl = getClassDef(class(x)), checkDense = FALSE) { if(!checkDense & (isDense <- extends(cl, "denseMatrix"))) ..diagN2U(as(x, "CsparseMatrix"), sparse = TRUE) else ..diagN2U(x, sparse = !isDense) } ..diagN2U <- function(x, sparse) { if(sparse && x@Dim[1L] > 0L) x <- switch(x@uplo, U = .Call(R_sparse_band, x, 1L, NULL), L = .Call(R_sparse_band, x, NULL, -1L)) x@diag <- "U" x } ## Caches 'value' in the 'factors' slot of 'x' { NOT a copy of 'x' ! } ## and returns 'value' .set.factor <- function(x, name, value, warn.no.slot = FALSE) .Call(R_set_factor, x, name, value, warn.no.slot) ##' Compute the three "parts" of two sets: .setparts <- function(x, y) { n1 <- length(m1 <- match(x, y, 0L)) n2 <- length(m2 <- match(y, x, 0L)) ix <- which(m1 == 0L) iy <- which(m2 == 0L) list(x.only = x[ix], ix.only = ix, mx = m1, y.only = y[iy], iy.only = iy, my = m2, int = if(n1 < n2) y[m1] else x[m2]) } ##' *Only* to be used as function in ##' setMethod.("Compare", ...., .Cmp.swap) --> ./Ops.R & ./diagMatrix.R .Cmp.swap <- function(e1, e2) { ## "swap RHS and LHS" and use the method below: switch(.Generic, "==" =, "!=" = callGeneric(e2, e1), "<" = e2 > e1, "<=" = e2 >= e1, ">" = e2 < e1, ">=" = e2 <= e1) } .diag.dsC <- function(x, Chx = Cholesky(x, LDL = TRUE), res.kind = "diag") { if(!missing(Chx)) stopifnot(.CHM.is.LDL(Chx), is.integer(Chx@p), is.double(Chx@x)) .Call(dtCMatrix_diag, Chx, res.kind) ## ^^^^^^^^^^^^^^ in ../src/Csparse.c } dimScale <- function(x, d1 = sqrt(1/diag(x, names = FALSE)), d2 = d1) { dim.x <- dim(x) D1 <- Diagonal(n = dim.x[1L], x = d1) D2 <- if(missing(d2)) D1 else Diagonal(n = dim.x[2L], x = d2) y <- D1 %*% x %*% D2 # inefficient for symmetricMatrix 'x', but "general" if(isS4(x) && is(x, "symmetricMatrix") && identical(d1, d2)) y <- forceSymmetric(y, x@uplo) if(is.list(dn <- dimnames(x))) y@Dimnames <- dn y } rowScale <- function(x, d) { y <- Diagonal(n = nrow(x), x = d) %*% x if(is.list(dn <- dimnames(x))) y@Dimnames <- dn y } colScale <- function(x, d) { y <- x %*% Diagonal(n = ncol(x), x = d) if(is.list(dn <- dimnames(x))) y@Dimnames <- dn y } Matrix/R/colSums.R0000644000175100001440000001230514561451364013517 0ustar hornikusers## METHODS FOR GENERIC: colSums, rowSums, colMeans, rowMeans ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## ==== denseMatrix ==================================================== setMethod("colSums", c(x = "denseMatrix"), function(x, na.rm = FALSE, dims = 1L, ...) .Call(R_dense_marginsum, x, 1L, na.rm, FALSE)) setMethod("colMeans", c(x = "denseMatrix"), function(x, na.rm = FALSE, dims = 1L, ...) .Call(R_dense_marginsum, x, 1L, na.rm, TRUE)) setMethod("rowSums", c(x = "denseMatrix"), function(x, na.rm = FALSE, dims = 1L, ...) .Call(R_dense_marginsum, x, 0L, na.rm, FALSE)) setMethod("rowMeans", c(x = "denseMatrix"), function(x, na.rm = FALSE, dims = 1L, ...) .Call(R_dense_marginsum, x, 0L, na.rm, TRUE)) ## ==== sparseMatrix =================================================== ## ---- [CRT]sparseMatrix ---------------------------------------------- for (.cl in paste0(c("C", "R", "T"), "sparseMatrix")) { setMethod("colSums", c(x = .cl), function(x, na.rm = FALSE, dims = 1L, sparseResult = FALSE, ...) .Call(R_sparse_marginsum, x, 1L, na.rm, FALSE, sparseResult)) setMethod("colMeans", c(x = .cl), function(x, na.rm = FALSE, dims = 1L, sparseResult = FALSE, ...) .Call(R_sparse_marginsum, x, 1L, na.rm, TRUE, sparseResult)) setMethod("rowSums", c(x = .cl), function(x, na.rm = FALSE, dims = 1L, sparseResult = FALSE, ...) .Call(R_sparse_marginsum, x, 0L, na.rm, FALSE, sparseResult)) setMethod("rowMeans", c(x = .cl), function(x, na.rm = FALSE, dims = 1L, sparseResult = FALSE, ...) .Call(R_sparse_marginsum, x, 0L, na.rm, TRUE, sparseResult)) } rm(.cl) ## ---- diagonalMatrix ------------------------------------------------- .diag.cS <- .diag.rS <- function(x, na.rm = FALSE, dims = 1L, ...) { kind <- .M.kind(x) if((n <- x@Dim[1L]) == 0L) return(vector(switch(kind, "z" = "complex", "d" = , "i" = "double", "integer"), 0L)) else if(x@diag != "N") r <- rep.int(switch(kind, "z" = 1+0i, "d" = , "i" = 1, 1L), n) else { r <- switch(kind, "z" = , "d" = x@x, "i" = as.double(x@x), as.integer(x@x)) if((na.rm || kind == "n") && anyNA(r)) r[is.na(r)] <- switch(kind, "z" = 0+0i, "d" = , "i" = 0, "n" = 1L, 0L) } if(!is.null(nms <- x@Dimnames[[.MARGIN]])) names(r) <- nms r } body(.diag.cS) <- do.call(substitute, list(body(.diag.cS), list(.MARGIN = 2L))) body(.diag.rS) <- do.call(substitute, list(body(.diag.rS), list(.MARGIN = 1L))) .diag.cM <- .diag.rM <- function(x, na.rm = FALSE, dims = 1L, ...) { kind <- .M.kind(x) if((n <- x@Dim[1L]) == 0L) return(vector(switch(kind, "z" = "complex", "double"), 0L)) else if(x@diag != "N") r <- rep.int(switch(kind, "z" = 1+0i, 1) / n, n) else { r <- x@x / n if((na.rm || kind == "n") && anyNA(r)) r[is.na(r)] <- switch(kind, "z" = if(n == 1L) NaN * (0+0i) else 0+0i, "n" = 1 / n, if(n == 1L) NaN else 0) } if(!is.null(nms <- x@Dimnames[[.MARGIN]])) names(r) <- nms r } body(.diag.cM) <- do.call(substitute, list(body(.diag.cM), list(.MARGIN = 2L))) body(.diag.rM) <- do.call(substitute, list(body(.diag.rM), list(.MARGIN = 1L))) setMethod("colSums", c(x = "diagonalMatrix"), .diag.cS) setMethod("colMeans", c(x = "diagonalMatrix"), .diag.cM) setMethod("rowSums", c(x = "diagonalMatrix"), .diag.rS) setMethod("rowMeans", c(x = "diagonalMatrix"), .diag.rM) rm(.diag.cS, .diag.cM, .diag.rS, .diag.rM) ## ---- indMatrix (incl. pMatrix) -------------------------------------- setMethod("colSums", c(x = "indMatrix"), function(x, na.rm = FALSE, dims = 1L, ...) { n <- x@Dim[2L] r <- if(x@margin == 1L) tabulate(x@perm, n) else rep.int(1L, n) if(!is.null(nms <- x@Dimnames[[2L]])) names(r) <- nms r }) setMethod("colMeans", c(x = "indMatrix"), function(x, na.rm = FALSE, dims = 1L, ...) { n <- (d <- x@Dim)[2L] r <- if(x@margin == 1L) tabulate(x@perm, n) / d[1L] else rep.int(1 / d[1L], n) if(!is.null(nms <- x@Dimnames[[2L]])) names(r) <- nms r }) setMethod("rowSums", c(x = "indMatrix"), function(x, na.rm = FALSE, dims = 1L, ...) { m <- x@Dim[1L] r <- if(x@margin == 1L) rep.int(1L, m) else tabulate(x@perm, m) if(!is.null(nms <- x@Dimnames[[1L]])) names(r) <- nms r }) setMethod("rowMeans", c(x = "indMatrix"), function(x, na.rm = FALSE, dims = 1L, ...) { m <- (d <- x@Dim)[1L] r <- if(x@margin == 1L) rep.int(1 / d[2L], m) else tabulate(x@perm, m) / d[2L] if(!is.null(nms <- x@Dimnames[[1L]])) names(r) <- nms r }) Matrix/R/which.R0000644000175100001440000000426014561451364013175 0ustar hornikusers## METHODS FOR GENERIC: which ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("which", c(x = "ndenseMatrix"), function(x, arr.ind = FALSE, useNames = TRUE) { wh <- which(.M2v(x)) if(arr.ind) arrayInd(wh, x@Dim, dimnames(x), useNames = useNames) else wh }) setMethod("which", c(x = "ldenseMatrix"), function(x, arr.ind = FALSE, useNames = TRUE) { wh <- which(.M2v(x)) if(arr.ind) arrayInd(wh, x@Dim, dimnames(x), useNames = useNames) else wh }) setMethod("which", c(x = "nsparseMatrix"), function(x, arr.ind = FALSE, useNames = TRUE) { wh <- .M2V(x)@i if(arr.ind) arrayInd(wh, x@Dim, dimnames(x), useNames = useNames) else wh }) setMethod("which", c(x = "lsparseMatrix"), function(x, arr.ind = FALSE, useNames = TRUE) { wh <- { x. <- .M2V(x); x.@i[which(x.@x)] } if(arr.ind) arrayInd(wh, x@Dim, dimnames(x), useNames = useNames) else wh }) setMethod("which", c(x = "ndiMatrix"), function(x, arr.ind = FALSE, useNames = TRUE) { wh <- .M2V(x)@i if(arr.ind) arrayInd(wh, x@Dim, x@Dimnames, useNames = useNames) else wh }) setMethod("which", c(x = "ldiMatrix"), function(x, arr.ind = FALSE, useNames = TRUE) { wh <- { x. <- .M2V(x); x.@i[which(x.@x)] } if(arr.ind) arrayInd(wh, x@Dim, x@Dimnames, useNames = useNames) else wh }) setMethod("which", c(x = "nsparseVector"), function(x, arr.ind = FALSE, useNames = TRUE) x@i) setMethod("which", c(x = "lsparseVector"), function(x, arr.ind = FALSE, useNames = TRUE) x@i[which(x@x)]) setMethod("which", c(x = "indMatrix"), function(x, arr.ind = FALSE, useNames = TRUE) { wh <- .M2V(x)@i if(arr.ind) arrayInd(wh, x@Dim, x@Dimnames, useNames = useNames) else wh }) Matrix/R/determinant.R0000644000175100001440000001672614561451364014417 0ustar hornikusers## METHODS FOR GENERIC: determinant ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## Constructor for "det" objects, used liberally below .mkDet <- function(modulus = sum(log(abs(x))), logarithm = TRUE, sign = if(prod(base::sign(x)) < 0) -1L else 1L, x) { if(!logarithm) modulus <- exp(modulus) attr(modulus, "logarithm") <- logarithm val <- list(modulus = modulus, sign = sign) class(val) <- "det" val } ## 'base::det' calls 'base::determinant', which is not S4 generic, ## so we define own our 'det' calling 'Matrix::determinant' ... det <- base::det environment(det) <- environment() # the Matrix namespace ######################################################################## ## 1. MatrixFactorization ######################################################################## setMethod("determinant", c(x = "MatrixFactorization", logarithm = "missing"), function(x, logarithm = TRUE, ...) determinant(x, TRUE, ...)) ## FIXME: if we knew the specific class of 'T', then we could optimize ## knowing that 'T' is block upper triangular with 1-by-1 and 2-by-2 ## diagonal blocks setMethod("determinant", c(x = "Schur", logarithm = "logical"), function(x, logarithm = TRUE, ...) determinant(x@T, logarithm, ...)) setMethod("determinant", c(x = "denseLU", logarithm = "logical"), function(x, logarithm = TRUE, ...) .Call(denseLU_determinant, x, logarithm)) setMethod("determinant", c(x = "sparseLU", logarithm = "logical"), function(x, logarithm = TRUE, ...) .Call(sparseLU_determinant, x, logarithm)) setMethod("determinant", c(x = "sparseQR", logarithm = "logical"), function(x, logarithm = TRUE, ...) .Call(sparseQR_determinant, x, logarithm)) for(.cl in c("BunchKaufman", "pBunchKaufman")) setMethod("determinant", c(x = .cl, logarithm = "logical"), function(x, logarithm = TRUE, ...) .Call(BunchKaufman_determinant, x, logarithm)) rm(.cl) for(.cl in c("Cholesky", "pCholesky")) setMethod("determinant", c(x = .cl, logarithm = "logical"), function(x, logarithm = TRUE, ...) .Call(Cholesky_determinant, x, logarithm)) rm(.cl) setMethod("determinant", c(x = "CHMfactor", logarithm = "logical"), function(x, logarithm = TRUE, sqrt = TRUE, ...) { if(missing(sqrt)) { w <- getOption("Matrix.warnSqrtDefault", .MatrixEnv[["warnSqrtDefault"]]) if(is.atomic(w) && length(w) == 1L && ((w.na <- is.na(w <- as.integer(w))) || w > 0L)) { if(w.na) on.exit(options(Matrix.warnSqrtDefault = 0L)) else if(w > 1L) { oop <- options(warn = 2L) on.exit(options(oop)) } warning(gettextf("the default value of argument '%s' of method '%s(<%s>, <%s>)' may change from %s to %s as soon as the next release of Matrix; set '%s' when programming", "sqrt", "determinant", "CHMfactor", "logical", "TRUE", "FALSE", "sqrt"), domain = NA) } } .Call(CHMfactor_determinant, x, logarithm, sqrt) }) ######################################################################## ## 2. Matrix ######################################################################## setMethod("determinant", c(x = "Matrix", logarithm = "missing"), function(x, logarithm = TRUE, ...) determinant(x, TRUE, ...)) setMethod("determinant", c(x = "Matrix", logarithm = "logical"), function(x, logarithm = TRUE, ...) determinant(.M2kind(x, ","), logarithm, ...)) ## .... GENERAL ........................................................ setMethod("determinant", c(x = "dgeMatrix", logarithm = "logical"), function(x, logarithm = TRUE, ...) { d <- x@Dim if(d[1L] != d[2L]) stop("determinant of non-square matrix is undefined") trf <- lu(x, warnSing = FALSE) determinant(trf, logarithm, ...) }) setMethod("determinant", c(x = "dgCMatrix", logarithm = "logical"), function(x, logarithm = TRUE, ...) { d <- x@Dim if(d[1L] != d[2L]) stop("determinant of non-square matrix is undefined") trf <- lu(x, errSing = FALSE) if(isS4(trf)) determinant(trf, logarithm, ...) else .mkDet(if(anyNA(x@x)) NaN else -Inf, logarithm, 1L) }) setMethod("determinant", c(x = "dgRMatrix", logarithm = "logical"), function(x, logarithm = TRUE, ...) determinant(.tCRT(x), logarithm, ...)) setMethod("determinant", c(x = "dgTMatrix", logarithm = "logical"), function(x, logarithm = TRUE, ...) determinant(.M2C(x), logarithm, ...)) setMethod("determinant", c(x = "indMatrix", logarithm = "logical"), function(x, logarithm = TRUE, ...) { d <- x@Dim if(d[1L] != d[2L]) stop("determinant of non-square matrix is undefined") if(anyDuplicated.default(perm <- x@perm)) .mkDet(-Inf, logarithm, 1L) else .mkDet(0, logarithm, signPerm(perm)) }) setMethod("determinant", c(x = "pMatrix", logarithm = "logical"), function(x, logarithm = TRUE, ...) .mkDet(0, logarithm, signPerm(x@perm))) ## .... SYMMETRIC ...................................................... for(.cl in c("dsyMatrix", "dspMatrix")) setMethod("determinant", c(x = .cl, logarithm = "logical"), function(x, logarithm = TRUE, ...) { trf <- BunchKaufman(x, warnSing = FALSE) determinant(trf, logarithm, ...) }) rm(.cl) for(.cl in c("dpoMatrix", "dppMatrix")) setMethod("determinant", c(x = .cl, logarithm = "logical"), function(x, logarithm = TRUE, ...) { trf <- tryCatch( Cholesky(x, perm = FALSE), error = function(e) BunchKaufman(x, warnSing = FALSE)) determinant(trf, logarithm, ...) }) rm(.cl) setMethod("determinant", c(x = "dsCMatrix", logarithm = "logical"), function(x, logarithm = TRUE, ...) { trf <- tryCatch( Cholesky(x, perm = TRUE, LDL = TRUE, super = FALSE), error = function(e) lu(x, errSing = FALSE)) if(isS4(trf)) determinant(trf, logarithm, sqrt = FALSE, ...) else .mkDet(if(anyNA(x@x)) NaN else -Inf, logarithm, 1L) }) setMethod("determinant", c(x = "dsRMatrix", logarithm = "logical"), function(x, logarithm = TRUE, ...) determinant(.tCRT(x), logarithm, ...)) setMethod("determinant", c(x = "dsTMatrix", logarithm = "logical"), function(x, logarithm = TRUE, ...) determinant(.M2C(x), logarithm, ...)) ## .... TRIANGULAR ..................................................... for(.cl in c("triangularMatrix", "diagonalMatrix")) setMethod("determinant", c(x = .cl, logarithm = "logical"), function(x, logarithm = TRUE, ...) if(x@diag == "N") .mkDet(x = diag(x, names = FALSE), logarithm = logarithm) else .mkDet(0, logarithm, 1L)) rm(.cl) Matrix/R/expm.R0000644000175100001440000000407614574651323013052 0ustar hornikusers## METHODS FOR GENERIC: expm ## the matrix exponential ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## MJ: currently going via ddiMatrix or dgeMatrix in all cases setMethod("expm", c(x = "Matrix"), function(x) { d <- x@Dim if(d[1L] != d[2L]) stop("matrix is not square") expm(.M2kind(x, "d")) }) setMethod("expm", c(x = "dsparseMatrix"), function(x) { d <- x@Dim if(d[1L] != d[2L]) stop("matrix is not square") expm(.sparse2dense(x)) }) setMethod("expm", c(x = "ddiMatrix"), function(x) { if(x@diag == "N") { x@x <- exp(x@x) } else { x@diag <- "N" x@x <- rep.int(exp(1), x@Dim[1L]) } x }) setMethod("expm", c(x = "dgeMatrix"), function(x) .Call(dgeMatrix_expm, x)) setMethod("expm", c(x = "dtrMatrix"), function(x) { r <- .Call(dgeMatrix_expm, .M2gen(x)) if(x@uplo == "U") triu(r) else tril(r) }) setMethod("expm", c(x = "dtpMatrix"), function(x) { r <- .Call(dgeMatrix_expm, .M2gen(x)) ## Pack without checking: .Call(R_dense_as_packed, r, x@uplo, "N") }) setMethod("expm", c(x = "dsyMatrix"), function(x) { r <- .Call(dgeMatrix_expm, .M2gen(x)) forceSymmetric(r) }) setMethod("expm", c(x = "dspMatrix"), function(x) { r <- .Call(dgeMatrix_expm, .M2gen(x)) ## Pack without checking: .Call(R_dense_as_packed, r, x@uplo, NULL) }) ## Until R supports it: setMethod("expm", c(x = "matrix"), function(x) { d <- dim(x) if(d[1L] != d[2L]) stop("matrix is not square") storage.mode(x) <- "double" expm(if(isDiagonal(x)) forceDiagonal(x) else .m2dense(x, ".ge")) }) Matrix/R/cbind2.R0000644000175100001440000000632114575137654013244 0ustar hornikusers## METHODS FOR GENERIC: c ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c.Matrix <- function(...) { if(nargs() == 0L) return(NULL) args <- lapply(list(...), as.vector) unlist(args, FALSE, TRUE) } c.sparseVector <- function(...) { N <- nargs() if(N == 0L) return(NULL) args <- lapply(list(...), as, "sparseVector") args.length <- vapply(args, slot, 0, "length") args.i <- lapply(args, slot, "i") args.nnz <- lengths(args.i, FALSE) s <- c("n", "l", "i", "d", "z") i <- match(vapply(args, .M.kind, ""), s) k <- range(i) n <- sum(args.length) a <- if(n - 1 <= .Machine$integer.max) as.integer else as.double r <- new(paste0(s[k[2L]], "sparseVector")) r@length <- a(n) r@i <- a(unlist(args.i, FALSE, FALSE)) + rep.int(cumsum(c(0L, a(args.length)[-N])), args.nnz) if(k[2L] > 1L) { if(k[1L] > 1L) args.x <- lapply(args, slot, "x") else { pattern <- i == 1L args.x <- vector("list", N) args.x[!pattern] <- lapply(args [!pattern], slot, "x") args.x[ pattern] <- lapply(args.nnz[ pattern], rep.int, x = TRUE) } r@x <- unlist(args.x, FALSE, FALSE) } r } ## These are insufficient as dispatch only consides the first argument, ## which need not be a Matrix or sparseVector: if(FALSE) { setMethod("c", c(x = "Matrix"), function(x, ...) c.Matrix (x, ...)) setMethod("c", c(x = "sparseVector"), function(x, ...) c.sparseVector(x, ...)) } ## METHODS FOR GENERIC: cbind, rbind ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## MJ: not yet registered or exported cbind.Matrix <- function(..., deparse.level = 1) .External(R_bind, deparse.level, 1L, substitute(list(...)), ...) rbind.Matrix <- function(..., deparse.level = 1) .External(R_bind, deparse.level, 0L, substitute(list(...)), ...) ## METHODS FOR GENERIC: cbind2, rbind2 ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .cbind2 <- function(x, y, ...) cbind.Matrix(x, y, deparse.level = 0L) .rbind2 <- function(x, y, ...) rbind.Matrix(x, y, deparse.level = 0L) setMethod("cbind2", c(x = "Matrix", y = "missing"), function(x, y, ...) x) setMethod("rbind2", c(x = "Matrix", y = "missing"), function(x, y, ...) x) setMethod("cbind2", c(x = "Matrix", y = "NULL"), .cbind2) setMethod("cbind2", c(x = "NULL", y = "Matrix"), .cbind2) setMethod("rbind2", c(x = "Matrix", y = "NULL"), .rbind2) setMethod("rbind2", c(x = "NULL", y = "Matrix"), .rbind2) setMethod("cbind2", c(x = "Matrix", y = "vector"), .cbind2) setMethod("cbind2", c(x = "vector", y = "Matrix"), .cbind2) setMethod("rbind2", c(x = "Matrix", y = "vector"), .rbind2) setMethod("rbind2", c(x = "vector", y = "Matrix"), .rbind2) setMethod("cbind2", c(x = "Matrix", y = "matrix"), .cbind2) setMethod("cbind2", c(x = "matrix", y = "Matrix"), .cbind2) setMethod("rbind2", c(x = "Matrix", y = "matrix"), .rbind2) setMethod("rbind2", c(x = "matrix", y = "Matrix"), .rbind2) setMethod("cbind2", c(x = "Matrix", y = "Matrix"), .cbind2) setMethod("rbind2", c(x = "Matrix", y = "Matrix"), .rbind2) rm(.cbind2, .rbind2) Matrix/R/kappa.R0000644000175100001440000002701114574054152013164 0ustar hornikusers## METHODS FOR GENERIC: norm ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("norm", c(x = "ANY", type = "missing"), function(x, type, ...) norm(x, type = "O", ...)) setMethod("norm", c(x = "denseMatrix", type = "character"), function(x, type, ...) { if(identical(type, "2")) return(base::norm(.M2m(x), type = "2")) x <- .M2kind(x, ",") switch(substr(.M.nonvirtual(x), 2L, 3L), "ge" = .Call(dgeMatrix_norm, x, type), "sy" = .Call(dsyMatrix_norm, x, type), "sp" = .Call(dspMatrix_norm, x, type), "tr" = .Call(dtrMatrix_norm, x, type), "tp" = .Call(dtpMatrix_norm, x, type)) }) setMethod("norm", c(x = "sparseMatrix", type = "character"), function(x, type, ...) { if(any(x@Dim == 0L)) return(0) switch(EXPR = type[1L], "O" = , "o" = , "1" = max(colSums(abs(x))), "I" = , "i" = max(rowSums(abs(x))), "2" = { warning(gettextf("'%s' via sparse -> dense coercion", "norm"), domain = NA) base::norm(.M2m(x), type = "2") }, "M" = , "m" = max(abs(x)), "F" = , "f" = , "E" = , "e" = { if(.M.kind(x) == "z") x <- abs(x) sqrt(sum(x * x)) }, stop(gettextf("invalid %s=\"%s\"", "type", type[1L]), domain = NA)) }) setMethod("norm", c(x = "diagonalMatrix", type = "character"), function(x, type, ...) { if((n <- x@Dim[1L]) == 0L) return(0) if(nonunit <- x@diag == "N") { y <- x@x if(.M.kind(x) == "n" && anyNA(y)) y <- y | is.na(y) } switch(EXPR = type[1L], "O" = , "o" = , "1" = , "I" = , "i" = , "2" = , "M" = , "m" = if(nonunit) max(abs(y)) else 1, "F" = , "f" = , "E" = , "e" = if(nonunit) { if(is.complex(y)) y <- abs(y) sqrt(sum(y * y)) } else sqrt(n), stop(gettextf("invalid %s=\"%s\"", "type", type[1L]), domain = NA)) }) setMethod("norm", c(x = "indMatrix", type = "character"), function(x, type, ...) { d <- x@Dim if((m <- d[1L]) == 0L || (n <- d[2L]) == 0L) return(0) switch(EXPR = type[1L], "O" = , "o" = , "1" = if(x@margin == 1L) max(tabulate(x@perm, n)) else 1, "I" = , "i" = if(x@margin == 1L) 1 else max(tabulate(x@perm, m)), "2" = sqrt(max(tabulate(x@perm, if(x@margin == 1L) n else m))), "M" = , "m" = 1, "F" = , "f" = , "E" = , "e" = if(x@margin == 1L) sqrt(m) else sqrt(n), stop(gettextf("invalid %s=\"%s\"", "type", type[1L]), domain = NA)) }) setMethod("norm", c(x = "pMatrix", type = "character"), function(x, type, ...) { if((n <- x@Dim[1L]) == 0L) return(0) switch(EXPR = type[1L], "O" = , "o" = , "1" = , "I" = , "i" = , "2" = , "M" = , "m" = 1, "F" = , "f" = , "E" = , "e" = sqrt(n), stop(gettextf("invalid %s=\"%s\"", "type", type[1L]), domain = NA)) }) ## METHODS FOR GENERIC: rcond ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("rcond", c(x = "ANY", norm = "missing"), function(x, norm, ...) rcond(x, norm = "O", ...)) setMethod("rcond", c(x = "denseMatrix", norm = "character"), function(x, norm, ...) { x <- .M2kind(x, ",") switch(substr(.M.nonvirtual(x, strict = TRUE), 2L, 3L), "ge" = { d <- x@Dim m <- d[1L] n <- d[2L] if(m == n) { trf <- lu(x, warnSing = FALSE) .Call(dgeMatrix_rcond, x, trf, norm) } else { ## MJ: norm(A = P1' Q R P2') = norm(R) holds ## in general only for norm == "2", but ## La_rcond_type() disallows norm == "2" ## ... FIXME ?? if(m < n) { x <- t(x) n <- m } R <- triu(qr(x)[["qr"]][seq_len(n), , drop = FALSE]) rcond(R, norm = norm, ...) } }, "sy" = { trf <- BunchKaufman(x, warnSing = FALSE) .Call(dsyMatrix_rcond, x, trf, norm) }, "sp" = { trf <- BunchKaufman(x, warnSing = FALSE) .Call(dspMatrix_rcond, x, trf, norm) }, "po" = , "or" = # corMatrix { ok <- TRUE trf <- tryCatch( Cholesky(x, perm = FALSE), error = function(e) { ok <<- FALSE BunchKaufman(x, warnSing = FALSE) }) if(ok) .Call(dpoMatrix_rcond, x, trf, norm) else .Call(dsyMatrix_rcond, x, trf, norm) }, "pp" = , "op" = # copMatrix { ok <- TRUE trf <- tryCatch( Cholesky(x, perm = FALSE), error = function(e) { ok <<- FALSE BunchKaufman(x, warnSing = FALSE) }) if(ok) .Call(dppMatrix_rcond, x, trf, norm) else .Call(dspMatrix_rcond, x, trf, norm) }, "tr" = .Call(dtrMatrix_rcond, x, norm), "tp" = .Call(dtpMatrix_rcond, x, norm)) }) setMethod("rcond", c(x = "sparseMatrix", norm = "character"), function(x, norm, useInv = FALSE, ...) { d <- x@Dim if((m <- d[1L]) == 0L || (n <- d[2L]) == 0L) return(Inf) if(m == n) { if(isS4(useInv) || useInv) { if(!isS4(useInv)) useInv <- solve(x) 1 / (norm(x, type = norm) * norm(useInv, type = norm)) } else { warning(gettextf("'%s' via sparse -> dense coercion", "rcond"), domain = NA) rcond(.M2unpacked(x), norm = norm, ...) } } else { ## MJ: norm(A = P1' Q R P2') = norm(R) holds in general ## only for norm == "2", but La_rcond_type() disallows ## norm == "2" ... FIXME ?? if(m < n) { x <- t(x) n <- m } R <- triu(qr(x)@R[seq_len(n), , drop = FALSE]) rcond(R, norm = norm, ...) } }) setMethod("rcond", c(x = "diagonalMatrix", norm = "character"), function(x, norm, ...) { if((n <- x@Dim[1L]) == 0L) return(Inf) if(nonunit <- x@diag == "N") { y <- x@x if(.M.kind(x) == "n" && anyNA(y)) y <- y | is.na(y) } switch(EXPR = norm[1L], "O" = , "o" = , "1" = , "I" = , "i" = , "2" = , "M" = , "m" = if(nonunit) { ry <- range(abs(y)) ry[1L] / ry[2L] } else 1, "F" = , "f" = , "E" = , "e" = if(nonunit) { if(is.complex(y)) y <- abs(y) yy <- y * y 1 / sqrt(sum(yy) * sum(1 / yy)) } else 1 / n, stop(gettext("invalid %s=\"%s\"", "norm", norm[1L]), domain = NA)) }) setMethod("rcond", c(x = "indMatrix", norm = "character"), function(x, norm, ...) { d <- x@Dim if((m <- d[1L]) == 0L || (n <- d[2L]) == 0L) return(Inf) if (m == n) { if(anyDuplicated.default(x@perm)) return(0) switch(EXPR = norm[1L], "O" = , "o" = , "1" = , "I" = , "i" = , "2" = , "M" = , "m" = 1, "F" = , "f" = , "E" = , "e" = 1 / n, stop(gettext("invalid %s=\"%s\"", "norm", norm[1L]), domain = NA)) } else { if(m < n) { x <- t(x) n <- m } R <- triu(qr(x)@R[seq_len(n), , drop = FALSE]) rcond(R, norm = norm, ...) } }) setMethod("rcond", c(x = "pMatrix", norm = "character"), function(x, norm, ...) { if((n <- x@Dim[1L]) == 0L) return(Inf) switch(EXPR = norm[1L], "O" = , "o" = , "1" = , "I" = , "i" = , "2" = , "M" = , "m" = 1, "F" = , "f" = , "E" = , "e" = 1 / n, stop(gettext("invalid %s=\"%s\"", "norm", norm[1L]), domain = NA)) }) Matrix/R/Math.R0000644000175100001440000002475114574054462012775 0ustar hornikusers## METHODS FOR GENERIC: Math (group) ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## > getGroupMembers("Math") ## [1] "abs" "sign" "sqrt" "ceiling" "floor" "trunc" ## [7] "cummax" "cummin" "cumprod" "cumsum" "exp" "expm1" ## [13] "log" "log10" "log2" "log1p" "cos" "cosh" ## [19] "sin" "sinh" "tan" "tanh" "acos" "acosh" ## [25] "asin" "asinh" "atan" "atanh" "cospi" "sinpi" ## [31] "tanpi" "gamma" "lgamma" "digamma" "trigamma" setMethod("Math", c(x = "denseMatrix"), function(x) { g <- get(.Generic, mode = "function") if(startsWith(.Generic, "cum")) return(g(.M2v(x))) cl <- .M.nonvirtual(x) kind <- substr(cl, 1L, 1L) shape <- substr(cl, 2L, 2L) if (kind == "z") { zero <- 0+0i; one <- 1+0i; a <- as.complex } else { zero <- 0 ; one <- 1 ; a <- as.double substr(cl, 1L, 1L) <- "d" } if(shape == "t") { stay0 <- is0(a(g(zero))) if(!stay0) { x <- .M2gen(x) substr(cl, 2L, 3L) <- "ge" } } r <- new(cl) r@Dim <- x@Dim r@Dimnames <- x@Dimnames if(shape == "s" || (shape == "t" && stay0)) r@uplo <- x@uplo r@x <- a(g({ y <- x@x; if(kind == "n") y | is.na(y) else y })) if(shape == "t" && stay0 && x@diag != "N") { if(is1(g1 <- a(g(one)))) r@diag <- "U" else diag(r) <- g1 } r }) setMethod("log", c(x = "denseMatrix"), function(x, ...) { cl <- .M.nonvirtual(x) kind <- substr(cl, 1L, 1L) shape <- substr(cl, 2L, 2L) if(kind != "z") substr(cl, 1L, 1L) <- "d" if(shape == "t") { x <- .M2gen(x) substr(cl, 2L, 3L) <- "ge" } r <- new(cl) r@Dim <- x@Dim r@Dimnames <- x@Dimnames if(shape == "s") r@uplo <- x@uplo r@x <- log({ y <- x@x; if(kind == "n") y | is.na(y) else y }, ...) r }) setMethod("Math", c(x = "sparseMatrix"), function(x) { g <- get(.Generic, mode = "function") if(startsWith(.Generic, "cum")) return(g(.M2v(x))) cl <- .M.nonvirtual(x) kind <- substr(cl, 1L, 1L) shape <- substr(cl, 2L, 2L) repr <- substr(cl, 3L, 3L) if (kind == "z") { zero <- 0+0i; one <- 1+0i; a <- as.complex } else { zero <- 0 ; one <- 1 ; a <- as.double substr(cl, 1L, 1L) <- "d" } stay0 <- is0(g0 <- a(g(zero))) if(!stay0) substr(cl, 2L, 3L) <- if(shape == "s") "sy" else "ge" r <- new(cl) r@Dim <- x@Dim r@Dimnames <- x@Dimnames if(shape == "s" || (shape == "t" && stay0)) r@uplo <- x@uplo if(!stay0) { y <- .Call(CR2spV, if(repr == "T") .M2C(x) else x) tmp <- rep.int(g0, y@length) tmp[y@i] <- a(g(if(kind == "n") one else y@x)) r@x <- tmp } else { if(shape == "t" && x@diag != "N") { if(is1(a(g(one)))) r@diag <- "U" else diag(x) <- TRUE } nnz <- length( switch(repr, "C" = { r@p <- x@p; r@i <- x@i }, "R" = { r@p <- x@p; r@j <- x@j }, "T" = { r@i <- x@i; r@j <- x@j })) r@x <- if(kind == "n") rep.int(a(g(one)), nnz) else a(g(x@x)) } r }) setMethod("log", c(x = "sparseMatrix"), function(x, ...) { cl <- .M.nonvirtual(x) kind <- substr(cl, 1L, 1L) shape <- substr(cl, 2L, 2L) repr <- substr(cl, 3L, 3L) if(kind == "z") { zero <- 0+0i; one <- 1+0i } else { zero <- 0 ; one <- 1 substr(cl, 1L, 1L) <- "d" } substr(cl, 2L, 3L) <- if(shape == "s") "sy" else "ge" r <- new(cl) r@Dim <- x@Dim r@Dimnames <- x@Dimnames if(shape == "s") r@uplo <- x@uplo y <- .Call(CR2spV, if(repr == "T") .M2C(x) else x) tmp <- rep.int(log(zero, ...), y@length) tmp[y@i] <- log(if(kind == "n") one else y@x, ...) r@x <- tmp r }) setMethod("Math", c(x = "diagonalMatrix"), function(x) { g <- get(.Generic, mode = "function") if(startsWith(.Generic, "cum")) return(g(.M2v(x))) cl <- .M.nonvirtual(x) kind <- substr(cl, 1L, 1L) if (kind == "z") { zero <- 0+0i; one <- 1+0i; a <- as.complex } else { zero <- 0 ; one <- 1 ; a <- as.double substr(cl, 1L, 1L) <- "d" } stay0 <- is0(g0 <- a(g(zero))) if(!stay0) substr(cl, 2L, 3L) <- "ge" r <- new(cl) r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames if(!stay0) { if((n <- d[2L]) > 0L) { tmp <- matrix(g0, n, n) diag(tmp) <- a(g(if(x@diag != "N") one else { y <- x@x; if(kind == "n" && anyNA(y)) y | is.na(y) else y })) dim(tmp) <- NULL r@x <- tmp } } else { if(x@diag != "N") { if(is1(g1 <- a(g(one)))) r@diag <- "U" else r@x <- rep.int(g1, d[1L]) } else r@x <- a(g({ y <- x@x; if(kind == "n" && anyNA(y)) y | is.na(y) else y })) } r }) setMethod("log", c(x = "diagonalMatrix"), function(x, ...) { cl <- .M.nonvirtual(x) kind <- substr(cl, 1L, 1L) if(kind == "z") { zero <- 0+0i; one <- 1+0i } else { zero <- 0 ; one <- 1 substr(cl, 1L, 1L) <- "d" } substr(cl, 2L, 3L) <- "ge" r <- new(cl) r@Dim <- d <- x@Dim r@Dimnames <- x@Dimnames if((n <- d[2L]) > 0L) { tmp <- matrix(log(zero, ...), n, n) diag(tmp) <- log(if(x@diag != "N") one else { y <- x@x; if(kind == "n" && anyNA(y)) y | is.na(y) else y }, ...) dim(tmp) <- NULL r@x <- tmp } r }) setMethod("Math", c(x = "indMatrix"), function(x) get(.Generic, mode = "function")(.M2kind(x, "n"))) setMethod("log", c(x = "indMatrix"), function(x, ...) log(.M2kind(x, "n"), ...)) setMethod("Math", c(x = "sparseVector"), function(x) { g <- get(.Generic, mode = "function") if(startsWith(.Generic, "cum")) return(g(.V2v(x))) kind <- .M.kind(x) if(kind == "z") { zero <- 0+0i; one <- 1+0i; l <- "z" } else if(kind == "d" || .Generic != "abs") { zero <- 0 ; one <- 1 ; l <- "d" } else { zero <- 0L ; one <- 1L ; l <- "i" } if(isN0(g0 <- g(zero))) { r <- rep.int(g0, x@length) if((nnz <- length(x@i)) > 0L) r[x@i] <- if(kind == "n") rep.int(g(one), nnz) else g(x@x) } else { r <- new(paste0(l, "sparseVector")) r@length <- x@length r@i <- x@i if((nnz <- length(x@i)) > 0L) r@x <- if(kind == "n") rep.int(g(one), nnz) else g(x@x) } r }) setMethod("log", c(x = "sparseVector"), function(x, ...) { kind <- .M.kind(x) if(kind == "z") { zero <- 0+0i; one <- 1+0i } else { zero <- 0 ; one <- 1 } r <- rep.int(log(zero, ...), x@length) if(length(x@i) > 0L) r[x@i] <- log(if(kind == "n") one else x@x, ...) r }) ## METHODS FOR GENERIC: Math2 (group) ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## > getGroupMembers("Math2") ## [1] "round" "signif" setMethod("Math2", c(x = "Matrix"), function(x, digits) { x <- .indefinite(.M2kind(x, ",")) x@x <- get(.Generic, mode = "function")(x@x, digits = digits) if(.hasSlot(x, "factors") && length(x@factors) > 0L) x@factors <- list() x }) setMethod("Math2", c(x = "sparseVector"), function(x, digits) { x <- .V2kind(x, ",") x@x <- get(.Generic, mode = "function")(x@x, digits = digits) x }) ## METHODS FOR GENERIC: zapsmall ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setMethod("zapsmall", signature(x = "Matrix"), function(x, digits = getOption("digits"), mFUN = function(x, ina) max(abs(x[!ina])), min.d = 0L, ...) { x <- .indefinite(.M2kind(x, ",")) x@x <- zapsmall(x@x, digits=digits, mFUN=mFUN, min.d=min.d, ...) if(.hasSlot(x, "factors") && length(x@factors) > 0L) x@factors <- list() x }) setMethod("zapsmall", signature(x = "sparseVector"), function(x, digits = getOption("digits"), mFUN = function(x, ina) max(abs(x[!ina])), min.d = 0L, ...) { x <- .V2kind(x, ",") x@x <- zapsmall(x@x, digits=digits, mFUN=mFUN, min.d=min.d, ...) x }) Matrix/R/solve.R0000644000175100001440000005443214561451364013231 0ustar hornikusers## METHODS FOR GENERIC: solve ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .solve.checkDim1 <- function(nrow.a, ncol.a) { if(nrow.a != ncol.a) stop(gettextf("'%s' is not square", "a"), domain = NA) } .solve.checkDim2 <- function(nrow.a, nrow.b) { if(nrow.a != nrow.b) stop(gettextf("dimensions of '%s' and '%s' are inconsistent", "a", "b"), domain = NA) } .solve.checkCond <- function(a, tol, rcond.a = rcond(a)) { if(tol > 0 && a@Dim[1L] > 0L && rcond.a < tol) stop(gettextf("'%1$s' is computationally singular, rcond(%1$s)=%2$g", "a", rcond.a), domain = NA) } ## Factorize A as P1 A P2 = L U . Then : ## ## kappa(A) <= kappa(P1') * kappa(L) * kappa(U) * kappa(P2') ## == 1 * kappa(L) * kappa(U) * 1 ## ## If U is diagonally dominant, i.e., if there exists a > 1 such that : ## ## abs(U[i,i]) >= a * sum(abs(U[i,-i])) i = 1, ... , n ## ## then : ## ## kappa(U) <= ((a + 1) / (a - 1)) * max(abs(diag(U))) / min(abs(diag(U))) ## ## The bound contracts as a --> Inf and in the limit we have: ## ## kappa(A) / kappa(L) <= kappa(U) <= max(abs(diag(U))) / min(abs(diag(U))) ## .solve.checkCondBound <- function(u, tol, rad.u = range(abs(diag(u, names = FALSE)))) { if(tol > 0 && u@Dim[1L] > 0L) { r <- rad.u[1L] / rad.u[2L] if(r < tol) stop(gettextf("'%s' is computationally singular, min(d)/max(d)=%g, d=abs(diag(U))", "a", r), domain = NA) } } .solve.checkDiagonal <- function(diag.a) { zero <- diag.a == 0 if(any(zero, na.rm = TRUE)) stop(gettextf("matrix is exactly singular, D[i,i]=0, i=%d", which.max(zero)), domain = NA) } .solve.checkInd <- function(perm, margin, n) { if(anyDuplicated.default(perm)) { i <- seq_len(n)[-perm][1L] if(margin == 1L) stop(gettextf("matrix is exactly singular, J[,j]=0, j=%d", i), domain = NA) else stop(gettextf("matrix exactly singular, J[i,]=0, i=%d", i), domain = NA) } } ######################################################################## ## 1. MatrixFactorization incl. triangularMatrix ######################################################################## for(.cl in c("MatrixFactorization", "triangularMatrix")) { setMethod("solve", c(a = .cl, b = "vector"), function(a, b, ...) drop(solve(a, .m2dense(b, ",ge"), ...))) setMethod("solve", c(a = .cl, b = "matrix"), function(a, b, ...) solve(a, .m2dense(b, ",ge"), ...)) setMethod("solve", c(a = .cl, b = "denseMatrix"), function(a, b, ...) solve(a, .M2gen(b, ","), ...)) setMethod("solve", c(a = .cl, b = "CsparseMatrix"), function(a, b, ...) solve(a, .M2gen(b, ","), ...)) setMethod("solve", c(a = .cl, b = "RsparseMatrix"), function(a, b, ...) solve(a, .M2gen(.M2C(b), ","), ...)) setMethod("solve", c(a = .cl, b = "TsparseMatrix"), function(a, b, ...) solve(a, .M2gen(.M2C(b), ","), ...)) setMethod("solve", c(a = .cl, b = "diagonalMatrix"), function(a, b, ...) solve(a, .diag2sparse(b, ",", "g", "C"), ...)) setMethod("solve", c(a = .cl, b = "indMatrix"), function(a, b, ...) solve(a, .ind2sparse(b, ","), ...)) setMethod("solve", c(a = .cl, b = "dgeMatrix"), function(a, b, ...) solve(a, .dense2sparse(b, "C"), ...)) setMethod("solve", c(a = .cl, b = "dgCMatrix"), function(a, b, ...) solve(a, .sparse2dense(b, FALSE), ...)) } rm(.cl) setMethod("solve", c(a = "denseLU", b = "missing"), function(a, b, ...) .Call(denseLU_solve, a, NULL)) setMethod("solve", c(a = "denseLU", b = "dgeMatrix"), function(a, b, ...) .Call(denseLU_solve, a, b)) for(.cl in c("BunchKaufman", "pBunchKaufman")) { setMethod("solve", c(a = .cl, b = "missing"), function(a, b, ...) .Call(BunchKaufman_solve, a, NULL)) setMethod("solve", c(a = .cl, b = "dgeMatrix"), function(a, b, ...) .Call(BunchKaufman_solve, a, b)) } rm(.cl) for(.cl in c("Cholesky", "pCholesky")) { setMethod("solve", c(a = .cl, b = "missing"), function(a, b, ...) .Call(Cholesky_solve, a, NULL)) setMethod("solve", c(a = .cl, b = "dgeMatrix"), function(a, b, ...) .Call(Cholesky_solve, a, b)) } rm(.cl) setMethod("solve", c(a = "sparseLU", b = "missing"), function(a, b, tol = .Machine$double.eps, sparse = TRUE, ...) { .solve.checkCondBound(a@U, tol) .Call(sparseLU_solve, a, NULL, sparse) }) setMethod("solve", c(a = "sparseLU", b = "dgeMatrix"), function(a, b, tol = .Machine$double.eps, ...) { .solve.checkCondBound(a@U, tol) .Call(sparseLU_solve, a, b, FALSE) }) setMethod("solve", c(a = "sparseLU", b = "dgCMatrix"), function(a, b, tol = .Machine$double.eps, ...) { .solve.checkCondBound(a@U, tol) .Call(sparseLU_solve, a, b, TRUE) }) setMethod("solve", c(a = "sparseQR", b = "missing"), function(a, b, sparse = TRUE, ...) { r <- qr.coef(a, diag(a@Dim[2L])) if(is.na(sparse) || sparse) .dense2sparse(r, "C") else r }) setMethod("solve", c(a = "sparseQR", b = "dgeMatrix"), function(a, b, ...) qr.coef(a, b)) setMethod("solve", c(a = "sparseQR", b = "dgCMatrix"), function(a, b, ...) .dense2sparse(qr.coef(a, .sparse2dense(b, FALSE)), "C")) setMethod("solve", c(a = "CHMfactor", b = "missing"), function(a, b, sparse = TRUE, system = c("A","LDLt","LD","DLt","L","Lt","D","P","Pt"), ...) { if((is.na(sparse) || sparse) && !missing(system)) { ## Do the "right" thing : if(identical(system, "D")) { r <- new("ddiMatrix") r@Dim <- a@Dim r@Dimnames <- a@Dimnames[2:1] if(.CHM.is.LDL(a)) r@x <- a@x[a@p + 1L] else r@diag <- "U" return(r) } else if(identical(system, "P") || identical(system, "Pt")) { r <- new("pMatrix") r@Dim <- a@Dim r@Dimnames <- a@Dimnames[2:1] if(system == "Pt") r@margin <- 2L r@perm <- a@perm + 1L return(r) } } .Call(CHMfactor_solve, a, NULL, sparse, system) }) setMethod("solve", c(a = "CHMfactor", b = "dgeMatrix"), function(a, b, system = c("A","LDLt","LD","DLt","L","Lt","D","P","Pt"), ...) .Call(CHMfactor_solve, a, b, FALSE, system)) setMethod("solve", c(a = "CHMfactor", b = "dgCMatrix"), function(a, b, system = c("A","LDLt","LD","DLt","L","Lt","D","P","Pt"), ...) .Call(CHMfactor_solve, a, b, TRUE, system)) for(.cl in c("dtrMatrix", "dtpMatrix")) { setMethod("solve", c(a = .cl, b = "missing"), function(a, b, tol = .Machine$double.eps, ...) { .solve.checkCond(a, tol) .Call(dtrMatrix_solve, a, NULL) }) setMethod("solve", c(a = .cl, b = "dgeMatrix"), function(a, b, tol = .Machine$double.eps, ...) { .solve.checkCond(a, tol) .Call(dtrMatrix_solve, a, b) }) } rm(.cl) setMethod("solve", c(a = "dtCMatrix", b = "missing"), function(a, b, sparse = TRUE, ...) { if(a@diag != "N") a <- ..diagU2N(a) .Call(dtCMatrix_solve, a, NULL, sparse) }) setMethod("solve", c(a = "dtCMatrix", b = "dgeMatrix"), function(a, b, sparse = FALSE, ...) { if(a@diag != "N") a <- ..diagU2N(a) if(is.na(sparse) || sparse) b <- .dense2sparse(b, "C") .Call(dtCMatrix_solve, a, b, sparse) }) setMethod("solve", c(a = "dtCMatrix", b = "dgCMatrix"), function(a, b, sparse = TRUE, ...) { if(a@diag != "N") a <- ..diagU2N(a) if(!(is.na(sparse) || sparse)) b <- .sparse2dense(b, FALSE) .Call(dtCMatrix_solve, a, b, sparse) }) for(.cl in c("dtrMatrix", "dtpMatrix", "dtCMatrix")) setMethod("solve", c(a = .cl, b = "triangularMatrix"), function(a, b, ...) { r <- solve(a, .M2gen(b), ...) if(a@uplo == b@uplo) { r <- if(a@uplo == "U") triu(r) else tril(r) if(a@diag != "N" && b@diag != "N") r <- ..diagN2U(r, sparse = .isCRT(r)) } r }) rm(.cl) ## MJ: truly an exceptional case ... setMethod("solve", c(a = "Schur", b = "ANY"), function(a, b, ...) { Q <- a@Q T <- a@T if(missing(b)) { r <- Q %*% solve(T, t(Q)) r@Dimnames <- a@Dimnames[2:1] r } else { db <- dim(b) dnb <- dimnames(b) r <- Q %*% solve(T, crossprod(Q, b)) r@Dimnames <- c(a@Dimnames[2L], if(is.null(dnb)) list(NULL) else dnb[2L]) if(is.null(db)) drop(r) else r } }) ######################################################################## ## 2. denseMatrix excl. triangularMatrix ######################################################################## setMethod("solve", c(a = "denseMatrix", b = "ANY"), function(a, b, ...) { a <- .M2kind(a, ",") if(missing(b)) solve(a, ...) else solve(a, b, ...) }) setMethod("solve", c(a = "dgeMatrix", b = "ANY"), function(a, b, tol = .Machine$double.eps, ...) { d <- a@Dim .solve.checkDim1(d[1L], d[2L]) .solve.checkCond(a, tol) trf <- lu(a, warnSing = FALSE) if(missing(b)) solve(trf, ...) else solve(trf, b, ...) }) for(.cl in c("dsyMatrix", "dspMatrix")) setMethod("solve", c(a = .cl, b = "ANY"), function(a, b, tol = .Machine$double.eps, ...) { .solve.checkCond(a, tol) trf <- BunchKaufman(a, warnSing = FALSE) if(missing(b)) solve(trf, ...) else solve(trf, b, ...) }) rm(.cl) for(.cl in c("dpoMatrix", "dppMatrix")) setMethod("solve", c(a = .cl, b = "ANY"), function(a, b, tol = .Machine$double.eps, ...) { .solve.checkCond(a, tol) trf <- Cholesky(a, perm = FALSE) if(missing(b)) solve(trf, ...) else solve(trf, b, ...) }) rm(.cl) ######################################################################## ## 3. CsparseMatrix excl. triangularMatrix ######################################################################## setMethod("solve", c(a = "CsparseMatrix", b = "ANY"), function(a, b, ...) { a <- .M2kind(a, ",") if(missing(b)) solve(a, ...) else solve(a, b, ...) }) setMethod("solve", c(a = "dgCMatrix", b = "missing"), function(a, b, sparse = TRUE, ...) { trf <- lu(a, errSing = TRUE) solve(trf, sparse = sparse, ...) }) setMethod("solve", c(a = "dgCMatrix", b = "vector"), function(a, b, ...) { trf <- lu(a, errSing = TRUE) solve(trf, b, ...) }) setMethod("solve", c(a = "dgCMatrix", b = "matrix"), function(a, b, sparse = FALSE, ...) { trf <- lu(a, errSing = TRUE) if(is.na(sparse) || sparse) b <- .m2sparse(b, ",gC") solve(trf, b, ...) }) setMethod("solve", c(a = "dgCMatrix", b = "denseMatrix"), function(a, b, sparse = FALSE, ...) { trf <- lu(a, errSing = TRUE) if(is.na(sparse) || sparse) b <- .M2C(b) solve(trf, b, ...) }) setMethod("solve", c(a = "dgCMatrix", b = "sparseMatrix"), function(a, b, sparse = TRUE, ...) { trf <- lu(a, errSing = TRUE) if(!(is.na(sparse) || sparse)) b <- .M2unpacked(b) solve(trf, b, ...) }) setMethod("solve", c(a = "dsCMatrix", b = "missing"), function(a, b, sparse = TRUE, ...) { trf <- tryCatch( Cholesky(a, perm = TRUE, LDL = TRUE, super = FALSE), error = function(e) lu(a, errSing = TRUE)) solve(trf, sparse = sparse, ...) }) setMethod("solve", c(a = "dsCMatrix", b = "vector"), function(a, b, ...) { trf <- tryCatch( Cholesky(a, perm = TRUE, LDL = TRUE, super = FALSE), error = function(e) lu(a, errSing = TRUE)) solve(trf, b, ...) }) setMethod("solve", c(a = "dsCMatrix", b = "matrix"), function(a, b, sparse = FALSE, ...) { trf <- tryCatch( Cholesky(a, perm = TRUE, LDL = TRUE, super = FALSE), error = function(e) lu(a, errSing = TRUE)) if(is.na(sparse) || sparse) b <- .m2sparse(b, ",gC") solve(trf, b, ...) }) setMethod("solve", c(a = "dsCMatrix", b = "denseMatrix"), function(a, b, sparse = FALSE, ...) { trf <- tryCatch( Cholesky(a, perm = TRUE, LDL = TRUE, super = FALSE), error = function(e) lu(a, errSing = TRUE)) if(is.na(sparse) || sparse) b <- .M2C(b) solve(trf, b, ...) }) setMethod("solve", c(a = "dsCMatrix", b = "sparseMatrix"), function(a, b, sparse = TRUE, ...) { trf <- tryCatch( Cholesky(a, perm = TRUE, LDL = TRUE, super = FALSE), error = function(e) lu(a, errSing = TRUE)) if(!(is.na(sparse) || sparse)) b <- .M2unpacked(b) solve(trf, b, ...) }) ######################################################################## ## 4. RsparseMatrix excl. triangularMatrix ######################################################################## ## TODO: implement triangular solver for dtRMatrix, so that we can handle ## A = and A' = .tCRT(A) like so: ## ## P1 A' P2 = L U ## A x = b <==================> x = P1' inv(L') inv(U') P2' b ## setMethod("solve", c(a = "RsparseMatrix", b = "ANY"), function(a, b, ...) { a <- .M2kind(.M2C(a), ",") if(missing(b)) solve(a, ...) else solve(a, b, ...) }) ######################################################################## ## 5. TsparseMatrix excl. triangularMatrix ######################################################################## setMethod("solve", c(a = "TsparseMatrix", b = "ANY"), function(a, b, ...) { a <- .M2kind(.M2C(a), ",") if(missing(b)) solve(a, ...) else solve(a, b, ...) }) ######################################################################## ## 6. diagonalMatrix ######################################################################## setMethod("solve", c(a = "diagonalMatrix", b = "ANY"), function(a, b, ...) { a <- .M2kind(a, ",") if(missing(b)) solve(a, ...) else solve(a, b, ...) }) setMethod("solve", c(a = "ddiMatrix", b = "missing"), function(a, b, ...) { if(a@diag == "N") { x <- a@x .solve.checkDiagonal(x) a@x <- 1 / x } a@Dimnames <- a@Dimnames[2:1] a }) setMethod("solve", c(a = "ddiMatrix", b = "vector"), function(a, b, ...) { m <- length(b) .solve.checkDim2(a@Dim[1L], m) r <- if(a@diag == "N") { x <- a@x .solve.checkDiagonal(x) as.double(b) / x } else as.double(b) names(r) <- a@Dimnames[[2L]] r }) setMethod("solve", c(a = "ddiMatrix", b = "matrix"), function(a, b, ...) { d <- dim(b) .solve.checkDim2(a@Dim[1L], d[1L]) dn <- dimnames(b) r <- new("dgeMatrix") r@Dim <- d r@Dimnames <- c(a@Dimnames[2L], if(is.null(dn)) list(NULL) else dn[2L]) r@x <- if(a@diag == "N") { x <- a@x .solve.checkDiagonal(x) as.double(b) / x } else as.double(b) r }) setMethod("solve", c(a = "ddiMatrix", b = "Matrix"), function(a, b, ...) { .solve.checkDim2(a@Dim[1L], b@Dim[1L]) if(a@diag == "N") { x <- a@x .solve.checkDiagonal(x) a@x <- 1 / x } a@Dimnames <- a@Dimnames[2:1] a %*% b }) ######################################################################## ## 7. indMatrix ######################################################################## setMethod("solve", c(a = "indMatrix", b = "ANY"), function(a, b, ...) { d <- a@Dim .solve.checkDim1(d[1L], d[2L]) perm <- a@perm margin <- a@margin .solve.checkInd(perm, margin, d[1L]) p <- new("pMatrix") p@Dim <- d p@Dimnames <- a@Dimnames p@perm <- perm p@margin <- margin if(missing(b)) solve(p, ...) else solve(p, b, ...) }) setMethod("solve", c(a = "pMatrix", b = "missing"), function(a, b, ...) { a@Dimnames <- a@Dimnames[2:1] a@margin <- if(a@margin == 1L) 2L else 1L a }) setMethod("solve", c(a = "pMatrix", b = "vector"), function(a, b, ...) { m <- length(b) .solve.checkDim2(a@Dim[1L], m) perm <- if(a@margin == 1L) invertPerm(a@perm) else a@perm r <- as.double(b)[perm] names(r) <- a@Dimnames[[2L]] r }) setMethod("solve", c(a = "pMatrix", b = "matrix"), function(a, b, ...) { d <- dim(b) .solve.checkDim2(a@Dim[1L], d[1L]) dn <- dimnames(b) perm <- if(a@margin == 1L) invertPerm(a@perm) else a@perm r <- new("dgeMatrix") r@Dim <- d r@Dimnames <- c(a@Dimnames[2L], if(is.null(dn)) list(NULL) else dn[2L]) r@x <- as.double(b[perm, , drop = FALSE]) r }) setMethod("solve", c(a = "pMatrix", b = "Matrix"), function(a, b, ...) { .solve.checkDim2(a@Dim[1L], b@Dim[1L]) perm <- if(a@margin == 1L) invertPerm(a@perm) else a@perm r <- b[perm, , drop = FALSE] r@Dimnames <- c(a@Dimnames[2L], b@Dimnames[2L]) r }) ######################################################################## ## 8. Other ... a=matrix OR b=sparseVector ######################################################################## ## for now ... fast for this special case ... .spV2dgC <- function(x) { if(is.double(m <- length(x))) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) i <- as.integer(x@i) - 1L nnz <- length(i) r <- new("dgCMatrix") r@Dim <- c(m, 1L) r@p <- c(0L, nnz) r@i <- i r@x <- if(!.hasSlot(x, "x")) rep.int(1, nnz) else if(is.complex(y <- x@x)) stop(gettextf("cannot coerce from %s to %s", "zsparseVector", "dgCMatrix"), domain = NA) else y r } ## for now ... fast for this special case ... .spV2dge <- function(x) { if(is.double(m <- length(x))) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) r <- new("dgeMatrix") r@Dim <- c(m, 1L) r@x <- replace(double(m), x@i, if(!.hasSlot(x, "x")) 1 else if(is.complex(y <- x@x)) stop(gettextf("cannot coerce from %s to %s", "zsparseVector", "dgCMatrix"), domain = NA) else y) r } setMethod("solve", c(a = "Matrix", b = "sparseVector"), function(a, b, ...) solve(a, .spV2dgC(b), ...)) # FIXME? drop(.)? setMethod("solve", c(a = "MatrixFactorization", b = "sparseVector"), function(a, b, ...) solve(a, .spV2dgC(b), ...)) # FIXME? drop(.)? setMethod("solve", c(a = "matrix", b = "Matrix"), function(a, b, ...) solve(.m2dense(a, ",ge"), b, ...)) setMethod("solve", c(a = "matrix", b = "sparseVector"), function(a, b, ...) solve(.m2dense(a, ",ge"), .spV2dge(b), ...)) # FIXME? drop(.)? ######################################################################## ## 9. Exported solvers ######################################################################## ## a=dgCMatrix ## b=vector, matrix, or Matrix ## x=dg[Ce]Matrix .solve.dgC.lu <- function(a, b, tol = .Machine$double.eps, check = TRUE) { if(check && !is(a, "dgCMatrix")) a <- as(as(as(a, "CsparseMatrix"), "generalMatrix"), "dMatrix") trf <- lu(a, errSing = TRUE) solve(trf, b, tol = tol) } ## a=dgCMatrix ## b=vector or 1-column matrix ## x=double vector .solve.dgC.qr <- function(a, b, order = 3L, check = TRUE) { # -> MatrixModels if(check && !is(a, "dgCMatrix")) a <- as(as(as(a, "CsparseMatrix"), "generalMatrix"), "dMatrix") .Call(dgCMatrix_qrsol, a, b, order) # calls cs_qrsol } ## a=dgCMatrix ## b=vector or 1-column matrix ## x=list(L, coef, Xty, resid) .solve.dgC.chol <- function(a, b, check = TRUE) { # -> MatrixModels if(check && !is(a, "dgCMatrix")) a <- as(as(as(a, "CsparseMatrix"), "generalMatrix"), "dMatrix") .Call(dgCMatrix_cholsol, a, b) } Matrix/R/00_Class.R0000644000175100001440000010575514575137654013462 0ustar hornikusers## README: ## ## Validity methods should assume that methods for superclasses have passed, ## following validObject(). We should _not_ be testing, e.g., length(Dim), ## typeof(Dimnames), etc. repeatedly ... ## ## When checking whether a class is validated correctly, take care to follow ## the 'contains' recursively!! ## initialize() method for Matrix and MatrixFactorization, which both ## allow Dimnames[[i]] to be a vector of type other than "character" ## and furthermore to be a vector of length zero rather than NULL ... .initialize <- function(.Object, ...) { .Object <- callNextMethod() ## Suboptimal if ...names() is NULL but that will "never" ## happen if ...length() is nonzero: if(...length() && any(...names() == "Dimnames")) .Object@Dimnames <- fixupDN(.Object@Dimnames) .Object } ## new() does not work at build time because native symbols such as ## 'Matrix_validate' needed for validity checking are not available ... .new <- function(cl, ...) { def <- getClassDef(cl) structure(def@prototype, class = def@className, ...) } ######################################################################## ## 1. Matrix ######################################################################## ## ====== Virtual Subclasses =========================================== ## ------ The Mother Class 'Matrix' ------------------------------------ ## Virtual class of all Matrix objects setClass("Matrix", contains = "VIRTUAL", slots = c(Dim = "integer", Dimnames = "list"), prototype = list(Dim = integer(2L), Dimnames = list(NULL, NULL)), validity = function(object) .Call(Matrix_validate, object)) setMethod("initialize", c(.Object = "Matrix"), .initialize) ## ------ Virtual by structure ----------------------------------------- ## Virtual class of general matrices setClass("generalMatrix", contains = c("VIRTUAL", "Matrix"), slots = c(factors = "list"), validity = function(object) .Call(generalMatrix_validate, object)) ## Virtual class of symmetric matrices setClass("symmetricMatrix", contains = c("VIRTUAL", "Matrix"), slots = c(uplo = "character", factors = "list"), prototype = list(uplo = "U"), validity = function(object) .Call(symmetricMatrix_validate, object)) ## Virtual class of triangular matrices setClass("triangularMatrix", contains = c("VIRTUAL", "Matrix"), slots = c(uplo = "character", diag = "character"), prototype = list(uplo = "U", diag = "N"), validity = function(object) .Call(triangularMatrix_validate, object)) ## ------ Virtual by kind ---------------------------------------------- ## Virtual class of nonzero pattern matrices ## NB: only subclass ndenseMatrix requires an 'x' slot setClass("nMatrix", contains = c("VIRTUAL", "Matrix")) ## Virtual class of logical matrices, ## * typically the result of comparisons, e.g., , ## hence NA are allowed and distinct from TRUE, in contrast with nMatrix setClass("lMatrix", contains = c("VIRTUAL", "Matrix"), slots = c(x = "logical"), validity = function(object) .Call(lMatrix_validate, object)) ## Virtual class of integer matrices setClass("iMatrix", contains = c("VIRTUAL", "Matrix"), slots = c(x = "integer"), validity = function(object) .Call(iMatrix_validate, object)) ## Virtual class of double matrices setClass("dMatrix", contains = c("VIRTUAL", "Matrix"), slots = c(x = "numeric"), validity = function(object) .Call(dMatrix_validate, object)) ## Virtual class of complex matrices ## * initial 'z' is derived from the names of LAPACK routines setClass("zMatrix", contains = c("VIRTUAL", "Matrix"), slots = c(x = "complex"), validity = function(object) .Call(zMatrix_validate, object)) ## ------ Virtual Dense ------------------------------------------------ ## Virtual class of dense matrices ## * includes "unpacked" _and_ "packed" matrices ## * included diagonal matrices until 0.999375-11 (2008-07) setClass("denseMatrix", contains = c("VIRTUAL", "Matrix")) ## ...... Virtual Dense ... by storage ................................. ## Virtual class of dense, "unpacked" matrices, s.t. length(.@x) == m*n setClass("unpackedMatrix", contains = c("VIRTUAL", "denseMatrix"), validity = function(object) .Call(unpackedMatrix_validate, object)) ## Virtual class of dense, "packed" matrices, s.t. length(.@x) == n*(n+1)/2 setClass("packedMatrix", contains = c("VIRTUAL", "denseMatrix"), slots = c(uplo = "character"), prototype = list(uplo = "U"), validity = function(object) .Call(packedMatrix_validate, object)) ## ...... Virtual Dense ... by kind .................................... ## Virtual class of dense, nonzero pattern matrices setClass("ndenseMatrix", contains = c("VIRTUAL", "nMatrix", "denseMatrix"), slots = c(x = "logical"), validity = function(object) .Call(nMatrix_validate, object)) ## Virtual class of dense, logical matrices setClass("ldenseMatrix", contains = c("VIRTUAL", "lMatrix", "denseMatrix")) if(FALSE) { # --NOT YET-- ## Virtual class of dense, integer matrices setClass("idenseMatrix", contains = c("VIRTUAL", "iMatrix", "denseMatrix")) } # --NOT YET-- ## Virtual class of dense, double matrices setClass("ddenseMatrix", contains = c("VIRTUAL", "dMatrix", "denseMatrix")) if(FALSE) { # --NOT YET-- ## Virtual class of dense, complex matrices setClass("zdenseMatrix", contains = c("VIRTUAL", "zMatrix", "denseMatrix")) } # --NOT YET-- ## ------ Virtual Sparse ----------------------------------------------- ## Virtual class of sparse matrices ## * includes diagonal matrices since 0.999375-11 (2008-07) setClass("sparseMatrix", contains = c("VIRTUAL", "Matrix")) ## ...... Virtual Sparse ... by storage ................................ ## Virtual class of sparse matrices in compressed sparse column (CSC) format setClass("CsparseMatrix", contains = c("VIRTUAL", "sparseMatrix"), slots = c(i = "integer", p = "integer"), prototype = list(p = 0L), # to be valid validity = function(object) .Call(CsparseMatrix_validate, object)) ## Virtual class of sparse matrices in compressed sparse row (CSR) format setClass("RsparseMatrix", contains = c("VIRTUAL", "sparseMatrix"), slots = c(p = "integer", j = "integer"), prototype = list(p = 0L), # to be valid validity = function(object) .Call(RsparseMatrix_validate, object)) ## Virtual class of sparse matrices in triplet format setClass("TsparseMatrix", contains = c("VIRTUAL", "sparseMatrix"), slots = c(i = "integer", j = "integer"), validity = function(object) .Call(TsparseMatrix_validate, object)) ## Virtual class of diagonal matrices setClass("diagonalMatrix", contains = c("VIRTUAL", "sparseMatrix"), slots = c(diag = "character"), prototype = list(diag = "N"), validity = function(object) .Call(diagonalMatrix_validate, object)) if(FALSE) { # --NOT YET-- ## These methods would allow initialization of zero matrices _without_ 'p', ## as in the call new("dgCMatrix", Dim = c(6L, 6L)). However, they would ## also incur a small performance penalty on all other new("..[CR]Matrix") ## calls. setMethod("initialize", c(.Object = "CsparseMatrix"), function(.Object, ...) { ## Suboptimal if ...names() is NULL or if 'Dim' is missing ## but that will "never" happen if ...length() is nonzero: if(...length() && all((nms <- ...names()) != "p") && length(w <- which(nms == "Dim")) && !is.character(validDim(d <- ...elt(w[1L])))) callNextMethod(.Object, ..., p = integer(d[2L] + 1)) else callNextMethod() }) setMethod("initialize", c(.Object = "RsparseMatrix"), function(.Object, ...) { ## Suboptimal if ...names() is NULL or if 'Dim' is missing ## but that will "never" happen if ...length() is nonzero: if(...length() && all((nms <- ...names()) != "p") && length(w <- which(nms == "Dim")) && !is.character(validDim(d <- ...elt(w[1L])))) callNextMethod(.Object, ..., p = integer(d[1L] + 1)) else callNextMethod() }) } # --NOT YET-- ## ...... Virtual Sparse ... by kind ................................... ## Virtual class of sparse, nonzero pattern matrices ## * these are the "pattern" matrices from "symbolic analysis" of sparse OPs setClass("nsparseMatrix", contains = c("VIRTUAL", "nMatrix", "sparseMatrix")) ## Virtual class of sparse, logical matrices setClass("lsparseMatrix", contains = c("VIRTUAL", "lMatrix", "sparseMatrix")) if(FALSE) { # --NOT YET-- ## Virtual class of sparse, integer matrices setClass("isparseMatrix", contains = c("VIRTUAL", "iMatrix", "sparseMatrix")) } # --NOT YET-- ## Virtual class of sparse, double matrices setClass("dsparseMatrix", contains = c("VIRTUAL", "dMatrix", "sparseMatrix")) if(FALSE) { # --NOT YET-- ## Virtual class of sparse, complex matrices setClass("zsparseMatrix", contains = c("VIRTUAL", "zMatrix", "sparseMatrix")) } # --NOT YET-- ## ====== Non-Virtual Subclasses ======================================= ## ------ Non-Virtual Dense -------------------------------------------- ## ...... Dense, nonzero pattern ....................................... ## Unpacked, general setClass("ngeMatrix", contains = c("unpackedMatrix", "ndenseMatrix", "generalMatrix")) ## Unpacked, symmetric setClass("nsyMatrix", contains = c("unpackedMatrix", "ndenseMatrix", "symmetricMatrix")) ## Unpacked, triangular setClass("ntrMatrix", contains = c("unpackedMatrix", "ndenseMatrix", "triangularMatrix")) ## Packed, symmetric setClass("nspMatrix", contains = c("packedMatrix", "ndenseMatrix", "symmetricMatrix")) ## Packed, triangular setClass("ntpMatrix", contains = c("packedMatrix", "ndenseMatrix", "triangularMatrix")) ## ...... Dense, logical ............................................... ## Unpacked, general setClass("lgeMatrix", contains = c("unpackedMatrix", "ldenseMatrix", "generalMatrix")) ## Unpacked, symmetric setClass("lsyMatrix", contains = c("unpackedMatrix", "ldenseMatrix", "symmetricMatrix")) ## Unpacked, triangular setClass("ltrMatrix", contains = c("unpackedMatrix", "ldenseMatrix", "triangularMatrix")) ## Packed, symmetric setClass("lspMatrix", contains = c("packedMatrix", "ldenseMatrix", "symmetricMatrix")) ## Packed, triangular setClass("ltpMatrix", contains = c("packedMatrix", "ldenseMatrix", "triangularMatrix")) ## ...... Dense, double ................................................ ## Unpacked, general setClass("dgeMatrix", contains = c("unpackedMatrix", "ddenseMatrix", "generalMatrix")) ## Unpacked, symmetric setClass("dsyMatrix", contains = c("unpackedMatrix", "ddenseMatrix", "symmetricMatrix")) ## Unpacked, symmetric, positive semidefinite setClass("dpoMatrix", contains = "dsyMatrix", validity = function(object) .Call(dpoMatrix_validate, object)) ## Unpacked, symmetric, positive semidefinite, correlation setClass("corMatrix", contains = "dpoMatrix", slots = c(sd = "numeric"), validity = function(object) .Call(corMatrix_validate, object)) ## Unpacked, triangular setClass("dtrMatrix", contains = c("unpackedMatrix", "ddenseMatrix", "triangularMatrix")) ## Packed, symmetric setClass("dspMatrix", contains = c("packedMatrix", "ddenseMatrix", "symmetricMatrix")) ## Packed, symmetric, positive semidefinite setClass("dppMatrix", contains = "dspMatrix", validity = function(object) .Call(dppMatrix_validate, object)) ## Packed, symmetric, positive semidefinite, correlation setClass("copMatrix", contains = "dppMatrix", slots = c(sd = "numeric"), validity = function(object) .Call(copMatrix_validate, object)) ## Packed, triangular setClass("dtpMatrix", contains = c("packedMatrix", "ddenseMatrix", "triangularMatrix")) ## ------ Non-Virtual Sparse ------------------------------------------- ## ...... Sparse, nonzero pattern ...................................... ## NB: Unlike [^n]sparseMatrix (below), there is no 'x' slot to validate here. ## CSC, general setClass("ngCMatrix", contains = c("CsparseMatrix", "nsparseMatrix", "generalMatrix")) ## CSC, symmetric setClass("nsCMatrix", contains = c("CsparseMatrix", "nsparseMatrix", "symmetricMatrix"), validity = function(object) .Call(sCMatrix_validate, object)) ## CSC, triangular setClass("ntCMatrix", contains = c("CsparseMatrix", "nsparseMatrix", "triangularMatrix"), validity = function(object) .Call(tCMatrix_validate, object)) ## CSR, general setClass("ngRMatrix", contains = c("RsparseMatrix", "nsparseMatrix", "generalMatrix")) ## CSR, symmetric setClass("nsRMatrix", contains = c("RsparseMatrix", "nsparseMatrix", "symmetricMatrix"), validity = function(object) .Call(sRMatrix_validate, object)) ## CSR, triangular setClass("ntRMatrix", contains = c("RsparseMatrix", "nsparseMatrix", "triangularMatrix"), validity = function(object) .Call(tRMatrix_validate, object)) ## Triplet general setClass("ngTMatrix", contains = c("TsparseMatrix", "nsparseMatrix", "generalMatrix")) ## Triplet, symmetric setClass("nsTMatrix", contains = c("TsparseMatrix", "nsparseMatrix", "symmetricMatrix"), validity = function(object) .Call(sTMatrix_validate, object)) ## Triplet, triangular setClass("ntTMatrix", contains = c("TsparseMatrix", "nsparseMatrix", "triangularMatrix"), validity = function(object) .Call(tTMatrix_validate, object)) ## Diagonal setClass("ndiMatrix", contains = c("diagonalMatrix", "nMatrix"), slots = c(x = "logical"), validity = function(object) .Call(nMatrix_validate, object)) ## ...... Sparse, logical .............................................. ## CSC, general setClass("lgCMatrix", contains = c("CsparseMatrix", "lsparseMatrix", "generalMatrix"), validity = function(object) .Call(xgCMatrix_validate, object)) ## CSC, symmetric setClass("lsCMatrix", contains = c("CsparseMatrix", "lsparseMatrix", "symmetricMatrix"), validity = function(object) .Call(xsCMatrix_validate, object)) ## CSC, triangular setClass("ltCMatrix", contains = c("CsparseMatrix", "lsparseMatrix", "triangularMatrix"), validity = function(object) .Call(xtCMatrix_validate, object)) ## CSR, general setClass("lgRMatrix", contains = c("RsparseMatrix", "lsparseMatrix", "generalMatrix"), validity = function(object) .Call(xgRMatrix_validate, object)) ## CSR, symmetric setClass("lsRMatrix", contains = c("RsparseMatrix", "lsparseMatrix", "symmetricMatrix"), validity = function(object) .Call(xsRMatrix_validate, object)) ## CSR, triangular setClass("ltRMatrix", contains = c("RsparseMatrix", "lsparseMatrix", "triangularMatrix"), validity = function(object) .Call(xtRMatrix_validate, object)) ## Triplet, general setClass("lgTMatrix", contains = c("TsparseMatrix", "lsparseMatrix", "generalMatrix"), validity = function(object) .Call(xgTMatrix_validate, object)) ## Triplet, symmetric setClass("lsTMatrix", contains = c("TsparseMatrix", "lsparseMatrix", "symmetricMatrix"), validity = function(object) .Call(xsTMatrix_validate, object)) ## Triplet, triangular setClass("ltTMatrix", contains = c("TsparseMatrix", "lsparseMatrix", "triangularMatrix"), validity = function(object) .Call(xtTMatrix_validate, object)) ## Diagonal setClass("ldiMatrix", contains = c("diagonalMatrix", "lMatrix")) ## ...... Sparse, double ............................................... ## CSC, general setClass("dgCMatrix", contains = c("CsparseMatrix", "dsparseMatrix", "generalMatrix"), validity = function(object) .Call(xgCMatrix_validate, object)) ## CSC, symmetric setClass("dsCMatrix", contains = c("CsparseMatrix", "dsparseMatrix", "symmetricMatrix"), validity = function(object) .Call(xsCMatrix_validate, object)) ## CSC, triangular setClass("dtCMatrix", contains = c("CsparseMatrix", "dsparseMatrix", "triangularMatrix"), validity = function(object) .Call(xtCMatrix_validate, object)) ## CSR, general setClass("dgRMatrix", contains = c("RsparseMatrix", "dsparseMatrix", "generalMatrix"), validity = function(object) .Call(xgRMatrix_validate, object)) ## CSR, symmetric setClass("dsRMatrix", contains = c("RsparseMatrix", "dsparseMatrix", "symmetricMatrix"), validity = function(object) .Call(xsRMatrix_validate, object)) ## CSR, triangular setClass("dtRMatrix", contains = c("RsparseMatrix", "dsparseMatrix", "triangularMatrix"), validity = function(object) .Call(xtRMatrix_validate, object)) ## Triplet, general setClass("dgTMatrix", contains = c("TsparseMatrix", "dsparseMatrix", "generalMatrix"), validity = function(object) .Call(xgTMatrix_validate, object)) ## Triplet, symmetric setClass("dsTMatrix", contains = c("TsparseMatrix", "dsparseMatrix", "symmetricMatrix"), validity = function(object) .Call(xsTMatrix_validate, object)) ## Triplet, triangular setClass("dtTMatrix", contains = c("TsparseMatrix", "dsparseMatrix", "triangularMatrix"), validity = function(object) .Call(xtTMatrix_validate, object)) ## Diagonal setClass("ddiMatrix", contains = c("diagonalMatrix", "dMatrix")) if(FALSE) { # TODO ## CSC, symmetic, positive semidefinite setClass("dpCMatrix", contains = "dsCMatrix", validity = function(object) TODO("test positive semidefiniteness")) ## CSR, symmetic, positive semidefinite setClass("dpRMatrix", contains = "dsRMatrix", validity = function(object) TODO("test positive semidefiniteness")) ## Triplet, symmetic, positive semidefinite setClass("dpTMatrix", contains = "dsTMatrix", validity = function(object) TODO("test positive semidefiniteness")) } # TODO ## ...... Sparse, index ................................................ ## Row or column index setClass("indMatrix", contains = "sparseMatrix", slots = c(perm = "integer", margin = "integer"), prototype = list(margin = 1L), # to be valid validity = function(object) .Call(indMatrix_validate, object)) ## Row or column permutation setClass("pMatrix", contains = "indMatrix", validity = function(object) .Call(pMatrix_validate, object)) ######################################################################## ## 2. MatrixFactorization ######################################################################## ## ------ The Mother Class "MatrixFactorization" ----------------------- setClass("MatrixFactorization", contains = "VIRTUAL", slots = c(Dim = "integer", Dimnames = "list"), prototype = list(Dim = integer(2L), Dimnames = list(NULL, NULL)), validity = function(object).Call(MatrixFactorization_validate, object)) setMethod("initialize", c(.Object = "MatrixFactorization"), .initialize) ## ------ LU ----------------------------------------------------------- setClass("LU", contains = c("VIRTUAL", "MatrixFactorization")) ## Inherit most aspects of dgeMatrix without extending it setClass("denseLU", contains = "LU", slots = c(x = "numeric", perm = "integer"), validity = function(object) { object. <- new("dgeMatrix") object.@Dim <- object@Dim object.@Dimnames <- object@Dimnames object.@x <- object@x if(is.character(valid <- validObject(object., test = TRUE))) valid else .Call(denseLU_validate, object) }) setClass("sparseLU", contains = "LU", slots = c(L = "dtCMatrix", U = "dtCMatrix", p = "integer", q = "integer"), prototype = list(L = .new("dtCMatrix", uplo = "L")), validity = function(object) .Call(sparseLU_validate, object)) ## ------ QR ----------------------------------------------------------- setClass("QR", contains = c("VIRTUAL", "MatrixFactorization")) if(FALSE) { ## MJ: It would nice to have symmetry with LU, but then we would need ## to define methods already available for S3 class 'qr'. Still ... setClass("denseQR", contains = "QR", ## based on S3 class 'qr': slots = c(qr = "numeric", qraux = "numeric", rank = "integer", pivot = "integer", useLAPACK = "logical"), validity = function(object) .Call(denseQR_validate, object)) } setClass("sparseQR", contains = "QR", slots = c(beta = "numeric", V = "dgCMatrix", R = "dgCMatrix", p = "integer", q = "integer"), validity = function(object) .Call(sparseQR_validate, object)) ## ------ Bunch-Kaufman ------------------------------------------------ setClass("BunchKaufmanFactorization", contains = c("VIRTUAL", "MatrixFactorization")) ## Inherit most aspects of dt[rp]Matrix without extending them setClass("BunchKaufman", contains = "BunchKaufmanFactorization", slots = c(uplo = "character", x = "numeric", perm = "integer"), prototype = list(uplo = "U"), validity = function(object) { object. <- new("dtrMatrix") object.@Dim <- object@Dim object.@Dimnames <- object@Dimnames object.@uplo <- object@uplo object.@x <- object@x if(is.character(valid <- validObject(object., test = TRUE))) valid else .Call(BunchKaufman_validate, object) }) setClass("pBunchKaufman", contains = "BunchKaufmanFactorization", slots = c(uplo = "character", x = "numeric", perm = "integer"), prototype = list(uplo = "U"), validity = function(object) { object. <- new("dtpMatrix") object.@Dim <- object@Dim object.@Dimnames <- object@Dimnames object.@uplo <- object@uplo object.@x <- object@x if(is.character(valid <- validObject(object., test = TRUE))) valid else .Call(pBunchKaufman_validate, object) }) ## ------ Cholesky ----------------------------------------------------- setClass("CholeskyFactorization", contains = c("VIRTUAL", "MatrixFactorization")) ## ...... Dense ........................................................ ## Inherit most aspects of dt[rp]Matrix without extending them setClass("Cholesky", contains = "CholeskyFactorization", slots = c(uplo = "character", x = "numeric", perm = "integer"), prototype = list(uplo = "U"), validity = function(object) { object. <- new("dtrMatrix") object.@Dim <- object@Dim object.@Dimnames <- object@Dimnames object.@uplo <- object@uplo object.@x <- object@x if(is.character(valid <- validObject(object., test = TRUE))) valid else .Call(Cholesky_validate, object) }) setClass("pCholesky", contains = "CholeskyFactorization", slots = c(uplo = "character", x = "numeric", perm = "integer"), prototype = list(uplo = "U"), validity = function(object) { object. <- new("dtpMatrix") object.@Dim <- object@Dim object.@Dimnames <- object@Dimnames object.@uplo <- object@uplo object.@x <- object@x if(is.character(valid <- validObject(object., test = TRUE))) valid else .Call(pCholesky_validate, object) }) ## ...... Sparse ....................................................... ## FIXME? simplicial symbolic factorization is specified entirely by ## 'colcount' and 'perm' ... ## should 'p', 'i', 'nz', 'nxt', 'prv' slots all be emtpy ?? ## see comments in ../src/CHOLMOD/Core/cholmod_change_factor.c ## S4 representation of C struct 'cholmod_factor', ## from header ../src/CHOLMOD/Include/cholmod_core.h setClass("CHMfactor", contains = c("VIRTUAL", "CholeskyFactorization"), slots = c(type = "integer", colcount = "integer", perm = "integer"), validity = function(object) .Call(CHMfactor_validate, object)) ## Simplicial factorization setClass("CHMsimpl", contains = c("VIRTUAL", "CHMfactor"), slots = c(p = "integer", i = "integer", nz = "integer", nxt = "integer", prv = "integer"), prototype = list(type = c(0L, 1L, 0L, 1L, 0L, 0L), p = 0L, nxt = c(-1L, 0L), prv = c(1L, -1L)), validity = function(object) .Call(CHMsimpl_validate, object)) setClass("nCHMsimpl", contains = "CHMsimpl") setClass("dCHMsimpl", contains = "CHMsimpl", slots = c(x = "numeric"), validity = function(object) .Call(dCHMsimpl_validate, object)) ## Supernodal factorization setClass("CHMsuper", contains = c("VIRTUAL", "CHMfactor"), slots = c(super = "integer", pi = "integer", px = "integer", s = "integer"), prototype = list(type = c(0L, 1L, 1L, 1L, 0L, 0L), super = 0L, pi = 0L, px = 0L), validity = function(object) .Call(CHMsuper_validate, object)) setClass("nCHMsuper", contains = "CHMsuper") setClass("dCHMsuper", contains = "CHMsuper", slots = c(x = "numeric"), validity = function(object) .Call(dCHMsuper_validate, object)) ## ------ Schur -------------------------------------------------------- setClass("SchurFactorization", contains = c("VIRTUAL", "MatrixFactorization")) setClass("Schur", contains = "SchurFactorization", slots = c(Q = "Matrix", T = "Matrix", EValues = "vector"), prototype = list(Q = .new("dgeMatrix"), T = .new("dgeMatrix"), EValues = double(0L)), validity = function(object) .Call(Schur_validate, object)) ######################################################################## ## 3. sparseVector ######################################################################## ## ------ The Mother Class 'sparseVector' ------------------------------ setClass("sparseVector", contains = "VIRTUAL", slots = c(length = "numeric", i = "numeric"), # 1-based index! prototype = list(length = 0), validity = function(object) .Call(sparseVector_validate, object)) ## Allow users to do new("[nlidz]sparseVector", i=, x=) with unsorted 'i' setMethod("initialize", c(.Object = "sparseVector"), function(.Object, i, x, ...) { if(has.x <- !missing(x)) x <- x # MJ: why is this necessary? if(!missing(i)) { i.uns <- is.unsorted(i, strictly = TRUE) i <- if(is.na(i.uns) || !i.uns) i else { ## we know that there are no NA, and the order of ## ties does not matter (since ties are an error), ## hence it is safe to use "quick" here m <- if(is.integer(length(i))) "radix" else "quick" if(.hasSlot(.Object, "x") && has.x) { s <- sort.int(i, method = m, index.return = TRUE) x <- x[s$ix] s$x } else sort.int(i, method = m) } } callNextMethod() }) ## ------ Non-Virtual Subclasses --------------------------------------- setClass("nsparseVector", contains = "sparseVector") setClass("lsparseVector", contains = "sparseVector", slots = c(x = "logical"), validity = function(object) .Call(lsparseVector_validate, object)) setClass("isparseVector", contains = "sparseVector", slots = c(x = "integer"), validity = function(object) .Call(isparseVector_validate, object)) setClass("dsparseVector", contains = "sparseVector", slots = c(x = "numeric"), validity = function(object) .Call(dsparseVector_validate, object)) setClass("zsparseVector", contains = "sparseVector", slots = c(x = "complex"), validity = function(object) .Call(zsparseVector_validate, object)) ######################################################################## ## 4. Index and more "miscellaneous" classes, but _not_ class unions ######################################################################## ## Idea: represent x = c(seq(from1, to1, by1), seq(from2, to2, by2), ...) ## as list(first = x[1L], rle = rle(diff(x))) setOldClass("rle") setClass("rleDiff", ## MJ: simpler would be slots = c(first=, lengths=, values=) ... slots = c(first = "numeric", rle = "rle"), prototype = list(first = integer(0L), rle = rle(integer(0L))), validity = function(object) { if(length(object@first) != 1L) "'first' slot does not have length 1" else if(!is.list(rle <- object@rle)) "'rle' slot is not a list" else if(length(rle) != 2L) "'rle' slot does not have length 2" else if(is.null(nms <- names(rle)) || anyNA(match(nms, c("lengths", "values")))) "'rle' slot does not have names \"lengths\", \"values\"" else if(!is.numeric(lens <- rle$lengths)) "'lengths' is not numeric" else if(!is.numeric(vals <- rle$values)) "'values' is not numeric" else if(length(lens) != length(vals)) "'lengths' and 'values' do not have equal length" else if(length(lens) == 0L) TRUE else if(anyNA(lens)) "'lengths' contains NA" else if(is.double(lens)) { if(!(all(is.finite(r <- range(lens))) && all(lens == trunc(lens)))) "'lengths' is not integer-valued" else if(r[1L] < 1) "'lengths' is not positive" else TRUE } else { if(min(lens) < 1L) "'lengths' is not positive" else TRUE } }) ## Idea: represent x = c(seq(from1, to1, by1), seq(from2, to2, by2), ...) ## as rbind(c(from1, from2, ...), c(to1, to2, ...), c(by1, by2, ...)) ## MM: (2010-03-04) more efficient than "rleDiff" [TODO: write rleDiff<->seqMat] ## MJ: (2022-09-06) data.frame(from, to, by) could be _handled_ more efficiently setClass("seqMat", contains = "matrix", prototype = matrix(integer(0L), nrow = 3L, ncol = 0L), validity = function(object) { if(!is.numeric(object)) "matrix is not numeric" else if(nrow(object) != 3L) "matrix does not have 3 rows" else if(anyNA(object)) "matrix contains NA" else if(is.double(object) && !(all(is.finite(range(object))) && all(object == trunc(object)))) "matrix is not integer-valued" else { from <- object[1L, ] to <- object[2L, ] by <- object[3L, ] if(any((from < to & by <= 0) | (from > to & by >= 0))) "degenerate sequence(s): sign(to - from) != sign(by)" else TRUE } }) ## Idea: _ab_stract index ## MJ: (2022-09-06) why not just ## setClassUnion("abIndex", members = c("numeric", "rleDiff", "seqMat")) ? setClass("abIndex", slots = c(kind = "character", x = "numeric", rleD = "rleDiff"), prototype = list(kind = "int32", x = integer(0L)), validity = function(object) { ## MJ: should 'rleD' be "empty" if kind != "rleDiff" ? if(length(kind <- object@kind) != 1L) "'kind' slot does not have length 1" else switch(kind, "int32" = if(is.integer(object@x)) TRUE else "kind=\"int32\" but 'x' slot is not of type \"integer\"", "double" = if(is.double(object@x)) TRUE else "kind=\"double\" but 'x' slot is not of type \"double\"", "rleDiff" = if(length(object@x) == 0L) TRUE else "kind=\"rleDiff\" but 'x' slot is nonempty", ## otherwise: "'kind' is not \"int32\", \"double\", or \"rleDiff\"") }) ######################################################################## ## 5. Class unions ######################################################################## ## MJ: aim to deprecate and eventually remove these ## (except perhaps 'index') setClassUnion("atomicVector", members = c("raw", "logical", "numeric", "complex", "character")) setClassUnion("index", members = c( "logical", "numeric", "character")) setClassUnion("numLike", members = c( "logical", "numeric" )) setClassUnion("number", members = c( "numeric", "complex" )) setClassUnion("replValue", members = c("raw", "logical", "numeric", "complex" )) ## Removing these entirely in Matrix 1.7-0 invalidates class definitions ## serialized in existing installations of the following packages: ## ## [1] CVXR FinNet GENLIB ## [4] MSnbase MachineShop MatrixModels ## [7] SeuratObject SingleCellExperiment WoodburyMatrix ## [10] apcluster arules chromVAR ## [13] conText copula destiny ## [16] distrom genomation hypr ## [19] iGraphMatch kebabs mcompanion ## [22] pcts podkat qpgraph ## [25] quadrupen quanteda quanteda.textstats ## [28] saeRobust scuttle snpStats ## [31] softImpute spflow xcms ## ## Define stubs so that the serialized class definitions do not cause S4 ## machinery to throw warnings or errors. Remove the stubs once binaries ## in most repositories seem to have been rebuilt under Matrix 1.7-0. setClass("compMatrix") setClass("pcorMatrix") setClassUnion("replValueSp") rm(.new, .initialize) Matrix/R/kronecker.R0000644000175100001440000010410214561451364014052 0ustar hornikusers## METHODS FOR GENERIC: kronecker ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ kroneckerDN <- function(dnX, dX = lengths(dnX, FALSE), dnY, dY = lengths(dnX, FALSE), sep = ":") { dnr <- list(NULL, NULL) if(identical(dnX, dnr) && identical(dnY, dnr)) return(NULL) for(i in 1:2) { if(have.sX <- (nY <- dY[i]) && !is.null(sX <- dnX[[i]])) sX <- rep (sX, each = nY) if(have.sY <- (nX <- dX[i]) && !is.null(sY <- dnY[[i]])) sY <- rep.int(sY, times = nX) dnr[[i]] <- if(have.sX && have.sY) paste0(sX, sep, sY) else if(have.sX) paste0(sX, sep ) else if(have.sY) paste0( sep, sY) else if(nX && nY) rep.int(sep, nX * nY) } dnr } setMethod("kronecker", c(X = "diagonalMatrix", Y = "diagonalMatrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) { if(!(missing(FUN) || identical(FUN, "*"))) stop(gettextf("'%s' method must use default %s=\"%s\"", "kronecker", "FUN", "*"), domain = NA) if(any(as.double(dX <- X@Dim) * (dY <- Y@Dim) > .Machine$integer.max)) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) r <- new("ddiMatrix") r@Dim <- dX * dY uX <- X@diag != "N" uY <- Y@diag != "N" if(uX && uY) r@diag <- "U" else { if(!uX) { X.ii <- X@x if(.M.kind(X) == "n" && anyNA(X.ii)) X.ii <- X.ii | is.na(X.ii) } if(!uY) { Y.ii <- Y@x if(.M.kind(Y) == "n" && anyNA(Y.ii)) Y.ii <- Y.ii | is.na(Y.ii) } r@x <- if(uX) rep.int(as.double(Y.ii), dX[1L]) else if(uY) rep(as.double(X.ii), each = dY[1L]) else rep(X.ii, each = dY[1L]) * Y.ii } if(make.dimnames && !is.null(dnr <- kroneckerDN(dimnames(X), dX, dimnames(Y), dY))) r@Dimnames <- dnr r }) if(FALSE) { # --NOT YET-- setMethod("kronecker", c(X = "diagonalMatrix", Y = "denseMatrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) { if(!(missing(FUN) || identical(FUN, "*"))) stop(gettextf("'%s' method must use default %s=\"%s\"", "kronecker", "FUN", "*"), domain = NA) if(any(as.double(dX <- X@Dim) * (dY <- Y@Dim) > .Machine$integer.max)) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) uX <- X@diag != "N" uY <- FALSE shape <- .M.shape(Y) r <- new(`substr<-`("d.CMatrix", 2L, 2L, shape)) r@Dim <- dr <- dX * dY if(shape != "g") { uplo <- r@uplo <- Y@uplo if(shape == "t") uY <- Y@diag != "N" } if(!all(dr)) { r@p <- integer(dr[2L] + 1) if(uX && uY) r@diag <- "U" } else { m <- dY[1L] nX <- dX[1L] nY <- length(y <- Y@x) if(shape != "g" && nY > 1L && nY == prod(dY)) { Y <- pack(Y) nY <- length(y <- Y@x) } if(as.double(nX) * nY > .Machine$integer.max) stop(gettextf("number of nonzero entries cannot exceed %s", "2^31-1"), domain = NA) if(!uX && uY) { diag(Y) <- TRUE nY <- length(y <- Y@x) } if(is.logical(y) && .M.kind(Y) == "n") y <- y | is.na(y) if(shape == "g") { r@p <- seq.int(0L, by = m, length.out = dr[2L] + 1) r@i <- rep(seq.int(0L, by = m, length.out = nX), each = nY) + 0:(m-1L) } else if(uplo == "U") { r@p <- c(0L, cumsum(rep.int(1:m, nX))) r@i <- rep(seq.int(0L, by = m, length.out = nX), each = nY) + sequence.default(nvec = 1:m, from = 0L) } else { r@p <- c(0L, cumsum(rep.int(m:1, nX))) r@i <- rep(seq.int(0L, by = m, length.out = nX), each = nY) + sequence.default(nvec = m:1, from = 0:(m-1L)) } r@x <- if(uX) rep.int(as.double(y), nX) else { X.ii <- X@x if(.M.kind(X) == "n" && anyNA(X.ii)) X.ii <- X.ii | is.na(X.ii) as.double(y) * rep(X.ii, each = nY) } if(uX && uY) r <- ..diagN2U(r, sparse = TRUE) } if(make.dimnames && !is.null(dnr <- kroneckerDN(dimnames(X), dX, dimnames(Y), dY))) { if(shape == "s" && !isSymmetricDN(dnr)) r <- .M2gen(r) r@Dimnames <- dnr } r }) setMethod("kronecker", c(X = "denseMatrix", Y = "diagonalMatrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) { if(!(missing(FUN) || identical(FUN, "*"))) stop(gettextf("'%s' method must use default %s=\"%s\"", "kronecker", "FUN", "*"), domain = NA) if(any(as.double(dX <- X@Dim) * (dY <- Y@Dim) > .Machine$integer.max)) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) shape <- .M.shape(X) uX <- FALSE uY <- Y@diag != "N" r <- new(`substr<-`("d.CMatrix", 2L, 2L, shape)) r@Dim <- dr <- dX * dY if(shape != "g") { uplo <- r@uplo <- X@uplo if(shape == "t") uX <- X@diag != "N" } if(!all(dr)) { r@p <- integer(dr[2L] + 1) if(uX && uY) r@diag <- "U" } else { m <- dX[1L] n <- dX[2L] nX <- length(x <- X@x) nY <- dY[1L] if(shape != "g" && nX > 1L && nX == prod(dX)) { X <- pack(X) nX <- length(x <- X@x) } if(as.double(nX) * nY > .Machine$integer.max) stop(gettextf("number of nonzero entries cannot exceed %s", "2^31-1"), domain = NA) if(uX && !uY) { diag(X) <- TRUE nX <- length(x <- X@x) } if(is.logical(x) && .M.kind(X) == "n") x <- x | is.na(x) if(shape == "g") { x. <- function() { j <- rep(1:n, each = nY) as.vector(`dim<-`(as.double(x), dX)[, j]) } r@p <- seq.int(0L, by = m, length.out = dr[2L] + 1) r@i <- rep.int(sequence.default(nvec = rep.int(m, nY), from = 0:(nY-1L), by = nY), n) r@x <- if(uY) x.() else { Y.ii <- Y@x if(.M.kind(Y) == "n" && anyNA(Y.ii)) Y.ii <- Y.ii | is.na(Y.ii) x.() * rep(Y.ii, each = m) } } else if(uplo == "U") { rep.1.n <- rep(1:n, each = nY) s <- sequence.default( nvec = rep.1.n, from = rep(1L + cumsum(0:(n-1L)), each = nY), by = 1L) r@p <- c(0L, cumsum(rep.1.n)) r@i <- sequence.default(nvec = rep.1.n, from = rep.int(0:(nY-1L), n), by = nY) r@x <- if(uY) as.double(x)[s] else as.double(x)[s] * rep.int(rep.int(Y@x, n), rep.1.n) } else { rep.n.1 <- rep(n:1, each = nY) s <- sequence.default( nvec = rep.n.1, from = rep(1L + cumsum(c(0L, if(n > 1L) n:2)), each = nY), by = 1L) r@p <- c(0L, cumsum(rep.n.1)) r@i <- sequence.default(nvec = rep.n.1, from = 0:(n*nY-1L), by = nY) r@x <- if(uY) as.double(x)[s] else as.double(x)[s] * rep.int(rep.int(Y@x, n), rep.n.1) } if(uX && uY) r <- ..diagN2U(r, sparse = TRUE) } if(make.dimnames && !is.null(dnr <- kroneckerDN(dimnames(X), dX, dimnames(Y), dY))) { if(shape == "s" && !isSymmetricDN(dnr)) r <- .M2gen(r) r@Dimnames <- dnr } r }) } # --NOT YET-- setMethod("kronecker", c(X = "denseMatrix", Y = "denseMatrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) { if(!(missing(FUN) || identical(FUN, "*"))) stop(gettextf("'%s' method must use default %s=\"%s\"", "kronecker", "FUN", "*"), domain = NA) if(any(as.double(dX <- X@Dim) * (dY <- Y@Dim) > .Machine$integer.max)) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) shape <- switch(.M.shape(X), g = "g", t = if(.M.shape(Y) == "t" && X@uplo == Y@uplo) "t" else "g", s = if(.M.shape(Y) == "s") "s" else "g") r <- new(switch(shape, g = "dgeMatrix", t = "dtrMatrix", s = "dsyMatrix")) r@Dim <- dr <- dX * dY if(shape != "g") { r@uplo <- X@uplo if(shape == "t" && X@diag != "N" && Y@diag != "N") r@diag <- "U" } if(all(dr)) { X <- .M2m(X) Y <- .M2m(Y) storage.mode(X) <- "double" storage.mode(Y) <- "double" r@x <- as.vector(X[rep(seq_len(dX[1L]), each = dY[1L]), rep(seq_len(dX[2L]), each = dY[2L])]) * as.vector(Y[rep.int(seq_len(dY[1L]), dX[1L]), ]) } if(make.dimnames && !is.null(dnr <- kroneckerDN(dimnames(X), dX, dimnames(Y), dY))) { if(shape == "s" && !isSymmetricDN(dnr)) r <- .M2gen(r) r@Dimnames <- dnr } r }) setMethod("kronecker", c(X = "diagonalMatrix", Y = "CsparseMatrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) { if(!(missing(FUN) || identical(FUN, "*"))) stop(gettextf("'%s' method must use default %s=\"%s\"", "kronecker", "FUN", "*"), domain = NA) if(any(as.double(dX <- X@Dim) * (dY <- Y@Dim) > .Machine$integer.max)) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) uX <- X@diag != "N" uY <- FALSE shape <- .M.shape(Y) r <- new(`substr<-`("d.CMatrix", 2L, 2L, shape)) r@Dim <- dr <- dX * dY if(shape != "g") { r@uplo <- Y@uplo if(shape == "t" && (uX & (uY <- Y@diag != "N"))) r@diag <- "U" } if(!all(dr)) r@p <- integer(dr[2L] + 1) else { if(!uX && uY) Y <- ..diagU2N(Y) if((nY <- (p <- Y@p)[length(p)]) == 0L) r@p <- integer(dr[2L] + 1) else if(as.double(nX <- dX[1L]) * nY > .Machine$integer.max) stop(gettextf("number of nonzero entries cannot exceed %s", "2^31-1"), domain = NA) else { head. <- if(length(Y@i) > nY) function(x) x[seq_len(nY)] else identity r@p <- c(0L, cumsum(rep.int(p[-1L] - p[-length(p)], nX))) r@i <- rep(seq.int(0L, by = dY[1L], length.out = nX), each = nY) + head.(Y@i) r@x <- if(uX) { if(.M.kind(Y) == "n") rep.int(1, nX * nY) else rep.int(as.double(head.(Y@x)), nX) } else { X.ii <- X@x if(.M.kind(X) == "n" && anyNA(X.ii)) X.ii <- X.ii | is.na(X.ii) if(.M.kind(Y) == "n") rep(as.double(X.ii), each = nY) else rep(as.double(X.ii), each = nY) * as.double(head.(Y@x)) } } } if(make.dimnames && !is.null(dnr <- kroneckerDN(dimnames(X), dX, dimnames(Y), dY))) { if(shape == "s" && !isSymmetricDN(dnr)) r <- .M2gen(r) r@Dimnames <- dnr } r }) setMethod("kronecker", c(X = "CsparseMatrix", Y = "diagonalMatrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) { if(!(missing(FUN) || identical(FUN, "*"))) stop(gettextf("'%s' method must use default %s=\"%s\"", "kronecker", "FUN", "*"), domain = NA) if(any(as.double(dX <- X@Dim) * (dY <- Y@Dim) > .Machine$integer.max)) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) uX <- FALSE uY <- Y@diag != "N" shape <- .M.shape(X) r <- new(`substr<-`("d.CMatrix", 2L, 2L, shape)) r@Dim <- dr <- dX * dY if(shape != "g") { r@uplo <- X@uplo if(shape == "t" && (uX <- X@diag != "N") && uY) r@diag <- "U" } if(!all(dr)) r@p <- integer(dr[2L] + 1) else { if(uX && !uY) X <- ..diagU2N(X) if((nX <- (p <- X@p)[length(p)]) == 0L) r@p <- integer(dr[2L] + 1) else if(as.double(nY <- dY[1L]) * nX > .Machine$integer.max) stop(gettextf("number of nonzero entries cannot exceed %s", "2^31-1"), domain = NA) else { dp <- p[-1L] - p[-length(p)] j. <- which(dp > 0L) nj. <- length(j.) rep.dp <- rep(dp[j.], each = nY) s. <- sequence.default( nvec = rep.dp, from = rep(1L + p[j.], each = nY), by = 1L) r@p <- c(0L, cumsum(rep(dp, each = nY))) r@i <- (nY * X@i)[s.] + rep.int(rep.int(0:(nY-1L), nj.), rep.dp) r@x <- if(uY) { if(.M.kind(X) == "n") rep.int(1, nX * nY) else as.double(X@x)[s.] } else { Y.ii <- Y@x if(.M.kind(Y) == "n" && anyNA(Y.ii)) Y.ii <- Y.ii | is.na(Y.ii) if(.M.kind(X) == "n") rep.int(rep.int(as.double(Y.ii), nj.), rep.dp) else rep.int(rep.int(as.double(Y.ii), nj.), rep.dp) * as.double(X@x)[s.] } } } if(make.dimnames && !is.null(dnr <- kroneckerDN(dimnames(X), dX, dimnames(Y), dY))) { if(shape == "s" && !isSymmetricDN(dnr)) r <- .M2gen(r) r@Dimnames <- dnr } r }) setMethod("kronecker", c(X = "CsparseMatrix", Y = "CsparseMatrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) { if(!(missing(FUN) || identical(FUN, "*"))) stop(gettextf("'%s' method must use default %s=\"%s\"", "kronecker", "FUN", "*"), domain = NA) if(any(as.double(dX <- X@Dim) * (dY <- Y@Dim) > .Machine$integer.max)) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) uX <- uY <- FALSE if((sX <- .M.shape(X)) == "t") uX <- X@diag != "N" if((sY <- .M.shape(Y)) == "t") uY <- Y@diag != "N" shape <- switch(sX, g = "g", t = if(sY == "t" && X@uplo == Y@uplo) "t" else "g", s = if(sY == "s") "s" else "g") cl <- "d.CMatrix" if(!all(dr <- dX * dY)) { substr(cl, 2L, 2L) <- shape r <- new(cl) r@Dim <- dr r@p <- integer(dr[2L] + 1) if(shape != "g") { r@uplo <- X@uplo if(shape == "t" && uX && uY) r@diag <- "U" } } else { substr(cl, 2L, 2L) <- if(shape == "s") "g" else shape r <- new(cl) r@Dim <- dr if(uX) X <- ..diagU2N(X) if(uY) Y <- ..diagU2N(Y) if(sY == "s") Y <- .M2gen(Y) else if(sX == "s") X <- .M2gen(X) if((nX <- (pX <- X@p)[length(pX)]) == 0L || (nY <- (pY <- Y@p)[length(pY)]) == 0L) r@p <- integer(dr[2L] + 1) else if(as.double(nX) * nY > .Machine$integer.max) stop(gettextf("number of nonzero entries cannot exceed %s", "2^31-1"), domain = NA) else { dpX <- pX[-1L] - (pX. <- pX[-length(pX)]) dpY <- pY[-1L] - (pY. <- pY[-length(pY)]) rep.dpX <- rep(dpX, each = dY[2L]) rep.dpY <- rep.int(dpY, dX[2L]) t1 <- rep.int(rep.dpY, rep.dpX) s1 <- sequence.default( nvec = rep.dpX, from = rep(1L + pX., each = dY[2L]), by = 1L) s2 <- sequence.default( nvec = t1, from = rep.int(rep.int(1L + pY., dX[2L]), rep.dpX), by = 1L) r@p <- c(0L, cumsum(rep.dpX * dpY)) r@i <- rep.int((dY[1L] * X@i)[s1], t1) + Y@i[s2] r@x <- if(.M.kind(X) == "n") { if(.M.kind(Y) == "n") rep.int(1, nX * nY) else as.double(Y@x)[s2] } else { if(.M.kind(Y) == "n") rep.int(as.double(X@x)[s1], t1) else rep.int(as.double(X@x)[s1], t1) * as.double(Y@x)[s2] } } if(shape == "t") { r@uplo <- X@uplo if(uX && uY) r <- ..diagN2U(r, sparse = TRUE) } else if(shape == "s") r <- .Call(R_sparse_force_symmetric, r, X@uplo) } if(make.dimnames && !is.null(dnr <- kroneckerDN(dimnames(X), dX, dimnames(Y), dY))) { if(shape == "s" && !isSymmetricDN(dnr)) r <- .M2gen(r) r@Dimnames <- dnr } r }) setMethod("kronecker", c(X = "diagonalMatrix", Y = "RsparseMatrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) .tCRT(kronecker(t(X), .tCRT(Y), FUN, make.dimnames, ...))) setMethod("kronecker", c(X = "RsparseMatrix", Y = "diagonalMatrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) .tCRT(kronecker(.tCRT(X), t(Y), FUN, make.dimnames, ...))) setMethod("kronecker", c(X = "RsparseMatrix", Y = "RsparseMatrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) .tCRT(kronecker(.tCRT(X), .tCRT(Y), FUN, make.dimnames, ...))) setMethod("kronecker", c(X = "diagonalMatrix", Y = "TsparseMatrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) { if(!(missing(FUN) || identical(FUN, "*"))) stop(gettextf("'%s' method must use default %s=\"%s\"", "kronecker", "FUN", "*"), domain = NA) if(any(as.double(dX <- X@Dim) * (dY <- Y@Dim) > .Machine$integer.max)) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) uX <- X@diag != "N" uY <- FALSE shape <- .M.shape(Y) r <- new(`substr<-`("d.TMatrix", 2L, 2L, shape)) r@Dim <- dr <- dX * dY if(shape != "g") { r@uplo <- Y@uplo if(shape == "t" && (uX & (uY <- Y@diag != "N"))) r@diag <- "U" } if(all(dr)) { if(any((kind <- .M.kind(Y)) == c("n", "l"))) Y <- aggregateT(Y) if(!uX && uY) Y <- ..diagU2N(Y) nX <- dX[1L] nY <- length(Y@i) r@i <- rep(seq.int(0L, by = dY[1L], length.out = nX), each = nY) + Y@i r@j <- rep(seq.int(0L, by = dY[2L], length.out = nX), each = nY) + Y@j r@x <- if(uX) { if(kind == "n") rep.int(1, as.double(nX) * nY) else rep.int(as.double(Y@x), nX) } else { X.ii <- X@x if(.M.kind(X) == "n" && anyNA(X.ii)) X.ii <- X.ii | is.na(X.ii) if(kind == "n") rep(as.double(X.ii), each = nY) else rep(as.double(X.ii), each = nY) * as.double(Y@x) } } if(make.dimnames && !is.null(dnr <- kroneckerDN(dimnames(X), dX, dimnames(Y), dY))) { if(shape == "s" && !isSymmetricDN(dnr)) r <- .M2gen(r) r@Dimnames <- dnr } r }) setMethod("kronecker", c(X = "TsparseMatrix", Y = "diagonalMatrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) { if(!(missing(FUN) || identical(FUN, "*"))) stop(gettextf("'%s' method must use default %s=\"%s\"", "kronecker", "FUN", "*"), domain = NA) if(any(as.double(dX <- X@Dim) * (dY <- Y@Dim) > .Machine$integer.max)) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) uX <- FALSE uY <- Y@diag != "N" shape <- .M.shape(X) r <- new(`substr<-`("d.TMatrix", 2L, 2L, shape)) r@Dim <- dr <- dX * dY if(shape != "g") { r@uplo <- X@uplo if(shape == "t" && (uX <- X@diag != "N") && uY) r@diag <- "U" } if(all(dr)) { if(any((kind <- .M.kind(X)) == c("n", "l"))) X <- aggregateT(X) if(uX && !uY) X <- ..diagU2N(X) nX <- length(X@i) nY <- dY[1L] r@i <- rep(nY * X@i, each = nY) + 0:(nY-1L) r@j <- rep(nY * X@j, each = nY) + 0:(nY-1L) r@x <- if(uY) { if(kind == "n") rep.int(1, as.double(nX) * nY) else rep(as.double(X@x), each = nY) } else { Y.ii <- Y@x if(.M.kind(Y) == "n" && anyNA(Y.ii)) Y.ii <- Y.ii | is.na(Y.ii) if(kind == "n") rep.int(as.double(Y.ii), nX) else rep(as.double(X@x), each = nY) * as.double(Y.ii) } } if(make.dimnames && !is.null(dnr <- kroneckerDN(dimnames(X), dX, dimnames(Y), dY))) { if(shape == "s" && !isSymmetricDN(dnr)) r <- .M2gen(r) r@Dimnames <- dnr } r }) setMethod("kronecker", c(X = "TsparseMatrix", Y = "TsparseMatrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) { if(!(missing(FUN) || identical(FUN, "*"))) stop(gettextf("'%s' method must use default %s=\"%s\"", "kronecker", "FUN", "*"), domain = NA) if(any(as.double(dX <- X@Dim) * (dY <- Y@Dim) > .Machine$integer.max)) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) uX <- uY <- FALSE if((sX <- .M.shape(X)) == "t") uX <- X@diag != "N" if((sY <- .M.shape(Y)) == "t") uY <- Y@diag != "N" shape <- switch(sX, g = "g", t = if(sY == "t" && X@uplo == Y@uplo) "t" else "g", s = if(sY == "s") "s" else "g") cl <- "d.TMatrix" if(!all(dr <- dX * dY)) { substr(cl, 2L, 2L) <- shape r <- new(cl) r@Dim <- dr if(shape != "g") { r@uplo <- X@uplo if(shape == "t" && uX && uY) r@diag <- "U" } } else { substr(cl, 2L, 2L) <- if(shape == "s") "g" else shape r <- new(cl) r@Dim <- dr if(uX) X <- ..diagU2N(X) if(uY) Y <- ..diagU2N(Y) if(sY == "s") Y <- .M2gen(Y) else if(sX == "s") X <- .M2gen(X) nY <- length(Y@i) r@i <- i. <- rep(dY[1L] * X@i, each = nY) + Y@i r@j <- rep(dY[2L] * X@j, each = nY) + Y@j r@x <- if(.M.kind(X) == "n") { if(.M.kind(Y) == "n") rep.int(1, length(i.)) else rep.int(as.double(X@x), nY) } else { if(.M.kind(Y) == "n") rep(as.double(X@x), each = nY) else rep(as.double(X@x), each = nY) * as.double(Y@x) } if(shape == "t") { r@uplo <- X@uplo if(uX && uY) r <- ..diagN2U(r, sparse = TRUE) } else if(shape == "s") r <- .Call(R_sparse_force_symmetric, r, X@uplo) } if(make.dimnames && !is.null(dnr <- kroneckerDN(dimnames(X), dX, dimnames(Y), dY))) { if(shape == "s" && !isSymmetricDN(dnr)) r <- .M2gen(r) r@Dimnames <- dnr } r }) setMethod("kronecker", c(X = "diagonalMatrix", Y = "indMatrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) kronecker(X, .M2kind(Y, "n"), FUN, make.dimnames, ...)) setMethod("kronecker", c(X = "indMatrix", Y = "diagonalMatrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) kronecker(.M2kind(X, "n"), Y, FUN, make.dimnames, ...)) setMethod("kronecker", c(X = "indMatrix", Y = "indMatrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) { if((margin <- X@margin) != Y@margin) kronecker(.M2C(X), .M2C(Y), FUN, make.dimnames, ...) if(!(missing(FUN) || identical(FUN, "*"))) stop(gettextf("'%s' method must use default %s=\"%s\"", "kronecker", "FUN", "*"), domain = NA) if(any(as.double(dX <- X@Dim) * (dY <- Y@Dim) > .Machine$integer.max)) stop(gettextf("dimensions cannot exceed %s", "2^31-1"), domain = NA) r <- new("indMatrix") r@Dim <- dX * dY r@perm <- if(margin == 1L) rep(dY[2L] * (X@perm - 1L), each = dY[1L]) + rep.int(Y@perm, dX[1L]) else { r@margin <- 1L rep(dY[1L] * (X@perm - 1L), each = dY[2L]) + rep.int(Y@perm, dX[2L]) } if(make.dimnames && !is.null(dnr <- kroneckerDN(dimnames(X), dX, dimnames(Y), dY))) r@Dimnames <- dnr r }) ## Catch everything else with these: for(.cl in c("vector", "matrix")) { setMethod("kronecker", c(X = "Matrix", Y = .cl), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) kronecker(X, .m2dense(Y, ",ge"), FUN, make.dimnames, ...)) setMethod("kronecker", c(X = .cl, Y = "Matrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) kronecker(.m2dense(X, ",ge"), Y, FUN, make.dimnames, ...)) } rm(.cl) setMethod("kronecker", c(X = "denseMatrix", Y = "Matrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) kronecker(.M2C(X), Y, FUN, make.dimnames, ...)) setMethod("kronecker", c(X = "CsparseMatrix", Y = "Matrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) kronecker(X, .M2C(Y), FUN, make.dimnames, ...)) setMethod("kronecker", c(X = "RsparseMatrix", Y = "Matrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) kronecker(X, .M2R(Y), FUN, make.dimnames, ...)) setMethod("kronecker", c(X = "TsparseMatrix", Y = "Matrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) kronecker(X, .M2T(Y), FUN, make.dimnames, ...)) setMethod("kronecker", c(X = "diagonalMatrix", Y = "Matrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) kronecker(X, .M2C(Y), FUN, make.dimnames, ...)) setMethod("kronecker", c(X = "indMatrix", Y = "Matrix"), function(X, Y, FUN = "*", make.dimnames = FALSE, ...) kronecker(.M2kind(X, "n"), Y, FUN, make.dimnames, ...)) Matrix/MD50000644000175100001440000023717714612713767012103 0ustar hornikusers92c3a065d79c5ad365dc9416841788f5 *DESCRIPTION c7f467ed87d2f96f60dd6b8961a663ce *LICENCE f04972d7f10ad2937dfb1de4f6c6c7c7 *NAMESPACE a58a091de2e94b45c0138bde737d538b *R/00_Class.R 41bdc701502b0096f23a48bde2df7b89 *R/00_Generic.R 7da139d7679777c9cc9ae7e7836ebbae *R/Auxiliaries.R 4975f5a0fd9a9fdcf3b13bf63ee99d7e *R/BunchKaufman.R 7addbe75a6db14ffbb7b7e9ed0a16eb6 *R/Cholesky.R 9c3bd08c92063dedca3e4c9d761a5c89 *R/HBMM.R 7acb17192c1c08969822defdd531e35a *R/KhatriRao.R 4715dfe5732cbb88e97dbe39cff8c2b3 *R/Math.R b8ed7055055d4db61d02649db783d99f *R/Ops.R 6fded25b40b5ce9df1b7c21b146e88ca *R/Schur.R 4160a8d9f5da92dd335613f11a3fa9cb *R/Summary.R 8c2a6592f967220f8a5cf78e14a14851 *R/abstract.R 704ca816662fa15acd2f84e160b7c5b5 *R/all.equal.R 55c2f2df4f72efa05ef0029391fa1bef *R/cbind2.R 85747aff2573a899b697e2e727120871 *R/coerce-SparseM.R ab5cc27deac115816214f76aa0ec9bdd *R/coerce-graph.R 996196fca23ef186887bf25b7c2a38ae *R/coerce.R faaca4bd5f9c91735e56475826a9054e *R/colSums.R 73f70ce30c4eb94c71d69d824173f8e3 *R/condest.R a848a0850272aac7b5562d679adaea69 *R/construct.R ad09a63a07c77ea099a97cfb93fae17b *R/dense.R dd5fa48bd2b6395bd94731d709e73401 *R/determinant.R b25edb9ac01ea9ac4293f407ed7465f4 *R/diagonal.R b32d3bb64c3dba7bc2448050d8621c3e *R/dim.R 1874278a72159af59fec5c30b9a04458 *R/expm.R 7cf8b373092f376510d6de3ea34ab4e0 *R/image.R e1de087188a64ce3ff7851cae9fe62e1 *R/index.R 602b98fd5ffcca26602c5597ce4ee764 *R/is.na.R 5745b60b872453b4e53606e693e9d2b2 *R/kappa.R cfd81d9b1c3a0b4c7ad8a5660902165c *R/kronecker.R e30af337433eb4baff5b1ab6769f0f0c *R/lu.R 9022dd898a0704ed5533ab6d6214d85e *R/matmult.R 31b8d3853f6bed848a0714af7e9f94df *R/models.R 8befb12aeaaa31bc53817f73d4528381 *R/nearPD.R 84321c0b552dda474de19ca8b48157c9 *R/nnzero.R 2c8428619f17bcbd37fb747c73ce4e1a *R/not.R e27d39d5a7447673a1dfed85545da15f *R/objects.R 66c8030926759f87234d58628bafe364 *R/perm.R e62f89c5bcce206ee1b30382abaa6501 *R/posdef.R aa7fa1623398ed5d9d9bf76f56cc4cfc *R/qr.R 49a56dab6ff6e6a943dda3bb4ccf46b7 *R/rankMatrix.R 914cbb2a388cf68d7f082f881b9e443e *R/show.R 8ede83ea067d09b6ec68fd28a3fd2ad5 *R/solve.R 2619c0795f6dec5772dd90732e012953 *R/sparse.R dc55221e0d0aeecd0b2e809c609c232c *R/subassign.R 33e9d68f6a81a8202ccee66d66b3ff39 *R/subscript.R fbed493ac3fea8c73a9b4b98a023208b *R/vector.R e783029cc758d4408ac5f20964eb1668 *R/which.R 76d33f26b453c96776207a060408fc6c *R/zzz.R f61db891eb928123aba4412ca322f508 *build/partial.rdb f009af65010965a4d03f2b74f90312df *build/vignette.rds c7ce869602cbdbcd1ab36489ac6c383c *cleanup 9f8e37cf17a5d4811d0c28f07148cf7d *data/CAex.R c60c038f2c6d15c5303d81330991c838 *data/KNex.R d6193dad1031a61ebc3d3e38fabd252d *data/USCounties.R 0d65337740b3914f535239cbe6e8a2df *data/datalist a40150a1c71deabec67e61af2b8f7e38 *data/wrld_1deg.R 0789a31935ec8eb3466f762c1fc435ca *inst/NEWS.Rd d1092f2de709b554fb06b516ee00a885 *inst/doc/Comparisons.R f6c9e4986022f1db4c085b8429d06fca *inst/doc/Comparisons.Rnw ee5a904a88014d2f0d4ca558c590ceec *inst/doc/Comparisons.pdf 3f45bdb5515081392d14b87f4770cb2b *inst/doc/Design-issues.R 2bd2896847fb11eaf102158b8696c884 *inst/doc/Design-issues.Rnw b6e3ce242aa2d0a04937dc53ccd47131 *inst/doc/Design-issues.pdf 3f87d045a10e0afc85a3385bab8f215b *inst/doc/Intro2Matrix.R 448278dab638a78df6eb59270772cbe2 *inst/doc/Intro2Matrix.Rnw c612bfbc57c0a4e6744a0b0b953f69ae *inst/doc/Intro2Matrix.pdf 1a59a7d3257a30349a5e10285ea05a69 *inst/doc/Introduction.R c39a26dfe7ccaafd044e88468155b153 *inst/doc/Introduction.Rnw b82bc189bfa9edde04825b03dece9c59 *inst/doc/Introduction.pdf 197c57692f593c8ea55f9bd482204c77 *inst/doc/SuiteSparse/AMD/Doc/ChangeLog 5ba3300acc9ddc20a56f6c843e2d5e13 *inst/doc/SuiteSparse/AMD/Doc/License.txt 02e708c21b24ce20b9ed5ff5c881c0ad *inst/doc/SuiteSparse/AMD/README.txt fadba81ab131063153f6d8a006489d43 *inst/doc/SuiteSparse/CAMD/Doc/ChangeLog 9207c2ee27101a898ff5fc1c60636cee *inst/doc/SuiteSparse/CAMD/Doc/License.txt 0a3d3e0ea1cdd23a0e1ba043d8f3e5b7 *inst/doc/SuiteSparse/CAMD/README.txt 5f0275bb876438e458cf4fa850c125d1 *inst/doc/SuiteSparse/CCOLAMD/Doc/ChangeLog 6f2bad59ec6185e681f66425faaf13f6 *inst/doc/SuiteSparse/CCOLAMD/Doc/License.txt cc929a77c3e1928dbba78e780bf57271 *inst/doc/SuiteSparse/CCOLAMD/README.txt 74daf33f0b4221fc7eb5c1b92c20406a *inst/doc/SuiteSparse/CHOLMOD/Doc/ChangeLog 56def293641dc4b931815801e87b5aea *inst/doc/SuiteSparse/CHOLMOD/Doc/License.txt e2e3a28ee0ee25c9c4f6a8ae91896919 *inst/doc/SuiteSparse/CHOLMOD/README.txt d48d9aea01ab2c8a17490cd535ea91a0 *inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/Changelog b46727c71b60d35ad5d2f927c4a3929b *inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/LICENSE.txt 97e88b1d5f940fb777a4476a8f03b9cc *inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt 777b89adea789c692bd7a1991e2133f7 *inst/doc/SuiteSparse/COLAMD/Doc/ChangeLog 93997dd55f2c98be2351a1e84f528ecc *inst/doc/SuiteSparse/COLAMD/Doc/License.txt 05d6553f58ebd8ae67a7047978857232 *inst/doc/SuiteSparse/COLAMD/README.txt 93bacdedfc09b9da90c13ee70496b5a1 *inst/doc/SuiteSparse/CXSparse/Doc/ChangeLog 0e5191611fba4aac850756c5d598ff23 *inst/doc/SuiteSparse/CXSparse/Doc/License.txt 172b7d2d9e266384ac9fb49333c00f87 *inst/doc/SuiteSparse/CXSparse/README.txt e90084a2277e2862233005ded90492b1 *inst/doc/SuiteSparse/ChangeLog 928c37b0d42ae82cbc723ab396df49f1 *inst/doc/SuiteSparse/LICENSE.txt aba05a2df94e2032b68cea74165a1366 *inst/doc/SuiteSparse/README.md dabbb8fc940f88cfe4fde254fad9dd68 *inst/doc/SuiteSparse/SuiteSparse_config/README.txt e4e486aee6a99cb21909bb6de32db68d *inst/doc/sparseModels.R 813e0c8cc7a5f7ecff43e5882270a431 *inst/doc/sparseModels.Rnw 77bdc7d031966d3e6f8642c9783c7543 *inst/doc/sparseModels.pdf dcd11f6947f910f743254824e930b2c7 *inst/external/CAex_slots.rda be886d6bb832210bb654b9ad064fe0ff *inst/external/KNex_slots.rda 90f019ec81e67d7f3542f7ca39bf3f2d *inst/external/USCounties_slots.rda ecf98cf53529ca8e794e48f1ce4e4bde *inst/external/Z_NA_rnk.rds f01fae298b6f33c20cef0ab32ee468c4 *inst/external/jgl009.mtx 47bc35200e7b3fc1cdd6ab1adbeef3a0 *inst/external/lund_a.mtx fc72dd2599982f25f9ffbfc75f149134 *inst/external/lund_a.rsa a5748e10322306f8c2114db09cd58dd8 *inst/external/pores_1.mtx 8758e19cf3478732e62e563b638bcda7 *inst/external/symA.rda 7980f700b4fd62d0d6de7f96201b2645 *inst/external/symW.rda 7e22a368a5d129fc7396432949fb72ab *inst/external/test3comp.rda 697db4242eb44425ce2550fafdc957a8 *inst/external/utm300.rua ca51a0b8b76e7ea3e7881cc8da1390b1 *inst/external/wrld_1deg_slots.rda 5ce5ea63a73e4641173fe37b6a809a01 *inst/external/wrong.mtx 9a7e9eac66c8e2e4f302ef50e52e7a56 *inst/include/Matrix.h 393d17634a64d5414c62d83cb4b05764 *inst/include/Matrix/Matrix.h a8f80507036f68ab0180c36e4d874abd *inst/include/Matrix/alloca.h 9453d69ed641a1842043a4b28b677784 *inst/include/Matrix/cholmod-utils.h d09f1ac35f40cd3b2b13495562a25403 *inst/include/Matrix/cholmod.h 851b528969721a8bfa532fd9ec412642 *inst/include/Matrix/remap.h f831983954808a8ea24f8e26507c1106 *inst/include/Matrix/stubs.c ea62d72933b31bafc521e98ad7726bfe *inst/include/Matrix/version.h 7d96680b80f7792dda638a3900abab51 *inst/include/Matrix_stubs.c 521f406135ff54057933d9a152482ec7 *inst/include/cholmod.h a4f45a0c66a82f35c7b077bc8c0df84a *inst/po/de/LC_MESSAGES/Matrix.mo e64d7f98b7b164d7519ae7f385ad91ba *inst/po/de/LC_MESSAGES/R-Matrix.mo ede270a9a427499b50e8c9227dcda678 *inst/po/en@quot/LC_MESSAGES/Matrix.mo 0eea1145d21cf382dd8af03ecf2871c2 *inst/po/en@quot/LC_MESSAGES/R-Matrix.mo 465f802628ce2dc2411c4692b1adabcc *inst/po/fr/LC_MESSAGES/Matrix.mo 205f3b581952a8f3ddbc4d4cafa59ba4 *inst/po/fr/LC_MESSAGES/R-Matrix.mo ba54cc41253905c19132e40cde3221ca *inst/po/it/LC_MESSAGES/Matrix.mo 648f3d77497c576252e81fa04d8ca03c *inst/po/it/LC_MESSAGES/R-Matrix.mo 1a06a3263a69b9bdba7da729f74ce679 *inst/po/ko/LC_MESSAGES/Matrix.mo d06bf95a913cc6981ddc8d7c7c870b7f *inst/po/ko/LC_MESSAGES/R-Matrix.mo b39781bcd601e046b42000a3dda31144 *inst/po/lt/LC_MESSAGES/Matrix.mo b4d9022d77514c2a71fc5692ac69c80e *inst/po/lt/LC_MESSAGES/R-Matrix.mo 1fffca27569d6dcdd74aa86332159026 *inst/po/pl/LC_MESSAGES/Matrix.mo 71c78aeb12f673f7e0665cc97cec9c76 *inst/po/pl/LC_MESSAGES/R-Matrix.mo 034502e45766c6a27500e33f057ebc34 *inst/scripts/AMD.patch 7f8f10ce8bf5bca2f71563b7aab654f8 *inst/scripts/CAMD.patch 9c6e7727b17f05942b6344e69491f1a5 *inst/scripts/CCOLAMD.patch d33629a5cf9cf17965eba15c3f2b825f *inst/scripts/CHOLMOD.patch 84fcc7c23f439341cbf8924bbcb03a32 *inst/scripts/COLAMD.patch a0185ac1d1b48eeb1c185110db750a3b *inst/scripts/CXSparse.patch cab0d76221978a4043778b8ac58c08f6 *inst/scripts/SuiteSparse_config.patch 80078f39d759e7dcf1290e4a16cdb2de *inst/scripts/api.patch f5ccc9054c07b238429f3e94f0682057 *inst/scripts/disclaimer.txt 874580077f7ce7b51199d942871c4472 *inst/scripts/rules.mk f608eb6dc206cb334e370c379b9fd34b *inst/scripts/rules.sh e1debdf022931ea988475c00c106cc6c *inst/scripts/sources.mk c8ad087daa587aa9c0390f667960e71c *inst/scripts/ssget.sh b35536a6cf924e3eeac20633228eaa0a *inst/scripts/wall.patch 5d9af34027b624cf8ec958cbfdfe915b *inst/test-tools-1.R 253a8835d89c31946ba3410bd514b9df *inst/test-tools-Matrix.R c54af18acaf2a18fad0cfe5f4fe54e83 *inst/test-tools.R 2f258fd7ae54ca8e0c16d7538fb1810e *man/BunchKaufman-class.Rd cefbc46d17630ba3c2a013206b741886 *man/BunchKaufman-methods.Rd ea7ad17e8de043439cfdeebbb25ff032 *man/CAex.Rd 92742aec0dd21a1508adef2bfd9e52e9 *man/CHMfactor-class.Rd c867760baa3dee3b88eae2f615327b15 *man/Cholesky-class.Rd 24861c21d20212b2f2edef439656c07d *man/Cholesky-methods.Rd 967b9180ff69515cf75eeabd0212cc0f *man/CsparseMatrix-class.Rd bec00d32ab2f01ac1a0c10b85bf3508b *man/Diagonal.Rd 0cf81d62916c9f84c70bb3df8bac66f6 *man/Hilbert.Rd 245096209777000baa3d711f452beed0 *man/KNex.Rd 766bcb9db86ea1733136c73bdeb29508 *man/KhatriRao.Rd 1c40302d44471cf6630ce67f914519a3 *man/Matrix-class.Rd f9736310b1fc9e7650899c4e9a7f7c61 *man/Matrix-defunct.Rd e8e82ddfbec9066619d4e55cf99de506 *man/Matrix-deprecated.Rd 9d74e16af8d8612781eb7432f8194b1f *man/Matrix-notyet.Rd 598516534cf2b915ff341b4d63aad61d *man/Matrix.Rd 3c4bf32296b8480193fe30125bca1bb5 *man/MatrixClass.Rd 460b276819cf27a5a91859c8bf25a53b *man/MatrixFactorization-class.Rd 9342c1c4c46385d83ba6e153e98f93cb *man/RsparseMatrix-class.Rd 64047cfd57b039ebfe665176bbd6556e *man/Schur-class.Rd bb8e14699a2db8acd01a2b1383aadaed *man/Schur-methods.Rd afc8dc11f750be8e2baeb2f250502829 *man/TsparseMatrix-class.Rd 878b685a8830a6a9b246e271f08de034 *man/USCounties.Rd 3de3d37c17171bf90a417615ee83d74b *man/abIndex-class.Rd fcc83ecd00de345e89e3f4fd51544255 *man/abIseq.Rd 2b6cb5615438cdc36e89f5b96ff94baf *man/all.equal-methods.Rd a1fc3f49b50407991ef4c9be7ee7401e *man/asUniqueT.Rd 6648de3757eb262eb643c87f2d1945bd *man/band-methods.Rd bdbedf88db3709b91fee02404f570928 *man/bandSparse.Rd 0a71443575762f0c15fed79a880e117a *man/bdiag.Rd d9c43ef03b0db490d2548c4889c0ce1b *man/boolmatmult-methods.Rd d4d34696eceef2a9fb972a1db930f0a2 *man/cbind2-methods.Rd ae7ee7c0dd1c9f4181623dae808f4fe8 *man/chol-methods.Rd 93ca58a43078f2cf5f20f0dcd586d63e *man/chol2inv-methods.Rd d7da791c3f651790bd3762ceb2426c3c *man/coerce-methods-SparseM.Rd da8ce2fc366523d31ec02e036c8d4690 *man/coerce-methods-graph.Rd 57cf38160f8d7ca08c3c8e197a4be3fd *man/colSums-methods.Rd 37187eb2930421a7a8058dfe28420e4e *man/condest.Rd 1cf0376b9ef9184439c06de7864adaef *man/dMatrix-class.Rd af2b6fa724abf84be877a4552095e067 *man/ddenseMatrix-class.Rd 14120a7152aa753135199518d9df7865 *man/ddiMatrix-class.Rd b738442c0f0993f176337480e48b9d0d *man/denseLU-class.Rd 3185e295c17031665892edfcaad5fed6 *man/denseMatrix-class.Rd 97d2afdab45dca3b2818620845225870 *man/dgCMatrix-class.Rd c0b134f5e751f760f4f60495888439f2 *man/dgRMatrix-class.Rd a17c04aa44294870428deb29386a5fa2 *man/dgTMatrix-class.Rd f0407dddde00f3e54ca4d4b656a3c079 *man/dgeMatrix-class.Rd 837f10f351fac09f984104016461926d *man/diagU2N.Rd 287f4956dc7629d18dc3b8c09ddf7d1b *man/diagonalMatrix-class.Rd 1589473042f7a3649b2e231a96222512 *man/dimScale.Rd 326daf4ed53d4314f8b298f88da4ee95 *man/dmperm.Rd f4fd61ef08f415e8404145d32ee4c9bd *man/dpoMatrix-class.Rd 1b4b6104d111472373cfe1acdc605085 *man/drop0.Rd 0e3390f6d482c4a5cd4372639ebe6f6e *man/dsCMatrix-class.Rd 96ffdf3c526cec9d788b3ac9e0f958bd *man/dsRMatrix-class.Rd 0dfbd82b81b8881f3ddb4cf6ec8d8433 *man/dsparseMatrix-class.Rd a8bafd0cdbe3b86490e575ed1e3cf4b5 *man/dsyMatrix-class.Rd 8fc3d49bfa636ace0f9f09ff5726521d *man/dtCMatrix-class.Rd 09bad402e9ce15538b62fedc8641da36 *man/dtRMatrix-class-sparse.Rd a65c8694c345ab574ddd7ca26ab9b986 *man/dtpMatrix-class.Rd dbb9523ebdb9c6f90b6d42c5043dc104 *man/dtrMatrix-class-dense.Rd 38f82f7dca6fdce61f93f239cbcf66a4 *man/expand-methods.Rd 5349189c7d182d444a83d35768a2e626 *man/expm-methods.Rd 8e94ad028775467cd069de4afe77d804 *man/externalFormats.Rd 02c720f10b2ee80593bc385a9ba7dfb9 *man/facmul-methods.Rd 59db1566e0cf830e4198c57f977feeb2 *man/fastMisc.Rd b3a0c135476b28bf7569e96174bbeb8e *man/forceSymmetric-methods.Rd 544ea441f152320cf9a6e94c11ff84c0 *man/formatSparseM.Rd 1e87e9f223354c3d73f345fda4f6ef70 *man/generalMatrix-class.Rd 334d679156521d39c80673b7138736c8 *man/image-methods.Rd 35673a6311eb2119721fa1fdf91515a6 *man/indMatrix-class.Rd af0356f72a183c7664cfa368fa32eec2 *man/index-class.Rd cbb67630dfbac437f9d7e9a7648e03ed *man/invertPerm.Rd 44270ed554b737f9ebf9050ac16505c0 *man/is.na-methods.Rd 390ef00efc06f4e5ba986179f9be1f28 *man/is.null.DN.Rd d095e553e6911c14d31a319dfa3c9591 *man/isSymmetric-methods.Rd 767fe8a839b710ff0e6cc278be3f48d2 *man/isTriangular-methods.Rd 73fff25f929d0743e6c80ffa1d714d06 *man/kronecker-methods.Rd 7fc275d08b1b5122cf363ba3b047b78c *man/ldenseMatrix-class.Rd fa91e53c4ec47d073e09c126b3739244 *man/ldiMatrix-class.Rd 618fc22c94018fb2b422a93cb5a08ad0 *man/lgeMatrix-class.Rd abde048d69d2eda6825150f87cedf2a1 *man/lsparseMatrix-class.Rd ba8662010144ffc10b1f1504f8122950 *man/lsyMatrix-class.Rd a08a6989e10415fe94aadafeadeeb57c *man/ltrMatrix-class.Rd 4112592f1b2b7404a7b8506d8714b665 *man/lu-methods.Rd 4ca9cecf4789f9d6c063b1a7f0bc91df *man/macros/local.Rd e4b848a97c4d271ddd245ddb0757e604 *man/mat2triplet.Rd cbb84c3f84d7ae45ee527fd4c67a90dc *man/matmult-methods.Rd b1c829c1061f4b6d68baa86413b3312e *man/nMatrix-class.Rd bcc0684524ef635f554b0e473e40c07d *man/ndenseMatrix-class.Rd cc6c44c14a8392071abe325799cc90c2 *man/nearPD.Rd 28930b1c705719e6afcab8aea870ec0c *man/ngeMatrix-class.Rd fa06fd574d4e47d3c17d765b6d7b6018 *man/nnzero-methods.Rd 9ae810a456018192a784228abcececd9 *man/norm-methods.Rd 466b315ccdabd718aed3b2cc95696bd5 *man/nsparseMatrix-class.Rd abc1d387f0b990d7b92edf8179a7638a *man/nsyMatrix-class.Rd 9e2a8c507c74de92a095f0850af4826b *man/ntrMatrix-class.Rd 6ab28432582e3d39abf69ee16493fa9d *man/pMatrix-class.Rd 383e2680fab1ded76ded4d7a410e8dbf *man/pack-methods.Rd 6c1b89ecca5c60dd2e42fa334e2ef0ae *man/packedMatrix-class.Rd 7a5edaa1838bda4e6abcf02fb143ddab *man/printSpMatrix.Rd de39ac806d65094884fd40ec9a3d42a2 *man/qr-methods.Rd 6e3a120611604781386e5186158b0873 *man/rankMatrix.Rd e5d1405bf89e755ca3e9f08fffacc35b *man/rcond-methods.Rd e477841f445dcdc94519c80406941469 *man/rep2abI.Rd a4109e704374bad3ef6aab75ccb8f8d9 *man/rleDiff-class.Rd 9a4e3ae4ca031791c7c366b5db715334 *man/rsparsematrix.Rd b679593ae1622eff6a99dd11054d4dd1 *man/solve-methods.Rd 753adc3e257e2d4bc9d9cff17779ec15 *man/spMatrix.Rd fd22402875896e84469ab3e8b9a06856 *man/sparse.model.matrix.Rd 19907299c8cad824cc36fec5bf469499 *man/sparseLU-class.Rd f2ec428a78fc56b8281872efcd4e56d5 *man/sparseMatrix-class.Rd f4f5ea8780961c40e4eaa051cbcd0460 *man/sparseMatrix.Rd 9a608bc076c014029f02da234b0b5a59 *man/sparseQR-class.Rd 04f82b969b3d8aabe18bc566d29817c8 *man/sparseVector-class.Rd c44929260581afc4a5958dd01a3ce944 *man/sparseVector.Rd 0448ed6a278bcdb4bc2c5fbf1c3f5349 *man/subassign-methods.Rd 3af6c843afd6c5df234514a74d0b41fe *man/subscript-methods.Rd e7e76e3f1e0b6a74bfaabb85a91106db *man/symmetricMatrix-class.Rd 7844008e1a149822f8c5f6085bf7510f *man/symmpart-methods.Rd 66409f3da0094a78d44adfb7faf12b17 *man/triangularMatrix-class.Rd 2e7fd0a03a8b6a038cd856ee0b861e7a *man/unpackedMatrix-class.Rd 673d3bd30c6c5855e5ec845950ee8fdc *man/updown-methods.Rd 88a8da5ec55171d282a0ca47e0951a51 *man/wrld_1deg.Rd 990eb78c04d29838a9bc383377147c00 *po/Matrix.pot 0c81ae3c81dd69c87906ff6c31de2cdd *po/R-Matrix.pot a68fe47a5b6bdd957b6a3fb8420a5ff2 *po/R-de.po 8ffacc0b9e33a1956a937a5babe9e71d *po/R-fr.po 51d2f76faf7671251a82269da724a15d *po/R-it.po fcf74c3db597528384008708cb5de471 *po/R-ko.po 9629f0bcc9013a7e91d757b97e8b65b5 *po/R-lt.po 9fefb0957409373aa64ec83ca37075c8 *po/R-pl.po 5b6111d0c513b9e7c40e7128d207377d *po/de.po 1ed5b0c42d3749fea8c63d0987b71024 *po/fr.po f904b8169d772cf8cb356f8a6e11cc4c *po/it.po 90256387b2fe1ea51a7b6b0c7897e98c *po/ko.po 8d9494aa7eb938c53db11d5fc15cb4df *po/lt.po 6684fe7be6ed623042b7dad4dc2c2c77 *po/pl.po 3ef06bbf30f553eb1fadcca85b9956dc *src/Csparse.c 3dbc7f72c6ba0852474fb9547bf00489 *src/Csparse.h 42a5a13f71df7c64201fc5dfe518e0b4 *src/Lapack-etc.h 048d61c42ad6f8f9e76555eb8a24e851 *src/Makevars 6c9b4ba256a8beda2c6783290046b412 *src/Matrix-win.def 8ad63bef4e4f58201f7e39e3514cce18 *src/Mdefines.h 28438ed30c5bcfeb627f207b4bb81b7a *src/Msymbols.h 58b892a8ce17195862908b45d30fee4e *src/SuiteSparse/AMD/Include/amd.h fe3a147f6ee0b5dbbfea70f582e17024 *src/SuiteSparse/AMD/Include/amd_internal.h d8713d000652d21fa649b474976a134d *src/SuiteSparse/AMD/Makefile a7d4401bdbe21efb0f707378fcf79ab2 *src/SuiteSparse/AMD/Source/amd_1.c 36beec2a4ead899c32ca9eb8440d8cef *src/SuiteSparse/AMD/Source/amd_2.c 0f648efe56a732693314b8143460bc83 *src/SuiteSparse/AMD/Source/amd_aat.c 0006b2bd223f9fda2b8eed2fa30f06a4 *src/SuiteSparse/AMD/Source/amd_control.c 2900d1575bde0c793a0d5a90f65812ff *src/SuiteSparse/AMD/Source/amd_defaults.c 053075ceb4a9d223c135516265bb6d50 *src/SuiteSparse/AMD/Source/amd_dump.c 32b1619b35f7a61965d50a0d0d446945 *src/SuiteSparse/AMD/Source/amd_info.c 9fa4ffaec64c335a6438570d6bc4c5a2 *src/SuiteSparse/AMD/Source/amd_l1.c 62d06f79d08153f8a4317c292a64e1e9 *src/SuiteSparse/AMD/Source/amd_l2.c f9b1072c711febf080f727bf60bb3af7 *src/SuiteSparse/AMD/Source/amd_l_aat.c 6a24d5df91aa51f724f167ef281ff345 *src/SuiteSparse/AMD/Source/amd_l_control.c c751016d6eaf8f535b37f664730b1382 *src/SuiteSparse/AMD/Source/amd_l_defaults.c d96aa8e32b3541140b1ec5d544ba6ca0 *src/SuiteSparse/AMD/Source/amd_l_dump.c bfbab54186dfa7b6b13654cd2ad78430 *src/SuiteSparse/AMD/Source/amd_l_info.c 10b5bdad3544eb481373142426433369 *src/SuiteSparse/AMD/Source/amd_l_order.c 29c3fd44d8c35ad8ea1675317de59bf0 *src/SuiteSparse/AMD/Source/amd_l_post_tree.c acb86c4dd045546bc633504a91ee5e42 *src/SuiteSparse/AMD/Source/amd_l_postorder.c c45691344fa5afa07fe1c00ad2269e33 *src/SuiteSparse/AMD/Source/amd_l_preprocess.c 3bcf424d5b1a0423baa1cfe0c11a8baf *src/SuiteSparse/AMD/Source/amd_l_valid.c 86cc7c57079892e7f9f91cb55050c495 *src/SuiteSparse/AMD/Source/amd_order.c 56916a5de5ca5968ebeb87b312316e38 *src/SuiteSparse/AMD/Source/amd_post_tree.c f36cc632e05d19214276d35cce07f767 *src/SuiteSparse/AMD/Source/amd_postorder.c 949337218bdb8c27f3ff4c9d6f95ffb8 *src/SuiteSparse/AMD/Source/amd_preprocess.c 2551031e3d81e69a1bfb7b71473ef6a0 *src/SuiteSparse/AMD/Source/amd_valid.c 86b3c5668c66d7a5e44865fa0c5a0deb *src/SuiteSparse/AMD/Source/amd_version.c 67e7d56cae6c9d487dca0b64992f0875 *src/SuiteSparse/CAMD/Include/camd.h 46df1262f925b998e4355194aca61f68 *src/SuiteSparse/CAMD/Include/camd_internal.h 882eefcb4f4f8df0a1e04cbaa67b86f8 *src/SuiteSparse/CAMD/Makefile 96c56774f9589088a9c6d55ae6a2d279 *src/SuiteSparse/CAMD/Source/camd_1.c c62a33f01bff109b5f6917f86f789158 *src/SuiteSparse/CAMD/Source/camd_2.c 0cfef72a08e0f719510742ffef0136e3 *src/SuiteSparse/CAMD/Source/camd_aat.c 99256fe71367caed6fd80aac9e9d0e3a *src/SuiteSparse/CAMD/Source/camd_control.c 219e92673ef2ec8a859dbf57a5a953b2 *src/SuiteSparse/CAMD/Source/camd_defaults.c 9624642b8bb605a6fbc754e47b3d0769 *src/SuiteSparse/CAMD/Source/camd_dump.c 2800af4b0c7fd46883f7ecea7b7e1d43 *src/SuiteSparse/CAMD/Source/camd_info.c 0affc4ed34d4071f6219034d328fc6fc *src/SuiteSparse/CAMD/Source/camd_l1.c bae773b6329d541b0eb9d348825bde07 *src/SuiteSparse/CAMD/Source/camd_l2.c d78867e2a8a3b2e498807232b5910015 *src/SuiteSparse/CAMD/Source/camd_l_aat.c c76347f7b2109736ca8fb820cc0560f9 *src/SuiteSparse/CAMD/Source/camd_l_control.c 0e44d65bd75884bd5ce244b08c89c933 *src/SuiteSparse/CAMD/Source/camd_l_defaults.c 0a4a05bd75b5e863504467745f4c7811 *src/SuiteSparse/CAMD/Source/camd_l_dump.c 732a6d8f3d041866563e75ea69702bcb *src/SuiteSparse/CAMD/Source/camd_l_info.c 401b0e5417f1c781275635ec8665525d *src/SuiteSparse/CAMD/Source/camd_l_order.c 8a0052261690bdf13244a767566c2887 *src/SuiteSparse/CAMD/Source/camd_l_postorder.c 73720f148c30bbd2d28e7ee80668238a *src/SuiteSparse/CAMD/Source/camd_l_preprocess.c 3bef588c37365ae0f1cf71a5726af265 *src/SuiteSparse/CAMD/Source/camd_l_valid.c f2260dfcf61f017a8cc446dd8dd8c705 *src/SuiteSparse/CAMD/Source/camd_order.c ec0be1e8945aa1e43e4a0ce548eef496 *src/SuiteSparse/CAMD/Source/camd_postorder.c 574ef73f608f25f37b11f9d4fb7d17e2 *src/SuiteSparse/CAMD/Source/camd_preprocess.c b7fb35f1a2d310c7d34215be1488c43e *src/SuiteSparse/CAMD/Source/camd_valid.c 28fa61889939c1af1ca21661255fb161 *src/SuiteSparse/CAMD/Source/camd_version.c 977ef58abc51d1b9b1c8d6de658db92f *src/SuiteSparse/CCOLAMD/Include/ccolamd.h fde0baa607121606d0657dd2c3df5dfe *src/SuiteSparse/CCOLAMD/Makefile 4f551758db890932fd7a8e1108484840 *src/SuiteSparse/CCOLAMD/Source/ccolamd.c bdd0b79f0238cab0b2600dade44e85b9 *src/SuiteSparse/CCOLAMD/Source/ccolamd_l.c 73b33791675bcc264613b3f8d362f8cf *src/SuiteSparse/CCOLAMD/Source/ccolamd_version.c b4f4cee6163b2508637636fc581d6c00 *src/SuiteSparse/CHOLMOD/Check/cholmod_check.c 63bf972dafb68676a376f3211cf5a94a *src/SuiteSparse/CHOLMOD/Check/cholmod_l_check.c bf998bf49d781be289615aa14c0a7b0c *src/SuiteSparse/CHOLMOD/Check/cholmod_l_read.c 5d2a2f1d09e87dded444881044ed94fa *src/SuiteSparse/CHOLMOD/Check/cholmod_l_write.c 0178c4473e2f6af972137f1b045cec27 *src/SuiteSparse/CHOLMOD/Check/cholmod_read.c 62b51b065f544f61c9e307823c9d6ee9 *src/SuiteSparse/CHOLMOD/Check/cholmod_write.c 7e186ca5073f3a8a90c95d7b14b2e867 *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_amd.c 67f41e0b8b3e02d3ba29e99403e0e1ce *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_analyze.c db37da2ea0369d10197da288ab069fb1 *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_colamd.c f988074cb8940c9b6fda84315a347688 *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_etree.c 2dc2c6a8b467903ad97ff74b28cfecce *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_factorize.c 4bc3d6f0edcb8319da50afaaf9d0e8df *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_amd.c f702bce4d6d05c0cc5c181576f5080e1 *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_analyze.c 8ae579b17cc77e0fc59a4b31166e7b24 *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_colamd.c 1afc224178b8e58ddf15c357ea086ab6 *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_etree.c 735111c84227a91a32bb7708eb5760dd *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_factorize.c 76b3821290aab4897b4aa8b11c0bb769 *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_postorder.c f1853abddf6e57b69aa53b49a870798a *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_rcond.c a30c60895336e5f9095754466703a995 *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_resymbol.c 9e3a989207acde5d2b889cf0ac6386f6 *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_rowcolcounts.c 6f1811fa02be0bdd3af644d21d690f5d *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_rowfac.c 29494674bc0ae34447804ad94a81f52b *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_solve.c 44ecc2877ad756094376b593fe9f6713 *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_l_spsolve.c f25b907ea5d0daa95a13869267fce83d *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_postorder.c d3252845d1aed92f2e4632384f2d0ca1 *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_rcond.c bda3568c1204fe370fbe14f4bc9ee441 *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_resymbol.c 4e34f8f2201399a1ee722c7f911b8603 *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_rowcolcounts.c 2b06ea692aa354bee3d473ac088d9a40 *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_rowfac.c b58fb26d774b2209e355cd617f1a20f1 *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_solve.c 49452892c7fc1e9545ed33847b7bf578 *src/SuiteSparse/CHOLMOD/Cholesky/cholmod_spsolve.c e16fc75c98f42f8a45fcdbb78659c12f *src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_lsolve_template.c acdd2f854b5d1f80a5f98979488cc633 *src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_ltsolve_template.c b0fe74fd699f38f36ac905f935fc5630 *src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_psolve_worker.c facd7f932f971df5b3008388b203bda1 *src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_rcond_worker.c c0a5d4e0a4192f3448982d073914bf16 *src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_resymbol_worker.c 9cb774ba37248929d435174cf98b258f *src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_rowfac_worker.c f4521ce005c25f394c8ed13d11cce7bb *src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_solve_worker.c fac219d8c48446075c0a3d20c22025a5 *src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_spsolve_worker.c daf8f5d4d40afec713e448e008bc5462 *src/SuiteSparse/CHOLMOD/Include/cholmod.h 82cf9737a857213e3fbf8fa92f97abf5 *src/SuiteSparse/CHOLMOD/Include/cholmod_internal.h 2c0137c5ac6bef6fc8b9518983ced244 *src/SuiteSparse/CHOLMOD/Include/cholmod_template.h 3edb3a788eddcd686c28add0c41c1900 *src/SuiteSparse/CHOLMOD/Include/cholmod_types.h 7b10d2c7f5c47d090c546c97a824b382 *src/SuiteSparse/CHOLMOD/Makefile 4b020f04f831c880b3ce25bac4745717 *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_drop.c 840e21e35dbda2e541beec795b095a44 *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_horzcat.c 76a54ed97e5018711116b27d1022a926 *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_drop.c de72ed49a720de5ded329f60ad45a972 *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_horzcat.c 20c738171f1ed9e05d587e7c2b5414f2 *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_norm.c 80249626871b53869ef2035b51e00f25 *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_scale.c f1b9d3f65746b7275f315fafd05a3673 *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_sdmult.c 3e62e2d4a277afdf23fe5d36ca7d43c0 *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_ssmult.c 485b3d8c57fabbd858423db671058f44 *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_submatrix.c 3a71966007c0205452a0f079e823745a *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_symmetry.c 1e0e84dc633f8900403269498d5c2f0c *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_l_vertcat.c 25e3aed6f467abeb7541c02d8d47a716 *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_norm.c ceee00345db1a3474c704f1755d9412e *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_scale.c 6290827c944b93b0e9fe31040b84a53d *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_sdmult.c 1f23b3ccc87a96d08cb6741c13414295 *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_ssmult.c 112ea0b2f2dac3098e845526044544b8 *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_submatrix.c 72896b26b3fde3161e410733cbb5a740 *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_symmetry.c 1c2f1ea977c46a4075370a2d402b7c36 *src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_vertcat.c 0787603e047bfe2ff2e6dc1b2eec102b *src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_drop_worker.c a91e0c65d57fe78860f3a5e5bf19cb6b *src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_horzcat_worker.c 08832446513fe2402815bb25cbba6a59 *src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_norm_worker.c 9e6fb930e00065190fe9c6d8ba9affad *src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_scale_worker.c 234c4b279220471c01a522b37687de8d *src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_sdmult_worker.c 59c3919455d73e6ffb8054e2c1a0f2ab *src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_ssmult_worker.c f5a26e224a7db1662ea9a14311f452ed *src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_submatrix_worker.c 0afa0a9bd246ccb193c6b63657ead64c *src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_vertcat_worker.c e5ab11dc0c8efe46f2ef960c773aa6f3 *src/SuiteSparse/CHOLMOD/Modify/cholmod_l_rowadd.c e829745e818924019f89f2bfbc159166 *src/SuiteSparse/CHOLMOD/Modify/cholmod_l_rowdel.c 12e7eaade912399f810edcd8f9b8cd4a *src/SuiteSparse/CHOLMOD/Modify/cholmod_l_updown.c d91665c271f8c7867dc9c8503e7fc66a *src/SuiteSparse/CHOLMOD/Modify/cholmod_rowadd.c 6cb3b21cc78466b64b4b30d7d74689a6 *src/SuiteSparse/CHOLMOD/Modify/cholmod_rowdel.c 817bade6d617d954676918efb014b721 *src/SuiteSparse/CHOLMOD/Modify/cholmod_updown.c 9fa1f7e6a7d52b7063391ea6be00e519 *src/SuiteSparse/CHOLMOD/Modify/t_cholmod_rowadd_worker.c 83929d8f15152982ed2e668384e72efa *src/SuiteSparse/CHOLMOD/Modify/t_cholmod_rowdel_worker.c a8bf414e889c51c2e3e16fd4a8c15fcb *src/SuiteSparse/CHOLMOD/Modify/t_cholmod_updown_numkr.c 67d96d5da8b536f5b10070967f8b59fa *src/SuiteSparse/CHOLMOD/Modify/t_cholmod_updown_wdim.c 3dd1b49dccafa6451d8f1999f524850f *src/SuiteSparse/CHOLMOD/Modify/t_cholmod_updown_worker.c cfe64828940fff853302c363a331a67c *src/SuiteSparse/CHOLMOD/Partition/cholmod_camd.c ef9201b905ba47628cd8e3df95491a35 *src/SuiteSparse/CHOLMOD/Partition/cholmod_ccolamd.c bfae7eefb26fb595113b6e8066185082 *src/SuiteSparse/CHOLMOD/Partition/cholmod_csymamd.c 4893677c4fb7f23f152cce4c5d299c81 *src/SuiteSparse/CHOLMOD/Partition/cholmod_l_camd.c 0e0d28e98b75b8ed0c0cd6925a81fb99 *src/SuiteSparse/CHOLMOD/Partition/cholmod_l_ccolamd.c 31b267528be9be4c8eb90760d5fa8731 *src/SuiteSparse/CHOLMOD/Partition/cholmod_l_csymamd.c 9d4fca96cc7175c2ce25681e1a88f5a5 *src/SuiteSparse/CHOLMOD/Partition/cholmod_l_metis.c edacee3cf4a82efb7fc399330c1d1ff2 *src/SuiteSparse/CHOLMOD/Partition/cholmod_l_nesdis.c 81e0980d112bf28c434d942f5eedae20 *src/SuiteSparse/CHOLMOD/Partition/cholmod_metis.c e6ba9d6afdc0abf821c815b8fad8b6d7 *src/SuiteSparse/CHOLMOD/Partition/cholmod_metis_wrapper.c 0c9920e822b9133ed40a8f73d541ac49 *src/SuiteSparse/CHOLMOD/Partition/cholmod_metis_wrapper.h b85cb84838a5171633d92173222aba1d *src/SuiteSparse/CHOLMOD/Partition/cholmod_nesdis.c 5136576c5a8b8705ad684a6adffd9043 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/GKlib.h f62fdf012698516719ab414b2a858209 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/b64.c 79343a68dc4c8934457585b53d042a1b *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/blas.c 68cd952d2a344fc7e44d6011c636394b *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/conf/check_thread_storage.c 1115a205b8ca7ef49b5ccbe14fbdbfc5 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/csr.c a58bd30e3c55db4bcebe11882139af40 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/error.c 8c3b9054d021daea88f16922c3f98885 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/evaluate.c 64243de3ce97bb137bb6399595eab591 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/fkvkselect.c adc31fffb37dc7b98deb67a87cc8faa9 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/fs.c 43019e55af9eb4f11199144c99b4454c *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/getopt.c f44a3e36435433858eb611415568e697 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_arch.h 4c2c3d6a13672f79b7f1fd9826b7571c *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_defs.h 48994378387e95735987c4642e42e00b *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_externs.h 7dfdaf89437971583c0fbe4d4c409f4b *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_getopt.h dbd75474db601bd32dbcad98f51d085d *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_macros.h ed7338ac375a384a826dc991eab2c5f9 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_mkblas.h 67bf3b332b5a7e893737b7bb518f0628 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_mkmemory.h 463f2f9e159dca29712d3bdb2cc23303 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_mkpqueue.h baad8e99f354bb64449e49817709a2c3 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_mkpqueue2.h b43d3ab9f785c010ac8bcbf9a792d33f *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_mkrandom.h 1336b53db1b99f4aed50404ac55d34c0 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_mksort.h 4927916d398ad7024b2d0caeae283c3b *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_mkutils.h 62454d4325f4b9eade63839a423f6a29 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_proto.h 85ab0fe7d094efbdb3dc12fd91b12f4a *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_struct.h 9aeaca4b50ef567c3339a23393479740 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_types.h 45b7745121acfcdbc0a340fc4aa8fd09 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gkregex.c 6bcc5ea4dfa0a6cec8bfe020d1b341da *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gkregex.h a45a69874b4f26f0f543a4f7a96ea7cb *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/graph.c a06b381481f15d6293a20dfd87e54cc5 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/htable.c cc3d8bc125dec83773d0fc5142c79303 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/io.c 17aa3561adb89154a6c0f9575a7d1bea *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/itemsets.c 611ea52b06dd03933a74310da79416cd *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/mcore.c 0f6829adb1d38bad1fa398d552723f0a *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/memory.c fe5f2219bac2a9ea08b17861426ec87d *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/ms_inttypes.h 17ac9a0eccc8b618af7faf32ee686649 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/ms_stat.h 732d934cb05f782024a6992820873767 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/ms_stdint.h 36dac0100f49d16c701945db854c2110 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/omp.c 2559a52a8c51f68dd6641c5e9e2a9c31 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/original/GKlib.h 3a50ac1b6d320571b037ea8b62f1bf95 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/original/error.c b1bfad9ec31776be4cafce931f42ffbc *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/original/gk_arch.h cebcfd88aa1f25270254ebc3ce309e56 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/original/gk_mkrandom.h e6d2834efe4b81a073fdcaa0ed9d4126 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/original/gk_proto.h 40490fa2544628be49730d1d95c9291a *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/original/memory.c e087935ca81c098c413d3999af3b0673 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/pdb.c a25621da852b5fcfdb1f152e6cb72d5d *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/pqueue.c c24d34be631e0788cb721fa3a1d40e79 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/random.c ea368bb9c36f829642dd21d5447a3840 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/rw.c 6e0eb94483f3d67256033eec6e5389b0 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/seq.c 1b44755b292aac85bd0cb4df18f9697d *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/sort.c bef79ad651da2e071cdc136363c4c4eb *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/string.c 5d372bde20b7088045de3e48362adc2d *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/test/fis.c 16bd14ac6e1fe656a81019bdd58654c1 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/test/gkgraph.c d930544f832ad5c905d366d9f255a3cd *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/test/gksort.c e01504275fd7f7958c6c3e73f341870a *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/test/rw.c baff57d4a645b663f987be848a848741 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/test/strings.c 839a8dd4594347606f1e43c52f9eb0fb *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/timers.c f6b02a6127be490fb10dc09104253424 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/tokenizer.c 4ecf225453ebe75491ce39626ecce35b *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/util.c 15312281d1c9aae0cc6c35157319158b *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/include/metis.h abb6eb34b82794ec21a23bab7cf80330 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/include/original/metis.h 6558c2891aaf0b839e58b985060706e7 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/auxapi.c 004853b786fe0de2b8203a574ac75c66 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/balance.c d9a9af977868e49ae6be99090215cde1 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/bucketsort.c a51da08c61629fc13e65e2ef70683e76 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/checkgraph.c f971a2d52c1041d36eb0d5bb3f512b53 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/coarsen.c d3f9c00d84f8f1352e7e25bbc5ddfd26 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/compress.c 9f21e5821816727a4fc520f124c3fede *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/contig.c b20121177122db7422f73088872576c8 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/debug.c c47b8833bfb5995189b46d891bc62155 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/defs.h e19d1c52900ec549b36e6c9d1ad9ec60 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/fm.c ef8a42dfb8888a86aba56d889101a785 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/fortran.c 6c039d755a26b332af6fab488d564a45 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/frename.c aea25eabd1950be8ed4d09f427eb1f5d *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/gklib.c 9ddc68f2cc9dd752376eaffda1772050 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/gklib_defs.h 0a73238b00a39d66868c4e767bbf35c3 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/gklib_rename.h a947eeeff8c3dccb1fb524d854fb93fe *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/graph.c 43b2e72c350879357c60241546d22cce *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/initpart.c 1cb551902b9cc1c2aeca262fee5d71eb *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/kmetis.c b508151c3383ae4423f83528fd8d2920 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/kwayfm.c 2177ed2d7efa858538d9280eabb012c0 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/kwayrefine.c 160176dca69d05ca56c5fd7b603bc86f *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/macros.h 978bc8430c5f5657fdf654cee8d6abf6 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/mcutil.c 5250f895b3484282f06da01b47a42983 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/mesh.c 2b147fb678a9fef5b3e90d16b9f419e0 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/meshpart.c 1459aad18611c3de4bfe7290fd2d8e2d *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/metislib.h a307c11a051935b659d156bab168f1a4 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/minconn.c 2cc4f46da1cee7c016a05871454ba3df *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/mincover.c a3a92de1007cb88ef4f81e59c1fb047b *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/mmd.c dd33b865f8ccf8d8771c69fc88b9118d *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/ometis.c 1ea58caed336019fc88f1e85f856de3c *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/options.c 24e626a4ca73233df6094e9e3776cd84 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/parmetis.c 705eb52686ece2dfaf1738d0e125d578 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/pmetis.c d4adcdb60bebde47ce54b8f707f1e354 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/proto.h 32c1dadca6e5e978edcf6d2b2c0db67e *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/refine.c 57c1fe64241850098b02fa493465a5c5 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/rename.h e4ee0aebab2fc06d580066a860e2dca1 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/separator.c dab29731651b3d502f48841ef378de15 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/sfm.c b7db2d6ed39f35dc69056f92ca0c4f14 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/srefine.c bb3c0128cbc46ece3dab43e9356ca5f1 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/stat.c e8f60e708099107da38c821ebe56d450 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/stdheaders.h ed59d80201ab1539082b6fbd0da6808e *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/struct.h 2c93a611c5e87deb5bfacc7be1e05f85 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/timing.c 213dab13837554274ec836b620e84422 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/util.c 8a9bd959702801205b6bd1c2c71b4c44 *src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/wspace.c a0118ba542da57861e9fcb199325c23c *src/SuiteSparse/CHOLMOD/Supernodal/cholmod_l_super_numeric.c 7e67a4916586b4220da252d851e56a35 *src/SuiteSparse/CHOLMOD/Supernodal/cholmod_l_super_solve.c 248b9dd76a5d68fddeef5ef5fbf96364 *src/SuiteSparse/CHOLMOD/Supernodal/cholmod_l_super_symbolic.c dd958aebeba9281fc82125a7bdb77a98 *src/SuiteSparse/CHOLMOD/Supernodal/cholmod_super_numeric.c 9de779933b82289e430fec8e9af10cfc *src/SuiteSparse/CHOLMOD/Supernodal/cholmod_super_solve.c 9a9dc7c3b07ebd629ba0526306ccb7dc *src/SuiteSparse/CHOLMOD/Supernodal/cholmod_super_symbolic.c 6e5f0d0de8c64ca65d080f3ec309a1d9 *src/SuiteSparse/CHOLMOD/Supernodal/t_cholmod_super_numeric_worker.c d922480caef67a7e10ade5687223c7c1 *src/SuiteSparse/CHOLMOD/Supernodal/t_cholmod_super_solve_worker.c f8353492d7d7151aa9606e745b83e816 *src/SuiteSparse/CHOLMOD/Utility/cholmod_aat.c 2dac07bf24dc628ae68efaad9a42342e *src/SuiteSparse/CHOLMOD/Utility/cholmod_add.c efe4972ba48f2f735bce1b7004bc54b7 *src/SuiteSparse/CHOLMOD/Utility/cholmod_add_size_t.c 451f0a1c12a4b55ea3cb8ac7d2331f93 *src/SuiteSparse/CHOLMOD/Utility/cholmod_alloc_factor.c ffa34dfd44dc7862ceb862a148d0a6bf *src/SuiteSparse/CHOLMOD/Utility/cholmod_alloc_work.c 1146182184f5b08c2f5d7d63aa9ed5f3 *src/SuiteSparse/CHOLMOD/Utility/cholmod_allocate_dense.c b26ff9c0013ea220ba4801f671bd3de6 *src/SuiteSparse/CHOLMOD/Utility/cholmod_allocate_factor.c 0695e873c073cb544c8194d1c5582d59 *src/SuiteSparse/CHOLMOD/Utility/cholmod_allocate_sparse.c 0eaa9fb7668fafbf99efbc7e98554f2a *src/SuiteSparse/CHOLMOD/Utility/cholmod_allocate_triplet.c 4c7f8ea01d4429aeccf4f4685999f9e8 *src/SuiteSparse/CHOLMOD/Utility/cholmod_allocate_work.c 3428df3d8364eea9d1906e1937f18bb2 *src/SuiteSparse/CHOLMOD/Utility/cholmod_band.c 117d62b7965f3e24547ce21bb1bd0958 *src/SuiteSparse/CHOLMOD/Utility/cholmod_band_nnz.c 80d8d59cd388d49fce5a485c1e00947f *src/SuiteSparse/CHOLMOD/Utility/cholmod_calloc.c 145428780d6712f6da654de7f0ebb13f *src/SuiteSparse/CHOLMOD/Utility/cholmod_change_factor.c 284bd672f7b874067b3c459620db3583 *src/SuiteSparse/CHOLMOD/Utility/cholmod_clear_flag.c 48bd159d2b09238fb543132e7191502e *src/SuiteSparse/CHOLMOD/Utility/cholmod_copy.c db18872f7f1b62b8f994e1a51b3f6311 *src/SuiteSparse/CHOLMOD/Utility/cholmod_copy_dense.c 791eeb773047c487475540c131b25062 *src/SuiteSparse/CHOLMOD/Utility/cholmod_copy_dense2.c b54786f62a91c32c16d4232949f97f10 *src/SuiteSparse/CHOLMOD/Utility/cholmod_copy_factor.c 2823f7f3d5146c0d73de61ca8ea3d92b *src/SuiteSparse/CHOLMOD/Utility/cholmod_copy_sparse.c 07dcd5d48f27146c6c6a1a32b18772e8 *src/SuiteSparse/CHOLMOD/Utility/cholmod_copy_triplet.c b9d130d723a6759ff6cbd2f169c602b1 *src/SuiteSparse/CHOLMOD/Utility/cholmod_cumsum.c 74436a055f49ed3f60c32ec5f50c353a *src/SuiteSparse/CHOLMOD/Utility/cholmod_dbound.c 6b8dfb27024d13d0868200b384f37ac7 *src/SuiteSparse/CHOLMOD/Utility/cholmod_defaults.c bf568e77ac24050ea972f98233c9d2ea *src/SuiteSparse/CHOLMOD/Utility/cholmod_dense_nnz.c 6dc1bc3706ab83df114ae4025174ae5b *src/SuiteSparse/CHOLMOD/Utility/cholmod_dense_to_sparse.c c0f3ae08da403c7cb09a835693f7ade0 *src/SuiteSparse/CHOLMOD/Utility/cholmod_divcomplex.c 375f128471ad37fb42b75cc235cf8af9 *src/SuiteSparse/CHOLMOD/Utility/cholmod_ensure_dense.c 40566ee7a3701789d7b239d144abd459 *src/SuiteSparse/CHOLMOD/Utility/cholmod_error.c 3427c04c8406897a06b806a706b1bdda *src/SuiteSparse/CHOLMOD/Utility/cholmod_eye.c 372ab3a99336db0f929f4ae15bb71094 *src/SuiteSparse/CHOLMOD/Utility/cholmod_factor_to_sparse.c c5f37a23a1d5ae87807ddae3159b8d2e *src/SuiteSparse/CHOLMOD/Utility/cholmod_finish.c daf7c5d84b1843b2083a7626ef55221d *src/SuiteSparse/CHOLMOD/Utility/cholmod_free.c a197f6a2fc53ae6b18980ca23ac068e9 *src/SuiteSparse/CHOLMOD/Utility/cholmod_free_dense.c ffd9cc4ecc8b11937ac9351e00e2617f *src/SuiteSparse/CHOLMOD/Utility/cholmod_free_factor.c 1f889c715dd5a7b4093fde99659f2772 *src/SuiteSparse/CHOLMOD/Utility/cholmod_free_sparse.c c3d0371b63ddb70c8145f859c14ac883 *src/SuiteSparse/CHOLMOD/Utility/cholmod_free_triplet.c d00de9aec817a2320c304f051df8cea3 *src/SuiteSparse/CHOLMOD/Utility/cholmod_free_work.c 5f94be1edd11507b7953dc9cb2411f78 *src/SuiteSparse/CHOLMOD/Utility/cholmod_hypot.c 8a71344d1a2e001b91b4e74dcb52b1f6 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_aat.c a885f65c055aebebc2adabb9693fd16b *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_add.c 7146f9a1abafa6e86ffff34509845a4a *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_add_size_t.c 5a2093962c403eb6de446e4d193b77ea *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_alloc_factor.c 1d4f73838689c1564ae61c266f514864 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_alloc_work.c d18b2b5e3e45f9692877855c1d20ae16 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_allocate_dense.c 592c8af105a7dffe9228ef7d16679474 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_allocate_factor.c f858031fc2f91b348254f2b2c76476b9 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_allocate_sparse.c d9dee72ab21a7b2326874c0cfd955254 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_allocate_triplet.c b60a8a4dbebb407ac530c2bc74418ba7 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_allocate_work.c e8e90563be782dea12a1e009dd1fce20 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_band.c 7c6fb6d2705b97f8fcb4f99e4fbee75e *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_band_nnz.c 429d8ca97b71e320e30e722c15fde19b *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_calloc.c d383e818960c57cf524acded0145506b *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_change_factor.c 35a04825f00812ab440e76de4d82e977 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_clear_flag.c 6142b1e1769e0e5b715662e4d12c2ebe *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_copy.c dd9ecbac2f5eb34a1c2bf9bb46729851 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_copy_dense.c 7bbe3da21e3fd448d4f6758b35d0b1de *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_copy_dense2.c 94335dae67075a421d1aa4b36b55b0ce *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_copy_factor.c 9a6fd0019b250d1eb3e105ad3c3e4957 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_copy_sparse.c 6af64aa65535b04685b9663ee2cb2512 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_copy_triplet.c adfbd06eecf509f67861545a65cf992c *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_cumsum.c 37df9241ff4b8b6b83d92f27491d61e2 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_dbound.c 4086be9f8f906c60b3b0851d978acbbd *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_defaults.c 48a5150c3843d67805f96cfd065a3760 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_dense_nnz.c 69ab16b7df5fa5ce788305f79fd6e2a5 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_dense_to_sparse.c 9c64bb71a11de867f9b1f8d113722f05 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_divcomplex.c 3c8f0dbae3c491bf1c3e53edaff2bed2 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_ensure_dense.c 448435a64c1ba577b10632c495f10591 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_error.c 7b34a4588f93a16fec7aee575aab9c43 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_eye.c ddce27828db23ef7ef94a8fa772069eb *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_factor_to_sparse.c 6bc432620e0cc5e6ad64c1b0afb82747 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_finish.c 71f14ddaffdd788435980a1d9a1184be *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_free.c 6d5e0471ac40a202306a904ecf58758e *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_free_dense.c 08a1f8bf64a6e68fc9071564d7882cd7 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_free_factor.c 8986aace7704457b28cf1d8e27f844fa *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_free_sparse.c 71504d71141db3bd71004cd61d30fc5a *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_free_triplet.c 958b94607db51a42ed912dd09c63d2b6 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_free_work.c 7b36ac92992ab27b8483a8323fb11083 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_hypot.c 2adf8c01955fe8b700e2b4d8df41f789 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_malloc.c 6f2f53c8dc2a4faf578bdf2d06971307 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_maxrank.c 087c26a062961807d0b16ffbb329b4f2 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_mult_size_t.c 4614db0bc08891b6347ef4af6888eb72 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_nnz.c 381af37d566e97e6440ae6facd80eb71 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_ones.c ae7d432af9566adfc5bf47f7c7bcd6fc *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_pack_factor.c 59fea998ef9b318e42a4839dc291d5a8 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_ptranspose.c d617a260211f8c6da36ceb7e81f78b86 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_realloc.c 4ab2b13c41a9e7ee58f9f3138abbd1ea *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_realloc_multiple.c fc5f70d8b267e6c96e24160c0bd51eae *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_reallocate_column.c 20877561bd6dc6d1fefa8072ad87d84f *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_reallocate_factor.c de9e3903fe0789ccacb9d56b40c261be *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_reallocate_sparse.c ae6b8c45017da176fd4ff59754510b4f *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_reallocate_triplet.c aafef974877e078b319c2e7e92d2ad64 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_sbound.c 1e72cdc47a93074fea2e72f59c50087d *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_score_comp.c 5dd16849ff55cf93c5d61373237deb5c *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_set_empty.c 22b7da3b2dbccea2f95527841b4c1df0 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_sort.c 584a754b1ff45aafad6e3cbaa85389e6 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_sparse_to_dense.c 0a4fe83fd628892d39a35951099c93ac *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_sparse_to_triplet.c 8ea1b9b7632e867ed3b5aa4de7aa0084 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_speye.c 172fe18cca76d0204581d09f7285c93f *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_spzeros.c 8a3d5e7701dc52090d00ec4f42a3928f *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_start.c a14c19f3e3c40501c32d7b62a61afcfd *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_transpose.c c500d6a610ba57d4707dd0d0f24cebd8 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_transpose_sym.c 5c454a3d7858ec982c0319f6d9b0a141 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_transpose_unsym.c 734b74a8ae70f556d09dff64485ab84d *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_triplet_to_sparse.c 4bcd53151f3b918430f88049ddda8c45 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_version.c 83b81a47fb42dc8c808ac96a0f876391 *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_xtype.c 6bb82f7d1a52bc7590877d4e9270d13c *src/SuiteSparse/CHOLMOD/Utility/cholmod_l_zeros.c fd4d2a4c93737b0c943c1ab4a894cf1e *src/SuiteSparse/CHOLMOD/Utility/cholmod_malloc.c 23eb7c66f114bf74af7ccb3076280807 *src/SuiteSparse/CHOLMOD/Utility/cholmod_maxrank.c 0e54cf4d73c497ca62c40794e9d62f46 *src/SuiteSparse/CHOLMOD/Utility/cholmod_memdebug.c 04e79e8c3d9f663c3d367027639fe2fa *src/SuiteSparse/CHOLMOD/Utility/cholmod_mult_size_t.c af22a428433ac41c490973261f682c2d *src/SuiteSparse/CHOLMOD/Utility/cholmod_mult_uint64_t.c 09f6b14a6a35c93f6d7c73da64177c37 *src/SuiteSparse/CHOLMOD/Utility/cholmod_nnz.c 9261861ca1d8e89243a8e63013ef8368 *src/SuiteSparse/CHOLMOD/Utility/cholmod_ones.c db368b3a6f634be266f3565395be693a *src/SuiteSparse/CHOLMOD/Utility/cholmod_pack_factor.c 5503659328ae8ebafa0db9bc2efb02bb *src/SuiteSparse/CHOLMOD/Utility/cholmod_ptranspose.c d35746d0cf825b494f9cbcaf3e60a8ea *src/SuiteSparse/CHOLMOD/Utility/cholmod_realloc.c 35c3468e7c1c94bf003aec2ac3772297 *src/SuiteSparse/CHOLMOD/Utility/cholmod_realloc_multiple.c defa786c898c3da9d65decee2f8f3cbb *src/SuiteSparse/CHOLMOD/Utility/cholmod_reallocate_column.c 001ffb4cf63d795f3a0dd844b3798733 *src/SuiteSparse/CHOLMOD/Utility/cholmod_reallocate_factor.c 8a7bd92a573a660616d84e3190ea5afa *src/SuiteSparse/CHOLMOD/Utility/cholmod_reallocate_sparse.c bb518ad3a5597d00c9a9f41c807efe2d *src/SuiteSparse/CHOLMOD/Utility/cholmod_reallocate_triplet.c 586a6c3c0d585ebdaa9e92a6a4f17d4e *src/SuiteSparse/CHOLMOD/Utility/cholmod_sbound.c 2cdbefd8c860e6204dbff9b34bae4ef9 *src/SuiteSparse/CHOLMOD/Utility/cholmod_score_comp.c e64e4045d8ee032eade5f5ec86100276 *src/SuiteSparse/CHOLMOD/Utility/cholmod_set_empty.c 026228bc86a7baeb4413c9943d4395db *src/SuiteSparse/CHOLMOD/Utility/cholmod_sort.c df65f197019ce2c6fbdd917ddebe7d97 *src/SuiteSparse/CHOLMOD/Utility/cholmod_sparse_to_dense.c 342a20b5602cfc3614a6656cc0150958 *src/SuiteSparse/CHOLMOD/Utility/cholmod_sparse_to_triplet.c c480fdf2cbcc6025f9a604dfd5eedbd0 *src/SuiteSparse/CHOLMOD/Utility/cholmod_speye.c d503cc78283fec107487957ea57f9995 *src/SuiteSparse/CHOLMOD/Utility/cholmod_spzeros.c f5154ac5d7c42b99a10cc338c6fa80cf *src/SuiteSparse/CHOLMOD/Utility/cholmod_start.c 17062526a825cbf0aab00bd94066d93d *src/SuiteSparse/CHOLMOD/Utility/cholmod_transpose.c bcc22fbc333fe9d060cc3c128fe32cbd *src/SuiteSparse/CHOLMOD/Utility/cholmod_transpose_sym.c cf78af0fa86d8294cf23b424bc7f6a6b *src/SuiteSparse/CHOLMOD/Utility/cholmod_transpose_unsym.c 97caa8bc027f7edbabbecbcc0fb29f18 *src/SuiteSparse/CHOLMOD/Utility/cholmod_triplet_to_sparse.c aa6a328fb4455a9843a36fa6e3bb04af *src/SuiteSparse/CHOLMOD/Utility/cholmod_version.c 3672fb3cb4990a4f297b49ab3d6fe5aa *src/SuiteSparse/CHOLMOD/Utility/cholmod_xtype.c 7fa3e2d6e6f41a1a7112dbabdc7a7028 *src/SuiteSparse/CHOLMOD/Utility/cholmod_zeros.c 3b59df79b6d832887af9adf4f58a1554 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_aat.c be7ce9990c85eba66ed75476e04107c6 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_aat_worker.c abe421c4fe5779f37c34353453c65d58 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_add.c c92c117a8815b4c52852440f84fc7ebe *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_add_size_t.c 82d14a79da891c3188770b245715de42 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_add_worker.c 66be7e270b39317995c91e99c241b9c3 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_alloc_factor.c 8f6d5de2a8630fd9712249b94d1beb0a *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_alloc_work.c f797ffd171c56fb727c65035a943e817 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_allocate_dense.c 1c212d8216dd18000efa69d51c282bff *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_allocate_sparse.c 2f7781ee25ee2734b38b3239f6f6ce7f *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_allocate_triplet.c 7df4e74ff1211e8c3c12064f20cba8b9 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_band.c 6d2c7b373785c69c7f4a2ab137114b85 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_band_nnz.c 60252e3424f2fae8bc155f25bc677788 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_band_worker.c 4c471e0995cb685479583390e284db9b *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_bound.c 1a96696a60fd9b6bd9e5c6d851bbea2d *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor.c b08274fd3ba27d2e00110a150ec5288c *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_1_worker.c 6ebf33102de811af79aaf323fb81d1d0 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_2_template.c 5c0ca90632f0294b51b53adcdb7bab5e *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_2_worker.c ce6174011c83c1a1f480d0f60905e099 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_3_template.c 9c49736c4faaa474bdbbf4401d8ec9c0 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_3_worker.c 0e73503ad0043c9f0986b0b1da5c72ba *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_xdtype.c bffcaa47a12528fbcb36e825cf57554a *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_xdtype_template.c 38c06c2855eb12d09194e4477cd4a027 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_clear_flag.c f522005f8ad646cfa1bf5d7686293445 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy.c b1a797844093441a0ae5e61618afab7b *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_dense.c fbc37921a25a4f584071e60dba74fcdf *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_dense2.c 24f4050f5df551e04137eee710fa8ae9 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_dense2_worker.c 8204bbc65fa68a953146047e8c73b14c *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_factor.c 481d3f95a156945b399ba57ddde4865a *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_factor_worker.c 5a80427150a1cd28c4a377aab227782c *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_sparse.c eff3f8d6258361a277440b2259e752bb *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_sparse_worker.c e238185851a417366bdbdb070a375e31 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_triplet.c 33491a76a466ef9cb2a6844a951caf25 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_worker.c d547910efe51df1f057e8d31b4cf6544 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_cumsum.c 218cc4de6be5fb89e45d61af4b6e0579 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_defaults.c 89acc39d0db91f2513d2a5a21a2970b4 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_dense_nnz.c b4d7089ab8234d73a9ac315c96062751 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_dense_nnz_worker.c 56a9dd8b5f24a566964f4611373218c6 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_dense_to_sparse.c 78404eca379e05255e072035d8124a9a *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_dense_to_sparse_worker.c dd862edc1e6804060665c01e72b1ba4b *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_ensure_dense.c 6499bcce32c317268776a553447fc54f *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_error.c b7e4f858fdf02b2a621cc247d5b96b3c *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_eye.c ebe188cf257256828cbf87e357c680c8 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_eye_worker.c 239e27f83e0c6fc63c39ff6193c4ad77 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_factor_to_sparse.c f3c5b53fb17ba2a8921e6808834838a2 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_finish.c 56c4a09b786cf6c3a5db0f61e621602e *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_free.c e5ff700906d79302c9a579bed2ffc700 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_free_dense.c 77460cd3ab4b8d14174ee71e692ff9fd *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_free_factor.c 947da5aa4385476c88f6c2f87a80be35 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_free_sparse.c 42e757a813fb05350ded6ffd3d528f62 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_free_triplet.c 0ad28408b2899046f6214f5fd2f013fb *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_free_work.c fd4a31527714c8cd169b8248ca37f50a *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_malloc.c 835e5fe11703717400f74bcce7d3d854 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_maxrank.c 476df1658d19abafb8297ed6dc4a1149 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_mult_size_t.c 096bf162477673673dbb2ae46195e335 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_nnz.c 4bc1a1ece8d9bdcb9284723093f9c26c *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_ones.c 61f140b9e87e58f1448bfc641a3da142 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_ones_worker.c 91665e08ba6381e1ead7f6831413a417 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_pack_factor.c 3e8bf3dce28c114a1529a068d47de655 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_pack_factor_worker.c 0b1456ba9cd052c3c036db74a95fc71e *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_ptranspose.c 5a43c8f965118e8ee68f6dc9c89e9f8c *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_realloc.c 5626783869f5dc52c9ba07f041e0748f *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_realloc_multiple.c 8301c1c1ffdbb44a11c268723ff74763 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_reallocate_column.c 27caec3513bc34302b79f17308f960d4 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_reallocate_column_worker.c 3342c2f8e66eb6dda594b8f1451ca46d *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_reallocate_factor.c 08ad7ce2628af6ecddf67c29026e4863 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_reallocate_sparse.c 8f690fb9f396868818d5a18beee1aa07 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_reallocate_triplet.c 4e9d8e80644696affbc37d8a99313e9b *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_score_comp.c fa09007292a7a35ae14a605132b4219a *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_set_empty.c b90bbe9adf944390b7eae5c68909637d *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sort.c 9e20d630a90e8809b4a0581692ca5483 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sort_worker.c 08ce8631f543fa7a5d67e052de440e2e *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sparse_to_dense.c e321bb8242c9191e60845c8c54440fd0 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sparse_to_dense_worker.c 5c86b7005d5574bb5782f57a6a16dbdd *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sparse_to_triplet.c e31209c4b962f508affea9f1c4be18ec *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sparse_to_triplet_worker.c b6af1e0380221ff8c4448756f194ed3c *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_speye.c 612921e340bff04750a2a4ba121cf05f *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_speye_worker.c 6617b81127b7513675732959a0809eb4 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_spzeros.c a870d6004f979ad4503669a725d19cb3 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_start.c 5f5ac0eb82b0a7c23876f591935b104a *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose.c b38ae033e6f5dc3e4b7c3d762a302905 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_sym.c 42a867128bf2e19b40d98ddf421b7b4e *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_sym_permuted.c 80ffee32bf440807baa50134321213ef *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_sym_template.c bcf256fbd80d951621ce427bd8fde3ac *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_sym_unpermuted.c d5facb6c78cdfb8fab16e6a59c4278a4 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_sym_worker.c c92f0b07bb450f1025a7e3173bad4c3c *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_unsym.c 3d6d776dacb8e72814dcd3c106179732 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_unsym_template.c c910efd96bc54d1fa03fba105358c043 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_unsym_worker.c 9008e78a4336ffed4df17d835008f374 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_triplet_to_sparse.c 8f3599824b90c5c123370661c22f404a *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_triplet_to_sparse_worker.c ea218487e83622a44fd3c53e9c3a4db6 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_version.c 0f479c1cd763c75b573b7aebaf59c553 *src/SuiteSparse/CHOLMOD/Utility/t_cholmod_zeros.c bede0c1086a1dfeca48b4ca9c664d185 *src/SuiteSparse/COLAMD/Include/colamd.h 120665962984f4c8ff117165c15c982e *src/SuiteSparse/COLAMD/Makefile 490b2a0716d2309b14279ff3ff8b6ab1 *src/SuiteSparse/COLAMD/Source/colamd.c 69becc1142ce31049ea15b123bbc97c1 *src/SuiteSparse/COLAMD/Source/colamd_l.c 6bbb0db3ce4e48cdbfb44d3a9a9bfd79 *src/SuiteSparse/COLAMD/Source/colamd_version.c a8047cef633ca0642069e70f77e4608b *src/SuiteSparse/CXSparse/Include/cs.h ba2dc285fd312b317b161424ed7b9f51 *src/SuiteSparse/CXSparse/Makefile 4540676e3b2c9259842d5442db1e0184 *src/SuiteSparse/CXSparse/Source/cs_add.c 663e76c1e5fe5aa877ab0e13e412e43f *src/SuiteSparse/CXSparse/Source/cs_amd.c 42e0170607c6c3b4b8404f39ef9f6fc6 *src/SuiteSparse/CXSparse/Source/cs_chol.c 1dd83b0812e20195081715a3a92d5b3c *src/SuiteSparse/CXSparse/Source/cs_cholsol.c c96f4230862a4c35b2d30d1bdec1b679 *src/SuiteSparse/CXSparse/Source/cs_ci_add.c d45abbdc9cf87ce712164e70e54b70af *src/SuiteSparse/CXSparse/Source/cs_ci_amd.c dab48da863ab96ef88bb9199699a0146 *src/SuiteSparse/CXSparse/Source/cs_ci_chol.c 7f35e869c7e042aa02699b6911e4795e *src/SuiteSparse/CXSparse/Source/cs_ci_cholsol.c 33365184d6130a327990f9e9b280013e *src/SuiteSparse/CXSparse/Source/cs_ci_compress.c a965a791730bfeb87c144e4fef850909 *src/SuiteSparse/CXSparse/Source/cs_ci_counts.c 07a0c95ce7187bc7a333792b5c557309 *src/SuiteSparse/CXSparse/Source/cs_ci_cumsum.c be1cec98e5e5c9fb69962d040651184e *src/SuiteSparse/CXSparse/Source/cs_ci_dfs.c 745f84d385d9641d38fce284392a74bc *src/SuiteSparse/CXSparse/Source/cs_ci_dmperm.c 98f0a035b3e36a00f7ea9f014107a0a1 *src/SuiteSparse/CXSparse/Source/cs_ci_droptol.c 409adebb134d5184017c6ec68306912c *src/SuiteSparse/CXSparse/Source/cs_ci_dropzeros.c 3b2b69deedc65005af8d321e21e9f238 *src/SuiteSparse/CXSparse/Source/cs_ci_dupl.c a5739b485f1fe2c83b53dca189b4cea1 *src/SuiteSparse/CXSparse/Source/cs_ci_entry.c 75c10e9d957ef4e81d6ff1b7e36802d2 *src/SuiteSparse/CXSparse/Source/cs_ci_ereach.c e202cdb3a5b281c9d6224c4a137dcd24 *src/SuiteSparse/CXSparse/Source/cs_ci_etree.c 3fd763cdcd77564bb4def2a5b48009f1 *src/SuiteSparse/CXSparse/Source/cs_ci_fkeep.c 81e339d63de3c98a9cbc84d7a5eadc0e *src/SuiteSparse/CXSparse/Source/cs_ci_gaxpy.c 29252f58601162c99eae0d73a5477bad *src/SuiteSparse/CXSparse/Source/cs_ci_happly.c 78399cac5a09d2ab2f6367d4e3a42bd8 *src/SuiteSparse/CXSparse/Source/cs_ci_house.c 80c7fb935450333eeb51ef867b4d8b19 *src/SuiteSparse/CXSparse/Source/cs_ci_ipvec.c b6560c14e58891032aa110794df42425 *src/SuiteSparse/CXSparse/Source/cs_ci_leaf.c a8f1b1f894e709a1c6b048fd75a2692a *src/SuiteSparse/CXSparse/Source/cs_ci_load.c e41d0f53cc8c84b14ae3a37830bd44bd *src/SuiteSparse/CXSparse/Source/cs_ci_lsolve.c ce0ec426a9513da971173c60596ce8ed *src/SuiteSparse/CXSparse/Source/cs_ci_ltsolve.c e4c9a52098698986e0c13b7b951f4255 *src/SuiteSparse/CXSparse/Source/cs_ci_lu.c 2d5e7929d70fbe2bf9bdc96a6c33af4d *src/SuiteSparse/CXSparse/Source/cs_ci_lusol.c 72088be37c2e1397a48108afd166d317 *src/SuiteSparse/CXSparse/Source/cs_ci_malloc.c ac1e1200ff1d6c407ed2c158d2997891 *src/SuiteSparse/CXSparse/Source/cs_ci_maxtrans.c 1dd280e193fd6fa4be893296e4cb9a1a *src/SuiteSparse/CXSparse/Source/cs_ci_multiply.c f3d495ef554f3877eb3b12961d105a74 *src/SuiteSparse/CXSparse/Source/cs_ci_norm.c c7abb2e3dc210ccb710f813cd1f01995 *src/SuiteSparse/CXSparse/Source/cs_ci_permute.c afb02de393ddf9696f6f444515349d48 *src/SuiteSparse/CXSparse/Source/cs_ci_pinv.c 70b51352f1151b2e8ab83383536f15da *src/SuiteSparse/CXSparse/Source/cs_ci_post.c 7e1318233f3ab967d89b634482d325ad *src/SuiteSparse/CXSparse/Source/cs_ci_print.c 8c01f92c32d58db307c8462b8762b711 *src/SuiteSparse/CXSparse/Source/cs_ci_pvec.c e75e33a421bed0c8544a90c7558559d3 *src/SuiteSparse/CXSparse/Source/cs_ci_qr.c 4ed47307198e515728e22aded1518b17 *src/SuiteSparse/CXSparse/Source/cs_ci_qrsol.c b03819cd83d36822ae2a54bd193ed624 *src/SuiteSparse/CXSparse/Source/cs_ci_randperm.c 3e9a36c5a9d95b3589aeabe3e41cef8d *src/SuiteSparse/CXSparse/Source/cs_ci_reach.c 4ecab2c1088f66378f7fe3b5fe066c8a *src/SuiteSparse/CXSparse/Source/cs_ci_scatter.c e5b18754654c8541a13810b0b26ce38e *src/SuiteSparse/CXSparse/Source/cs_ci_scc.c e42d513e86cac6bde617a49a4e324e3e *src/SuiteSparse/CXSparse/Source/cs_ci_schol.c 304215e9802c8ad02a06c91eaa55d7d7 *src/SuiteSparse/CXSparse/Source/cs_ci_spsolve.c bcac1c1224eeee9adf3f6ef82f1fe9c1 *src/SuiteSparse/CXSparse/Source/cs_ci_sqr.c 8ab6c2217c5de6afdf2241bf7fc37f04 *src/SuiteSparse/CXSparse/Source/cs_ci_symperm.c f47ea9f7f73ae17517e98c447c5bc7f7 *src/SuiteSparse/CXSparse/Source/cs_ci_tdfs.c 8e21699583d8c72ecd3f20a6f222953f *src/SuiteSparse/CXSparse/Source/cs_ci_transpose.c b5d197123d5cd60fabe65f202a70641e *src/SuiteSparse/CXSparse/Source/cs_ci_updown.c 0adf590d78c268ec111f4b2d6fc79ba4 *src/SuiteSparse/CXSparse/Source/cs_ci_usolve.c 9dec0b991f675ac3437547c6dc8fb0ed *src/SuiteSparse/CXSparse/Source/cs_ci_util.c 6975485935042faba44df3c3c24358cb *src/SuiteSparse/CXSparse/Source/cs_ci_utsolve.c c10816197c485ea7959d0acfcbefd016 *src/SuiteSparse/CXSparse/Source/cs_cl_add.c 2c3d5a54c81139455a26753747fd88e7 *src/SuiteSparse/CXSparse/Source/cs_cl_amd.c 775db0ec11fb115a33d30a5da6ec2698 *src/SuiteSparse/CXSparse/Source/cs_cl_chol.c 138da4b16815857304d7bfa2a46566fc *src/SuiteSparse/CXSparse/Source/cs_cl_cholsol.c 91266f5235e176480bf72272977a1d58 *src/SuiteSparse/CXSparse/Source/cs_cl_compress.c 670b189ad46a7cc132e64832a79a542a *src/SuiteSparse/CXSparse/Source/cs_cl_counts.c 8db3f93ee794dd92e339612dc212affe *src/SuiteSparse/CXSparse/Source/cs_cl_cumsum.c 7e585e6b980ec4d18ce103366dd2b76e *src/SuiteSparse/CXSparse/Source/cs_cl_dfs.c 49fb2a54cb8cf0a941a9e6dba612b4c6 *src/SuiteSparse/CXSparse/Source/cs_cl_dmperm.c 2afab8e8ae16c4479308cd45a37d69ce *src/SuiteSparse/CXSparse/Source/cs_cl_droptol.c f27b1493d9af4c184fbd761344b0003e *src/SuiteSparse/CXSparse/Source/cs_cl_dropzeros.c 5d6b604543880dabee183a141a82880f *src/SuiteSparse/CXSparse/Source/cs_cl_dupl.c e399de317adcd3f4ad3eb3c9792478fe *src/SuiteSparse/CXSparse/Source/cs_cl_entry.c 44e5e4acc864b6d343be4f4e5442cb2c *src/SuiteSparse/CXSparse/Source/cs_cl_ereach.c edf606637528c66be5f400985d5d5f15 *src/SuiteSparse/CXSparse/Source/cs_cl_etree.c 7374e95094e71c69c6587fedfa28ce9d *src/SuiteSparse/CXSparse/Source/cs_cl_fkeep.c 334f69d9a9147faaacbc1ed037cf4c44 *src/SuiteSparse/CXSparse/Source/cs_cl_gaxpy.c 539fc6f4892f533f4965a0102793a3e7 *src/SuiteSparse/CXSparse/Source/cs_cl_happly.c 0166b8c1ff321002eb2e9b4b73fc2df5 *src/SuiteSparse/CXSparse/Source/cs_cl_house.c 01f60625a43f81f0952e20426452e660 *src/SuiteSparse/CXSparse/Source/cs_cl_ipvec.c 89849ebec42e9baf89c42371ace14d2e *src/SuiteSparse/CXSparse/Source/cs_cl_leaf.c 3621ee3818a2ef1a724e92d199c0680f *src/SuiteSparse/CXSparse/Source/cs_cl_load.c 6311336010ab1b32b12776a902c1cc8e *src/SuiteSparse/CXSparse/Source/cs_cl_lsolve.c 76c8e367c5a5ec4c140ab6a9dbd987ff *src/SuiteSparse/CXSparse/Source/cs_cl_ltsolve.c a177b5bb1bfd6f821b5cd51d9662cb4d *src/SuiteSparse/CXSparse/Source/cs_cl_lu.c 7a724b45015f95723d9f9901b421695f *src/SuiteSparse/CXSparse/Source/cs_cl_lusol.c d0c9d2b5562d5dd622530ea3d6d13d77 *src/SuiteSparse/CXSparse/Source/cs_cl_malloc.c 16b6ce8f63a22655765a7eb6ecd0e978 *src/SuiteSparse/CXSparse/Source/cs_cl_maxtrans.c aee75c5305ebf05f380a61740915793c *src/SuiteSparse/CXSparse/Source/cs_cl_multiply.c f0e892a98159bcbd94f635d64ad63264 *src/SuiteSparse/CXSparse/Source/cs_cl_norm.c 146a66d81d5fadd6caaf29823c9da8b1 *src/SuiteSparse/CXSparse/Source/cs_cl_permute.c 6329959cd5d41d476c23930dfeb15084 *src/SuiteSparse/CXSparse/Source/cs_cl_pinv.c ff37d2a18c4ffdf627c5568a26be5fe5 *src/SuiteSparse/CXSparse/Source/cs_cl_post.c f34bad1ab50d623af9c841028f83a1e0 *src/SuiteSparse/CXSparse/Source/cs_cl_print.c d016c9c09d7d73a4b1189e86a0cefd82 *src/SuiteSparse/CXSparse/Source/cs_cl_pvec.c 4d95b0e6d2b13a926f8abf20162b9333 *src/SuiteSparse/CXSparse/Source/cs_cl_qr.c 7c10a125392d6deca33e6d72ab1477dd *src/SuiteSparse/CXSparse/Source/cs_cl_qrsol.c a63fb7aa8cb81d1bf608a3a7c66968fa *src/SuiteSparse/CXSparse/Source/cs_cl_randperm.c 687a6ceaad6101219dde845d6300f512 *src/SuiteSparse/CXSparse/Source/cs_cl_reach.c 822c0f3b599e4ee33acc3fb60a80d0fc *src/SuiteSparse/CXSparse/Source/cs_cl_scatter.c 3a00ec2369c0c688b52c512ce435f075 *src/SuiteSparse/CXSparse/Source/cs_cl_scc.c aaf3b37dc4f9156583de56e44fe958ac *src/SuiteSparse/CXSparse/Source/cs_cl_schol.c 93ae0f23d146bc1be15bd80f0341bdf5 *src/SuiteSparse/CXSparse/Source/cs_cl_spsolve.c f4e7833db1f669680aa41de543706231 *src/SuiteSparse/CXSparse/Source/cs_cl_sqr.c 469cda77c9dacf20b26266f556abde95 *src/SuiteSparse/CXSparse/Source/cs_cl_symperm.c d8daa068898553976c6c382ea716b187 *src/SuiteSparse/CXSparse/Source/cs_cl_tdfs.c dba941df7c0f22fd27341469893560c8 *src/SuiteSparse/CXSparse/Source/cs_cl_transpose.c 913a090011b0765a66e3be420d4515a6 *src/SuiteSparse/CXSparse/Source/cs_cl_updown.c 3a9a5b91d4856785dc027da25e2c7301 *src/SuiteSparse/CXSparse/Source/cs_cl_usolve.c 001456593a7f7b64a2a23c997de60209 *src/SuiteSparse/CXSparse/Source/cs_cl_util.c 2b7343443fb30d48fc00a7190428369b *src/SuiteSparse/CXSparse/Source/cs_cl_utsolve.c 33172d9bf68efee65bd3c0ab42b3d25f *src/SuiteSparse/CXSparse/Source/cs_compress.c 08e447134bd8ff85a77848dd94baa301 *src/SuiteSparse/CXSparse/Source/cs_convert.c 78c5ed7a26a3b0a315ca2ea6505aebbc *src/SuiteSparse/CXSparse/Source/cs_counts.c 3d4bb2ebadf0f6dc2756af4c24a74439 *src/SuiteSparse/CXSparse/Source/cs_cumsum.c 7e5527a7c20192525a5886fcc0a563dc *src/SuiteSparse/CXSparse/Source/cs_dfs.c 776525520c8c77efc8d6f4a93e6bb759 *src/SuiteSparse/CXSparse/Source/cs_dl_add.c 7b2c821dfa472a11f0c5b75ae0f5e317 *src/SuiteSparse/CXSparse/Source/cs_dl_amd.c 152b676523428b59777240f62a7a3c61 *src/SuiteSparse/CXSparse/Source/cs_dl_chol.c 8467604dd4c92512e7831e61ee3545bf *src/SuiteSparse/CXSparse/Source/cs_dl_cholsol.c 001146238fa3a92a556499538837a6d2 *src/SuiteSparse/CXSparse/Source/cs_dl_compress.c 260e249e9f68763fed786fb02c9137e7 *src/SuiteSparse/CXSparse/Source/cs_dl_counts.c 76e540bae9ad1399160e459690bd4de9 *src/SuiteSparse/CXSparse/Source/cs_dl_cumsum.c 75156dcfe8cc5d3f0efa9d9e5815e540 *src/SuiteSparse/CXSparse/Source/cs_dl_dfs.c 639c039b8dc409415310972c2436b22d *src/SuiteSparse/CXSparse/Source/cs_dl_dmperm.c d37557a656cdfdd7a96d6d84c7e46263 *src/SuiteSparse/CXSparse/Source/cs_dl_droptol.c b6c2da7233eda8da72cf86d8ca710524 *src/SuiteSparse/CXSparse/Source/cs_dl_dropzeros.c 0b9ece3bbfc5b2fb72ad304dfe400771 *src/SuiteSparse/CXSparse/Source/cs_dl_dupl.c dc8f07f81d5a232f2f24a7abb2c226f5 *src/SuiteSparse/CXSparse/Source/cs_dl_entry.c 5a8ac12cbfed4756ae011981dd7e3f51 *src/SuiteSparse/CXSparse/Source/cs_dl_ereach.c e4fcc83b66c284526c4627c66c5763c3 *src/SuiteSparse/CXSparse/Source/cs_dl_etree.c f45f0c8519dd874a63ef75173c4e780f *src/SuiteSparse/CXSparse/Source/cs_dl_fkeep.c 9ff75d43979d475268bd00765fbece87 *src/SuiteSparse/CXSparse/Source/cs_dl_gaxpy.c 36eeae16d451b46755aa27911d890d5b *src/SuiteSparse/CXSparse/Source/cs_dl_happly.c 811b6864fc7e92c2834786fd9398a819 *src/SuiteSparse/CXSparse/Source/cs_dl_house.c 980a0c54f8f705bf35c8a1e5c2cb8bcf *src/SuiteSparse/CXSparse/Source/cs_dl_ipvec.c dedd4c63f525cba1b7e4c48bdbe525da *src/SuiteSparse/CXSparse/Source/cs_dl_leaf.c 510d6af17b7afd77f3e69ac9251829f7 *src/SuiteSparse/CXSparse/Source/cs_dl_load.c f7dc4cb61bbfd4ad5e0bb3102f552ae7 *src/SuiteSparse/CXSparse/Source/cs_dl_lsolve.c a5a8b40fc08c49902e05278e2e1ff6d7 *src/SuiteSparse/CXSparse/Source/cs_dl_ltsolve.c 1c5f506cf383ae73cfa8dde3045e279e *src/SuiteSparse/CXSparse/Source/cs_dl_lu.c 219cc2ccacb482d9a7efa4fb6c067b7f *src/SuiteSparse/CXSparse/Source/cs_dl_lusol.c 628fa99f9e74d238f9aa7bab65fe3ac4 *src/SuiteSparse/CXSparse/Source/cs_dl_malloc.c 6249b772073c7dd3e5bc80603d34777c *src/SuiteSparse/CXSparse/Source/cs_dl_maxtrans.c 6d929906de2e88b674d349bc4933ba57 *src/SuiteSparse/CXSparse/Source/cs_dl_multiply.c 1c8bdd4bfa298ffd706b156ba20ecce4 *src/SuiteSparse/CXSparse/Source/cs_dl_norm.c d024f0240a8bee65aec7131509412e0a *src/SuiteSparse/CXSparse/Source/cs_dl_permute.c 9bbc5917cf77fb9e5bfa0eb0e64bd490 *src/SuiteSparse/CXSparse/Source/cs_dl_pinv.c 3c55c739fa845cb18c704e930b951842 *src/SuiteSparse/CXSparse/Source/cs_dl_post.c ea96633a8efec15e4b956562d653e7a9 *src/SuiteSparse/CXSparse/Source/cs_dl_print.c 4492dfd761de67df4a021a734c91c111 *src/SuiteSparse/CXSparse/Source/cs_dl_pvec.c 7c2d3faf6c6e351e78aacf312f9c6f58 *src/SuiteSparse/CXSparse/Source/cs_dl_qr.c b66be4f8b14c9e79feb2fccef112c077 *src/SuiteSparse/CXSparse/Source/cs_dl_qrsol.c 5a63d3005fecadc1cb90cce9eac33aa6 *src/SuiteSparse/CXSparse/Source/cs_dl_randperm.c 17a75ab38eaf97c0f7903abe4f8b09e0 *src/SuiteSparse/CXSparse/Source/cs_dl_reach.c 2afb07704ba53ec5504c2f8c8bf0cb85 *src/SuiteSparse/CXSparse/Source/cs_dl_scatter.c 622d76da7601201ec0b3a95e0072c5c3 *src/SuiteSparse/CXSparse/Source/cs_dl_scc.c c65a946a86c760ef4285939e8046bb0b *src/SuiteSparse/CXSparse/Source/cs_dl_schol.c 91ab11ea4ae8b10b8c0cb8043d227b12 *src/SuiteSparse/CXSparse/Source/cs_dl_spsolve.c df009cc98849b136ab986068d52539f7 *src/SuiteSparse/CXSparse/Source/cs_dl_sqr.c 97638c31bcd179d74d493f1f5e148130 *src/SuiteSparse/CXSparse/Source/cs_dl_symperm.c 4805483a5e8e992f661613aae98dae4c *src/SuiteSparse/CXSparse/Source/cs_dl_tdfs.c 77c257807b1803ebc6025fe5ac17862d *src/SuiteSparse/CXSparse/Source/cs_dl_transpose.c 0eabb496428ec50fb61173e42fcce6e5 *src/SuiteSparse/CXSparse/Source/cs_dl_updown.c 95b2fc4005ba38f581f115d03788312c *src/SuiteSparse/CXSparse/Source/cs_dl_usolve.c f90ca7ed511fe1fe7569469fddf85c2c *src/SuiteSparse/CXSparse/Source/cs_dl_util.c 893c651764bef26c73c9ec5f00f01c96 *src/SuiteSparse/CXSparse/Source/cs_dl_utsolve.c f081a773dac5c503d62a2f890acc4b82 *src/SuiteSparse/CXSparse/Source/cs_dmperm.c fa36227f32dc65ebb57c9dfee6cc0816 *src/SuiteSparse/CXSparse/Source/cs_droptol.c 3ae40b182ed8123ad95c04c48431dc54 *src/SuiteSparse/CXSparse/Source/cs_dropzeros.c a6f000790f68e9f4d445b55700fd57b3 *src/SuiteSparse/CXSparse/Source/cs_dupl.c 5070dedb04934fae2cf8e2ad63b14c09 *src/SuiteSparse/CXSparse/Source/cs_entry.c b6f9ea08c1ba2304130e380ee8e927ce *src/SuiteSparse/CXSparse/Source/cs_ereach.c 58393921fe8493ca15ed02a4f2d8b441 *src/SuiteSparse/CXSparse/Source/cs_etree.c 79993ae7e3b969b62afd5b71fea34c87 *src/SuiteSparse/CXSparse/Source/cs_fkeep.c c13676eb2910f3828d8e633665cf8727 *src/SuiteSparse/CXSparse/Source/cs_gaxpy.c 43595b86025bfacaf51e52afcf32474c *src/SuiteSparse/CXSparse/Source/cs_happly.c 821cbc77579646cb20ce0cd74d6a109b *src/SuiteSparse/CXSparse/Source/cs_house.c a04bddc9c7fc8789edcfe5cd0fea4410 *src/SuiteSparse/CXSparse/Source/cs_ipvec.c c64f105e0b14c0991910475313841cc9 *src/SuiteSparse/CXSparse/Source/cs_leaf.c b0fbfa82b4a911531858bc260fecd26d *src/SuiteSparse/CXSparse/Source/cs_load.c 4953afc0698e761a078790ecf08bf378 *src/SuiteSparse/CXSparse/Source/cs_lsolve.c c0a8324815215f6577796909860546a2 *src/SuiteSparse/CXSparse/Source/cs_ltsolve.c 7160f4491d6135b66652c35e9cba2f7f *src/SuiteSparse/CXSparse/Source/cs_lu.c 699ff20f29f521f2ab251ce61958bc43 *src/SuiteSparse/CXSparse/Source/cs_lusol.c acb8f4a697f85a7db1992187ca82dc4d *src/SuiteSparse/CXSparse/Source/cs_malloc.c 9a1956fbbe26fe2a69ca73e063a40d3e *src/SuiteSparse/CXSparse/Source/cs_maxtrans.c 8f83c4464f60e59e4937c1d2b0844cc2 *src/SuiteSparse/CXSparse/Source/cs_multiply.c 88e839a609ce0e419c5a7bb6cea90936 *src/SuiteSparse/CXSparse/Source/cs_norm.c 076d08b610fbc7629b5078276ea44ee2 *src/SuiteSparse/CXSparse/Source/cs_permute.c e59c2b98666144ebf853c1bd5428e6b0 *src/SuiteSparse/CXSparse/Source/cs_pinv.c 8980cb04f1c955b94a1d12301ac899c6 *src/SuiteSparse/CXSparse/Source/cs_post.c 506b526aabe7cddd9574e7ffe291e88c *src/SuiteSparse/CXSparse/Source/cs_print.c 9987275da12eee0b81c61fbd3e52e89f *src/SuiteSparse/CXSparse/Source/cs_pvec.c 222c27091d2177cb80bbc77ab98c3f5d *src/SuiteSparse/CXSparse/Source/cs_qr.c 6e8a29aac53f515e9ec5516133a21469 *src/SuiteSparse/CXSparse/Source/cs_qrsol.c 9ec3f8f61d53cfcbe95c3191f013ff12 *src/SuiteSparse/CXSparse/Source/cs_randperm.c f24da137b4d9bc9f8459e5b372c9598a *src/SuiteSparse/CXSparse/Source/cs_reach.c 11f0d57a63eeb8bcc833d1b116bff8fd *src/SuiteSparse/CXSparse/Source/cs_scatter.c a4bf9a51dd7e299710044bc6629a3099 *src/SuiteSparse/CXSparse/Source/cs_scc.c cb9a73c9698d0ff130f5bbc901107ee3 *src/SuiteSparse/CXSparse/Source/cs_schol.c 88ad6321414660c4bc63feefc271d710 *src/SuiteSparse/CXSparse/Source/cs_spsolve.c 9c5bffe8b9856cceb385cc135f19b032 *src/SuiteSparse/CXSparse/Source/cs_sqr.c 81a9ab4baa77aa18599d84ffd9e9c4f9 *src/SuiteSparse/CXSparse/Source/cs_symperm.c 2675e43880aa60971eb9be556c249ee7 *src/SuiteSparse/CXSparse/Source/cs_tdfs.c 769fb7eded70690ceba42b9f78994892 *src/SuiteSparse/CXSparse/Source/cs_transpose.c 5a11b248ea3f2fc41e3ae60166c7e24a *src/SuiteSparse/CXSparse/Source/cs_updown.c 8c8ff0cbacb62ab503e0345ac8c08571 *src/SuiteSparse/CXSparse/Source/cs_usolve.c 80e6f2f874b8a148701afa2cd3945b81 *src/SuiteSparse/CXSparse/Source/cs_util.c cf3a5eea93b8bcb7d8306a4a2d0bfbc4 *src/SuiteSparse/CXSparse/Source/cs_utsolve.c 389f57706780b5ff78277f7769d9681c *src/SuiteSparse/CXSparse/Source/cxsparse_version.c f1d49127586e8022b6770f712439ce68 *src/SuiteSparse/SuiteSparse_config/Makefile db1bcc4963a9a7daf297d48d02bd8fb4 *src/SuiteSparse/SuiteSparse_config/SuiteSparse_config.c 27ee3ce841a35fcb179fc33add112683 *src/SuiteSparse/SuiteSparse_config/SuiteSparse_config.h 2b6c0d590e8364a254f32d84c39a7a46 *src/attrib.c f957aa1decb3ab62e5768873dacbd08d *src/attrib.h 2c5fba5b2b59e716446291cf65d1beaa *src/bind.c ae9faa18a9b4d9e424979c2c8018c110 *src/bind.h bdea27b6a2a79989b45eb5f10be141c3 *src/cholmod-common.c 7ddfb9a09ea189bf314431ee2abe7a76 *src/cholmod-common.h 3b657b53e32d2704cf020faa8cff4958 *src/cholmod-etc.c 5057233acdd848262cf1259e81fd5206 *src/cholmod-etc.h 46570ed7aa667c23a9a71a8f060e67ba *src/coerce.c b28b0cb0755257433a153e528a0efe5c *src/coerce.h ff38f95916965b86bb63a18dc828f884 *src/cs-etc.c 56e27f15d4c466a08c060ef4e548bfd3 *src/cs-etc.h 7ca896643baf5aef00bc298f77b30f7c *src/dense.c 1b283c24487fa2a8a08a5d5a5a8a5728 *src/dense.h fb5d6b8b559b3c6f369d335d7286afec *src/determinant.c 22ba2bee6a8de4cda0c60534be652beb *src/determinant.h ebac30257407d17ae0e503c55dc014fb *src/expm.c 784571681aa041d7248177f73ac61a09 *src/expm.h fe86ffab508369b6f3e0ca2e08f6746c *src/factor.c f0bb8db176ebc8b6356f82c6197daff4 *src/factor.h 3a00ec0197947e526799ddef28b9f265 *src/idz.c 0b015211a474aa369610621fd3c543c2 *src/idz.h 8445396b5abd16b2eaf79e54c6396ade *src/init.c 15d79a179e59c135b44f5967efd8d90f *src/kappa.c 6204a5bcb90a0715baf19669ef9eb940 *src/kappa.h 3d501c4994b2cdeeef0e70b17b135e82 *src/matmult.c f9ee4aa8d7003068ebace0d47144cde4 *src/matmult.h 19a94f8f7852b68b878e2cd07a1b190b *src/objects.c 1278d3c21ed8726e9048f7031fc4cbd5 *src/objects.h c868b7a3a85521769278f47fc2860c28 *src/perm.c 2ca56d1833e400fe657f963a72c87bd5 *src/perm.h 57edd3ef0960f3fc624c9d47c4b662c3 *src/solve.c c7e4d0db483efe92dc836aac9ec0e894 *src/solve.h 0a3c1ca9dddfc78eaab799354e06a1ca *src/sparse.c 1e950bcfe739de1fa814cda80a680aa8 *src/sparse.h f0fc2f470ea62fe17c4ba59d5f329151 *src/subassign.c 2b1565ac685ec8576cdefccad00e8227 *src/subassign.h 239a1593560fe15f100577b5f81814b2 *src/subscript.c 5801e16aa00d9d5188f34e7270057e3b *src/subscript.h 9542b498b327ff7c9345ed5df2b9fc01 *src/t_rle.c f19b280e45b41112486642bff65e3c0e *src/t_subassign.c 011fb7c429200853c88774bf8cbc8521 *src/utils-R.c daf41e27b6baac69a421bf6b78b789d5 *src/utils-R.h 7dd32b8add5da5db098536fd6323bfdd *src/utils.c a819313eb7f9d3c3fc57990d6022b076 *src/utils.h f05fedcefa889c8a6b634230548cd8d7 *src/validity.c 1735b37f8f587fa7d1eb563f3c3a1729 *src/validity.h 30f298e0c92c127269e38d68c3551dcf *src/vector.c 27223e66cdf6bcb9a382ee3142da4924 *src/vector.h 5269b559fe3abdad65b7016b5d62dc7e *src/version.h f57d29e1eec69ce50a9d64811aa15c33 *tests/Class+Meth.R fc506ccab4036af8ad69cc1dd0b3e987 *tests/Simple.R 5e53e6b4552a116eb3a0d6d2feff0105 *tests/abIndex-tsts.R 0de6da80621eb6de7e56a07e766e9a81 *tests/base-matrix-fun.R ffe85c58a3ff60c53ae1d66b4720764e *tests/bind.R c8ab42a19a673f079fda781843914f8a *tests/bind.Rout.save d8d4dec1de3026e421c1faeee559e6fe *tests/dg_Matrix.R d9e757825755abd46eaa5bb29f1b9848 *tests/dpo-test.R c8ee301b09c474efe164f0b1455f74a8 *tests/dtpMatrix.R 3e75f51d54d7ffd38f8a5451cef43c2a *tests/factorizing.R 58db5af64179692469bceceebe17c8e9 *tests/group-methods.R 08ff41927038ab7031ebaa90f2e3f8d8 *tests/indexing.R f7d2ed51a4b5ef3b0941df425b3526cf *tests/indexing.Rout.save 3f2ff4d5c0d6f7678047da84d9f9c23c *tests/matprod.R 33d98d8dcdbe8a42f6ee2b28b97a774a *tests/matr-exp.R dddc7f18c7b0c6404b137941124a2ac7 *tests/other-pkgs.R c6f4be392e5076d14a202c7c7416b7f7 *tests/packed-unpacked.R 21b5499b4f1928d33eeb840b94e69ff4 *tests/spModel.matrix.R 6730c6ccf0899c14ea93bd0559b752d0 *tests/symmDN.R 452c0d97b12669765908372d3b7b4d54 *tests/validObj.R 0125b34bc9a1d99bf4062ff55fa705c6 *tests/write-read.R f6c9e4986022f1db4c085b8429d06fca *vignettes/Comparisons.Rnw 2bd2896847fb11eaf102158b8696c884 *vignettes/Design-issues.Rnw 448278dab638a78df6eb59270772cbe2 *vignettes/Intro2Matrix.Rnw c39a26dfe7ccaafd044e88468155b153 *vignettes/Introduction.Rnw f64681e48c222aad57f4d43cad34d68d *vignettes/Matrix.bib 74ca9e8b3e91ace4ee3f9e85506bcdfa *vignettes/myVignette.sty 813e0c8cc7a5f7ecff43e5882270a431 *vignettes/sparseModels.Rnw Matrix/inst/0000755000175100001440000000000014576343415012525 5ustar hornikusersMatrix/inst/test-tools-1.R0000644000175100001440000003475714535165176015144 0ustar hornikusers#### Tools for Package Testing --- in Matrix, sourced by ./test-tools.R #### ------------------------- ## to be used as, e.g., ## source(system.file("test-tools-1.R", package="Matrix"), keep.source=FALSE) ### ------- Part I -- unrelated to "Matrix" classes --------------- identical3 <- function(x,y,z) identical(x,y) && identical (y,z) identical4 <- function(a,b,c,d) identical(a,b) && identical3(b,c,d) identical5 <- function(a,b,c,d,e) identical(a,b) && identical4(b,c,d,e) identical6 <- function(a,b,c,d,e,f) identical(a,b) && identical5(b,c,d,e,f) identical7 <- function(a,b,c,d,e,f,g)identical(a,b) && identical6(b,c,d,e,f,g) require(tools)#-> assertError() and assertWarning() assertWarningAtLeast <- function(expr, verbose=getOption("verbose")) tools::assertCondition(expr, "error", "warning", verbose=verbose) ##' [ from R's demo(error.catching) ] ##' We want to catch *and* save both errors and warnings, and in the case of ##' a warning, also keep the computed result. ##' ##' @title tryCatch both warnings and errors ##' @param expr ##' @return a list with 'value' and 'warning', where ##' 'value' may be an error caught. ##' @author Martin Maechler tryCatch.W.E <- function(expr) { W <- NULL w.handler <- function(w){ # warning handler W <<- w invokeRestart("muffleWarning") } list(value = withCallingHandlers(tryCatch(expr, error = function(e) e), warning = w.handler), warning = W) } ##' Is 'x' a valid object of class 'class' ? isValid <- function(x, class) isTRUE(validObject(x, test=TRUE)) && is(x, class) ##' Signal an error (\code{\link{stop}}), if \code{x} is not a valid object ##' of class \code{class}. ##' ##' @title Stop if Not a Valid Object of Given Class ##' @param x any \R object ##' @param class character string specifying a class name ##' @return \emph{invisibly}, the value of \code{\link{validObject}(x)}, i.e., ##' \code{TRUE}; otherwise an error will have been signalled ##' @author Martin Maechler, March 2015 stopifnotValid <- function(x, class) { if(!is(x, class)) stop(sprintf("%s is not of class \"%s\"", deparse(substitute(x)), class), call. = FALSE) invisible(validObject(x)) } ## Some (sparse) Lin.Alg. algorithms return 0 instead of NA, e.g. ## qr.coef(, y). ## For those cases, need to compare with a version where NA's are replaced by 0 mkNA.0 <- function(x) { x[is.na(x)] <- 0 ; x } ##' ... : further arguments passed to all.equal() such as 'check.attributes' is.all.equal <- function(x,y, tol = .Machine$double.eps^0.5, ...) isTRUE(all.equal(x,y, tolerance=tol, ...)) is.all.equal3 <- function(x,y,z, tol = .Machine$double.eps^0.5, ...) is.all.equal(x,y, tol=tol, ...) && is.all.equal(y,z, tol=tol, ...) is.all.equal4 <- function(x,y,z,u, tol = .Machine$double.eps^0.5, ...) is.all.equal3(x,y,z, tol=tol, ...) && isTRUE(all.equal(z,u, tolerance=tol, ...)) ## A version of all.equal() for the slots all.slot.equal <- function(x,y, ...) { slts <- slotNames(x) for(sl in slts) { aeq <- all.equal(slot(x,sl), slot(y,sl), ...) if(!identical(TRUE, aeq)) return(paste("slot '",sl,"': ", aeq, sep='')) } TRUE } ## all.equal() for list-coercible objects -- apart from *some* components all.equal.X <- function(x,y, except, tol = .Machine$double.eps^0.5, ...) { .trunc <- function(x) { ll <- as.list(x) ll[ - match(except, names(ll), nomatch = 0L)] } all.equal(.trunc(x), .trunc(y), tolerance = tol, ...) } ## e.g. in lme4: ## all.equal.X(env(m1), env(m2), except = c("call", "frame")) ## The relative error typically returned by all.equal: if(!exists("relErr", mode="function"))## use sfsmisc::relErr if {sfsmisc} is attached: relErr <- function(target, current) { ## make this work for 'Matrix' ==> no mean() .. n <- length(current) if(length(target) < n) target <- rep(target, length.out = n) sum(abs(target - current)) / sum(abs(target)) } ##' Compute the signed relative error between target and current vector -- vectorized ##' @title Relative Error (:= 0 when absolute error == 0) ##' @param target numeric, possibly scalar ##' @param current numeric of length() a multiple of length(target) ##' @return *vector* of the same length as current ##' @author Martin Maechler ##' ##' @note OUTDATED/SUPERSEDED by sfsmisc::relErrV() which deals with Inf, denormalized, ... ##' ==> define it only if it does not exist visibly at this point: if(!exists("relErrV", mode="function")) relErrV <- function(target, current) { n <- length(target <- as.vector(target)) ## assert( is multiple of ) : if(length(current) %% n) stop("length(current) must be a multiple of length(target)") RE <- current RE[] <- 0 fr <- current/target neq <- is.na(current) | (current != target) RE[neq] <- 1 - fr[neq] RE } ##' @title Number of correct digits: Based on relErrV(), recoding "Inf" to 'zeroDigs' ##' @param target numeric vector of "true" values ##' @param current numeric vector of "approximate" values ##' @param zeroDigs how many correct digits should zero error give ##' @return basically -log10 (| relErrV(target, current) | ) ##' @author Martin Maechler, Summer 2011 (for 'copula') nCorrDigits <- function(target, current, zeroDigs = 16) { stopifnot(zeroDigs >= -log10(.Machine$double.eps))# = 15.65 RE <- relErrV(target, current) r <- -log10(abs(RE)) r[RE == 0] <- zeroDigs r[is.na(RE) | r < 0] <- 0 # no correct digit, when relErr is NA r } ## is.R22 <- (paste(R.version$major, R.version$minor, sep=".") >= "2.2") pkgRversion <- function(pkgname) sub("^R ([0-9.]+).*", "\\1", packageDescription(pkgname)[["Built"]]) showSys.time <- function(expr, ...) { ## prepend 'Time' for R CMD Rdiff st <- system.time(expr, ...) writeLines(paste("Time", capture.output(print(st)))) invisible(st) } showProc.time <- local({ ## function + 'pct' variable pct <- summary(proc.time())# length 3, shorter names function(final="\n", ind=TRUE) { ## CPU elapsed __since last called__ ot <- pct ; pct <<- summary(proc.time()) delta <- (pct - ot)[ind] ## 'Time' *not* to be translated: tools::Rdiff() skips its lines! cat('Time', paste0("(",paste(names(delta),collapse=" "),"):"), delta, final) } }) ##' A version of sfsmisc::Sys.memGB() which should never give an error ##' ( ~/R/Pkgs/sfsmisc/R/unix/Sys.ps.R ) ##' TODO: on Windows, with memory.size() & memory.limit() defunct, how do I get it ???? Sys.memGB <- function(kind = "MemTotal", ## "MemFree" is typically more relevant NA.value = 2.10201) { if(!file.exists(pf <- "/proc/meminfo")) return(if(.Platform$OS.type == "windows") NA.value ## memory.limit() / 1000 ## no longer with R 4.2.0 else NA.value) mm <- tryCatch(drop(read.dcf(pf, fields=kind)), error = function(e) NULL) if(is.null(mm) || any(is.na(mm)) || !all(grepl(" kB$", mm))) return(NA.value) ## return memory in giga bytes as.numeric(sub(" kB$", "", mm)) / (1000 * 1024) } ##' @title turn an S4 object (with slots) into a list with corresponding components ##' @param obj an R object with a formal class (aka "S4") ##' @return a list with named components where \code{obj} had slots ##' @author Martin Maechler S4_2list <- # <- "old" name (I like less: too hard to remember) as.listS4 <- function(obj) { sn <- .slotNames(obj) ## structure(lapply(sn, slot, object = obj), .Names = sn) `names<-`(lapply(sn, slot, object = obj), sn) } assert.EQ <- function(target, current, tol = if(showOnly) 0 else 1e-15, giveRE = FALSE, showOnly = FALSE, ...) { ## Purpose: check equality *and* show non-equality ## ---------------------------------------------------------------------- ## showOnly: if TRUE, return (and hence typically print) all.equal(...) T <- isTRUE(ae <- all.equal(target, current, tolerance = tol, ...)) if(showOnly) return(ae) else if(giveRE && T) { ## don't show if stop() later: ae0 <- if(tol == 0) ae else all.equal(target, current, tolerance = 0, ...) if(!isTRUE(ae0)) writeLines(ae0) } if(!T) stop("all.equal() |-> ", paste(ae, collapse=sprintf("%-19s","\n"))) else if(giveRE) invisible(ae0) } ##' a version with other "useful" defaults (tol, giveRE, check.attr..) assert.EQ. <- function(target, current, tol = if(showOnly) 0 else .Machine$double.eps^0.5, giveRE = TRUE, showOnly = FALSE, ...) { assert.EQ(target, current, tol=tol, giveRE=giveRE, showOnly=showOnly, check.attributes=FALSE, ...) } ### ------- Part II -- related to matrices, but *not* "Matrix" ----------- add.simpleDimnames <- function(m, named=FALSE) { stopifnot(length(d <- dim(m)) == 2) dimnames(m) <- setNames(list(if(d[1]) paste0("r", seq_len(d[1])), if(d[2]) paste0("c", seq_len(d[2]))), if(named) c("Row", "Col")) m } as.mat <- function(m) { ## as(., "matrix") but with no extraneous empty dimnames d0 <- dim(m) m <- as(m, "matrix") if(!length(m) && is.null(d0)) dim(m) <- c(0L, 0L) # rather than (0, 1) if(identical(dimnames(m), list(NULL,NULL))) dimnames(m) <- NULL m } assert.EQ.mat <- function(M, m, tol = if(showOnly) 0 else 1e-15, showOnly=FALSE, giveRE = FALSE, ...) { ## Purpose: check equality of 'Matrix' M with 'matrix' m ## ---------------------------------------------------------------------- ## Arguments: M: is(., "Matrix") typically {but just needs working as(., "matrix")} ## m: is(., "matrix") ## showOnly: if TRUE, return (and hence typically print) all.equal(...) validObject(M) MM <- as.mat(M) # as(M, "matrix") if(is.logical(MM) && is.numeric(m)) storage.mode(MM) <- "integer" attr(MM, "dimnames") <- attr(m, "dimnames") <- NULL assert.EQ(MM, m, tol=tol, showOnly=showOnly, giveRE=giveRE, ...) } ## a short cut assert.EQ.Mat <- function(M, M2, tol = if(showOnly) 0 else 1e-15, showOnly=FALSE, giveRE = FALSE, ...) assert.EQ.mat(M, as.mat(M2), tol=tol, showOnly=showOnly, giveRE=giveRE, ...) if(getRversion() <= "3.6.1" || R.version$`svn rev` < 77410) ## { methods::canCoerce() : use .class1(), not class() } canCoerce <- function(object, Class) { is(object, Class) || !is.null(selectMethod("coerce", c(methods:::.class1(object), Class), optional = TRUE, useInherited = c(from=TRUE, to=FALSE))) } chk.matrix <- function(M) { ## check object; including coercion to "matrix" : cl <- class(M) cat("class ", dQuote(cl), " [",nrow(M)," x ",ncol(M),"]; slots (", paste(slotNames(M), collapse=","), ")\n", sep='') stopifnot(validObject(M), dim(M) == c(nrow(M), ncol(M)), identical(dim(m <- as(M, "matrix")), dim(M)) ) } isOrthogonal <- function(x, tol = 1e-15) { all.equal(diag(as(zapsmall(crossprod(x)), "diagonalMatrix")), rep(1, ncol(x)), tolerance = tol) } ## .M.DN <- Matrix:::.M.DN -- but do *NOT* want to load Matrix namespace! ## from ../R/Auxiliaries.R : `%||%` <- function(x, orElse) if(!is.null(x)) x else orElse .M.DN <- function(x) dimnames(x) %||% list(NULL,NULL) dnIdentical <- function(x,y) identical (.M.DN(x), .M.DN(y)) dnIdentical3 <- function(x,y,z) identical3(.M.DN(x), .M.DN(y), .M.DN(z)) ##' @title Are two matrices practically equal - including dimnames ##' @param M1, M2: two matrices to be compared, maybe of _differing_ class ##' @param tol ##' @param dimnames logical indicating if dimnames must be equal ##' @param ... passed to all.equal(M1, M2) ##' @return TRUE or FALSE is.EQ.mat <- function(M1, M2, tol = 1e-15, dimnames = TRUE, ...) { (if(dimnames) dnIdentical(M1,M2) else TRUE) && is.all.equal(unname(as(M1, "matrix")), unname(as(M2, "matrix")), tol=tol, ...) } ##' see is.EQ.mat() is.EQ.mat3 <- function(M1, M2, M3, tol = 1e-15, dimnames = TRUE, ...) { (if(dimnames) dnIdentical3(M1,M2,M3) else TRUE) && is.all.equal3(unname(as(M1, "matrix")), unname(as(M2, "matrix")), unname(as(M3, "matrix")), tol=tol, ...) } ##' here, as it also works for qr() chkQR <- function(a, y = seq_len(nrow(a)),## RHS: made to contain no 0 a.qr = qr(a), tol = 1e-11, # 1e-13 failing very rarely (interesting) ##---------- Qinv.chk = !sp.rank.def, QtQ.chk = !sp.rank.def, verbose = getOption("Matrix.verbose", FALSE), giveRE = verbose, quiet = FALSE) { d <- dim(a) stopifnot((n <- d[1]) >= (p <- d[2]), is.numeric(y)) kind <- if(is.qr(a.qr)) "qr" else if(is(a.qr, "sparseQR")) "spQR" else stop("unknown qr() class: ", class(a.qr)) if(!missing(verbose) && verbose) { op <- options(Matrix.verbose = verbose) on.exit(options(op)) } ## rank.def <- switch(kind, ## "qr" = a.qr$rank < length(a.qr$pivot), ## "spQR" = a.qr@V@Dim[1] > a.qr@Dim[1]) sp.rank.def <- (kind == "spQR") && (a.qr@V@Dim[1] > a.qr@Dim[1]) if(sp.rank.def && !quiet && (missing(Qinv.chk) || missing(QtQ.chk))) message("is sparse *structurally* rank deficient: Qinv.chk=", Qinv.chk,", QtQ.chk=",QtQ.chk) if(is.na(QtQ.chk )) QtQ.chk <- !sp.rank.def if(is.na(Qinv.chk)) Qinv.chk <- !sp.rank.def if(Qinv.chk) { ## qr.qy and qr.qty should be inverses, Q'Q y = y = QQ' y : if(verbose) cat("Qinv.chk=TRUE: checking Q'Q y = y = QQ' y :\n") ## FIXME: Fails for structurally rank deficient sparse a's, but never for classical assert.EQ(drop(qr.qy (a.qr, qr.qty(a.qr, y))), y, giveRE=giveRE, tol = tol/64) assert.EQ(drop(qr.qty(a.qr, qr.qy (a.qr, y))), y, giveRE=giveRE, tol = tol/64) } piv <- switch(kind, "qr" = a.qr$pivot, "spQR" = 1L + a.qr@q)# 'q', not 'p' !! invP <- sort.list(piv) .ckQR <- function(cmpl) { ## local function, using parent's variables if(verbose) cat("complete = ",cmpl,": checking X = Q R P*\n", sep="") Q <- qr.Q(a.qr, complete=cmpl) # NB: Q is already "back permuted" R <- qr.R(a.qr, complete=cmpl) rr <- if(cmpl) n else p stopifnot(dim(Q) == c(n,rr), dim(R) == c(rr,p)) assert.EQ.Mat(a, Q %*% R[, invP], giveRE=giveRE, tol=tol) ## = =============== if(QtQ.chk) assert.EQ.mat(crossprod(Q), diag(rr), giveRE=giveRE, tol=tol) ## =========== ==== } .ckQR(FALSE) .ckQR(TRUE) invisible(a.qr) }## end{chkQR} Matrix/inst/test-tools.R0000644000175100001440000000114214464662072014762 0ustar hornikusers#### Will be sourced by several R scripts in ../tests/ ### ------- Part I & -- unrelated to "Matrix" classes --------------------- ### ------- Part II -- related to matrices, but *not* "Matrix" ----------- source(system.file("test-tools-1.R", package = "Matrix"), keep.source = FALSE) ### ------- Part III -- "Matrix" (classes) specific ---------------------- source(system.file("test-tools-Matrix.R", package = "Matrix"), keep.source = FALSE) if(!exists("doExtras", mode="logical")) # << only if not set *before* doExtras <- interactive() || nzchar(Sys.getenv("R_MATRIX_CHECK_EXTRA")) Matrix/inst/doc/0000755000175100001440000000000014576344040013265 5ustar hornikusersMatrix/inst/doc/Comparisons.R0000644000175100001440000001215114576343771015717 0ustar hornikusers### R code from vignette source 'Comparisons.Rnw' ################################################### ### code chunk number 1: preliminaries ################################################### options(width=75) library(stats) # for R_DEFAULT_PACKAGES=NULL library(utils) # ditto ################################################### ### code chunk number 2: modelMatrix ################################################### data(Formaldehyde, package = "datasets") str(Formaldehyde) (m <- cbind(1, Formaldehyde$carb)) (yo <- Formaldehyde$optden) ################################################### ### code chunk number 3: naiveCalc ################################################### solve(t(m) %*% m) %*% t(m) %*% yo ################################################### ### code chunk number 4: timedNaive ################################################### system.time(solve(t(m) %*% m) %*% t(m) %*% yo) ################################################### ### code chunk number 5: catNaive ################################################### dput(c(solve(t(m) %*% m) %*% t(m) %*% yo)) dput(unname(lm.fit(m, yo)$coefficients)) ################################################### ### code chunk number 6: KoenNg ################################################### library(Matrix) data(KNex, package = "Matrix") y <- KNex$y mm <- as(KNex$mm, "matrix") # full traditional matrix dim(mm) system.time(naive.sol <- solve(t(mm) %*% mm) %*% t(mm) %*% y) ################################################### ### code chunk number 7: crossKoenNg ################################################### system.time(cpod.sol <- solve(crossprod(mm), crossprod(mm,y))) all.equal(naive.sol, cpod.sol) ################################################### ### code chunk number 8: xpxKoenNg ################################################### system.time(t(mm) %*% mm) ################################################### ### code chunk number 9: fullMatrix_crossprod ################################################### fm <- mm set.seed(11) fm[] <- rnorm(length(fm)) system.time(c1 <- t(fm) %*% fm) system.time(c2 <- crossprod(fm)) stopifnot(all.equal(c1, c2, tol = 1e-12)) ################################################### ### code chunk number 10: naiveChol ################################################### system.time(ch <- chol(crossprod(mm))) system.time(chol.sol <- backsolve(ch, forwardsolve(ch, crossprod(mm, y), upper = TRUE, trans = TRUE))) stopifnot(all.equal(chol.sol, naive.sol)) ################################################### ### code chunk number 11: MatrixKoenNg ################################################### mm <- as(KNex$mm, "denseMatrix") class(crossprod(mm)) system.time(Mat.sol <- solve(crossprod(mm), crossprod(mm, y))) stopifnot(all.equal(naive.sol, unname(as(Mat.sol,"matrix")))) ################################################### ### code chunk number 12: saveFactor ################################################### xpx <- crossprod(mm) xpy <- crossprod(mm, y) system.time(solve(xpx, xpy)) system.time(solve(xpx, xpy)) # reusing factorization ################################################### ### code chunk number 13: SparseKoenNg ################################################### mm <- KNex$mm class(mm) system.time(sparse.sol <- solve(crossprod(mm), crossprod(mm, y))) stopifnot(all.equal(naive.sol, unname(as(sparse.sol, "matrix")))) ################################################### ### code chunk number 14: SparseSaveFactor ################################################### xpx <- crossprod(mm) xpy <- crossprod(mm, y) system.time(solve(xpx, xpy)) system.time(solve(xpx, xpy)) ################################################### ### code chunk number 15: sessionInfo ################################################### toLatex(sessionInfo()) ################################################### ### code chunk number 16: from_pkg_sfsmisc ################################################### if(identical(1L, grep("linux", R.version[["os"]]))) { ##----- Linux - only ---- Sys.procinfo <- function(procfile) { l2 <- strsplit(readLines(procfile),"[ \t]*:[ \t]*") r <- sapply(l2[sapply(l2, length) == 2], function(c2)structure(c2[2], names= c2[1])) attr(r,"Name") <- procfile class(r) <- "simple.list" r } Scpu <- Sys.procinfo("/proc/cpuinfo") Smem <- Sys.procinfo("/proc/meminfo") } # Linux only ################################################### ### code chunk number 17: Sys_proc_fake (eval = FALSE) ################################################### ## if(identical(1L, grep("linux", R.version[["os"]]))) { ## Linux - only --- ## Scpu <- sfsmisc::Sys.procinfo("/proc/cpuinfo") ## Smem <- sfsmisc::Sys.procinfo("/proc/meminfo") ## print(Scpu[c("model name", "cpu MHz", "cache size", "bogomips")]) ## print(Smem[c("MemTotal", "SwapTotal")]) ## } ################################################### ### code chunk number 18: Sys_proc_out ################################################### if(identical(1L, grep("linux", R.version[["os"]]))) { ## Linux - only --- print(Scpu[c("model name", "cpu MHz", "cache size", "bogomips")]) print(Smem[c("MemTotal", "SwapTotal")]) } Matrix/inst/doc/Comparisons.Rnw0000644000175100001440000002166314444514070016256 0ustar hornikusers\documentclass{article} \usepackage{myVignette} \usepackage[authoryear,round]{natbib} \bibliographystyle{plainnat} %%\VignetteIndexEntry{Comparisons of Least Squares calculation speeds} %%\VignetteDepends{Matrix,datasets,stats,utils} \begin{document} \SweaveOpts{engine=R,eps=FALSE,pdf=TRUE,width=5,height=3,strip.white=true,keep.source=TRUE} \setkeys{Gin}{width=\textwidth} \title{Comparing Least Squares Calculations} \author{Douglas Bates\\R Development Core Team\\\email{Douglas.Bates@R-project.org}} \date{\today} \maketitle \begin{abstract} Many statistics methods require one or more least squares problems to be solved. There are several ways to perform this calculation, using objects from the base R system and using objects in the classes defined in the \code{Matrix} package. We compare the speed of some of these methods on a very small example and on a example for which the model matrix is large and sparse. \end{abstract} <>= options(width=75) library(stats) # for R_DEFAULT_PACKAGES=NULL library(utils) # ditto @ \section{Linear least squares calculations} \label{sec:LeastSquares} Many statistical techniques require least squares solutions \begin{equation} \label{eq:LeastSquares} \widehat{\bm{\beta}}= \arg\min_{\bm{\beta}}\left\|\bm{y}-\bX\bm{\beta}\right\|^2 \end{equation} where $\bX$ is an $n\times p$ model matrix ($p\leq n$), $\bm{y}$ is $n$-dimensional and $\bm{\beta}$ is $p$ dimensional. Most statistics texts state that the solution to (\ref{eq:LeastSquares}) is \begin{equation} \label{eq:XPX} \widehat{\bm{\beta}}=\left(\bX\trans\bX\right)^{-1}\bX\trans\bm{y} \end{equation} when $\bX$ has full column rank (i.e. the columns of $\bX$ are linearly independent) and all too frequently it is calculated in exactly this way. \subsection{A small example} \label{sec:smallLSQ} As an example, let's create a model matrix, \code{mm}, and corresponding response vector, \code{y}, for a simple linear regression model using the \code{Formaldehyde} data. <>= data(Formaldehyde, package = "datasets") str(Formaldehyde) (m <- cbind(1, Formaldehyde$carb)) (yo <- Formaldehyde$optden) @ Using \code{t} to evaluate the transpose, \code{solve} to take an inverse, and the \code{\%*\%} operator for matrix multiplication, we can translate \ref{eq:XPX} into the \Slang{} as <>= solve(t(m) %*% m) %*% t(m) %*% yo @ On modern computers this calculation is performed so quickly that it cannot be timed accurately in \RR{} \footnote{From R version 2.2.0, \code{system.time()} has default argument \code{gcFirst = TRUE} which is assumed and relevant for all subsequent timings} <>= system.time(solve(t(m) %*% m) %*% t(m) %*% yo) @ and it provides essentially the same results as the standard \code{lm.fit} function that is called by \code{lm}. <>= dput(c(solve(t(m) %*% m) %*% t(m) %*% yo)) dput(unname(lm.fit(m, yo)$coefficients)) @ %$ \subsection{A large example} \label{sec:largeLSQ} For a large, ill-conditioned least squares problem, such as that described in \citet{koen:ng:2003}, the literal translation of (\ref{eq:XPX}) does not perform well. <>= library(Matrix) data(KNex, package = "Matrix") y <- KNex$y mm <- as(KNex$mm, "matrix") # full traditional matrix dim(mm) system.time(naive.sol <- solve(t(mm) %*% mm) %*% t(mm) %*% y) @ Because the calculation of a ``cross-product'' matrix, such as $\bX\trans\bX$ or $\bX\trans\bm{y}$, is a common operation in statistics, the \code{crossprod} function has been provided to do this efficiently. In the single argument form \code{crossprod(mm)} calculates $\bX\trans\bX$, taking advantage of the symmetry of the product. That is, instead of calculating the $712^2=506944$ elements of $\bX\trans\bX$ separately, it only calculates the $(712\cdot 713)/2=253828$ elements in the upper triangle and replicates them in the lower triangle. Furthermore, there is no need to calculate the inverse of a matrix explicitly when solving a linear system of equations. When the two argument form of the \code{solve} function is used the linear system \begin{equation} \label{eq:LSQsol} \left(\bX\trans\bX\right) \widehat{\bm{\beta}} = \bX\trans\by \end{equation} is solved directly. Combining these optimizations we obtain <>= system.time(cpod.sol <- solve(crossprod(mm), crossprod(mm,y))) all.equal(naive.sol, cpod.sol) @ On this computer (2.0 GHz Pentium-4, 1 GB Memory, Goto's BLAS, in Spring 2004) the crossprod form of the calculation is about four times as fast as the naive calculation. In fact, the entire crossprod solution is faster than simply calculating $\bX\trans\bX$ the naive way. <>= system.time(t(mm) %*% mm) @ Note that in newer versions of \RR{} and the BLAS library (as of summer 2007), \RR's \code{\%*\%} is able to detect the many zeros in \code{mm} and shortcut many operations, and is hence much faster for such a sparse matrix than \code{crossprod} which currently does not make use of such optimizations. This is not the case when \RR{} is linked against an optimized BLAS library such as GOTO or ATLAS. %% Also, for fully dense matrices, \code{crossprod()} indeed remains faster (by a factor of two, typically) independently of the BLAS library: <>= fm <- mm set.seed(11) fm[] <- rnorm(length(fm)) system.time(c1 <- t(fm) %*% fm) system.time(c2 <- crossprod(fm)) stopifnot(all.equal(c1, c2, tol = 1e-12)) @ % using stopifnot(.) to save output \subsection{Least squares calculations with Matrix classes} \label{sec:MatrixLSQ} The \code{crossprod} function applied to a single matrix takes advantage of symmetry when calculating the product but does not retain the information that the product is symmetric (and positive semidefinite). As a result the solution of (\ref{eq:LSQsol}) is performed using general linear system solver based on an LU decomposition when it would be faster, and more stable numerically, to use a Cholesky decomposition. The Cholesky decomposition could be used but it is rather awkward <>= system.time(ch <- chol(crossprod(mm))) system.time(chol.sol <- backsolve(ch, forwardsolve(ch, crossprod(mm, y), upper = TRUE, trans = TRUE))) stopifnot(all.equal(chol.sol, naive.sol)) @ The \code{Matrix} package uses the S4 class system \citep{R:Chambers:1998} to retain information on the structure of matrices from the intermediate calculations. A general matrix in dense storage, created by the \code{Matrix} function, has class \code{"dgeMatrix"} but its cross-product has class \code{"dpoMatrix"}. The \code{solve} methods for the \code{"dpoMatrix"} class use the Cholesky decomposition. <>= mm <- as(KNex$mm, "denseMatrix") class(crossprod(mm)) system.time(Mat.sol <- solve(crossprod(mm), crossprod(mm, y))) stopifnot(all.equal(naive.sol, unname(as(Mat.sol,"matrix")))) @ Furthermore, any method that calculates a decomposition or factorization stores the resulting factorization with the original object so that it can be reused without recalculation. <>= xpx <- crossprod(mm) xpy <- crossprod(mm, y) system.time(solve(xpx, xpy)) system.time(solve(xpx, xpy)) # reusing factorization @ The model matrix \code{mm} is sparse; that is, most of the elements of \code{mm} are zero. The \code{Matrix} package incorporates special methods for sparse matrices, which produce the fastest results of all. <>= mm <- KNex$mm class(mm) system.time(sparse.sol <- solve(crossprod(mm), crossprod(mm, y))) stopifnot(all.equal(naive.sol, unname(as(sparse.sol, "matrix")))) @ As with other classes in the \code{Matrix} package, the \code{dsCMatrix} retains any factorization that has been calculated although, in this case, the decomposition is so fast that it is difficult to determine the difference in the solution times. <>= xpx <- crossprod(mm) xpy <- crossprod(mm, y) system.time(solve(xpx, xpy)) system.time(solve(xpx, xpy)) @ \subsection*{Session Info} <>= toLatex(sessionInfo()) @ <>= if(identical(1L, grep("linux", R.version[["os"]]))) { ##----- Linux - only ---- Sys.procinfo <- function(procfile) { l2 <- strsplit(readLines(procfile),"[ \t]*:[ \t]*") r <- sapply(l2[sapply(l2, length) == 2], function(c2)structure(c2[2], names= c2[1])) attr(r,"Name") <- procfile class(r) <- "simple.list" r } Scpu <- Sys.procinfo("/proc/cpuinfo") Smem <- Sys.procinfo("/proc/meminfo") } # Linux only @ <>= if(identical(1L, grep("linux", R.version[["os"]]))) { ## Linux - only --- Scpu <- sfsmisc::Sys.procinfo("/proc/cpuinfo") Smem <- sfsmisc::Sys.procinfo("/proc/meminfo") print(Scpu[c("model name", "cpu MHz", "cache size", "bogomips")]) print(Smem[c("MemTotal", "SwapTotal")]) } @ <>= if(identical(1L, grep("linux", R.version[["os"]]))) { ## Linux - only --- print(Scpu[c("model name", "cpu MHz", "cache size", "bogomips")]) print(Smem[c("MemTotal", "SwapTotal")]) } @ \bibliography{Matrix} \end{document} Matrix/inst/doc/sparseModels.pdf0000644000175100001440000031165314576344041016433 0ustar hornikusers%PDF-1.5 % 1 0 obj << /Type /ObjStm /Length 4879 /Filter /FlateDecode /N 99 /First 837 >> stream x\Ys8~_);qd'E-ȒG3 ^ e-H8nt7DM =>$Nj$?"=^`2g? -n7o\d~rIί5PI/r,hu/5dK~X^\ЧǪ;Y. ԷrOt5^NR Ā2~OƩlL#^SP2)4 %3&3?|H3/RT4CJXFj:Z<@1"_%&r c{Ppƾb|PC|]IoT{U@,,W)(YWҔUY] q'Y%.. iPg3{lzX (ur}MK%p6`~\h ~!_Cef,o$/'~IsʘeS6Ҝ,"|<-wWudA~hTLAAۖAKY]2PUyjX*/=*ODgK,TijQJ>j\t-@V&sU9b+pRW84+[U<ӽ1`Żj:|sܞhT8%ݴ3Nue,U2I!g;kTU8Vu=h)X!Vͳ]ݺ߫͜&?w+F)/onLL;9% PVS~ T+6h=MD^(4G(jѡ0%fyȔ.s}(Џ'o?7j:Uf#a(ATYYCٴ׮9x[|糫S`-ʋ5 2)5ZuXQlýuA1HSzZ@cφݶ ܙ#7[֯KtY7LxQofmhDpj/F\~#!!CNn dYwE:ΠZοm3p"'$ɧhhlmNª9qܣAf%a k|l[J݋߂#NA~>"V)[@elr{5ZM,iSCG.~byHo3o0sy5}W3U]v>lG[xC,{ >PJr fk%}%yqf_o1xBoLK̾I*"z?5qY\LI.쾓Lfפ2r4#ILN|FR WU\dV_Q!)Zv|_]k| > X/Wk ayw>C + ,CIS m`-~R0e*8yw1zᄵ+/tzk)PVF234+qљd"pdkR@Fwb%bcb>}=߽eִTAR!H>G?h4ayfFwwCfzvNY:v j-Ҝk󑱅I"i\~<BKG2Wq'Z ][֟ye,4ήj\vՒe͒ժtpu߮NWei4{2X d*t[4۷[Vj:=ZҠnA=+޾zk T;^eRм`7>q\/"c mD+MF\ރ<@/ڿKN]K 4V lr:|w޹t( wmKk|.yنjfXwL"鱺7]\M,4 \c= "=EXp2(|ȨL#x%m2hck1Z 5p5nFף*y%<Fһ{U1H+9}* *>e(assɺ%kovVWeM-@lCg Xe S.#!008j>v5u *Oߺ2hy3%zӼTu Rw?ZRJZXtmJwy{xѭUKnD=4?i{0U([No[i2k zu=-|u eN"`7Ɲ!랔R$ҽ t(#{Go?~8Z0/9ACo٧/Hą9 YYúcIB%;uHrT;q6޲էkO4ek)$P|Nr5v>[gf'`eӧi7}0z>eۦO8z>4,9Iӻկqd Ɠn F*,$Ōqx?SfIz;{zВ[>R`Z<3" Z IɀQ1"L7~jo.E_0ܰ R7С5c1tK)1`o ~WO#?x|ԗ־~0ڴJOHw-tbDOpM\…/>d8uK?ĝ~4/˼x\gH糝/gOT.pME­BXe'jF7$~ꀸimXX1ȝ5s:T vt_OU{NebX[{za!H> stream GPL Ghostscript 10.02.1 2024-03-19T18:15:13+01:00 2024-03-19T18:15:13+01:00 LaTeX with hyperref endstream endobj 102 0 obj << /Filter /FlateDecode /Length 2938 >> stream xn\f.PJ\A& n$qa*ٮvm#Er/ǷoyVtV__gԝ¿z7ٟ^S1`T͙Bgɂi>St˲(B(vb)+ad(dlWiҷ8STKR7ŏHQZX)Rua -)^Uf4+zOZc CBYeɶiR$0jgKX^F-2Ty`&0Fᘐ=R*Ibi”&MXQYx[vA|M|:w|noKZZr~i})Yn'`P(h)׏Nc?7>ロ?ZȊ7X9i /Hk~78ypj`Jh[I{\SoU[/`Ԟ d01ɞ6h,ܿMV[$ͨ(P^ʂK>[ VH-cNI|Is0~v >%C 0d e0Ԃ_]һAaV8gUpE/Zt%K&%7c8V-5k܁B)6_5ȿ μ7UqKC0:$/RCAW7VC7]; -Wrfȣ2Ez }.TѦT&<6Ĕ zVI#vhHi)- VlQB(0&< A^OP#9'\H{l6{c[}Er;V>-pL |Pאwao< JNon- %o֛? 3gQ7BNi,v0XY:$e y8 4W:O9?ZjД#dѻM U.,gdۅKV@AN4H aC'.[wqY6b-R$9ͥG (:OmmKJ׋D15uOYM{؅A/s} a'b,X,mp@b_ %m0X1̧گ#Xw8A^Q ĖHQ;/~7$%zr_mwn,|鮪+wMR窻ǻ%}<>¡\Ϸ LhV J е0z@+CD.QݧeK>nrZP' ǐ]А>!pk`}g^:A~<}?r}‡_Ӳt $os26-wiO?e1<$d%-)lgD(?3LȱPr>yFWWJ."C7|biPOy sj&4)eyp^ !g4X f51BHݹQFDԷˤfC}0Q yD9tekaxP8~IS f}Qdio~~RC 5`3h5[@r*󅿲+P@8 wƵxi8+Dm2,ԿBXµءBjh݊o^$'XUВAwE b.Tv#:z5Тdʉ8|*5YT['(&5<YYځt]p)KQ;GMn|{JҸcД)AZ _rl2/=-LY$ԽF[J|S5hh!,KU2,S6p4c$jm3l"aPaqo;Hn4 ƖNʩàkR*뛅nhB6ER\x[R3܉%~ܝ,ϻ;1ŕE }c] >a{|@c]:]CFt!h ⿐Tia.:!B9`Q$\&3o~XFrʟoL#4ad&E\C PN٨%O3uSxd<eZ 9'_ޠDh}V]XXȁg vY{VFlB9@o:.xa@b.ل2#jG=;hwy39s0ok$i' %7B U!;?Ntܚf3q"IxVfTf u۽ <AY״Rw<( cBXjcAK08,-9dFhU sb_nsYy,NY:(m>˛.Γ#ikovv@ErXUM,VSO؈)8 \鬟ZȄ4X6w朣c0; `]D򘲖ķ!Sl"/wU_CDZK=?WԺwV7_CO@~HTkn۪}\4QHXW2JbdviC\?Z᯦Ic}T>ˬYsǖK\*¹`{kp>m?؆(59YyǮ=㣇ĄZv#֧rT iq?tTXRGP\FD-'JgB9/YCNK*2 d*c7}qqodR>endstream endobj 103 0 obj << /Filter /FlateDecode /Length 2324 >> stream xYKoF딽@aoR]$AIc,(GC*$ǒ.~{FkR7]],,Q?o9Hf`tf?߾"lř bXx&L$N-6(oVќrgAE>z;L9($FR˘_e }*$/󮯾*jEsFe0uzoŬ% bu6M>t-h}$I+.2`O2vX'Tm4eQRn-CKtQvt.of~N9q96L\FB5Cm_ѱ]X$<-^,GsN80@ѰDj€@GRTmTxXKSoO.;RUPvEy9L gq.<~HLO%OrҟlsrqSQ}4V25sJ&7c>{fb/ EGa!vﶝW^>@(Ok,8?KkVPo 07| hlґ{+MynoQxm}Ov#:m'OXR;U|iR?:RoWuUa^Ր^^4 (\n' T(d$)}"WacS (xs5@:N|-T9|NQl6\Y $2a&?/]K P3CHUx+C/g<\`/V0^r_);Y>yA$fFGѾxLHYu6%Nb2sY#6D2ԏQ =ncҷ7b=k>TF+e۬|BGP#ȩ5(&3b zE*r Ɖ?5,MGށ"& 4wRu)niӛ0&"R4@␠Y%nwf "sΩ 2/U )8Rz̓H 1C 9ǥ#[D.SBa9*J5f7;f"54#HwDa(S1zZ#|ӄ %|yaLZ08EaH![ccjqS^]HՏ9Y#k u#m+Wr ˕N\fmz۴KEo#EPU5EzXĉ`H7] +]OE?Uaە:j0%nqۀU{9)~JM[(lqU5A_zQ0tQnJ/| PUU}¿jL\_I2ѽ.An1Fvo?S(d X͋tv{bxEN1<`ܹwS]*c>n 6__v- _)L J u1u&T;~ъ&(l,y^NQfcTف*ԕu^(wܽ!LKSoG' جP LY,Ɠ1..R5y_z5*F`& }"}Mع4PFjΌQd )P<8VV & kqf8pVn;/2e1^|At靍E,}eXE ܤ+*^gg6:ݧ\{'OF|׎-50Q:,Ëj_bkl6F4Np!U~hod(Y/mZR9C_uAr TtAWywyTg|W`rwgنJܱq{֗]p)T6Ҙۏִ >nM[Tofir:vL4åyn D;k]v~xeSTRz{XYR[Waq3wqsendstream endobj 104 0 obj << /Filter /FlateDecode /Length 2654 >> stream xZMB*K=S;To*XJ!\toO| l>~+KQs}iVVJZeQ]. +a9/JԲX>|@Z0JAy!,r7#}9 &/t@ J-.3a#C/pcm!-M1;aNeYQK.u9{M񡝩x?_ BPpQj[&Ҩb;{;c֤KXCT2@ kP\`$%NneTPS u ippRf@tU"0%eg&ҚRJC" (-@mimPubV~95#VIE9쥤zف(6u Ph\Hl[f*+S  9'"^xa$Hl HF3DT/*CuPtN2j~E ƭ%HJ[G3*m2X3 Q籙0QV9g((;p4GI_QGI+8 (iF^E)$AR{ۺJT Բp%X%5^\Ew2)T JPR$jBc^%sR8%%UVxXP9G6k(=19yi5qbG7$z TUeM"$L^쀒l,l 1bQs'n #QwrcUT5/>逸7tʄwiR6p#T2*hrW@-Tqc@-TT*ˣp, *m Ǣ;I^ps21J[8DW@-`TYMT 39yTFr*m j"p.v@- _E-\*Ճp(JeT79Ws㎟TMPsfǠ椉㸃_@s<*c8 Hs*m bN򊨴sRecyT9F)29FT9|6qN'=Pi8/sPi8% sCQi|Bc^6q2lj=*mGc8P9sgcyT9E3J8DZ(,{bAHpQOAI8^Ӥ<(mPRoS(c8/ {H:ʃ2#QLn73<&cv,<(Ȑm YEPڵ)i :xJ{IxU-[ [g Ai8ȅc @I8s1kS] ?D&DJY&XvLjJxvI~V@%M[x:+=¢\5 pfCPҵAn*i!jETҷNBDD%[(q+m&D?1ÐJ7NCH0+=F<J}#*iGeQ)8Y$:'P)vK:!27c\6CSikUlRޓ /(9J BNw$9fקa?_WVÃX'E|ng8f?gbG_WP (K[ rl{t| 4e6\SM֏c;NLBW@.c@\%=9(os)ȌFT~ԡr񩉎q^*xxܯc^%Sd_rU҆DnPC|BnЊ]Cu}lP)8̖iNJ.<#| *8Mnb@VFMYPJyڃ%5 Dl bRrlqݴ~ 2o~`œk^LKbͼNN!5 8aoV*H=@N ϝJT`m³'vvL =}q^9Hx џ $l}}Wd- ^?4~ iaĂ(!+E YoEo~{X[,'_m XL{2f>]p4Dh19Cn.uLҽڵ7} D^]ەHR>Q( վdT32&^ruۮ]dN$5 t> stream xMTkPT>Ŭ5s/~HL5}5ilDVS :v]>]AހaUЈ(DS8 6fڴfLx9LI:pfpI(Y%HsҲ3^𓍉* YrPJA) <fzTb-}𽌢9ECPzJFQϨ j6(#DR(!II2rMVd3Բ'T!(]ܐb]68QXhrR־ 0Ys8Vh+:w_0X醡ډ~)۹|qy"9%c#-?xwEdaho{k#wN i E_NR"KSI5+c׺X"wՃ #C`#ऋc.1k}+Ĭ-<%H0w]^Y&~Y.6]B1t/5=Y"Civ]>/w/+:.btX'T*+}|Zظy @>`zJaqŏIy⑋saXN;.Ix`4qdi<ɾR *5 "Ӌ:ëdk`e57{ٛ+!wbӸ~J nPMDNl7ɚOR٠bn|{yu;+vF_phMߓ= 34V{aՒrkK\‹%ƈ1 pb;@WS!KNwDJ6Zi]F;{"jXq8jQ>4,rƔKxnt*zLsИs|ܶv3, w濽vo̭@W!U٭: ]nZÍ]w-+{WZkoC_vEAi. [ `DTM{hOK$>bQ^vhc(A`@Uz}hD2VX(endstream endobj 106 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 3236 >> stream xWitg-![Ufq݁4IK $4` Y"[k}x  d0417$49 ݝtO 'sOϙutTޫw@-k7,\` cE0Ygs3 gcL:-2#+[v:nC|btVi77bEHl&f[mvb A""׈5Zb HaD1BL#,$O`0}Bp$P ,M咋j5D&nxkRͤLN|r ,XyGf. |Y=m1ap2F2"e.#G:=ʨ(瓉2s*y(-f6HNKVXI1|S.}hςoDǷ*{o)EK~`1E_a! EQ&h)5SS–)?zftC)} - i:ބ/A9[FPz{QO]Q]+;Kxƛl dE腒VJR]#Ecs^\*9J޷pKG;q3\[NgQUns0t"cDtB.6/pU [ԑ-x, Nz*>ՒL-ۏ2zi`v)MDKOٺ7-sD5 1CZ}IT̻}0m* >_;qX7ZcmAn$"=>R"nGLz%R9(D.\q1B+q V`3ЩqSԢTHpP$ePFۛ4}Wtj">yx1,б mlm5y^|R3I@n7Xe@P*>\ru%ߧM<A&h:[ ODnFb{Z$c^b}5_ Oo'[M \]d/gWwhJ4NMyVhK# D#*s˾OēL~zџ1 &}P6uvgN9 c1-OOgIl4 R\Gw5IšQwaϻTud[3GȄt~j{nS6†uo$3]CbOB:U$?d?$8Y\N>k$k-(3^al`Xf9)L,v{*%_hYsI;Sgx&G6z? qONt)|/+coI8_]tTs@KPhH!WɔdEZLS))r@YE4MaUCsM -)/v_t8`Mxm(7M?vJ} 5BߠM辄%#Sލ2.t$?^?\EA%v0*M"4\[LYI蹆 CT)97mw%S"_3v^P̺!Z|׊wu<<+=E=12d1| ӥ-=4-m6{pZSRx@.J>X,,<$z>NuF'PV.*Ф$&nC44,0ڌX~VAIä^+YfkV}w/J ^2A!eMTasUV`܏Vz-h#F,}x3-DuNiޒg2xU,hxN4v7Tnݥ G\SY\VF?5+{{M,+ՂwHBH g <FkEs_gEhulpuzxV,qU$2-Oۡ>(O.+A ?cwwImKfoN/]>;YLEfXVya``|-v/9Ltǟ _B_s_{Lq@645 PDaAx!endstream endobj 107 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2074 >> stream xU}Pd(*Z18S-?ӨXdD15*bS ʇwݽ{pwǁGQQу`6RmԘSf^bWwwޝyv{'"(:umZE =̲`Uw*S';gGϋ}6 3cF!lOf-r!Mf"H'kuzb1-CӉB"vQMj[&EE`4INļZ+˰(|QeC ۀEm_`jI49@Dc%nA;s{NL_|ٮ̏Ņa(nchn0Oț7,+bVLɹ~~tegIr:=',Z@\.O Cv8.?zd}Sq0EV^b\jkwBEkWF_-p=GJx`1>e8Ayr:*T28Ti F2ާЕnn#kƷ6:tn9KM!͆OO4vv@@72O|>Է&59[Fӕ"4-% ȢJ5oq .zփ:PdJߣثR]F1`@h9ٚ ߐ5 ؁a AHր5ٻ\"[B5t-?>u+X*k:u]UÖx*RVC 'R> m,J;XɌĊ ~u `Eb>7%۟`i`l$N)s]!"$4A3~YoOޤݴٿKOb4R8tt`=;y3\~[# YќӰMG[%t@|pL`K^$)~2:j6tṄP/hJj($շ]#lU{aM=k<V uP@ضa65G?ף/"$iou>˗oWP-b*m|,/ӛ*u& BCZf,Tkw=W˛ {sŜ_vTSh*Z'խm⫫0wyܩoU>GCvnNCm :_񬆜jņe?PK3B?/_ '6 ^5B)K/v]/=tPF{3ZS`Bc(Ǎ#UhGE.H^2($wڃ' bm5ι74⌝lj=d;УZ4@*]%ql<# (?0JNA8AJ)UC{O 5J?_{S93)2}jTa*3vq^j:̎POӷ+ݝ;n?gT)kx%( |iVOY9lp20E;JRa*xW+WNbNրªT%*H{p*aצEؼUx\7M{ỵ8V]hƢ=@ye,LXu@u>Ϗ#EIF#o U(At(I+R@ yGZ[9 d2YL1kh/W^endstream endobj 108 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2535 >> stream xuVmPSW1{t]̀bo:]]pJj+E +(@ IH!I S>  oknR-jwik[[;'a{Y3gq\4SDoX1 O6t!Lr͙v/ f|̯'@vHJrdC(3t{9^"Yr.e4(d)%?3EyNϡS_x>]vTY|Avg*Hx/B$dt^驭9rG7^0g5Kx[<%?C^Bۓv{/!ܤ9< Y"Xun0 zhZ:)+b=98}&!ucx h"_.*i;>|fۋ!u\͂,>xD 5"4Y}LZjMz@lDBfЅBOvt,6Zm ;xXJb/5I;}nR _V^,4:*j$8*(TB!s諴]r<.LbXU=82SWpI3w~$ENu.׻?d0!Չ4mCɺ['/؅M'kq,=߾l`+\=zw@xQl. Ft|iDJz),,ZLN?}tyu7WkC׍s \4T۪aD}cв<)P\_Pb yEIMҮ0uvGwu6ER| l a/L] hf1 矝4VJRZ^ޖPNzwe4"&Cє#;wEvnv] ;?vaXUseSSm簳 'M-j@7FcYz5􊥜s 9h{}4%"vOv n<| :PCvˡަ#hlgAEQx&܁O\*DUENCYE_GƢ|gw)5wVK/CFqO¿ e>y<6/%aV37{ay|? OLUH@ ^!Vq^Lo, "@kՆe8$L?BיʵI$J%22L!0q`D'b`2>%8rU?CG)HAle"=ϕ]ꮫvԥhfuy|wm.</T㩫%5\ nȝul&ŘkYoUd!b0ڌ<2m^!P: s6x(r?4"sL_(s1lȍ۾|g[ SE]{Ws{dE't6SdeetȻX<Κ 4Iȹ>^D"N ̔yC^ԕwx?;&Z5}*Emendstream endobj 109 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 3022 >> stream x}{X/XI3)7jGZgX_ÈD"a BC{1&a)8kڍ'a(Wr IRByuy YD0zfļD3aL Y΄3*-f !#cB?f32RY$FbIg"}$>>}M |/HI./793wuNNJdɢ}?vۙ|1=S]{=-Ko x"d&NzQ*'9 ,wҋq{}{g*WHXAoy+X ˷y-r"f>/` yȅ, /F'FF&kg S0`COI|i)d*/֞n ñj4uiʴ$H,Wf ?G"хAnywݿ+O:ЂjiP|U/교KhWuwrn[.B'Џ0 cӨ,쿈9K ?z( gjʬIʨVXuGώd- :7Vz\zbTj]N~6 ZP7h*s+s͹!K8Y[lD]/,IcYtk 9 d,Vmz=ɮT7WQ>?]z =#[ 3TNH+ ii2;.//~)w'rP`.|^Qr!Nt\Ej2^\q"']5138MgoL6KU{K-\{Kn9JW|B|`nz9Zw$?tp&Nw-)g!Q_}=q{ރ5{\TW:"ܳg_U8'7o:nkmjlU5R o_ֵ’_}yad#[QY{x7y[n/㠴ܨlݪ٢.Rfqdŧ-e$!9q^\8s)G_ }tz`+':-ɜ%O?YI EQSWlԡ…u\nUvAQ,HTwZ^9n ds6| Hm<M_XTѲĺ<ݢoNr{Jmў$=FjWޜ"(,lowe7RK Tɯ;>W]9 >wCAsnmSD*gge)vJt猗^Qrb$PM{ {`y֜$/gBd֤+`OWF]BR6ޮ(JX E0;X_z%_ՠNkk3[O\XSC7^8GIvp[Pz.$FGuoY(ȾF\:DG5[UMaH8R6n5$w U*'%#(5fǤrTwTvSw6`w$m12:; ڱgX3`:T;=Z,=cg=!cE5翟@|sGGWM3<͍v܄>_!+a. .<:.$AқGQf-t9c ܫ=󈘓rRJIffrNg 5k{;2zWwԺR:;P!Z[IGVn;2[Y&=ߝc?ƦWiiAYCC^*9;vRGTw":DbbDc$ $gu 3sh-VBx|o״iX/a~nO:/dUr߅oEf*{uDFK>X%UڼWLC{4d;hkr{ܞ'R-!t<(),p8[{+}qB _}|y ԢtB&W%d)@VMpbf_A|p.\Da XkWrVBeF0.X3 @ۦ)zD]dP o'2h(1RMVhn1 \B/AЕiBx8Yx_IuQ|pG2Xg0 P›8s]g}unh)8\\ܙع 5?C~7>_;=; T 5d3MBoo2:rN/V ! t&eavd??rrendstream endobj 110 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 8129 >> stream xy xS)90sEEQAyRmi<';͜4ii)(e (gEpwsӢ'm~׻w8k"..ۢ ?wE/ؿ_6>¼8`OşN~gN<9廋- WDcq <Dt |No5^PrMVC)@BHhU(F\ *TLprR8XvXtTf \ &A\ޒdB+bHKy<~G x/ D̬p$݆dl7bP!ӺKL-w?㚺F:2Uh2NV$h6^^KQܻ֟5&l nڤO ؊Θ<)iTԴOr֊~@A8pi SHr?|yf_7$PܝR5N|6WfMTP`8$Uc]a! p!wnI|-sJ}#{ ڦ&ĆWZ7`$-D嘧(pu}`42Pd^Mr}X)p}^P $@ f$U `X~\%^˥$>4w^|V;So}Ҳ%B+h4Z!h<|]A:؜97JM乗G80h\նlmp}o_o:z, Tct[jf.hI G_5,Z:3>,9$sY,8"V'Vn8&?=aaQ+E63gIXL<㤍Gh)gX%ڪ| HHb,Pmㇻ6j$Np=ZZv>z5EJNE84=j()N[) 9,ݸUWy:YpO{ːw~PDJ[a4sA1_nŞ1p yv?u>Wý p`.\OJjxDZVɕ9n^xbWc." ?8̢BV^<pc PYN\}țJ JUWlO ot c-l[{qm$>_QD\ oԊ ^ZnM`L2A6Pcf\̒d} v-6nKvu/"L(; 4ti4U$q)X769""\0oz8sGn)h Й zBڌvJrJ@IKq<&B_jY0>xs+(e >Bw=Mсʁ/wɤ~kՀ?Ò /,9ğ/D`$pp!o=1܏o!?wꓒ;mrP@ՌP{a @/9䣎TOGas}O?J*^dɇ Q9a`*N^ 3ȉ)X$ > OR~5nb6)4T8cQRAKwmcbMdK)":&W ĆE:I pH㯣 U].nScQ2) N|[YkZ4TWj+G5|A:ˣr|Z1BE1i4q/b;X6wm-Y%"F]_UDۭv`VUEn^}nu Gꭕ޸y ]C{l*u7ΈBq#S"SVMPA x>j+k+os]A{]R8uceCj* Rp$tlF jkž 2ӵhF1΂JY3͏nlRAl^y PUkԘu H!ߘ/PU45]d Tu-`G[`ZE )'J$ ƞE-8} M"݌886H]j6a4=ԕdq ZC7ɎB Pߎh{c+7inaE^umi.4h9L]x2qVo8I0Su|7?.$RriBW+nWR\RRR\}✐Dk֞;g5^MIYL}@_#" ɼʐdi|63݌1DH99\TampB5l@fjd49bW)xl;I{: =]q@RZZAI+ԋ0ytlg̦yS׎xP8-JiB`Q1ST\T(^?UFVӰ>*#AMyUe[v-\nK*ʣ%;Y^PLu@C$Q[mU>Y Y X(HP'MLH NPCŶ۷:>+uZ}J0#ͥ){Q(~b׹@ V %V*}G8mKUTf/Z !q!%('8ͷWq~( GiPUpZԌi m8e \:,6¡9.íX/")TVY^M}Iv+U-(sāsg^a ]N/f ѩkSzZqhuH1UDrpZ@.So6u{|jcO[8yu(f׆cy#s͹f_FjuZt]> .RO3d{xnHW(;;(wg'0vRSgO̔-( wkٷcs/'^Fs+q}4u< "441ԫ+?\]A)uTH X~<磸mrMޏm( jJecଥuUО 6qFZt.~]g^)ٿɖt{Nh-9.6 2&0c#kʫC[+Vv ()- ԈÙ[Rll6LVLdgu0;ÓH dg3`R}Âz9}Nm{G8ю4@0g5 #!/@ \z*`ݘ9E|Z^n2WQ4av9S.7GSLTV2 Iqd2iQ翘4EWVc4ܘ Uo|u*G°Ö{ /8 rZݫ+Iz>̾,VTy;oU}W_=2](:KyAη/OyI)p-AO"uQd0tx;\Ϻ~>{SUV3"3[MJlu'B){-,gFD5h]NU&ͽkX:OAmQw p&Rx9 )ko62s#-K#n.}Khܜ}20t[::S L ;VMA}'a* 11Ed^Ԅ_6HJiz)73:uNO,R_kuGytt45q:n@f0|:fQX*혅t*XY\NFcskB_PVNsi=JdRby՟(RT4ln|8(pпw=gX3S@ԊUYb&#[CD<:LR=)]awp LrP)xpҹ w}8Awcy)nn(އՋu_x'_v?dfʴx8 F%+ۿ{ji4Z{ϟK8YfJHbi5e7&`iJւKk"S,07Y2~1no$5li*!F NBžp~8b=^,Ȝ"+ww#f/Y|ޡX\{3x9睂svTl& (9yCsLM.SѤ٦nN=6`_vc`ʩj`3)҆ f Ѥ)ӴX~S"-|z|(;)dmQ7ɗ?1?PWbh,̀ΓfgKkBMWE7%:Άr`a7}BLcC|U=>si9݀#լo>6V#$4c|7Ѽ4 ۳Ҷ P՜*PYXlɋ&a[Px(хj[iBlʃe X9`>2QfW$q%>; YIS&єt 䜇]K9:q7J'q[7asL8.ԑo#̬k=QL[!4M*A1ŞRG)EDOXVI 0)6;t.ȡrʅњڊ(m֦ f3Z'Dτ0`d1һLn7/2 ֡mޕc`R6gXTjO}vGMV`b5vnxgn%?Ж]ZQbS+1n[s]FL.ϪPgat/8΀aoU-.p|V֒ʖ?1b|Ի]FY+5X'FmWDxy>{cjv:ZSN[J}\mRFQ)UV($b=*Q},P+e)7r$¯( y֚t.[Pc)pzK a5˯+R}8(.nfc(+ } :o]&a7[ʀ\R-ٛ)5״F6\_ʧ-RU]TdqߜYרt>?%8vlnQdmظDc 4I*Ve821D/'} @j*sl,KT[SYQ)d\^NHbGMRô2^m`Z+-ڀ29 `Ͷ0.}`Gybͽ!HΫ).q* =|Xvq:< &=w$yd,b1 5C` ğMDKdo5B`7h;_itNñp \v/Z܅c`'Vs qe;O;BT%&0;=! ^`\_i g5uI~kP!> stream xzxU(uM :+MQ""l5=&Бb"E$RTV﫞;3K~s/'@2gnѳիpڢE5}F$No2;}{:{\x|r+S*_}jj3/ Eų+gKV͑>w5׮[dQKFy鱃ƍ2G[ذeG,9'$At1YwLZtw7>o=wc26}ӿd ާL6ddz`ЈA 31!T 99t-=~hswKWO}Eh\%TI2ɫt8΂F?E>^g_9p44X=/P,RS62mNQpL|Ѩ'z>bE? ~'^xu]Fzj ^FF$qYp XFZs})J-JzȩpQw TLbFZ$ iORI.R)5 %CDL3'N]<}9dK)Z.c,>Y"艇~@Uq:)XJ_[t'J5bjr#hiv%8y|~O`3C!S1Gt4]e9//4/ݙN~-)c ~:z 6ugCKz6QOe} h xT h$|`?s .FK=cO2ust'_)rdZ)ayD5NӅ˔N"ȕNkL09$[6R)o+ TTd%y~b(L2ah<Եrd돰<L fcdW ;%>aj(DJRY;#׵- h5L@ѳ1"3֬vYuB@ItU8@y>fu2 8">Bŵ!aTj^;*G[%a\.Ch0HTW+ jp9p)brsv>@C@!**ga?^t>x/z狽O7:fUp3.{q=CYlUED=zUj B-T!K8e$ռm7^ 1y= LǵJ]&%rv4US%gr/v03-UE%:8t#H؋RGu p̓!rH{7UZ5s;!V!TÙ.(w)؈x1m>*) HUDY"F*-L%NH`$Wė>("ʆ۸u+1pC}zO5̧&O3w.jn;0ܙS^wqr%@<(~ ͐+BpW++ #0GQ`=]1D"aFnA!H ez$4'hחdSp)s.Zd~KvX8o V*W1R, ~ sC^U$RZ ^)Z$ JUeEHւ;WI_oo]b R})SJ5:^7LxNgB ocAZJ0z-Q_P;e .+}@:j7ӊ:Xi@p 7jnA/E@F{/I>@E.oYyP{iX ޑ;'f/Ȅ!X'swC κNLGl1+nwNN`Q_41Ug;t7ngh+i߸Q 6Vs[0p&~zA%_kQ6&&&: OQ3WR<;z跑Nfö '현3QyW)ʝG7c #H1U0 [>#9TG1]88AM&X\摱ZR "zo՛O>ɮwmfCdPKU'R-Y'֢h&baW"UX^QףIAX]z`~9LvAD=}QsCVO*AS6 -f_Ty&w۸Afz#s,&=KN'nõF$ώ{CWP#W Fʸ.,"g] SD=UH*ABP!kMuj@FX3I GA,4[{o$SY9%/n4d%&I@Cm6¤V9-L7R^z eP#aa }+O+("P<Dt5l cUc6hwLhez~ƥ:)Mj+/=E)W *NB3#vo}0 8"-Sp*]aN2 " O,!w فܕ̕̕-U™3Lf0MD,k3m?vZW5"tv洹(FC QhPJVɱ|bڹ/|te]YG`L(Z | |O6qUح.k|%/_; g,?ylLC-Wk;1@'|HDe@^/[.)L.nҘ4f ]OuIAAAɑ|ZL2pZ4{榸ӣ'vݪ PI ]f&CFcv b^jb(uo?]$$ JF`S֤ۂ[c'µtp ,z*MνߓCPun(JmB)^jd>'W".W2 Tc#e(AJX0q~;+v.2򀩳j )f̚)=CwGH㻿h פPGf=E2ZN7. D݈UmXM[)!TŨ gz֫g!_+ ]urqvfە8䥲Ά<mђ7^c3qTj);H}.| ̌قV‹8?zbwק ؽa_ Of*d'hUhB]X)o^<$ <27: X[\S.Q[ր5u*g!EyKhxҗvÁ[F?^K S%Bs==EOݤq(KİrX=ϰ@œ.tsǾcRD"51fE}5ָgT i޾N [x{(m7r&ԯidF%|Xj-p|O:(PAV6W |(.Hߡs5)tMXst:#3ضJb=BJu +IhWjD*ZM DŽdc݄ p'x>[Q蟿3K?dg6I{bwfm2U@,Z[%217.*£5vNm.*N詳VΙ9mؕ֋$ H < ,c7}$ԍ ( p!,P.[bCcյBIo+ N6Ipc#"cԧ3Bرp$nǽpuqe*g-Y8c\ )ع#y#HM2QmF} ѐs_ˑe-dq!=&c|2z1`_4p󷵂6veHɫu̮f/yY aە=k5ٌvL 4 Ic'n> R( 2}$ˁ(സ04+}X1rR& nb\avCuwYNl,b[h/ x-`# Jh YĒ8t(P\p>4߬KH\ #C6Wڏi`Mf%eS%VA7]#\aN˽xaO1Qdi5)kyQƤHdOd<-h8.tV蝠pDrJ9xZߦ#ƮZ^]&axMP"fᳩY,3(nXQIcySA3ْmdy{1 !q'O?H}YCXVPwFтjZOFM1=ŇU+us ٞcRY_vzp!,Dak*2 JEIJblltAio??c,zU5񸁟Nc5U"q=>}LQZњ[3m]p\WS.9< ~w {bEN뀚l%bS碧pߌ%.~ # 0~tfIGv;ӟTt5nv\ϊW> L0t IGٴJB7Y!ʚ4Q8)HyA֏9M*UhklF<5rtv8'?Ϯ ˤq?`V7q-4N<>֐#QυC^if|K^ES@uf#GUTl1=yEn€kBB-bRWc9y{gr/sz>zZO&w{G 0WtA?_f*N>q{*ybAu@je&4|ܤ. |%p0^( rKK=iJfrwvzЕ|eL֡O LK)t w=6@`XTy, lXz>aObfGt`$תڠ_>[F$V2ZWv`|g΄^^iPZS-u G#i /tU LG=<橮lMr8ڡh[<̩ 4[4>whbtxn4ju*i S#/`ԯoì_;ؠ=d NZ(HۓggQ|z$^)|>*=BI*EY?)pH^kfD_(1m`i q$o]FWEb$k*}ȴ8_ƁpgiRbVĦwBflnp)ʢ 0*BWObSp VBrC0klo,TVɥR3Bfć_|KvuUDuuN:"szŕ;*nh:a o񈭝2~U ܔ{KE"4T} dza4&(i\ B&|H@ 2gNf&@o[v/F+6N2 ?[zpœJO/1zcI1PQ./Sj6R"XɄw}=v{߃ u=~\xH1C[f(k7܁[v% tR}̓ $NG jC s4i+UP0LV?ztCJ3]O+`/hꃷ)+8FmИNU܇#v- .Ѩ[ÎH7qm@Xcj򒕚}Jh'lo Nѧ~~4?pG_.D}(eUD-MxSP!oS賟/L]Vm,z8_iA-]12.;:!R!*[5{%>pxo6'9_d8 ie @ y^Z3rʳK,{ױǶlNx115%ɊSc8}u/}w&6_r5Q@U[2iq's';;o/_~jendstream endobj 112 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 194 >> stream xH SFSS1000K  BR3rM@vKJ%Au[ы'}}}#ԋ뇰2R`aUxf~dd ? Kendstream endobj 113 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1223 >> stream xmmLSWpUI@YZߦʼn*a HqQRKiA[@0E7{1aeF?-'4XVdal4)*4 cy7VzTYr{ E\(YmVT q%ұ@Hﴸl.5}1)(dY MǮ eF*8ɋyJ{NdpP/P:GrVV6V{ <q7ϫu =>tuCrg!s4549/m`VzD:fC&IJLSc1M/eB ;ێ:0Ax&5Q@GUyǽ_O$^i׌gf˃m{9OTMʲ\CV=SO5j$r?{TW*ԂZ>x#^ͨތFOHCTc!5 4pxuyVp䥑 D&oE6%{1^/>L%WEȴ IX~=kH~ؽ`3}w_X<(]RY{iUؗ][i4|nzt&-BsKeZ3@ ׇ~0I!C4Т|MLns!{BBh嵶fCd0 5~UeqՂ+- vNtwB2c9_endstream endobj 114 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 3230 >> stream x]itu|e52ܙؒ#JĖ-ڭ͔,!%HqIl0ep`' %ZLѶko%*Nb>=N{Ӝ:9U ~߽w G y.]_~9gQޗv|Gا,}dc_qKk[{GJM߿) یmbavl[ʰwl[5c?aRT'#g.~^w6'gԎb .a܏s~4d<W ;6VDn~1\c#]zDI@5V䴢:o >$_;mgGr׶iE:¬0C*?2;'zp/rIYCZ]V HmDn?p;{LB !f+GJK׷j/?sv R&w%/'xP?2w73uYKZn"(u `υԅ#}l Djva9tȤ7>1i|ٴ) ԏu?w/l^Pf6iD`-Rs.6&6%LĮ*Mn?v]cѕ8%0,nρ$$]I@2 =^gQeHhGXbsBs e~s~ BKv*s3 #b9w0ʍE"XO:t8\A{bAJs/ȔVH&z7w4(*kpji VB *!k!:Q^,r4 TVY- f3Bc). \:v8Ig v/e}^]X_5ũ׆?"|=8'Nu6¬ᱏ`j J@'҅c=̹]y 7\+ߩٺoWdʘGn|MyU?Dfm1Э{-*Q!rcw?Nn}@gqYg^iM$VLx%>"w tUoP@n,8˝9~K‚7 3Ӥ+Xv@$MOؤ.s P|ۧ?2 06]}]O/('d.IdχK/O8 BjCA1 ACXJ+T7 _QWY"98+QcXF:i\նº$ՕVM=5u-w-//F8Rzݫ:\5/l:"<<:qEql7=؄V|\qk|,3 xlgO_ gwr:dfpn/"(B;[D|N~ࡽ)&yu'^M:'Qw 'jCӡg+遘-dR(nmHoUնԒ6$ε7v.C^gzY@Ii2Cyw~;㵠m'9Nee_qc#I'(%݄URoj:2խ;wQv"0~PD!Q^ ReU{URnw D U+뗽rh%٨LZ &ѹy5Akx_x~>'Y}v#ӊp -k_Cx$-@Ɨ!vz]JRvS 643챆$qh (ʭ*q*̞S5ݪV0U%1|pxGz?~~֖<[R|k-/[G,O4Z1<_xKl16r׶wmLBs__(ċo۬"aEV?^4ܴXxɱ&e`|}"so^Ќ!3 _0T*H~|s"ZzHyz`jCd#٢|JX`a#׉I}".\ 1 %7dZ+;g\c;y]c23U zв栨 2kjk똸2v|bPMR%6Yai/ޗ6#qS~`~ G}!؈kͱ^:{=ޫpb PN?;~{dz4wP@YUT5p<]aa^|VU(b< ?vendstream endobj 115 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 961 >> stream xUQohe雛rSw8E\2&8*d:a ,i%r潵]]rkH:]N(h1tW@o zYE <<<ۉ9=MMO80b}׭}o> >aco`/b^̇V<1oNy5a尽~x2#LĠY !EÁEY8q[$a*6[)5N%/h5:q^`uѠ~9E)(RMk,Eb %@PtWqSrh73ځRIVj/"T *ucMKP-tK(gZI=#u`+z3 MVU,f*rw!uiR*h3i}듋!#XC΍kgNZK$ LI ="\&?YH+oƿ`6R4_WPVĒD/;,03 jT!.kW];ܝ , j (l~=<s0/d;߽37%6Љ I]NtL5(Y;ONPDtȭj!7M`VKTj h mmRVm6Hb*zXmiZZd??p ǽOLc9itN3D]F?C\S)46D^DcGND(F@lw3>DbAɧ> stream xKq;SfN3KzB(4(QSMLtܝg[xT(RžZ7 h*9totoAڡ޿PN*sw3 xEY@;릨E0(ŧhJBs[vg f> stream xzxTe!#*` bK/Ҕ -!!u2NeD B`E]u}{߽ >~w{$S_~RB ())teO0v#+R8l'@[#7S7Θb%"1xxN8xXHۈ(%F E`b1xFHSyf$z$o7@Q]e@$ӊQm#J<^"'감5l ^ϲ0`A۲mKY*!!բJYI rhfZ ZEF6%qxOE:JiOLFxCeFN7e6/A|9ۚP%\ PoCR$׶4qz/x/[ JDdi4$DLӕ߼pNБRՈ"2fQ`J* [i2$WGڝvSh]cm厅p%|YX}_yqcx1pJN<J~BC!⑗_Y3LZ<H>;h~rm&h.^[۟#87{6oϟmn˼ U:f)0Dsߟ]; 0H:9+5.з^XX9K:q~S={v l8ctKT^˃yLG iGхHvtqmZZ iLwo|aIr6IInot6s'Q:^= W{RSqf]Y~U5 f۬:X8⊑Fڒ~p=mn64&rEC;"]4IPŅ ;Rq*ŕŒE" Tĸ,S2YV&C@DDĸ\S__TIY%HDEhKKRB !@+}ʸF'@bJ6h ZCdD9h+4b<¾g}31 e;@6HTfz zE#-)cJ(G=,ބ`xr~/w{+@LߐLłXIUH@qV4TE/!8D%V 85&e s=a=}{r{o]6lסgO>ۂH@,T:,JGX00(7::7 P(X)nVPH5G͌B.K]:Qru\Y)H)ӐQfOѵBаza$Fi/Hr|t!.IHH +Jlqf0!32m@ mosmmXwu@2b0BzPB?؏e@&L%A!0pm(TJ,Jr*+,E iI҆a!> J0nHh` &rI& NML*r! vN==Br;BD ݫgn-oX/ʝ$wш ¸.5^nKM1PP"Ѩkf>&d , Ұ*7ٽ?d܏/(.#P5,_1wf>+ɚSX3qP…G}`DVɇ\dfae5%Ha#HU >48c }|kƹztW +/.ngw4-ӰRX&oY6&BҠ*v})?ʂDA5nv]2t#А#MG^j$웱5J*h3 ۃ,eq[ڡjsKg1`h[N'~JV__ }Ww "`qHD27FROvRdh2 "d%; ] }wqKmN:pvv8J@2Lgvo Uohb1CҊ\$gOI '^0;0BRaTf)VE$ 'ifo&3vjR͔֧ܱ; s:D ϸrHf4W;= Cƅڥ*ڪM e"Z\No&v*:}3V m܃s4DswL? f YUbgggJ(fΒ4  ]Zjy[PWX\FGZwj wy$Bhpvz:ݝ!LT^KU%ߛccyv鐜?}}tNmM"3%cӚP].k⭡5be'=*2#a8jFf0&Sfw`]QԲ2qBNaTne_3'RO` dNTP̓@"654+ĞFt1.Y l.N3_ Zp8*عN #.t%. }}o;91 ։Wǁzh[Ě|K6_ՁOp&\ GjlyQo$[BHf3d&`2@](H4uqr2-.%R6Do>heЅ)8$5K&Sqv܁1"Ƃ Y),d~ee} '1 >y Os)4kH&"$`ƘM3Of^ <^e -qg]4IrEjT#[a5lP4Jg;X=˓2D֔J[͹p/}dXݤQ} ғ;H9Q0J MP'ji\_r*K-bXE6l1jG?u2_ 2kٵANX>WovgFްgQ,Q_nlt*7n6V7c%*spv@'<]0Z6kj<͈-㣕0C6W+6SWK=rX(Ez.ᗻ2Vo+œͣ&mӨޒfY+d2Ù#rڂ "^O*~#mmd87*Zy䬧ܳvxW.)LO `2`fqS)=оӶxh6 #A$KLec&lջIne0@C+[IS醮XE"̕x+Myu 6Ktve"GCB>xąrۋ&|Z:Z|AW'9v}Wyw=9Nޓ6 .C1^/F^սa0d >nӅo d%"76L?wwQ_~э5aGH&Tʐ?G8zg;&dԍs l3]ov[Z'+,)&>Fd U~ o<be긱qefB, (4FLF4JrV_w]T`GS?Ƭ{Tρh)*Л#B'M;u&d!ؠ)MQb$f +Rk#0wE\v- i84]O՘`5Y&覼Eݔ0ojp i;\mmmXw7K`J_RSWyzǦa90K8$&fF g+?[p"49jK|:s;}c&KO'wMKdJC)Hʲ_O;0M9PUsXiF# 3p -`!2쯆pjH5:[_ =Gn~Q@OތFrY_E4P!EJ_\C[uӍ;]n;tSyܳl|G^_47R4m"ǕB+xUOV^8=2ٺxb#U2|,pOb@:OE5ѿ;OCF81_Ο|7'z$e*\Et5^<&i-狮p$Ε潸 _zy(S(+j?;[݃F|凼AV1UHfBX NgKn·PZuj.p^82O<1I*Kxq Fh7C!I&8Tq8Er{ZG]=[bj?k7Ǜ26 K-)Zemjlt &V_qlP P;Simq}1rrQmn6YN& # Wv*Le^Yn M0o o>RVZJYZ-rvzz~Q7P,̔iִIR|WC%W*CS@`%םT13T i|nNjRhҵykiq<44J;*n`]=T-_ٞxj 黀=# Nò&BIjڦ.(o_ 1%qW3(ZO|ly};28&[lg>p l>짮4h, BؘB>*wLptv}f{¸o_pJ.69Ǽ>mH*K-_.pCI~n4E+)a<Ϻ/I s<$OdXB *ٟXq+Gd%;=RcI&2 MÌE\*дW8f$'30r7,:v; rA81Mz~w-YW/l5%M]8{Ѩ=Z^smt(1#skW"Dn^#PZ8vEXcmh{d#ΖY0p(=GͻO ⒟.uƅF26T<݇5)bV]5PqDЏ}Μo\xFn5dIL=# V6?]=q~N^~ps)RnlL*T2砠׊+K+%{FAIWX~(5`) jI؉'=<ͫmɭA#Z45Mw#NWnWsj5/ל> ;lz%XC*"X{u^R`7!yӷ򘢱%z DPp=$SCJ Llendstream endobj 118 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1718 >> stream xu[PW('QJP'k'yiL<O| c`쀍1V P $.V $$$q18mH쉈=Ij>um6i=g%.83}ۙ9|(ZE(vݲyyCnPGgUZ J+vb,"GGM<,'Kʵ?銾(~bVMu]d?蔸!_+oap!c?2JI >- )rg4'ʫtPvkUO5ߙCa;06`]d ULpzH)*pÚT7Hוcp :lƮ3F0x %{-vJ \ASFqf+>ʄ<>'.\8X!O@ S Pη/K:A!(ZNKHuWvNĂ-Jie- D q5z! X$%&J?_RXhTY; &d|`Z@"bjM>߃7~h<;('$a :z?d)y,iK ;`R6(p>HpA],|ESq, %g?᭪+6a_PeA!;`v]@RJ]hĤP_^]`{NOz~T&^2c8^GxO1`BG^ŖYhh*ZFcSew2LKvɫ 1<.#%. <=?NB n[Nz\=nšwvw 8})-*hʟKɑ;&zI\c<ךޛgUk#-gN53M1B_$,Yrz͠몪XW_}5~O+tX4 z}ϔIȲMdT %}re ^mzZKbA;l,~_ԽT]}EJ-nȯYnkJqL0 M)fn0 cao1:omn?}o|pw-'xکu8."/- o]k`hR1{ 7įqZgtgɖH'Iq c;tM~e~{1=%~eA3ږinnkknδf2Zd$~I PGA~P]ɐ?-wY Q>JŔ)]`x(n l~1cq<^k|02 G'Dߞs$܀ٹLV8>}"LA:.Q\9 ig> stream xdCMMI7`K+  ijJK(Ҫopnqnzv`~z\e~}t;_bdw揗cT(]z~ᷯpt|rMl`zK~pnpop{uh6zFVQP~xwlqpker \OK}~ſŋzk} 7 endstream endobj 120 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1251 >> stream xMS{PTe hswiLc1BTFKS .QD,,"opdDžDDP4|&`: tq|s8K)D zOTӁ,gyۊ{nW\OO&'~ޟ(wʃ8j5r(5P"$%Z%Jҏ7eeeE0;Gԝ;Bu,:?!T֔h׫ƦFPe@v~r46Wo LJѐ3*d B.PU i%@m{# BL@7mi1:\ü@(2WZlA^9ΌeUXSo5~]ǥ]uGJwo9=L#3KhĊQ6Pc|FcƗC}8N6⻍U臃t_vs`lpؘIzOsGr62,v (Z* UZe,ٮ)ҟ*+Rq2#eՒDEé2 K ]_E5w&aC[b; :Vw${{m}PhdxH W|\}.zZt u3Wޜ`Kgk cxq,V.6lU =k: ϥK]xq=[pncl$Hӌ*Ӓ@@F!_םTCeY Ѓ/ìǗdxdCAr qCu+UN8Ź1S0k DNddy&W]TSDVY)P=@ss&ȳ4.y@vYEDm&X[T6 2(@ܣEkT [%E&d7I#6)`!)#MIF1/e$Y`1sY9<$d@&l^scnFA>7XK '\Ы?]{mH}MI/ klьnp tYv Ua5,R? x`mCoɰ1D.x<z*BkǫTѦt-Ky-}GMTZSy?;86]9[l3F xRO\bG>a8`hʃ|wC'/ܸh]#b{=1A<eN|aȟ,:OF2endstream endobj 121 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 543 >> stream xM]hqz7̩%dntv} P`%E%,k^ a8ekrDj16.MjI02h5tu 8j3֋(&W@.N9uAy^o7`51SLZ31;˦9w[ F[CYIXkF{.5@ȅvjo'!9zҢ܎]fpw<2->郀?DI GG^;@3ukD ćfUEdEvlBѝYnqs"aW5 ޵w7OO&P=LCMvWe'2kSx3wEM 'B ƒ\>IߪJpԥ;i1DMA߄m:Sbs1Ó}y /V1%bh\O{C]0PSHo䲯o&;Z˴΃ƦfSy?0 .`*tMbcZ?ݔ endstream endobj 122 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 202 >> stream xcd`ab`dddwu041%faaGYS 9ĒԊv&FF|69Kv3?D.0{ϋl9xUVcISz%zZ#HwU-s,a3^"[AWW<Ke>'_L endstream endobj 123 0 obj << /Filter /FlateDecode /Length 1683 >> stream xYr6kиBmNh&Nt&xhT}R([r@8lJM ^OO~;r|GS~ˉ1ƌTy9yCh/H_)l<)?l1aWaȦ?'ߐ>C ;X\ȁÜk$g Lkk/ȋ d:CnʋSq#gG ]](@Jp4mcKkziHZ$mb- 3LąKp3#\)_Edp>K(eFDuV^hIrʚl> ѠbKhr}! we&JuICIBlڮ#>z: ~yud"e KhP猳~rS]^W USoK [Wϼ+0M^,#kRU@`(UPr *"e_Ʒ0j ?Y@1}%9iko2 f)KOaD>B v$M\Am(C0sO?p(PBc)@yE6bk;*kA\4#G|u@6{=lzZ/`!^L)f@Z+ܖBnj dSB$\0QS~<.kRq_6uiPOGD3,9ia+M.Fhf@nS MV`t@BrOhv>#$Au0ٝ cbnfy>P*=]&mf4[M";r&\<$)ҼnLO#d+9)Zڝ`(36VhؗUҹ>q=u\{AjzWEX#u`bbʏA ݞv+80`8lUnkmRCԪ#]<ӝ'k~vxAw4Cvçpç4}:Ѳ?c0"?{pa;Ɠ_M`㣖5 SkQB۠š4(`*L4 (fПL1ٴVh}q{n\Pto ۵2ʿKH&3 aeb+{)`<6 uS#= ^aRt&C(F^ :ٺdxE&itҀ*"ɳ˚ VY Jʬ> stream xcd`ab`dddwu041%^2{@1eϏ?wxqϭ?*~(~^8mfOϺ>}wsŖ՝Нmם޷G9}nu ]m%~;KVzo[RNw\wrIwX[E=3C#/mkߞm@snt*^ !cZO}-K|wjöUݏׁUjqd`mSendstream endobj 125 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 156 >> stream xcd`ab`dd v 1400q$2黲!{@Q!=?}>0c]Bs۟~}O&ђ >S{6us,]@~*}&3{ry%|r\y8T5Kendstream endobj 126 0 obj << /Filter /FlateDecode /Length 2993 >> stream xZˏԞ{[[Ԣ)mz䠱53Nl.#)+mb">SV4+wuYgofUEVb*4,Ӵ |P`"T挙Ȧj\kP,g=rwb%hY#R,V,95y2+ZWn'?WmuWo=[IKV楔s$;ՏMh+\2,SQ ^T<&sA)%4'4cy;5zn2xAH^xjQw j9ÐM|1b (ȣ7a(/mC=Z!Ɣ4'8"z*a;֟&IUȐC$PqknaU*E!,\F[4)yT:|.:T@ݦ*$Mk2WFӋ_C8(Ջ\ V2%<-G Ibڟv}Wԧm|q $(J! ~U{޾ڐnp(g~xJRGwO]A6M»eOǾ(vs@Yա|uԿ< p`e?A.bBs޹\hj˭skMS<0BOâK_PrK0` GghL@pϼ|S7sIjpB^bE,ҽ2p0d}<+RC@ℷ]YT| 'T1 ^"sD ҢZP-PHg>m׏(am o]F9+ ti2+g hn[ U0:9sλwHMc!E޸)|ַ3:7mYƼcE'zdaSl"XKT7%4i49]m$ʋT u}jb["k@#vs${'wU3Ճ1cۭ [cdx9+D8yBEQZQW.ڃmw+?l⹷V (T?.$ءVي5CEu?U30i!݌CʡZ+yq8GTY9j&{hf%gHgؿ0Gp#PInnƤ%QrH+D v *$(|e:E=E)G ր^0K5@2W"Eu=EǢ>&:39e8)RBxqBuB?mm"sqpD&q"WlĈ{TpYD= *,չ,AkEDe\j[X -~<"pKG\ 'BDT ՇOJ§GӣISpކXRe'Į6>$J;ϰYs~1\^π*[ܖ()9% f ZbI$*J r2L%ϵZD@C&i P CK Z +\ Z e>zN([S`DݞQ(8`/8J$^RՉ Z r?JKC.Prq>ű\6ia)y =kQ] 3B=*uUD qRN qZRNiP⻜+04W@Rb@aZ@RaqLIQNPJ% ]=jTGLE\=jT.AݶsB5.%\աi1XBNGa 15q,f5.%.Zj%.Kj\G~yJK):иTwLP㴌_*OhP~q>!W@% BLyGMвKqdG;Umx:,@ݛ;J;`:?ϛ~}\+:#ߝwą ]qwbkoΡEmSu{Jm;vtȴ}ܠ;j. s6_9| j~VTpN_L}T`ɷD5ͽa#W{3㣉•?MdnoJ_Tכ{nOF&E(ФEm)y=]Z%޴yWniBLnh4v&Hohljp[u oMe[r;ѱn8bj /c=_w+K]`_\voBxH q%yendstream endobj 127 0 obj << /Filter /FlateDecode /Length 3098 >> stream xZIo[c94)VV! `$0(AIhm=y.-F=0E{߫8WY<_~Qv[m~DF73+Gq%"߶ywbLDqla&>^Po/>Q!Kr]VbPnHOgxja'{ /''1'}>qbF"Os~e'psGaCZ8P.c:.9FqK>v{QzI|E0Qxwy|OaLW>1jl^y|:[}>vgs{'^ t}bЊS(&fM -E'۪Œ'Xb \2nvePC^-IJ +H RmO\/2A 'm OjcAYE>ۗAxXU8aqOJᥔMbQ۶5gMQb]ݞ]^oҢ< c|Q/bjjx{+ ^jyJRj.VZKJXtnx$,R*}~$$gjko+KnM~njiV &&/\Gf}hoi΃,IMT&orVExcHYǜTߣ bp*Y|CdUsR hg?KEq=+p[l/0){JEgyS%CԹMxɬcx}eN?e y21IHdfѺxi Hބlrp`;Lc"p49m+:uZ1Ԗ< #䛪,RK<,pخDIVȺzC6胦,ַ9iʐ%JtxsV\-)J d"ʄ=V?-ڪ"@D+~wi׏=X&q@=K[/Eӑ3׻tEȮcEvo'kDle_Û<@)S/4^-m^mt6y?cMZ uq:=G Oǃ:҆w*"jCLjD׽|g,v6  qr~3D[E&N(y:I0X,;]Xtpͽ?Az6ziJ,uІ#) 1Srda `ig= 1 Z6QZNBI"oO~/";"pt>1s};mrHxA؆շˬ 1bP]%TOOI @ΝymҶ.^GY~lړN1 mQM~=-ΦRn?mUR7Myom g10Sa)Y&qps4YW-> '.B] Ԫ-,RǗ tnkٷYZӴ$Jauߑ5 6K;XheR8/Na-5Hp)HU:.`.AlauWݰy$&KEL77`W|6(֡ ~y̏4~g IM$KS]$%IW0^ue6[u]Wg(|mɖRn}p5OF i~D[cvYl#LZdΝ6SkOgD*1-୳#e&XOYC내Rgx[6=}|v2j<‡GD-dG.@Z^?#M0XQW"8@tȄM< lfEzsبה2|!BObf k3競9CLx-|'+AL!ɀ0$}3#M P>_'Lаq`9@lE)Ρġ+?>??*24Mmɸ iG v_ NҶjÓIй p"`im ~0!0|B,mth K_XCbbHw'VmP(6MHQ:MQr%"+@B^e7->"B~&dwM~B<:pʘ"K~3O0dl#Cq?(J$5 > 9R8Iȡ/u P7rHj,;1(G[ ch_;Q$ywiMEZrz:͔b  BbwZmEl|e&w.`*ш܅&o<_M|X'hyٱS~W6}44q{qq {~Ӌ 毛RY< (͜R N73& 7[*:4JVC 1TLbCg/@%V|*Ki0Ot] %$ sW}~7Nr +Po0D02ܿ~3Ojbd0E*w ܙ?ڹgW:WW42]$X.%]}xbhtPHkeUz_edendstream endobj 128 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2759 >> stream xV{tetf cx CDP@)h%e+oQm&46͗&mҴIՖ P+ R%![AYduA/9S?{vNΜ3߽߽lDp7,ΞYCxF$7J) e㩔T8n1'dž"XSr^?}Y/ư,ۈ -6c˰-rl` D`ccTžd`șJJgbF|4#Ưarِ&'{iLbbFKJY)=6jbmDSFqD"70T ꞃSZ\QZŃ!u$N`0X I|]B p8Дj׾U۶bE3aLfFS/G+:[]99;pZor3DpirT";k%"PjRky(A4 -7"5ϕR| ^/9NR5K̥ u~pmQ8F g99xV+yCMp۾d~~V{(Ep9Qg/ڕ4z/x)ñ.(V %ފ'p>Qd }8 \V[ *ja$ځ/X+޻C`鹸T/uQ+ 6F/% :m%**IFdH"/xǢ7ۈP}u8ul͵P`g2fX:\2: nˊ% jzo^}D:2ׅm-,a*FS"10p6V7pW|@ȍ!yc)h:wf<{WV:6[  QNuR]Q\ZZX>w@ (5Z mՀ4Ƈ7*PnL8 $ָ 2e!eéh5b CuKFDӓq}s& 4"q&'h&~׌S/FY\@!N^l,B۫m.PMMu>˛"Ɠ0V{; xϢcʈʢzUM`c쏶L1@&`æOq>X"RK,*RRO\T*jA>)U5qoY^PMz+&thԂ &zBTF^gps0%ʉOs"cxxw/i4ɈD<8rL=>8\pDy@㔀|`T2n>H9'ziO-(L>un$ :*ۂM -lv6)0H(R7x_N޲Uk~ Wk5!(,*R !Fc AqLRח3׺bp^ˬ[TN1"MTQ 1naJ Ĥ_l8@SH>M5-fpи$a%FBNV x7 v)*@G'G$jkC?FmU=\a U+Mmp@R%*D^i`~ƒpHY+5١RH[u FR!V6z-JŃwm崬S@Z,%6G( 'T=uGzP_V3zPBMAEᵴ Gi'-(]W@oBIvZoo*K:;pؙUX8}F-UUhjS:ܷlm [T!.I*\~&݄\ '‰nz,,RrM ִ I]I PЏ`:'uem ckw`*x .NY+`דs]~06RDI&/8`;h ;KU;> stream xcd`ab`dd v 1400q$dbaa]R~= >r~2Ft''%'u5u6t7rTM^"c˾HLX8yq|>EUJ丘p20C".endstream endobj 130 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 176 >> stream xcd`ab`dd v 5070q$eaaX~= h Ȟ2&K??O[t;'g*{wzAgIg^gnw^7G@E}vg.HHAi魓kr9丘p208endstream endobj 131 0 obj << /Filter /FlateDecode /Length 161 >> stream x]O10 :"0~ 8ʀ0%:t8K结ϲ=(ul"-~H0Xt2qA6ٝL.Boh )jHUյvIG`ٜu*9K7SiZL!`(S!endstream endobj 132 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 134 >> stream xcd`ab`ddds 4$qq# 2sS Yl~t}e3#Gtݓ8V/Iϩn-ǵK~UI=&10-endstream endobj 133 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 186 >> stream xcd`ab`dd v 5030q$caaV~= h ȞqLI7-?މ&;i?ٻK:s:s9 o=M`of⮲n g2F."ۯ%Oy=';=endstream endobj 134 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2508 >> stream x}V{PSgbP{>Zۗm֊ZTT[*H  b ◿As(;dnmeka?W3GTrZi3lK:BU kHOnU4VXfy]ē.4!I?@OV6I~\5I7fJnUQFZGCf%m6fڗSǼ$E`=G| 'c[Aq*AAEԙs z,PaR@^͚GHFO'&QDmOhB^/8AX kp& "ؗq$< ԳZѓ@9,1<]%MװbVWv|Ά: هf3&`MS;_ǠY0r0apƢpp3[Xg}3muZ\6-x[Y3gc7]Þ)W ׉HUZ,UJj 7t՝Y1u>[H4sLK?ϬVURriUr֋SQ%%t؋<~)4w%o}1EObǿ@8- =7f_|f!,zfS]^=oȓ٠DPa ~.mE+e޾6].h/Gץw8hKkx($1=_|YK=lf[5:2GGGh 8 Z%E7@9Tتm͍ЋwZ$ $mJ4vy3>ԡqIˈ rh<ih%+5T'uR]Dթ\6z;R+04mHh҇2U1}qu~ { )w3 ,`O1|fSSA*YV"!*.; 7zn8vufI3 sՎ5'/(IC\PN7zAsQ9m#yCT`VK&`2031KW]tS& xƮ.J)ޝU adR:BOqoHF_퍳LF5pL d-ﷻ'){v; D1,Z(#B[FirvNB ;M[`PSw(VL teP 6ses4ɹюb0oendstream endobj 135 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 181 >> stream xU SFSS0800%K  5R3ebUvKJ*XʖeڜЋ;) ҋ3 }4 ? cDendstream endobj 136 0 obj << /Filter /FlateDecode /Length 1020 >> stream xUM8+(O"l$=%9$m x۷%$ OT[_?~ !?_ S@mk}E^nn^8)(:>"!,, @?ټB !ъLRXL.2K0ALQ=2NV 6hheӨܛz[eQ^d{hE)970XFҷsj|-mkq̨=p_25 jT_j_M"sS~,ȭZsN6tq.4jgUxХST&|w>m7( = S9|aE,4 E 8֭δF_fS{Ǯ7[٤kxiLqp*@UT|~ N`ΧhzY=BUmן CXwTV&Pwl*[Vˑف.HV~BxQt}z{ϭX)|M/+X4\ t*r@y5w]Mo{2kp/,z-(Si"pe8L Cs~,)!:)$2Hcr_9m"TGDWmKl)C~s=| 'aTMB\Ҙڇa26{5C JwWEj5$ g:\LL$xՒK:g:> /Filter /FlateDecode /Height 450 /Subtype /Image /Width 900 /Length 20276 >> stream xw|SP({K)-[l,{o!CA* KTd([ (R,Pʦ*=?)iI'$敓4#$#F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!FA=G:cƌǧK8 &iӦdɒFOđ...m۶5z"ԩS۸q㌞#{ٗ_~9|p7770(P^֬YfD[3z.ɓ'3g7z.J*)Rᅪ#/|||xj;~~~5j_?0(ի州qdˇ~(Fa=~8K,RңFőU\YbT^Y=GhXXX鍞ڷo_͚5}}}[je\"Fu@1bT(`GQ: FA1 bTĨQ}: Fu@v1bTĨQ!Fu@1bT(`GQ: FA1 bTĨQ}: Fu@v1bTĨQ!Fu@1bT(1bݻ~Ç#{ѕ+W)SDDD8q8s%KLFOđݾ}Ν;k8gϞ?~ܹ}sIbToE׃z]Y0W1D;1o}F/|z{sy-'`p/g/V޽-p}3m~N{ 2pN Qp ?]?\2&ãĝ;|o?I/ou'v1̙3`SBMbw?*Y.sw;tP*UV^G=!FKjg&(*FV1 lڱBB+xЩ$A(M>} FCh< Qh,1 JCQx@p("F=h@B+bVV#F1j RЈQhE;Њu( `QhE: tDB+bёЊE˜DbGB+bVpb("Fa R1 Q; bZH8%bZpaЊ=QhE VЀV(h8+V(` >ЊЊ6K("FV!F1 lQhETp("F$QիwbNHUvgÆ Z:qD2eΜ9ӳaÆ>>>SNk $}Ĩ}rJ ._3F駮]f͚nݺ7nؿJٓ&MDHb8bׯ?zhDD-F_z7oޔ)S!k&N8~ O{XBرcp̙k׮E%K{Μ9 Pּy&{3gt钋ϐ 1jw>GѶmۮ_^@J֮]{ܹ"EX`ĈQ=@v'-[ɓ'_~ꪮ9r_iӦ͛[>yȑ#֭DΝ;jѩ@=ztڵ^T)fsh߿/h>rÇ_jUǎ-JZ[5p&mڴ8,Ydwܑ$aJ9W-Z4$$#Tvk[y3hР… @a+gt ˑ#Guk޻woxxxՕF:uQOό@V$|f:tXf͍7rέܹU.^X`A1 =Ĩ݉5F#7ɿ={TDFFzxxLڵkɓ'8V1jwbgϞyzzʕ?cƌoׯߤIƎeQ@t*FڝXcT,[gϞEiѢիW}}}vؑ%KDي8v'7n\hgj՚2eJ 4(@'|ʙЊ=V( )![bZA bZgD1 Q#UFB+b!@B+b[qT%F1 ("FwIp+1 Qa%F1 SзSQhE`1 Q*z#L ̗0}y3:u@ҝya8c4<\Mq%r;Qg%N?,Ye 3S3 mz%Xy1 t̨84bZV2bZiC "FUҋa+F Fhd/-5jԩ+VܹsƍmvٳztңG+W'I¶ NS+W/_Ydɠpu_|۪U+⿺'Nl߾=13g,T. @$-U&%ZLxe̘wc8Gр6m\~}޼y~ɟ?ӧOo=pr,nݺQH 1 ؐR!F킻{hhh_lr=zqƏ=*_k޽ۻw 88J(`/  oРA\3^zիW׭['gZڴim F$YHjQhE=1 Qp4+z!F1 +Њ`a` 1 Q6WgEB+baจQhEH`غukڵc=3#F$ya1E'K6mz53gN]QBp"aB͛7^^^͚5Xbbiͤ=@!Fcg'NW֤I d̘FnQH0Ç{Q4((HYZF]v0A@bR?@¹ p &lذAjg:?1 p\Ĩ=ڷo_Q$F+uww a{ @Gɓ'~~~J|ʏ5ԪUH"6RG,H b4v/^8x(^RֻaZxqMWLJTzT S)TTe=vV4Qv%)}v3 WI1Q$CܹL"wӦM f bذaϟWWfϞqM4iذaLlt82bB%@6mZbEus"FNY1L2կ__T2FגXExx.<w=pKrQbEh"##=YZlq5Q BG4((ŋׯ_ϙ3XbRLi ,Y=z,ZEY?pΝʏiӦ]bE֭K8J(q=h׭[7rk׮ϓ'ό3ڶmWwԩ˻/XbŊwܑ޵k\א!C1͛7߲eرc;w|ƍ~]tرce˖8J((a%Fc7|ӧBԩ (3gΐ/*G=zW_}Wg͟?? @TYc777_~B M,پ}[n}۷oΝ;w 4PTTرc˒%Oh,:tf͚#FL:5橣F:uRA®]ׯ߷o߅ ʏ5k֔}Iƌ1 7o^OIVh,J,xru7<{A[.^ヒz|jS ,U%~5j$%5kxΚ!CM6ɿ:LS#hr?~…B < 1GѺulٲ]xQڷbŊN>63qo޼YfX?%o'o6},u?tUyjݗ-['ȿ6 .ܹsgzZh!Mٳtҩ/-;vU4 1ӧOWXիW:u7nҥK'N\reT9RTD:)H5k]|~A͞={޽5jPTV?444k֬X?OV1 |gUdȐʇD%K6g95`~2jpȎ/"""f̘믿9s&mڴu֝}h1ZrÇx"uY 2k֬۷7hgH@c+1j/iǝ;w֭[WWcpϟ?7?ɓnjf͚[O8q„ o_r%H8:a-Z8ٳYfaJ9T:uRJ5kߗ1Z`G=x\2XuŊ;w8 ٳG51֭k9rH7`S|0Iپ}j֬YNɌxIN8UY81ˊ+FFF=zTy=fz{{p4}>>>;v_ϓ Ib+oOB j@ӧO;;w HG=M6<0;ݧOŋ/^Ic+@ObQR|͋/_.Y={͛O6mҤIƍlժ:XbwM6ϓV1jbM/M/_K *oիW۷… 1 ЄlEB(f EuԩcǎW^?~|DD .qQ@" UQ{k6LrK(?˿XluĨ= S$@77Xkq[#FvTu("FIj߈QhE G("FN=AB+bر ("FHR4bZؖS~V(>@B+b!Ia%F1 =("FpjJB+bΊN%F1 (/F9dx+(J=+1 xNʾ>3BB+$VI)F#[01 3FG`c(rՎlЊ}{*q F1dQhET8bZI H"QhE:^sΫVZj~~~̙3===6l:ujXuFa1j/n8}tJW*UjܹO?Եk׬Y֭[ƍ{I&V"F?T@b F;k׮XO}U޼ySL)w8q,XЯ_?-GQ8vٲe߿cdɒ޽{ϙ3gʚ7odϞ=s̗.]rqq8I :1jV:w… K˫f͚ꀶmۮ_^@J֮]{ܹ"EX`$Q^#"Fʕ+tv=uezVX^lٓ'O~U0rȯzӦM͛78 ]p!1[Vޱcl!`kaIѯaÆ ː!tn¡b/)]%+L"ڨQ[ʀ ܿɓ'>}WZձcG@.\hqnJl{ۦM\\\n߾Ô4r N>F~~~XbѢECBB?~l~.5???W$W7HRHUЗaŁJ3,SL 4mVZ8Tj~%KzYv{'O\0jԨSzV όگkʽCk֬qFܹq/^X`A1 $ Ɠ \rƌdTٯWZ5M^RH)S^v-yX?Ob s#FBǎ>?~5NΛ7]]]={+W.VoҤIcǎ-1 TQp֭M[QhEJ?l3gfϞ}L9=Çr2z"L~u\tPBFO]v3eʔFOđ=x YdYf5z"իW!!!y5z"I_;c=ٳl߾}ٲey#rC~ooo?~,2a*W"E=G_O8}լYSUVF%aQ8 bTĨQ}: Fu@v1bTĨQ!Fu@1bT(`GQ: FA1 bTĨQ}: Fu@v1bTĨQ!Fu@1bT(`GQ: FA1 bTĨQ}: Fu@vd̘1W^5z"l޽u=sLѢEzꕛԩSg\Yf$F7'Ν;nܸ{=uRJٳzF%aQ8ׯ_miӦ5zY/dS/^lkI71 0 1 0 1 0 1 0 1 0 1 =zK'ܺuK~9(PkgΜٺuk@@K%; YrgÆ 5k<?~\Lٳ9r|ׯǿ[~]TVk׮)SL@sٲe˘-[رC+WܥK9r$ym۶]v-_|5j޼y'NX~%KlݺWpT 4H.݆ bCǶc#Fa|}};u$;<<<444k֬6mV?~\lדtx 0{dɒ%ҡC5kTP}(a*6ݻ"E e@xx<.](*-:|/RN5k4h`6L0A{4icTuFYEF3ftss|tLm߾e˖R/^9s7o\n]yٙ;wVZE2ƍriXcT.m'A®zjҤIӧOwqqǏ}Сp0}>>>ʗfEJQyH"ʚh1:f̘ɓ'۷zv]^ѣGWeCکRՕI^^^ܹsg S屧x捫{キ~賥ze|"##Ϝ9~=$$Dr(:j׮-=3Rn9йƨ]Nzjƍϟ?/ZxhӦoo8gŁŋ~h 2ԧF1]t˗wss[n?3ZjYvG}`~Y?@-5!C̘1|}vXXSRV;wzG۶m^~i,yTR]WǪUVٲeS-ZÇlk$Q)'.Ϳ4iҸqUNbł޽6mZtDgJJ*_|{QFg}.ZHi6XN֭[Y|\+w7yطo^!d6X(㏗/_n^^++WȍSn]yHK -;w̙Sik$Q)E3~x?/(T~?Cy]9… e6)jӧOǒV2@Ϟ=X^.]~'NPx駟Λ7O~ݻ%KEFF ڵk:2$˛7oN>n͛7K*%*o߾mdSL9r2GjF?L,5uǶ Fa/ES~f͚(QN:uի;pH81*OrTTiȐ!d?scǎJ/((Hwk8 vg%KYܹ{/UTL_WX!}cB|}}۴i#G/^;wnhh EƍZW_}ULC&W Q#yXJz*SWZ1h6l0G~B_RJcg3FMQ59hРwʲH:Frq3 On߾8}:uWl"/XHٳg:tعs(J"EÆ W^1cDQ.]=0+V/A`yP?Ҭ<ҥKW\']|Y~qÇ׮]H9ݻs玼J<8<FΗ/_\?~y\GzCǶ#F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b!F`b 22رc'N;,Y/իWSNѣG&L i F@mh"۷oիرcsɓ̙3³gҥK8s^~ݡC___Yd*V؝;w^*+wȑlٲ%QNxbcǎ7.yzaÆ~ݽ{vgB/Q`ǎ 6_~M61ըQC9RB]81 `Ajϲe˞ f>zhܹS1bDk;tPP!S~ى'Mvذa֭kqww\rժUܽ{7 (((W\uussS/[f۷f*^^ 2Xu6(G,gΜ %*=װ[n=~Xj2_|?[nϞ={Ꚙ1z Jh"e˖Mʏ)RȖ-k׮]DՑ+WE)+3eO?)5?]7n|ٳg_|L F@|:udJ}]^LQ;Mԩ2eʿȚ#F(s2%F%'K,W\=zpss۸q͛Ԋ+9r>|DpHHT7RJ=C r.9IK.\,zE=` (gʔ)GΑ#C# *!CL6EY?gΜ?ٳRĈQY(Wܾ}V믿dg̘13gΔ)S&22ɓK6?{ƌ8PD e[/ 6ouV(gӧO/_|@@s}#G ROUF ??}.\ДH1uF$G!~_W^ݶm},&M;v5nX͟?ڷ1 /<<<>~]tYrt^,Yһw5kٳǔH1*ѩ|Ux>}HqJPĉ1cUT1G]bl2FaaaӧkXHH޽{eEiҤ;t?еkh#w]^=OO[n)F$ WLd>#Q!F >.]R$YN͝;wNhhKʕ>kJ֪U+[l3%0FMvv1 @G(XPT3gμ{kLzV۴i/}ѣGjL ܹs 1 []vtRCWfMYPw*_`*TPPPWDݺu޽{/ZwLU1 `ׯ_/ 6mrN֭[?{IJe*GqzGF1ydNw}3g .l-FdMddƍŋk.1 `ϥw-iҤ)˗:w;|p|h^zO?0aBLe=z UdȐaΜ9|&qㆴɓ'/MxzzJ 1 JDzxx.\hѢYfkO>-YO5+O=U]/Ϡ .ܿvݻw߾}Ç;t|_L8QjJ=**S>ꪒHԩS9=sL&M*Vhŭ0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 xŴibO*U̙K(QR%YvjPPкu~|p 8~<<<֭+WX={l۶mW^M.]2e{dɒY9Ҧd"""͛#GX>}ܹs2e*VXҥe±Ŷɭ (`/$SeIÇ1E]ۦMe̙3Ҭ^idc5CF4i])̙3f̘G]#rGL#m޲0{F;5,,lرϏTW)St-ZbV?bcTѮ]kת?:Rs:}tժU{Hղe~Mqܸq1I.W[;w4lP6[ʓK5d>W^SM:Un'Q^h޼yk׮,=z޽{E[YX`3gNlC]KVr-G;v,P vܩyf͚RJ/e~ǡ{왬)Zh``UH[dpp-[.]*1lٲݻ+2: >52C)Btm!F{amڴ_ԓ_~9qD?;#5:ujS믿' )R3f̹s~W^yxx4lPJW̙{xH"5k̘1cYIm޽[.k֬2Zjў:m6eyȑ)SPޒ.^O&M̋iK \z5s/_|,Y 3r;\rE"ҥKrRJI%O\% rʂ\qr޸qC%ц & RK+VOOO.eY>@۷7h A#cާOeYӧOW Alܸߏ>f֯_׮]PDǏk$塨\ˬYlJtF"Ut~P.]x;/ oW^@II9ovz) ȑC.QFɓ'O0!""B]YpiӦlR]3gΜ?\YpB=V,XpժU+WVל?~OǏW1l$5ݍWlٲիzbݻ-RT"}o5kdAヒkȞ={ԨQr륥]Ҭ۴˗KxÇ+V( 3g:tRn˗5O1;wny # SLu矲Pvmenͭ@g(`/,'N:\d)FE1HO<ΝSbÇ˗vZG}zje9VڜlDՠAl:1qI@eYo\ѣG Կٳgee|̇ݿ_+!(9[l>2)ٳGHwٳ%ym;uPy1,(Z2eJeYcǎI|IY lJDbL2=}&K1 M6]zU])СCWW_UZYtR2׬Y#sС}/200UEy߼LQWދ/~'e& PS"E ijժIH_n޼Y)Ru޽"E(y' y').ZH:Oz6Isߡrܹsnf &|ʩGP,wS Q*UԩSG:%˖-S;VQ6Y^s^sO<ɜ9sϨ^ǘyƑ{P5oذ۞(ŋ2EUǏMbtڴiʧ% ,s*~&Mϯ*2dȌ3"## *tYӷo߅ *g  3_o|}ѪUWb)SdQF۷o9ʩru7oޔ'ڮٸqc-eɩ5j(;ս6Is^pAKYΐ!r(H5}T޽N:^z)/_>2))>|XXPYhtXRvshX'w,wqVlr+ 1 -1*gzKZi/1z}]צM*uzJozC˙36)*7dɢ|!&f5E}*]WZvܩ~FRXmeSԗQ2#cjڵkҤI#zk]xLRyCqӦMrbVb3'W|ur%Fwء~)GQo{!gr#NDB.]d2%KԃR)rZhQJu}.L.~Jł wҧOoig;rrmXLG۶mnݺ{J*#Fj ڵ=3eOפI{еr |xڴic!C퀴|7oٳg͛6m.](;3:i$;7 v~[2k֬6vϞ=ː!X77лw}ٲe|:R:x޽}dsժUS?kq$-uwj>cƌ:'lu+1 1ڣG^YVn5?{z3'vڹs*$ό֫WO#F gihKwU`x^z׬YSuL%{P xC>}zFD y=zT}]tiϞ=ŋoܸ`1/۞(}?F'OwyGޕaÔ7e&_ҾMEQ>5*7BO>`/^>(?nb^/wȤ$_|?+6mZ A娨T8W\-[ݺur+VLK{GEβi&Sԗ?.]P/UsPK(Wy*Ŷ[+ 1 GW^-hfTR?> stream xWnF}W˲W{' nʗCbM%6T ٝE[B]̜3;3:$4f@vW 9wSqPKСÆ%pglwG˖LbB8:-(L(,ƢfWRymksX` /vWߞBַ>0= ϝ3+yfaU"Xi-t>J`Oohjg_ Nܡes*M:7+ h=IIZ48Z]ZX6EeXGyy(&vP@0anSS客3+w#j蛫Jww/`3B <6̲ ~KM'kROv{P"ty#9\Uwj/o/tvңN1GpHD,^ouz{sa.wl6hs~ OO/.`< wj !/fߐ+܌oUP'#NIڟXUb/C.L )*:muL =^nj8k 2 N <ڎ13=dL.[,@{<~".϶ziѺ #OF)2 +8lG(X **}v -;.Mt$ 4~| } CzapfYrSRw@:˧vE~Z}C 6o(0teN(P~$l|@gШ[FPGDlFȆ@'sІ(G?$0UY?dFx|m&/Bchs/P\%b]HJI /](21@ҏT.ZHBSE`bL }4g% W#y]'Y.6ʢB /fYIb(tU:VFf! r}f(ò[hWI?*h" aM ss8~>@wBeR/wPwĦFWxH]mO$,Kz XjQI4^'^ߟ&=nqQ]={+E;f|㐨VQeDaEpa頚Z` |}+endstream endobj 139 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 142 >> stream xcd`ab`dd v 5400q$baa]H~= Pׁ? 7~H/(>GhXKdiVB~FM|w> /W [ 1 3 1 ] /Info 3 0 R /Root 2 0 R /Size 141 /ID [<8256376fe8bba7510ad93dffae106c77>] >> stream xcb&F~0 $8JT 3"WH ?XDr9UjH D2٬J`?liɴD*WHvAI] ֫$Eb"`3y~{&3\`|&EnSA$ ,_ endstream endobj startxref 102900 %%EOF Matrix/inst/doc/Introduction.pdf0000644000175100001440000021353614576344041016454 0ustar hornikusers%PDF-1.5 % 1 0 obj << /Type /ObjStm /Length 4346 /Filter /FlateDecode /N 84 /First 699 >> stream x\isF6k%ْ/)vh HCR~_)[NJ7oZd,6S<ә:3v2Q,s.g(YƅPx!Eq#N錫Li23&= \&K`bgx9SB4CeJs:ӤDja3!GH F{(2j#3)=KK4QeNBԙ3 mI)3rweg;|d2L@S\szQBU(3)1yp Å4Z0ډ TiHiMF^d !YXBCp^e%4C.^R.+0(lA 4+PFy]!YBfd-Ԑdm` kP4$ @mn,<Ḁ`n;H6sl!onЖ[d+׏?f~9fx@>ʊ>p<~ý,{G᨜fUe?>/tZ6)zC(sGt_1cnrr?jwK30:fLy(|Wy\U6?dыQV=մ6ߪn{#x }h/s_qXbCWpH(ê^NYBr-:jF.kQfU}է>m"+k{0-ON~8=GruptIʝp`B,V ٌ֟ A(n=QpCOȤ,k>?e8K;.HZk|_M(JTOP!.9މ%7}~zFL^^dLb(|0*.᧲,a{1*tb8>/&Ŵ?m_9j{Jg\.l#+!PG 1w/NQh:lotS0fM0jqwZ2}213C]f,xUߒCE)!FL>t 9B~Ae˗z:|m<}ܳ6o%IcZ[[;1Ś^cc;xƖ65vBiF%Ēx^uxg.-d ^QuO>K [Tu[f[W1/,;oCT`MS4خ 4ĹXg}7QR/])!A#*Cc&b:4:{p\pYHqbD>4:ʰIAդ,Ъ,rdCF9#+qʨeAbH'oA3zFDdIZ!i6tLdMeB;ҙ{Py::`a |*z&Md9kD]xxkQyV~Sf6v^3aqΒQ|.AȜS)x3/^n\zܤf%Rp,~q^YQ/HW3>oӥ,2P=9˰{-ޏi09r0$ݭ<"p$Gg:X[=|VOR 7;Ub4婿D3GvVv}Ǥ1<0̡ws[G3=_[ ׳> .M;yq2MVxr}1=+fg@(sx?\Jq-\j8Q64ui4^avs= ΄]<7ڴ{i[8{KgbNi-}-*UK6Tv +f)uژGۜH SR%)hi.WCйc9JҖ\V֠zp :b^em&@wtQ[[ lfIɘ;䪇vT⾾4S]յDn3%Zd~dIS_KW-}{4NK?1XG{'%|e8Xt?2hvaGm$a50)E͵ c3l8ҁ_9yXjxْ9%swؔxlev^c~.'ɕK3ͭ43>1זnS*ݷ--.NDZNF:3HS (R`mifW96څ鿙v(PC!߫@KڳZ\+7kW{Vwl1q2֧ã+s K(Eqdp $ktA"1yxzZ;tN{K1-]|# KGvJ\2N xViNy{Ŗ 3`Pʀp/Ҽ=2`вR;:1Z;!P6n9'`M?~\}NNlE&&trqL9@w-ՎZ yh941a@Uuw74{8h}n6Zp|;g>Ľ+m'+u Vܷ~yv|D{G7Z6RI5^Y o//Zr?hE{O_(8BؖxSN¹mG~ ViA3<6 G z\k, Xyx{@\Pf&wO`H6V9O,rwqARRN)Tk9@ ,a.hYy˟^: NzGdsv~r5]YgÏm4aކ0bh7U٪A0Ɲr&^љRQ?\~Go}+(vnc Aigtv]޽Z]d1LTaOwpKz9̶{zkkuBY*0בFcs_w-"endstream endobj 86 0 obj << /Subtype /XML /Type /Metadata /Length 1388 >> stream GPL Ghostscript 10.02.1 2024-03-19T18:15:13+01:00 2024-03-19T18:15:13+01:00 LaTeX with hyperref endstream endobj 87 0 obj << /Filter /FlateDecode /Length 3223 >> stream x}YK\rrxqrI3Nv+gr8#%o~}PF ~~ +R*WVX|}.{XYH[6I[Pw/~lSbNrek-vԭ+X('k+,8ѯ7Z겪`)ZL6pM;4ww$Sp&g]+'~[[,X{A^)2aI?&VVVc%,2鋻uaT/N 3>B{kzե/\,)ZUi,6ږR|{ .CӴqg_l@Hki@7m֪*eE{8܏mo*H? L*)e ɂDGxoOE/||1M8/^ů v083,Љjbꊼ{d)=Ptv~,,~? ʐ6B;uNx(J 4aO"vK ?rUy X-p1_QX JB6;bO 5!{`1BX&(( =@aJog-J#88C4Rd0rsQFnbK.t?F :ͳIƩh8Fl8`dTn*+yӾ~`)L%L9Zq &fVPP\$EV_kjRn k#Xi{ z]eX];(ػJs4fJ8T ZEb׆ %ή5.Q/46Ϭ4" x}9F|*E:h~̱}߽{(0.Ԉ>7XD 7UGDzfCV@Mk\ Re!NѐERFLHC*SJ%>SYf=*e)Pפ^̼Jkƅm&Yn&TLi}b*J/x 6ϱQ.X!(U9q]QH=4j֥tuD炋- 2yZLty&u?Z) :ZeS+Kgᳩu֕ wI%?0=LK TBmJ1gS"^4)@Sm?lo 6 8P-v8_  c2ClLDH"GS+[@4y R?6ڂAqB h1% #b*6ﺑ{k ļpJ2[CD10s^˒hqDTdf=' uD(l:NC*v4ćkkOB|8 ݭ~B\8(WUJ0+uidq\ZBV4j2hLH~Q@ $қR*跔8 !y̗1._iAiU[HW_2~}Bwp45@E=+d5}^BLt5:(A] VKjKGa{w<)8އ?x=/54&AiT& ٷ|*A+'vi86[[d|:\&R|YI<9> stream xZKoȁ%ybP9JHJҪr^pͯO?f KUwЗEE¿Ur%"-~;.$w-n>_ Z' gDi]}qTY*J2IS/.Fۦ+1m5,kIe^5S#R{ZmQa%Si':8q+TeXε8re-Z+~-xoӎ D7/G"V畔In\ܼ(JP5In4/3)\TV%xU˄)Y# Mq(Xދ{< rZERTSjqJT Pm}2Pps@yQe[ƻ㙮|X*I@@zE庢%:d]2<}[^ ~`viFf+J;E֥hвl"|]usJML΃?.=E[pv״5- "9.h$չh}>jI( /`'@{:~Jv渎Tn:Òco ~ny~[qT1mc@FR֊+MјH w(ھ YP*2&p]I$r`./2`FQ/^܀QMn]/hkjP\ࠒl&j<ŠO1%Aj6pdF&' +:IrLЬԂ)W!$+r@fS\z )v^SR~;W0%r o'qN0(x讷M6Qo;k7m,6h|a>{ђ]%}!:OPYεnD1Wj(:dxu}/u_luH/7a )GK]u}ܔCX2ZwK6}0vF2MӁHqBN?GHDgGoF!1M')mL QkJ2 3`%%dZMUB>w&;@pUY"fMJ`W0duHKTKU|G;(O> AHT-%VȑS r$-E\A!z we\(SJ ߍ@nhh5Y_w##Хښ!Ŷ`|vq6qɎ˖#`=UTeUMRCK-хV\0Ji8QiSD }Og_We9x*M<([F>3g1Rd <-~ϘB94g:Wc:Ҋ&nb MA7.2%,n@ *bķPyDi,D ,$(F lMGe)D,&tCK"hs\UCx ܇|;e\BZ ʸI1063Id$2ԧB 67,UeiA }؝CPS:B< SIou$ 1+ܨcOɢFo˞37x]ŁI(/0CEϋOȔZWĊ\26SÞ , Ӆ.%4;ѓQ ɍ[xwrOb^&F[;baC7PVu4%oq#^ uD L3q=&L`*Jl㧺Pͪ=db ˳>V-'+;cL<1csDAl[NͧC)&RvH (`Z@43u*8p(eĔDVW=s&tJ&0n0G* O|!v"@gg*Tw OqzxvM*7{b·b3pWfcL&nk]|$(w]iq]$/SC\3LK_?`0!-UBY8zkpƜD]%WYj zw?-GZ{h<$oTӉ.Od;,L&=M}_Y_վ8ir7Ӄ 6=qH :>׹h100Otv>P:s)ﻶ9"La tD wjgM:=mf'&TmDf8tJL?ټl~;'|\-- 儛 <TqL-\s1+Oܝvr裰}P - YyQ^e0NIfHi4m U |ʝ  90ҸfB?n~?GGendstream endobj 89 0 obj << /Filter /FlateDecode /Length 3249 >> stream xYKs7ڋ1<^U;.V9PJCIO?>F#]:hH t믛]Iv__߮2z{ovW)O}4׻+^]g%6FDzw$~yFZlIQOx]Q]_Qu4D7ΗUP/֥NC2QMyj;,l9WCaUy((~o6S0Me,Kn ߈ƛ LW),jCՒT{8I"`[3F}AxӰ}>O$l/}h \mфNvՠ^|1ljRn*(>ˆrtkCf ?u3iĩj*LLlSAa}f.v zfDk1J^C|Ӡړ?\;OnmUفOlDicus-ظ4e>hJPN`J$c͋Z?Gޤ qS3f֡=Y/ א (Jx'pU^8,-3`hKTBǎӳU5z@5`K`HB,K`d R[7)ZC*!db <CH{xyÑY#(AIe-@F5"UmV^7҉e,ӑ -:(露5v1i'J*XvD$1^AAW4ݠ%w+T4I~;+ ڡ>WGօ_Q0Jw HiG7GPFGRSU,GY z >zX/bA}ώ1x)8e|H/bb,#i}7a#M`ʐŠvĨ!xe !Wat4g2vќ|%[ Ѧ@:m=W- )(M/Tq$SCN ~Q}c{~q ikͮQJQ`} oPp9UC;!e+f"v: ƏK{g%Fi[`&f]rcm}rl^@_LaH؂PY%,'_YZᘓ $pZX] \8e@u*YʤrJi^t&<Z/%og(.n:8 w\:c$@|&ʈ#M>6No".lvJYTyL.牯`~D;mofjc\q䭅Kv̛ 9] vf/סj ; /<H!L8E9ִE @~r{AϜ.1t1',8kHe< }u&^R&&Z0WS/BlBz&2ݜ PGĚ PBaO a3lt ONxSP;tD3bL3" "a4ĂSv1wmaE[Q-)xCU=~ cVEͼL痮N·~At'_H4y;&^$" 8rۏ,X]5ȹ(_M?r=&-mk-E 4kr(i.BeЙBx . 50e5EYqg !9hՓ뚆LD j*gIwgmG ISosĆ﫶-|ׄsg`]mcAUs Gy [-)\_~~V61·!hú/ #EOͭv4m< i]a^@-́?c|ͦuHmp/:Iiy(NkvJstJ%"FchH 1t=TtNqaiΩPOdleS秳/]C5Ƹ0aiQU!֍,+@vjY-zc1vzB'5e:bѠ[eӏ{@S699l2y6:BGᔺtE{O_-!FBb}׌Rd P2^hD |t2In,`C{IvRK5%##H΅7> stream xV{PSg?1p7Xs޵Qֵյj*["*%$ׄKhm--Zꮶu.:ݾ~oo6Lr{y$TJ"$OMya+b_!1i(Q|H>=L^)KJחWlܣݻ/%;'7/_QHQ-V*zJ2mԫvj-zz@m6QԣC#Q PE-I9[ER:G/N1(_W~P\ӼU[bbbÏPFy!T#~ݴ`IgTxeu},NE~w9y+#ڀYĘbϫhUi;,4 zh+zcWM|2F4˸)VE7DkDKW#s'2"ɑ#??4t  _ۓs3ˊ%u<ͨ IUb}7  zL&@ތ0ĩd 1tIy]?.C qM C֧Ӣ7Qb7w- Vmm$ofr&/L?G/Y1djJow Xw3%(*ux @F[ԇH>僧ͨU6U;a9>,ؼ354Hnc>/HIj* < gFVvUl!g+F9AJ/+Џf-Be 7*z&;ݬsV^õ7,?F7 `]KI>}ӓr;Yy/WȈLkz0~vR,=>? Nͤ/7XeWIcU·PYKZ"i|gn.[SQ^i~ochyAxMv2:G, PчOE҉2J*li, T .)Smڛtf3w18KeL Z6.`i55PqwYM'-9V Tg:QBtD swAWA*kY 59`Dާ7'+N=&MyIƎ^ >όjО AQw#I69PC!&t*IeR:c 3}ٓ$cqX#|/oAr'"2z+gӧ^2r6q:3"֏}O̍{r;o+5V}GGk k O^yuum5Hor0oNC6 >GW 93l#Iw-YlGP{ 1!Ao);GY>z&ѕޑpX;* }QrQݶ1y~VngN.rf3FV ta#/Y{a:1کf΋--ծR0n9'gc7da9Ѧ:#-zYtɧbc bH>´ Bp:jAA{jҲ&QG4#ww;/^ pjYY[9Ôvo²;Nkerry=GB -6Wm8n:YD:"p^f!#44F2|UMZ]8Y.X5n o^z-ye^`wWgN0_ӣֿE)?}ʾ?p㣏IKذqK訕iWJgqٕbҩav 8v[.G.{b3DJޭ:86C>h&Dcџ26V<ʰ谼,\.W ZT pkG Uu1)s.ĭM=Y%eu=Z< @ Ҩ h;^S}52*k5rlG=.qx$!6ΖcGNzĞhi0)YliyyJ `V?>S!l\ ^ :=ȋ`[G7i\F[g\7pv糸DLK/KhB8zzNށțsrmݜ䝈#ցNI@3ޣawچk--+0(uL!f&(~\WԭNV U٨~I^cpSrqJLE"b^4xn 0t ʌ%Sd,ޱHvI"y\~.N@İ3x^\+b^WdbjNNNwh2#TȌL׺%Sҏ>yMoO^W#yw겊RuBubڅ(6IߣouUYUmpFdcc/LK!OZڧ8@҇T6+ۗ'&Pb\endstream endobj 91 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 3586 >> stream xWyTTW~eAk5fq$#mV("{P@US{P[QH!JL D M0JJΌc6I}y3s̜3Uչ} I@ xfmW,[6ccQ0USsg%3>4csaYV\f,9pVEQsai3esnOHI]eW@Q;gs.j=^* P-o6j;%fSAL* J;}[rV9ej59([z;}%rk{^>&Ԧ@RئF&^ԳDR%/jDp},qXH"ƳC4&za-J˜(zY: KwYS3ۺ{'/qM7/*qn;a{*h>"^ۍ86Ϲ Cu}:Ep9ƈkrr9ܸD%(7DM@Vg;Pf.r$nk^K f*XE6!^AΉ[*e XtKKqh]B@iV0R':JxBV@fZ(A&}*>qѸCǬ6c!p|Joy9C)JIZC#І^d5)m۝gQ|d+iL:K҆NMVp\ުmtFYFՐ)F.293ik]_&R(տ;B!IEf{l% [u4<JjxYvQ4ߝ-U&S`cҀznwGnt^i x&|J–6@_&M{ȳd#y{Akl8Sx/M`ϫ eFNGrD2@3:Ru'%%ѮQ4|^<|~Qj~v/dž"ylɕtwqKiHᒫӛB\Vb<ЗKK,gYޒ~@񈴂no1`~ڰhp  uC?o+ U}/tpEKEX,ή]OveRknP@tB=9QF^m*MŎiۋ@#PJ;S|x'D|,wEL/$id6f\0ZՏ8X]ڞxzN7Ae痢d]OsZ, NU޺& i뭩kh̭18%/ ky?`\%.tӿ{G1"Gb0qŀr2= wn%AH "zrǖ,e 6[%FP(չ{4?Oۄ8to^7  0W/PCoݣ;D~g|[+dq?y2Y|<j)ȫyp`q#R{_--K1LX߸ƗL'X: ljTTy}d_,!G;M"r)/ ns>* [-?E~K&A+{W9mP7>OJK,`AVPhH/1 eͱCInw?{;ވl/(1;[]TdK^o2"r,k6$| F)ESA 9D_Ѕ{IC{7W\Z\ʗvϥj<fA",rUWT3V A<TR1$~o[kZUXgsKwlYrS5#~ԇ%/>v;.?xn.ۄhj&>eӘ'Z]yöcy;qrNn·/q?ҹ_3CfRDG3KO KН;TagJ<>ljeIFէd%&B$F]Ew[k{ey<`=#VD~M$tSLt9pMahw42`@ 4x/$d"iVIvLۑp ljL qy;Y-l("G 3>wHxDGL[|t!%[o~- mN\X|'pP k:>9=PO S' gb]·%V۵1=!! 8̇Oԫ^/=m=^9Րؗ47Mߛ,0 L-wU)c3)}:gи>zTT䠀g +J@Z{X'TV >>v-%.W.[vÚYlVV^5B,0p0"?%jkE1w)CkD/~߅܆"|}aZyI=VؠK:ЃsaA^'GaJ⽉ MEK?)BXak55ZMCG,ʴ٪T|HGerqZGS{I/GvE.].F|_uoIY{ZGSR=jGU[nQye,gK@%q58[qTRT*m}BFbZ߾uXS]Q1uSBMendstream endobj 92 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1844 >> stream x{PTrnd{kc'v|`VTP1(D ,vYv>Xvae]D pjT0%mdLtT'14eqڮѿGϙ9g;?1-d7_pLJW![L3p4k?x- 㑺whGqIy"nc Z w쏞]-oy٦OgGP2e )nEf=j`%uM);ZN o gݫtA!AC|dld;vvB.NOa8?X\Km4.m л=rA]eR"X}.gg>庄424w -|֤A;\KfL9r-xjxPEZ˧gm(-AgWMpz7,n:~OeB# |6WKͱ/7n>t`b :a hm]Э<*5Q~CRD.C9=,̶ ‘`0&ËL>귵."G0L Dk$Z֤DCC̣ʺbJ] j=T@ޮ'6rt~6:@<:sjXG[[gUVm7{x)8= j^ij*>>Ku%ksIxDJp=UoI7[p~Kn6>-$jiCdc 6K-4D[ hm =|$cf: OEQr@L 6U+>=V,cM)Rooendstream endobj 93 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1041 >> stream x}LSgW !$.!ư87Ȩ`P@ʀ^ʥoˇmiPvvYC3زeq8 Nrߓ<IH$V_+=}cI]k81zq^`w\K@C]XZE(Q:ltQ"GкȦAuq !%)֋ W :5P&;`!=#-546'7`Ho@^(4 bZ6Z{Ln>ܘhWq:lFS`DSRY]iڀ<{RDI/"y q:p}D2[@ʘ ]JыN/Ծ^yC $t![8ji5k/=qEiwWO<ɦP C{يޥ {>ҌN3U|,IWc n8kc[& uTCVЊv576%,kc'+/0U)y%%(2y*ђ_y#ue W0uPQ)Y#b HjjRDCj@> Uxb*ٮ91uNkik|<}c1f@goG;}6qmsTDS OR`&{]z'}SV^7(9_?3{nrc9 rlE:^0C}97l]vƁ,1N/^10Ie`-[ ;.Lz:dxatI NZďF[{ iOO17 N˕V5Ԗ*0E|V'a!Ƚ5S-bPL=d v~_`X#)LN}6QsywO8syg;@$,?? !F5FYCCIIS|l?'Nu{#̊Fendstream endobj 94 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 5305 >> stream xX \TU#r#uokYk[kYߊafxσyy2a" PH-ڭt< T[]>gΝs}GEx1m;?q_/CюG#HX$MLB&W]&k_Tvu $mJޜȨ#ga)W:j:5D=EmPOS[hjb%l*zCmR˨rYjZE=O~GQQZJ@R$8j9<('o F]r|kFOo51`̙/-츦COxw➉W'|hC'ϙ|+lg)9SNL9U68;|{V 5Qyŏb ^[@BQ),JʾՐA l*NsL&u3Lc/2(-TuKЖhhK'6rյ( k[|Mb3(KƢh,:Q/}@Y}jyyok(Z8=D ~7t6!Arg}Hb 0{S1Q,VD)ͥv,̤El676JKba\'`:Sb\Gah~k0%R f]<I4g$$g?\ οa.%Rl#wn@ M ߹ʨh/\6(hDI9xI U A@=c1 \̿ ޯ}߄H?580ߔY BC't1Revz HV{}a[ATfq@RKp|:Mb%xXgÎC~S6JaǟL=zR3ss_1֬#Go{W ;|).S,%IbA3ra.ɮVy<n۔;R,㟡X_ Co4d]2UdDA1@&FX!m;M3kܦݵJiʂYvâ MuD3>Zd (J 6Oo&hIRvCsÙ1ؚn\Y1箖u?-KXtX-MK@%kZH^nBY3Dcq=ҭ̒u򭬚^lw: +r!2h8, urnw6-J(J5Mk 翇"ؙnJ S+s2.ҏL#|oVBš 4+d6=n<",P ݬ @Oa/x)A2,: ¡# :4̠.x$ UP U `ETy[u'[-"Lw?rT,U(HX-ƝU}0XoU! {k7,'`Qn+G";f*a=\.?4|iQi,.n@bufOE+$dQ:MnuDA;ih#kL?۹ $ȖH(Ƶm%ETW鷕;ˋ* ]̵$"/KbST ¢RTQgae!h0` LWPdkQ'ύ:!XE-,B_W@-cPS *fmGf'?\a {%Q-u}_ BFoWq̚jES,0_3.N8楯 7θOz1@/L6Բ(|lo椿*RQ`,ƠD`&X~[@%^KD] |$ѽ `lju{Dgt$8I JY*qFۆ7|b]X鞓N;vKC8I9y* ֨j ^FLBR) zZ?=Y?0ϫQ7`NTԤw슰ZTaN֎;׾!8A[6]1,uUuz6j` >&Y bORobѦ!}ch21]Y 7e+22DKƷ*:LEf+,e52dW !F&"67;bN;ߡ 5u={8.&a~(1-e,qތ7RIg "c<85-9m~h~T}!wVF "։2 iY^c-5A'+ARNX.KlhZ[Ѻ "W] tra{sSӔRE챔?A]kf}nUwmA A)xH!}cƆOnGicxoӅ:Sb_Xr]BX K iS<8ϻ(fQGlvǰ#Z? EMT? 7sx?H>&|CӧIC u]^β" E( |XWG:5ZuZ.k~QWKZx(h绅 B@t.h?'FaMgCg_ @P%A1L.KhڙK 2OgӮ|hdIVY3laJ>2cdc dًƅ42"Z՝q\|}}}I+'+ڤ54kFY\e_:q/QEՐ)HWNU;-KY}?el#yuq39l1,˃U8Y{es0xOICF!jZ3o i]1[t˳$0F_Wkra t ?L" LÏ$tUmfY^RV^Q{dg[]ʃJ&'S˒ Q,aCژ[_WFBjm}O'h)Vq6`%dȲo ^NT2!Ro&s>"[d"?QE504;m#ҫgK9 s< H p;7\LZ&cG8#s h2SH~<ZIV7KHvup>fBzKUpMtȃ=DdNXDN~ $@ sr~`OJ> J EB dfF0)E-4N VU 116XCo.aʎLTHZGȁÌUCDƁ0Y+GG5=((A1^#n:F4ٟ }z {p~=W,[=WB?"^6{@^ΡQ2buWa݋W[a2j vDGl4s4X<Κo~˥&y&0_᭻aݺƊ5p|NC:Km1I2ug5VM\bRdt6Xe&cC Ǐ\,endstream endobj 95 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 247 >> stream xcd`ab`dd v 640q$~L2{!{@1}ư&LV7ʮxzȃ0.-^r74nlܲq _L_:qEwNI]tp{k2wMj2oA?͓$mrޢnnTʎn[nJn}Z(dsM8丘p20dendstream endobj 96 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2197 >> stream x]Uyp_Yv8vv0thG.aJiL8e[+XӅVnB"C PH  %e:Mz% 'fI\e;3;~ Sd [[g]*FIyٻ[`*VaVl { [-Ė`-2 `c&m&kݩRs[3C`NmDkjnb~{+|Ev2[]ǘNDpQ~CAT+_%8g# NQOGR^0[$k^?c7.8{-Į z<~{e'N(Ķ8c1q3OPGiKWWOlPm5( mHOkGЄcGZLi|Q>t|!j%`79Awoedwu d1HTE[\I5 K& 7Y˜MZ]ܘwWʂ7IBpx`5[*QdȖ%k7lۂ:\KRE* d =baGdJݹkS#WqaOm)BgbGhK({UNܘV#͕joRk8gX2xdT-Z]f["SCb?䎷3۴4yihz|Th!0A4=%'Ps`WTA֓_Wk>[淥5Z{vcr}8 ?}\F~?+ Ch0 hRȘ*t:<=MdѨ]Sġ)hhl䒑`INI%͒&-p(IFf4)f 1 d}ټѢ UH1s%ul dtNfi)i8fHÉC4V3و q 2tDQ18OM\,@aBЅty`-?.qpw{r^Hd@2ҽx;mA(=ytU]]g)h?d>ī,~Ӊ_-ŖԒ9U þáR :}&q DQF=*TU'$i KaoOtffeB+`w5  XIIZs}ΡP]EVmMD(Ec[#>+>dcPr'ѡH(cw&N w@j`5mpa{N:9<Om y:SAJ=f5E|\[jɸ=GWFq ("6ؘ{3@>0}b[uߣrR3m@  VdVv -dD' kn\4-Qv?APⴻV4G50!Worry\MD9Rݷ؀+V1lm@6NZX m@CաJK\s;5 {--h T'nQh\S7_\3Gl'Z]fm"\&(8> u@_!e0zGI)"wyXUphZWQ! ' ĠR pp̓.9> stream xmU{Tg7EeHXԶk}Q[jyY| (!<BxBXRڢe]JRٺg-q'j=gOwΜ{/DD"א@oygV!ΆtiGgE9iJ_Z"#3(V-)yk+)j L-R!T(FmS?@R먕zjrʃzV"T*u_NNJRN/ eװEn` z!yP]Q;FLPݠ̭'p~cY6+vY.()x7e%PBU7԰}A@H` K C9`Y=(%}Kƻg MYt>?Qo8[|m>2UP0'm !Pb-Bʡ@1BK.5D|8q\K Usp̀\pgx]dM,D1n/U0s8,#bɡqlqTNS㼓 ad#Ok~\"С߁>X=ľLj6@{qIo>(9t8k9~gejL ,Ɠ{,^Tj)limh)hP0.!vDn`bwOLW= ;P%:D}tU>dѩ)l4{hrV/1<&my-ljhZWK+>" W޻.7kg6sOa-X-@?8vJZ:$t RYjwS/ }pCU@,CA|ٔQz68VVh54_L@RMZ\dj$@E*jXQ ㄫ0QR]1.L)^W"}_' M @Z5dGܲ*]%T"}DfqQ-JkE?&g5udZ: '+d*]فBgOMǿTTE;{[3,-LQ+iJ wwUhQڰׂ6@gЊy2yݎUOL{ {QDt%iOS-osVOjˌyzC :ҲHs1ט[Yh9hFSO7S9Qֹ1M{!Z&SDu{\ޏ98̝~@j5@3r@6ڗbܱbX.O۴ONC[ti^iZPJ%)UPXm ],G}}jwgEyY>RAqd?.t3%xW 0詏d6~*AȞC%5y UEXb> stream xzxW!@ Veg IH 11lݒ\d~՛.YrTSB'z& HHH6^le{y{s#݈.{}ȑ& h;QW$9p9>ܿ3f9Ys)/^ ea^B\E-پtDz+RV W~cq'b`n~Tu{IԔw *ף⩘=u^zm}zwLegxFGDG+{6/ҿ)-֟π|xf 2A5<g >K_r!#5֋;^l{iK#"n:?}s0Px$/[M&_  %d0+l*B'<i=jJVBidȶȋE2mI<_Y>);i@bd9&-CŋM| FQP7a!1zI?A^~k4in"b  4cId"m O+}PGD(޽*mpkF1F)1޲C@HHnȰp,&p _'wt% *5Hr<+A.mmں J+ih]Zw&;5.ভ#D^ICC' r'ln^Uh&hGX؀\VfM/WC >DOaUh.8<,tRN[!]7Yc`V@xhu`ZTC*ڞOcr8fٶΨrJ}^X6{v"ːuH%7ji8>-}ʑ3߷:5}l07;7`6}@jzuuyǻ,̕咹@CFwB2Zn3f-˸ (|eYYV,Pg;}| J_^ |Pgu.4z۪P&l.=o(3G}gC 'Ȧ)ꭺ?z+|82ґPDPb¼%%"K R-`BX$6g,ZY ˳+囖s sl E7U Ut5EA#.֎ru!R Mr@d1cUB76+0%ժ prJ t}Ey%VT_96W`!xn; A)kRmYhK5Ɗb9d>1vr"u66oB\i ][w%9Wni ߔ%Moü`1p6&mlqaHQB_ hEi'2Fɍk5,EuVD[RPZdͤ f5er#No{xiel\nҼ^.i{JY\ 3#p.PfaM6|#ObkLZj}4~c/}Y>̘VS9Zv'RcicBh'Rs)76#N:y'?$ST;OWxod-pH1{ma)V* h(RʉWx i.pE`$kYp@0~ğˆ(ɖҴ@¡6@T<ۚE+ES,S]= L`G=f |4t?aá$jse 1TN%$31ewphL]yXL5nfJjOm'YpmP1;X|tR=흪FG*(hfayZC[Y8="h ITKSeEI2Χf$N<9l}DRo;AdcXtGTb6Y*59TaRp3lo@+lGM!Z/(MUFI] >h<p#2mNƦN6Ǡҩ\T)TUwm=dqE"\H}NMxժ>dqslj+~6 ܆a(ko߽wbƂM%3\f?eV]w1`UϮ[378as)ŗ}M+W;8B{aDA6M^ zp|9LrTWhM)̂MR|JN 9/.~4h R_EcWISh6_)ר땵 =5@"2 jZ8Z{fu /v?ïVӛq# MَbX548 .6bKja4Mͬx*CE]ITg"GppkKԕ9e LB/R` \0kèV=Ju%;1JJYn%%EҒҒ"o[.*.{`N[n&*']("E H%Lb/-{WVU92u2M ̭}eUc1(1޵sXP8U]CA>,mͦE\l\lXED> ^h>өt`:l]Y~gV7}4BY2g"EPʇ{IeC"PG'|V)kՀv7Vک8&+LƵi6ϨM8hޡ~~ޯ>b7*ŏ c|Iu.SdӖY4;eAؒ%p<ĢpZNg @IQRAK4.npX{R \ M@BpXi :0r$Ĉ"IiTnT c{n]2|!P'w]>)6j]LNr`MEe-#~y65ÿ>_i3…ߜ;Zk/zhއfiY:ujC-VXSq`5l ԤMKUͦ*Ahz%uEMcx(`*ZڸRBNj,.c{=Lf5FN}%rm޽\'#ʚvVJ]+,-+*.w$2Aכ0jڥҼřǮKdmzK3eM- R"qE?:!:s0n+J|Q'}n^E=qJfVQ Vc@?^SDp}uo1+sޗ~uQ.SF] D vgG( D)(GhLsAb$ACW͗v|VS6oη,t(ƁpخR 77N .q. "5rfꛎ׮l=z,,9IaPv&^lVBײ,O931Cdwkam!mo=ί[so D|bt ݐ.Ωxj^p}.Ǝ}QYWg03s]moME,d|2|gnhp7/vH5,jvi㭦$Tf A מe2UgBYth2 节81.xB$mq;^=׵OjbUO3jL//2V!fTK25EDܲw]:d={7b֯ud Rkg{㐒0&crNʣFAƢqx|.vzll ?vOt.w47;R ϜVf3z2'W\ `rjџ wrè dD~nvz=rzdmHބvJׇ[m{̾&ӆ$l7 =L9 ÍkBdr,. > L $;T.y">IyP Y-Y;3[6(sNA.R%>Ea E;0`bfh.BoauzNQ#A% RW RHfCf-=qY(ZM.~arcIF;^t٘ҲmVc,SUTeEr[ zz$rv-n܁a/rk0*-WBavHzQ#KH Jǡ,l|4Upcނdv8֑3 t^^"o!d9",ݙu#}ȇ#-BjPCWHpb?6rxlf{癏Ko(4p4x8z54X'vXk-]󾀆0z6<0c>qlv۵!`/ȝq~}]NefFNn MۏsqZ 6Hj* jMty \j8tp8pfLvM 0O`Hn**FgYufH7:ݢTVۙmC40O?vjb:ϐQ{$c& }Ag7 Wvf$0\Iffb4iZ^EGB{K fC] B[aF1yԛZod|5yok1O;&Q&j>!n!j'S+D1A=]h3|g_eqEqŗP pyvܛQ@a0X8 O<ѧ:zۢzHpoffΞ& O  y>՞xrF+w)2 :ǽ;|kq?({`3l#'O,v[ڐS.۝Z07}ͤYS~G ܏.G*D|d&ZF08L,Ԑ(4TY h̤2'%c3ItZIoЦu6qVkPg7W.op7ItjZ34A8= &]ƬT$j,N:=p^ipTq1NmvuOOO5( FVS)WTW 38.K * caʴPm?Zk$u) j/7pw̽Mwtzë*Gh`^ҍk_@Z{q 3*ԤڒRͮ u-#wNgHlW>PU@iXb&^@kIMk^vwap쑝[^H, B"033Ku<\>kT4 Z _BO h+| O Nha_pS4^Cgb LFikI1DFf?yUW+ȭ4 1ɸzi42%V3:"KF#p*.E] L2'TnQv(Lϴ.Ct+&%PHDqp)=˶ SzU? hxgOFRVЙ슜*iuPWgL=eF)6@3]!s s!+ad6߅$+'f]mɷ[t9QbaࣤH1y<'K_0HJ%УlF36n:B# 8Cw [^v6,0W- jDxRMDC3h> taѣZ\Mp\}߄IlpnlbUufI.7UtࣕzCk.q~Fc#>t2^{z_*!*;;ie0~]]Q9a '!a.>Sj7=\ŗu0T= Udn苓&|?8lUP[[̀;õ4@'oRnSQV0V7Fn> stream xa SFSS1000va  RS34rM@vKJ%Au[ы'}}}#ԋ뇰2R`aUxf~dd+kv8rqrypN7?o󊒊ͱǏ{iy\XV+V%.EsuFOYGEGS ? Qendstream endobj 100 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 4483 >> stream xX tUsLC8UlȈ :#`@pP$$$!IwUkUw'݁ Q!EqFgQttm8 ;o{7$'UujQQQ1n…?vY(*8JQV\q-ӛ[6+U_/Pj74nhrm?sS|b4QG,$% Yb&+QN1b1CxK`,/x7 ~_z4u&б˹z3z"@p.55J>nƹyυ^{"z%nH!_#-S7gWN_2H^+#, ;_~nv3'_qԍ[p8nBn#׆~ $#[W<t":Z5IuZy7WgJ4n߮mX9& :{ݳo͝'2=9m[gw Xs_.,*TpAԆUl#sh+#_ߗ zhTk" K|~=_'>Ү)$"^Cе 9\M'COWYаtDhy#oP0N"v@1زˌ|/yg[샻NAt`?gWR@nJ6Eq,F;>$rgwM{k d1\Sƛj:jv mNLFJ1H=tJ c4@@1\o/TڍFO`|$G8` ulU{*QX痩[w3Ȁ'SYO/nlAkm1 K>B"aKl]1l Ýy=H'ٴ.$K9Fբ\]=4*_AdƞjfÀ0S⊣ .,_{dHB~ z*t 6ǀX;\Zȳ^.iAcJ-齿wj߃֐R~IW4#/?rb)ɤu%CZh1h3p\S1Yl5ɏԄrֽwC_xxބ+I|>?/, z>HoɳL[GWDfoR]fhqUr8Vvt=ȅ"R/JZv \/7GqcrP0l:nRA3T+#m ?yUdK ϔNC]gZvk |p)",jŨjZT-je4Af-mO_z9t2TƓ>Lؓ K_y8$t.aD_CήzI#E(R|YT-ްWИyED7?K]$2@RlFg16zV;5a*xg?Z&>G-!eFjSsN{q.xхoW"-T= lx]"^-ZB1_OBc!ݯgD")2jQ4fk\_sg(aƎ$ܱ;gB\<6 rR\N9q!Fa!JџV |>w22Cۼkҷ2OewQ<; 9C޼ ܙ7>[snŔ+Du(A)R>k<#/tC=?) ַ7 k;5p]5^rS8wx^//:˗>8RϪl{.+vO˂_L_~R+`Ȋ# YKN '1A] oru='0Oܨwె슍Z%TQTlO?ͪ751W,nWjwO. u.-pqv LmJN<㣮W1>#uSũw~mWb0K-iFVw`2U@IoVG8%; {'.ɔ%˻i@+ŀ3PF,=jF7$vٰ~HTyXǞ) AZVKf,B$]yvV+No1w&U(1yL}̒eUo `Jb7 y*Ъ9#uMɎ("(6>bp`@*u|ЇA< EUٞ|22gAbrh2 N$|n@Xyɕ MԍG&Nھé+_hkR3tb-6h+zPɃSal琥,À8Aoγw!1D1l+qǙ}R]&f hM^&1kFYFɑf Ԋ /抇 4̅8b\'(V'M0P ҝuu{t[_8@,vF~Ѓ*oVIΧ,%.Id|/_f~fNOoWp`+-7'7zBB+a9v1j|6"bܘ+6!0ɮ.gW-=  :T3"jQCG d߆}ePB@1Srӎ_dNaj_`#ūv>̇%g땖z:1Lte)?&L\ՌGUl3s_vd/uUqxDZtA$mH6IFC7ZMԔC6ol5k u5Z56*caduNVi2A2I&Nm]p[Я"ֈo^騔HZo'ZC7|'$h&AF4 4Mϡd#& *LNsX'K\L0ˡp~ϣq(*6Pkw0[Զx霁[vXn\wdYפoLzxMTd gΏFAGCQLBm˔َ> stream x SFRM0600f   asteriskmath*bvBwadb~}{x~x{m|}{Rr oe{x`_`}wsoqcueefĤ ~x{}~bqdoasz{sw}`_` ? xendstream endobj 102 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 4215 >> stream xW xSe־$z":**e)Z)-6k4I$m'_&m$]5M.,PeDtיg_dđ/:<ߤyҧ;|=!N!bbbm]%i KDod;8#ΘZq=+гs:9<(˗) 3g8M yd}\ AAl"6 6"N$?с2xn@rz#sqѪ Zg+zʫitT+|. WPW쪲"HzH<;!Brulk߾U[ZjF^ZrU;p:s#)JvF%P̘0S_U] i n_cPP&/: ?]bzmj&,ߔ9sF>X} %(RK;39k2ڣc=0hqHJ`),!TE6qM{axvtWX˫m/&ǫ8!Kj}Cݠ+`Ű^y.k넑C"9@Py # 6${: x+/0*,@V $Lw9=+C,nY]G+y׏,_tdSP:8}7:pDw IB0ss)_OQc/ MJr2i, U_/*\JXI:1`kIGhB1> ކvA[bE=K^ i6AGvBөSMr\۴u_rS(hSSm7}}M}# /AMU&yJ6`kΤhI+آi5]¯ c$Cgj4w^SA\f&O+SW^U؋I^{\ax)Φ .#̜IrKPFz7)}4h^~ t]87 #lvU;g魜ηjcl}هO94BB˘07l¢ <9_[cqcFEub5o343,@c>zhk=J« 5.H S%=+7h|ʥ+,WC{7p*U.]Eiq\:/Vcp|C P@MYpi4GN X,eN{kOÏw` 9/p)6FZ*2M7_Nйc袟n?mn]וֹ?^b^ɬbS:\mKqKI2`4UD7樇f"v!q<IIm}wc9]e]u{!>sϔU8]ع 7.+,)IC)7o1TNEϢd^3=>Y<54wMM&¡qsz>DyyZ>P۴PGff45TΏ>en DnU@'!GmUt]hT&e_X.].3iLEchV4&<*$kk4}z5klbtpgoX,̑=ijDcL[x^?iCtnHVRޱ|+ŴZc!. v?MGvzF}nWfAۗn)aYyv^g;\x&WȳWULrT-A%XM20[fS*7KdI;)W&K3C4#κ.5|bv*N Hp~ex{SQfhͥ򸎳7ODw7jw]hgh;Q9nF^q*+UzU0!yȗf\np@= zjIeIE3 b2!/&ЗwR0ŧv,y0aQdPW$7Ŗb^E<ȣns(=P:i0cPzMw ~jp7ͭFsٺa(Zh?zنqަ Oh͠ !2a]\T&@"w3H`TǶ섛Jq&+*9V# MQx*Őư*YRSʺ0x "5Od*̅ydNB~M6Qb Vd_\=sgO9AJ'u>CVόw S&znF&Fb]t?$?uőߝ"+x .Z 5{rjWgL#2Gendstream endobj 103 0 obj << /Filter /FlateDecode /Length 2292 >> stream xXKs8>*Ua"rs'Nʤf=l1Çq~v7H j媄Ƴ_̒_U'NU5{^f'9,QϖkY|}<} v:WI" w-D_S^Uy[x?8rյ{L5ϱzXX6i]9D#$JJ#?G/'q;IUћ D `gN)}&8uy+iޞ^mk9evvSp3G4jl1,e s/<,c8^i̭I8 YU45u LkiѡP3p]YoCg(} o5]pcpݮ!Y ro?U b 0\|l1ڰ߾\,U1DKd{ֻE:͢m%%nJI"#56<;Q9d(K1Ymy];n&Fj`2K tWS{mMѷ08P\S22cZ7naiMY[ao2^uJ3,6=NvhQ`pL yoTהYX=8_Eث'=zI,X?N)&/f MI#6&.Ϩ_~)?^wJ&C~w7jCM*|Wm6KmfU$߸R3 djS" @ `4"of-trjO/nuqr ;YZ/Ic96if~"=mR MXI!| eATSD?JhJЋZ3O1RW> stream x5yTSW_wUDرT+3v{ݰc ȢKHX^K H!x%9ТjuΨhTku:ӱ 㼴wy}ߟb$ɔ k>Zd&|W Uٵd<όY9$&G0 C&`v1kH& a3Mff93Sp^*uKLz{#;:9'=YJR{z1 gIqV,)6tq،bWC(nwŏQ\DyJ:6ʯp0b=W .pf$NCR9[~@_ە}2dU:of) G-j :VS^RZJM].̀ȃo\/|zM2z5 cw)lڲ U>j|m)JpMaV\D"{+Q<#ph6)_KHdZ9ӏōk 7.>7CR&[""c l N&49!=q @ =56{ Xz2{K%&C4Y35nIQ5Uiϙ Gk*JsYpڼ`E&iᝤeeStC^{VNm%&st]VZre Nr(gJ ˜9،=KN9H~D.æ1J}UֳtF?y>8ti@wN7薿6r>ciJąpc\=T؊:w 9<Ȧ*=)):YuVbᚫ@ efJKKy>Nѐb_:M N>c-PYsΣ{mh?M?@tpr\ʼnD3/o$Al@U4+-Mu{tC~n:\d"l3TW5\Wq VT٪U_RFʸ##6Lz[!cCZ]0WKZHBxİb]HwQcpq8-g9: 9yǕn64e47 2 ӋJߕO\qO#t , WsT튈c!B)Mj*yrP69-r1ISћҞ|0H0 " pdx-%gp }ЩļHR-MI(@\v)5)~N|W`@@fTyճ]A_/&ߓ)#3'\pwi!`sྩ5++SLY;aEq6Nendstream endobj 105 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1984 >> stream xu{PSgOs ZO+uGb,VDPA E. HHyCH܅PQ٭mqݮ֢ujq=Q잙s~{>^@ )Yh…myڞ͚H[eS3ێHbuQyա'bgC)sܥ^A+ y2`>ptݍ QetsZGe@"ZUZxZ44J*JJF+ F h=`U6ǝHԋ7[9.t V`S`Wfh eP̪ Fi n{ZW:Ww2U=ͅr(T3+V|4'D$c_ߨC+ɥbJN؎A30dYBcwϴg5NyTWgR|CFgpbVl! ZYјv0ij ťd^Şf),3)+ਲY YvL:{U5b>BXθ{O:/UkV{ZA@}ERmuinM3$n WG&엀"6L~M~ícݗ Z-*RuQ]#ufV[]תI_#pk[{|Esn C ~>Kѿ8ƺ W5%&e.7L!h+|\t?ްm0z(*l{ IfG>G:yBwc-k,HInY|lAEd4 #fhy,:LP|!o#G^;:]<kDg/ ⏮@E/š|r$ g̠3(m,,cr-́e`¹e-b{ EUAMjŶK077a}Ghǚ5@/n:u΄,C2M|8@Y]~ı8ʀ'U*W-6tTg }NȧL)Y)ӓ;SOfi8N/ñ1tIgZ[No$O.%v ˵ԕ}UM'3&s l5Iᴎ<4*HKM(Vj ӡכ,rs0H)Fr*P}}t\Ve3'fQP7j-l)YJ4U<=)w;y聸E7 `<5*j3wEhݥU˖LUfiLZi.eOaWJOӒ5KjƣMϴ%IeJ 8'}쯏'&c ajQ =<=vsHp~ M[j}}}Μ v ;> stream xWyTՙMí۬+մy/*#DC 6kK+Dn譪kj߫^U7 Ѐ( aZPaQQ4f0scEs21sΜ3uϩs}QQeee떭yTyU[+&h=ӾUw}0m{gFkےKWعnOˏ}ZCj:zzZL9 ZF-j|j*hHMI:VvWY׸'u?Tx˄&X1soL>䧦,rrꬩ6&5uSĿ)aMJa=,b]}Xj`EA)i%/NX:R7㙔1`6@h 0'5}7oV8#R%Z:J3t1x>ȧ.b6/r>.'پ>_o<G[Zh"~Xe{SZ)ET9xXOBXO4K~Ⱥ`g#靡/~}E9ƞm*BEKw /<ˢ3_x?o@Ƴ?yQΌ!(G#tʟYqs{&)n߇͇ܟkbZrlV\ɔ;Uz2VV >h֬qݴOp`GM-[;÷/J|W~Qq+W2o2̮Cυ]u!::N䠅L~y_w8ҡW_ErJT!&jżXΏ_32l .)-ܳᚪw#̩?.v&d!Yqw_xR؎J@_b\lX28 n4 igrugVjVک@@IXݲ;:b3${+Vm'g ' 0RI;-nUH{T CR]1Gcirrڎ:+'&riUʘkGy҄446oް/"0)HmV@-I4q]9 ZSmc~'h !9{0ȩ*7޹+r47/ceSn#;2Ln#[E7_=s<5dZNǴG{ nؗa(I_jvoE_O2>iN!?y"sҶ=kl[8ڇ݃QP 0 ъ}^ڐcEU2N)K[3 d+F>cJۭv֤1=X8DBHwylbq[D䲴%DŽYk@wURʩ#JZXoNP*RYڜ~rq#EVSu #shh޵t f:Tq}r'X%Ȧ\NU0Ճ^*/-,M~siFbg?m?;[`#o!_~qL]! dTsʠŰS)e6KXs_n\\;3*iQm$t*U Rh.(=$EFvwUhCx}hCpاd%(2#W Fے'(*.2Ba@#;7K7unmҷk;m[N_56;^Z\B0~;ug`PHxYrv~~˾-I6~4 ⽿Ґ3y4rI[ :Bڗ%X Jf&}Iof ]9mPc@IQ}>~:5/W7 (voBfr[տw?Dx'sIdU?/s (WNPvT!G ='Ⓚpe_?&=V%^Uċ^?so:**K[.?!Zز=Xr}0}"C~Jb({Ml:%((YΌ-Ÿ}NȹG s" Xr#;- &up9]Đ"f?~J4|tUՌ%,:`8TH2M~h)?qBhSC tpBӍ 2f#Eڍļ7cSg#ʋۿ}iG>M({Xw{¤BAnFX,@wkŞ70 LN 7Ba Ҹ EB@@ɻ{ 9 -tcQ+mj^%~ _A*=^"( ]޹ bk;;}.GօҼaKG,4(P*cp%;b<Bk t0lV"e3x&s`MNɡUIΑg ~¹AoD|1.oȦq*KnPXPK|ƛߵkUmXPr2+ [E1W6KNJh;-ꈞc&ݒ,QiR$OZB<1cшj.ϒPZч#cr:YVU8AtHl.IըaSC~ 8a ; xB-Yb*P'jlm[{P#jӶ+*,([D Gc}cv_ӱ33ސ7 "*(2?5}%![$Ȉ$H7=""/%q;qcgo"sH]"ӢG:H\o!@.' -NDJ٫j <\Ҙݣgʑk ު5ZWoصkΜ ߃<|QLǒɴ.h3O{'sƕJch%aJS;]*0x'o]s Hqsru<4 > stream xywt/(Zq\b A ~3&%\k;n-%3T(R$mPf.0(hXڒ쵤(nb{>w;{Du,UIIɵ.\CWTtțje6\_ _#v[v~z&ٖ^-Կk˒ƚW-^YrǫŃ*J]WUTTUkTWS=z@^  U/~ZZzHbգUpՍKT.)*zk.ή};V։?YxݵnqOﻩ5s:կ^[vjoZ|}Ig\U2H݅o??ܢ(&%_˭uPçcpfHuw *X&ꉽpM~ z]\=w7z[}gҭVZQf9quVjFY)#d3,d u0 3 C!&Txn `Y0MD jC"Dž!SHˤrGc>Q9sr%3R98*<lk/vNxHo Zqw48܍-non #|_'NH=|y9P^-lze6굖wwrW.~oܽjmčߗ?]uQ],L#/]] z/Dn}'rsu+]'Ѳ0, ޗL b3j| JpK\)t^8X sផ >2 ߌ7+!=)i?K!"+yRhtw}5߱魯H%!{`Ld4)"c` KZ6c8[i[e{W8 (sߢ/m8 `,Uҵ.7tQZxw1~pjO Y"28x`0Xjɇ-~RNݘ,a=tzJigSG^'<m=2#<%؜p"|;Q ,u.B=2uzB!L?c28ڽzR.ɱo{ʝ#^Ր,0u'3\EH.2w˱n4݄~nզD k_e03CH8VI(9ttA7b< l rLТ`l[Gs1sˋj^K7qSԜ Yk\оq4{][ 0dM&/M0hywN0xY(ki.ĜIf8pZ2kSo".b=%]g/NJkK{K'߿Oq=Ѓe=њƞ8;~v9ܠ&-1{z(58pfO/XJK.?Ͻm=MP;gg5>_01:f*Kzج{4[ǹHdx_ [vۼbr64Bw(Ly붯Z\R; }Ϗ!.W}xIBIAnE+Wh#T7NLHOywpXTJ.ڂDZ[KmqP['@poơS<(2':w<xPRBF w2QEȥ8wi+guC47 ^ u×`6Jʂn_)-xXMiȞI|i(Ad斈C;|fWqqz`rg } Bl''QKS"VUj%uFt`72OVKBꗷ.%7}hw!~ir{a:+<>7PG>,7MTD7^5[U(w`.aK 73Hֹ FIu6: z|/'aX0-xC^uuЄ& 'g^ R樏Isф983kZҩ-ѩwGIpB+Nэp| ꦧB}o3 uvū6~)SsŒX1 N:`FgUE=礝P 5Ij?ו#?+=xV |İ$ ^_&OI|=ةL GuhܭTFi` cx,;2*vXڨM:6I ڞP,]^|e= !^! Y\nݾ[e!$zIB&0vM3Ӱpb|`<$_"ΗJ߾Imζ "~atbg΁AϿ%ǀ&&D clv|!؁"u}͝ *Ƃ[a[(¸uۺ7ZvG&N%?>9,i_̩GV9xs2 ^ߐ޾H'!Oiy1HݛBzZw}FtlU٫0vEfnFxDqczl~2l#LG2}L 6^^ks̸0Y\e}BU8>>%YH(6P]tCɥՀ?hLHcts&4(G>Gy#W A\ |o˜ӜYeJޜ+ҕAMUMJ0q.o|F,Tz+a MuZSlCGŠZB`+]jQ|xyXU͕k_g|',&J1 ҭř(ʗDu{<4f Lۙt㮐7F$#5Z7/ܮuotHQVRFݮ7ғNIe#9NLwTh̿Z5B3˄i3yA EVebQ&Vxr6< GGϤ"=V%zw>"9LLP\R9bltbjg|/^"f=X-kAA]W_;3e[↑ՂQFr hJo,9q ;ʸ++ԛ=^[!߈oGQGNZs҂<\vAݢ,}3nS3IbIUT8(qʚ_uȹK~-%:P_y_|\Q.WL57),B*y86w(H< w`Kums< 1UtF\6Cx36[ڷL&-i?%%<-_ƒIzi#D\H&,cCAqptG^:pS7"& .|& ҅\RFz JA|'x\~ɉaiɥvMW>H[F0ʽ/ yہP\O0 43qe~FH6|LjìMRRϥ)- BᏽZTvr[:jʲve\W5%: ;͊tN1t/ kVЁdkz0QRbgQa*7wdhePMW&V R0y=aCq6u]ӷR|P pAUO 9MbBb⸖HYb'/;X_R_OTf3C JQ*U#jxڲn&O ~NL$Ng4n0V7L PdkNvqv44&,T">={;a\E|(5h:]\?kMvOiԢmaCC%=QʯĄC[S+Hoa%&jpe>T.@c܄1$@i68Ve'5Mt]\&l]fݱv2NS޳FiSȦ ݭDvA>EqA"EʵZLqPةwrL) BpG9'3)zXt)Qc~ G_/#e0gq \7PsvDԁy|ç7B2l`xoZ)k|F#73c,+žv@)څ[&BXOW(nQꤖ*EōqWrDtOPpPxw^HC/LhWl=L>nOo96ac=Tv Trϛ82Pz 7Ua걠 bmB)byAR6Y.ΞRX,5G(C2>6@4A?#TTQÕ]%_Q*M^YYMz#DbLFgm~T m>!sكq> 4D2 KANYg|=ߛ>CJۃ8>H$>q˄hޣZ(~؇39 G_|LkbJVkf>W0J#\pX/-r6'Oxw9w/7l6C. m+4O0y1f E/6:ai_V-E Az^'s"sߏ*0I{__36hnєudzzhL1TyK>16܍&;&tR4_6/ ci}-Јrhady1W6OlF4תTendstream endobj 108 0 obj << /Type /XRef /Length 111 /Filter /FlateDecode /DecodeParms << /Columns 5 /Predictor 12 >> /W [ 1 3 1 ] /Info 3 0 R /Root 2 0 R /Size 109 /ID [<97b6f6b49c35b524c211d0ba9335398a>] >> stream xcb&F~0 $8J ?`Z m(yHG0m"b@$Gd )Dr@'d< "4HK`5v`s`[VIFI] endstream endobj startxref 71133 %%EOF Matrix/inst/doc/Design-issues.pdf0000644000175100001440000022777014576344041016522 0ustar hornikusers%PDF-1.5 % 1 0 obj << /Type /ObjStm /Length 4081 /Filter /FlateDecode /N 67 /First 546 >> stream x[Ys8~_VDR;N8Jm)mq"KNy߾H%QN nt 'XL$EI&J1M ?IBF*ԅK ?X]h?0(xk¹L4 J 08 ɴ$\)%|K"c@c"Dcb)s!DތhsNbCQ I L %F`Bc4   L4Nh,`MT%PD_`(p%%yZ@ћCW\~>zBaĭ3:B58])#~KH]~054a@HHS\%ӯp nv'ksAؠma,o[h_SCS`n=OI"|"O8:(J(D6E.ZDyTDWS M6%nE[h(~r4Cs^ oIvf7i;KjrA՞{ǜ%3j|."%\{΍ 06\ \Dz~TW1`4҆Ie]jNں+FkW92 Ӯ/~%8r{ЋA/f D4:Σ v @r\Be4.\ja+!N6ͧ 6']Ut p$;&pKn?n0/|]\l\ i xO*&YTsHEܲ5h?+ha}Bq[5Ig_"1d˖lp&t6ׁ 7c vk˫'/,1bf#zsڠ)%@('=a~Azz Z.WISU& 5, oQ}7I:q܆ZuP1䙖t)⃳0%MzcMw3hDDA[(< (H[sm]Xi :džs ߁Mi?ksETi}cVb 2i[@*YV%Tbr3T qمf*[0Q}_'Bn5w)|nѐ2TqӉH$on}7iDA/jo7.J/LmnY+[o7+<4Ԗu]6}Nϫ߿E:<凫a֡ߢ+LBʛ0 pv_ȥ=ۋǗho!B9v}۸p]Gd&=1nj`@!zPZm`_@ε}0/.^[)觧ȷ .(\ ]h6z+q&BhJ. ǼrRRj0S R[#¦R卬"M؈waf 1iXgl9!.yљTiS}:)B[JDdx\d=" vj!x[MYd}NLCUi_Voؗa< Ck+Wj?dBKJI oo`bTlŶv˽Ë}BwĀD3-~ LfhhZk.ÙgМMn{YE}7NzhȦ8cl;~a8]"v@W]]mpZ]R!z?޻;rzzR^>#<ԍ[cM]k2+<"$9 K0+o[$y c`ndrJs'o \= I -b6a|_+Mlw:xv?\X7lw š[$a6ѭkY+C$K9h:𠛁Ƹh,vZo֢lM&!j?8#T}uuֶ`r+i!6NM[Sd3K+mj)^҃\€ 懎nu3y-" v ?Gp"`Zx{8ᎃ#wҟ"//ia]vnBۏϧb}?\U.Bfy-fمIsY/2jNJ[Ԏ; !`74wstNwge3f=fb0M⏼a1h򫽍;_qM'>^P|u `Qp9l D,~Oٗj^xtۉ,-x+v0_l?cA, Ki O.-,=qf]!욇=hm&lk,> 6=/ۂe[Tl ~(]DKLۻn_3zY;b=ym:ڕcpG* W> stream GPL Ghostscript 10.02.1 2024-03-19T18:15:13+01:00 2024-03-19T18:15:13+01:00 LaTeX with hyperref endstream endobj 70 0 obj << /Filter /FlateDecode /Length 2965 >> stream xYKIs0%b1O˒]I*NUAJ`.v $h+yuo=3 R[*aᯋUJr"-~#BV,nF&؅СZފUYF*--C鍸Ckk~R*B".QNVi}?ӝtoy4MYcX/,*Y16$N4xO;4[>̔V;hx%+%=&IR ,RZEs02J*,nnaВZ{/6 .msIt4p4|=u Z|[03t-VP8x&Jdhԯ0IYؠ;ޑUQ:kʋ/qVT9RpLK6TLic kLP΋t~>yM*D1b:5?ܸ1iC$(,+^,o~~KVi?}R3gvfژ{5mfCݴ 2$wf.Yb%U(f YZPJ)űD}+p5#i| Jx'rAtI>@Rc Q&Xjl-Y$K Ln6-<A5}3L0% fˬG0&n`#ֳ/1&xd䝧JoP?Jplfp`Dwww4Yb-v51u57ә+{{hw{frk\[d}l6o}Xa $cjJ2=}8wշiON/!yG.5gEmA^=䨷6Y2fjVoW7z 9r BPm$gCf٥LU7EW^3 B*rkseDL` dh9H i#N'gƥrj+5 ,#,M^=j,:=dÜx h 83IȈz΀'b=- NcFJU,; ̇/!#G=u w N}sT!F˕$cp+TEqv+ލGv6>C 06.GR^QGʒH VQY%hBT@+A1̝cHlCVB$ t^<*$[f B<@BIU61 ? Ci)zKC͡$UZlT{&mL6ԉV2@M sΔF~ ]m+"ݱ-aI TCu?C 4 `)Q7ᾱA~s 84PؓMubsjKVU;bPPz[ {5=GҠ>}U5ɃzEM}2KAe9Zow(<ɽ|4}⟣ 7<.aF$aDi}X-f/uo=Rht* Tg>A*&IK6hN} A[ʒ W:&OD01,+ndQ_LuF[*v߷inB I9!pY4urrBRݰ.f:̙:>Epr]s$/#,P1X3^ESBOiԞEwJ;\Ɏæ*Q͜zʋ2r|"߁*kiVj)qbf=<ǣV;C̏`@D7OSГD v? e6Ki%7{?\NZYRL- 2yD/cACRᤕќNvX!rg'fO?4;2Qd1rO|Fu* L=2".(T1KLvnzM}]m&(vRlaN~$d#G4/d^U/1*_/FV*a0ݧrܞV Sɠ b 0@/ O /„ǫX}))^mǵIb&mĹ7B?Q x_iRL~"M}fBfӧgOܝ 4uV)LlXQ_u L|%C|zA[y_ g2nJ/xء 祧F̈%N:|N-L{<6yWho~LW&s4]q$,$ [U|tmhǚcv1oSťVүv04{e"a.nes^BzUh}/2#!=m)ED`RYOр !7,ka6o=92|1;}RѬh}m4ۦ 檬` xeaGMx?w/T<#LjJziK>O<iaV|l]J̈͟ fu+4OHFnve9puAjcҩ}')tw=h~oUy?RUǪ\? E{Pѣ (in Uendstream endobj 71 0 obj << /Filter /FlateDecode /Length 1544 >> stream xWIoF7 2L gEAhD9$or$(ty۾2d/l 寫ū.5֒a$Ȓ0sR2\k۾躛$%"8#nj3:y#\aѾ$c*wE[9݂2IFz󥯚-( k!yz2`aj=mW^ITpf[U9;1II}[i_GDp^9ċN68IKqD)`<~ F^L12f,c_Up.wYB-] c2B0*mf8Bs$*sT8:<<ԝL#V;i(p:zès0;w<4(tl݀#Сj9cS7dG8u'! Z%t8I%ψBok׌6Y9Cy hW؇ DHьj߼J%H 5*<\ZO8\}%uJTA z+P 3j pӾ.aBYQABVdۧdywDE;8rץ8H4kqhL >< Ϙ įsa"ke\T/4)#}{*{K*+ E}4Pz6h$(ЌϻKY1, (AE u0~ S0)-ɠ+p3\Y^yF֚_ L2Z={$U՟f4WZfx8xOU"LI Y%'P9R!ڡŜ1ői&Gں*݇K*lhthx~k# Fq0 DDn&1Y2Ƀ/2zjJLy7 \_<&wD ZJ!=^,%|Ԛq8j9@}]BbL̿wK"dej/GCx61ΐ ڏٷ=ԻT:1>_JCS͆N84QI@ sP맢xv(YPܹ;RJ}$6(1C7ܵNnIj." E;H+h;Sф J"츀qx7?@d$4&4CXZ!>4Sͣ5k# l7ٍ* o+uXj$̚47DQ_޹>fn1 >&,yv1,7,]7[5=:ZvPn`n`q tg\.0< -5grI9k+^6 Ny&qg<ľL S}OA$arBΙqj:= endstream endobj 72 0 obj << /Filter /FlateDecode /Length 2504 >> stream xYKo0{i,nvL6.C8$zEil|>d:6>lvwۢ]ۋ.]ğnş?((X}+K[F\HX.X~mݞ8p0,P$4]]K/3]@~ɪ. ')[xZ}.,x:FC|[w"Z75o{a40tiC\kFcjvGIy RRAqz{Dm @ ?*`@oJR+齄c,k (K^)d 楛lHi^7\cjIyrj4 =2SNv5՟>/uǐ'x 7]WrVܫ"h,wWΛ "OA~ꭔIN]JXwמ\֦:Uu7!}םA@qCFZ#8<BZȴEqx"?~i P6RErV2QyOA:eCb 8eLEǖ9OϷ\5%2a(V}H/TQBYVwq9v2#4ҥn:$Ҩ.*s7{.@[1iQT,8k-\.C:rlYWUVF?6ڗjt,@;"g[u[:۷ xʺլx뤩e:Pn 1GG;W)aM; $6o<&e#BFT!#Unm)X#E!:T6{/1hOwivґ8 $F-}.^W]CsIQ"h nsYN g)%y*Htb _OOkᴭMΉvCL'DjL j7PvKgѱ{jjA !yQPK܌3+p "=\@za&8}ըݼ7xUt4=ΧM<\̕ -+}@.(LR 9|2y*0sp"G$3 }(s'`~~Ev,$c}0݈TF "sIIJIJN$oLo 2SwB'cט<`yKZHI!$L GvċL`S8T;\1Ϲ >8 dW$Ht#Lz >V㞰>ζ!p!r΢eW9 w9wDPQmՈ<=W fS'U > yFz;Bn=ןa=X3޴ezzM g!'?U^()\KΡFуґ5N]{ΞNTƖNM~ⵦRr)ZNotnvTO.e#Y=Rs>aTY:ۆ}󑾫K|t7oȓom6pO ${;(HЌGt-{Y=^cCnh́o^*q?kZğպ3UhN}g1> n(7ɇ8PoxW8ޟ g T[ʹAJ?RR?yh3f,jD.C1'}WZ F`7>xw;^"8r8RY gL ?.^endstream endobj 73 0 obj << /Filter /FlateDecode /Length 2075 >> stream xXr8}W2T A U*Q#;Y~nMh8HK/Ϟ vlwGxse`2 ^N 1WGj7z8)}H,-v'`o_x=@qD~l> ^{~HC^L^yAD$Zz?wr|qĸKfB!{E Cj4aUZ;Z3 _ǥ)UD&ɓ2;cj)H*qD2&eW Ğ(%Py~pAQoPP'U{&9Ec"s+Z(t2S% 8W5}yƘ0 |SH$#@WJo,.ÈDaHF~A痾,BaJ;2LR,da`X!jN@`Mq ''hB{B!J<~gGM=Q@(AeBꤢQC`U^{inXƁoٽ#R&eQak`1Se풺I8qDj9;˂<!|!D9B9 =N7, "„&b.,@Ӽ=&D#(qt!mO@I`Օ3F }dQapT&uSid/qP颁]^[ e:Fuj`Աzo)Bڧ8Ӥ4pH/ؤ{a! BoR]CHm-ta" *A~6S,  j z3|i2j* ,Ty]eS֖N+W:Si=G As::]ZDGm}.6`H ur>*Ѝխ;w8qQ`*éۚd4~h Kм%: 6_@jK`X ̳$‡R)1`Vxø!a"@ :#GEkN&X)]@b {8GmDoV`ď˝ₘ9ErGfݜ $>YߵdG0WMuC+~ ܨDP)j~@wR|߯,͛;7߾wMC4gBEJ B(Ң3fN\N߮O?ߌrVsZ^W_j ]`L^|6?]_s, ="g@.hOq6,wNjb2s 6<ӫ?Wm=]RbY|R"X樕]N. 4Ebr> :ד5%!9@n:^q1Mx ԱNb7Oϧ hC0#9p}8;,>^8/K:t;k"un_a,; =n6eOƿ6C@B*т$c~] T~\ X~:mf5ܡ|ٶ6or3Za0};!Ye7}D23{1lDmZDtrM ]NѾ,Yjݬj}nO!&qՃu=&Wo@ 7]YRm@?0CO CMW*~l3b>\zR1h \ʂwk޸Jmog5 C] MQSy. PQ@GlvAa$G^pq ^B=^{˾Cڔ~*' 3͠RdySYF#lݫpys8ߧ  Kph^>d#pk]R#I?.ݫ+BE7Z`m^z{hU> stream xVyp^Yޚ8$PKI IJ2 HH PS>eK$:}ۇ.l G@H 1i:$LR.IF4eܘ+/-J=̅lɝCwf,>J͛y6]~X3GZ𦼱IZY޼#ZRS[azl4VbE&Yl3VVak\,[1a7xisҔGҟIf<,Ђ[O3-~ 즙B)c?\.@۴dRHP>r0 [ߝo XԷԺF H ~<.W p6}{˧2IKG,/bo= O]d3\ПQJ >NsY(~𣎿~7 C<̿nP U%uUp ,j[0"&yK MCn  xUC0o44$zmO(U勣d 7\XUd[QfNO;N؉>ycl+R6b qf;0*|RI0qP?ff-]V.* ^U%T2­=T\Th)z=-a_FZqaBL " FfӶ>f3Z?/P}~dj "PO+ mpMu n ; J)GI4 OmQM>[f[:5ݭ@ Խ*\ucnB >GaeBD'Z >#E1r+l6|{ϙG{|z[6`! _b#Gdb^Gt8*qv&wQZgTq3eb`wZ=h<>~\d ݚ#"yW+B%PGim__ZZ 5x tO(3|82+Gx>FCb Z} jz@=#7ᙱ)y1`F?H {2f`oXAk/,4}8ڗKa\<м )1`8Ȝ)[8WKuLLP[>#ܺA?>2&ww_TNɂ$\y-{_ CWF'Ba@4Vi,-VYvtd79vnjvohsVXbߩ'CeSs9E߉BG&&!~qW`!dy-Kjk#Tf]4"gqZ@ooO ۨg`{?JUH8O 95( l\F9`G5aFQvհ7ٞ҆[%eB`/L8fx"uBSݩ6D RhJYMR.5 .C `r6tf~߮kY f=Ž:c-PMk}6C!sbaɄc>=t@<~П@B6aynDbAeLl9Bmz9n촍C\kQ)#ڞHhʫOG/s\t]mz59ҊJsͨ3xƠ9(qiI'm9?I:3U9Yŀ?HH:y,\_SA6~툱# ou?}-8uu_+Z+ VG= U]Ɩ}M~f ?/IҟDFJe3Y˹Se%iKvq8\v`%e%b(5p"|/Ro@|j%;1ۻzwۨPDeY$ b*+[hή7p҃d1_P,Eۃ.rH5h积% d}$ b=z(ofA#n0Z4u$RN8Z:6Un7~YVPiLA Q%;$3!L}}muykH 9%b=~x)@j)+^fNND2tIvǙс&`$ېTa VDzpN;TܟE8 p?BWH 8wJc+wj. m#p0 ;T@s߮>IkjAXu܆WP ]'jWMwxpnc}Gqlb+vAW755ʔxR~6NV](A"w G~gmHTL}\d}>Auck`>#3 *+Fa>\W)=9CU_2t,~DzL 2}'9endstream endobj 75 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 3916 >> stream xWyTS׺?1UD%7O,SڪSmkꄭD"*S0$d<_$! % "RZ^U*V׵C7owZw]/s|ox8+lE x1)?>XgL=_SS(Ւ5kSB32{c6=x(,.|kbҒe}i"zL=KmޣfQV*FmP![(TWX}u)}@YYlV\rOgʡP至+xae<1o R Kg)lJx+m EnkY&{#}'.+ pӄ=8&zZ< BD"|{Njg D=Z "SE ᰭT 9 IL Qica DVtC_ el).sw=Þ_E[:V",`*x;a0 Ɩ(r 9ZqsX k:m܁gs{BLk5(YUʌfEgQi ZqnB(?pNK./q0ɋjIAmP &y^d SMG~a@I'<<d)1K4$jf}\mu'?b2kUsf Y#6s3oyDNV@%lЭO`UEOR'v-Lt:ڠpf·gW RV{FE"=C1IEI5LVb3XxT4PP+RpϬmbX `  ype_nnEt!f0lnۊp èXZV!e:˝ΎCqk 9y[ڃk' +x!@k$(+~2m O6'틡ޢ3)*CӚbUo.hޗqNob"D-|~=7Ҡ* [ JuVu~n.o8&Mwx,狙.M]YYv(p$8wvB׋BTa*;î]dgr!Tٶm@BR-d`PPeUg2;¤=ދ7]ӄ};O8O:{L=$.yNy8[*A G⺂C1t=3hT e2瘡`2olXBR[__USאU.1D(z?cF/~m|}ۃD:t22jr\uo/l@&J| "NtȐ)J>5i YvĆ >'޹݈ا7;UdpyT~?/7lSwE\b [%g92w<!M&Y+NLexg_^no 4Zbal IJ۸ʝ@': XO}l\d1E}zuX1ԗkUU W itWlp4~'_M2Gg]1msͥQUpIeqj|6|w+הbz{s+Qᨠl*y2Fxһ諃LA(WO0M`BfYSIWvG%D@,զ7|Ftw.䉕Z1pׅ elm "VSIԪ%]iQgj TOABy;]C$Z~'7o u3&Pe-Us[&wQ mnQg>@[]g*]0曬RRB!; +Kb3UA؝~4Od6omq+ . >ԔD*zedy_SA`s-_%o`̹ btK#FR9a-9\rPt { "P"%srAp4q ?/;Q?`gx{Oe!$h' [J^3Q(UȋS :1#.jX{役%ٶlZoGIl3"O?p5XZ(.}:-ݹ\&U h.@V :o3RΣ%img"E)ڼL"ie5\"mJ t.qH sO`~C~wO͒[I[qܵﯭ')..Цr9d⤴5ΜΥuA/#>o~Z2SUi^ʽ!j́dx<[r19h֬1j)X5)ƠU4_\44kOY&&.ÝL'xfw@}%8I˽Y{t`a9qBjsEpk_2! #/s [(foLp $#̈!s4OF3ǢwsPPrfo8֓} weqatHº-ב88 q(hM{q7wZ[9GrrlM\rӫ#D$,% xM$V]7/ΐ=d \Xȥ/'j[]>CIb^fVӰZ> stream xVyp_Yx!x!ݒv4I8℔+)4A%ْ:,KlYec; 8!v CI@<$h)fv Ly;}[1!DYk̚=s؍ԅ5`ߙpN:$z=c#|Lؼexe3~MZ($^"/KerJb*1LZEIE-5/'L8\N^Q%kNVyV?Jbҽ2HRPU_G`|`?C0$~ 8eI uy\rr g-asxo N b73 IN_BK_{ngIpF3,I&h"TBv<|D}yo,ovȍKl/-Z.!ba%\g{FN]lv}<3>UB"?Zbp @eu<3Y18*!KG$hB!fJkH6!%KV&E$a--ƭJi>X<2PK%vʿ-CU9é)tzXac7#(%7ؼ#xap>-Mnynol`G%-fcSڸͻ l/yRp^}{15^پ 75}lq5얖TZ66 Z*h6{>!Y.dMDshzzd&)755~MC>}LRrQU[4*oPh$l -QOs5wx}zl{.>D Bz$掻&j ~< '#vWCUZcIsH#cՔP@I*e|\zXOEyh4Q ],ZHr)IJߚ^߾4r)xDauFR(kιyn? Sea{c<3ԏy#պdz/ .Jdr bL'WSԢi"!6{ 607q,FS?L%OgP1OWk83Õo?U] ?:<oF(L3ΧDQf:KIvK\Ӿ7[C[ iQ)m3tܪkcZA^t~kmUh→M:ֻVkL"``3D޶ϟgX%ZYa+K{+ܰhk=z=i Jv"#Oގx{@}Yl(¹992X\ja\+#?ʵ{ZH}f "ZsPQ-n>UlcuoFTF09{  Ky I42b{Y%Jǔx;ꄌ:.AqV +*'S2UEY4JF5ad19Rrc}Gr\wN[K?#i*@;cMe"N܎ϓvhmB6XԚ% ƘVm hu: v1@ !-jU5~Mp5`{{ThpNxh})0zԴR…55 736bb֜#=]g: @_-o4k591a$UnL #7?H@-(_l,&,?MԥZߠ|JW8k)^C ఙ/qu.$|J@%(S(SRʡ w&Z[T% pIL8hbAA1ջendstream endobj 77 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2535 >> stream xuVmPSW1{t]̀bo:]]pJj+E +(@ IH!I S>  oknR-jwik[[;'a{Y3gq\4SDoX1 O6t!Lr͙v/ f|̯'@vHJrdC(3t{9^"Yr.e4(d)%?3EyNϡS_x>]vTY|Avg*Hx/B$dt^驭9rG7^0g5Kx[<%?C^Bۓv{/!ܤ9< Y"Xun0 zhZ:)+b=98}&!ucx h"_.*i;>|fۋ!u\͂,>xD 5"4Y}LZjMz@lDBfЅBOvt,6Zm ;xXJb/5I;}nR _V^,4:*j$8*(TB!s諴]r<.LbXU=82SWpI3w~$ENu.׻?d0!Չ4mCɺ['/؅M'kq,=߾l`+\=zw@xQl. Ft|iDJz),,ZLN?}tyu7WkC׍s \4T۪aD}cв<)P\_Pb yEIMҮ0uvGwu6ER| l a/L] hf1 矝4VJRZ^ޖPNzwe4"&Cє#;wEvnv] ;?vaXUseSSm簳 'M-j@7FcYz5􊥜s 9h{}4%"vOv n<| :PCvˡަ#hlgAEQx&܁O\*DUENCYE_GƢ|gw)5wVK/CFqO¿ e>y<6/%aV37{ay|? OLUH@ ^!Vq^Lo, "@kՆe8$L?BיʵI$J%22L!0q`D'b`2>%8rU?CG)HAle"=ϕ]ꮫvԥhfuy|wm.</T㩫%5\ nȝul&ŘkYoUd!b0ڌ<2m^!P: s6x(r?4"sL_(s1lȍ۾|g[ SE]{Ws{dE't6SdeetȻX<Κ 4Iȹ>^D"N ̔yC^ԕwx?;&Z5}*Emendstream endobj 78 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2033 >> stream xuU{PSw1ɽjD܌]N]u}շIyT (@H A/1 M :t9uo:ޙǝsCֵG :B)UIYi4R*N6VӓcX/!vn]l vPYU'ì?Q L^@aXV(~ACC4P 5מbjLz6_A^ d.a!Q+oF|8{#fAjTz*'rzN{Fb rv@mn@}~П)*gV~0 )Ɇtwf@7VbmtQѮY]Q ȨQKtBHגy fT.} WZ$Zpݦ?~digk 芪IZS+@\('hTHjPMmBEu|[3s!xy!F)z |0rxRRK6!7(T(#JY8PB[ ֆ8=#ꆙk`. )+nq[}Vq$ < I$뻑q'ml\أnpǬ%,>hD4h*YޒrkEVDHN`* 'Vlr礩<ٻgX/zws#-ҚvpҙTx߿+*0Dmۛ -; iD+MȊنtHtfL9Zfr{D]M3PW@vWAx =fl(Z mޠ3a۲2n6fn;` qH4jN\#t=`Һ H/axۧ}lڄ촅26lT TS''H9-_%LV2U:Y(;(+&;>,1:{3L 01QDQ4^ oF fN5j@"M<9^(q=x'FX*x,3HN'Q OJ̌t7dawBghO'ug!J0Dp847m΀<\R7Y^1Wikk<03cb=J5xk[5)Md%C]Yq}( ,LKi :-xkoAL3c# v߾aT/&endstream endobj 79 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 4107 >> stream xW tSU>!ë@ClDg ^-oI46+6ټ4Mi'R+;>@:hѫ8xaxwZsgݵIWWo3s01o֯[\Kv͆ εL^]<V>?#mWTJG3j -/ݰzJ}`-ہva{^l²Xmb/`b[mX/X:ebRl9Fb%KcP9`Ί9eL̹ k:q)LLu_6߽`B% (O],]2%K7/ '-M:$LjK9G07; eYsL =Ƽx+pq m, vED%7*rίiy} KT $@'fOdOeЛS$yҽ荇a5·|rBws6Y*IP.Kɬ3ln pn"Oh̦X\{`,ř V" Ue z&| ݍ&̌][?f!8Yp- wq`2dUa-j@5ZO-Wco_ ާhfPdsEpt=N5nV>MfG >sKD䕃y|"\ :?IULd9_B6se{rEs5lƃdVs((Ք*&DП2Pkd<ƁkD4-&aʯ'@PP ,tSWۆc,2a%ʁToړN0L2>vOٰbė<<5-Bn#NmQ &b]d'"®oS2FMc81 X ΫqN6$TfK5.RHC Qjrm6jm6Nō$!QfH]ɬwaj{s =~JDƮ>p[#/מdx@fɝ)WF0"* {&E0 3Dt78JJ>@rYyS 'L] (vOIl<69s(-8 uO"*| u_\h|fW(Oq>a L"RKQeB Qw4[Z v8>(1 ?%&$֟:ړjU^و7z7?mh6&\먳9M&adC 'nYVe3@f=f"\2 U*3;$G\YU]v2|RQ:!zA9Ϭ45i @Fo@._Ou_yW?k>{8ņDC> %  /MY`b,vj+M\PFV׃Y"a#7Sщnʑ,BzQ~rK ')E|o3 7R~Ad Z:@x+$,W'ݹjX(O}A͍2,2htڄQpPEP /Vy01@rӈpa\j8A3[Z; jBgQѮbAAn$0?ZE@EdhI+pޖ^;1~8Y8l>sȤ2RƩVI*I.>V+0`޶&/jm/DpiLMb*oI ;%{{x[sCɥRukZAd biKe=F:r}FH7Q~\"FT(x] >.q{nj7Ny]bW6T+*;GB}h :.5x1iYHjBY%>t,(K9H$tu!ʮiz$̾Ө7DHb2Gn> xLn@h V.aD(qpNShb6IUzkQO-$&g[=K0Ls\vӭ )ye2lV$E 2y{mn=MHZ9uƧy };U -ZK5stplQqSI?áSa$L[$(=h#Z!T: }pwreaT3&9\t . [mW[T$ڐ񒹈NN]H?Жޱd z1_p[!i;\8(!1$/n^OmpL:=U!7*˵j(m(oP7E-c]G b?LH6V .}{TG/xũϷqLfXHPm,(\^. xVʱ!(!MAT1vOz~8\gŊ(|`r0Uqe#nrv>.ŋ,,J{NAD6@5BXvȳUFdYtPvI'{'YQB g TY[]}'WS{#BzI*j^bc #{96} ?2i|1]cA$k:J$uZ-2JT6H(Ud+E*8ot7N2=t:iϐjaz\}M.UυΆ.95Tm>?1pF/qh-&5h /RN[-uOf{=`kYEƽ?nn+I|uЬ iq/0q.[@UlBD¿G(;i @˩Y6EbϘ-+'O7"K7["/_S,GREqcˉ8oD[lCTR,e/JgbO-J}4OW2za'+H mmr4-rmM2 kus(Q *:/M\4aX6kW{ЙwYj)HT ?T{F9M trW\XPsnE;KbqD :lOr]|i@eOC+/#ﵰ F:S` Dz\`؞/ً|Zҋ3W;b~6!BOnu.@)WmZksdK<9"?[)Rj>౻\$s]{Z&} 8%#zC#uJe^g/ߝ{{tIJ`S oF onD L1)hgulnҮj+e8_~ _OFۃQNhPj2^}CWK&2clJ҉M~ g]BΦ҆-\zcY.YdPU#0s̷Q: V59tb_<À~ފd1QQGc)nl x=p 7 7;`. i8` x Bɬa UmԨyڮ~79ꭝR| Zh6 v:K|3IdLx7Lד a:endstream endobj 80 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1171 >> stream x5mlu6?LԬab70Db\aalFO[Owmwk{>Ok;R6"T2C0f!\/'0B?ܸЀhn&qmҪ7n:V?Qܧ7`b=VlC L7PmϚ^(7a-/VTTwԜjc#I{~&S..np̂{SL5i`q &DNc &,ĎZ5+3p1R^,;=Aڗf^BꭾAp!Ht6+܍ "Tc^ܬhؗ; O Y'2‡E;@(c{Q:Nxګ,h)>@NM9LBy bbM6nZj2$}Cqz:(dpwDq@_)s6>+ے]t'LJ1Y2qiAs]=wIʩ30 ;-e E 2$t/>;~0w+ ӗokEl?\ݫ6rcF0DqLZ&0Ago[^p{N4\ުĽ**$PLxn'<*Wc:p}Rj}/.J-BTt]6Ȟf?ԼR827|!,62RM0~Ie3%X"~&Pk Yl~|a(w>΁##ۡNuJls膔Rwkk[}mxf>Q>:+rV޵J&5> (pn떅Ҁ%oYTs}c \t&"e<ۍQDXfUKGDz.*xD |Qr! bn+)/8zj!@v:.J>5Ü9Ȣ#s]ҀZ`B-.fɔ_e9vU~&{dQ<(]}ޡ~rp 4$cL#FJl=uP}ɟ.bI>$WTq1 h`m~@g\z|VV`D ~|ecy =endstream endobj 81 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2435 >> stream xmV{Tg23TIi;Z-ֶZ(Z B[ *W KBH|y, !1RD[vUڵe֊ZYJsC?q'h=?Μ]CHihs!!+m"/DjgCxYٻya*YxJδȨ D$EDoKPbXNH D!^$‰-D  >,AA'K)!]['9"Gb u66rWe'$ap{f;]j靥ds*5S̅ Q̍2t@ ܾsʴ)ŵ3a/z+{U]9QZmfnT%Bp]'P81/Y }ġgO!srT5kgF0Nrv XmQiP"P\Efjq*JA Ny E$nxi bF:Gj:!a'`[R)AifΏc 1۷U ؗY{ ,v bnM􈻳?Dͫ'ZJw*ØfyM9"A';rz8w-CJY,3^]Um AEyH͖ eT`*0 :I%܇Ӆ(~I욚ޜo+j4 %:}1(TQC:T^SwZmj^/+ 7D*=9AEX55G ,`3(+D "r˜;BņbTDa;C,t"9Ƌ .RWY]SMҘGc-ߚ/3vT:Fͧ /J`7:9Ø"4"Y Ra9}#iK(ѥ>S?|-Jp `vMgz_n7u_NHne#_\eNџ ri=y1ȘdžN8Ol wi ,$S֟,f,(}qClon+iPs׉Qwmf'`/Y9>u ٳM,;J`A5Ȭ|Ĭki:,%*3/mn2â6&3bQ d񬫑ުV VeE6ݸ&^iGoQݺN¢'ah):JسR\G]kt \% EnO+//ts&ku v-'UXT'/EJeP~ó ) *r<-x#}=֎K$/uO=/ !; }y;.qitڍ2_,ld%M5ߨ2Vi+FbԘJk5ՉjclÏqXz1Iߨ)Wrh(z#]FI"_^0KV:-#Tj4N,:[}e7/y_gUb.HG}GN}f6~ZYO{n!OY3MLED؅ Qvd7yPϷ6鲸/y(y\5nBvo|ojXO~{V7EQ&<^o`;4A =_1y>y񣞯(d6#يT\u>k6ۗ3Wȃ܂0 @qX+oX?}Ci]j"cj4:TJ{VRH$ÛHQ@ ~x>zr`g$ > stream xytSW3zXXGHeBK$ Loc ؖe[$7]&5$N&I'+φLf[ӽ}(o"**߲9K<~x?Óonu  uaA, <cL?333|gvۢ99s$ [%-ߚh;,K]BՉOLz'Oy/>z/ 4A$)ij 9b)˃B7 -O|w۟}@?NƧ6! 2So>N,aN>bO?mIg?k{ek‘ҨF dRjl6y|V7(.rYaS=Y@BIUVPZ 99 "/V˵+ᨼ#Nj}ZG!D+]ZXޔ,ky9;ix0a 8o4? K \i Jɦ:Փ[2Li$vedZ@^ms9h&S~B̲530M悆A"XY1̮yranPJ~;lB w3>3jg.y&S)Er3P>LaB!8[se c!-:{cTC(^Ԕ;i5s;:W+(0f*GaB{BA.]![Lq۝yvti[&PzQ ȸj4:r-4@bn>p0v/C zI? B^^()پin" 5SI0>%FCQ(xf PG&ttK NY TԖdZ agCH09TJer-+5Sa" kª SrQ_NV.c_ҨJ{.;ӕupSV^l^OHcQFGnvCaUh*8< tN[![@"сȨPԽ˰Ft- JހqMn ٜlN gTo9!mCÁp{[3IX<̭#ǫ(-gީj=og°O-(nhM:v[~%ͅ M*8&ıqhmm8xT Snq st"sгUP+A%Jh0ۆEpaUcJPO]~M8r~݅Bq{A1U\N!vnO݌ x0: h&73H@%ٶn|̳`$n y^ J:PotcT֒ ,n:):PX9oLXF[;,C1ܮ߀=_ci&[;(d/x%^8lz~Yr WK[$~L9Q@BEB]#mJ2zVT' |K.ʆ2lJٻZEoqhvhN͜6j\5U'`p1= eƮjJ4 |m._S Q+ke|CN gY [aNb|q-̀}#OB᎒V@}4w6E"1j5;Ipo'ul݆v6;kdn MVK7}}+7hnП[SWg0=O9kSzκͭ; ƴܴb~eԧ_*#H"(Uhc V{JJ%^oTT]ݞй`<-7Q&2'CK+A6zEg\Ŀ+DסჇ;F;ZuV^^AQ(tzN2~^|v"0օ@rZUZ%j7hߦwY[Vl 0>L*+JJKK2_v;LZ@X)tN PbU!pr2W[^)/Mёڡ*-F NůUẶ,*K5GQ$"jW\c'([S0@K]f d2hX8a 2[H'Wmز=kNz|]zʯ d\dk%G<$+&8Fm*LExYFIȠ2+skuT^\=/@Q̗y\Xv7f ή4t-L#@꯺Ob >`ⴂ6ESwQ |鰒i7ax f6smx.hU*J)R֩Vm/ }\r{4mZaQjAgeJp #e֘HCn (ΫMVb 6XA_FOCtZ-VJ4xh5604/)sbW9~~Է[mUR!! OQ)#[jKږ{=6ăF==Gv71I"|RnDItすWJ^WU\I 01h pںIw/*.K@)uuKPk1jȷ6fS"Qey>O x8cu*X=VG^F9)BC:;цӰ^p7?0..:WTVU~*p`MhL?l`[ <Ƕ[>w4fjN]|Zp=3,gD3}ÃaԖ[+-ԇ༱m]PhMvC8=eG3.=E^ilQGpGMG+`j\ڸgӺCmd@YEf|EB[en4 0fb'Ijp^+,+/.)2vhAכ0jڥR_%YaoNZ>>՗^NVgI5"l%[d"yE>F9j5dx>΄$lQOy+KTȧeUƠ!Hn|s&_ndSSJ2,@H&9SAg^!co=FL'>^$<3Gwx$ܐC^SW{\t<<*Q-/ȓwM1_q9Jgu"tqr;ƙo.Ac5wB]|W z1bE=㸷Z{~}~=yExia)mmd"ɥPv RqPa(&3hd֛I{|]sҹhH}砤 s}u]o41iƕIvA}r.Bm2q5 L'FZ(RZLz=jsGKJם(:QeY zk/($mܔjQQ&h\:v!w=x7͍$3\PZq_Y80̽s8g7z.*+3'7ϧ.k\EAmDs. ,ɮ*^6$,:Ϊ3SF`QRexkj`_>LIS y|CgY[8Lc]p8p}-ͽȯ<4ҰH|&^ý9 ҚthwpVJKSqYRmnϷWRiv4LpK ;4Uez`TV4+JZS[Y|->1-A/v>)f~y=!eFCl1Nݓy( kh;j8APm b[Y9ko3vOSz©1A=UjpWURYR ]^w4k`a$X ; T/Y$Yd1{ uoҳdVq>{E`M JgPaC G cp_Hs/σ_2ߋ~ z=(Ň Dxg$gf͞&S / o!"|+FRŸuz'CoޘW.13;pAqoL6Pp-6fnȩ(jq-xzm7fMw ص@o6=Xa& d ݫ5R w"5zs3sDӨeogl) ɕSGՆJB9l"]g| q!܆Lxs{,CFPD|h;UJ *QC.bJ]r@˘G)`Sx~O #3y89@D:HpvPW.~7;4IwޯT0gѱ Ӗl\kJoKjw|tpo?OuZWI礧֖}nfmdlwQ$%j Z+m=^tf-ōpzp4Vٗ8H`<ӡ6'Uc5ȲiQRZ`A ܮ@USXj =~o}^r%+`c)UB]T.GР5h*@o4Z_@ fzaf>Y8( Nn`8$nCgК&Ӱ%Ēw* ^Go40ɫ_FvW4@)RbSlX{NE~`H}ÂVfp{{p6'#ˊp"YЭP@ oކ5F"N&B%y As>x4:efWVBA^^<崙;hĄ[q70⪟Fr/`(/4S1ܣ0ߋЎD\F NxhE)(0օhL>}j/Y?7JIDq;RVWv#hD:@o?`eo 4TaBϿȬ#AY)d>Q4W>dsC` oG~f;8`oS*ɭڭfN?fyPI;;H(U+ADp_ 'Q_Eߊyí꛽pyҹ KTz-gbgk&q&| ٜ .]և>U)(13G> stream xV pS׹ù0&EDBڄ B %fq1 eٲlْ}V%q!(4y#LK{Ĝ̼wdfھϢ˦hKSd~(~gssl_ф'n<8p+^K^+Ql[*5;_/3c'OyAGQuZK=CͣSRSBjF-S˩T%T!8ROhʒ5!ˑ/'?cUCCn3c }awö 3|NnN,܈SGlq>oiޙc+;&7x5&0uJNtJ#f1?si̇+=(d:!=CrI$7rw$xD2f!iPpEVL**e~Cgo)zRh&hDz_6=GAÿ;B4n+^׊uş̵_5ۜ-E~7-ܟf^K+IZI˔&1*d~]c65ښh `.-D>G3,E J"[y ?(;n8/?hCFHrQ*eʴ}C*^Mg6A[Edfn2b3Q.WQb@c=[v,^[y=jK|~$Y$GNѪw!se%īz/3Ǯ:w:9[dv#a26d:]+e 8[<|1ͯxVl JO2lY(HE {!#}Fh<=K0QgAN'{Q 3o@&uWaOql`-Vh W- >c2/r{?:Do$m)TJ^{s xa\icp¯+krZhEhbUR\Q$j< @g5^ d5 &[P֓B䰭\KQ/p4{iACgB\Mz/A& XO]bWl T-Xg7;ǡ j^9]P< 4:]Q+ڪp*yF*U$£qxox@ ƔrbNہj)TYAIީst?#R{~#1@㓟?LpD%\ko<;UTV\+>"RW$J֚&KY h ۴]%%u~d^K|{`Ŭ)ԙA#dT2f̜Ϟ'tp#w[4b!ݮhR* nntN\u%ms;XմةJ|ήQd9'>p nx+^/ 6u<~r wwңo~ U}be&# (D] `+翸5S`4X6#42K6Ι;k۵ ]@O^@ɬtrГh ÿß,Dæ{xG =L=]:p* jyv89kH1 o̙Oyx>"23@$0g7~4I)vECZB>]9 @ 7x<s(~cD붾--׹~Kb?ar*Cw ^G7{"֎!b`<+FۧV߃+/mܤVЇ697 tzdmA> h{2󈏮3HC'͈L@kC&Qix2?wT:܋(!f>ቝKNr2 h6ɴ}*w|41pIX7ĹҢeӚ2q502d -vkmͱ{ I qx4]34 DPO`.L&+U% ":̯FCW~2ߌGd MP$Ygot>`$DHH.m+#cQ[F(Hm,DK4j">O(H77gn)8Ao' wi${C~*>ADE{%;fἍxO3i-!c<-Cc LP%^z@ ]f/~c8t$ɳ4*9UWJNfg0:mQ:qf|{Z6=P jF }U>u]-4ULBB|?24A+H/_6JR¢WB# hv?e> stream xu}TTe0r/T\gQ'PKRAJ@@@AP@f7ʋˋ/jxlkC)öm庶y<ǽ3;3y~*Bp ]cҥKn@5?O8l%̞Q8cÏ3C?a}65|KdTt̶ؠ㼖"0o2L 6b|_ƏļlfV0/1[gƅᙹI2s&:;f\uʮcs!\ KHp}EjCc%e_,!O J*M=/Ы?"?E-[r/ @AOAoz~͒+~ʌ u38ʓ=N8W R܈Mka l E^O§.K`:S 6e5%wE6E9-J&DeHNmO鰜%kQ\.+?.L T{fc[xg @5e)* EY\6;/?Ss:s[(+`IWd\Otä9:fW)gˡj x{MYAۘo̓f6ʌ{ިA,?bVh W.i12l,E5EQ`o"$쬼 ȐNjmMnm>5$MͦLQ6F1$c8m"\FYC~\2yZ_ܤ,Kh\0]M8S?|RH=1{&))d|W#WTBMu9{G5;ԖՎ3ʦh G=Hki4vnc*ي}j5Cͥ0 Yʢƕ%c-c@Ɔ<ٰ'<5:Bщcի 3MY%ѣ~ 'Y: &s8:s7?(շ@'3nTaa;[wRu*v/ u. ]*~\̽)hq[5l6UDQJ)tc^.=N59җUkCΥOT\N]DyL W 2 FY]\hGDU0:~.Y ^ӵ':H0p7:IGuJUgG6acb 0vLea_]9㸥 W\c /5%5CЁÓ7fx!TOL6}\\^ZC i9aAi;@H}4[ Wky-K^W??~jC-yTTZqAUi Ӊߵ% \ę56?"60:EGl '|~tJi-yrVIJ]ƱؽqY)jh05p~!6"8 ´8*bK̪7-U} #I Ai%vyw<4r͍½Ϳm^AGAUlc ؒEvN󓘋KL{tn2K\ٹ*KJ[he\945bIfQ)\=)*PyiU58᳇t,s&F 49n^,[]KD6 Rcߴ~GBF麊+鍓?>tI)㳗qk(xkEڨaਥHW{~po01Ôa~.Dvӹ 3;9d1̢ 'E%6O,Ul%MɊ5^4BK\R{ 7GH9G˃{ I'*.Z5U[Soe/n\ʫ~~FhA&Jř,1ɦ$Hn ; ZˁԥP׷Lޞ! -j2o߻} CDa[ieZ+o|vok_*w{u&hٴb#kg;1ؠOendstream endobj 85 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 870 >> stream xoHw,!Y[vi `C95lX61h-ĘcMfܹ+su#mEa ܯ%ϻ>:P(47;a2JF}XqՁsKoQItoEg !3:9t5!XdEPv)P!U2p*ip?G|RH˧AvF6xi.s32X.ofsΖaC`*ȷ *м^߯6Wj V!IO]lފg~?@O|-|pS}YP1,2J8 4I=I SE?caj;½}(ߌ c^N_f%oDn_38qM7[^>yqϰpzr! 7OlgZ.-m-`<Ī eһdKc-=?f?>6`r])\NpVfCo"<<-`]]JB DDv^Jݾ7-ތe3I+O/u*eZU(_,.SȚԶ~AvsZ~{CX+<]t=6su|&v6"yhMt&+[4q >xؒ)OdbXqY> stream x]ype;]I(Mp5K۔I !m- 31q0p 6-ձz%vWuXdI6`jmR(I;=δΊntꯝ~{)U*))){KUK˟zBo }/W޼OR|W(UMf]K}]IdVER'*l씬4HJ$$ՒM \rdEғe+~ס/m͗//=Z{=3}E7KZ$oJ,wR%]2n?3zrG`r_80Zʡa%G)>Ό$/r=4vWյJaCj8s=~-gIڦu;6˻i\HϏd dɺ}%2/MR놇A@?:!07Q藻>zP)um6O"ؽvhOR8 -$!z"V(2IH $CӁX`Ѱ3wxev zdq gƹYu*Qwtz\Yat-ށ?EJNM[HE\װ }RI넌e:Y0 @&dZ2Hp?ƕzA!9' gci0ʚjX^8ŹɑѢ>s3l\EA34B[PUg[K bőCWDbCwL{yaw63fNKauvJfW8m9{ N)H,y㿌(]K?}p R=gbp%DRLҟ.uf]eRg NקԪ#SdLD:7U_ITO7rRo׃ DcT*E>kOG$"SL2/'b@E:V.ґj45}!s!yFF!ԭn_̀ d\ʕ2x] SEN(6tW:naD4=V_VXWOUGLTC]WW\3S,ɒ`CܸgKw TԱƷ`ܨƗC Zf҉rZ@wh >#nwםsL,\_:3ݵLx½Ŋ)qz /JHa0QpTBLǭ-_9K0O` NmpgjQ'#oKzΦdazlVb9n.t_z- J+.%s\Pw[]6]C%'8'w: X4 KUAhwj;:tЎ'q[`&>JvdG"'? dd0F|(?L~*\"C"3ƨ^I7K~{^ZkXbԭZ;ijgmMPim<Ŏ'LRF8%}$hn:K%qי"⯇팫R&uc[MXTw j5A%3n|gxd6q14%?G]%>HDVG~'@dj!Uz(<#*ؗ'?bTpqЋ,jMj ]bt[3pf.zxL9|6G%f@f8B0!O0C'ߎb3;͵knV-["7endstream endobj 87 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 8224 >> stream xzxTվ!{o@E3FRH4 f53k2 I)^'H,= 9G Z+ g"##W 9r$GH|cf'kag+e'/ybr唪 E3+gJV͒5{5s׮v~т׿Q 4v'&<ҡˆ _>b3y sb1xL''! uI )b!H %aUb8L #345Yb:1xI@"^$f|"x$,1!XяM'D6#$X/cBFGie{=K{%tה^z3ϕ{޻kxzp{,gvwGyQcma0>Voi3 gAC-K wsgIy[ά@{u/F^^W L?sd@=ЛaB%fybmu8kdD^гaC&,>W[w=ƋorЋ kаb4b5V#1k%4̀y 0;B6wмۛNdrA2GL rx@)E o~\HvJ0ptƣ ]_"?{A[$[J rYuXew,UePϥKE[[0&'ɌcgacW&4fQ~Qƕa/@{I}Wj`ހFHu6PO?|O;&do>,SCl_zVw>Ja#ieC>d uKJR։jG*[R2Y/*S :cSd']Oل]neq6]OIɌ]ZEZM5cX%4>m?=*Oj{IU/D:{I8Rg͜` 1@և,|iJex;M" G$߫Z;vYŒ%ER](ہ͸Z.IIR R_$@R6 ,EԂ Ǽf/SOĕ=L5)E2d܄ T:Ɋ% Ǣ^/!j<ޏay$s#L? ;;NS:?Jp2l;k +[9h`~ sY\ev6pXXE+uH@E>\Zy_X (Kz^cMԌA5 Ҙ[ߤw>4AZUFѰ=$ܓ>L}oDNyS(bkbdy# E$g̤tJ!xT1v?i_1lF/EvZ)?kiVW Lq @H4<΢W`&э;,v& 2. IdJ%1 ~|c}ˬjK*U56eqk3\&|E1J/v&aWLW:\JKEg[t΄wٮt&됰)E 6Gj|1+C͸yK]L *@`A GQn'Jn/Npɐ=R$R,6< vݞMM4O,\q?1^!@3 j8eBgk޲%@ŌREQZV4an qDYTF)Zvq?Vy00L}/hRWxfaaޡ@aG(Uz*!$/P-00  :znQ/9+խa2N[֟~?d$ʽ8'ҽ>TEw_zOgv2[i+S6O;̭!LeM΢ttirm- :@x\ Zu=N.BA4V1|5tBefBx08H- A hc9?<} Jpp\?lZp38[=E߮:ak1[,V@[H} Ѝ@Ru!K , S'ZQiqiC"mbpz3™CǾ p0m֍i%M̚3& 촙vg ÀvaBU;Knd$Z"Y0W`QzG\&!]nB5__}frFEbxX=5Kؔ+l6 4>M@]~wæO靀꛱6Rϱ,''SVť.õFq$φ{CW%W +FʘN,]"r SD-UH*ALP&kM5j@FX5_I {^4N7S8d2d3E ф8?Mz!3T* >UIF?_[]P!$Uj2,15b>}$)E'P8u4j2[iHL¦c,hlzMۘm/5Oͭ8@T:I-Y,*:,܃ERE`΢?}.61!=h <cd$bmlRvFtU8v9:O0/Ѹ%dqWW*W5 0LD6Ѱ|:~)0k`9=;Amau'V$Р Lʗ>!3%: ev3@7`F.J5Tmoo8DFGMk<?W-)uq/Vٹd)ʖKsS 4&M%MM hlR d5sW;4g'ύ{~u@9-t*TZsTBzY"Եk|` 4.*+*]HaڲIZ^O3n]w]<~,\k[B;PE#+s e|<b%vG7oTQ50_3E┟jXAH)^eEo튍K<`(pI/ڬ*zҜi3-xVW((jO]#pRKIr†Ew Qr|6 )W 1$ yt9ir4xMo!kUn2n~Ane= yɌԣeB\XzX~hףf |Zʆ6h7yr"i!)lW+ր1`%|928vͫ)Ӱ 뢲ک6[SzZ6=o:wqY7i|JL ;RtL ;@17{1'p{nkspye7h;@SU[u&G>^\+XԴ3ߢjRkxzw9 S*R$?QEq?T+e>2JoN F$n聣]ѝ1Veg.`,qhV={wLBSDL]w;`L1$Gĸ"8#sp|MF&D6NOWDrP֭C$xII(师S[Oב̡e@kF@G쫠yW-\@;:̞Xǖô f6i4טfZdSmq[lB٤iŅu U[k1@=pmub<" ime5oD"ojZgVOp3$x6P`maUHfX*>NஎC0m_m_D먅+ȥַ^ikí`? =,ٴp6zod&C0H_M %}l8Ŗ¢Ƚe (tc7o%SVbWm~Nl]xҺvPMփ"v#I!gB}GTćETap|M-:k(PAVw(&NK_s5It?MXsQZ{)=~b*$)֔ F$_^#Z.ki761 % W&ߑm8w?-`Rހp>uzS1rSVnzq_Tާ D !;XM۰C`l*z򌕳ok+vŵ" Qht@r;f.y熉qShePR:w05}:5|LhSzIX)*p=oF;Vs.aMtu gce>;ל9$Ri{= sssYj. :6{8,"Χx;Ǥ/KF10z'C(m 2iRH:g^<$0R m`Ft3^l6[=vmcqKO+&4ʵs/GOgp_^gsHB)U݆WF]Pݕy%( 1xr? :C~?#f6D BH;YĒ8v1 AQzp\0S2AhϦ,%"si, Z~Cjn~)4 LXu/LLmK"{[нVG1ѭ_a{#ao'6@~+B%tbA7JNnF(Î!xs&?\W= z8 PZ KUwN|0+(^9 Z!Hr7Gּm(='hiw2tVEg(py3h6@Y$SBxz Xu Q7|5j nVW"YyL=A1؝FqSt=H65 K!$ΐ6Qb/d6V¬!N,D+W#hA%#(Ӗ s3. GwfhE!Uo_>XlQh:fdhIm hoB?} FWȉx?9 %S4z⼩'=fBw4$$d.rx3ր40.G+x[W_5p2rzGk^OkA_~F1⻨O.t};-5a&Ow~9NFOMv'u "?Մd gŸn k%Z!*l.͵_i40x_?j)& 1N(}֠XZ ryBkxsG,G돤vn05QЉ5mN Eڦ]F%A;y_ݺl፰({Gf 婛Q3p܅Z*PSW5ZMq, x|.l*lx W {@/tIB>O頾v!vSո_ZER@jꌠHZ fo¯'י& r/)"&y>,h…ZzvJGoPK]Z pLbv. Sjq 8|nҁ.bNʀTU EB|XSi ȼZ.lP2׫j)w7©t:|(+:/3i82r [ǘƽwр/7sI_u4|ܤ.q|%S/ 4|i w'KOk)^Q,dbO:d>y(8̯g~;}řAKwW9T9JLŗ\Z4ވML 1):/<Rʎ|_q]F7 $uls`6?iy:JL)CV]̄ԿHZ-oГ`p͹ M-`}>b p&bVk+%ӗ,a"![۶eGFp"/2*8%ecc큏ժ#ڀ㎠>eě@V2oUpvof:/~tuU8ɵx`&$3v(r4358%W20~}=dmV@BA+8AAcǎŷfAZV1UR qQH|flAkG<^@h>x7gP%ST}v$FzQtDET<_B`2kĴUUP|a8KpԞ`y-W-{ aMx&\7+RMq( u|fvuEEv# ,GS=4e$|8h.89XlC[@ד6`~y,Qut-9 k XK*I5nƔs0R>Uַ19WpD*vxi*cTˈזT+lm*׮|vlM;4j;HC:GN;r|MAgPF>( ƀ 4$P/NW//X\+W.x ]Feb&StħfjSb@Ay-ұkS=6QfOvw5#&_:il-6Fu6pt8RYZ( I݅*a ௮oyWo>xkC:FNB`_њ]&LAoYHsendstream endobj 88 0 obj << /Filter /FlateDecode /Length 1757 >> stream xXKs6& L릇NiS@ST".@IE緻vI0]YnoԿ]~z%gKbj] ' ȗJq\׈l% l6c[{ @[[lE`NQ9l9g*qW%F+Խw'2{ pP6Umb Ob5XÖW׈ό<mWpJkPgs%ǚ f6W.[y)ƄÎi (s^܊RT#r\2͝ 5-E|컙sDU~wqAKoI Πcg7Q;5mx *wE]Ę\ؓj8LkJ03ZuQFJ:ꪯ8PP}o.EJX1&$*[]@l&0Cu@b=Bm*W讲mі2YcN8z28NJ>:pSaÎxP]+AG׶I $oSZK#h-$ȋgX\T4f9'2c \L񿿳 8Qd(FGtܤqZlCl'D2"#S=w׫ZAa+/!݀c@*P:TM3©۶OQ:&@A_TQ)"X[_V ͊3bo%KulT2) FydytgJB6dRF]s'Pjgs8@ ϼK >ֺ7bJѓQʝHۮ顸/Q&7=sytmZ! A:L.xpQ6(ڍۢ Ǧ9m n}L`d":$_0FMPgk}% cυb7z[o|R&}5V ؋iϦjm{-ɔ2CCovP\@ݼQÄM}r/r76e[sM.DOOfsqي;8QyR`M[:| 8ơA$YͺIݭs"Eqr\G5R@[Pb M<;mȿ8V̕x@=3s٧n|2vĤsKφ< GR|\: בrאn{kpg rر7G-[e*%xrY3~pxTaRbqedK~e{,Tg~bm/xT)a]0I}5#I)ԁTM%ͽ~77瘂/wnƜ#{H7X{i'' X.î;L%) )97>z+ \\Qendstream endobj 89 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1344 >> stream x5mLSgo#:i:@þ,qi622Е7 "B޶CKۖp[ [u*ZTE7fd%]d{N<_s~") (ܚ %R\Wѩ뮿M9K*j|A$ =D#MX/G I tڤ=IC63lƹTTo[J/GkCՐa+caA֮͡!;vn@vAbQ1*`IL*cW su{RAgHģh9۝D]W~=VHzZ 8$x>A^aL٥8 U5hz?y?^n~ԯ7WicԴk*M0=Fs*#lx+T<;܅EW2co5ϝug)91(huqk_%/ѻ3:7BU [\~]4Ut /bάk}0UӪ }*yz\86]<:@jZD=g)eiufS6V~O`MEIV7թ-}.\+]r>_ѣH椿ͥ =qkԩ0mx7e&Tc1űj3mSM:{__]vul&@[$їR_J-L 4Rv><|3{rCjc؂•I%+O7n3 GaM5LIO9"EOSSUPkPBS YM鎄Gz.\~0gnkLzr{vGC<&ss>(uUxz$YcEG9W|O7SFu|eGꀾ:nrsN{܅t?@”m !pb4dz9γ2)[t%$zw&endstream endobj 90 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 5111 >> stream xX tTU~! |P1vkAPdM5BȾV%{խ}߷T(MPIm(.- =jێ-1gV>gz9wsrw}_EDQQQEk=RYYYBJXV1#=w^(CK&ۈԖm %/KvYS[߰y̟9O<9xG#UijĽj>b-XOL%/C"b1 XF V+ ('DqA QJ"Fc8b<1(#n' qhBQ׈'Gd-fn%* >HP*/~f{=c.7o[H6ML n^{oϞ=m&h>S+ thI* %PE!IR&|'dGLF> 9'ݧܲq{6umFh4sxVI54d'EU94^TmCy@)XTfUE9O_ݜdpIfI1p0#LwH$= e@ȰWڑqfl^.[ڮ ̴jYgha/A'.$JХa$("W0hDRtVgfA`0օv"Za~.crGQi{ҙG˚fFhjnke+c~&|$f$2 L3PؔvS@Lcx+H]jgws$=hzq$Dz z4Mu; ٺ6|쵏>bژo0Gγ PoNBT[0@ ջQyV%j:H8A/>>O(pΘ.xAUuC ˓`/MIb[e0zAgLRA٩ y(~"<ىIj;jUC3:!$s$0ܔkT| 1_* m7  jWiPz<6wE~,v]Tw<2-JMfm;-$@:HN]D*T+x/7g1 ww[w.>L&L׈7<9ӹUQ@R+oWm;I4Mtxs0$1"p]\N_)% k3t7`ghdZUoPpP4z=@N2?_,͏0It졍gfث YH@v"_w]^^R6vtU ūN\ϯLYNC0`I7wdR1Ja^Vϩ iX2AD)oo!KO|ʠg.AKuV?!*Q2([FCsA:%>3JDK)O+Tcx_L/ZҺVvvgZ0N6}e.pJrO.QY~ΙI/Qqyep "2"qHDcO3ж6R H" yÌ d/c!XfJ6ӿߗ9D1eD*Ps]Fʘ,f _$IFfND)c7ٱ:ܠL(b/#[HivTSz.pL˖{-M 7ư(Ϝ8sY"JaºN 429.LH. ҡDqprrz 1[ݘ-V`o ,#=4*GFouZO =Tvq)>ͽjXt c@7q@BHYرl)΄!ٱςn2#w ;h#'*:|MzE*J`| *БyITz X.2T&`3 ~ Cdg®r#oH2t qy.l.:. WM:$sCLʝJZaGgyVmZĂ%۳(?Gk&R2,r -KtRͥI}BkSϾZ'Dƞ~uc:bAT;~1= &2Μ HrCW_zR"ztKܱlZ;p4A< 7!5Vykʴøݴê&Ow9/9Svkb Ɉc47qѵof2nÛP7) \Q˾}[N 9TCqja&T w,.J[d&l?ޙ~>X5!H‘h\S/yuqi@;m̃S&df*H\͌ۅF o:._7y$6VIJZLx %#?QjvzޚMkZv<ߟ2kj Y] &|qhvqufҀ. [O&Ɍ# 0 ^0ݾXwhOD0CrJoеI? _tq_ӼDLƦ|+Dz|#V1Ԧ+"Yn)~ųjpjx=h=قh:t9z@Bs`8e;xKBvC'LEeU۝R!kϊ>;n^WQ&(IG)%ςendstream endobj 91 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2586 >> stream xmyPw{1b:S !h+F+)׃qAE7} h` .#h&211 lW{{6</$6je+ ,D39&a CkO|e_:/@(%uCzFy,$Mfb:1%-DJ"V("x@oPmSpڲ>^zBƾc\,& 01]4kՅIQyi$1RF?- Z񁁆4K%ZVhv NF/.9ÙCq(nre8۹U=%6QJM ӻ;{w;J$rʨ&<]0X;U+q%鿄i™nLXY sijTA%26|17ɀ zu֬d6zt4*-n#m#; D6=i(tW# 6SR8Oxwn J.YՒX6LG./.AX Un/raIn0-G<5:WDCZ2-(8~l\ޯǰaQNCW'q]-R7Qڄ̏;޺u%6@c>(cx9Bqj֮i%o?æsi@K4zˬ@TZ) 2-->*Vl)R,%zЙSuRNpYQR]zFWK/ǹԚQ/ݿU8urIO5h;Y1D8'O}..hv P `Gf!Ő?+?;l;J8Uh$,RP j: o@c(r%T*JfYv;g)7)v%JbwFA4l9Eu\:]ফI9K񜰇ʑj9ڠԦB f]g6TI1S'CdV^b_m&6cil^MfGQ E>wit4$doGZ-+/c`ckJ+KuTȇ0l3mAUUJěe cN9'旄wbJw'Kw殅hWq7z[b=eX%ޟUⶦ<_C/sŻNY ~lR.Y7z_p/o™{R-LV4WO8)M3ssL+Vʬݖ.䱻chմLt-y>ys;$]5GQ ƲƖ9V3`*Xot J3XH\ݛ,cjAi@ 9pV8̕TP26r ee}t Յ{VjJ\5ёG; Dc(r Mf=y;חۙaOOW-B)endstream endobj 92 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 156 >> stream xcd`ab`dd v 1400q$2黲!{@Q!=?}>0c]Bs۟~}O&ђ >S{6us,]@~*}&3{ry%|r\y8T5Kendstream endobj 93 0 obj << /Filter /FlateDecode /Length 2380 >> stream xXr }Wtj)+^%rݭ\&ʌ'/<ݚ+|}ԥ-{,@CJX%ojㅠ_Wŷ\9/~X xj5)ʬnLo4N~ݕ~#Y͚:.m99˶UuPl$vJƿ͟/B[;cfn^ϣK9{uϣKT^S\0aBldQ$ G5w7hP4CLʗ42u,|LV`U|b1:5ii Y}+e$>.D[5TPpsCq%Kztl(԰;0TW]Qo U.De)<u Jdmê.mվoGP WiDN[e+,rYhɥQ.`XZ/xLd\k4ar'6kcEpYp}pLIxi,ϲ4yj2AdMw} RK3q} j UoN]E?ڌ`}3^!BcRL3Hm^Op5"cuQSPã4H~3&;'56_]%² wLm&(ľfl!`N+A)Oc!9dNS0Ӏ &͂!ffW 2^41IX]I.䰭IR7 P끵^(z7ggs^Gk} Hd0L`]q,ÃaE8_gPcUE!bW[k"Q"<68#dKalHhn\sl}^R8~3 E2IC q$,1ErM LSOzWAXj yF|-7<7 >c.WC%&~{p@\Yڀ+Hn䥳aL ~CԺ}p\ٞ22(ʨ9C V{b3BY7#1x ::R4cha7-DtyU-{:dHmnm]a@2i?)p\kp: J0b hkxdBGd0Hԍ '4?;BcEn;l)x,LEڔϸ/8 {69Ӣ2iV'Q?֑PT0ds;ؘ#J+$<1Qg8ĘM gy\0-KmwR4ngϻr !IChz| F99%6*D4KX8CX4AYS0m> stream xcd`ab`dd v 1400q$dbaa]R~= >r~2Ft''%'u5u6t7rTM^"c˾HLX8yq|>EUJ丘p20C".endstream endobj 95 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 142 >> stream xcd`ab`dd v 5400q$baa]H~= Pׁ? 7~H/(>GhXKdiVB~FM|w> /W [ 1 3 1 ] /Info 3 0 R /Root 2 0 R /Size 97 /ID [] >> stream xcb&F~0 $8J ?@> m(^xH@%"9R_ R`8`T,~D*|3"A$~U ] H2E6rHƯ`ٯsr\ endstream endobj startxref 77417 %%EOF Matrix/inst/doc/Comparisons.pdf0000644000175100001440000023700014576344040016257 0ustar hornikusers%PDF-1.5 % 1 0 obj << /Type /ObjStm /Length 5032 /Filter /FlateDecode /N 97 /First 816 >> stream x\[s8~?o;SS;5:%qEmRF'kH)'l$uHIƹeIΙffւYfҌO+OS/5_qTfBr3LKL8cLQ1Ca&31J-^L)2S%t*F2,LX32dI;f32˕Pa:'$!5 uưt²Y˘I:Ŝ5 gaz1Jg.n|QN+)J"i4@A!2hhRPMfiAMdu)tM ʠf%S5+!5+Uw)ʠ<p1UAڀW5kzl)F<2Dbq)*D#d^+@0n ٢"^Eց~Z,j8{I'X20"99 )x A͙p2 H07q# 5;J2h4 AaܠT4t_Pn8 05`R++KjOwFl i%d<)|<ɏfW9KyA_/C {7sO?#g2g?P\rY~u5_~ͯN糫Qfngb4YT 8ʜg>Z*INwf%JjFKB@@IH]"ņ˧0V%YJiUޛMyP\Gx;Ҕb,hI|1pzHiD !z#6?}Z\s0_}N{O$KruI $t)O&4HVk+0GW 0:M0 tOfTKҶ*{Jrߓ!ݿ/r*ڻmZ Z";Oó].ZFEWY|[ i0iHnYs3ڔ];bDb ۚ1ڱ⻩bfcA|2TiCBZpUUZdهmE)^}Ó#KxzÒt1^%xMw;59W+ ːIsK?әm> Y)y)pV^-rր$aЕ>U^<0`<ܖd/y&dM2N&]2Mfɗd,erǟ _ }2Yꉰ[ʁτ2ǓQYHz3;xx3@ãbyb|sރ#΁b0c~{puhO za&oa$aK+'-W9mdVUYϠ'<%b,')Z"zaʑyBF=ye2]G.p%'əhvw7⮡vSX _ -Β_|DR$- 6#`l"p"q>;;:b͜RYig2T/U\r7UJӆy5$܀>6LBͧ?5Rop5ƳNGh-Jj67AFX@ փ*Nzy۽H]odY"ez"+s6֫іB*) s2i2Me*>uƛ\r6ɍoڌ8Q8N1/]:yWy%=[m~ WX?EDI\82wm낊W"0WY Q}Z(̧tGViԬ.>1LC%e0}(+뱟 5f20~M%6C] '҅\aw^FoJW=>}W[-"2ߡzXEg\ݐʡx#d /ou>: 6#ojrd21˗^%rz=.frl6{T1=}+҆ʤ Iv5h%5ʀlì&4DzyMBܴ;=8zuC]k(F5aj3$w|~q(is+]6n"sYRO׬#_@V$p ?K}>T:a62 F9҄9 oг>Yi|:L<`xsF@a29+ALgI2i"DFӕ>Tgyݴtˆ .a,yH^& Gɛmr q8D{crYMٴ6jiqysq=BQI~ ws_]5S~?[W'@pKơo4#vg_cפҐ IqvMi.ふ-]Y1z4G|q䗽 _4L-u}.~Tǁo$7P|&#an_W 751/pLRɾ K-Fo4,jId+ҋoPы&0j"1;lBEӓnب|9l;"FET6DDm&Dm ˣӷhG;4SfY? & ŸU'Q^NI U7WtcaXLIcfi=Sc51F!57޸ -O4{},u[Wgez:fٖN%ZY/a{7b@TqD/%Kgڈ^вg3EbhujFٸ%-K*qz]>Әo"ys]}cUМ}OE|V}m.x&GWuGH]Dpvn#5ǣcSA! ERݶNW+eͻ)|R6韓F5lME-TWwEC܄,~M4|>l2Ϋ{o]VY $/Be=-齟^h67Ek{hDz\{5]DqHzrnG_8N.)'#vK>^2ʺؚ֥Q+A-V!$7t\' w!UV"e_ZWS: ״`RX,Q/x>6{'N)(_+er 0{|FplUشޤ<<< rh;s鬞HTz<TKgaS4Qk< Ln@'TjIt ;Q nXy;ӝ"^:'K8|ׯc2ӛŽ?Y+&wa|WftZ3+ NidvS廰T.ϫ*VT9|v#w1[ a+e0 n13eq[L]S{!7X\؆ٌ㏦mS8G݊=(A~Q7FZgno8a"/Kd'b]̐eF2c|3B8u pDMPl>zwz~1m+m{{n: ZWVTWI&gY}Z;An; 3ϡ]?·~Ob{s68"-3?̏86]3ڵn8jj紷ݩO̯! o.,D]}& y-xhT3a{m-t4{OL03-E W%n mONv&t"m!?Σ0qtv~b`N(9_9H0wN fp7\nobYyOz̈2SܰޱS@4dFPF b`-CtlHPE~TYV9_g;G⯢|lE))줭 : hFުs}}~dru2(biאI;ULԁS5%\_| {LK0AQ&# J}"=?9$*;'9Vka,ԕe^J'DQ/=|s Q~g/;ŔA!gw#EjXx\ov=dhZT2FDF15S*F|xGᇳ[:V_Tne/SNj$oZGڼo@ʇڧ+}h%Y؅P=R&Ba[ƓB~29^߰0]t8:E+=7ve<˪P0 5\n:"M~*1> stream GPL Ghostscript 10.02.1 2024-03-19T18:15:12+01:00 2024-03-19T18:15:12+01:00 LaTeX with hyperref endstream endobj 100 0 obj << /Filter /FlateDecode /Length 2657 >> stream xYKoNrr1"9iIMG@rhʹٝ=ڵ}*=lyd,:Hlhh'^. _jxwu,ofqu{HBXNFG]|/9,/ۦ52hknI%]Q' mi夷bRcӈ|NG%qNߏfeRh^͎֋C;R6Zzmc\\Єj =<.(,;>5Qqq - C>i\跇]_*ߴNiA Пȯŕ^ݮj^"|V;s/]֋^fh7KP/.C^Tٕi^0dsbtCCF{Vg2~NVA.tYԶ b)ތǡ[W?yUȍ`oX$YP7qOv+\)ekB~Z(PJp;$MĶ(rD^s.frc@B p9jΰIrQ|E$'FѯUr膉ʊ0leG{ [t̵^<̔'P<ð[G\⼄|mSpa@0s?"hlIxWG›hv`VEv;"Znf74]Pu.EG&!I-6CJxqV]ߤ83mP82紣@XXv5G6@ҏ0I_Nn M$a^cZD)ӖE@0t:=cD =!#+JÒDӂRY7) L9S~NQdg+)e^$! m¾,Y.u.yD 4(@P*DobkL"q(7!8:^b;.GB`"Rbqzm̠#DM"}蔀EF8N  ahTFѓ~oH%9kH2pr"2q~,!=6rlф&JWO^P 8*S7tC L*0tFk8u"-xt1MlR CC4BED,eh pF!0[#a\*@x2HH]k,NJ*JLf7ζaQgKeOQgx4rW'Ϙ7khз3 L6gٴ9 ò[p͉٭Zn΄8nhĵKX1\s)BGW+ԹMOznc0,73jÕ?G<nj30)#x}FXe}(}=/NśfݗuRp/Zk@p~3E?lMjkS>cڗ\|`arhZgr 6U,BcJHTT 7NQsM*V WEhOU%9B'KGu\GJAE\;ٜPrBfjתc0ͷZV(\#ҴhXg$ Y _K` Ҵ.\eghG|vs]L_?SƸge~VYSyPyxwA5ZP֗FAl]Z zl*\su_ZtS}75dF>n[!vԮ Ǽ<$4=6~t<}s\2`FSz&w/ȝ&0vaTS"6 ?i"DeyG ^HC6 :bV&?8qH`vK-1X5nъq3( [@_nu3̀[8‰X|ɂ 4x)cfƠ4/Ȇe[ >M6 ix ն?7ˢLߎ9fR H| jL(FWCU#db>e,KQ$njpd&,h]3=rȤ_J*^a?9>.ǎVpV5$E3YSĊ,ρy৚~z<;0lʳ"$m= U"nOqXq*ĔeqZOE8(Y8@u%onG Oszh|NnƦ蒞dk݆rnt7~|ÒI!ip:fDnic-!L1!jdiAmYE> stream xY[n^}h@! 2 ,>"u\&*ZĵY,R_slErΙsůEUx~Eg,r sX _p)skh Xf ;XfҪ{˶yޖaYR^Ƕ>FYX}}ɼ(`2SV+Jip2 jQ(Vo2[t!lmM$**.}(°SytV(7yώ =N-P^ $pI9ٽ(٦jv 'fM"vd LR8*w%5cIpQ%%nPeCٷ9 E!oة{QE>Vwձ /$ݖhą]:r`3\J|n8 vGm<:pԼn@/Jcm$(p{,M `U>s~Sv -zWHr\,1PQ`(r8"h?fD<i҅'TK7|%~`{wn2IM R܀|QgpF1r(rM3C1tQce&ꦺaru^k8E1{>Եl4SBG_=u^ss_dd+ $! HeʉfPږ f:| * 0G@sr47b=%QC9!4\^׊f}ܷmv8&`R5u[8"` 7s!FNaM",R j|/dn)D Y!swlBsi钹T^{ɖ 0b&:|gR( syԈB@ym )}I ބ'F$c:sIRAm'ZJY;IܲebZSC3 c,傽w&妀_f@̓MVhE% Bw.#d祃<2RQ.kmtA&rC5D9lR.mEȅh#&@X>蛆E;"*T9hi]3MxM 9E}\rL`_,ROehd8LdzCQE E<9|-z7YQl& 5ᤄL@wPXDt1= .\X{BWIhpلZ+aڀ hE hK&у(9lC6<4Rbϼḯ>A{vR`їQx±4jFcGV=1/f\ǾT4˖U-]c /IG$F؜wl]Uӳ@|[7..z5DSpQ*ER^cz𭎓>g0ks H9ZMFw4`PNF L2fB.HOmI 9,h-3XRLYW8p׆.+DV6ԭ@ ^~)P90?G ͽk&ʤk&}4Q>E7xƀI$tg8ZsC%:h{@}Lg\bkC@Sjo)NUh}CɅš@l)&]Ve``Su aڟi}C8n]h(1 (; ]?RMX*ZZve^,NA \E޵JY*e3ڤp9IEN\oz$UC@ç9^@[ȕkdrͫWrKUo54`50(kwrv19kT)xC_ԡ= 7 x< ӿ8L킰Ɓڦ=ﯓX6iÑ2Cx i7>![l 0%1lXEV/#dn+0֔An"O@w?I0z`;:*462y?F **00z X|payWkwPM}z?`=lf1O:( BܐzbĔrv\{__MO<9縈{(Gch6V@"*=4eU, i9/ Fpmn'ޏݸahb\OZ_ Ő'$"#c=G(EP-$/WW Fendstream endobj 102 0 obj << /Filter /FlateDecode /Length 2550 >> stream xYKoAXp1' 6MӎgĬHjIj'_ztF'>{U_HH_oIgS/[ER8!I&,Q.Gv˕uRJ r/E_UMhRe0]Q(F-`ڦT}X;Xҹ5Z%YZE\"Q6K5(f0`Y?)P{w죡4A}pwKuI!+)Zy~U8=')Lo E]Q(:{dbhw*~3)Hx.᧕U#~]G }j,K%[ ,?XTnU9 |WI셕Jd#cVb盍!>qCeNe?`(R8C;~ Fv*)g+e0XCW'CA.]SEp؀Cn/j$EDiWmFFU@gRo(G,7iJn[FaԾrar C>2 ~%QHZQ3L`*Y]1FL4F*+SN  ;r>.q<CEȆgRh;#g܉j؅/#߰b/IJŧ,O4H0ڭ_~#" c!cW(" ᰯ@FRGGdfW#X&ڄ[d pXha[n,-\e,E>P\DQԗHjV))J9_j<`s(Rp%tyyCR Q==)qOxI> Ì'HPVMrjoemEqXMuhۧp>[{, ǨAeOxiVھ* *!Ud4?4ONI>YWկoGGBǕKbtVb!)<|x \E8EX.&$ZI"5] hzA@;ߵ{0xl8)kב`!'REVf;ҳ ȟ @"t1|<b}CdA MO› ^EUh/ 9GIDIMϘ &s.uNt%8SXN9E^KvH*Iϴ巫Kpժr ČLD Y0G,VY}86Cɫ0FBek;Nm/ٕ=ڣ2pKAlHǞU|;A[Hho41|n\I{V㗧LR /}k8&YL" H@U|jbpTqnCXlu,G9]i"2+@q6"MX!͘wŖ  /К/IW< g@ ^u:=7C3̲e'È8O2H-%96 Ѡe7mendstream endobj 103 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2193 >> stream xyPW{4D#Yn<*fW11ފ ʱ`f`f`7'# .xLDx \ΑBhpQ0"SQ+L,W_ Oܞ#jx*JRJj5=E|, Q=AqPZ9a;xF͐OC:DSл(+W1?[)GY 6mcn2)ByNġ+mϞ\^OsFcɦj,Ͼ!졼vYG;ú-%q&y%qڭ'*ދ.Tj*iWQd2yO$rhn2pnpוW/܋*kA)2=)?;0Bm0TCyzxFfzn l>ٳ0y[M~-'LLp D\Xfp-:G͛ʍ{@PCt`1p K v7C*uʲ"44.?S ^H%aO@jlJb^&![u) Ȩؽ$2Xл$pNSX^h/ )oeO"9ĸ,k J {0FRz.?7$V.%K9#V<}?BjK>7v Ʌ|꼷8I%ۭOl]˝,H<3], ͎^IapWG= G0;^{Ϯ&YD_ R]Н^96a'a!YQMԔqT xAÊ# mLl'.~h`3prH Vg9M& e,h92 GҎifoҞL[26 Yw\-b:d`d38+M.Y,+!QJ37e:~!(f5P?{0IcՀ'\W|GvITӥ Չo`)ݨfՠadXx}a>m5vx4(K>ĈW - ߖբu -ɘ;W&-߫K؋*Î'ɾDDIͱc~WVD0h6p妅E|P`r%oVu[>g~G7^0nMO-'ZA;ۦik=+3jp^zOo&uddYM8JkE4b()3nL5N)MAϼ#0qzy3DR$3M5@%Be-'B=},TҞ*{Lo,g2?y.1YV`EJ46մ5{7uoyo nuۑd5L7lM%(EUkzWO&;DJIxE~Bы`5>h.if[|(n*1j <9)s#H!Ro Z+9>܀Eh-is"$2kC@یV6|( /KaU+=Ũtw"MBPZysK]c-Wͧf3k3#+Yeة~rDټ u7SoDt,4fx>|gh拋 (c5]{9C: ZU{OIWL1^^ܓüoخ# +AjO=-6dZm c 'E` hUe'xv!oy ey J/H(p Dj~CR6" w<}|.&t(#ߒKU lLtW.RѰ.8)-G@AV~: xendstream endobj 104 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 3310 >> stream xWyTTWe{WXS|DEcbDb1nEb)*j{P["ATb%FDmMg1Ikܢ/s2Ι9sΜ3uSu}OBL$k6,^hKc}O ~>`q wy~!kRBӔ#7DƅmKLZ|K(j"zB͡Rۨj'BR :R jS3 tJFA1JĤIץY҇>>[};&O=));%(+D2 SWpi'DgVigb a' BizfѣKU7S'9)|7U 綦qFn؟-?CE j:fo߮ {_`:ڌ1:xhL`xeԻ̮?=Ҋ)KeOsn-fm5%6$r 76)y47+˜4<` ռПοU_QǽGlcZ*[X<} 3[7"Y=۪R͜%82)۳mVMn㶑I F 2D?)~=YyO%3XIl "?9d#zK]P7t4'ulռ>:<-1&;ކ[E7MPa.Gc;UBA2PM{`s*@d'y&ad CV]\59Py+X2M`}ib!+¶( >wwep׿kLY*JW2bP7{֠S' \+ŬC^lx I%P3hUD% x(].sCMZ?4pjc!163Ӭ '"" ЛJU`<:Pd-P~C_s!}h_+4B$2HB/COUô' L! L f`O(5[^\^jq\]q ;eFƌ$ٔP5$n< {`yn TEGݼj9#E?w_J|S*XO/0b>?W坃.7|%Íg5nṞq?V'4 ->ctl_j^ jQbcXi7ٌ_ )35Gl"&-@62amULoqGH֤Y=/ \(-'8Qڿ0dvlDQi3nATezpA=x{O+UYY5N.:j=Y -j'8Rm8G@Y`̍ y|CjGF^c*MŎS))׊vp cs H`A-x渦}_G}uS[qۙ$44Lه \iD<-S ꅎ݌pP\Wc *w._"]E}nSSm}csVőD&N]oru8R/{ BsD݃`gg]5-n_OA| "7>a+Y&.lKPkv hv~n^ a&or^$kܒoe 0.^k#ǖ37H^9O$-Uu8j4Z*UUʎR{"^ E(:ѐqpIHty8O-sVYi(eLN*5䀧[՗S$fH1j)yd {HZڿ䏱\Y nhɗXzcߠl8#^~M/>K2рwcB5Z'gL4GV;$T&ӸbĥכHCJL BhG썂hiĿn9/0|r[;LA߁ 4e ťťx>Wㆉ2k :-"uU2FUbao2x!n^Հ_¿*V!jbӺҰ'x\^|bEG|ws{v؂p؂c[4~I5&Ok5(jl 1ٛx 'R*/s.<(4}(=?tHGp KsЛ-IA0l);ڠ\.I-0qx{eَl˕,=OكsA똖kJ"_g{\1M#o[&Jwgޑg|ZrCh?}r I`Jƻ1BQZ6I,lc-9O6$Y;v7/+Gn:+'E$CҎ_!~ࠠG1Z=  xsGٛ o~ `ǹaU׫0fV(_+f>} ٴN|"1_(!zGeO SfeFĦkj" %>@֨+׃5 rl=3~U+sy6KÆ{Roy^AJ\\^Q/v[7S2Tj32kHyclbpiJOֆn bS &Sԋz/U&"ql"endstream endobj 105 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2309 >> stream xM tU'"fS%˞UP!RZPæcjڤm;iM&MI-*`h)hW.q]Ϻ친ݝ"3̜3~wGBLBH$Mrs͟;wA&՜o.ӧL!C{?9t1yVRQQܶp=2G9&"#6+*b5XGD&f3 ZEPD3wI)zc֩^H[CP ?`9M$fܺ K ٵ$& R'J7ު0 dv1Ϲ$/n=4h`^A&K**`s43Hh___P/T?GEkZ*%$Q>SٕO+172zy.]{)߇Q(몽E5ey%*tEA}6Ν>3qka#*u"!DWni=Gkt^C].%G/s9Ġh ~ùFN7G/ESfQ^4U~f9a"껵-wњb,*AѴXO[sˍr{_XD;Ujg%;S^_}JfEM#G3hj>0xON Wm)'rFe =p-;b`M_?Vtd[Ƌy8=]vx} 'ڂU*\&c=[M^Ӵһg@ a^5e_]Y&̃5#K6[HA@ !)/&L=D Rxyf.YQeҨ5"7Bw_=|Ut1[̕ۦڮQ9zVovb*r[~_o]. 6pY67{!ho * S*9l1eG#8s8;F&.Z3+sDϚ9q)3C=O '`6Wm[jЃ*K҄$Z\qU0Z&bZ "n]e>. V{75f~971vJwXk,(x\ 聞]f}GXTVxURR0(!8>g.PX}z#"SZehP̴ }sUd*ݰJ5M}cnw,| {@j!u@Px.Xʀ9ơQ|EXE"SG,`5l)Jdd3)TZBJM~mO%MEȸ Rj(6H#^$}׆P45;dx,d+},sIGiA _נfe?xjut{rCzQSa+ o߂߷T\@ÊpΝѮˉOLr*z9!e2 Ȼm-!<2E0':m (&]()ePhSyC}E,jY3iRaendstream endobj 106 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1041 >> stream x}LSgW !$.!ư87Ȩ`P@ʀ^ʥoˇmiPvvYC3زeq8 Nrߓ<IH$V_+=}cI]k81zq^`w\K@C]XZE(Q:ltQ"GкȦAuq !%)֋ W :5P&;`!=#-546'7`Ho@^(4 bZ6Z{Ln>ܘhWq:lFS`DSRY]iڀ<{RDI/"y q:p}D2[@ʘ ]JыN/Ծ^yC $t![8ji5k/=qEiwWO<ɦP C{يޥ {>ҌN3U|,IWc n8kc[& uTCVЊv576%,kc'+/0U)y%%(2y*ђ_y#ue W0uPQ)Y#b HjjRDCj@> Uxb*ٮ91uNkik|<}c1f@goG;}6qmsTDS OR`&{]z'}SV^7(9_?3{nrc9 rlE:^0C}97l]vƁ,1N/^10Ie`-[ ;.Lz:dxatI NZďF[{ iOO17 N˕V5Ԗ*0E|V'a!Ƚ5S-bPL=d v~_`X#)LN}6QsywO8syg;@$,?? !F5FYCCIIS|l?'Nu{#̊Fendstream endobj 107 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 4076 >> stream xW xU{Uh A]qeTܥ[wڦM4ޛ枓4mI ҂ *:. Ž㢫?I32;6i?6.~2"򳺔/(i,"'97/Ⱦ¢ż7< v{>b?qx8HV"F% "H"I$b 9N!JP"fs3Xs\6MN'%jE JU-,Yĸۥ\vryCbOOrIx{qe95<@02]OY<1ơd4E;ձ_u%L((\|,-5r>P#OiIpgxkN ![/~'Ɛ:|Pu hOEfSkUL<P4>عF7J`uP K˭ʃ[ak[aه GI}#5~md U뙘GH &\ϳx"b# ˬ؟.PbkdQH$NrS[`+un/ƘVA^ET]Tœ7&1@9pO'4_"]X$rJ~N{&ūe1 Aotfx"o)6<ܼb6h͒}֡wt, ~8 5DpRiV!Y7-z҃VSOg{JO_C.ɄITM`}Y?xnR>:4^I2sVK-vJ|Do~z-d?pHv0] }GdJ 9lxfv\X+Dit$&7JJ]>aQ(cuTG ɿWBMTU[U*sknqB:(ԉ駊Ǿ=G9MH\05 3QѼȯ ') aFq>d>&js"@`sgw/k46J!kX!nx7C/iL_e<'2Y=(‡~$ۥs}XG:a#?P);ćq'hu&Z,ZKo" M Z-~HޡPnH}p܍.u J5Q49J0#4S 1^kkln 2f%h!^x|<ק>e GOP2c/7E262D+ V@?yK`{o^<[' PLڰj c{ DOJ,aE.ޠõ`s4b~{iI9>d#văϫ;iDvt1/4k:r~Vd-65SX8n^~6i-\XoBN4D]z34Cglq8]́[ dj/Dxir#*td6[=g'މ\ S`i~r>v:*\(N1|[`@!qhz6WƤWۂ;5Wo\ ,3f?DĎc Gct,n#9Rbnwv]c_PrIl"E{@'ԵԶԘdcL {;<1WDmo4'CI׸cm6rSM&pe2"+kve$ev"bxq2=v1b^q>9kPUTy +|hRQUhVY~mQڡ2!)Kq:qhWzf9T:Nd2g1 UN56s >A 9zΌE.x~?؈3#y?9|w ;cM8E۸Se0BwoŊ0m྆Ilcu;0C ^H'A!%}.=ܳYʐAmlC(/V;Bw;&5"{OTX҅iuf=6X6Qυ)A4"b` 1Sen~/>#)^K/؟] oۼendstream endobj 108 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 964 >> stream x]ohu/n-,3p?`)f]+Up-8n/r4M&Y./].Q)snt*R (7!>/x|}Fi#l6s##'z{[tvԹ'g>O< 0˾! EQ<41D -kW[(K-Nツϟ:D1M{\  0VHWw〾7 ].;T)[B%JH$Lέ]LJE_1tpBscMG,mi Eh" 5Ͼ" H_ L&/ v~(Hj1O|^wk jvoan4;Di$mIC'_{ a^{lk|4P$Zh [4 P8Y5z,vfj Q)ț/7oP^K3T#@okJ|7c/v(+}?2k'g66+<.Tp[. Ӳm@_Lqٹ:@Zs Q)c1n%2"jy\U4G*H>0J9cE=д:JNb-PVV<+'2"Brol}lyI/-g ßsY3JqIL 6:>ẹIۓ38nZ𱈥T=} CZj c.{ o|9endstream endobj 109 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1745 >> stream xEU{Pvbs1ɮy51VZcl8CԊ<AE< Bx݁x|;b !4P-1Z-M֙"C̏tOt۝<~KSMʐu@b&z |<-/3}Y}e dekrrwRӢ3)jIEQT KBw0JI~A}@| Pc:,LvS^^Jy|:FRFĭo=~k,qsNqBpݝ5ps*uɹpLyq820P;UX@(*Yn/"K<ݧ K;PM&&(OI@]_M9~X\n`բɴ!!b+Ʃ Ύ>DkIkԂe 6Xj4}BJ[CCX<,".|!4@ e z68Ϥ:wj[!x$66Yy= __ 3T15ʓN* աDxRfOܬkf/t6=4?2?Vsi𣴷!%iA|_|IIE ܭ zv|gOCoB$Wԩ1XL-+/].͌a2b\)AmVYB`x^/6"o1O |c]yc6C_6]}Q}ؐ7ty }t*.VLH7e4U@9%j@V1PSg[^_jFoG YLu~mܺF񮊬Zg2_93'Ze`#RP̪"b؋lhY ]-;̲Qb>ZS>K 5'V| S-<(DVx2gkav])m 8)<LƍDO ZFqbovb\ 3dҐΟ:k~Z03FG>w|UWxLa x>],iӝ0)62;'' rZi"]}n)TZ\^Pc۽RUK'& .Kj&hmȳbȐKPfgs{scP+ iq;`K'図7| TWu`*,O<&Ƶ]]Ҙĉv {; .om ol)8,$d%{#㞃76ꡁO }9qߙ3s ka3SR:fdQ.\Hq3!Uf5 )tKnÏ]}D5_ 9r- N8t.tS̉/qwpi3[0 -]ߴfV@P+S]=Z8Sl+շ[M;܎e€ $wzL75զT*'U ݹKø~aw1 XV`gTg Rz.q1C'*J&}Q{ƐtV[a=OD⶧m،6 ucC|S’+\ʥw ٰ,iJXH yE%uoh0Z=iye|lΞHi)'`o Uomendstream endobj 110 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 8256 >> stream xy xSU-M1 x/ (RPMvJi&M%;4{Ҥ{tKֲ쫊I3?sMn~~ߍ!z bbbz-hKGf38Mߩ}cAߞ0/qpZo'Β̖ΑmH87?e^lٺ(mqc=:W'L|Æ1/_/*og%< ?q82` ';,4[Z s;V`|{#ᄵQ-VÝ,2C}[P )̃OS(@E E+T!_+b3wZH"-Y=D7GrR3VPLH <1SytHPvWC*{2 *@=򏘟optTE_LWL| BqwP8[Os>/A {q|{`܍=tHML,SH`XqBf?+:c"1X C;(:  [Ń'hE 3 @o1 am)vmP Ia3w@%T(O)Uf"? =3 =_u*((j])Uq"%I;i5kߴ$>r.JCAs z AW_glc |vb['!>OgKwAQbZ 1HP<bѣ!j'7qY]D$X0;Jn8`9%W) -Y,5߄WbOh^fyuddVf)RjVDǗ&(~D/s&/ĠRG]z9ww!ƒ`՛T*ҢIϘb &ǘ{hpȢTF@V}kr(H5TVw,Xlr{q}c;݁\ER 4$[.s0 fJ"|s,TWӰ08c޾i{=ٵ s$ƲPdղ0?$>g`~lܤҢ4pFy*yI֒+.'@k2i5L U)em%6q:Q\_aÎ/ϯ::W (w.v=Ncva@irk "~ܙ/ ^,zF:P>O;/T?&&I,j-#h2k729$PbWRnOk1>U?ݸؾDq{FסL37)+J #ob\7|FN\. &"2:40}4#F#<]:|O }$ܐ]0 SҌ[t [L4Bhré/h!wי70HC5žnLP4ak|nsq\z`vf✫BHnT֟P{pJc_\DNg0XqNa8ߊq695u«Xhi}LZܯ7NløVZ#̃25C.[}I/Fb* "o5Ԫ)!P*݄)`qu }Agd)|Ӥ1h̬jT5 p-6cX}j1 iPGe]0>5oQMno3nb$nC61m؀  En^cnm@$I{{7o4@б2E"[#BQE7Œڙ*[Q- \7W=:1J,JӅ oYiYYYi/KE2q{ҞgUAY,]@o#b {ʲ g >[i c}#T}<ЁC{8 8uڜBQ F`8zqR zvw;=q@rZUZi+ԟo7+jM3׍~ P!@I)SRZR/u{=/]VvKtTDSӰ!O<ܝQV*K;vwhJb3[ NflWBUeY<Uk0# WKCE5~6PJn1oa)N~Xq3=r2΃P<;ZuR|;_C=|hV^ƎW6dneJS6\4z@).x㐨EwY 5f_3lD+zvP;Q(DJZ!MTXuTt'sYI 3rT@P֥`E'U42[y@dNeI)WH)Aah>ʹ >xz{B'jN<ĚBB0(ab.JtSb&sNp^2K`xH1bp(|XJ &rBEeW5i'6> #/ APgym\;.C'פ*txFZCU¾rsUSOۀg1>8?FΙ_ᩈk8/y2֨!ܲѼhUdW9$b{*\x.pS2Ene!@yy&u!|p eyLYQn0>W;]P>NXH%(ߠcn._b>.0uYr5sw`C~PNy6-o zXxJZg\XfEk?IoǨ7!0, Ӷv+z޻US*0)4 ܅s6 K(5g3>:a]cI<%\hX}6득سq3Q Ye?J}lK*&ksy;Svgl?e~*اg!Wk֭7!ӹ5{[|ɰ@ ~WMUB_ewn2Vb`͢u@AKeu`ִ"Im2F fP=к 6*%U92| fBa llS!<7ydo(ךIӆxQ/: 1/LڨF$X@˫!S!Kz9=RָyPΣtaRY{?L⎕5s6-x՛a  <5ƀm?co@yJuM^%vGi6y5BZYoy|ܣ#+]UJ=s4푮k! bz5΍JcA=Tc n6Wcg]Hin(jkHn[͈!A{]dIuH(EsӠSF:G; /ޙHc/?~kLrxyYSJ8tP^8tK?WFlܔ3I٥ZZ)ר޸ku,@ &qz?[)SmW+;B sx,^r^C6ku4&u:w劣}t|+owɄq|O-֏J|JVR I6rr$ŧ=}*?O{QsNΉQJm/œz6))- ,jGG9Rܱs4 ;;HakpmkAdGr9"v. wև*<~0;5nPR2bE5Н/ UZErZc; <,R(sufdp&{V=lG/#l؃CuAtb"ړͷ:ۅ ` 9gpi8dWn¶ :^#,[h>dYE-w35t6uQ͵h(3X^E9yɋ!Xd:G}164ni{9ߍs/`v6iT-'jCXrM_ 풃X`2g&̘&P*9אszljt< 'ҧ_yg/2؊[1Wwqpcb݁#m̭P I2ek'L-{0:!/\v;Kh`,\nd6 7ϩ.,oNjн۶`w>D/02|Yi@HqSu@c&+WZ(61rE8f4ss& i=M)+qD;>oq@.o i!xa,B 3r{9yMOPV K0!::(Q0RW_m {d*XF4Y٣+ X+6T3[e &;uۃ~:˿(N.ǫdJr3jJ~*:O6Խ([_n HWj[%^vGyW)N°rs.s%{<ETX{ݎbl&yΖ<%-J)\Va:J>ÀjH"](OB6ߟdܩeJ%Dz'R09 ήG-v_v< gW| p68^vmszZbϵOƞfeMO Į2@Qt 5 I[9%U%%03w>nw0E;/埽Jψ |!޿6] 8"dpr#냆jd%KdDIC9 d zC'&QR9lqen]MuYqGLy)cVZ- ݸ%f3?a܍)|2ͼ$k vlp?^ݍ#3O&;jSu⡥FnsfjS1Ap?^w>RCN%gGЊA#;n{0ZB"9۶wW7[kv`FcV *zѨz=Fc b?~[v߱zPInJo*(v<k ,J>˹FzL.UQAVE.[?i9x"N4 j;tP_ƨyfJNZ8[1هtvĺƱI GhRqWFq/6DXSX' `Y\ *c_vwO ]0&zײhQ@rt,_y[: W^錜$eYCp>&9)Y0ng!$~2{Zw>}чGNaDF(1"*&{kf3n~ Wz`B MT65UmLTFAώ.JUNO[)g ``s;Ϥ*sHGro|y*LKuJ  =[5br&}6`K0a08= H]޸0yyޖ|{rV0^R0<狳'?ijPI´(@X,iLfzܷA_L]uendstream endobj 111 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 352 >> stream xcd`ab`dddwu041d~W8e7Bo?``fdU,H,J+L(I%)`4Pac;cc' ##Kf|?&/aivW*[mtm-Xmm`J^ZjfoদNIf:1sg{t/DZ18}OGK~O_{wL+eEq2E;{;bIn^SO}]lʔ^55ury~{t.ww߶S=UO2pendstream endobj 112 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 699 >> stream xkHSaq3j^ aa_"D("(4JQ4uMtWuy;g:9uMRXB%EE|!}x_R?є4i޸rNVJLdRfVbvȂ"C>EQlS9t%6鱈ru]dX{tRrC|[ʔ@kaAh9v0cP%wH$rPvaJ\ۀ3j0߮;bZ\l[VYqR]*:ZLV0ªstGѠFcbp HbgAݤe NorIfm 2hwg}M=lc]?\' BhφD*F[UEB}%{qFl;5U;{M8r6tC~ vx`h2鐍Ȟ֥IдJGb/߼㌾ `e*b Ǎb6>|FkBX-q$Dg-hGM^]b)N53AF{>I$'rX_JԜ큗LN:0*03sL7+H&K?>t/Mx L tP?ZUĨI:^Rendstream endobj 113 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2269 >> stream xUiXW\JY|UI&j&qDc!Q4(A4.l, -l+ h,-˰$*tQ1:Q&6y'̏5S}w9$%HdָD;9Ka}+c;d ݮ zg޻.1s˜MR'ZMq(gj 5z1XjDdjX%r;i8V/Z"Y/DG݌#cm`9X Nh׋[{&8UGsBtdԴL{I@/+g/^(\')5v=(AsA_9&4B9p*ɫ*Hm\IpMg=8}Ў&HhTB=@z.zivaoMħB Cl8b*<ȳ}8*C{.'kjrfN㝯-GZvpVK(3TYMyLB-!uKq]yE.򈮢(|p s!sm4{j(pz`~EzIt-pMmgNj`#mD0:Uv_Ck]s*э{:l ܅ERHKݱ„p R]ݎu0z{,IQ9Y~jTY*HeSKKSB2A8`f-[~aiirB1[މ@x<^8)*O*}`@Hߧe*_'O7Zyy>8Sp㣻Ǘ9]{a3?G6@&~{վΜr_x"kk媔q1цsI_;}y$Cw֔K _/y/mA: I]wlR~WA! b .L|K9D^H@B'-GjN)r@,s#8gK-2vC0H`{H>8I%89$j IwI6I@ 9d:)m@Zt 8xdZ&?Ke9a?7T"t8t wV&/WԘ$涢*|i-:xy\ [,F> ӧLFnV{_ {oG"QV$uX/UndRȵ$=&xbYbXn. KN-?WƇUJr!)ᑪ<\2w N@OBٌ >J~kM(Ekű ih2W9HvCG3|UHYb]).[`vjĀJ!=g# Oq$K<Ƿ E  ai٠QK.`Zh{kW d-PDvNem̨=i+ l+.q\Fw⢁%?:S8:uYDܳzccfXfHͭ=54sI JMfgv:i5aU|(e,gWmt+=&Tg PDT~%xS^, guP?endstream endobj 114 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 311 >> stream x,CMMIB7VdR  beta vV+W @rL!t,t^ˋQ (F-6c+}yuvymw6eiw`0O\͊}vyhveVgZTsM6򞕴ړϋ_{sy0q^ yo #endstream endobj 115 0 obj << /Filter /FlateDecode /Length 190 >> stream x]M ƶn6uӅƨghXH my34x'}DžZMyZFptpCOH՟exҭm|bu6_bғ9HQIǘ{jAٟ$bC.:&QLB^,ްU" > stream x5Ohp:@s09Ny9dA@u$ -\s G I@Y$35hɧ\rf!_B/*endstream endobj 117 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 269 >> stream xCMR7,  12Q͋oKL0bg͋§j~'eg #e'͋JiuP~>}L讧Ǻɋ !74/XWϡ=:4MFkgo0 7 nendstream endobj 118 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 507 >> stream xcd`ab`dddw441%8eҏw 0s^-?C X+ Nb5?:~iXCw!_gf~|LrfӬs'ϟ$;}% JL\8qEs&韵W;eFNo*nYj6uw4vwԴɕgGusTL]d) ǹΆQ%UrmVvvW4VVgts4NӳpܜKw?..\GUuavyo>Ζn u[޽{m<ftϟ]=i'-> stream xcd`ab`ddds $:tfaaQh `bgf/n0~?/٦wO]_Y* ~Ͽl|r\,y8 )endstream endobj 120 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 105 >> stream xcd`ab`ddds 4Ļ.>;@1012h%lw?k^ܽxIIwlE10U endstream endobj 121 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 3340 >> stream xV pSW?`'i5CM )`Ccf32 xɋVj_l!-Ɩ70!$$C@ M U'줧fFUR{Q!NΙx0Cx.D"n<*yiqNn^~AatC>pF6trᾥp#O45tUok尛V}BnFQN"R!SY]?;5^GQ=(H6%'x##Ҩ!~Z~m-u(b$ fqo=6gK&,2 +˗gJ%&/#%c ؇^BTqxoyeG&z[YC|+!:H7oH^Y,v*zT(mh\k&ߗ9RS2P#TZ[s 2(=͙ Jpg!~T&C;V4 J]lfkag;-FdOlh߲Q#Ii*4bpw(eȾϑ@QNH_~3fR}^ܻ !x-Ƣ/tnc JZSUhЉg03h@ vBYZh'حvklڀ561CR!4U˴6s8QH[ /4E)FAFd$w=^BTK#?!\E53oS N(1ʭ=Î`Ʀ*̽5ͭ?k:M.̡)ZeælVmlpxI"W~@AR:Y(oYβXL>)?Β, &LL:˾H }E h~`4[[-9kxC$1 PykߐYSه=n֭uմԔendQw${Z>\Ì~^^]O+ӝ}R1יĭ+8۶A9Z;" yϦ9 EI}[Y5hXJMǡbuYNX Zgr,/C!x|v *ou5v]*~4u(eHg\ힺgDm55_ a:tNWCfQfI齉Lj Up8 dBqރ[}zh|L\T)A;. k[Z}ߙZI1Wޡ r{קfl oNEX)/ؖ17/> f-d茯~𴣁q`JRA9KM&EmVG{>ÓC8Qb-i޾8EC(d"GVo|h}Џ P4eExb<#F'4VVֳl?YuAB05?\9!Ӕ>p\$\&uz[E}eVqSV*۴5U[SiJ ';Ŗ6%d5zx ٭rmNY{2 Yl9W7DgcޞXlb%w =#On^سaYb|W])WVg^N2PJP~>f M^O+gJX*]e@?`N䑃m̡)8$hA`4:N { 'W^aQPp>CbZGNڡIFڨ?fAx0A,%%+x#l9g߾S_1^e#6ϯnqz_XRUZMg2FYg v4g&`gSw2rC';G$a&`[goo~{i^h>Q>%fwٜ[ӾBsq+b`lL6J{u-w|? rTPŒ)Z2okBmN]T\ >9&hWZԤ4+, #+ɯ_D~k+8-޺5͍, CQ/endstream endobj 122 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 8522 >> stream xzxUƐ(qM :b(" bB޳ٳ$ )*V,wx{,~s/'@23WnmS,5rH?Q&uef r+&d}wr?^Xڤ_\7~*oethLY7gjo/xeMS~fώ2t~ŏ-y|#G=$gg0g.g,gg9P΃b0CW8s^9}98sys'.N>ysvL9}۳^^ܼؓI\Hދzs_}g߱w|w߹Aw_5 n 7t}eL 82ߊxH0ݟ Q &7d0ۡC ׃<6lڰm>ܑn*|r]\К˔"O/cdir5Q: SX`Йu`_dȧhMNQtK|Ѩע;ttcDm/'z+:vx3b%xX/j0>}kyw=4Lpn< f\/k0L%4(2MPHAuc+{EBɮ\J1Ÿ@%"vza_>Z K_wCI(?tr+qDW/iւoW}pjI^̼s|pc|\]r.@.SDKl,Y:zt`[ގt2[ktkAt;33L_դA`mLao@0s'`_>` 1Lv`#μw;'4 o<$ՀX|R{r ,̇BV(Vau*&˄*Ӆ #˲yT| tkڛrŃcA}5#7"$WU$(?B[׈i[+XФ?&ЪzPVFpc!tI68nxʡ;Q3ẗ̇ܲ%˜Gqy0]` _^ ~@B1;_#_G07shE"4|kB:Epw4'n{.C`S0D(q_ڂZ?p)bx ?!׋c,)WEC3{qыc1A|4_csTh0ntuF9 ף3ta*WTcz?3}tJH[BAx!It5df3I,ޤ:2DŽ%8 "D,W).=8 M^_:';:[+vX<u w#Tk)vL$~5ڷs&=#)bOɤa!S-joIsD嫣WmLL%[ps~pyKnD_@_*y([b"JqX3 J aF|- /AEdNi]F~!X@l`'~HD`l8?ttwSN5 y`Zv@ynq{: uEh>T~\QΕx?< ϝh#>cHB8.OkRJ,lQkM#f$>E8́OtΦnt*7mdpԞd?Mbfr04L[ R.{q]0 :^ID5 8yQ<e訊2@1fhf$Styl[&HX7P$H^ CasOq®Oi"J%KJwQP# kKT̄/,@HuU :(jKݰ KV¯ql-\:`#! y+CIr?]J_&ej+]_@"f;ʔ0e1ޠAnCaozU',d eqPe懫ZAH%P ^/b }zYң2sʹ޴)؄ *D>8VF <2yxZ!Fva O Qf0Kz& LW%b"Lo2 aN!e8T^)02cӸOD$fUyٖ1mϹj=6@8Ay玟s $ Dc2ɾ*-) Z嬶W1 sLŻ.`vB[2 3fJ\Q}3 '[kD݉ąn 5.ҹ8}[!C ߯bXʴ5REzByn&N@#U]gr#֘ ᓼq4ӏZ>g:q7m-f  f߰V V%IcmF8~ba{u~ZUBҔƚHYi8}'wNQZ较D:u:[Ng, _^Wݏmn@Vja!-gyf^PEt`ٸK=#54Dtw WXyb ]Œ[N /"@bz~IiGNYD`4⊅](۵"6rvF6vj/vq/bI wvE[6kES-H RAJW^}kw~ct w" aZǖeY5q:My2Ԟ;!c͆^& (q+!\H^ű ]QD#ި5J~_-4 *0\-B Q {"n {<{e@}S4!@Ffi"clsL:UJQ\`zN~z:n""rRc`2drG?!olI+#>vg+5#36f6 ?Y%4 ^/~%SX;*:@ps&3Ӷ=` 'f8;1@$|HDs* k. FIM4bƔj6)+++>P(!Tb.Ct.)8njO={v`<Ϯ.[Q jK2yX4fmOIK$$Fj/__B$PSHI5Bі]ܚy[zL[x;Y6V>r;Kop2+4gڌKϟQ;{ M;&:0aM>_$۩U*aӢkfb;jܲy6k,Bgܭ8ːH** \9Yz}F _*!qܪG {*p{{[o{4o(v#`?@x\h DNq %X)_ƂYnOi}m,0tQ\8TPbZƝ1;;m~ >&`.5vj;+\>\ lNӾb[I4lgO:Vo/gVW[t,6g|f(g v^#;~c=n71ձGlc`Qux6)u{w{l[\Q:(< "'MWԊnN44fI؝{F!D:GÙpO7s9 R$#a?x x ,XDX=:?8Jyw,(ׄ]k1晙U;+n0Q*_K?V.8\}g#h{p.06 f ={,N*RFX/>K*FlD~YDAoMv|[ސ cC^P{4|`ui}\ eZ[Qc;B ߻se:[V:Z|ůRFl=7! 7eWl.P"X0#/TE ϛ>P%ð*XD?׆hȹcY*#ovO1Nnc:N8,S|;wcF诽 ƒǏhb-f1t\E)&w4Z vĥf46$ۑ"H*@K( cF3K8p]S -Y?Ra@DQiT醪3 XIDw%'kO7X7M j(x"F.+C@=Dw0g1<_j`.(=gH&Dp?~!u#aN<35H~8](f|U@Cb~0w.hLPJL,d|#L爊<&kY[#!-v %!0 FʧjB*2@kcV,Sdh.Ky[/|>郬Q92i8{Jb{1RԱδ($kir'<2@>ڸ?k/,Va@+1%LwZր:BWD1=ͅ<_{N| QFs|XTmm *Rxf_T[f@|{'[8a@kmXq?k! osS11JknFnv=5[9L#&ΛUTFq*^AP:J2I8.ϔf&-<HƉnI(}>q{AƏYķjxrM=R76mI%0s̺ cw(7tK/mB?vj 6B`z'4f ׍tg|Ii c/;1mN\s-zGd& s?pXNCtk[Q̡^k-:oKÜcP9 O{Ajti$*炄~aFYwr7@NhzMa7Fu_y>@xpͧӎ ,H dxW^A4@6L &GmTF5R ,3"@_TR髿rWuKjy_#'۽čY!a8w8슟{>I1G36fRMQ's)hbyסxqFM+S "bL/a}hx&G'Lt s}*k-'/ZY]fp5&Q^7Xx,O.~ԨQ|Rd;U,ĂB_-Č}h/Q^, J`M^(KK4Kp%zbwnTET2}x)`B;2C/ na 8`>w=,vA"dDF((  |FRBW`\O'M1/ɽm Ga[zO:gǁ)r3C3b./pUa7ѻ^?~dWr:928EnYdF?2f7X;hoJI=U/R#k= _ރ9tA{&QB0#CMߜ8dzս9uNzp7HKUnetM2DɔBI%~UHGȚҔz@#^+jdRB$(1Xqh{- d&2SIr 8?&]0M`c]&| bh(IZ 4-a" JNIUH*E`=amN$W)5ήfVFpmϢRFm;+8 :J$!5҅q UM~0>eY94U=d-a7pk$ C&?]3D]vbNd,9By6B;< YY]T r񈵝7u~E0c7w} QS{;;{X9ĕrT;܀%|H@d c z-&n Gzv9bZƅV%)xK*,Bk\BbYn<}hFH'{)~Y(3_^%W*9/S,av]_n7]cGNC"eQ9) 9^2CTGr\,b8?1TsIkۛ7†\ D +g +֔/7 V|-zJ.*u4dܫ>)U"v Ep[hTg& 7$J|^WkoYlOۛn,s3vq5vt{?zpqd39~Ks,TdN9[qe#|55B Չ/Cڼ#"w xk'79;ϝh"-0 J #n5 @lȓg.1œXC7"jWSh]~i:,v~(?F3@_݋N_Kwwl{xa#'188?PۖEZFIANכ_+'uendstream endobj 123 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 7334 >> stream xztGB5M0ƌݍ#L2DPhrΡ&<=QBD2Ș5Gguy[m=hÙ *ጹSRR2vU9s&Č,//+J1n7G8M-  %,n]&۶\^bڗV_xmO~SO?slwƦ@C*΋8wrVqsVspYYϙ˙y3sgg>~F989spt9E$t6rhW”)+zwX݈x_lxEֺB̽|C딇z+pvԫ=Vh4?u~ Vi%(; IMHBθ+w ^vEحיɝS!Ĕ137~4fLUQ]c冭+!1Sj+ڭ(`сaex2o?l 2" ;HހV䧁Nqӡw} Ț&*6lbI$*CS]oA=ў2%tE #0\nO2 JNfèd&2o)C`EPTEn2pt`< +7MJ=iJ?!Ẉ^W#!IZ ~RC@WU)J\ bq{v%a vS#t{zݻBݻ?x_!єRҹ4#]c}Ko|iN)VH4*[ÓH}F^M7@cѧ5IfpWP]ě̷kאun[?8 ɤVԐVp)r)w!1k7n1%#ޡ޴ak5tt]E=RSޢ:BIJ~:?uɼT|<\<ƪk-;}aM= Ʒ@N^[X{M7z$3:$''ʺD+o5(VR3j1 ˆE5_vay!afAqPྑ5h|x->_IhZğ vc7/4*+-I"|шʔ'JDI=;l.cjn`䫇par4z\XHflĬ GDHY\$y/:}N`WcXlH!)uXHuQ%x~7݀NsO9!iIu%d;u`C7{6=c>(QEwB0g 7 @Ћ5Mw2CHS ACpFCWcGC 9)fj qL tt,8~ƙvg!.avl:`&2[nHlj`tQ}TʡvDdX1AJzR0  ;[ >3KVѐQaf&_W^+ln} ͫG,7 8ZE44P_b%l4N q_}8Ԙ2q\.L4i**ʠjH!9&=&9&</x"مc_7$B C._#rpa,2P: #cuj8(+i_&"J*Jo;n Pۣ+seN5ƴa `H , 2d3M/'gt<ʃyJJL&\[Tj@zn}D,Hk8nlڠ]Y;LhmEYaGZd<@c&I官)Vq /)8c3a~Y [ZAb6KMm'fh )XR~n:Bn=n6qyB.e|,dcN+bRy ,!a ܇Je gtׁnLp Nq(~B4Βf!x1qj:Fν7FߟCgKh5 ߈ip:qwTFG9SlT]'Q+liW[UVooļ%~G|&/>P`ǔ3 dŨb#j^P4҆ڨ07bOt#C;z5*4Zކ5q7a!9gȆs>yUH&:u#[T:_'ټD{ D`q D0F#fuTG)J{qo֤)N]VtashKP'!Mљ#;tfbZ-hz7IB ON9-NLРR4FE_z_n*o(ܳ/ w8rڶڈiƕK!QUԱSoAp_6:]M6nn*E<d"S2֋~6OF>-g.*q !^/ Cb4쌘v6av1OV27ڭ2X2*Uĥ mX7$xZK,L& Ƭ:e 0'⏆ݩ_,8ŔB ƵH'evفƮ5nS upW^R+l J-XBcսNۆ Ht %n8n@Kv,xz#%|L>29܏FgUf.LY? ʑflmFs]9Ezb]֢ $R࿶>Tz qjV/0g| yۚ4'w;rbJ(JYj k*c!qC,d %l\3ϭeu @?zuUl!wu ԔK"DG+O+ "q" e(dqަPLǝʺ9΀#XƵo\IahF :'t'ɿ[ wBѡyߠMEXؔD؇yd6b~Յoʄ@,׉9AI3-iwI Au1rp۠%7fr:Rt.ݑJ'>ǍawaŒcl ogV0w>|fFfTckܽK7&Lq[ ~/=x+y_8 h ?[HA) e`i25g++-8¯hz8:Ҟ+ݏ {{{ws# Sǭ ,01SNb~kȥ$Y@noqpruomPA2^,a6[ ^ȁG :I`gP5#CF?ϥد H3fjd/^0v4^S O֝Ov[Tk6Zجl1=s:gʲͼղn{n2G\ݙIw1`҄Ds7{VKX[E솥,b/rdc^72vFF3lJ@{~`P`33l!kJqBIjUn̈́{515i{΀N?;3ܓ 'm1bY0fTNΰ'{ioGB^>%q>b1IMܢ1c!|F>7;*:flhAsq)hr)iinD}>OgpZsJM~ [w^ޅXI|G;HN)ڍ^W3ʭ9rC0Kִ4.aMAߊ1Ə VY4͑ܒw~V~0m[k* aJj9ҕ`wglmHX{JT&a?9WYQDƣõpc9\h -A[k3||]puZ V\hIUhэy%| +f59R)2BWH'8`MDMBh$HJ6V;9Kt5De3o$Vh?qKo=SGo.#L)֤lR℁3\g}D)v+Rڼo5 +>ZV+mlr]C18_x[g>xaף_x0@it  WjΨ%ίm~uW4FѦ(pa('xk?^4uH$xRP>?(IC(ET30AVVܦY[4H:"x~j'ژ{GUr|.VW|181ms0_nk{^jXٰj\ߦ"LnvA"CBcߍ>\4O<:&\TH:sڸ.)L|9+|45X_S3cRf*dnأ W )%T>Mz/qB#&B~#jvkB˂!T62>Z:0N217R&*n' chM/h6D $׈6!ހOj*xg x-.UFWDkBWU$ØR9eSYYުnP Z } 7=C[t5: +AD&=}]S2D5Q;Fv:Jg>yj l t':#bT(DTj4FՊ]~g}WD$AvF inԛ3 C+ݫb>*|[61g0Y܇e~BRˀ،vy[DF}"a1%cX?a 6K*a)JB8&n/Dװ.^0 }B5ms ¸S$jRƦkʋv%;Э|έu:Ynb +c6⃯}Mlohn[qX_]gJz[3(m:yUؐ-F?ۇw#>^./B'JdhH6Z*?6Z0݉|%ܘ!vp2j)9FPUnmsvΑZu".;υ FiN)aRL h Z}#YA Oͨx'\ ;WћtDMM}}DzޯY[,v&f0޸DB*aNknncTVt4t=6\M3huE//.v+ * `Uk܋.s*Kx<ǰmfݟ||\o}DdbT'T׮mrʈ.ξi\> stream xWnF}WAW}(( I'+4ElDY^P@I3gg_?<_<-Dt*m齑IH6Y Rg}bK2ɺZܲ_+#MʹbVыNC-9tP톉~eo*omC6riҦB[Hp2Yo8w5X X:kqkɃ&+ O`KZdb򪽊H]52jdG#sMjN3# v/r|/rlc-WE ܎Žv r)0S/̌Wl4}u"^vbpqQKp`rˉ5T<",, ZX?gMAC"y(z;ŚSvUv ʬbViK@!Y^b?ϲhREK&DV`{2NÏY CA*GaGCqBʖ4%`Km)1H-NH`z<7xokײ{(!T1'~`q&ޅ)oٹ.Nt@8#8jtg5)/ʄ#xDOgxq.KhiڰQ\C׃.k[ԝ!hZb<2Sm[ݱv wtT梨I$)ZDX총Li]9w+zޟ!J"8/ۖU[*0=SQi} ơ:;Юן NW} ڰ|3׹/ML4\v6݌'͸4/Q#OXve^5~^#} $_qS}ˏCE'@ +PX WS$z.S(pSnZ>@ꅒ ]xv.b{ָ"T-jLAQ`4`u<`KuF_y8m ,^B ѷSFnIEDu BB@p{qOU'4J5Dꈧ݊TcV~GV{~)&/:G>,t z7 vFww|QA9{/E@l:gƗ^PЪ ӹ LOf!Գ}Q&. Ʒ粤E[ 쌱#endstream endobj 125 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 364 >> stream xa SFSS1000va  RS34rM@vKJ%Au[ы'}}}#ԋ뇰2R`aUxf~dd+kv8rqrypN7?o󊒊ͱǏ{iy\XV+V%.EsuFOYGEGS ? Qendstream endobj 126 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 176 >> stream xcd`ab`dd v 5070q$eaaX~= h Ȟ2&K??O[t;'g*{wzAgIg^gnw^7G@E}vg.HHAi魓kr9丘p208endstream endobj 127 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 186 >> stream xcd`ab`dd v 5030q$caaV~= h ȞqLI7-?މ&;i?ٻK:s:s9 o=M`of⮲n g2F."ۯ%Oy=';=endstream endobj 128 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 3269 >> stream xW{TSWֿɹXD6νUtaۙjE8 "P^ τGB^'g@ "*Z,bŁ:N;S۩mu\߉̬o/'$+;޿PA ][׿~rS~y7CaHP݊;ah?/~{ {-K KeR̊F]]ST<@%RIkf*Bm^QST SK)ZA`Pj  h[dAk`+hKc zC!U!!< H} vATmJ] C{[Q|83r t8|Y(0#ͼ;|肞xɻLx@TUJ,$ӯ_~VVV+tuvwtg&$V̐NΗ)SQOZ)Jq 4C=taVU`x!(Pg`շ[&1̧n!RKu %ތ5, ?8W%ѺvH vy#Π h:?}a(?Ճ:={4wmj8OOvܨ:TbmjbV@N].$h |EXZ+7k'+9 0gv'՞zKtƄ3+RZ+͕M MV kZVK#b-6ăea(`^F? g>G?De"X `M|(N=U~ߜE*L ߬>";zƃAߞ=#V7洁.6X$5V8\5ϵ x'XkL/-Cy Ԏq819͠װïS~\־ZɡyfwMYf2-<y,Ҫ(!hY[osV#@{3m3$3؍Js1<_--J&'kJ5게7otsG;'z3|h<v$fsum;a=d?11嘲j[6oY,Hl5䗦2FF rՅŻdq*]AMUs>G`zy/zUGE8R `NoIߺοXh?!I.T' @ w7~?}zMCIPĿ(x `W4=CsO/ЧhR$YHY`3MϏCAnLoj%M64:8oP3r(%%}nkeU|'xļwi𒋫6<7*$H?mއv .߂$[j dvb9 2!c,^B''#֒n+-gh~aqx+լ5L4 {7%b VC+҃R 4fk>%28S+0vU;g2LkJB-8&$W~ѦnAƙs=,p7n6F;ο~VzzPBP0YA#(t݆u~VA* }Q E#B4B'PM4u8#!\\%'JHgE4my0 L&c-Z fyYLe`Y04ǕXRίGNFXi_FljrR'Y|nA Z uUw=U"Im>#/]@\Py *)|X@9$}=,.v YfD7pn<$ʥ Yl%{) 8CIQw=XtΌW.%F4h0= ~ ga{ܷ@۾ }>>G[8s IK/EuhZVqwJߗ!}{™΃]cnjh=0i:+]CmΣN B +ԖC1-t_j-֦"5hl@3lGC93CY> stream xU}p# X SZD5bgH.}rKr\;$B X0t"`D. uF먠]v;fgv}>JɓDRZb}?/ )xZ 698gZ 4(>҇+Tj]V qAj;9} R$ кե]=h.qle.IUTi[_5W@9!ɶ{j#")C٤Ft|rH;TQ^`)A fR|_:tuxP"303Sp2/HVǭ},,F}pUP 3u迲0jNY~/B_ټv5.&#/rLW;rVa:ܶ2'}+Vi(͂?}2. jDG;zXp4{D5k0uX =FOgAϴR[TMT8A[9(㥰PdI dw#s1KPв˿9sCئf#Ch65?ZeV8AU ;9^kk $pB80L~.K~>Ԭo[s_\L|_wwt!MY}H.@ta+ MovXfJiA?&,>lwx[k=FM1sI zPcix;v7\~vVi1V\)'d\yA*NM}ƑT3b պoS/0P\$O85najXzS=5㸎Mᆜ n2CۻoZ0_0/Ha;Cq'rdڂˎOSc/OPWxOI5uo86'{kx?%^~kSLUWbYq (;AiȲ/M3hh?'N}4hX0kӤ)L%{z9ZWjld]nˉ~kMשm߿ھXlvωB˦w7w*c&$g[Af5MyОZwyC𵌆6o{l|h߾C~ ZúQްWZvTpyx(d8 b7Ȋ&V oGt$^VZ=E'"?2:vxP۩tmV[0ExF$~A;y_xoǫ/roeH%fbQB j8NzsӯۼȪZUf|}i(W`+Hd˜0lXxCȐpF"vp q<#܊xK @џ59^1[<8\f__=^jA蟀xDT娘b&zSǖTPgztk9O8S̥yH%K?0 aC1o46 Vk`*&x"N~\$zu4閔-Nwߊƻ)xc&\85U ]~'m>TL* `Ω,܂ ncm`*&2\1Οxʎ,(y3 pJ#z{uec(8a 6jYye 3PN5Q:l^ʏ8t ga.yny 7ѐsi\ƪy,sd vkCu??8<У72+VbtnZ)A endstream endobj 130 0 obj << /Filter /FlateDecode /Length 785 >> stream xmTMs0Wf[ 0&uRSLzV]ュ~}_)gMtJ0Ziҳ"y<ab G&OLHM߲GA 4Gd^kL 4u3˵Ќ}Tawg+/5, ]b1(#6b_9>M^K<>Z\$>$œ/98XO. LxC_.Ig3"3!{kprV)h=6zP88dtQ5Eۗ*r fH @zby;#Xݕ1jM(kP9#-iTFHR[V̥rh؞nV(ԷUiszr  d7ջho([Vp~S60ai;1)S-{ΤAёϫ.ӁV$UDij)oG*1iOEU:t&]eX9IN@F1$1VgDei \;?5nH+\˖gXwu 6 !BC<\a9:PW;V˱x8xN& 8piM)eCm)d.Fw&v;0#\U_7QF-&3["yȆFNÝ :t z% =i "H_wZXendstream endobj 131 0 obj << /Filter /FlateDecode /Length 1465 >> stream xWYD~_@BрDML>B<(o}hwc;vvgSՇdǠSuuW_/i–^__Y/,+KŸ`K&DRrgEEԋ:YB uiTN~Xڮ(Ti*cIJ$ZHwp'k՚ŗ[=`h]g RzZI +<-suI]5-_D[J^#LSh,Nz(N؋grZ+9MY(|PSMW)+kJt\%k_)T e6]D B[0YCy:X$AΔm}VHZ[Ui`qr˾wکvg39Kӡ(Vv"#o~ dڷUFڿᖰ3E^um;jDU?:+uR-,)!SԋYH\pXu(N&TF`nx(L靋cnyNHb!|xā "x<"|5r `KTf,h{C+rV~$L `j 3|&chXrU.;kdn:(Ycr6jR7A n9!&gJαtIH>" 5TZ'kAsuv}9aI* z1X@kevyBpM!}3\-Z)r3o;Y-9nLEa4xmi&܀Wiه憈"/@.@;VaG D7ں

y "+3;&tNq x:4a* ~A!Ǩ۽gWhXPS`7r=A_P韛R[s 4ݧa+0ʇ> :>eHӘghVy nW} ; 4=|WU ~0i /+L"8f=D ]P~ɰO~,^KEendstream endobj 132 0 obj << /Filter /FlateDecode /Length 1651 >> stream xXKs6WhCք AOE}H,h  Iv:gw&3>taO {Z#jvo8oaˠF߾'H0MC nbx{WEcMc~{/_tl ~Vg@J4&jp(o=B9۳#yϑwDG҇4BDi(kj/ޥRJ*6´*DPKDQ>PK7-lxMU.VRaZ/%i(np>WU|-Q^tEeFiv~2kRBәA\xiȑ̙h]0♓y\)boKԢmY7H.b hO ˭hF!e2&'茷P&1D(o̹ <%W0/T1Xj" [KͽD¸1tu몁uS~xlZY:ES-ŊJa4h}b|3^LV OT =<:(0i0&  .O'haA[gOO'G^ts.Z,8#_ qcf%}|>K==?أqNIлx[:k,_'ƉҹSña,Rb2oKO VN)M[tρ lr)dj_gRXstr>9udv9şLGgz 'ȞɂohܕkDRlkCI!C;tOad[onPš?7\ ! ApAYwۍ԰jEJinwR9\]ѺPtPu̪Nx8qx3YL+2D-L&z}CG(,1SM9uĿ/-)Vfvn*Ux0Fb,&C~gSendstream endobj 133 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 142 >> stream xcd`ab`dd v 5400q$baa]H~= Pׁ? 7~H/(>GhXKdiVB~FM|w> stream xMyp׵[\ v䩌JNO8N\Lq0fX@63U,gY4fFI-S ؘg Tꡚz;+Tuί3YWlY`?EM;7l{ÜS$=A~O/ojnY*-ؿ5/zb;csU ߛPJRߧ%Ng<fakg`C?&< R1]zd@R]"эmUЌ ~CיQƎs]wz#5K[V͍&h@|Drz\^"=NU6n ~PBDZ \]-[Vhw]qE]]'{N|c S@Jn>O})JtRFK/iZ1yPzdGwH+pq=E8Yy3_hTju8hR)2j-v3kEwMePN'$*(A ?ngtn-H0,ʾ+VI•"/Sh-bvZU OOMb6Qڎpy2^".í]}QZA4Am/ѝPxMo),ՋRo[K D|LB1`]a3g,z//'; esgi?s0/̸,t%փ7\>|Oz;恲F=ub#8 ZQkBmhw̎ů_(ʄ5W7Բ7>nr{bU=VgɬJQ"dwOn)W#볺P m3jrN{:<X;\Q/=fCaɹ9PZTcqPhh i0reYpf̹I(Y}G5`\{IaݸPwϡu߁'K/|ܛ&F4 ݀82IAûY J(*HnTd;0 `| hw rN|d^Ę2Εs*+?/|W''@ .<; gP2\Ҭhf)Є~C hӍ%ŀ,N?C#q#cnYخm-4նSamyIU+vЦǧ.}q.IT`%(ցkG%=a~4=qC~F_c+ׯuhxɵÙH:O . ?|"M6 9=(x1&3ChND~ |IoU :(n h[ jR+{JX.U+aMj 8Né!tFIY0#smzN4UGO]C!`xƉi4Sާ4o8S|E|rG^/tIh0hܻosz@4ӏ(=޾kS@K@/Cui>%,NX`Uu\?'>h$~Avw]d"5f[\|ͮBMGl 9|"x'Yxo{u'; U2;ȓ&I7e<;rO뛖헗Wîz kR٧sSTƶdFyŖnfO++kCuJU6A#lbz.%yw`"9E2gqzh6U9Ԑ\U|cSoa%?6K]R`osBaG}ڢĐc#ay'T$ Ec@5xԢ3Ž V x8b13`uL=gtNP?zPYf*7U@NwfW/ܺ N(wZ}T!Hۓa NgҭlNJWC^#fgٓs=kwI8g_ݺ }X e,V|}3Dxw}anvI|VPR}&Zg'DIqxQDQy쬦֠_ʞzJaHf9E`͌yX!lh =F;[Uy/Y#h}Ã!v2jԦ&J'[v:U,{&7Oz}I'A%xG7 MvR[->{?x\.6|>B1İx%mX]Ӹg:]%@X1{> } 7a0q< !!mvurXM!Pn'%n{\Snơ!^BMS|<=y4`$<@=2IL[+ךP?'<#pF>qy=-Jg@Y]9W ’lO_Gtb"ruC];aۛ!ƅVۛ5ɁÔQڡ(r|t_ԣsfڋendstream endobj 135 0 obj << /Type /XRef /Length 157 /Filter /FlateDecode /DecodeParms << /Columns 5 /Predictor 12 >> /W [ 1 3 1 ] /Info 3 0 R /Root 2 0 R /Size 136 /ID [<466ea7cd84103ecb701b5c54d253a738>] >> stream xcb&F~0 $8JdDd٬@i{5"@$ I,9 R̖: Ra6d"Ez-"A$#; fՄSeaW\ "e$#{9X1.0)v|g9Q DyVs8g endstream endobj startxref 80977 %%EOF Matrix/inst/doc/sparseModels.R0000644000175100001440000001243314576344040016054 0ustar hornikusers### R code from vignette source 'sparseModels.Rnw' ################################################### ### code chunk number 1: preliminaries ################################################### options(width=75) library(grDevices) # for R_DEFAULT_PACKAGES=NULL library(stats) # ditto library(utils) # ditto ################################################### ### code chunk number 2: ex1 ################################################### (ff <- factor(strsplit("statistics_is_a_task", "")[[1]], levels=c("_",letters))) factor(ff) # drops the levels that do not occur f1 <- ff[, drop=TRUE] # the same, more transparently ################################################### ### code chunk number 3: ex1.2 ################################################### levels(f1)[match(c("c","k"), levels(f1))] <- "ck" library(Matrix) Matrix(contrasts(f1)) # "treatment" contrasts by default -- level "_" = baseline Matrix(contrasts(C(f1, sum))) Matrix(contrasts(C(f1, helmert)), sparse=TRUE) # S-plus default; much less sparse ################################################### ### code chunk number 4: as_factor_sparse ################################################### as(f1, "sparseMatrix") ################################################### ### code chunk number 5: contrasts_sub ################################################### printSpMatrix( t( Matrix(contrasts(f1))[as.character(f1) ,] ), col.names=TRUE) ################################################### ### code chunk number 6: ex1-model.matrix ################################################### t( Matrix(model.matrix(~ 0+ f1))) # model with*OUT* intercept ################################################### ### code chunk number 7: chickwts-ex ################################################### data(chickwts, package = "datasets") str(chickwts)# a standard R data set, 71 x 2 x.feed <- as(chickwts$feed, "sparseMatrix") x.feed[ , (1:72)[c(TRUE,FALSE,FALSE)]] ## every 3rd column: ################################################### ### code chunk number 8: warpbreaks-data ################################################### data(warpbreaks, package = "datasets") # a standard R data set str(warpbreaks) # 2 x 3 (x 9) balanced two-way with 9 replicates: xtabs(~ wool + tension, data = warpbreaks) ################################################### ### code chunk number 9: modMat-warpbreaks ################################################### tmm <- with(warpbreaks, rbind(as(tension, "sparseMatrix"), as(wool, "sparseMatrix")[-1,,drop=FALSE])) print( image(tmm) ) # print(.) the lattice object ################################################### ### code chunk number 10: morley-data ################################################### data(morley, package = "datasets") # a standard R data set morley$Expt <- factor(morley$Expt) morley$Run <- factor(morley$Run) str(morley) t.mm <- with(morley, rbind(as(Expt, "sparseMatrix"), as(Run, "sparseMatrix")[-1,])) print( image(t.mm) ) # print(.) the lattice object ################################################### ### code chunk number 11: npk_ex ################################################### data(npk, package = "MASS") npk.mf <- model.frame(yield ~ block + N*P*K, data = npk) ## str(npk.mf) # the data frame + "terms" attribute m.npk <- model.matrix(attr(npk.mf, "terms"), data = npk) class(M.npk <- Matrix(m.npk)) dim(M.npk)# 24 x 13 sparse Matrix t(M.npk) # easier to display, column names readably displayed as row.names(t(.)) ################################################### ### code chunk number 12: aov-large-ex ################################################### id <- factor(1:20) a <- factor(1:2) b <- factor(1:2) d <- factor(1:1500) aDat <- expand.grid(id=id, a=a, b=b, d=d) aDat$y <- rnorm(length(aDat[, 1])) # generate some random DV data dim(aDat) # 120'000 x 5 (120'000 = 2*2*1500 * 20 = 6000 * 20) ################################################### ### code chunk number 13: aov-ex-X-sparse ################################################### d2 <- factor(1:150) # 10 times smaller tmp2 <- expand.grid(id=id, a=a, b=b, d=d2) dim(tmp2) dim(mm <- model.matrix( ~ a*b*d, data=tmp2)) ## is 100 times smaller than original example class(smm <- Matrix(mm)) # automatically coerced to sparse round(object.size(mm) / object.size(smm), 1) ################################################### ### code chunk number 14: X-sparse-image (eval = FALSE) ################################################### ## image(t(smm), aspect = 1/3, lwd=0, col.regions = "red") ################################################### ### code chunk number 15: X-sparse-image-fake ################################################### png("sparseModels-X-sparse-image.png", width=6, height=3, units='in', res=150) print( image(t(smm), aspect = 1/3, lwd=0, col.regions = "red") ) dev.off() ################################################### ### code chunk number 16: X-sparse-mult ################################################### x <- 1:600 system.time(y <- smm %*% x) ## sparse is much faster system.time(y. <- mm %*% x) ## than dense identical(as.matrix(y), y.) ## TRUE ################################################### ### code chunk number 17: sessionInfo ################################################### toLatex(sessionInfo()) Matrix/inst/doc/Intro2Matrix.pdf0000644000175100001440000040024114576344041016324 0ustar hornikusers%PDF-1.5 % 1 0 obj << /Type /ObjStm /Length 3936 /Filter /FlateDecode /N 74 /First 614 >> stream x[ms8~Bn%{j\adn'3g_OK/3ppPeKnZݏ[Lʔb)c֥̳TbRi2&5L w)'<5Nd|И!1c,zdYMf*|i$D Li4ST33y~g^G6񂩌3,5c,,2X3N3zoX&,lY&SLgG# քQaC0PǷ?$gEc\D |N2'AJ4>)H'0tE (+j$r H$&dhJem2HC:((e B((2$ (! 1M?Ń̃Ր6ep0"}yPP??ʋ3h`''t1gޅwӂ}@M1Hhq3z׵ ڜyGb`?z}xS\.f"g? t9d _>KgnrcƯmc9qNěȹȟT\)rJlWy<}h &+2,Χ 2nxI:}G-"6t8`rE:UDNGk>3'#lYP&'-R yX|Kt ТBw`5֗ Y ͹2rӋ0 ;%$~ď 1'47h S>W||15fQgSQ?,:_/xqs^73&Xy 3 /LEu}8J!T`CߟrRs*ߠpЄǣj z%*7*7X45ǖ .EOP 5_JeDKZkoӺꤡ\:`SxC^ Dko}X 'o z  yZnɋY\SQ7ƻiJA~Sжu|bTw}&=6$:#TE4{d[kkz`Qϟg~,_;;w}iul1߫q@̑,4Y ~A^@N2P*X>\}̗ڂi9Jv>Lzv"=<߯!`_MV`l5W3J~O+_.HnF zfA]YNH! E^z.NO;3?kЦf L/j?Nmw?wNlikASs%i~vh+j.Kq9r4.H/f3ⷛrF`Fw(9aem[$K Վ`}@L39>;!ߐT1̡W?\b8\VŸHe%lbLe/Qx@ * NDiJ$,R|kc>]YkzXX^ܝcE"96&M2{WɛvR(&0)stTPP&1%5`={]pŅ !h+^]$zW0Ml 56vc"wݶ:ѵڞv.im>:|nbxHl( 'U-JU$v~e\x6y!^4햤[hˇ*-=F5:+{/[,7cw`a$slIO |TS ј5sw\ uj'-ŦE4W!Wu*cZy)ؘ(WZx)M1lB ʎ 5&5?6gj작;:0]Oy0R{ǻыKNug']fd_&NcikN\6x{&ךpmۖHS{2^᪞B=go+DwYxwNZneF AWwMF>reaT۪e,4Pp="Qҭ @ uPn0U6@ۚP2ҩd0zjQD:2=; eD+ѣ.C\sm+ht4nG]6m~jy{uV/ CUTKh?{_F'lDJ/f6E'NiO%z`x!%z'dNȪLs2U9cLlV*tک:,-O5笂)I|i|tt"CCK/eHiA:in綷vjW12ε2h1 YR 5eԧP;ڱ^V=w;͘Zymm_e4:9;FZ+֏ +O;vz,^ki;;5f4Np-vDSf~J%b&t5߬x"ֹ̄;KvdJa› tpt35#:j,& CtE܈*Wmȳ;"{I<[4|_iiC ejc1e1To2;){@k#Y)gK=iG )CxeMct[鴣]Mr2/zn--(3xnPTiU1Ӵ3&h?Nm67>{~R h +a7f M̎ l= 7nqq%2褊NeLDuy a:y1-f;nm'\a݅ɓXN;RM]7Lwm\̆m6dvJtLi ez{s D_USUYQf,^*XDdҎ*~[,'~bbqN'8q$j`4ްosjWwtKAS-L$Av܃76޴IUHT_fO $Mg7 @f4r=KbNF^3sVڄUioěifro&3%j %VQy:6$Lbe6ߗ,KZ3p oŚ&X An6H<>F&n5l;R;2g  ҉oěݥx6Τ&hN$ld~_yXߊ9EۘR'VtUOi3̮-yh'4*iKvӧ y"[]Jަ=8 zr3Ϛ F q{3H"c0ӓF4Sm@fi*Ba![ Y</C$=endstream endobj 76 0 obj << /Subtype /XML /Type /Metadata /Length 1388 >> stream GPL Ghostscript 10.02.1 2024-03-19T18:15:13+01:00 2024-03-19T18:15:13+01:00 LaTeX with hyperref endstream endobj 77 0 obj << /Type /ObjStm /Length 3881 /Filter /FlateDecode /N 74 /First 669 >> stream x[Ys8~_ݚ JU'ILAXGZJ&_ ERQ"Hht}2PbQXJ8w2"5p5#VGF" C&L:5ʼn9Au0tr0d8F8N8Ap_!5\WDmM$/R qHes%4FQZzrr O hd0{p04(bq,1.3XX'c@58*`= ,RI צZ )EQ!-@=85BJdRg$Nq|J|B$H8N -2a x0HNCo!:tˁLhl;O oCR #%mEIU㳗eze88iG4btEÛQ 8+<px^ayq3 dWTiDmjθFJlQ{VSG;Ԡ |t.ѬJtg#5XGW\X._/~^aƧ@.'!Ȭ 1s-+A3ּppGq5 |ʄd,QT;NٳNK:hIi6+^ۨ/~֬ |XW5U9(%o||eq8 |kذּ%>%ԿH eK cд\P(Qӻ뀗P*Bʮmj$,?" "utW)̅ԳպYUG{̓.b4Q>g|}]>Đ͟GvB5lBxGmrcV!ei.u|fm6'm:w;e!ߛv79fґrq5&|9/xw{33h,~vZcZyaӼۧW&T)5+L~vA[/ %|pl3a d]7\H}OsiU~vwQ% JCZNhB#о;?ȏi~_E9g|/>_嫿<8hO f&N?/vDkoZq΋psov[@႗^O==XMogB r lU|}dW˪!CF ykw{G/|h=hjtM qh`c G{ ߴuh'ʈwu:DTA}עf>[_e:(rL;Xw&v9`ogOׯo%׫pv#@r~ª 7V] vuU@BՃÓ06XU)VmbH*&~yz{}}֦[D-mA߬8ͧ+w7ao[Q(BrK}]RSO001ĺ1}5G\47|lG&޴.7zy2=-n|$2=>2-Gw>6/a䵻TG̍̀i[)lc7PgZDǦ]C6ŷ9V_] u||\ >İ~J{6^:^_otv}ޛY|Xfbe&UcC>[.W~ߌp4<ÍeXVfEf/bXlƂ_X dq^o/asHJ';o{<17{*>]P,6[g< dVN/Q;L*-6 d2Wc󳣐G5] nQ,1'eiS:-|9Im0'D8Pl]\fVdҗG9 4a qRLṔ՗f,dj\ aqIU/UJŖ*[XZt9*> 5.b: h@[LDrU_37y 8=jXxSAңI7a`a*e`>{Jddk\Bq;ڐAh֞*n_ORCtxTX G8bvOGsgL|"-Rb/ʚf_[$NI͐2G/!\\88W0 .XPqkZqeBu1q-2\Jwj"tNGZQ*m\UqnvUǰe]c*֕j==dhD]OR궅kb-Vkqv8!8DGǒRi†m݈%*#TԡF |>.9OLbL k:?dD/ _4"?sendstream endobj 152 0 obj << /Filter /FlateDecode /Length 2977 >> stream xXmo6Q, :<M!Fp ʶV:I Ir>KgfUYU\=\q*V?^_+n Z]_#|ō.WpWׇ&֛(wRkvܭ7ˢ,6tz#LQJg5pYatlx îpBh sap\v- }l!__Z  <F6Y}_UРRQOsRuR8؅,zӞbd?VCݓYB^m \} ؾn; `yS?MBzߞ&هoJ#dckW6 9+ 饍MsNVZb/Si~8o~7얥+u%tbDvXKx>} n),uߜ4lƘ^O/{ H,au+xn `Py4 PEt2\z Ahb aR)⢫p/] ɒtZGJM;p*bF`WIwP M?4jE8p:>D\,vߵM3${eq[ޣ!RgI$?Jp*W n(pA !@hYz /|:+rz6*~<.@Ǽ`<-8 =5pȼJ21!?њD!0STP-P0YMmA~A?ڔ)v6j_Av%P^\`mRN%6W)6(8tn!*agBta)t 2|p/Hm)0I%\F<~m|R۷zA*OR)SRRv벏k `-=1muØ5Iا1m SXM;C .FÞ]kz;dn5Deݼ qFnj>>sj웡Aohk-V`7Sbo0HHx鼯df*wh$gPuq(g$A?g b!}6g^q:U`)PӮ|׵Ȭu^}>G0$~U 'H?Y3PP C&H5 zefht}$`BEhpY8g,̮S}Av d9WpQ(p Sh7J)2&]gRQmL:cPx'^ջ7$nޅ9iT%'Jxu&.Ra e92KΚq{g LL\p;醮kV! TX0ToVw:96rcmB cˬ`އdVC5Cɮ÷XƆ‌5/mT4kG@!?>G<*RmdGRu SﰱN8K766EO C2;\,‘~1P~AN@}Q۫A;ե=1'tPd}8)s_h2PSZL9ÍٗPoJגl.Rz3]٠Rwt;f| D Vk܅OG4ĭC XP.0| aCk:6 me%'24]L^J=Z9`<\3vq+U<}XIJdl5ml&\Ýt6܎Q$H& m5abEӈÜoO@%DSa~IED`dv6]T/x ;}Ś s$]/בWQNldž %\A_ЭA{@>ߦLAv)!ڌ~sUti 2o. u9Q RJ=>5m4pKW^S,d2C6|6G%uws) ~s5[V!c8S>K8Ƶy }NOP:E>s$g )-Ydё %y%9G!P?]_zSendstream endobj 153 0 obj << /Filter /FlateDecode /Length 4979 >> stream x[sܸ{NTxsz7}w+R9rf(k)_1Gzg@u7"MEË~_]H֪D^"iBDn2Mud_śrO-,4yQ>EVN'E* kf"Z >BLl"M prOs:*J5긆sR@k3)F c;+zӺ뇗~-Ho8Ԉx"gBO|w*1i %tNġU[|5C׬PQ`{2 Nl$9CF4KylIi~j.jR0̲A[R8)I?Qܨp,9 mͦxB˝9iAdꛅf`Nơ'՗V[P&m5zw{*t.z EY%dyFеe7gD5NT&yG"/n6~ "\@{8.:C8kvxij9qt8G),8-l[2üS^W4#вs0'q :wT`P#l4:p'jđ j'zB7jx 'J$\ywG!uA`$@uM uq/<#5lyNIP0Df]P8t}G Y0NxZmR3+ޖd08 NcS*dF18Ap 洵\ C8g_C`d3炃c +,ıQ<Q2-&N%Qn bL׵?, UEQX[xnW5x#?Nz W8!'7ry"R\6Q" oF{u :zABNt UEy!E7*@3yPwg]"%y30ףkCo4פ脴6 UnҔpcWm-b9'~vcft'8 eu Ϡ7,bVMu[^O(4h,hKgCendd&A:bOr6|@ E#\\ɋYEn|p y}O`M`NkƁb 1> jW&bܱ,5AV2 kM7e?(j@civKCKi$B S aP Q-0t +!+enChK9=jw$S!\x_s$zN'2]0c>6c .~ 7XБG Z'°V6&N9qQ&(<8_+C*̃_Ə;\@9@O|:@"̍U<65t0}EX Pv^bȳ5א~ :Jv60E|>%S6DYxss{s|dphnJl8"pr\sN,Kl9%$Yf kA~gLfRq:Vh t^4;1#'gw#f9pFiā"tfxD cDz <[ YΨ75bnH~3}NA"bgdmAz,"ӹ4{Ng$b3/CLYr[F\cQK4A< CDŁE,sPzMCC1T5ݼQpӎ 2WL~?ǿfGH 5V˳ľ!95򌴚C| ^7eT̼Rr9GZ( lΙfŝ7MeEվnyDf  > (Y!9 =?g a2(wA"!cڹ]HjtoLE=tah_tx4hmY rjvWXL |l JSԣǺFCx̋\ތ`V',Re|GQy6W&;h} |𚈛,>O3!Y_$x ^?T;qK܍6Wtlx ظo(LjrpOS] <9̿ntrϭO$ 3}nijd)/7G%^~(#J]1iZ-1^[_]EƹD`B9(wY[!q\(ƔU2&bIDˑyk n3ɽ>.Fiq&޾:cv*v\!zy)Mw$MMX>7K&N.'Դb~AJs{+sq^C8wqrm?_lF咋q!zvES@y4`}]%nh+*E90pV7"yn^N_YD?b#u-uJgO}&*bБʰĈi_,hZ1Ъs"N YޱHᦂn*KYm,!lTa?*LʱpZE OkŐS0@ڟ'66%J%9&JK)lUQ$)b|Nx.Q}z<- |jPc'Ft$JW츓A3omnh?xaOFs4ɥA=p9û NrpumT/Qy f(u'"12voܽUV?Z觛/YjL[Ep3 {;ML'RV[,琰VV98pW@7CXR0V,5Q&  U&Z3܁Qd9Wd-ɾzjxtNm⦄FtjFS*D]w+$+b99 \}S!QJ=uI3PgG7WhyHfƈB3K pY79!98as&a?s-$,.#-N` M9[p2!!EOlBNM`9sAG- =Ss.2>|z!D56HX`yW)ί-s/1|2br!m|z#|1T1_{|Ն:q"H5~|*Ր`\Opf;QA:b{[=sD@8'Z‘y! `zGr/~D?B'P/My ֗A+ed6u.@l釈uRIEx|w+1V}MuĠ :B[Ly@fV .6PWz9Ds6@T xTǾ5 Y dݽq%wgn;O{!_fǪo=hoAOۺIFmyZxn6)*܅>N$}J1F eW-66XBgbv+fO?+YcrΪlC̃^`}Z}Θ)jMdzoyU:آ /b?wEՖ/N"ױM?F)o!6BܗۮZj%aOج[/Z>yJ"ĄԜy,F+'@Áa6WrO|ѳyĿA_{ Vd'+:anTI `Ӯwwx̺/ITlxyר*?hΉ0:S=\5@:-=IVzfӓw4~Q3y.BNԋi2FHOI'zXƋ5?XfUSA;3z}5 הi6Y&E|.~Sd4YJ0wg+CaI q9P>,u Ԗ= }HKwo{B;8Ylh\-"Ӈ'<S( cId#Qޱ]G8IAAeCg%MOVvkLQ9'> E\sG?z\endstream endobj 154 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 3540 >> stream xWiTTgETR䖍&8DLhQT`D(f-&(jTb,h3!1J|=e廅~VZuWo}W@P=>>?X08c܃1'RK웲S! \!.(!gḱ?X@Qkutj=DmϩRj KQse\ʟZNP H*<)5ʗD1T2D.] K/\jw[O?3,f߹?bGN(jTOEDQk>\|Ç~rVN?,wq$ȇ]?!&kX k bt'ʍFj_KK#DqsW#>9 )gTgŽlN-K֧&2cOyWg\!(r&zP)=5 2pWn:ȹ|ܛU]v{YyGe}/98]-)KhMASB`U< `@S[XZTdLFh;$hnuw-AE7pыOc*n!4$$Om Z~[nIQ z8li訝L T6'(xP-IgwMؗҸ_ ༵n.I2Jlh2nF$!ruĚFͽ}P!3X~uN]Sq酯X.CEm'.t3'ֆu8C}(sč&S}ޒ8$Rx_:}zJ7u9i;]dHWZr<^vLD?"F[}ms]ެJ n$~̪-!8ѯ[?CQMOOxg]PX/eJ3@蕆"@WYeaZEdWNf6 ) 8t%q R4أ=IȊImҔ[Y6w11WUtC^Riv I" "e^kO.'sr9lVK+ȫU8gu^J)כvz,OzSbCxK\*65ot~WngѷQ ?n/N͐E|8ȡ]qM^W,)b,T+S"BC`S_\2.K{|)6>I_׫WƢIxd2mRs-i*Uk+ /C-!;1H UbdH3CckLgΩÃ<[p7 x` q:<]7A2;xcnvgy|܍6N/)=k)4dR\jPv(. ݆cCZxq2Wc#m^YDWхkC԰8(t ?\\lwL=Qfkk>l '[eRe^qfOq;f;]%C,X8mϴtIf|X^čueNힼ4Q ޙ0ÚlSEWk$Ch(/_"]"ŏ~ 7ބGCN0 ]=AP@g+G'7 WԆFܧJ}jXKWf@J\ȤwTUZ XxÍxmomqd@'DsĢ6WubS2c^|ۢ_V͋IdqӠW78[{Gw9>3š4"ܖM цزD_:VC+A);FnPWiY[KX3RvmXjLZRXM GLω^S8҆6!pԠlT*P@EaԲ%>8ԵȾ^8f^]#!=Z)Y[Uq_  s))kC&.փ pW 2ThVΕ1;Sf6b]ϙ1ҕ9rgY1](cЫ}Iޖ:u:>*snVf< ޹VnG[87IZ>>8SnFOWmܰ>hZB61b[} 2 d~L=s0Ȣ $kkjH~#CZ={k:cSu;ō=|mOX˿A`~y2 dLIA9#J&$EO^Φ=NǴx̓挦#R+NMN8o?]panDtjݮ'JF|Db9n|(wy .endstream endobj 155 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 9622 >> stream xzx׶c +z%3BZ(1w ؖ%7]&lM%$$@B r;gl'7ݼ }^k}FtFX>wY[GfyAog^t} )kfnv-o޶0'6&7nQKv,ݹ,ay⊤Uɫǎ{aw&4yk}>m#^{sԖo=fA &!b L %ˉ׈JbxXM '3Zb1XG&$sQ\b41xxxO!chbOE;/BLD|џN /@0DbыH&z)D*чK ^ " .bs /$jܭ.|PߍHDr1D}2uz>4 ^xy{e/QFma?h~`_:Lf^r! C>{e+xuk׹#q j؁7OFF[Xtu:a µFqX}=OA2 l+24eqy z  9$*} x t23Θ(S8Y ,+J4Ek5UpXἀ:ƞ@'҈wcehh1_ܩIf`w@EO p(,lo`P--ոƟ/ sfF7p>w TdB^@wdpҭ L%A1.mMF,*^Lq=)OÂaOdT3Q߬errK̶- s332rXv@ 2H%mY"a **.o8T@*4r#2[?z﫥ߨ]ZIH9*ẃ]撪ҠoPAU$INNU$riأGYՠRw8SB=A823)ۺ Pj̳ IL@N U+}~#pз($Lrn;pTA(>ؘ=eq;>㝷 3 Ol9[[>;#-{ IF,&EXhc`C ֗ D4A)4ǾRe*ې 58>8g-{U]m}=B!0S_J6ȑ| PIi6,C{VHJ4,!w +BvMAvY#IHL@>$8${ j$mB#(;&J(f0Sَ88//^ *@͢08?źq͔jR&ev꜔9zVi`5^]!PVLz {TN".{a8|>e8C4gd7oؕI[`VVnv]VU C0;y!mơc #Kl:#3NZ;ܪs&rK~![~PxPzxq[RْoϷN◮._S* (uW\(!k- 57IE_*B,h+u@֥̋z+KM0mJ2* jjsy*UZҚ*i97uluW5vH&?rG~QT=/l+ĮfG$zwbTsw(=#oގv5S2֐im$jN&; K}7; Lm)쪚emVI  ޫ$~l|`D} :R) wqQqqqQ%efgF_oCᒙJUgrt9B TVK?_Ѣ-pi]?z2NZ'3rVjuF=nX 7Ύzu;h9^BCPT5÷*֮Tz⹛GayA2[QZX^TXP{n )e|֡j*Oi!sAIqdEm;۔|VaX-Rq)`774 N]lg Š `f 4HnZb2aΘB.-v]G17›(* [fk&\|.8J%RӳI|i2 FygzEJ~v)-2B\qr4@&^MeApH-(G`nqH=O;q" Y˹?~(\* CpxJ1T[=|qg˨Os``OcA%ɖL)=3H @PNʠI$X%e7^_3"C߻vvoք&tJaKgU䜥M{e 7N&$sBA`/4ߡpa8\L}9[+γT@g r2gjPƒ{9dCPQG'~T(5@Y8bkuɂq aj:c`;HU_g(׾Oi{q{q`SeGb BUSY4;iE8%p'\yp!; F#֨=+!$+a$/S~=ps+sR4&_'14̅$7%RþIWa8Fܻ]NB>iIXqL2K!'z(d˕BIgk9 J/ϭ*+Z6z7ְٶQ߭.$qgp믺)$$ct5 }̓ATXm)pɰ{Ce%;-Kk~Mp*#9.x{9Y37 HJR]Hri%vSgp%JBkPh/- n0OzpUvJYuk-%aРi0<N#Zl?ߜ^?rcXs(4g ge9 =sW+!fB9{cӾXG7]Bn7a*(y(+sx+8\w!gլ3NYN^˄Se*Z5&8coyaYaאwz64@~0Xx'p? `<93}t0] +3Sqrܞߟȷߌ4;1F?~&fHJ3\P* em98ڊf2͌ڢȖyz!1KB '_/ tT4˼$w| p> nvmk #h0 kV#O>?Yn3^6 PpJL9\JFʬĸfjgRkI3jMmlقutl>`YԷw YtߝrnVǎ#M2pQHm,-}CSnl{8ѫ3HfJz1Ѩ.j&i_\iÿ mzVFkrsM==Ey~nJNoNYcTk8t>c hћz߸wGL[6YޢJ/\P5p{ѶI,'ň_ ě `8#"9(ÝWW-hFp$\>'8Ѵ_{aXxD @^vh{b&KN#?ޜHHctq`x*(;"ɮH2NlN`0X$| GSn]p/ݪ}l׷Ḫ( ,+Uc!)dwE_d= {?*d85* p;^]UW8|[B47v<_$ =L%@6 lh@;SSh:O2A;TC=O?֫AJendstream endobj 156 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 9255 >> stream xz xUo@U(%BqCpAAd"@dO>t$;d "paQqqQOs;d}y{9Ur8{qO]ѣGπD٭fޮF.{JeoZ3vjݴҙUīg5gܵ֕-X_\pâW<;>¸xKL|ǖ=O5)p8rrqqYySYy(ucŜ%I'8K99#9op^<əř͙y3 γ1Y89spx{98|N!94 <N@˜8ws 89\=8@xy^]>q Cm;~ŀw;.x`5⚹Wȋ[vAAYr(~߰?fz}c M?zװ.?4sß~#8G^DGy،N>?{ sgTe _vt@k/SD~eV;]fWQ?c1Ӛn{,4Lt̗+E ZW4,H:|Np-'UAP_܀FA#zIL<o7 XFTss,)pa y8.ȸ&TC?Ke* >,& DR'8h qO,/?{P4.#*>3xgɐ7QxT+{2 q&Yԝ-Y<_5y(JI;aP~F?Pynv;u˟9U7!_~ge粳KT>W  &[WIԪb[& p[\n,dRK\ӕe7eZ3-_ڝ*@@HP.2Wӏ܀Aop\Ohж<W I_ pqOכ EjtDL+->~*(nDɺ3y;󳣲Z@ǣ=Kq=&~;խqVUb@t 8 $3gq}Ph MXP 1LQxj8\-yn]` D[/ q|z3ZJ-   tWIb=h6OʒWjZc~3㿨Ss}OM3s,rO\oȝ g1 ZKdj0jb.e_ hjĠ*p,,y6;^|ʋI\%1F}XL0cD%ʴUeIJ"Q?wÁkܶAI8PvPW|rΙ]5/~oBS* V[wuec1"Wp%jz}µP/>sG`(c$g>,KP܍i%UU4Ÿ1R|"G]t3p_&6ӓB,94 Q2(Wb2CԌ|O>qI[B-=5Ͼ1da0=zU@Goh*K@ÞCchTtk/oLb38POa z";7S*E0oPpM:V).\bT:ry ]p~* d4ikƝgįFIuޮ ,aj7,åj*t&Ag{zLpIgX=oL[8Fo5&ESe ,Y`O-YNL 83 a!~A$r%B7UBw־аL4|hUA>jD摇M "`$a a" DBʠ.K~e͋Eپlf$~:q>.ƸWˌ zۍMNA`TE/4m}]o%r{~o?dZA@Xă!*qNz}QP oÿܚ*]UV47\|_;,aK`yz]7N2#pbŵBDȓLJܸ!pbUJ0lj%†` jPV*J+Clj?GE|v"V|~H`nɂ#P.yQ[܊ U;vη=jJ8@P0lRw@5yCQF#r`!,Zc &2 _&euRW&%XɆ)s$wߌWKKg&Eov6Spl7M綰- G6Rt ,$GҬ b. &ohlr.GrJ d(~KzC6BN7Ա9ZN 2)ƚp>PJ(:B4r+4$do`_1X]6}|ۋ jhR0KE^6Q0RW)/U睰4r3 ;")TlmIC<-WpJ]cNm#">xR0CّHyndPO w2@c7&65l,P/y=(KX;7vJⅩMAG\/l8QUGTIB\\ȟZ?M0ͨ6jDӪMڔhtZ yD=s_t,FgBǩv:Y'zܐZ[gBQGa/ 6`o|VJFr+>e#9 W,:X /\_4K~+ z''/]AcgMj T%PRN9ať:"G n$e6P&3F?+Jg qIt݈܍=W{dvxzZH0scFr%yCvdGzB7Ÿ*PŰ?|v; }!.D"h}Wv|'n">ÞBEt%XO$w]0f ޴`Z0>"LYNbt]dOi,Sk9h|C XJ$gYxPo miߵ-$x|P۩=,.ޏ!m$9ښ훣-D; umY`>`.xvlq gU~UaAv W9`u E{P%QY/+Z{5f0sh.eGww%tvCD4GիϮ~5+9L7vnH1C&,/Jg,8 ~G\2!5IoȃF8As ʨ!Rgd+.( 1ϓ5am,vmgdË1YrE\LrwP8ܦq#8x vi^".]YoO bOM.߻no>n!+ѐca߆7yDA;}O1>* \7旴Î\B&WHAe?B7Tu_`u&" Bm:j:@1 d؃O ȴP | y! A#?aCfcM!6w*ihC%|c5VA={ vG27bK--'V̯ި3J9fx6kge[} M~7k1fR!Jm%RBtkv@]90}/.fu18tEÝz@Ju5BQC{}x ߡޥ4µvt | 6~][뗏K rN TLu46=7=F"N/!ؿ"jrњ714+o?Cn]T04KKΞP8MfV|Ld˳`3D M@͢TUGٓ+&IK-c>#! I/Ph=\ST/1ICcomښ3{a ?ͪM/~R{sY|鄯&N4{tO`L\T[|޶кʺʾZ_P-QMr8.ҘEfܛKp,m%ӶRkRg}yQܳ'7 qd uæZ>tcArj]z |Nmi^Iկn\hZTw=+ˇuXIyen enF !׺&)+ |vqMDu@\dׂ? h)hrJC7F8I~C%5W76bȳ2@՚tǣ&&n7YiOtॠ"3bB&ATҙ0Quc Jk9YN.n'3=>F#Nzd!w8y|6'0E:sT<4ȵr24~ՕpEš`UX𻂖>wWLrd2›OEMcsNR]Iu7oV XL-JM8}Q~:Fy]6>}1nk^S*00f,GT;MI nƗ ݝŀ-U "aLeAVaxg%C7|ʁ< 7HRaEH"WuJ9(^W Vh R&M*I9Ŀ, 0üθ u˞ρBi.@e$}}:q$wdJڟ).zsI'0'wH=S7mf ,\RtU݃M8^RtǮ]Qѥɯy2ײrjis'dT* -)[Qvxi-ۢ4ke.EX J@ToK:}1|Q*{T]``[`[*nFɲ.In_HsN: {!UPbeF|̨fK$ !v <z{w“<))r%/1n) Z٥Y$g~;ۏ{}KJI mH\YzKڀ:yقk1\InQ {5T0JB:у]x `("q)wra!*&`6ҷ0֜/CQ?xFhněq~z@ǬQ 4$WX V `RYxƊxb,j"D2hcculQz`KztsXۖ4J&#?@q磻g\)2{]~?8t*IB"d3 ϊy пo0sg´ 6ȑ!]fʼnCca} _>v,}/v9K5zRRG*Ux=}]s;rmaŖd Fߜ9Bk6= =H19Hu^Elc"K+ǝI%UX4˚MҴzQIղBNQ C lqmB =UX$V=F߄ív_]#7A56S?UY55U˓.VX˯0 )Pjpϻap,ژkIGPX`0>_cZ}_詝9-*JUDqܺxN-6D:q@^)W*9I@DLx"t{߃:F4n",J̉[0@7܁1v-K4^|ͅOn vb8 =X@u cMmMe'~UnA0I W)1}WLhL<ߵ|TNj4d/$k*ڨvBP\ɦ"'DB%Z|NWmB"` ElwCm1w`ɩ)sg:waMg U6v"laڄ".I㛌lM6c&/;]<&N|#9 ]P^1ʫ≦45¾H WV~Wg6lPP&j@=U4i=.b6Ʉ>Z%n;S{pdg!:u/YDˬ3LRHZDMP; W׎Ҳ_odL6.:Ibں[83} ؏} u/;5c@C'|?sdDkZShѻ;~r8=!endstream endobj 157 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 364 >> stream xa SFSS1000va  RS34rM@vKJ%Au[ы'}}}#ԋ뇰2R`aUxf~dd+kv8rqrypN7?o󊒊ͱǏ{iy\XV+V%.EsuFOYGEGS ? Qendstream endobj 158 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 7378 >> stream xy tTU!) *F'pT,!!SUja1X@H,$tb11XB,%b<1eD11('q'A41EL"F1ijXbq+QJۈgT _$,:SM^o#/< gI#oԤQGS:nfl-q{md]x=!ʝP6LzOq;+rDz!}y"=m◓6Lro51v৭=ݟ$*E<3݃9wKнsw (I b)τB*$zx2$=?~tw[;IKP b-*3j3JAX)4jBMd3CRP2Kք!F =]S4'%#h&3f& O}_d2esA%! ΦPiL1 x/YD XRgh4$BxTѕvwr×2$`GRMdD)7 | l+IP qEPBo+H%(k{EYW]WśѧEߞG;OK8 Gy/32ӏ=FSA8h8W~dn~fq3WL?9dzv+j{k~&m󜚎Ky2YefbCeFS?vPN3e?ͮ)rmr<vU$jL; 9^{n:pppprSdSB%S9:ZQ0h$z`Y))OM`.NWcMH y6ӵ˼kZ*/"C%ݻ7fh{4NΜ/uQcv#eIU@"6K2C:vM ɹ W4M3a=^GT{{ޖ/oY͵jM!QU$M79TՏn[P}psU,*ʪ"լOԜS7'.[%<(֕76=B? DςxّP44pgux̊VoTs:E ˞<*Miu?/^GT4 M<} l%g^?7OI8^1g@2ICIrhk9O&A^xCR 0PԭԬ4T555*BRZ =6|нcSzrW}u#!3$+"WШDRtV `" K4Dr#53tǘ0?j`ǫ%{A&O%~=SzM_&W i!B%Avmxz-0t2׽_r]C $VTBScɀ/hŅx~݆':'‰=nJtmcThG@M2 Z*s5;>yǥܥ>k I/àݛ!]2F1L+)9 {=ƞ2S־n:YFSkEG} Q43Ur0M tfY~'mO:3|Ch3ڌ5UM2cMLg7^:㍽.\ ,9dX;F)J;VtAypqW!*&H~,')HqfGS\o^\ͫ=|;y;SkKNa{kz  Ө Hz:*ɲ6@WWYH1\4`xA‚H in%$>5%)vb|ALaA٩ (>"m\ىUjjնf HfIHXzmA"P ~[ҪW UUb(,/iv:ri;5FV#[޷\]CF>dB6deBS)VhM/FP#$z! *2]Ng*>C^IIhB" @@2 hf>RaT;Lnniarui\7f¨5YdFԺiR `SʈZv^Ugˁ_їRG3hFkؕDv0 %RJfvUhyɞW 3va۹s1%Hnxr uM͌`dƓLو8wnW>u0'ijO ͺfHȥ]C2eʪSEhbčS)$V/ɤ/<nԹʼ/y_l:.8/+ qπysC/Dz暸 A66Tp6 6([fdž3puǵǴ5'7e&H.bZ$-Pz[Ȟ<fFث"fԲ/$SRwYqwBibRG)Λ2*7{G>o iI=HB' (Iql= N|{uCC@-X-BfX2 X4*KŮH)& ;Y{2'+\3}u1{'E w9/QX=4^ 0*k{(>GLisOWUv_xGbu=VsP7 [s϶p(cJBg>8~!$,KRh( [!9hD@̅! 鯄 Z.*Bfܻ9}8)! XBSۨ;4320K DL5imf,䚵@Q@ <%~'І>4?Nbg@ Q~"~z  c#@$b7L@FO ի_}3 Q0p!)$R׷j4fd1MZ'E86R |)b#&;f\S *$(v2}jxrwO 0 fY[W- Jp ++W UUu䑓!fgZК)(:1Wr* "HZpsidr(FyɹM/əӽӵu$Bd~6GOPi2BpP 94A,R-;]fG167PwhPsBL0 @+^+c ;T~8ĶJ9HSnyM^N̨6pdl2&1rz!7O yyO 4ee1G },tV-Xd/rNR! 1O= QF4 }}>$ZqhagyQsbOAU$PKhP.qP,ȡ %p$G%+LrYkZ-AO4}ȟA ~l9hp+La$ٮ^ᑕjۚ(vX-!XO#?'Vg9(Sp)w -p-x$N ,ۓě(ɵG\!r zjm-Vp+W._?\1Mk֜5JN*I/ } Ma!uMyU"zJ-+t#* &Q33k1jJ=\G#vź{!5k=6{j &1Dj 4qCw~*3jfuDXTyi}ƥoYOF`VVԪUPjkKagdgǩ{^`*p\<&X[ ۻyO!{? wxv;vaZdkzѦyGԂ$ǴewЅou+sSΌdV43PBIPvm{{+;p  QPӏ@ESN_3-'Q}:3ԧm/=^wiלiל9MI5V oǫOQZQ r.ّ/nfPjE8  *3c|jg K/~x{kP{P[ S9oGߙ=gz>-3゘ *DoaYgt-6U7XuƘ'Q;ם y1e1Z/d2n_(\d򽎭83|ӅhZ?̯L, I6t.L+Yj\ӴZQb1`7$QFŸdl7;no)78+b,wb¼e.'>DS1ɨ"*U*4z5n~-漦+Y&^AN/~ʯjB#Ѹԧ/.:b4 C6^p=Ų ݚʑuJ 13n(_ #Fu.f+cWmjyZFA{w!C44AigʧU:>Y4_ IR.Ǵa-}v㹗mjKג:kkzh1s;d ~=S0)<*¿@TM6 z^QePj@yKPN G(,ZTByH]Z= N̓21wΔk("Z>4,^ ,=*وX&֭*gpR[}ʻh8Gy~̤{^zs -̊gv7%CPhɾ^pgO.QVEߌX?[>Ct̝p&C9ycX\`[ p]|˜toccFVWjAx]x֘ګ*lDbQ[VS9yVڮ U,mUnsjc =n?/ߛ2kj Y]&߱rvvvKsvi@V#D2H4/ };bn" ϔTzHꄎ.>wWxcCƕ~VFenj0nL2^;(䠢kwT F ]\%s*:c.WO>?kPhnL,a3fgg,Dk\[3 y_)`fIU&%eÞ覂 p"d9RY"+ALG UHj̔ɢl6Rb5bQo\WQ&(Ħ͍ ) v+Lx8z\ED;F;Ẅ #tx`I>4%>ΐ45a܅#EKx9\.<pq8S{ԁ bD˵T5ZRh3&i I6oiNq8q_Dl˥^yōނ x{:{g:b|a3)5-]aN UI 0u\6@fLK=Fa `?54l%g˜#}=k[8Y12 WKB%9;= I7\'/[/3 n23 Iq@NO'|&z ảmm V÷>$5UxnH?vendstream endobj 159 0 obj << /Filter /FlateDecode /Length 2168 >> stream xXK4лLM`;:=vkc[s=MYa#gOeSΗ ]ObȾhK[:A ƒ'Qfc+P7ђgͩC<(EET9'q[\ 3aafNR@$P6&KyuVtuӋF-)RMb 6aѢRh\3My~̥6dtc6BdK(3&[exm[Pcd7: {48tIWǣ4̂C 2#K6t8)H,]oe&iԜMsm}('Sř*Iׇ BKp fcՒ4lM? or!)N^) Ĥ؟6 RP .|Z}jjo%{Iql''M>]oeCf8},fs?$*2Rq@wq Xug)ͧ!jػO0)͙9o\>w9qa D&J`§T!0BUnFmH\R8|-8=AiS"  !Ve )QGpoVB[M1`p~xZt#)o狩z.!E.mn _H#˱PnԗVy$TφLVͤs(:XfPȟWcR*| ^ ڟęƁG$_Dc 6J7FMo(~}?aطۑ^:cFا- JT*(CC5l+`Q7(h~(\^1’RI:.kB#%hx9a) B>zV"*94ҋ}f 5p`& 8vCZ&QK]^IlIn3*tTa3ZxHH2oMp]ߥXЧEV~qGY}/7\CνhaZyMo{$(Mbl%L\5I*{AM =`I38|ja' ؐ*qq]p~@}qpw#EWǑ{=", ȟh~/eJ1^zLfM >QZl+A$iw螲_:4E䡄p\LA oᦶVACRmt_((m -Mpj8-o񔸐ׯ~mcG/~yiPBs Ӯdz(hQ2-Ə m0Pwhho j|}5O:ӂu=hXh@̨ ωUݼL †ZAHWM1VXʳsP^lc#q.flffh>6 -_cl5R e"m:X-NDDh:8u>in\]M~QG|]I$*MDŽ^AnKDE {5 Yة6z{~5/"۵3,ӌfN3Ʃɭ3 +O/j)kkPXƘ̙Vh_ʹ eՌlsRqcMtܔoDžKC80C)wo _A&|_kv'|Xr>| )35ҿ@o6}X M دO8@*m>uֹҒyd?:Jʈ%KUXը8y3%i!@}1:iI5TnƒM74nO~ό! `(*-].;%/ + _E+|F-sA-( eF8FψgQendstream endobj 160 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 786 >> stream x5QkLY3wa!aj?EB4Q#"$l)Eږ  m?ˣ%*XRqWG|] &*zDk$眜à),bfFӆ уC96 $Liݝqm_7h/H[f"Qqġ*f)Φ05Q6sjBTutd$%LJdsuu#E3ǿW \* ;5p0B٨*tsՙy~nT畠 (P3⾧:#Jqʿuw& M2 |+ulgTe'VRv5I?@BscQG'wF ?d/M/vz:K esW|dD\m'l ē^2ѩ,ٴ`sWHdU~m`\CYe\0sBCs>V x}1|٫rN@ŗSb\HjvB2w>Pϸ2 `tHddܼs#Q(FG,oo(t.du1xM7gU,Uc uK8NLjº!.}O.?UG8uJ؅YL.~M Hu?(67t`~t3 x:mw,?\jvZ _GSnҔN~ű*9h::䈽7(ki಄}5>\Vendstream endobj 161 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 9995 >> stream xztUa<,D+1;@JX@һǽ[ջ4;hԭn[q I i@XBjxl{ޕwNv{Ⱥ/S YAAx|Pzqk_+]T^C7Ȥ瞫{ /4<%[m]v;W,\zeM퍷~s. M%2Ų;dKdwʖʦɖɦ˖VfV#[-)[#{^vl엲dd/^= +{P6O%˲Gdef"[$k]!+*H*eje~!]/{F6E 2w5ѝPljvgE'ꏯ}_^O8:ugy9[+nc%[7l!#N;o[uۇ;;=8]3]O56g~=_|tf{|-(M2]jؖ˯onPWs+PQjq+f1uVGۼ-bI-G`l|vlw~G㷸| S (Pm,F.nR6o/]05,h×J Ez@CaL륽%N/ӂQSۅh3ډJq~#im>Y{ ak>< hwwm"xǀۊ@VA\7@3nc|G'ǿ)bŽ5sZ^&&Ѐ֍|p=E>צqV\qFQHdCɓoN2\'Omܹb {eLE #Ͽfh~+Gf# $C9>Cg|ZBg޸7p 6xo+xlujOk_.^ )_Sr~O1xkx O#Ή ^n)o}v̙:#cd̜ۛg{bhTo$ [d}xϗ -o.]}EOx#.x;| *a ~3\1svڦqW_ CW䮮A0tlкu$tہ( <0pV+ِ7 li/il$&!@ S7u n8XS_TP)3`C`5[\Y-_ĕΟ,xWٗ{͖MͶ fZp5fslG`(1H ^F9Tj ˳%yp 7x`qMB;ԃDy(H;zz3pPA]fR!ަm7zNWnxus$3ߙh:fofI=(f51S_>~'ï+ .A=; 4"<$ش(wmE:4Ur3Y],IkF.n2otdAL՘i$@:s4F1c lQ+6U!)["XT23[3yrFAX HžPa/E>^WWE5 dAuy$w+TN}Pڠ.ݛv0Tqv¶g xm݂)ы'hKvE$*w(ycv5WQQq+Ї,Qp Sw\ 튘O\+N):S٤>VGϾY/ɷsqDž"mswp U*F Zp}nv_ڵv3ps/ݱ6یPO'*S~2Bp5_l)&Ю\ @Ҽ`6-fP* vu~ݦk]:ҺQU[]cuTօ/ n7B`v 6rSZZ fmCm~c^v)X2o#,L Ou"1 >_BN)\ZWT8uJڡvqg οzP`D)Ҽ$[+b XaR pP54 1a88+>D%M(ѭSC} \ͶfGzqR4l.=)o>B>Z ǒ 呔]Ah=m k0Q$A2#p^B>!(89[m-j [18K,VJG f.]Rf@ŸQ}/Ms),Ob҆X 艣BrB[0#-6IҋRܭvU.WW )XmCͱ Gt A,LG?=VH 1MhTzlKU/w SlxG^re8E7YH+4trr\h_0'Ƚ_gtGMA}]Nciيe(6;Ig(G n54t4 `cUnہ4]p@нXh}}\G mzΎݒ̰'}Ty j$v`.Z8V7b3f5NcG^c_CY7.L#J(<y,D3jb.>Iȑ,|N/2 kj A@P$JKtz)DrPnnE5 `߂brǷ7?;Od&)0:س`۽5EmG(IwDxWoPx-uC:tJG4˻_c\ x4]*I_L _^Xw^Ee"֎ m[+^:`\KR0A}XP$)jeGVѪyjr#p)#(2~Z(hݍփeJ,xՃ-...0/I{5:>xɐ,510_GG.puK&6bKmFmOWHnv!/ap nTFa]]b'L4/4qPl)Us7:emw{]O l[tz S$Lʗd#^"<9χMfVECΏ w Lj;L*~KѾ9հ/cWyz&̛ p=%E ͧ[ЁPdxе5ʩ xAN_ڬ_ւWRO7~~ndt&PZmC+PeIϐwKd]̄ZTTlmQϠ2)omlۘZd͂@sCFa7#$#KL sl< %13x l`I926Ž{ Q*xHI@H)?<ͷ_Þ 5)H0"&FHݬM$hި~驗f\NKdl 9&$QC}]ʩ *-q47^"Rp7(eMNphsHw| MҸ5*/Bjyy>0k%xxIwfUH,՛ԛ]n48rpQYCvO7lPf xqe`) 4T\b\0hn? *+o4btgհn]zw?| vF>)=y~\"FJ@5-۴V\j~[d;ҍ݈ztB"5&l'"o@tujK#ٲv.[zj? VϷJ3B.+ZZ[#Do:wle*6J}]$HYz>@`6o޺v1@Ĺg8&fϟ $}I=PPIL@4 ƮVrⴐ8]hB(p"̰PnTʹ2ðv!/Hbz<)zR%~?>V PBY1D7)%ߟ!Ӂ<Вd.N*v4}TRgU^3!ލY,ȫ.U/v&ɖ݇(KAG#hHMs4t=8?ЂX~flྷ9 >7ŕ6 **׈Aб"m; (uz](F803eU`3p=;X|yEs c8/lcQꗂ-KMS= Q @F;njM`"yS>l ׁUvG`'I #m ="E[7)pQpmІ[b]6mU:ոnuTzĥl(Lh=x@{ű)MV-ҘywbO'2!D'&Oѡ * \8`I#f~*z/H: x!i8Gq#7 yN)H. $%d4pVʨ2ЌV3K}` tv-eyQt] s.VxFxfxkt)K”SЕ7;D@2T1w.Q֧ ; C7?混fH6|.*,Vlw."qp,p2ii~x5)BIJ;% wƎ}Iɮښ;ę<)CT'-u~5J!6O nwqxsU̕kw7J)fS|sJw  x q~K7 rxg8pśHɒG+ mA)x84 >Kl Ԥه =̭v]jXlnv/7!7@Kn< i5u[Fw}*'5D=Hk<7! ǰA`0̝ j XZj 4ڐ#fweW3+>9K.x2W0 (2K>ƞqCD.Yd'̸ Zkot\m{ީ:D pfFH:Nڏ' p :KtbpVI[@ۥH~1%ĺg7=m|e%%Z'@2;O{MmRZ[ʤn.8gO^8 lD~j!i5ԁ**2X7"`$&mn1OH.&= z-PV./iԼ |s)xA mvSZRvGG }K9::z`nA /x{8Mp[E}^ ~;#^\{vcɤ[1 mV4ƐHc~pSݨ"l4hXI j`yp:yVLtL䰒K33^ǎ~b~rjAEmdU"La/[ѯ r|BDKԬӔj֙UߖvaϢc'D{ wd|,q0>>ڲkqV)ZVC4}#IO' 6B~JdDT;PwƒeVE| o3^{Luxii \)K7po_pn9hA.5{D#EEN'ܶwx6ҹ 7Ekk5Q[;>P܂6 HM'z |cq8h$[c8l2)W Y{GM S9DqA.'' {BVB\bn[ Qq=X tN[6fVq>adU5N^(*Jxt:,.t̬5 c@M.4 *dt 5tTe@_8TNv4;<6P nZqǑC҈^ܥR5wy";t04>X<)T}7z}o8wGt'L~萘FglnynX<EϻPz +oq!$EmDyf`.Iq6`|J&M~7CByvVT\5y]1Ci2r_>8W%ٴ;r}\*@=n)o[~Rg5Ȼ=W v6qLN5.*x8FAQ_'];,}af"W^%RÕ?%U7BLբP x ډ=v˞lC[+j+ڎXB [&M٫L*@WeqV(54wjR!R Z\?b|(K7(}]QG7]}݃ٶ4?7C7T.5'"y*Ci*i -Ql?ʠK&ͩ'Q_q [Z׮?Sd $ۉѱxS:LhC٦.m4uзn"B~:vDq*.t-&)+{C?m6m"`:Vnw+NoWr4aY%: z%Xx;ѱGWjΜzK}(ZVذjƻwʑd6n kTZcDgHP8F*!RǣR P,jmZݭ=}N!#E[GGҪ97We7з5c8o[Q76i†4aCnЇHٱśa5`R!綶Ho?Ya;>}uXcn )l<k*04M-&]@A?u WB]\ّD?02-*8RH:dXj?Km8je.*\'7;{ƆO_ჺlUemmeMʜDž`rC?@RC?W+R}8ix`]J\Z ^)Ěm6Yj[BNk<@;9'a%SSgMx*B y}{*> 5Q㼗B.{9a=N"Ϲ'?୰C<!Ժ2h3tɤ+A6?=VC34p32ζ_po.-#kjTnKt׎H/Q F+aP5Ic6|Ƴ?|+8h{W4,CPALWn"/ޣ+]-᎐/w)2zT aEEKr*A߷ "bYY'("q $,@ ~BIuL/cFV#-VE`_-z;4NqEqucm[xuxm[wXۈg fT&im2ܼ''e'Rhmt4W+)HK=m; oo 5$"&MrN%y6N DŽ=Ma9١nq5xW4v˂ƕ[MKm N&H$'q FZH#+4h[(5 Io ~4FVB9ӣB[SlH-t).g3mmHGKCإAX0{DKN+'T&ΤA.\tI+WoR.ۉ09-`AOl0wCNѾc/egS)~]ˠ?VO? ^=L:T 3sg5^QT*x}5׫'j7Հ'7 ڤZč^=1SNTp'\ l {"ۘL<4 z#!?DŽR D6f󛑛ViZ䏺 ;6*jp5;Zf\4`롃`OK Uyq.ӝ> Y$l#\-ՂO!) ιj?endstream endobj 162 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 798 >> stream x-{LSgƿC9|bkͤL39/xcy[@jiz /s}yp ɵ&F'2$,1[ce;IX ><ϓ0(>1 -wSyXNXHAR2KL͋LdB鑀 .xtd.}?P\\4%Qғg S7cg9.Y+:8e,",ld5l? _\hn$DiѫF+e+^N3hZRfY n U~UQߤ oI7DBmUee%l?dY  W3=|Xj>=?C)1A \˹kUzRc|U$>N$>L|A \|WNk?V}ξ ;uJ7:3kcڟ dP } ~wP+٠PRi`I' ˤ c^\S$A)Yu FFO> stream xX XSWھɹZ5uf.LWZZk(hm\ؒ$@6''d#@X`.cZuCu:N[m۱3'gN;3? y9y~wIDTTAo\AP$;x DɟxĻ[6ff?*+TD6I\*N-TPiVB2Gh\Y..-)6767Kڲmzߦt F?Ci1w9a~BK ]h? u*EIu;UU;Q#5IYW}&ط;v\pRCs㺎!U{x/:y^$lC'П1\r-;Sȓ:=_5UVYIS_;OAީ.Rٚ2&pkhuc_vh=\(ܶcz(TͰz'K.WN;aw f J-j,2O}~[3l%GJCϾ\9VmIVQ"p-4./ Mva Bɦȷy(a8PUsUZ%G+8A)m 5X.Rql7 v2J<'2wiS-/;R@LwaN+Hx ݦ`6=9l'@f$}L u:<3,nqhA*| sZHŢTqJaH[.w}'{>1: 尜k}R}D#g>glQ>Iv89-w/^lSU&mGXB qrx_lX/9Ql/lx [_W6B2Ȯ-Y &IƤ&\}IXpΚpa->-Fo s;2Tjm5j| RT/Qt Nc8 81dl2rs'/@-h?n$}{<@CY@RPʳ35O}w[ wwWVCGS;@~_nݘ nCo<F0e_.wZmƔ%K eFH#0 ZN J[ܡpT;lԈ $QgtGnmj|oN9( mUbT)3k4bM,uIմ%& Έ*ƯI$F#g!?jlst1q] _ z[L[6ێZ,Yؿ>6w3ZH G,kUxXW}Eӭz#\M^%#. V? M \NgNf߲`a'޻v䊏X-V|˵NԘTSwm0ş?,3Aʫ8QW-J,S^P ZU?O}i5n&ߔC'] ]dg 8W{ E4bXBR$-m5MZehݹRܒSޏBxwÝhҟТoѽ쬺y܌n,n{+c"CgMgvꔯi ab{5OmPXߟQ$-&^q0@Sk#S&]źW wq~@~n>`4#D4+#4m=vC$/i󙅛~Z"F(& 7arxpd}.^ÇdvS?= gv+S'7r-tbN?ο>1?^8%h>DI6צZb?aNv׶#8$uǠF1(Y QnCR|a5 u6, p,_Mt- jfϋZ++;#%+Lu\ 莚4HT*6le7@YȾ|݈v5nwzjK D+!z}h%:nrMk2C2H.]d*5h; O@vy<6ZiRkחeJlKShDϒl7GIDmM+' 0vt?E]Wsg69B, 9-"Q隀m:Fe =oGtEB1*Ⱦ ~/ȸVK,%5nE%Xu;ߪu_(aIF1)w*J.ᶘoc>wn!>bhC0|n:{g\ZPW/E!(0$:Ģa;Df$X#& k`Y;t 3n5訒g1l넔|lwmL2#}k+#t42GRNoK-K}I=𷐝W$zcERtqyZ.PB!jns:=%rFendstream endobj 164 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 3594 >> stream xW xSe>õch59#ZPTt @AGlRBs;4I$mMNB[" U -e7YgfVg{xfOKggwr{<]{ѣ1֯/|0Ex60>:9'Κo&aDe2LU۶{|zlOŰil-6+cMK؛2)Uil%6{b46M&bd, #Y]Vcl8v49 6d1;r0h¾&j&~BI(&}:fἁ,E pρ8We=PG[ta2ui#n52D%/SDpʃfkl&}ux` 4~ C]{wO+E)&O]KRЋpVi8C9nƩ2V)ZODQ}Plkp}v /*#$UF4\d\<wo%uZK+\)JDp@Axz eKeúJO^<wϥ|^)uzPG^쿜зX 4vy=OZ=x7YJ[TA7Ÿ&@JT5x3Q/U _ ӋlW1ɯ6.[ W\|'|V`qX{u=7 8yߤ`^jj= Oߤ HE0K5;7:.(U-{N k T(RŢWp;Cv( V]-U|DPux9g6IFߥdԗ,ViQ~/L1OMPh퐅) .+& '*y}d:RԠ ԻBdv oʘ%ZWw(._)%d~H)}? kda#jx2*S K0@: K΂R7f!,$Za!V8k@8OEvaS /1 7F ~|Jp߱KS]rO -쬏q9Y .vG+?`Vͨai;!)|.W0s_CMf*lN %: <Xz#_ǫ|-b MbHA2"RDej֩hvU(M:L9(F'^Wxwr$ 6t=|66*Lp&PU؀.7>R}UTnJեo N@KtL&I(ѠT6lN=uj&_+pa @A]6Bwv:`ܱdS`Q>uqAsyb)Ïe_o` 8jd :*FS)DYܻЯr  mE1Y{KkETbbb[WF~Cwwv>vet*oxN5.cS[{H1kԪi^4IChcH'5.#2xNOxSsmC' 4;,i8;LW]/1e#;|,\S RN\݊7Z|1fA8lV[M%+`+=Jb[ 4HLeɚ1v& Gtbҁ[)KeNBUH /⮋eY(Y.%^$`4 qq&&V~g!2Yq̷8jՙ.~0REƊH%j8:sQoE3[^Ӈ4%ܺG$-ۑQz+׎(@E+.|鑉j;8 dWa\+xGC8~{O?SƓT8a>{jxa ]DM\aA9p* Uh k.3 T=vg{w3 Ҿ8zsB2!mq7@HǏW-e`]mg$5޾vWɪ̻.:*N2rν$S>GOΤM6Y֟,! ؟s)߹MH/䆽mty2GhJg ^~Q+jxob14 fYx+h&B;H)wb;=$j;ڥ-"^ VmY}`ׅl8Sл$ }N<[2yf|v'w #몋%[t!Ĭ`-ڣWՋ| @Wg.=Z|ZtXW7[[lq{`jk~kg h]Z@tHX8zPFP:P# )T\N julŕr5]ϝp2: JBHt],?2APC2!Or uُ;b< J0pЌTeRjw" mM"jUwrY@mmhh =tB /I]Ȱ9A P%(~e1gl_{ %C$Ʃ!~zDZա-fz/䀵K֯kA 1kp N/qCslh<0:v,RRroڏ NS@双2M9sy3Gm='P۫@Cꤻ 4+D86T.Nnv`wE v aOٟYpɕ_jt#AVKDW>dS0 Ffƕ7 $sa>>oAlv;p$\D꼒Gn45F-e2Zr$^mhck ?]p: FMUP%5w;VfX k]lvڬ Z<#ΖWUR^V!~]#ԃ+́NTSU44܇ 6|w1|^Z,bAcԿ 8ֳEG)5t> stream xYo/7?%@" d՞wES}O%ԝ~p){u>E ?xIfӌlF/_nlusogr;菱jg7g͌.lV2ZPQ.gW5FPLvk kNC?XrS}}/Ym5tͲ#$n9\ׁǔ Y[dS^z7waZҐM_G9T]3,;@w`h' &{y iKM鉏R{b|~#3 ]H_EqyT1Sőz#ĸ:a=1W d!?RKVd_u.}k ar`J1/zh!E\A{A]2RB%zZ2Ql[T)揥0e#S|aB1΢ᡌSF<ݣ^~EXσ$b(Z].h0*ȫ!^5eѿJ_&[8rZ"  :1ܦI~a 糯6:02iބoV>1AmVcR=sqp&jsŞMI׸.'o̸O;6ebO:|>wO/6QM≮IIWnVp܍r:T~rӮe5~{ܷ[3渽muHWT%tbp$ :jT:^,֠(j)ƭS)~2BۑPHj2zC*=-|4pd]"(qzi|HU) ThT(u]qڞ ) ;~@0x F_J)šwRH qj llۮDY6Uwk!vB92zo5.46/iii]N:eclSY!J]MP=:Q) fz#HW!vpT5rdl\R YI1)2<,Ǥ"aQB6SLqCa-Z|lneۀ]A_T"bp!'ڤB!ߏ*0<+Y?Bǰ}v[,Tg>ʄb$pPi{~UpA UNeI8wI"tVkXF9@*fSİNahM;x /]Q|4KI CH"LO4`ALKҷ<."e?Fƨ,8chBq☘Ϗ{ŚӗMR'癓RwrH+DPHӖ'>65D)X,dztї/?ଐj4CȾ (O,p+:9(I+AL'9hk_*q{Zz (@`ɤ.Lʉv&?y┏p"He"9ؓS0"NaszJ )e#R᧨m>.ٴVIsG?18plqNG.*S*IrU&GxaĉKq>h9=k Z``ݳV"p6P$,^J&3{U0iX 8VΛA>UQ)sݵ f5̑Y=`Q8ęMLqpW#ԓQWI ށg*aL:,Gu g>Ov&Q] Ql HanQo+]]ZWoZC(*du{GGJx|}롤KVO'e N+1mI.J0=f=ͩ*C 䑲l ,F]m,x?R EB^)#'1ae .L7Rn`Dgu{\#QWcq ׹$G+ ?LJw]ȸvKNNm*m7p9.uGT MkCv0hSiBAG ҦV{ urDAa;a!W3-a'(8^ŻE]́&̹OP`<\Dz0Q`_^~G&endstream endobj 166 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 714 >> stream xkHSa])c)Dh(j! ib:ia"`5' ms源3fkF" ay4E>Os"#ܟ@ "ais@OӵU;#@G!P "|ŭ:yQ֟qZ0w JN@ T%q򓦛p܍wtv"U N F^3)V8 $"=+:*,G ϤⷿvZPImFmșMӒHo3 E1n_^[YbK~ڙn %!QbwzN{'?;1p-^y,c;X8J `AE=!4Y&bPA&3ƾJf r9S'$00S>)k/ H>~*!BbsÄG{&d./=c-S0Me설gaFx.,Hj=?"Zoendstream endobj 167 0 obj << /Filter /FlateDecode /Length 192 >> stream x]M `OҰ.4FaQ ]x{ajqH>73O5 ͮ;,T;h!<$=ɺ @o|d7Tx6r#^*>y.Z;=7à*8g\D<T*"+X+6Y{46j )1EZX~w>hy_endstream endobj 168 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 568 >> stream xEkQkv(@Wq x<MmlJ[!&M6fvLI6llŃ_W_P<'o^|{0Ho3of~qcc<QxXypw󀏫gOFS+Kӵpb=,qVW"P<6Bz8G_B|dypAՈC>C' +.v1#19< 6ڪDtF<0}%2USv@-.CI%@XQSs8˂I~7_U@PTU!,l]0@K[F"N:$uP\&n$$x* [[ؕ&ic{>x(l,e<ᰫK5BFd.xg;+@ZHdV"lf'sR9ԪifZHw$*TSuVݭc\w efendstream endobj 169 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 216 >> stream xcd`ab`dddw441%2{@ΖAA%GϹ) ~xw+DM<{z >SnRgwG7GCSSCӄ֙-?ĵ-mM SvO!w߂_g3FtŒiMSZZ:Z;~V8oҜr|r\,y8"Yendstream endobj 170 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2916 >> stream xuV XS>sp_$+6+ʴD,(M40L:(_6c$>U0@_z񠡕7R,+խ-q>{}sΞ0~cD26:r3"""|?BkRs>swgw 3ksvPo֤Ĥ~|Jf(fƼD31fe™EL$YbV0+Pf,12fs-sU11fi#Qa]82hHvlu'3>}CR8cL cROKlld%W5rOZv[Ҕ4'Ta>D-p@ֿM7D"pUڝӖ.rK`eD6bEb.1>.INJ &o|a91Ĕ0E{CtqI|/IJzݻ;Y5֓4Kc2Iu펶~s7C:/)젓8-Xv5RN'TVQ0m=)>§HW×( laY4rǗSfqIT| M,_h\\ͺmW,dnKu"~J`-lmʆe@dg ް[5>'MȁriO&YzmVr]i"uP)N^OUJ;ܼ mdf+@;> D#y୼r "XhDQXP NRZuvv5.jŠtIxcxC;DYza`0DS$Lv'C20LlPTTsIִRvu@ lniQrPl+*%v4Ɨ[r{]@. 5 a(oM¡/nR6]j G Ő/#Gή .dADV%`y;z|v"!}vYbڐoq컃WjPT%Iuơ lɜLdDG|{:p,nF ]=-=@eLVn瞃i/'%Ш!L{r;FERkY{`er7(eWa$`&.dz&9m@Sh",MXu_NW*m5Pm2Vr r\>K!=6$8.#`HIiwdk3 灨pe: {?A _\aKbܕ}*+Zjv&ì'@οW`o-M<ZP,njQк:PiO:b0RJLX:oNl\SeU34Yf[WrQM[Wٸ ATlwR ̇oa/GG>Q/Š`} *Nt4s,4Y!~ z )[˚6ъʝ?bg3B&u֝)px'9Nvʨ2dM~AxHbxp^o7ù/y8ܺnGh u'E/WoJ Hs)]Isv!4pJ'k&ޯyP};eG9 v+ ;^)? q IݧpM6|No6el\ 3@{8C5p~"L̐l]j/XIMZ KaeS眃pqo]Pm.(P+LѭqYu#Nw-_RjKT'6goeQ*DRXҷ&qIuˮ>᜿ĮܞpNݜp?hȡM8Z.砽]ߚ9½^%(Q:9`1,Iދ\Fg(6)LA߻x7[a )yždRWT99!%Ui5z3dYA١~|p!E!;D@i<њ\y}AޠAFy8~7VB+gʳkm:bUݜe]*VFk ~>9.)^i˛ jZ7oݺTj. 0t±:wKk'<{N6c6n Kh$Ҫc濒!0endstream endobj 171 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 156 >> stream xcd`ab`dd v 1400q$2黲!{@Q!=?}>0c]Bs۟~}O&ђ >S{6us,]@~*}&3{ry%|r\y8T5Kendstream endobj 172 0 obj << /Filter /FlateDecode /Length 5194 >> stream x\K9rscwŚЌ=;ucფCY.=,r$;*zEP$L$c5˲,\>,~YP׺ [|Zҥ-bjyqtRӲ(^od(KN^=0 k yKt|*Vw> gV^X?up~E7觪>PmRZkj T(Fͥm:oI?9?^=KBT.rM՚i\VjaTMX !Ж<T2E:QiCjws]xa%d39k~DsΝN [.ARLf{Sw/~QG}}z=b$ WľMi5;[|&]|aRrM3[7WﵟTYFˆ%Qn zhNRpTėf).x2ieqBEi3"m]V @X]H\tv_X;1~gx0 [2>ǐ¨5,$KaG_jDk^+|h {IM%[~C<,_0=^k eśR% /FB%x262₱PlII mRЂRR!i4Pe jRBTpѮhz a`X@D-Wgh2)Q0 ݳa"[`D(tBϚ&Q,L-)057d06n8Հ8=%~2PVS+_:3PX qn9 I*hS'd .vKyctFS^=UU+,mH55ZA6'Ftw iπХ, ($K%Z0K:a:y*!wxΩJJ3u T_ΦvNQ9Fj {4Asz8Ϫ<.cs6@S>SLluS>7s* J)"uÒQN Дg(IJ~(p,S>JM(53 z,~.-ДB[g~RB7fZ"3WIXH%9cy۷Ϸ/'ȳl?@>k(up_C =/"0!sc!@S=7t GE2T8JM>&j 9E3zsC<[HY!! uƲrӈgmp s޸:9.춎荓猺8Wg %Js&zR<7<0γ >|1A3 ✵h@~uV`5E3zqΪϧμZ5Aoԍ)Q>:x>yu=p8g Sg^ O&guGEOɳ*;(5Α[QKpގ#(r۴J%9#EKQP=X;J?n&W<;攱B :QpVd#s 9]B3R)5Hu7'$}yr[G3O%~o"¸b,"|`  :@|ą{5=}N.k}&]+0Rn~?iaia@ 5CVnb""yc T: q,hk諯UnGtJvLw!HYG2!A7nQk tz@?w鐁eLHH`4bwpŝmPkJm_H޶ Ң5O vrғRߠғҰ/ThIYfD*/a׆IŖky*ZzRcKO Xoe.) YÚg40&Vֵj("Vt@2)d~ woS읈S$oa~UuO/c}zg:5H-jESu>DIT]0L𠯍Zɒs@xV8(X) ҝuoË=j?39K jXYӰ&?g-JjӚއ1:T~- G)C)`5O@=|ڞtt_'x>T_ cxpWkK{v2!_Bh*]T*[J#3r xv0W1&r>cR%`I7!kjHsfyB'ep#?? f ]EBR%a'i )LHj³hH=s(l7˺BuRϭ0ഘXNa3f[R[M !# e X%n#=V?;.4'C#li~ةŽZaPJNa\>'$jve?]NJwӚCn/f#m|6r`C'rw2)(.6*OOBxm b}x=;T=O%!cVA[IqWzPu7NMHvW k#8[(!0ʸ%&\47+JRАk-]Oo{oPqٓ)=@mnA^%LmA3#ݣS:n xrS7? ,}ҤyуKr #7ȩKt{IA'W3B9}}'$ ]î^SndWփ9c;0y?`ON'X28i`F2!H?[YJwp$q|Wo sBA%"tJ\Zxoa.n! ۗ'YK\wN<4\+}^:9dwXթtrY?!E'|4Յʯ+)1%ՀCC}YXO``<|Q^6A+``䤹,Z YXߤw!זJ8("Hl׊f{ԟ<\o#| q#q8se5y6a`Į32oQB 2e@s(p~waf'7֤WCf^uwM. HmC˝]pVk#Ұb\X6CY[SnNZ0\ %( PC{ indLHG 3"ذŚ}6N-cz H4 +|V0X* a{ǝyS56ߔo&ϾI-}78 4];{h-}iIH'nr}M]XfnͽM[Uf,I&ܥ?WQ /"<6n"{=$0_6j燛X$2o4ի2$Yev]tmmw%ϰJ}8(s|@NRo;_NcF1lwLX6&J#,X&v5RCPDᅂ _:l/ܺz{eiI- @I}w"ֵ|-m%]"aaqQendstream endobj 173 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 359 >> stream x\CMTI10VN  opPQZ-P4"&$M"'dfӽȻ_P`u$kOnTX^ZV,-Oldx #}X&zb ()OOZ`gin^rgwt{mxc~Pўn{ot‹Rkap nKr`EXQ 7 endstream endobj 174 0 obj << /Filter /FlateDecode /Length 1914 >> stream xXKoH>a fd%ı3^K`6-%АT_U$E , Mvuu=?QȦt$n'L{;jry/ٔPȘOWOM>MXF"W=IcO㇚R$*2&nSt1gfzޅ`^nlTE0 #^Y4,-bc`1p5kܐvr*OQ,ggz3ztWJt(lXUnӺNvNZ GbkkK21B1=uĕb6rBtXhbZu[RPBKwPVph~4 ^hHM/;$ݡeU۲eإ9f43BP殿|$1ِ<($GԜ$ 2)48lcaE<*/CU##N>o/zGn]1ׁ(azsn6#3ź!a:`dv歲 M`#YCIM: iiX Xp. 6ihrwr<.ޛOmUgw pP*7BH\E2ZRn4^)/&myh\-DC\^묱_$vsmcڗxİ\*ѢrjQG{Ro#vkKw=F%QAJ XW%:გ,w;l ī-mpi3اp(ѝtTg ,&mlūsQ}bLU>;0E7ç-%}sܞ:$qEz 7$x# K {m'CD:Ժٵ=ceմ:PTh:QJbzj_SJCeDER~!Mu%D2b&,jXKXYp'NHv*rC$QP˭SB;':q]Ĥh>=S{Ě- &is4G#cnt]t]U-uR01֭L`}z@-_:ͻlP@q fu)xa_:I##H[ TĴ;9A.248[Xz71GnB$~jm9;T~DTK/יEuZ9?igDi~ 4(y'Ydz ;Wn~yc?dXa vd+KnUIH;}aW8£;,sG|k۬m'Nu7]P? v5} >CՆ~H 燶BZ^ P:[;zWjf0yӴG癀Ip(r=gGdYsp;ұ/oѼNw>^Yy=xsqtKFu&'~Pb)шd/]ɭo jKlrSLDQF葉8"uSCL&jX΢h6 )u_eE.3x>!xI 4Egi<{ z{{_F[`$F2x16inֻ_?endstream endobj 175 0 obj << /Filter /FlateDecode /Length 4869 >> stream xZϏFvr"8X0bU D gWA@8 nM%d-!X^Տ,U wǛlx㍢ͿMNݻBm )Tfy;$gX֖mrye^'}SCoo%}]Ie#N4m|vmGm[]L0v}Xo~{n僝!sE_E>iуeҵ-*tr]tlo Q8JxDHtC36Hj]1d- ɾmیQb A޼T%cZ :Dzqg!m ljUq춷*`?z&YfB2ܖ_a ݆Yy V9C-dwv^F(xLeZ*r?wM ,#G"X+lR׭,T.%" xSd$'Iu: |eNv?ef7FPxr11Z{}ÎK 65p'y*9ciecd9-,R ^ QM؜ͮYrCh mcaw+.`w|EisMwTt?Ⱥ^*syI+b0jͧq돲sue¤+55*B8a̭q*Z&%yz{d2 B(=r o7[ +5ֶRm^h$&kɻj@\^_ iEyd^Oh׿@4@N/WZSw=I=$ElZ+;{!%eИ9jr@$)Qz1}3 d$(I Jhy(g2X|մqH 4T0!nKd-5mU(?֞/e8Nq8΀e|GTԬT[ʧ/JYo3/4*O*Y) ?>5\&A Anee/9e U_O/uz@ٴ$CA`loV#4 bB{7߮e2n*gg*ɡ{l*.8+v94en.2}y{F;bZyͅ)gTT*oN9 dd KϚ@: =`WF}T{,^ar.uF[șZE, X'?l@pI!^l=C5CY|s3 ˪s.f P Ha"c}j/Ưd-F!z 6|+$YC@IX1v[M;aw՛~ +^ޒI  CF1B1X'. U#D pUJ9h⸜4Vmg?s5TBX:W)[ ֔9gYiSbbU /ō,0 YLXy[bg層Ky,Su<L34W^yHnkQuSZ ;]O(M.lR,PDwa(fF̫5I~fjEki!LBƤfNvopC>HP`ϧZڢ'$"MXP${hQKv'fti5[ǖ/ӛ  ݽν:8zܥ:Ӏ|) M߇p*-mdd[TnuRCݎ3Z2}<:= Ѕ"DG^Ts!MER aAFBۜZ 'ÆWqA0DqST({/yiŠ {~DOx^z_2IG#Tf/CtQ2w"FD֡IynsVg\Y Oa3 DbB"> D T$5g(Nި3 =!1Pxfb<ڑg)*`g3έ3C,$ Y`ˮէL tIuwP` ԡ=3m )рt:,WMEʩ=φ{!k*|>F>],!K~$R|߯w-fE(#5Hg t̵F1-9`:AJyG|G9sI El8SkWt-'?DL'u=אLH,W~ bK9 5֠Aw fK 4VZ;͹y/ zOpna'VΈ@gFG.ibA:ڙ^uB`Wmi/r :BNq.l,ei \tV8W& Qdi11&@9DS cȈtEĦ(- #&T 0\c/nLx4ѠxJ0uz] ҳ;qvƫ,'J)W𮖧Y;#]J9\\kl”k^iu<(6~ lgJ%,\y_˲+kT&KA/O=cĩᕶɏA5rT6_h~Z8 5 /i(pyP;omtƾ2vwoTګsǺdtISS^ Ū$C 5P0c Ni7x/E5tex dQ3 |oC8bK'Tkf% a@|j%0~~Mkz;rP:Ġ`)>1Sz#gxwbUT;unU *۝\>mM%i1KG_/3Ty4Gz2W[ӆ1ǜʗ wRSh/U%]6wZ'‚7'/ q|xm2;|s1o7o^vfcX\H!5,eu myE,nWxe -pv?횺=<쮆po3QQӨ7HnenOpZ@QJZ.@)9Z+aG:Gڙ&0('@(B՜UVP.ˑ.yĞn .e:'?}HX;ZTU[0 1筑[WImVaR~,d]v]}DZ?a#;^8-U ^ 7F݄^_17 :NUcz0ʅJ#GUsks_!ГN !23 +.[35F4pi}/]ħ@aFPx%ľGz|SAZxXb9*һgЗB7AIyp~f hs$DmZ+ ?jv}M/pU #á^U!f5]kȚ./nه$ʪΦ7Z_W/Wbr*)%Qɾ#endstream endobj 176 0 obj << /Filter /FlateDecode /Length 3396 >> stream xYMd_rfaJ13pRN9'C>`Ah PZHCjK f{8긊w_WG_u\}$[QaY^ yj;^cfd* ˢb%^oZ&9nJ"a_+)"Mzj١l$4 v72$OQ,eqhc\$@|8f}&TLOH¥R㓧ӌ}xxͰMX,Zܾw(kphmURݻv$_I{KJ12.d+.*Z0ϓfXēV*s94v }3̂?r}W{΂u*pqgO&!/My7s_d82_P^Ѵ  jCuBvZM~Kf!9g솸]}yL7b*^!H 61f 9%C>]~Z:F!xl53=n3#|׻=`oU!H*LdXʋKY(X ! fP8q L3*hoOpח%Y(5{I Q[ b!I/A@òaCiq,DZB kW:AB*#Nt2!פb&ҒD DcH:GrqeoOU*ۀtּ6N+M6"O+ȈM3}= ȉ'cӵ/;D4RQGF"7dﭟUE$j")(St=6%GZDA³9l,((+ SQ{0T>~pdzڪ zy\~ᇎJRQQJRBt6h>O_fS s .I9rT*dաcybӺ E YvM?b؂8t^wљA ̙E6H#趡PoDy: :ofve(`O`0'vvC 4X1UHQY 0-) Ne@4kOo6кP⻺@ƺ;`@MVN {McduԀGC8L 5k_V-]\J xُ PTb0]?:@䚲o:Txdckn!a:2W-Pd^Wmy@Ȍt 8$`w$ڜ~Sp2ҹCFCO`'f!x6w|,6ʁnx=bm%!bJ$dM(=H'Ro%aesOA-ZMUʚ r6Jrꝝ(XEULi/-9PF;F`<aΎe_Ok@HҀ9/+la7͡Yw#H|Aks4Jp<гdJbfRTO9VXDauoˁ~ELĆB r ޢդԌU/ވ詝v f*_.Pi_ ۈ[6jW=ZRUq0.R{J8fkD Z}](2'GJzZn `sL}vG'(,~!YG9vv Olu=gxK8U.Uj'Oag3w=FV,*Xӄϳ,=m.Z&8JniE,].:LIqdq (ћtm+R |bk9Nzzs5%\rs׺KF`bW2V*jl(#sX8l¼<ηt!(Ij6 K&d3Xy 1醢68n=-8Rp! 7B \̻7(c%%Z܄BY Cy{$C/ab~Ԋ8Jad.P\Q9<"Ҕf57Uf dEv[lF?][#mnU(U}sI}FoF-mQ9 EU0;YϾ?~Px,+\21{?-3#b5h96zL?ܴa'Y6mcw\N/A'dr]L4_!Ƙ#;Mʁn_TFݍ"$oڪy.n*!BezAB 0##- Df2 Ι!tZ A/ۧ<A{7/ots:jRmB* `0uȳX@xvJ И' q@ٗ9D=ncg/ˍj~m/wWF%3 rfr_wnT:VQfǕJ 4 #Ջ_QwYv5)zbR$o|AE̅GEDg?<3Ȅ#YJu^%b"̨ZFK.v67x /[R3Pr%CT&L?B5#bȿ6 =ԭMd ?6(*ilZv |_cƆTb [}.o8K-+֌՟2,_pRc-90,eH1$; ٓY\)M2ߨ<%$#1/ilendstream endobj 177 0 obj << /Filter /FlateDecode /Length 3296 >> stream xZKs$s)M `ńryE  /N< ˤTf~`fU׋3?X#~c=jNӶf`ΐPI¨jig Y$cN6 F-_CWRI*p2Z)&r.JHj0Kֱ6pLQn40&T}7y_р("(5AorI[mD(Pcc:u4i3ԢnO:CC,ҦQYS،@s T0ǁitTB BE@d )#(ac07 y(' 1z.ݨy{z6h41+buxFyZ' DaE+Ji]YbUP &J;ML#"?r!EVu . $c(WK~P4+ pzpY+m#N(u%%hpk]6sb-M~3ɽ6'Aa Ցb-bKKa3(bC<`sMUP30ԎL8&ƪ>1oބSQd^$},b4Z>\hG%| =$!P!N4X˙v #*+t2Koa9SW}ƃu Z˳VjVtk^-aUkjVzY&~P@ʦ5Fk܊o 阙Y/Vv;i^P] zZ9X;/CP&sA!d`\!x"hzaPByq2 h@Rٚu͆CT}R;>^S ^YHպuE &)^j]XZdJAz%fXs # *O3;J=q`ԥj%Y< ?.XYg&rș/fJU.=1LV$^n5OFay64LU`OBۭ̓Mk'u: 2rVZt`*=Ȩ<-\4 2UKL${zͰ@ڢ7aCS4کu A:S@{ 26]B}$P\<{x€a=t]Ƅ1vݨ ]4:<8/45 w^9~ =>:\xo,dhfjYw'Jps6;62?,+YU౹ ɪӶŁq1|`c5 ؠaZ>L 0s =R+ Դy̏z DfNNP0Vq|[\H2 }r+S۸FS=n6ؠ}&ʮS(׷n'篦QAusll.A oU[.=l:wvT6 X?_?4$Gt=p̃ѤHt. T>iK4u8ְb> stream xU{pSU!m-Wcs/3DgTDQ[ }ePH$M$6ihަ-B(-* Tquta{;ވ3;s9wCD$!D"QJΪ̧'Y+Y2>U\tO mxT^_ po՜,}asͿ^.}E[G;&cבB{H3q"|9B: llCbb6abrJFN!U>qaOp[|Ekď͓~5V _=,߽lOY"kF_̨ާm2uB;qH" ^?>:WG(Y[3 *NUY i[%?k|Hxߔ9YRmӨpV/SΝ;N7Fnq.#-.JaKQh@ݨm]; .W9|sl]x_XCw]O"N_XŦVs譊ƏvF(/BF8~$~t?kot_QfVpJ.瀏>T''1k ٓg!YPS@=ND! Pؓ;/O)c9HzqR 6͆d~r%ZtQpT;LG;/n-̠vU&;*,C::Ɇd W~9| }/zLDޒF5iܰ]x##&Ε1H]kC%:A-\ymK~sfHN*i.a̒+#;ݯ5SWL4oas4(Vd- *Z5rA\. 6І ZƣR2+ nh).e~4ql$~ًgxe3-j[ơ_ /Q^&S?L"5b!5smB=~TqmRS+UV48PfZ8aI'=W~rr/Xإzᙇ>žpwDQ8L"▗RS?3 hendstream endobj 179 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 3789 >> stream xWyTמ@~WE\2h~ֽuV\ >"*H{B7{ l$$"P[ŭOSZxmَ^t~A_{3̙9WNr~gQv | bz0T !| M8a~i&P:mMzD$+[oܦG&DmKNyY--V]jEmj5Pk;Bw"5jLP㨉z;ES2ӣ"F G ~wI>7fܱjCԇ􏓄N ;~ 彽 u'xEQC9Hq*Neѩs7}[Ť>K.H03XFC3{41cwe,}eH[> ;24HC>3&aq?ՆC+E-tKU㒵T|A ̮u>ֈ)s*Џ3>/VH ri7r)TN>ᩂJ2T7_^0o ҋˎ0\ 1 tK7#aMnɞFq诼ae|i` GU: ᐯbZǑ)bՆ *bX}Ǒp5ׄC[n}J~s(vC|LfAy<,OKС2\?Egk @dy"]<;*om9j,Ζ*,IZq Xb.o^5 BoiK_ ^n }d3ꬪMZ+NۣVŔ'!>Q\I -|1u.dw<>18 'I;\q5Q4%+WisŬKi`9/ʏ$m(fԷ#zO/B)T–f6)uJQ9ndu߁뵽=$Ax59(:RV D%~RJR l7U4eP- P-Rpn_\:"XŠ`Ǡx?>jIb+PJJpJ@9uk7 ve-X:_̇2/uyBMl{vilGVV6}ΞޗޗvCg̴G>1)> פxߵ~dٟA"oii@D3ID(uW\k a~XBG)h9n>>EjbT348 @_/:%Sk^gm]}NDP4س!"~gӇ_}~f\\id+M  _uc[9EGm,wzŞH™˜-A(bX|'W"nMl8^I/ Cg캂GyIb:%@^t7es2ks=u#w7o ^#K'\rґ gZu;M?mB-O2 `3^-Ք}}{J3)K=ך;2ut:CF Ͳ*Nֿ?%d3ٌv0(1('k%щv VO4YYGYDddp{^@eQvLt"ֻ9I~2kO{ݙ:O焓G? .Wl!2M:rٞ]bnVb F]<ߟ A\h۷d yZؽ/:EI :c0`FESI/T3$EC<$%qk{#d~+ Oĺq{lp;d>_=;Y8g+XdL:VHmL%z*}yWBC|xZ-ĺNLJ{/Eي{Añ"ܧ3L+hbFrUjTJ(Fŕeb 9%pI-jC?4HEe#b<,߷ ~w㦽%˖o:{a$9cs50| m8I?\TͰ|+G*`_2%s| _d23|P"r y%2'ISJ@fElk\8+/1 o&3YcVXгOKVHq'7-]Tָ8V9 FYoQ[w}F튏w33<9 Q!s =Վ~\iD 2r1|>P d5yՄU [:,뎹[=mT%{YE*CSR HH/RGOay=ǹ_X6c0kHdJVD S@cЀ)A^-(1:i\/;=go~?#<ۄp̴2qYW_WPfaT+BFSc2endstream endobj 180 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2233 >> stream xVyp_Yx!x!ݒv4I8℔+)4A%ْ:,KlYec; 8!v CI@<$h)fv Ly;}[1!DYk̚=s؍ԅ5`ߙpN:$z=c#|Lؼexe3~MZ($^"/KerJb*1LZEIE-5/'L8\N^Q%kNVyV?Jbҽ2HRPU_G`|`?C0$~ 8eI uy\rr g-asxo N b73 IN_BK_{ngIpF3,I&h"TBv<|D}yo,ovȍKl/-Z.!ba%\g{FN]lv}<3>UB"?Zbp @eu<3Y18*!KG$hB!fJkH6!%KV&E$a--ƭJi>X<2PK%vʿ-CU9é)tzXac7#(%7ؼ#xap>-Mnynol`G%-fcSڸͻ l/yRp^}{15^پ 75}lq5얖TZ66 Z*h6{>!Y.dMDshzzd&)755~MC>}LRrQU[4*oPh$l -QOs5wx}zl{.>D Bz$掻&j ~< '#vWCUZcIsH#cՔP@I*e|\zXOEyh4Q ],ZHr)IJߚ^߾4r)xDauFR(kιyn? Sea{c<3ԏy#պdz/ .Jdr bL'WSԢi"!6{ 607q,FS?L%OgP1OWk83Õo?U] ?:<oF(L3ΧDQf:KIvK\Ӿ7[C[ iQ)m3tܪkcZA^t~kmUh→M:ֻVkL"``3D޶ϟgX%ZYa+K{+ܰhk=z=i Jv"#Oގx{@}Yl(¹992X\ja\+#?ʵ{ZH}f "ZsPQ-n>UlcuoFTF09{  Ky I42b{Y%Jǔx;ꄌ:.AqV +*'S2UEY4JF5ad19Rrc}Gr\wN[K?#i*@;cMe"N܎ϓvhmB6XԚ% ƘVm hu: v1@ !-jU5~Mp5`{{ThpNxh})0zԴR…55 736bb֜#=]g: @_-o4k591a$UnL #7?H@-(_l,&,?MԥZߠ|JW8k)^C ఙ/qu.$|J@%(S(SRʡ w&Z[T% pIL8hbAA1ջendstream endobj 181 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2535 >> stream xuVmPSW1{t]̀bo:]]pJj+E +(@ IH!I S>  oknR-jwik[[;'a{Y3gq\4SDoX1 O6t!Lr͙v/ f|̯'@vHJrdC(3t{9^"Yr.e4(d)%?3EyNϡS_x>]vTY|Avg*Hx/B$dt^驭9rG7^0g5Kx[<%?C^Bۓv{/!ܤ9< Y"Xun0 zhZ:)+b=98}&!ucx h"_.*i;>|fۋ!u\͂,>xD 5"4Y}LZjMz@lDBfЅBOvt,6Zm ;xXJb/5I;}nR _V^,4:*j$8*(TB!s諴]r<.LbXU=82SWpI3w~$ENu.׻?d0!Չ4mCɺ['/؅M'kq,=߾l`+\=zw@xQl. Ft|iDJz),,ZLN?}tyu7WkC׍s \4T۪aD}cв<)P\_Pb yEIMҮ0uvGwu6ER| l a/L] hf1 矝4VJRZ^ޖPNzwe4"&Cє#;wEvnv] ;?vaXUseSSm簳 'M-j@7FcYz5􊥜s 9h{}4%"vOv n<| :PCvˡަ#hlgAEQx&܁O\*DUENCYE_GƢ|gw)5wVK/CFqO¿ e>y<6/%aV37{ay|? OLUH@ ^!Vq^Lo, "@kՆe8$L?BיʵI$J%22L!0q`D'b`2>%8rU?CG)HAle"=ϕ]ꮫvԥhfuy|wm.</T㩫%5\ nȝul&ŘkYoUd!b0ڌ<2m^!P: s6x(r?4"sL_(s1lȍ۾|g[ SE]{Ws{dE't6SdeetȻX<Κ 4Iȹ>^D"N ̔yC^ԕwx?;&Z5}*Emendstream endobj 182 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1041 >> stream x}LSgW !$.!ư87Ȩ`P@ʀ^ʥoˇmiPvvYC3زeq8 Nrߓ<IH$V_+=}cI]k81zq^`w\K@C]XZE(Q:ltQ"GкȦAuq !%)֋ W :5P&;`!=#-546'7`Ho@^(4 bZ6Z{Ln>ܘhWq:lFS`DSRY]iڀ<{RDI/"y q:p}D2[@ʘ ]JыN/Ծ^yC $t![8ji5k/=qEiwWO<ɦP C{يޥ {>ҌN3U|,IWc n8kc[& uTCVЊv576%,kc'+/0U)y%%(2y*ђ_y#ue W0uPQ)Y#b HjjRDCj@> Uxb*ٮ91uNkik|<}c1f@goG;}6qmsTDS OR`&{]z'}SV^7(9_?3{nrc9 rlE:^0C}97l]vƁ,1N/^10Ie`-[ ;.Lz:dxatI NZďF[{ iOO17 N˕V5Ԗ*0E|V'a!Ƚ5S-bPL=d v~_`X#)LN}6QsywO8syg;@$,?? !F5FYCCIIS|l?'Nu{#̊Fendstream endobj 183 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 5003 >> stream xX XSWھ.1Bk{ֱ.cU[wEqW"@H +[B ZqmQg_3Ls3O\}~wYQŊغjKܼ,8 F;k'qb$"5k)`y HF"MZw .?9ecj2yY|1f\ #6ӉMį b+NH ≝2"XN!\b%G&kX5bkb=Gl 8D1OL & pNzuŰѩON)FTD|7:{aqj+_xnRԤKWMDd'O55)r{51Qr.ã,0O*ʸ 5jm-ve&\:kfx) $@T(+*hkp{7Zֻ Eڂ hvZ3Z>I ?q/16nO~VJ| G:L.𪨖a5SI9 [̣mx/$_h=ąkw:S 7f0p`H`.[:PJSsa/,āIͦn %R<(]Ɖ)r@hC-Ծ4S #' {=%3ʫmVfwbIpiG6_b}|@t"+AoX:h*t7qahFSIv8 ҷO_bJ a؜_K.HγEMXNe=IHX= jap} Zi%A7*Gp.[p0 \'erh@5WCf,Cc `1X| k7~sOPx- +)2z]YtqNRS"?{_Čm|Ga(ɖpjwHH%e] dЊ՞vT܏7;@U8Mٚ(JN^`=rv?cOp 0sWC/Xo%lAJ6;羉b{V4gGH6T7 pwZWp5Mi$@6>33<WHq-0;TRe*iTcjIv[]n5pCXK8jbEGb؇ZѲ񾛯|-a.\D9.|&JB:ۛ6t%ynHܹUΰaJJ/R]d)Xb߿iRtMN~2p>vج*ca5;h8r\B(#)صiiU3Wܞ9DzFFE.8UV\ġѪ,m'e[`,?8јbAJ.Fyg}rs(5{UomڮppF̀qԿTw ;ZX/aAd`_,E&]\XP/ð 7YHLک~.RzA&@0i =7uE51%JJ@_OPyjLwx ʲrB웼 *jE66ybp58p 6a8VmhJv,:9X&RyyJcV4+Z &,uJR8eA]*ZS]\mtI7#+s9cSZ*t eVqtM~[REIKVXrZވ?D.MaSb/!+J,6w#}Sn}s7yT)  GvPŗlm/z'p#*WN*]eEk-HVe(R#o4w>ᮦNsȉB'< /3r?NFs|]rkjfȤ`U|0'$oYfƙԐAө^A%Ц2=u }9vGvA=hVm4LC/pfR7b]K_1#6-~TI9^amNhΩZڴ{@SXl8~RfӖJPTVU{< lZg1PBiq\*yŁ޴MU'$x e"/˕Jh#):&4ZLV` \sdF#XaÝE+f,C_SCw&ONf=qGq 9]$$ĝn|r(gSDxQB4~aaEU6~TLV~]>n0:ju%~K33z}>!"^jUEwgM:іbgX^$)ѹ{x@MnU/PPOd|z z> yT%B-NVs7'~7rn>lǖvȐ 2Iqd"[28߷+:Ѩ9)4)W.sK6{|S&\Oj75>aO33Oú.tG.uRk7kbP8[jve.ShYy4Ѷ"[31[lWpuu+I"(K)AUC4UZo|)OtQOM09 #߇6coi*ghGM\BeU1it4Qw5q(2>n12q*)0ՔP+bWE:FG $ZQH߫ I!l},])ρ'2 '/,?=Zb+ًLYr#ڟO/!=jݴczgIg_&dw!my'"?vxU^u+3_si NF n35Ʈ۝HƾpC8 @> Ǿlu$+ku]1+XI)R1 %a!qoUHcup 7ygIi?L˶vsu9u7JF)(V<%Tv6_g7l&7pU~,f۹(;8&J&SȨHm۝Gv×~myǡI3tv?; CZ@ߺsnGQA=L7Z X%_!z*jxzJ(5:vH* W3WjN[y1R9ts_JSྮt9^CexE{!:[~ƀ?~Ŗ-Ro>SPk|OfT8la:6O';B$Pf;!34f (M-㗧dZm)lU &WYOB) \GG |OZ٦/Y*; 6\T*x jad~YԐ7z}1 =Uk>@;pͽq%"Ⱦ2:ǞmW$5qS׾tم'7;EJѪjrױ=9}98/s'z}֝5KZf0L.beRV/s2R h_{ 1P.a# H kcV9lZ^PK7DFbC~.c#I큏2"j.l)-q˰! _9]mS%x$} ƃƝt@VTd*&XK&'[t?Pe?ʴUw#ӚQIc %#M\""r1z YLkl*l.geYEeUisvKtA7D|kbST#IO~7a춦辣gN&>iԃOKWoƶJP_-cae l6&~yP;G+(-tE )>lO/:bq\OyNmXwԗc7X>M~%I<=J1^wȤLjLɶ8e;½00#*ӻE[(|"riX 5cB8!TQor0x#*h2-m ܊8ޮڎXU3B_p%'mN:h&#EB%h=P6pZ5UNjjZc&Jjp8ua":֦x`4#AoIY]8Vbc=&w]B^ e@< 5eLcWIpV]ܔ% 1?ٗ@=, ;U,784&뤐B" > S+h;M#0.{,2BW"ޭYV5K+pvO@L r,\@Q?2wgq (]q2aTk cI U'k:kOv@@ @H{rj%@bRw1#[R=M݃ƪ* 9( uwןRQ rªtm:DCO`ƄA 5endstream endobj 184 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 247 >> stream xcd`ab`dd v 640q$~L2{!{@1}ư&LV7ʮxzȃ0.-^r74nlܲq _L_:qEwNI]tp{k2wMj2oA?͓$mrޢnnTʎn[nJn}Z(dsM8丘p20dendstream endobj 185 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1892 >> stream xuUklWMIi jvghjKK6cA-joWOdExNu2˸BMRKX?ۮ \n䂓'0N]-_b;-,<ʊF'dW+"s7xa'9.7[w[8khGF:sLEYt>u"ɓ˝Gk]{8NVki'/JxIeRȗIaG 4`4VhOc"<:T%|iqYz,-[F#Q7t40:/>ď\~釙QIp 3e,3aw2I[ ('xp$ ~70|GL&1c%(܋,"WW2<-;8'jVp2+opK"DPZqLHWipP\}aiPգF*k_2TkKe5uѳ;a3LO+ƉJ/#8\Kj<ͺz{|eFϗzu晁3qC@8b7s]-K /z9>2{gEy >%ϐ %ǖKWgs'IEvYji؅*t\}.s;\K^Y,>tMf|'{:o:БHJ#6E }H_=^oGhmF@uhGHP^!RZj4+#s.0v)YɺeC٠Qa\=*eﮕ( R,'5Vs>Uo3nZ$޸' n۾RwLsLlv[svH6Y>e>9tnc=ڪXjg_䳼xڱ\ȅ#7t.yZg:>bA̤8!1IZd=  k(iIcҰN)IH0AU mst^nBB/+/Лc!Հ,ЀA0m<iuZhZ"H8u(@[9. eFC׏)q X`1KuRuᅇiq!TkFWj`簏QDendstream endobj 186 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 837 >> stream xoLSgK 6ݜb2mL$ё8u'H *T"B{[޶ R@@-,xN0Z.SFML5s>/s~JMAEnٳINIjl{[߮ ͹=,,p`ӎjJh* b"A.UA=J@ pNCj. vA2pb2 !~fՈOug&:|\wKafhNj=vtɻ ~xX+Cic]{,UQ^pgzWm᷃LaV䏧?*iwEF!f)dC)P߈la/B~EP "* `ӛFWE^U=g~m0y[=41{'w _`S[yxf[N ݌kJmf2L^{2Rþ`[xqc`DvI :DPgaVdnOѵfc@$]Y)qy+Mx7"n,zlmk7wVDƱ9X+.7n3?;j"X OcOCwӒ넏&UVj2!w܃;PxCjfձ2:,, &]anzR3%{9+6\0Y$6Ú|E @C2·$@`q2rpv}mm]>lHC=X|endstream endobj 187 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2173 >> stream x-UkTg[lvg=VZϱG-EDrk!@nF @@Dڭu [ѮVu/p֝ο9s{y?b6.z?3_B8քɢ_޸qfz"/(,Yk̬ 6` &,[%c+\,VaqBlX T?N8nP 3;,9 -Ka/Ŵ}A/@GH*N$RwK` qB}of/U٥;N!!f Gj=eX^QV-zf`\"wxHopXB8etyQόb$ƠωH$ #:Tfcgk+9'@ C=}@É֨ڠfAtaFy;~-d"1&~@p jn`qm!z;JupC S2U7NƟoHƴ#F'<++|Xݞ[*#n6RLk; xV-g?2jkH u^pܣi}5> w$_l[Z<==~4IV xYLx B*@Ce&E.3M5_@;=z`QTt'#{/&c 2!הېߑzQuH7~g^/ԓm^]!?Q8A,`OI_ԁ&pI=E&c ț|b4{'AsV@qikd}_VPg@i=V-l{m6*.#Ml?pmtݦ#7%6}:JX^"/V]^ @JP"Kd[*m׭g?pa%ztP zQr8_S/[6 \< >Ox:%I.[[aa,$ޒ'~"^$z}b)14isYCYhWOvмv$̨Gjڲ5JI=Ɉgt\>e~PRʩĐR_-K"s)$E2]GPUMAm(Bݤm!FL!t%>T'DĨwϗ 0[X `a k1fJ$*={dROW#MkkW!I#~TJEH8Z|p'c$; x^[9=ݻHc gU9]EhJkiCqt;ݘ|{~Kc'.^Bcw~ VƬ7`mq֚k5hVzR,jKW0lT'= zimoⅵ|vYF⧞*$zN\y L5\:DhPhi:9};{>Fx$5$E͌')▫_nq [-A#5GǷR`QLR AfC(Zt-Ekb{h4:xz.57izٵAPwH/iS;5؛ׁۛAOG{ ]xO"AxNW,Twh :!\9ney077Z`$e@ v)b9m@q+Ԫ3Go]yOy!&ӝitI-R̝$@n_?sK}Xg@a;JWKɗ4U*\i5P rgm^=g*54Sׄe'`Pendstream endobj 188 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2978 >> stream xuVyTw23ؖ<<ډxumv}գh"" (7$HrBD !Gt]m^*u[ۥܵ[[q_wo߾n^d~?W@M Axg/Z1;solj`&9DO:0Lɍ+(,*NMۖ=s]>YXOl qD<@Al"^"bBJ%bgWW׈׉H!~CL CKp` Bj+aDr?*ʦg8qsO:2y/Ĕ_&@p/0Q[PŌ˚(Rט-P̘T :sx諧vLM,wW5Mʞ9`-L-13 D\.N&>AFb}0IR8YZN qáᤏ\qCކ3pV>-tj5@sS;{>͎ r3r2T!z }p0HOE5;$>l,"k$8IehEfŘ#ruq`d3S<ެ!|> { 's!-TOHvQjs8f1"%OZGz[UC՘uzԸ6:=R$841͘UQ+r4$kgSP ZܼyԀ`#xoZUv5{ukk}=bM{}j{$>5_ Rkxp[R|ǝX:pѵ@bj. Pz*.Rz$Z)8S~Ng'{ڳj 5z)ЁΠKKMH{[ fwt`|7x/ xkwzn%l+ݱE)5-l {] vW"M,Os䭦@itwծ/[@U MNIDC:`xc='[w pxKZo7/*U ==޾3k,^VO=.uK}6E[(׉3**Ml\XwTR(53C>E;&J[fh55$1l̗.p&-h65{7tYʄ\M`2$*:+`}6{ƌffܻ[ zTQI *^YHс!y]qZ}b{}њ>h 1Rll Ů[B'|*0x e!|h~@]<$W9J6k;c^TUgPjY\YVK^r_A]b\C0 6؎rWu>0Y3`'SR 6!čynܞs  9)/Hsw+$f.dVfNquNs[X qWK|}/@CmdU& T1({ڸyaޡw8 ES;VQ(: Ϊr - n'Ga*> -(~WvpWB_$c g>۱ڤ7Xu|!y\L}ʮcUI/ZOɊk[;R՚RC 63NPj3#q8{Ȥn+B=ͷ/|JڪQYh+N}> Eg/g,DaoP5endstream endobj 189 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 881 >> stream x}hun9coq,"u(m'9CYo״Yվ%wiI.IvK3 eRa8u(c ˗,&@g_W[[\$l=Yxۊ̨̒(luby'(yvσ"N31]5o1; j%Y[l[I'vNjbˡ߅z#ϩ$"#Dq#v |Kz8f.Yױb:!Xg`CN&8ZI-zI5o2"^j1{:rqȇpx ӸyU/Nh(sY<;Yl%؆J[\+IAԵݵn8<*bؗF:?*/oF?c@|@V%'i!3RHpcbl=_+_꽜M]7àu̸~|sUqұDo,sFxK%d;w Nh >"w3馅M1& Qjf}Sw`Qv-6!'.'D400KrH(Φ榾Viyi*#QɈRu'sdqu|[y,6_ĦJ]K8.5ްsQusxX!#a}TЍ~^;RHǔXwo*>'~Zmnz+ك= Y7x?> stream xcd`ab`dd vsv6400q$~baaciC{@%?%Ċ!AQ |_ʸTԶ-++="۟wB} e6mmjm{LW˿~X2wJn )͝)_QUۭ>!EY3;gq-bYZvYWw tQ5W.H#Ȟߙ#WW=M8gΜ9@{o}w.]෉ʮJտ׉vk[ttsxMX&C}qrk&N0gvGDn tk?d VKYﻼnݚ5vvslf[+KZFRRX˾jQ:Ml',ї֗α{)+FXe? }*.|'Ѣ"y-_JNxr:::`ASJuwq1Od`rendstream endobj 191 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 188 >> stream xNCMR7,  <2p͋JiuP~>}L讧Ǻɋ !74/XWϡ=:4MFkgo0 7 LHsendstream endobj 192 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 900 >> stream x%oLEǯг2҇Ȓi D7mƦXYkVu@RRǎ#(cHF ! %LdqKaGWwo{]o> VBd|O{*\>+׮Ϳ4[o Ԃ=K& 3|*ה+wu/͖btϞa1&Y    &endstream endobj 193 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 212 >> stream x6CMR8vz-  T3vťbڽQ"DfVT@htkpozc,MI%ڧϋ1# :Q?f{ku؎׃$Ena}{mltNx~} 7 ZSendstream endobj 194 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 188 >> stream xcd`ab`ddds $[~gaa)_pN`db`XR繖?r3~71{'tO8Aw*}O-YX>Q{td]]g[wdݴSMT=wބ%gL6}r[w|&ߍCs10=NGendstream endobj 195 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1025 >> stream xekLUrB*KFᗙcY"l+1@nZz~Жb/ ֱ2k`dɲ1FL?zIN{7o>Qi)H$PzeS@jtL4?IeoqZJm5us[{oU&d ARpŸeZ␴bNl r 4{B871#lLlU_a9.Fy]=eP/7vrw Z-LK~?KVr>X+nIH ~0pzxHjunp 9 :L %=v*8 vs.ưpBr1g+>iJ1ʹ p;{edӪqғ'ymNg;-y«]YV/2b] +,b:μ!cŅ,Z!_6^Te\滵د~~8dlqZf9ŤTW[P5Gٓ5jڢ7;!>XNPtcK2!Oq:mrIet\= vFsgThbkyCnfF|<̰چr^A>4k0c$"eC?1MU A݇VC Bo`S(t,aش}U:6FeNhl!{HKh%1bÓwVS .. WKXqIX+/#uendstream endobj 196 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1037 >> stream xKLW1 P@NLi=}ڍ.B[UR%ET( jOc{ۘ8<&UEռHVU!]nDQuEY=wUN|䰹l޼j[ZAm%V_!]%JψfB=CǺ+~,V=%6*j[MܽV72K05+}:z):nH8)F!Rv2\pz}!gon`c@%Ȉ?J.Š@)0elXrc0׃$hieČAX \UDvd,)l4&g$ZqB|m)GCMg)fp33ٱɋZ2㭶67m=l!Dˑw>+b0 qE\!W}H#l&I@9/HJ|3h5dfN`ک',M&tȯ?6iӸ8 $eaLo[rI1G`YH44"h")R8ʲ<dr)$/% qYHr#534X?4 5i4O}X ؜nmuo}\}\=}o V`QL#8D=%bQ~&Dy5D<wɒR_y[T%)~pX|6_V@%2~{=FfGEkmkXy Ttzzs7x+B[u?R< ^(Qcx_k 65Y0#]9A+ijtr3ieE >4!{HO#0 ks顐_3u Os@WI^nY؂|xHݧ^|ʽ۔$ɲ󂞗i8=#;qJ(G*,:;jmcT]9Iv endstream endobj 197 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 342 >> stream xcd`ab`ddds$eaa~=;@1 QG/?302}n7uީ֜پf5wsl_[Z'RXZP/VՒQ2yYӧO8yH@Lygњ5{vm?ͱ~AYLHohŽ ]n0cjs_K}gKc\Ebjj7GuE&/D~ٻs\ _'|{nxwl_us1EeU1QݝM'_:InǶvs,XTZVќ%\^[K|r\,y8ȗUendstream endobj 198 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 377 >> stream xnCMMI6`d,  ijJK#Qئytpnqnr|OYY%Zu~tw|Wn~i~m~zXgy}x{XbOXy`٫ds{krlsvxi1x@PXQoq}pmufV YKExÿ‹rr~} 7 zͦHendstream endobj 199 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 142 >> stream xcd`ab`dd v 5400q$baa]H~= Pׁ? 7~H/(>GhXKdiVB~FM|w> /W [ 1 3 1 ] /Info 3 0 R /Root 2 0 R /Size 201 /ID [<186edc3f65764640aaf2781107227139>] >> stream xcb&F~0 $8J1?@6>P<9CϠz>= options(width=75) library(utils) # for R_DEFAULT_PACKAGES=NULL library(Matrix) @ \section{The Matrix class structures} \label{sec:classes} Take Martin's DSC 2007 talk to depict the Matrix class hierarchy; available from {\small \url{https://stat.ethz.ch/~maechler/R/DSC-2007_MatrixClassHierarchies.pdf}} . % ~/R/Meetings-Kurse-etc/2007-DSC/talk.tex Matrix-classes.Rnw --- --- --- %% \hrule[1pt]{\textwidth} From far, there are \textbf{three} separate class hierarchies, and every \pkg{Matrix} package matrix has an actual (or ``factual'') class inside these three hierarchies: % ~/R/Meetings-Kurse-etc/2007-DSC/Matrix-classes.Rnw More formally, we have three (\ 3 \ ) main ``class classifications'' for our Matrices, i.e.,\\ three ``orthogonal'' partitions of ``Matrix space'', and every Matrix object's class corresponds to an \emph{intersection} of these three partitions; i.e., in R's S4 class system: We have three independent inheritance schemes for every Matrix, and each such Matrix class is simply defined to \texttt{contain} three \emph{virtual} classes (one from each partitioning scheme), e.g, The three partioning schemes are \begin{enumerate} \item Content \texttt{type}: Classes \code{dMatrix}, \code{lMatrix}, \code{nMatrix}, (\code{iMatrix}, \code{zMatrix}) for entries of type \textbf{d}ouble, \textbf{l}ogical, patter\textbf{n} (and not yet \textbf{i}nteger and complex) Matrices. \code{nMatrix} only stores the \emph{location} of non-zero matrix entries (where as logical Matrices can also have \code{NA} entries!) \item structure: general, triangular, symmetric, diagonal Matrices \item sparsity: \code{denseMatrix}, \code{sparseMatrix} \end{enumerate} For example in the most used sparseMatrix class, \code{"dgCMatrix"}, the three initial letters \code{dgC} each codes for one of the three hierarchies: \begin{description} \item{d: } \textbf{d}ouble \item{g: } \textbf{g}eneral \item{C: } \textbf{C}sparseMatrix, where \textbf{C} is for \textbf{C}olumn-compressed. \end{description} Part of this is visible from printing \code{getClass("\emph{}")}: <>= getClass("dgCMatrix") @ Another example is the \code{"nsTMatrix"} class, where \code{nsT} stands for \begin{description} \item{n: } \textbf{n} is for ``patter\textbf{n}'', boolean content where only the \emph{locations} of the non-zeros need to be stored. \item{t: } \textbf{t}riangular matrix; either \textbf{U}pper, or \textbf{L}ower. \item{T: } \textbf{T}sparseMatrix, where \textbf{T} is for \textbf{T}riplet, the simplest but least efficient way to store a sparse matrix. \end{description} From R itself, via \code{getClass(.)}: <>= getClass("ntTMatrix") @ \subsection{Diagonal Matrices} \label{ssec:diagMat} The class of diagonal matrices is worth mentioning for several reasons. First, we have wanted such a class, because \emph{multiplication} methods are particularly simple with diagonal matrices. The typical constructor is \Rfun{Diagonal} whereas the accessor (as for traditional matrices), \Rfun{diag} simply returns the \emph{vector} of diagonal entries: <>= (D4 <- Diagonal(4, 10*(1:4))) str(D4) diag(D4) @ We can \emph{modify} the diagonal in the traditional way (via method definition for \Rfun{diag<-}): <>= diag(D4) <- diag(D4) + 1:4 D4 @ Note that \textbf{unit-diagonal} matrices (the identity matrices of linear algebra) with slot \code{diag = "U"} can have an empty \code{x} slot, very analogously to the unit-diagonal triangular matrices: <>= str(I3 <- Diagonal(3)) ## empty 'x' slot getClass("diagonalMatrix") ## extending "sparseMatrix" @ Originally, we had implemented diagonal matrices as \emph{dense} rather than sparse matrices. After several years it became clear that this had not been helpful really both from a user and programmer point of view. So now, indeed the \code{"diagonalMatrix"} class does also extend \code{"sparseMatrix"}, i.e., is a subclass of it. However, we do \emph{not} store explicitly where the non-zero entries are, and the class does \emph{not} extend any of the typical sparse matrix classes, \code{"CsparseMatrix"}, \code{"TsparseMatrix"}, or \code{"RsparseMatrix"}. Rather, the \code{diag()}onal (vector) is the basic part of such a matrix, and this is simply the \code{x} slot unless the \code{diag} slot is \code{"U"}, the unit-diagonal case, which is the identity matrix. Further note, e.g., from the \code{?$\,$Diagonal} help page, that we provide (low level) utility function \code{.sparseDiagonal()} with wrappers \code{.symDiagonal()} and \code{.trDiagonal()} which will provide diagonal matrices inheriting from \code{"CsparseMatrix"} which may be advantageous in \emph{some cases}, but less efficient in others, see the help page. \section{Matrix Transformations} \label{sec:trafos} \subsection{Coercions between Matrix classes} \label{ssec:coerce} You may need to transform Matrix objects into specific shape (triangular, symmetric), content type (double, logical, \dots) or storage structure (dense or sparse). Every useR should use \code{as(x, )} to this end, where \code{} is a \emph{virtual} Matrix super class, such as \code{"triangularMatrix"} \code{"dMatrix"}, or \code{"sparseMatrix"}. In other words, the user should \emph{not} coerce directly to a specific desired class such as \code{"dtCMatrix"}, even though that may occasionally work as well. Here is a set of rules to which the Matrix developers and the users should typically adhere: \begin{description} \item[Rule~1]: \code{as(M, "matrix")} should work for \textbf{all} Matrix objects \code{M}. \item[Rule~2]: \code{Matrix(x)} should also work for matrix like objects \code{x} and always return a ``classed'' Matrix. Applied to a \code{"matrix"} object \code{m}, \code{M. <- Matrix(m)} can be considered a kind of inverse of \code{m <- as(M, "matrix")}. For sparse matrices however, \code{M.} well be a \code{CsparseMatrix}, and it is often ``more structured'' than \code{M}, e.g., <>= (M <- spMatrix(4,4, i=1:4, j=c(3:1,4), x=c(4,1,4,8))) # dgTMatrix m <- as(M, "matrix") (M. <- Matrix(m)) # dsCMatrix (i.e. *symmetric*) @ \item[Rule~3]: All the following coercions to \emph{virtual} matrix classes should work:\\ \begin{enumerate} \item \code{as(m, "dMatrix")} \item \code{as(m, "lMatrix")} \item \code{as(m, "nMatrix")} \item \code{as(m, "denseMatrix")} \item \code{as(m, "sparseMatrix")} \item \code{as(m, "generalMatrix")} \end{enumerate} whereas the next ones should work under some assumptions: \begin{enumerate} \item \code{as(m1, "triangularMatrix")} \\ should work when \code{m1} is a triangular matrix, i.e. the upper or lower triangle of \code{m1} contains only zeros. \item \code{as(m2, "symmetricMatrix")} should work when \code{m2} is a symmetric matrix in the sense of \code{isSymmetric(m2)} returning \code{TRUE}. Note that this is typically equivalent to something like \code{isTRUE(all.equal(m2, t(m2)))}, i.e., the lower and upper triangle of the matrix have to be equal \emph{up to small numeric fuzz}. \end{enumerate} \end{description} \section{Session Info} <>= toLatex(sessionInfo()) @ %not yet %\bibliography{Matrix} \end{document} Matrix/inst/doc/Introduction.R0000644000175100001440000000032714576344027016100 0ustar hornikusers### R code from vignette source 'Introduction.Rnw' ################################################### ### code chunk number 1: preliminaries ################################################### options(width=75) Matrix/inst/doc/Design-issues.R0000644000175100001440000000314314576344001016130 0ustar hornikusers### R code from vignette source 'Design-issues.Rnw' ################################################### ### code chunk number 1: preliminaries ################################################### options(width=75) library(utils) # for R_DEFAULT_PACKAGES=NULL library(Matrix) ################################################### ### code chunk number 2: dgC-ex ################################################### getClass("dgCMatrix") ################################################### ### code chunk number 3: dgC-ex ################################################### getClass("ntTMatrix") ################################################### ### code chunk number 4: diag-class ################################################### (D4 <- Diagonal(4, 10*(1:4))) str(D4) diag(D4) ################################################### ### code chunk number 5: diag-2 ################################################### diag(D4) <- diag(D4) + 1:4 D4 ################################################### ### code chunk number 6: unit-diag ################################################### str(I3 <- Diagonal(3)) ## empty 'x' slot getClass("diagonalMatrix") ## extending "sparseMatrix" ################################################### ### code chunk number 7: Matrix-ex ################################################### (M <- spMatrix(4,4, i=1:4, j=c(3:1,4), x=c(4,1,4,8))) # dgTMatrix m <- as(M, "matrix") (M. <- Matrix(m)) # dsCMatrix (i.e. *symmetric*) ################################################### ### code chunk number 8: sessionInfo ################################################### toLatex(sessionInfo()) Matrix/inst/doc/Intro2Matrix.Rnw0000644000175100001440000004461614444514070016326 0ustar hornikusers\documentclass{article} % \usepackage{myVignette} \usepackage{fullpage}% save trees ;-) \usepackage[authoryear,round]{natbib} \bibliographystyle{plainnat} \newcommand{\noFootnote}[1]{{\small (\textit{#1})}} \newcommand{\myOp}[1]{{$\left\langle\ensuremath{#1}\right\rangle$}} % %%\VignetteIndexEntry{2nd Introduction to the Matrix Package} %%\VignetteDepends{Matrix,utils} \SweaveOpts{engine=R,eps=FALSE,pdf=TRUE,width=7,height=4,strip.white=true,keep.source=TRUE} % ^^^^^^^^^^^^^^^^ \title{2nd Introduction to the Matrix package} \author{Martin Maechler and Douglas Bates\\ R Core Development Team \\\email{maechler@stat.math.ethz.ch}, \email{bates@r-project.org}} \date{September 2006 ({\tiny typeset on \tiny\today})} % \begin{document} \maketitle \begin{abstract} % \emph{\Large Why should you want to work with this package and what % does it do for you?} Linear algebra is at the core of many areas of statistical computing and from its inception the \Slang{} has supported numerical linear algebra via a matrix data type and several functions and operators, such as \code{\%*\%}, \code{qr}, \code{chol}, and \code{solve}. However, these data types and functions do not provide direct access to all of the facilities for efficient manipulation of dense matrices, as provided by the Lapack subroutines, and they do not provide for manipulation of sparse matrices. The \pkg{Matrix} package provides a set of S4 classes for dense and sparse matrices that extend the basic matrix data type. Methods for a wide variety of functions and operators applied to objects from these classes provide efficient access to BLAS (Basic Linear Algebra Subroutines), Lapack (dense matrix), CHOLMOD including AMD and COLAMD and \code{Csparse} (sparse matrix) routines. One notable characteristic of the package is that whenever a matrix is factored, the factorization is stored as part of the original matrix so that further operations on the matrix can reuse this factorization. \end{abstract} %% Note: These are explained in '?RweaveLatex' : <>= options(width=75) library(utils) # for R_DEFAULT_PACKAGES=NULL @ \section{Introduction} \label{sec:Intro} The most automatic way to use the \pkg{Matrix} package is via the \Rfun{Matrix} function which is very similar to the standard \RR\ function \Rfun{matrix}, @ <>= library(Matrix) M <- Matrix(10 + 1:28, 4, 7) M tM <- t(M) @ %def Such a matrix can be appended to (using \Rfun{cbind} or \Rfun{rbind}) or indexed, <>= (M2 <- cbind(-1, M)) M[2, 1] M[4, ] @ where the last two statements show customary matrix indexing, returning a simple numeric vector each\footnote{because there's an additional default argument to indexing, \code{drop = TRUE}. If you add \hbox{``\code{\ ,\ drop = FALSE}\ ''} you will get submatrices instead of simple vectors.}. We assign 0 to some columns and rows to ``sparsify'' it, and some \code{NA}s (typically ``missing values'' in data analysis) in order to demonstrate how they are dealt with; note how we can \emph{``subassign''} as usual, for classical \RR{} matrices (i.e., single entries or whole slices at once), @ <>= M2[, c(2,4:6)] <- 0 M2[2, ] <- 0 M2 <- rbind(0, M2, 0) M2[1:2,2] <- M2[3,4:5] <- NA @ and then coerce it to a sparse matrix, @ <>= sM <- as(M2, "sparseMatrix") 10 * sM identical(sM * 2, sM + sM) is(sM / 10 + M2 %/% 2, "sparseMatrix") @ %def where the last three calls show that multiplication by a scalar keeps sparcity, as does other arithmetic, but addition to a ``dense'' object does not, as you might have expected after some thought about ``sensible'' behavior: @ <>= sM + 10 @ %def Operations on our classed matrices include (componentwise) arithmetic ($+$, $-$, $*$, $/$, etc) as partly seen above, comparison ($>$, $\le$, etc), e.g., <>= Mg2 <- (sM > 2) Mg2 @ returning a logical sparse matrix. When interested in the internal \textbf{str}ucture, \Rfun{str} comes handy, and we have been using it ourselves more regulary than \Rfun{print}ing (or \Rfun{show}ing as it happens) our matrices; alternatively, \Rfun{summary} gives output similar to Matlab's printing of sparse matrices. @ <>= str(Mg2) summary(Mg2) @ As you see from both of these, \code{Mg2} contains ``extra zero'' (here \code{FALSE}) entries; such sparse matrices may be created for different reasons, and you can use \Rfun{drop0} to remove (``drop'') these extra zeros. This should \emph{never} matter for functionality, and does not even show differently for logical sparse matrices, but the internal structure is more compact: <>= Mg2 <- drop0(Mg2) str(Mg2@x) # length 13, was 16 @ For large sparse matrices, visualization (of the sparsity pattern) is important, and we provide \Rfun{image} methods for that, e.g., <>= data(CAex, package = "Matrix") print(image(CAex, main = "image(CAex)")) # print(.) needed for Sweave @ \smallskip Further, i.e., in addition to the above implicitly mentioned \code{"Ops"} operators (\code{+}, \code{*},\dots, \code{<=},\code{>},\dots, \code{\&} which all work with our matrices, notably in conjunction with scalars and traditional matrices), the \code{"Math"}-operations (such as \Rfun{exp}, \Rfun{sin} or \Rfun{gamma}) and \code{"Math2"} (\Rfun{round} etc) and the \code{"Summary"} group of functions, \Rfun{min}, \Rfun{range}, \Rfun{sum}, all work on our matrices as they should. Note that all these are implemented via so called \emph{group methods}, see e.g., \code{?Arith} in \RR. The intention is that sparse matrices remain sparse whenever sensible, given the matrix \emph{classes} and operators involved, but not content specifically. E.g., + gives even for the rare cases where it would be advantageous to get a result. These classed matrices can be ``indexed'' (more technically ``subset'') as traditional \Slang{} (and hence \RR) matrices, as partly seen above. This also includes the idiom \code{M [ M \myOp{\mathit{op}} \myOp{\mathrm{num}}~]} which returns simple vectors, @ <>= sM[sM > 2] sml <- sM[sM <= 2] sml @ %def and \emph{``subassign''}ment similarly works in the same generality as for traditional \Slang{} matrices. %% We have seen that already above! %% This was the 2005 - Introduction vignette's first section: \subsection{\pkg{Matrix} package for numerical linear algebra} \label{ssec:intro-linalg} Linear algebra is at the core of many statistical computing techniques and, from its inception, the \Slang{} has supported numerical linear algebra via a matrix data type and several functions and operators, such as \code{\%*\%}, \code{qr}, \code{chol}, and \code{solve}. %% Initially the numerical linear algebra functions in \RR{} called underlying Fortran routines from the Linpack~\citep{Linpack} and Eispack~\citep{Eispack} libraries but over the years most of these functions have been switched to use routines from the Lapack~\citep{Lapack} library which is the state-of-the-art implementation of numerical dense linear algebra. %% Furthermore, \RR{} can be configured to use accelerated BLAS (Basic Linear Algebra Subroutines), such as those from the Atlas~\citep{Atlas} project or other ones, see the \RR~manual ``Installation and Administration''. Lapack provides routines for operating on several special forms of matrices, such as triangular matrices and symmetric matrices. Furthermore, matrix decompositions like the QR decompositions produce multiple output components that should be regarded as parts of a single object. There is some support in \RR{} for operations on special forms of matrices (e.g. the \code{backsolve}, \code{forwardsolve} and \code{chol2inv} functions) and for special structures (e.g. a QR structure is implicitly defined as a list by the \code{qr}, \code{qr.qy}, \code{qr.qty}, and related functions) but it is not as fully developed as it could be. Also there is no direct support for sparse matrices in \RR{} although \citet{koen:ng:2003} have developed the \pkg{SparseM} package for sparse matrices based on SparseKit. The \pkg{Matrix} package provides S4 classes and methods for dense and sparse matrices. The methods for dense matrices use Lapack and BLAS. The sparse matrix methods use CHOLMOD~\citep{Cholmod}, CSparse~\citep{Csparse} and other parts (AMD, COLAMD) of Tim Davis' ``SuiteSparse'' collection of sparse matrix libraries, many of which also use BLAS. \TODO{\Rfun{triu}, \Rfun{tril}, \Rfun{diag}, ... and \command{as(.,.)} , but of course only when they've seen a few different ones.} \TODO{matrix operators include \code{\%*\%}, \Rfun{crossprod}, \Rfun{tcrossprod}, \Rfun{solve}} \TODO{\Rfun{expm} is the matrix exponential ... ...} \TODO{\Rfun{symmpart} and \Rfun{skewpart} compute the symmetric part, \code{(x + t(x))/2} and the skew-symmetric part, \code{(x - t(x))/2} of a matrix \code{x}.} \TODO{factorizations include \Rfun{Cholesky} (or \Rfun{chol}), \Rfun{lu}, \Rfun{qr} (not yet for dense)} \TODO{Although generally the result of an operation on dense matrices is a dgeMatrix, certain operations return matrices of special types.} \TODO{E.g. show the distinction between \code{t(mm) \%*\% mm} and \code{crossprod(mm)}.} % \bigskip % ... ... ... The following is the old \file{Introduction.Rnw} ... FIXME ... ... \bigskip \section{Matrix Classes} The \pkg{Matrix} package provides classes for real (stored as double precision), logical and so-called ``pattern'' (binary) dense and sparse matrices. There are provisions to also provide integer and complex (stored as double precision complex) matrices. Note that in \RR, \code{logical} means entries \code{TRUE}, \code{FALSE}, or \code{NA}. To store just the non-zero pattern for typical sparse matrix algorithms, the pattern matrices are \emph{binary}, i.e., conceptually just \code{TRUE} or \code{FALSE}. In \pkg{Matrix}, the pattern matrices all have class names starting with \code{"n"} (patter\textbf{n}). \subsection{Classes for dense matrices} \label{ssec:DenseClasses} For the sake of brevity, we restrict ourselves to the \emph{real} (\textbf{d}ouble) classes, but they are paralleled by \textbf{l}ogical and patter\textbf{n} matrices for all but the positive definite ones. \begin{description} \item[dgeMatrix] Real matrices in general storage mode \item[dsyMatrix] Symmetric real matrices in non-packed storage \item[dspMatrix] Symmetric real matrices in packed storage (one triangle only) \item[dtrMatrix] Triangular real matrices in non-packed storage \item[dtpMatrix] Triangular real matrices in packed storage (triangle only) \item[dpoMatrix] Positive semi-definite symmetric real matrices in non-packed storage \item[dppMatrix] \ \ ditto \ \ in packed storage \end{description} Methods for these classes include coercion between these classes, when appropriate, and coercion to the \code{matrix} class; methods for matrix multiplication (\code{\%*\%}); cross products (\code{crossprod}), matrix norm (\code{norm}); reciprocal condition number (\code{rcond}); LU factorization (\code{lu}) or, for the \code{poMatrix} class, the Cholesky decomposition (\code{chol}); and solutions of linear systems of equations (\code{solve}). %-- mentioned above already: % Further, group methods have been defined for the \code{Arith} (basic % arithmetic, including with scalar numbers) and the \code{Math} (basic % mathematical functions) group.. Whenever a factorization or a decomposition is calculated it is preserved as a (list) element in the \code{factors} slot of the original object. In this way a sequence of operations, such as determining the condition number of a matrix then solving a linear system based on the matrix, do not require multiple factorizations of the same matrix nor do they require the user to store the intermediate results. \subsection{Classes for sparse matrices} \label{sec:SparseClasses} Used for large matrices in which most of the elements are known to be zero (or \code{FALSE} for logical and binary (``pattern'') matrices). Sparse matrices are automatically built from \Rfun{Matrix} whenever the majority of entries is zero (or \code{FALSE} respectively). Alternatively, \Rfun{sparseMatrix} builds sparse matrices from their non-zero entries and is typically recommended to construct large sparse matrices, rather than direct calls of \Rfun{new}. \TODO{E.g. model matrices created from factors with a large number of levels} \TODO{ or from spline basis functions (e.g. COBS, package \pkg{cobs}), etc.} \TODO{Other uses include representations of graphs. indeed; good you mentioned it! particularly since we still have the interface to the \pkg{graph} package. I think I'd like to draw one graph in that article --- maybe the undirected graph corresponding to a crossprod() result of dimension ca. $50^2$} \TODO{Specialized algorithms can give substantial savings in amount of storage used and execution time of operations.} \TODO{Our implementation is based on the CHOLMOD and CSparse libraries by Tim Davis.} \subsection{Representations of sparse matrices} \label{ssec:SparseReps} \subsubsection{Triplet representation (\class{TsparseMatrix})} Conceptually, the simplest representation of a sparse matrix is as a triplet of an integer vector \code{i} giving the row numbers, an integer vector \code{j} giving the column numbers, and a numeric vector \code{x} giving the non-zero values in the matrix.\footnote{For efficiency reasons, we use ``zero-based'' indexing in the \pkg{Matrix} package, i.e., the row indices \code{i} are in \code{0:(nrow(.)-1)} and the column indices \code{j} accordingly.} In \pkg{Matrix}, the \class{TsparseMatrix} class is the virtual class of all sparse matrices in triplet representation. Its main use is for easy input or transfer to other classes. As for the dense matrices, the class of the \code{x} slot may vary, and the subclasses may be triangular, symmetric or unspecified (``general''), such that the \class{TsparseMatrix} class has several\footnote{the $3 \times 3$ actual subclasses of \class{TsparseMatrix} are the three structural kinds, namely \textbf{t}riangular, \textbf{s}ymmetric and \textbf{g}eneral, times three entry classes, \textbf{d}ouble, \textbf{l}ogical, and patter\textbf{n}.} `actual'' subclasses, the most typical (numeric, general) is \class{dgTMatrix}: <>= getClass("TsparseMatrix") # (i,j, Dim, Dimnames) slots are common to all getClass("dgTMatrix") @ Note that the \emph{order} of the entries in the \code{(i,j,x)} vectors does not matter; consequently, such matrices are not unique in their representation. \footnote{ Furthermore, there can be \emph{repeated} \code{(i,j)} entries with the customary convention that the corresponding \code{x} entries are \emph{added} to form the matrix element $m_{ij}$. } %% The triplet representation is row-oriented if elements in the same row %% were adjacent and column-oriented if elements in the same column were %% adjacent. \subsubsection{Compressed representations: \class{CsparseMatrix} and \class{RsparseMatrix}} For most sparse operations we use the compressed column-oriented representation (virtual class \class{CsparseMatrix}) (also known as ``csc'', ``compressed sparse column''). Here, instead of storing all column indices \code{j}, only the \emph{start} index of every column is stored. Analogously, there is also a compressed sparse row (csr) representation, which e.g. is used in in the \pkg{SparseM} package, and we provide the \class{RsparseMatrix} for compatibility and completeness purposes, in addition to basic coercion (\code({as(., \textit{})} between the classes. %% (column-oriented triplet) except that \code{i} (\code{j}) just stores %% the index of the first element in the row (column). (There are a %% couple of other details but that is the gist of it.) These compressed representations remove the redundant row (column) indices and provide faster access to a given location in the matrix because you only need to check one row (column). There are certain advantages \footnote{routines can make use of high-level (``level-3'') BLAS in certain sparse matrix computations} to csc in systems like \RR{}, Octave and Matlab where dense matrices are stored in column-major order, therefore it is used in sparse matrix libraries such as CHOLMOD or CSparse of which we make use. For this reason, the \class{CsparseMatrix} class and subclasses are the principal classes for sparse matrices in the \pkg{Matrix} package. The Matrix package provides the following classes for sparse matrices \FIXME{many more --- maybe explain naming scheme?} \begin{description} \item[dgTMatrix] general, numeric, sparse matrices in (a possibly redundant) triplet form. This can be a convenient form in which to construct sparse matrices. \item[dgCMatrix] general, numeric, sparse matrices in the (sorted) compressed sparse column format. \item[dsCMatrix] symmetric, real, sparse matrices in the (sorted) compressed sparse column format. Only the upper or the lower triangle is stored. Although there is provision for both forms, the lower triangle form works best with TAUCS. \item[dtCMatrix] triangular, real, sparse matrices in the (sorted) compressed sparse column format. \end{description} \TODO{Can also read and write the Matrix Market and read the Harwell-Boeing representations.} \TODO{Can convert from a dense matrix to a sparse matrix (or use the Matrix function) but going through an intermediate dense matrix may cause problems with the amount of memory required.} \TODO{similar range of operations as for the dense matrix classes.} \section{More detailed examples of ``Matrix'' operations} Have seen \texttt{drop0()} above, %(p.3); only with logical showe a nice double example (where you see ``.'' and ``0''). Show the use of \code{dim<-} for \emph{resizing} a (sparse) matrix. Maybe mention \Rfun{nearPD}. \TODO{Solve a sparse least squares problem and demonstrate memory / speed gain} \TODO{mention \code{lme4} and \Rfun{lmer}, maybe use one example to show the matrix sizes.} \section{Notes about S4 classes and methods implementation} Maybe we could % even here (for R News, not only for JSS) give some glimpses of implementations at least on the \RR{} level ones? \TODO{The class hierarchy: a non-trivial tree where only the leaves are ``actual'' classes.} \TODO{The main advantage of the multi-level hierarchy is that methods can often be defined on a higher (virtual class) level which ensures consistency [and saves from ``cut \& paste'' and forgetting things]} \TODO{Using Group Methods} \section{Session Info} <>= toLatex(sessionInfo()) @ \bibliography{Matrix} \end{document} Matrix/inst/doc/Introduction.Rnw0000644000175100001440000001753412070262574016446 0ustar hornikusers\documentclass{article} \usepackage{myVignette} \usepackage[authoryear,round]{natbib} \bibliographystyle{plainnat} %%\VignetteIndexEntry{Introduction to the Matrix Package} %%\VignetteDepends{Matrix} \SweaveOpts{engine=R,eps=FALSE,pdf=TRUE,width=5,height=3,strip.white=true,keep.source=TRUE} \title{Introduction to the Matrix package --- as of Feb.~2005\footnote{ There's an unfinished ``2nd Introduction to the Matrix package'' which contains partly newer information, but is not at all self-contained. Eventually that will replace this one.}} \author{Douglas Bates\\R Core Development Group\\\email{bates@r-project.org}} \date{\today} \begin{document} \maketitle \begin{abstract} Linear algebra is at the core of many areas of statistical computing and from its inception the \Slang{} has supported numerical linear algebra via a matrix data type and several functions and operators, such as \code{\%*\%}, \code{qr}, \code{chol}, and \code{solve}. However, these data types and functions do not provide direct access to all of the facilities for efficient manipulation of dense matrices, as provided by the Lapack subroutines, and they do not provide for manipulation of sparse matrices. The \code{Matrix} package provides a set of S4 classes for dense and sparse matrices that extend the basic matrix data type. Methods for a wide variety of functions and operators applied to objects from these classes provide efficient access to BLAS (Basic Linear Algebra Subroutines), Lapack (dense matrix), TAUCS (sparse matrix) and UMFPACK (sparse matrix) routines. One notable characteristic of the package is that whenever a matrix is factored, the factorization is stored as part of the original matrix so that further operations on the matrix can reuse this factorization. \end{abstract} <>= options(width=75) @ \section{Introduction} \label{sec:Intro} Linear algebra is at the core of many statistical computing techniques and, from its inception, the \Slang{} has supported numerical linear algebra via a matrix data type and several functions and operators, such as \code{\%*\%}, \code{qr}, \code{chol}, and \code{solve}. Initially the numerical linear algebra functions in \RR{} called underlying Fortran routines from the Linpack~\citep{Linpack} and Eispack~\cite{Eispack} libraries but over the years most of these functions have been switched to use routines from the Lapack~\cite{Lapack} library. Furthermore, \RR{} can be configured to use accelerated BLAS (Basic Linear Algebra Subroutines), such as those from the Atlas~\cite{Atlas} project or Goto's BLAS~\cite{GotosBLAS}. Lapack provides routines for operating on several special forms of matrices, such as triangular matrices and symmetric matrices. Furthermore,matrix decompositions like the QR decompositions produce multiple output components that should be regarded as parts of a single object. There is some support in R for operations on special forms of matrices (e.g. the \code{backsolve}, \code{forwardsolve} and \code{chol2inv} functions) and for special structures (e.g. a QR structure is implicitly defined as a list by the \code{qr}, \code{qr.qy}, \code{qr.qty}, and related functions) but it is not as fully developed as it could be. Also there is no direct support for sparse matrices in R although \citet{koen:ng:2003} have developed a contributed package for sparse matrices based on SparseKit. The \code{Matrix} package provides S4 classes and methods for dense and sparse matrices. The methods for dense matrices use Lapack and BLAS. The sparse matrix methods use TAUCS~\citep{Taucs}, UMFPACK~\citep{Umfpack}, and Metis~\citep{Metis}. \section{Classes for dense matrices} \label{sec:DenseClasses} The \code{Matrix} package will provide classes for real (stored as double precision) and complex (stored as double precision complex) dense matrices. At present only the real classes have been implemented. These classes are \begin{description} \item[dgeMatrix] Real matrices in general storage mode \item[dsyMatrix] Symmetric real matrices in non-packed storage \item[dspMatrix] Symmetric real matrices in packed storage (one triangle only) \item[dtrMatrix] Triangular real matrices in non-packed storage \item[dtpMatrix] Triangular real matrices in packed storage (triangle only) \item[dpoMatrix] Positive semi-definite symmetric real matrices in non-packed storage \item[dppMatrix] \ \ ditto \ \ in packed storage \end{description} Methods for these classes include coercion between these classes, when appropriate, and coercion to the \code{matrix} class; methods for matrix multiplication (\code{\%*\%}); cross products (\code{crossprod}), matrix norm (\code{norm}); reciprocal condition number (\code{rcond}); LU factorization (\code{lu}) or, for the \code{poMatrix} class, the Cholesky decomposition (\code{chol}); and solutions of linear systems of equations (\code{solve}). Further, group methods have been defined for the \code{Arith} (basic arithmetic, including with scalar numbers) and the \code{Math} (basic mathematical functions) group.. Whenever a factorization or a decomposition is calculated it is preserved as a (list) element in the \code{factors} slot of the original object. In this way a sequence of operations, such as determining the condition number of a matrix then solving a linear system based on the matrix, do not require multiple factorizations of the same matrix nor do they require the user to store the intermediate results. \section{Classes for sparse matrices} \label{sec:SparseClasses} \subsection{Representations of sparse matrices} \label{ssec:SparseReps} Conceptually, the simplest representation of a sparse matrix is as a triplet of an integer vector \code{i} giving the row numbers, an integer vector \code{j} giving the column numbers, and a numeric vector \code{x} giving the non-zero values in the matrix. An S4 class definition might be \begin{Schunk} \begin{Sinput} setClass("dgTMatrix", representation(i = "integer", j = "integer", x = "numeric", Dim = "integer")) \end{Sinput} \end{Schunk} The triplet representation is row-oriented if elements in the same row were adjacent and column-oriented if elements in the same column were adjacent. The compressed sparse row (csr) (or compressed sparse column - csc) representation is similar to row-oriented triplet (column-oriented triplet) except that \code{i} (\code{j}) just stores the index of the first element in the row (column). (There are a couple of other details but that is the gist of it.) These compressed representations remove the redundant row (column) indices and provide faster access to a given location in the matrix because you only need to check one row (column). The preferred representation of sparse matrices in the SparseM package is csr. Matlab uses csc. We hope that Octave will also use this representation. There are certain advantages to csc in systems like R and Matlab where dense matrices are stored in column-major order. For example, Sivan Toledo's TAUCS~\cite{Taucs} library and Tim Davis's UMFPACK~\cite{Umfpack} library are both based on csc and can both use level-3 BLAS in certain sparse matrix computations. The Matrix package provides the following classes for sparse matrices \begin{description} \item[dgTMatrix] general, numeric, sparse matrices in (a possibly redundant) triplet form. This can be a convenient form in which to construct sparse matrices. \item[dgCMatrix] general, numeric, sparse matrices in the (sorted) compressed sparse column format. \item[dsCMatrix] symmetric, real, sparse matrices in the (sorted) compressed sparse column format. Only the upper or the lower triangle is stored. Although there is provision for both forms, the lower triangle form works best with TAUCS. \item[dtCMatrix] triangular, real, sparse matrices in the (sorted) compressed sparse column format. \end{description} \bibliography{Matrix} \end{document} Matrix/inst/doc/sparseModels.Rnw0000644000175100001440000002553414444514070016423 0ustar hornikusers\documentclass{article} % \usepackage{fullpage} \usepackage{myVignette} \usepackage[authoryear,round]{natbib} \bibliographystyle{plainnat} \newcommand{\noFootnote}[1]{{\small (\textit{#1})}} \newcommand{\myOp}[1]{{$\left\langle\ensuremath{#1}\right\rangle$}} %%\VignetteIndexEntry{Sparse Model Matrices} %%\VignetteDepends{Matrix,MASS,datasets,grDevices,stats,utils} \title{Sparse Model Matrices} \author{Martin Maechler\\ R Core Development Team \\\email{maechler@R-project.org}} \date{July 2007, 2008 ({\tiny typeset on \tiny\today})} % \begin{document} \maketitle \SweaveOpts{engine=R, keep.source=TRUE} \SweaveOpts{eps=FALSE, pdf=TRUE, width=8, height=5.5, strip.white=true} \setkeys{Gin}{width=\textwidth} % \begin{abstract} % ............................ FIXME % \end{abstract} %% Note: These are explained in '?RweaveLatex' : <>= options(width=75) library(grDevices) # for R_DEFAULT_PACKAGES=NULL library(stats) # ditto library(utils) # ditto @ \section*{Introduction} Model matrices in the very widely used (generalized) linear models of statistics, (typically fit via \Rfun{lm} or \Rfun{glm} in \RR) are often practically sparse --- whenever categorical predictors, \code{factor}s in \RR, are used. %% FIXME: Introduce lm.fit.sparse() or not ? We show for a few classes of such linear models how to construct sparse model matrices using sparse matrix (S4) objects from the \pkg{Matrix} package, and typically \emph{without} using dense matrices in intermediate steps. %% only the latter is really novel, since "SparseM" (and others) %% have used the equivalent of %% as( model.matrix(.....), "sparseMatrix") \section{One factor: \texttt{y $\sim$ f1}} Let's start with an artifical small example: <>= (ff <- factor(strsplit("statistics_is_a_task", "")[[1]], levels=c("_",letters))) factor(ff) # drops the levels that do not occur f1 <- ff[, drop=TRUE] # the same, more transparently @ and now assume a model $$y_i = \mu + \alpha_{j(i)} + E_i,$$ for $i=1,\dots,n =$~\code{length(f1)}$= 20$, and $\alpha_{j(i)}$ with a constraint such as $\sum_j \alpha_j = 0$ (``sum'') or $\alpha_1 = 0$ (``treatment'') and $j(i) =$\code{as.numeric(f1[i])} being the level number of the $i$-th observation. For such a ``design'', the model is only estimable if the levels \code{c} and \code{k} are merged, and <>= levels(f1)[match(c("c","k"), levels(f1))] <- "ck" library(Matrix) Matrix(contrasts(f1)) # "treatment" contrasts by default -- level "_" = baseline Matrix(contrasts(C(f1, sum))) Matrix(contrasts(C(f1, helmert)), sparse=TRUE) # S-plus default; much less sparse @ where \Rfun{contrasts} is (conceptually) just one major ingredient in the well-known \Rfun{model.matrix} function to build the linear model matrix $\mathbf{X}$ of so-called ``dummy variables''. %% Since 2007, the \pkg{Matrix} package has been providing coercion from a \code{factor} object to a \code{sparseMatrix} one to produce the transpose of the model matrix corresponding to a model with that factor as predictor (and no intercept): <>= as(f1, "sparseMatrix") @ which is really almost the transpose of using the above sparsification of \Rfun{contrasts} (and arranging for nice printing), <>= printSpMatrix( t( Matrix(contrasts(f1))[as.character(f1) ,] ), col.names=TRUE) @ and that is the same as the ``sparsification'' of \Rfun{model.matrix}, apart from the column names (here transposed), <>= t( Matrix(model.matrix(~ 0+ f1))) # model with*OUT* intercept @ A more realistic small example is the \code{chickwts} data set, <>= data(chickwts, package = "datasets") str(chickwts)# a standard R data set, 71 x 2 x.feed <- as(chickwts$feed, "sparseMatrix") x.feed[ , (1:72)[c(TRUE,FALSE,FALSE)]] ## every 3rd column: @ % FIXME: Move this to ../../../MatrixModels/inst/doc/ ??? % ## Provisional (hence unexported) sparse lm.fit(): % Matrix:::lm.fit.sparse(x = t(x.feed), y = chickwts[,1]) %- for emacs: $ \section{One factor, one continuous: \texttt{y $\sim$ f1 + x}} To create the model matrix for the case of one factor and one continuous predictor---called ``analysis of covariance'' in the historical literature--- we can adopt the following simple scheme. %% Possible examples: %% - Puromycin %% - ToothGrowth %--- FIXME --- The final model matrix is the concatenation of: 1) create the sparse 0-1 matrix \code{m1} from the f1 main-effect 2) the single row/column 'x' == 'x' main-effect 3) replacing the values 1 in \code{m1@x} (the x-slot of the factor model matrix), by the values of \code{x} (our continuous predictor). \section{Two (or more) factors, main effects only: \texttt{y $\sim$ f1 + f2}} %% FIXME: 'warpbreaks' is smaller and more natural as fixed effect model! Let us consider the \code{warpbreaks} data set of 54 observations, <>= data(warpbreaks, package = "datasets") # a standard R data set str(warpbreaks) # 2 x 3 (x 9) balanced two-way with 9 replicates: xtabs(~ wool + tension, data = warpbreaks) @ %It is \emph{not} statistically sensible to assume that \code{Run} is a %fixed effect, however the example is handy to depict how a model matrix This example depicts how a model matrix would be built for the model \code{breaks ~ wool + tension}. Since this is a main effects model (no interactions), the desired model matrix is simply the concatenation of the model matrices of the main effects. There are two here, but the principle applies to general main effects of factors. The most sparse matrix is reached by \emph{not} using an intercept, (which would give an all-1-column) but rather have one factor fully coded (aka ``swallow'' the intercept), and all others being at \code{"treatment"} contrast, i.e., here, the \emph{transposed} model matrix, \code{tmm}, is <>= tmm <- with(warpbreaks, rbind(as(tension, "sparseMatrix"), as(wool, "sparseMatrix")[-1,,drop=FALSE])) print( image(tmm) ) # print(.) the lattice object @ \\ The matrices are even sparser when the factors have more than just two or three levels, e.g., for the morley data set, <>= data(morley, package = "datasets") # a standard R data set morley$Expt <- factor(morley$Expt) morley$Run <- factor(morley$Run) str(morley) t.mm <- with(morley, rbind(as(Expt, "sparseMatrix"), as(Run, "sparseMatrix")[-1,])) print( image(t.mm) ) # print(.) the lattice object @ %% Also see Doug's E-mail to R-help % From: "Douglas Bates" % Subject: Re: [R] Large number of dummy variables % Date: Mon, 21 Jul 2008 18:07:26 -0500 \section{Interactions of two (or more) factors,.....} %% Of course, this is *the* interesting part %% To form interactions, we would have to ``outer-multiply'' %% the single-factor model-matrices (after "[, -1]") In situations with more than one factor, particularly with interactions, the model matrix is currently not directly available via \pkg{Matrix} functions --- but we still show to build them carefully. The easiest---but not at memory resources efficient---way is to go via the dense \Rfun{model.matrix} result: <>= data(npk, package = "MASS") npk.mf <- model.frame(yield ~ block + N*P*K, data = npk) ## str(npk.mf) # the data frame + "terms" attribute m.npk <- model.matrix(attr(npk.mf, "terms"), data = npk) class(M.npk <- Matrix(m.npk)) dim(M.npk)# 24 x 13 sparse Matrix t(M.npk) # easier to display, column names readably displayed as row.names(t(.)) @ %% printSpMatrix(M.npk, col.names = "abb1") Another example was reported by a user on R-help (July 15, 2008, {\small \url{https://stat.ethz.ch/pipermail/r-help/2008-July/167772.html}}) about an ``aov error with large data set''. \begin{citation} % RAS: in my PDF, I don't see the first character I I'm looking to analyze a large data set: a within-Ss 2*2*1500 design with 20 Ss. However, aov() gives me an error. %, reproducible as follows: \end{citation} And gave the following code example (slightly edited): <>= id <- factor(1:20) a <- factor(1:2) b <- factor(1:2) d <- factor(1:1500) aDat <- expand.grid(id=id, a=a, b=b, d=d) aDat$y <- rnorm(length(aDat[, 1])) # generate some random DV data dim(aDat) # 120'000 x 5 (120'000 = 2*2*1500 * 20 = 6000 * 20) @ %% ^^^^^^^ MM: "fix" and generate much more interesting data and then continued with \begin{Sinput} m.aov <- aov(y ~ a*b*d + Error(id/(a*b*d)), data=aDat) \end{Sinput} \begin{citation}\sffamily which yields the following error:\\ \ttfamily Error in model.matrix.default(mt, mf, contrasts) :\\ allocMatrix: too many elements specified\\ \end{citation} to which he got the explanation by Peter Dalgaard that the formal model matrix involved was much too large in this case, and that PD assumed, \pkg{lme4} would be able to solve the problem. However, currently there would still be a big problem with using \pkg{lme4}, because of the many levels of \emph{fixed} effects: Specifically\footnote{the following is not run in \RR\ on purpose, rather just displayed here}, \begin{Sinput} dim(model.matrix( ~ a*b*d, data = aDat)) # 120'000 x 6000 \end{Sinput} where we note that $120'000 \times 6000 = 720 \textrm{mio}$, which is $720'000'000 * 8 / 2^{20} \approx 5500$ Megabytes. \emph{Unfortunately} \pkg{lme4} does \emph{not} use a sparse $X$-matrix for the fixed effects (yet), it just uses sparse matrices for the $Z$-matrix of random effects and sparse matrix operations for computations related to $Z$. Let us use a smaller factor \code{d} in order to investigate how sparse the $X$ matrix would be: <>= d2 <- factor(1:150) # 10 times smaller tmp2 <- expand.grid(id=id, a=a, b=b, d=d2) dim(tmp2) dim(mm <- model.matrix( ~ a*b*d, data=tmp2)) ## is 100 times smaller than original example class(smm <- Matrix(mm)) # automatically coerced to sparse round(object.size(mm) / object.size(smm), 1) @ shows that even for the small \code{d} here, the memory reduction would be more than an order of magnitude. \\ %% Reasons to fake here: %% 1) print() is needed for lattice -- but looks ugly, %% 2) the resulting pdf file is too large -- use png instead: <>= image(t(smm), aspect = 1/3, lwd=0, col.regions = "red") <>= png("sparseModels-X-sparse-image.png", width=6, height=3, units='in', res=150) print( <> ) dev.off() @ %%--NB: 'keep.source=FALSE' above is workaround-a-bug-in-R-devel-(2.13.x)--- \par\vspace*{-1ex} \centerline{% \includegraphics[width=1.1\textwidth]{sparseModels-X-sparse-image.png}} and working with the sparse instead of the dense model matrix is considerably faster as well, <>= x <- 1:600 system.time(y <- smm %*% x) ## sparse is much faster system.time(y. <- mm %*% x) ## than dense identical(as.matrix(y), y.) ## TRUE @ <>= toLatex(sessionInfo()) @ \end{document} Matrix/inst/doc/Intro2Matrix.R0000644000175100001440000000500014576344013015745 0ustar hornikusers### R code from vignette source 'Intro2Matrix.Rnw' ################################################### ### code chunk number 1: preliminaries ################################################### options(width=75) library(utils) # for R_DEFAULT_PACKAGES=NULL ################################################### ### code chunk number 2: ex1 ################################################### library(Matrix) M <- Matrix(10 + 1:28, 4, 7) M tM <- t(M) ################################################### ### code chunk number 3: ex2 ################################################### (M2 <- cbind(-1, M)) M[2, 1] M[4, ] ################################################### ### code chunk number 4: set0 ################################################### M2[, c(2,4:6)] <- 0 M2[2, ] <- 0 M2 <- rbind(0, M2, 0) M2[1:2,2] <- M2[3,4:5] <- NA ################################################### ### code chunk number 5: asSparse ################################################### sM <- as(M2, "sparseMatrix") 10 * sM identical(sM * 2, sM + sM) is(sM / 10 + M2 %/% 2, "sparseMatrix") ################################################### ### code chunk number 6: add1 ################################################### sM + 10 ################################################### ### code chunk number 7: Comp1 ################################################### Mg2 <- (sM > 2) Mg2 ################################################### ### code chunk number 8: str_mat ################################################### str(Mg2) summary(Mg2) ################################################### ### code chunk number 9: drop0 ################################################### Mg2 <- drop0(Mg2) str(Mg2@x) # length 13, was 16 ################################################### ### code chunk number 10: image ################################################### data(CAex, package = "Matrix") print(image(CAex, main = "image(CAex)")) # print(.) needed for Sweave ################################################### ### code chunk number 11: sub_logi ################################################### sM[sM > 2] sml <- sM[sM <= 2] sml ################################################### ### code chunk number 12: Tsparse-class ################################################### getClass("TsparseMatrix") # (i,j, Dim, Dimnames) slots are common to all getClass("dgTMatrix") ################################################### ### code chunk number 13: sessionInfo ################################################### toLatex(sessionInfo()) Matrix/inst/doc/SuiteSparse/0000755000175100001440000000000014576343415015541 5ustar hornikusersMatrix/inst/doc/SuiteSparse/CAMD/0000755000175100001440000000000014576343415016245 5ustar hornikusersMatrix/inst/doc/SuiteSparse/CAMD/README.txt0000644000175100001440000001464614552026002017736 0ustar hornikusersCAMD, Copyright (c) 2007-2022, Timothy A. Davis, Yanqing Chen, Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. SPDX-License-Identifier: BSD-3-clause CAMD: a set of routines for permuting sparse matrices prior to factorization. Includes a version in C, a version in Fortran, and a MATLAB mexFunction. Requires SuiteSparse_config, in the ../SuiteSparse_config directory relative to this directory. Quick start (Linux or MacOSX): To compile and install the library for system-wide usage: make sudo make install To compile/install for local usage (SuiteSparse/lib and SuiteSparse/include) make local make install To run the demos make demos Quick start (for MATLAB users); To compile, test, and install the CAMD mexFunction, cd to the CAMD/MATLAB directory and type camd_make at the MATLAB prompt. ------------------------------------------------------------------------------- CAMD License: refer to CAMD/Doc/License.txt Availability: http://www.suitesparse.com ------------------------------------------------------------------------------- This is the CAMD README file. It is a terse overview of CAMD. Refer to the User Guide (Doc/CAMD_UserGuide.pdf) for how to install and use CAMD. Description: CAMD is a set of routines for pre-ordering sparse matrices prior to Cholesky or LU factorization, using the approximate minimum degree ordering algorithm with optional ordering constraints. Written in ANSI/ISO C with a MATLAB interface. Authors: Timothy A. Davis (DrTimothyAldenDavis@gmail.com) Patrick R. Amestory, ENSEEIHT, Toulouse, France. Iain S. Duff, Rutherford Appleton Laboratory, UK. Acknowledgements: This work was supported by the National Science Foundation, under grants DMS-9504974, DMS-9803599, and CCR-0203270. Portions of this work were done while on sabbatical at Stanford University and Lawrence Berkeley National Laboratory (with funding from the SciDAC program). I would like to thank Gene Golub, Esmond Ng, and Horst Simon for making this sabbatical possible. ------------------------------------------------------------------------------- Files and directories in the CAMD distribution: ------------------------------------------------------------------------------- --------------------------------------------------------------------------- Subdirectories of the CAMD directory: --------------------------------------------------------------------------- Doc documentation Source primary source code Include include file for use in your code that calls CAMD Demo demo programs. also serves as test of the CAMD installation. MATLAB CAMD mexFunction for MATLAB, and supporting m-files build where the compiled libraries and demos are placed Config source file to construct camd.h --------------------------------------------------------------------------- Files in the CAMD directory: --------------------------------------------------------------------------- Makefile a very simple Makefile (optional); just for simplifying cmake CMakeLists.txt cmake script for building CAMD README.txt this file --------------------------------------------------------------------------- Doc directory: documentation --------------------------------------------------------------------------- ChangeLog change log License.txt the CAMD License Makefile for creating the documentation CAMD_UserGuide.bib CAMD User Guide (references) CAMD_UserGuide.tex CAMD User Guide (LaTeX) CAMD_UserGuide.pdf CAMD User Guide (PDF) docdiff tools for comparing CAMD with AMD cdiff camd.sed --------------------------------------------------------------------------- Source directory: --------------------------------------------------------------------------- camd_order.c user-callable, primary CAMD ordering routine camd_control.c user-callable, prints the control parameters camd_defaults.c user-callable, sets default control parameters camd_info.c user-callable, prints the statistics from CAMD camd_1.c non-user-callable, construct A+A' camd_2.c user-callable, primary ordering kernel (a C version of camd.f and camdbar.f, with post-ordering added) camd_aat.c non-user-callable, computes nnz (A+A') camd_dump.c non-user-callable, debugging routines camd_postorder.c non-user-callable, postorder camd_valid.c non-user-callable, verifies a matrix camd_preprocess.c non-user-callable, computes A', removes duplic camd_l* same as above, but with int64_t integers --------------------------------------------------------------------------- Include directory: --------------------------------------------------------------------------- camd.h include file for C programs that use CAMD camd_internal.h non-user-callable, include file for CAMD --------------------------------------------------------------------------- Demo directory: --------------------------------------------------------------------------- Makefile to compile the demos camd_demo.c C demo program for CAMD camd_demo.out output of camd_demo.c camd_demo2.c C demo program for CAMD, jumbled matrix camd_demo2.out output of camd_demo2.c camd_l_demo.c C demo program for CAMD (int64_t version) camd_l_demo.out output of camd_l_demo.c camd_simple.c simple C demo program for CAMD camd_simple.out output of camd_simple.c --------------------------------------------------------------------------- MATLAB directory: --------------------------------------------------------------------------- Contents.m for "help camd" listing of toolbox contents camd.m MATLAB help file for CAMD camd_make.m MATLAB m-file for compiling CAMD mexFunction camd_install.m compile and install CAMD mexFunctions camd_mex.c CAMD mexFunction for MATLAB camd_demo.m MATLAB demo for CAMD camd_demo.m.out diary output of camd_demo.m can_24.mat input file for CAMD demo --------------------------------------------------------------------------- build directory: libcamd.a and libcamd.so library placed here --------------------------------------------------------------------------- .gitignore only file in the original distribution Matrix/inst/doc/SuiteSparse/CAMD/Doc/0000755000175100001440000000000014576343415016752 5ustar hornikusersMatrix/inst/doc/SuiteSparse/CAMD/Doc/ChangeLog0000644000175100001440000000736714552026002020521 0ustar hornikusersJan 10, 2024: version 3.3.1 * minor updates to build system Dec 30, 2023: version 3.3.0 * major change to build system: by Markus Mützel * revised test for integer overflow: for CHOLMOD 5.1.0 tests * camd_version: added to return version of CAMD Sept 18, 2023: version 3.2.1 * cmake update: add "None" build type, from Antonio Rojas, for Arch Linux Sept 8, 2023: version 3.2.0 * cmake updates: SuiteSparse:: namespace by Markus Muetzel June 16, 2023: version 3.0.4 * cmake build system updates: update by Markus Muetzel Jan 17, 2023: version 3.0.3 * SuiteSparse_config: now v7.0.0 Dec 9, 2022: version 3.0.2 * minor change to build system Nov 12, 2022: version 3.0.0 * using CMake build system * integers: int (32-bit) and SuiteSparse_long (nominally 64-bit) replaced with int32_t and int64_t. May 4, 2016: version 2.4.6 * minor changes to Makefile Apr 1, 2016: version 2.4.5 * licensing simplified (no other change); refer to CAMD/Doc/License.txt Feb 1, 2016: version 2.4.4 * update to Makefiles Jan 30, 2016: version 2.4.3 * modifications to Makefiles Jan 1, 2016: version 2.4.2 * modified Makefile to create shared libraries No change to C code except version number Oct 10, 2014: version 2.4.1 modified MATLAB/camd_make.m. No change to C code except version number. July 31, 2013: version 2.4.0 * changed malloc and printf pointers to use SuiteSparse_config Jun 20, 2012: verison 2.3.1 * minor update for Windows (removed filesep) Jun 1, 2012: version 2.3.0 * changed from UFconfig to SuiteSparse_config May 15, 2012: version 2.2.4 * minor fix to SIZE_T_MAX definition (finicky compiler workaround) Dec 7, 2011: version 2.2.3 * fixed the Makefile to better align with CFLAGS and other standards Jan 25, 2011: version 2.2.2 * minor fix to "make install" Nov 30, 2009: version 2.2.1 * added "make install" and "make uninstall" May 31, 2007: version 2.2.0 * port to 64-bit MATLAB * Makefile moved from Source/ to Lib/ Dec 12, 2006, v2.1.3 * minor MATLAB cleanup Sept 28, 2006, v2.1.2 * #define SIZE_T_MAX not done if already defined (Mac OSX). Aug 31, 2006: v2.1.1 * trivial change to comments in camd.m June 27, 2006: CAMD Version 2.1 * bug fix. Ordering constraints not always met if dense and/or empty nodes are present in the matrix. Apr. 30, 2006: CAMD Version 2.0 * CAMD released, based on AMD v2.0. To compare the two codes, type the command ./docdiff in this directory (the "CAMD" and "camd" strings are replaced with "AMD" and "amd" when the two packages are compared, to make more evident the substantive differences between the packages). Primary differences with AMD v2.0: CAMD adds the ability to order the matrix with constraints. Each node i in the graph (row/column i in the matrix) has a constraint, C[i], which is in the range 0 to n-1. All nodes with C[i] = 0 are ordered first, followed by all nodes with constraint 1, and so on. That is, C[P[k]] is monotonically non-decreasing as k varies from 0 to n-1. camd_order has an additional C parameter; if NULL, no constraints are used (the ordering will be similar to AMD's ordering). The optional C parameter is also added to the MATLAB interface, p = camd (A,Control,C). Since the C parameter is optional, CAMD can replace AMD in any application that uses AMD. Just pass C = NULL (or omit C in the MATLAB interface). There is no Fortran version of CAMD, however. The postordering is different, and there is no camd_post_tree.c file. A new routine, camd_cvalid, has been added to check the validity of C. CAMD requires more workspace than AMD (n+1 integers). All user-visible names AMD* and amd* replaced with CAMD* and camd*. Matrix/inst/doc/SuiteSparse/CAMD/Doc/License.txt0000644000175100001440000000372314552026002021062 0ustar hornikusersCAMD, Copyright (c) by Timothy A. Davis, Yanqing Chen, Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. CAMD is available under alternate licenses, contact T. Davis for details. Availability: http://www.suitesparse.com ------------------------------------------------------------------------------- CAMD License: BSD 3-clause: ------------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the organizations to which the authors are affiliated, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Matrix/inst/doc/SuiteSparse/ChangeLog0000644000175100001440000010707314561103552017311 0ustar hornikusersJan 20, 2024: version 7.6.0 * CHOLMOD 5.2.0: bug fix (restore ABI compatibility with 5.0.x, i.e., 5.2.0 is ABI incompatible to 5.1.x) * SuiteSparse_config 7.6.0, Mongoose 3.3.2, COLAMD 3.3.2, CCOLAMD 3.3.2: port Makefile to Windows * SPQR 4.3.2: remove unused parameters * LAGraph 1.1.2, CSparse 4.3.1, ParU 0.1.2, GraphBLAS 9.0.1: minor updates to build system * Example 1.6.2, UMFPACK 6.3.2, KLU 2.3.2, SuiteSparse_Mongoose 3.3.2, SPEX 2.3.2: revise version numbers of dependent packages * AMD, BTF, CAMD, CXSparse, LDL, RBio: unchanged * Package versions in this release: SuiteSparse_config 7.6.0 AMD 3.3.1 BTF 2.3.1 CAMD 3.3.1 CCOLAMD 3.3.2 CHOLMOD 5.2.0 COLAMD 3.3.2 CSparse 4.3.1 CXSparse 4.3.1 Example 1.6.2 GraphBLAS 9.0.1 KLU 2.3.2 LDL 3.3.1 LAGraph 1.1.2 SuiteSparse_Mongoose 3.3.2 ParU 0.1.2 RBio 4.3.1 SPEX 2.3.2 SPQR 4.3.2 UMFPACK 6.3.2 Jan 12, 2024: version 7.5.1 * SuiteSparse_config: bug fix to SUITESPARSE__VERCODE macro. * Example 1.6.1: add tests for *__VERSION macros. * Package versions in this release: SuiteSparse_config 7.5.1 AMD 3.3.1 BTF 2.3.1 CAMD 3.3.1 CCOLAMD 3.3.1 CHOLMOD 5.1.1 COLAMD 3.3.1 CSparse 4.3.0 CXSparse 4.3.1 Example 1.6.1 GraphBLAS 9.0.0 KLU 2.3.1 LDL 3.3.1 LAGraph 1.1.1 SuiteSparse_Mongoose 3.3.1 ParU 0.1.1 RBio 4.3.1 SPEX 2.3.1 SPQR 4.3.1 UMFPACK 6.3.1 Jan 10, 2024: version 7.5.0 * SuiteSparse_config: 7.5.0, to reflect the addition of GraphBLAS 9.0.0. Minor updates to build system, including bug fixes when specifying a specific BLAS/LAPACK library, and configuration of *.pc files. * GraphBLAS 9.0.0: supporting the v2.1 C API; see https://github.com/GraphBLAS/graphblas-api-c * Example 1.6.0: using GraphBLAS 9.0.0 and SuiteSparse_config 7.5.0, remove explicit dependencies on OpenMP, libm, GMP, and MPFR. Add programs to test the *Config.cmake of each package. * All other packages (except CSparse): minor updates to build system and MATLAB interfaces * Package versions in this release: SuiteSparse_config 7.5.0 AMD 3.3.1 BTF 2.3.1 CAMD 3.3.1 CCOLAMD 3.3.1 CHOLMOD 5.1.1 COLAMD 3.3.1 CSparse 4.3.0 (unchanged from SuiteSparse 7.4.0) CXSparse 4.3.1 Example 1.6.0 GraphBLAS 9.0.0 KLU 2.3.1 LDL 3.3.1 LAGraph 1.1.1 SuiteSparse_Mongoose 3.3.1 ParU 0.1.1 RBio 4.3.1 SPEX 2.3.1 SPQR 4.3.1 UMFPACK 6.3.1 Dec 30, 2023: version 7.4.0 * major change to build system: by Markus Mützel. Includes a top-level CMakeLists.txt that builds all packages, and support for pkg-config. Default location of files is now listed below, where PACKAGE is one of the packages in SuiteSparse: * CMAKE_INSTALL_PREFIX/include/suitesparse: include files * CMAKE_INSTALL_PREFIX/lib: compiled libraries * CMAKE_INSTALL_PREFIX/lib/cmake/SuiteSparse: helper *.cmake scripts for all of SuiteSparse * CMAKE_INSTALL_PREFIX/lib/cmake/PACKAGE: *Config.cmake scripts for a specific package * CMAKE_INSTALL_PREFIX/lib/pkgconfig/PACKAGE.pc: *.pc pkg-config files with information for a specific package Additional changes are listed below. * LAGraph 1.1.0: new package: graph algorithms based on GraphBLAS * ParU 0.1.0: new package: parallel unsymmetric multifrontal method, with Mohsen Aznaveh. This is a stable package but is tagged as 0.1.0 since the API is still subject to change. * CHOLMOD 5.1.0: full support for sparse single precision matrices, bug fixes in the GPU Module. * AMD 3.3.0: minor change for CHOLMOD 5.1.0 tests * CAMD 3.3.0: minor change for CHOLMOD 5.1.0 tests * SuiteSparse_config 7.4.0: added wrappers for single-precision BLAS/LAPACK, added SUITESPARSE_TIME macro. * *_version: added methods to all package that didn't have them: AMD, CAMD, COLAMD, CCOLAMD, BTF, CSparse, CXSparse, KLU, BTF, RBio, SPEX, SPQR, and UMFPACK. Oct 31, 2023: version 7.3.1 * CHOLMOD 5.0.1: remove "I" from cholmod.h. Oct 23, 2023: version 7.3.0 * CHOLMOD 5.0.0: initial support for sparse single precision matries. CHOLMOD:Core replaced with CHOLMOD:Utility * updated to require CHOLMOD 5.0.0: Example 1.4.3, GPUQREngine 3.3.3, KLU 2.2.2, SPQR 4.2.2, UMFPACK 6.2.2 * SuiteSparseLAPACK.cmake: allow the use of BLIS/FLAME for LAPACK; update from Theirry Thomas. * build system: further updates to cmake, by Markus Muetzel. Oct 18, 2023: version 7.2.2 * CHOLMOD 4.2.2: bug fix to CHOLMOD/Supernodal (heuristic to determine # threads to use for last supernode was incorrect) Oct 7, 2023: version 7.2.1 * GraphBLAS 8.2.1: bug fix to GrB_mxm; incorrect handling of typecasting * cross-compiler support: replace check_c_source_runs with _compiles, for GraphBLAS and SuiteSparse_config, and remove check for getenv("HOME"). * cmake update: add "None" build type, from Antonio Rojas, for Arch Linux, to all *Config.cmake files for all packages except CSparse (CXSparse is built instead, and CSparse does not have CSparseConfig.cmake file) * UMFPACK v6.2.1 and GPUQREngine v3.2.1: copies internal include files from other SuiteSparse packages (AMD and SuiteSparse_GPURuntime), so these two packages can be built independently. Sept 8, 2023: version 7.2.0 * build system: modern cmake structure, by Markus Muetzel. Most packages updated to vX.2.0 where X is unchanged (except SPQR and Example package). * SPQR v4.2.0: Major SO update. Support for int32 indices by Raye Kimmerer June 29, 2023: version 7.1.0 * GraphBLAS v8.0.2: major update with a new JIT feature. * build system: many changes to build systems of all packages, contributed by Markus Muetzel. * RBio 4.0.0: revised API: declaring many input parameters as const * CXSparse 4.0.4: changed complex types for C++ callers Jan 20, 2023: version 7.0.1 * GraphBLAS v7.4.3: debug was left on in GrB_Matrix_removeElement Jan 17, 2023: version 7.0.0 * SuiteSparse_config: now v7.0.0 * SuiteSparse_config struct: removed from external visibility to simplify the Windows build, so that no global data is externally visible. This requires a major version number increase from v6.x to v7.x for the SuiteSparse meta-package (which has the same version number as SuiteSparse_config). Added get/set methods to SuiteSparse_config to access the contents of the struct. * NFORTRAN: option added to ignore any Fortran methods, even if a Fortran compiler is available. * port of new cmake-based build system to Windows * UMFPACK 6.1.0: copy/serialize/deserialize methods: added new methods to copy, serialize, and deserialize the Numeric and Symbolic objects. By Will Kimmerer, revised by T. Davis. Dec 29, 2022: SuiteSparse 6.0.4 * NFORTRAN: option added to disable Fortran entirely * GraphBLAS v7.4.1: global free pool disabled, and GrB_mxm heuristics revised. Dec 23, 2022: SuiteSparse 6.0.3 * GraphBLAS v7.4.0: added non-va_arg get/set methods. * Mongoose v3.0.3: change in build for test coverage Dec 9, 2022: SuiteSparse 6.0.2 * minor change to build system for nearly all packages: (except CSparse, ssget, and MATLAB_Tools): allows static linkage of all libraries. Fortran no longer required. * AMD 3.0.2: Fortran no longer required (amd.f and amdbar.f skipped); minor change to build system * BTF 2.0.2: minor change to build system * CAMD 3.0,2: minor change to build system * CCOLAMD 3.0.2: minor change to build system * CHOLMOD 4.0.2: Fortran no longer required; minor change to build system * CXSparse 4.0.2: minor change to build system * GPUQREngine 2.0.2: minor change to build system * GraphBLAS 7.3.3: -latomic added if needed, using ANSI C11 atomic functions for gcc (atomic_compare_exachange_weak instead of __atomic_* variants), chunk factor revised for GrB_mxm (generic saxpy3 method); minor change to build system * KLU 2.0.2: Fortran no longer required; minor change to build system * LDL 3.0.2: minor change to build system * Mongoose 3.0.2: fixed matrix download in python test scripts (no change to the compiled library itself, other than the version/date); minor change to build system * RBio 3.0.2: minor change to build system * SPEX 2.0.2: minor change to build system * SPQR 3.0.2: Fortran no longer required; minor change to build system * SuiteSparse_GPURuntime 2.0.2: minor change to build system * SuiteSparse_config 6.0.2: override C-to-Fortran interface handling if no Fortran compiler found; minor change to build system * UMFPACK 6.0.2: Fortran no longer required; minor change to build system * Example: simple package that illustrates how to use SuiteSparse Find*.cmake modules in cmake. * not changed from SuiteSparse v6.0.1: ssget, CSparse, MATLAB_Tools Nov 12, 2022: SuiteSparse 6.0.1 * BLAS: C prototypes for the Fortan BLAS were unintentionally exposed to the user application. Removed. If you want to use them, see the instructions in SuiteSparse_config.h. Nov 12, 2022: SuiteSparse 6.0.0 * major update: using CMake build system for all packages * CMake Find*: all packages now have a Find*.cmake. See SuiteSparse_config/cmake_modules. * integers: int (32-bit) and SuiteSparse_long (nominally 64-bit) replaced with int32_t and int64_t. The SuiteSparse_long #define has been deprecated and removed. Replace its use with int64_t in any code that uses SuiteSparse v6.0.0 or later. This is unlikely to change any use of any SuiteSparse package, but since it's possible that SuiteSparse_long was 32-bits on some platforms, the SO_VERSIION of all packages has been increased by one. * UMFPACK: new options to support ParU. Single umfpack.h include file. * CHOLMOD: Single cholmod.h include file. * SuiteSparse/metis-5.1.0: now embedded into CHOLMOD, in a different name space. No longer an independent library. * SPDX License Identifier: added to each file. No change in license. * BLAS/LAPACK interface: now supports any Fortran BLAS/LAPACK, with either 32-bit (default) or 64-bit integers, via FindBLAS.cmake. * SPEX: replaces SLIP_LU Aug 25, 2022, SuiteSparse 5.13.0 * GraphBLAS v7.2.0: see GraphBLAS/Doc/ChangeLog for details. * performance: more compact serialization (ZSTD added, now the default compression method). * MATLAB interface: faster linear indexing, reshape, bandwidth, istril, istriu, isbanded, isdiag. C(I,J)=A can now grow the size of C. * features: reshape methods, cube root operator, isStoredElement * bugs: a minor bug; user-defined types were incorrectly limited to 128 bytes in size in v7.0.3. Apr 10, 2022, SuiteSparse 5.12.0 * GraphBLAS v7.0.3: see GraphBLAS/Doc/ChangeLog for details. * performance: GrB_mxm, GrB_assign, and transpose * bug fix: vector iterator for bitmap * revised ACM TOMS submission: Doc/toms_parallel_grb2.pdf * spec bug: GrB_Matrix_diag was implemented incorrectly, thus requiring a version v7.x Mar 14, 2022, SuiteSparse 5.11.0 * GraphBLAS v6.2.5: see GraphBLAS/Doc/ChangeLog for changes. Primary ones highlighted here: * v2.0 API: v6.x complies with the v2.0 C API of the GraphBLAS Spec. Note that GrB_wait, GrB_Info are now different than in the v1.3 C API Specification (and in v5.x of SuiteSparse:GraphBLAS). * GxB_Iterator: to iterate over rows/cols/entries of a matrix or vector * GxB_eWiseUnion: like eWiseAdd but with the op always applied * GxB_Matrix/Vector_sort: to sort the vectors of a matrix * better performance: for sparse-times-dense and dense-times-sparse, in particular; also other cases for GrB_mxm, up to 10x faster. * Apple Silicon: port @GrB to Octave 7 (thanks to Gabor Szarnyas) * added cpu_features: by Google * added LZ4/LZ4HC: compression library, http://www.lz4.org (BSD 2), v1.9.3, Copyright (c) 2011-2016, Yann Collet, All Rights Reserved. * iso-valued matrices and vectors: to exploit the common case of an unweighted graph * bug fixes: 4 bugs fixed since SuiteSparse 5.10.1 with GraphBLAS v5.0.5. 12 other bugs appeared in the interim but appeared in versions after v5.0.5 but fixed before ever affecting SuiteSparse itself. May 17, 2021, SuiteSparse 5.10.1 * CUDA: remove sm_30 from SuiteSparse_config.mk * GraphBLAS v5.0.5: minor bug fix * minor changes to Makefiles May 16, 2021, SuiteSparse 5.10.0 * GraphBLAS v5.0.4: many new features, much faster performance Mar 3, 2021, SuiteSparse 5.9.0 * GraphBLAS v4.0.3: many new features, much faster performance July 14, 2020, SuiteSparse 5.8.1 * SLIP_LU v1.0.2: resolved issue #51 * GraphBLAS v3.3.3: bug fix (GraphBLAS issue #13) July 2, 2020, SuiteSparse 5.8.0 * SLIP_LU v1.0.1 added: for solving Ax=b exactly. Requires the GNU GMP and MPRF libraries. * GraphBLAS v3.3.1: see the GraphBLAS/Doc/Changlog * replaced UFget with ssget: affects nearly all packages: UMFPACK, KLU, CHOLMOD, CXSparse/CSparse, etc, but their version numbers are left unchanged since it affects the MATLAB tests only, not the compiled libraries. * ssget v2.2.0: better URL redirects * updates to SuiteSparse build system Apr 8, 2020, SuiteSparse 5.7.2 * GraphBLAS v3.2.2: port to Microsoft Windows (with MS Visual Studio) Feb 20, 2020, SuiteSparse 5.7.1 * SuiteSparse_config: update version number * Makefile: fixed install issue with README.txt Feb 20, 2020, SuiteSparse 5.7.0 * GraphBLAS 3.2.0: better performance, new ANY and PAIR operators, structural mask, GrB_DESC_* from 1.3 C API Specification. * CHOLMOD 3.0.14: minor update to cholmod_check to print a matrix * added: CONTRIBUTIING.md, CODE_OF_CONDUCT.md, README.md. Oct 21, 2019, SuiteSparse 5.6.0 * GraphBLAS 3.1.1: OpenMP parallelism and MATLAB interface Oct 20, 2019, SuiteSparse 5.5.0 * GraphBLAS 2.3.5: Collected Algorithm of the ACM * UMFPACK 5.7.9: fix for compiling in MATLAB R2018b; BLAS library * SPQR, CHOLMOD: fix to *_make.m for compiling in MATLAB; same version * KLU: fix to Tcov/Makefile; no change to version number * CXSparse 3.2.0: version was incorrect in CXSparse/Include/cs.h; the corresponding CSparse v3.2.0 had the correct version information in its cs.h include file. * ssget and MATLAB_Tools/SuiteSparseCollection: update to sparse.tamu.edu * Mongoose 2.0.4: update to sparse.tamu.edu Dec 28, 2018: SuiteSparse 5.4.0 * GraphBLAS 2.2.2: many upgrades and new features, a few bug fixes * CHOLMOD 3.0.13: fix to cholmod_core.h (for latest CUDA) * SPQR 2.0.9: fix to SuiteSparseQR.hpp (for latest CUDA) * UMFPACK 5.7.8: minor change to umf_analyze.h (not a bug, but the parameter names in the *.h did not match the *.c. * ssget: new matrices * Mongoose 2.0.3: simpler cmake * SuiteSparse_config: added JOBS option for parallel make, also added to GraphBLAS, CHOLMOD, SPQR, UMFPACK, Mongoose, and metis-5.1.0 July 5, 2018: SuiteSparse 5.3.0 * GraphBLAS 2.0.3: bug fix to GxB_resize, better cmake script * new package: Mongoose (version 2.0.2) * fixed metis gk_arch.h for Windows * UMFPACK 5.7.7: modified comments in umfpack*symbolic.h * added contributor license for all of SuiteSparse * updated and renamed MATLAB_Tools/UFcollection to SuiteSparseCollection Mar 15, 2018: SuiteSparse 5.2.0 * GraphBLAS 2.0.1: bug fix to GxB_kron * SuiteSparse_config: corrected back to SO_VERSION 5 Mar 12, 2018: * GraphBLAS 2.0.0: with changes to API to conform to the latest specification. The SO_VERSION of GraphBLAS must change, as a result, since this affects both the ABI and API interface. * CHOLMOD 3.1.12: bug fix (no change to the CHOLMOD ABI or API) * KLU 1.3.9: minor edit, not a bug fix, but code is more clear now Dec 28, 2017: SuiteSparse 5.1.2 * improved build process for GraphBLAS * minor change to CSparse/Lib/Makefile, no change in CSparse version Dec 17, 2017: SuiteSparse 5.1.1 * GraphBLAS added to top-level SuiteSparse/Makefile * GraphBLAS 1.1.1: bug fix to *assign, split AxB for faster compile, added memory usage statistics, AxB performance improvment * minor update to [AMD CAMD KLU]/Doc/Makefile's, no change to version numbers of AMD, CAMD, or KLU Dec 1, 2017: SuiteSparse 5.1.0 * GraphBLAS 1.1.0 * minor update to SPQR Makefile (version remains unchanged; no change to source) Nov 25, 2017: SuiteSparse 5.0.0 * added GraphBLAS Version 1.0.0 * replaced UFget with ssget Oct 3, 2017: SuiteSparse 4.5.6 * changed COLAMD, CAMD, and CCOLAMD to BSD 3-clause, to match AMD. No other changes; version numbers of packages unchanged. Apr 17, 2017: SuiteSparse 4.5.5 * minor fix to SuiteSparse/Makefile for 'make install' Dec 8, 2016: SuiteSparse 4.5.4 * minor update to SPQR for ACM TOMS submission May 4, 2016: SuiteSparse 4.5.3 * minor changes to Makefiles Apr 1, 2016: SuiteSparse 4.5.2 * licensing simplified (no other change); refer to PACKAGE/Doc/License.txt for the license for each package. Feb 1, 2016: SuiteSparse 4.5.1 * update to Makefiles. Version 4.5.0 is broken on the Mac. That version also compiles *.so libraries on Linux with underlinked dependencies to other libraries in SuiteSparse. For example, AMD requires SuiteSparse_config. The links to required libraries are now explicitly included in each library, in SuiteSparse 4.5.1. * minor change to CHOLMOD/Check/cholmod_write.c, when compiling with options that disable specific modules Jan 30, 2016: SuiteSparse 4.5.0 * better Makefiles for creating and installing shared libraries * CHOLMOD now uses METIS 5.1.0, which is distributed with SuiteSparse * fix for MATLAB R2015b, which changed how it creates empty matrices, as compared to prior versions of MATLAB. This change in MATLAB breaks many of the mexFunctions in prior versions of SuiteSparse. If you use MATLAB R2015b, you must upgrade to SuiteSparse 4.5.0 or later. Jan 1, 2016: SuiteSparse 4.4.7 * note that this minor update fails on the Mac, so its listed on my web page as a 'beta' release. * Improved the Makefiles of all packages. They now create *.so shared libraries (*.dylib on the Mac). Also, there is now only a single SuiteSparse_config.mk file. It now determines your system automatically, and whether or not you have METIS and CUDA. It also automatically detects if you have the Intel compiler or not, and uses it if it finds it. There should be no need to edit this file for most cases, but you may need to for your particular system. With this release, there are almost no changes to the source code, except for the VERSION numbers defined in the various include *.h files for each package. Aug 2015: SuiteSparse version 4.4.6 * SPQR: changed default tol when A has infs, from inf to realmax (~1e308) July 2015: SuiteSparse version 4.4.5 * CHOLMOD 3.0.6: - minor fix to CHOLMOD (disabling modules did not work as expected) - added MATLAB interface for row add/delete (lurowmod) * KLU 1.3.3: Fix for klu_dump.c (debugging case only) * UFcollection: added additional stats for matrix collection * AMD: changed the default license. See AMD/Doc/License.txt for details. Mar 24, 2015: SuiteSparse version 4.4.4 * CHOLMOD version number corrected. In 4.4.3, the CHOLMOD_SUBSUB_VERSION string was left at '4' (it should have been '5', for CHOLMOD 3.0.5). This version of SuiteSparse corrects this glitch. * Minor changes to comments in SuiteSparse_config. * SPQR version 2.0.1 released (minor update to documentation) Jan 19, 2015: SuiteSparse version 4.4.3 * CHOLMOD 3.0.5: minor bug fix to MatrixOps/cholmod_symmetry Jan 7, 2015: SuiteSparse version 4.4.2 * CHOLMOD 3.0.4: serious bug fix in supernodal factorization, introduced in CHOLMOD 3.0.0 (SuiteSparse 4.3.0). Can cause segfault, and has no user workaround. Oct 23, 2014: SuiteSparse version 4.4.1 Minor update: two bug fixes (affecting Windows only) * CHOLMOD 3.0.3: minor update to CHOLMOD (non-ANSI C usage in one *.c file, affects Windows only) * KLU 1.3.2: minor fix to MATLAB install; no change to C except version nubmer Oct 10, 2014: SuiteSparse version 4.4.0 MAJOR UPDATE: new GPU-acceleration for SPQR * AMD 2.4.1: minor fix to MATLAB install; no change to C except version nubmer * BTF 1.2.1: minor fix to MATLAB install; no change to C except version nubmer * CAMD 2.4.1: minor fix to MATLAB install; no change to C except version nubmer * CCOLAMD 2.9.1: minor fix to MATLAB install; no change to C except version nubmer * CHOLMOD 3.0.2: update to accomodate GPU-accelerated SPQR added CHOLMOD/Include/cholmod_function.h * COLAMD 2.9.1: minor fix to MATLAB install; no change to C except version nubmer * CSparse 3.1.4: minor fix to MATLAB install; no change to C except version nubmer * CXSparse 3.1.4: minor fix to MATLAB install; no change to C except version nubmer * GPUQREngine 1.0.0: FIRST RELEASE. Used by SPQR 2.0.0 * KLU 1.3.1: minor fix to MATLAB install; no change to C except version nubmer update to KLU/Tcov/Makefile * LDL 2.2.1: minor fix to MATLAB install; no change to C except version nubmer * RBio 2.2.1: minor fix to MATLAB install; no change to C except version nubmer * SPQR 2.0.0: MAJOR UPDATE. added GPU support. Up to 11x faster than on CPU * SuiteSparse_GPURuntime 1.0.0: FIRST RELEASE. Used by SPQR 2.0.0 * UMFPACK 5.7.1: minor fix to MATLAB install; no change to C except version nubmer * MATLAB_Tools: modified SSMULT/ssmult_install.m. No change to C code July 18, 2014: SuiteSparse version 4.3.1 Minor update: added cholmod_rowfac_mask2 function to CHOLMOD * CHOLMOD 3.0.1: added cholmod_rowfac_mask2 function. Minor fix to build process * SPQR 1.3.3: minor fix to build process March 26, 2014: SuiteSparse version 4.3.0 MAJOR UPDATE: first release of CHOLMOD GPU acceleration minor update: modified all packages to use SuiteSparse_config for malloc/calloc/realloc/free, printf, hypot, and divcomplex function pointers. * AMD 2.4.0: changed malloc/printf pointers to use SuiteSparse_config * CAMD 2.4.0: changed malloc/printf pointers to use SuiteSparse_config * CCOLAMD 2.9.0: changed malloc/printf pointers to use SuiteSparse_config * CHOLMOD 3.0.0: MAJOR UPDATE to GPU acceleration. Released at GTC 2014. * COLAMD 2.9.0: changed malloc/printf pointers to use SuiteSparse_config * CSparse 3.1.3: minor update to UFget * CXSparse 3.1.3: minor update to UFget * KLU 1.3.0: changed malloc/printf pointers to use SuiteSparse_config * LDL 2.2.0: changed malloc/printf pointers to use SuiteSparse_config * RBio 2.2.0: changed malloc/printf pointers to use SuiteSparse_config * SPQR 1.3.2: changed malloc/printf pointers to use SuiteSparse_config * UMFPACK 5.7.0: changed malloc/printf pointers to use SuiteSparse_config * MATLAB_Tools: added stats to UFcollection, revised commends in SFMULT, minor update to spok April 25, 2013: SuiteSparse version 4.2.1 minor update * CHOLMOD 2.1.2: minor update to Cholesky/*solve*c (for Windows compiler) * UMFPACK 5.6.2: bug fix in Demo/Makefile for Fortran interface * MATLAB_Tools: minor update to sparseinv April 16, 2013: SuiteSparse version 4.2.0 minor update and bug fix * CHOLMOD 2.1.1: minor changes to GPU accelerated version, fixed GPU memory leak * CSparse 3.1.2: minor update to cs_sqr.c; no affect on functionality * CXSparse 3.1.2: minor update to cs_sqr.c; no affect on functionality March 27, 2013: SuiteSparse version 4.1.0 new features added to CHOLMOD * CHOLMOD 2.1.0: added new features and functions to forward/backsolve: cholmod_lsolve_pattern, cholmod_solve2, cholmod_ensure_dense. * MATLAB_Tools: added SFMULT. minor update to Factorize, problems added to dimacs10 July 17, 2012: SuiteSparse version 4.0.2 major update to MATLAB_Tools/Factorize. No change to any C code. * MATLAB_Tools: major update to Factorize, minor update to sparseinv June 20, 2012: SuiteSparse version 4.0.1 * AMD 2.3.1: minor fix to MATLAB install; no change to C except version nubmer * CAMD 2.3.1: minor fix to MATLAB install; no change to C except version nubmer * CHOLMOD 2.0.1: bug fix for GPU code, when the matrix is singular minor fix to MATLAB install * CSparse 3.1.1: minor fix to MATLAB install; no change to C except version nubmer * CXSparse 3.1.1: minor fix to MATLAB install; no change to C except version nubmer * KLU 1.2.1: minor fix to MATLAB install; no change to C except version nubmer * RBio 2.1.1: minor fix to MATLAB install; no change to C except version nubmer * SPQR 1.3.1: minor fix to MATLAB install; no change to C except version nubmer * UMFPACK 5.6.1: minor fix to MATLAB install; no change to C except version nubmer * MATLAB_Tools: update to UFcollection (filesep) June 1, 2012: SuiteSparse version 4.0.0 MAJOR UPDATE: First GPU version for CHOLMOD. UFconfig renamed to SuiteSparse_config. * AMD 2.3.0: replaced UFconfig with SuiteSparse_config * BTF 1.2.0: replaced UFconfig with SuiteSparse_config * CAMD 2.3.0: replaced UFconfig with SuiteSparse_config * CCOLAMD 2.8.0: replaced UFconfig with SuiteSparse_config * CHOLMOD 2.0.0: replaced UFconfig with SuiteSparse_config first GPU-accelerated version. * COLAMD 2.8.0: replaced UFconfig with SuiteSparse_config * CSparse 3.1.0: minor changes to enable creation of CXSparse 3.1.0 * CXSparse 3.1.0: replaced UFconfig with SuiteSparse_config * KLU 1.2.0: replaced UFconfig with SuiteSparse_config * LDL 2.1.0: replaced UFconfig with SuiteSparse_config * RBio 2.1.0: replaced UFconfig with SuiteSparse_config * SPQR 1.3.0: replaced UFconfig with SuiteSparse_config removed spqr_time; using SuiteSparse timing routines instead * UMFPACK 5.6.0: replaced UFconfig with SuiteSparse_config * MATLAB_Tools: update to documentation for Factorize, update to UFcollection May 15, 2012: SuiteSparse version 3.7.1 minor update * AMD 2.2.4: minor compiler workaround * CAMD 2.2.4: minor compiler workaround * KLU 1.1.4: bug fix in the case of Int overflow * MATLAB_Tools: minor update to spqr_rank and UFcollection Dec 15, 2011: SuiteSparse version 3.7.0 MAJOR UPDATE: added spqr_rank and sparseinv to MATLAB_Tools major update to Factorize package in MATLAB_Tools minor update to Makefiles for C code. * AMD 2.2.3: Makefile updated * BTF 1.1.3: Makefile updated * CAMD 2.2.3: Makefile updated * CCOLAMD 2.7.4: Makefile updated * CHOLMOD 1.7.4: Makefile updated * COLAMD 2.7.4: Makefile updated * CSparse 3.0.2: Makefile updated. Fix to MATLAB install. Now as CSparse (not CSparse3) * KLU 1.1.3: Makefile updated. minor fix to MATLAB mexFunction * LDL 2.0.4: Makefile updated. Update to demo program * RBio 2.0.2: Makefile updated. Update to MATLAB mexFunction * SPQR 1.2.3 Makefile updated. Update to MATLAB install * UMFPACK 5.5.2: Makefile updated. Update to MATLAB install * MATLAB_Tools: added spqr_rank and sparseinv. Major update to Factorize, dimacs10 May 10, 2011: SuiteSparse version 3.6.1 minor update * SPQR 1.2.2: minor fix, compiler workaround * CSparse 3.0.1: Added as the CSparse3 directory (original date Jan 19, 2010; added to SuiteSparse on May 10, 2011. Note that CSparse v2.x.x. was also distributed) * MATLAB_Tools: added dimacs10. Minor update to spok. Jan 25, 2011: SuiteSparse version 3.6.0 minor update * AMD 2.2.2: Makefile updated. * BTF 1.1.2: Makefile updated. * CAMD 2.2.2: Makefile updated. * CCOLAMD 2.7.3: Makefile updated. Minor fix to stats printout * CHOLMOD 1.7.3: Makefile updated. Minor fix, compiler workaround * COLAMD 2.7.3: Makefile updated * CSparse 2.2.5: Makefile updated. minor fixes to UFget, cs_util.c. * KLU 1.1.2: Makefile updated. ported Tcov to Mac. * LDL 2.0.3: Makefile updated. * RBio 2.0.1: Makefile updated. * SPQR 1.2.1: Makefile updated. Added examples. Fixed error handling. * UMFPACK 5.5.1: Makefile updated. * MATLAB_Tools: minor update to spok Nov 30, 2009: SuiteSparse version 3.5.0 major update to SPQR and RBio; minor updates to Makefiles. * AMD 2.2.1: Makefile updated. * BTF 1.1.1 Makefile updated. * CAMD 2.2.1: Makefile updated. * CCOLAMD 2.7.2: Makefile updated. * CHOLMOD 1.7.2: Makefile updated. Fixed 64-bit BLAS for MATLAB 7.8. * COLAMD 2.7.2: Makefile updated. * CSparse 2.2.4 Makefile updated. MATLAB install updated. * KLU 1.1.1: Makefile updated. * LDL 2.0.2: Makefile updated. * RBio 2.0.0: major update: rewritten in C. No longer in Fortran. Makefile updated. * SPQR 1.2.0: major update: added features required by MATLAB package spqr_rank, changed default ordering to COLAMD. Makefile updated. * UMFPACK 5.5.0: major update. Added user-ordering function, interface to CHOLMOD orderings, option to disable singleton search to allow L to be well-conditioned. Makefile updated. * MATLAB_Tools: major update to Factorize. Minor updates to GEE, getversion, spok. May 20, 2009: SuiteSparse version 3.4.0 MAJOR UPDATE: added Factorize package to MATLAB_TOols major update to UMFPACK (removed 2-by-2 strategy) * RBio 1.1.2: update to MATLAB install * SPQR 1.1.2: added more examples. Mac compiler workaround. * UMFPACK 5.4.0: removed 2-by-2 strategy. update to MATLAB install. * MATLAB_Tools: added Factorize March 24, 2009: SuiteSparse version 3.3.0 minor update * BTF 1.1.0: minor update. * CHOLMOD 1.7.1: bug fix for cholmod_symmetry * CSparse 2.2.3: cs_gaxpy example fixed. Minor change to MATLAB cs_sparse interface * CXSparse 2.2.3: cs_gaxpy example fixed. Minor change to MATLAB cs_sparse interface * KLU 1.1.0: minor update. * SPQR 1.1.1: minor update (compiler workaround) * UMFPACK 5.3.0: compiler workaround. added timer options. bug fix for 2-by-2 strategy (subsequently removed in v5.4.0) Sept 20, 2008: SuiteSparse version 3.2.0 MAJOR UPDATE: first release of SPQR * CHOLMOD 1.7.0: major update for SPQR. * CXSparse 2.2.2: update to MATLAB install * CSparse 2.2.2: update to MATLAB install * SPQR 1.1.0: FIRST RELEASE in SuiteSparse. * MATLAB_TOOLS: added: GEE, find_components, spok Nov 1, 2007: SuiteSparse version 3.1.0 minor update * BTF 1.0.1: minor update. * CCOLAMD 2.7.1: minor changes to MATLAB test code. * CHOLMOD 1.6.0: bug fix to cholmod_symmetry. Performance fix for cholmod_nesdis. port to MATLAB 7.5 and many minor changes in MATLAB interface. * COLAMD 2.7.1: minor changes to MATLAB test code. * CSparse 2.2.1: minor update. * CXSparse 2.2.1: * KLU 1.0.1: minor lint cleanup. * RBio 1.1.1: minor lint cleanup. minor update. * UMFPACK 5.2.0: change of default license. minor lint cleanup. port to MATLAB 7.5. * MATLAB_Tools: added: LINFACTOR, MESHND, SSMULT, getversion, gipper, hprintf, pagerankdemo, shellgui, and waitmex May 31, 2007: SuiteSparse version 3.0.0 MAJOR UPDATE: first stable release of KLU and BTF other packages ported to 64-bit MATLAB. * AMD 2.2.0: port to 64-bit MATLAB. minor changes in printing. * BTF 1.0.0: FIRST STABLE RELEASE * CAMD 2.2.0: port to 64-bit MATLAB. minor changes in printing. * CCOLAMD 2.7.0: port to 64-bit MATLAB. restructured directories * CHOLMOD 1.5.0: port to 64-bit MATLAB. update to Makefile. bug fix for BLAS int, update to cholmod_updown. * COLAMD 2.7.0: port to 64-bit MATLAB. restructured directories * CSparse 2.2.0: update to MATLAB interface. restructured directories * LDL 2.0.0: major update: added 64bit version, restructured directories * RBio 1.1.0: port to 64-bit MATLAB. * UMFPACK 5.1.0: port to 64-bit MATLAB. minor changes in printing. Dec 13, 2006: SuiteSparse version 2.4.0 minor update * AMD 2.0.4: minor MATLAB cleanup * CAMD 2.1.2: minor MATLAB cleanup * CCOLAMD 2.5.2 minor MATLAB cleanup * CHOLMOD 1.4.0: added support for large files. Renamed MATLAB interface to cholmod2. minor MATLAB cleanup. * COLAMD 2.5.2: minor MATLAB cleanup * CSparse 2.0.7: minor MATLAB cleanup * CXSparse 2.0.7: minor MATLAB cleanup * LDL 1.3.4: minor MATLAB cleanup * UMFPACK 5.0.3: minor MATLAB cleanup Dec 7, 2006: SuiteSparse version 2.3.1 minor update * CSparse 2.0.6: update to UFget * CXSparse 2.0.6: update to UFget Dec 2, 2006: SuiteSparse version 2.3.0 MAJOR UPDATE * CHOLMOD 1.3.0: major update to file IO functions, added cholmod_symmetry, minor fix to cholmod_analyze_odering and cholmod_dense.c. * MATLAB_Tools: added UFcollection Sept 11, 2006: SuiteSparse version 2.1.1 * AMD 2.0.1: minor update * CAMD 2.1.1: minor update * CHOLMOD 1.2.0: performance improvements. Added ordering options to MATLAB interface * COLAMD 2.5.1: minor update * CCOLAMD 2.5.1: minor update * CSparse 2.0.2: minor update to MATLAB interface * CXSparse 2.0.2: minor update to MATLAB interface * LDL 1.3.1: minor update to MATLAB interface * UMFPACK 5.0.1: minor update Matrix/inst/doc/SuiteSparse/CXSparse/0000755000175100001440000000000014576343415017231 5ustar hornikusersMatrix/inst/doc/SuiteSparse/CXSparse/README.txt0000644000175100001440000005467014552026002020723 0ustar hornikusersCXSparse: a Concise eXtended Sparse Matrix Package CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. SPDX-License-Identifier: LGPL-2.1+ Derived from CSparse. Conversion originally by David Bateman, Motorola, and then modified by Tim Davis. ANSI C11 is required, with support for the double complex data type. (if you use a C++ compiler, the C++ complex type is used instead). CXSparse is a version of CSparse that operates on both real and complex matrices, using either int32_t or int64_t integers. To install for use in MATLAB, simply type "cs_install" in the MATLAB Command Window, while in the CXSparse/MATLAB directory. (NOTE: you may need to run "mex -setup" first). Refer to "Direct Methods for Sparse Linear Systems," Timothy A. Davis, SIAM, Philadelphia, 2006. No detailed user guide is included in this package; the user guide is the book itself. To compile the C-library (./Source) and C demo programs (./Demo) just type "make" in this directory, or import the CMakeLists.txt into your build system (such as Microsoft Visual Studio). To install, use "sudo make install". Run the demos with "make demos". To clean up, do "make clean". To run the exhaustive tests, type "make" in the Tcov directory (Linux is assumed). To remove all files not in the original distribution, type "make distclean". While in MATLAB, type "cs_install" while in the CSparse/MATLAB directory to compile and install CSparse for use in MATLAB. For more details, see CXSparse/MATLAB/README.txt. This package is backward compatible with CSparse. That is, user code that uses CSparse may switch to using CXSparse without any changes to the user code. Each CXSparse function has a generic version with the same name as the CSparse function, and four type-specific versions. For example: cs_add same as cs_add_di by default, but can be changed to use int64_t integers if user code is compiled with -DCS_LONG, and/or can be changed to operate on complex matrices with -DCS_COMPLEX. cs_di_add double/int version of cs_add cs_dl_add double/int64_t version of cs_add cs_ci_add complex/int version of cs_add cs_cl_add complex/int64_t version of cs_add The sparse matrix data structures are treated in the same way: cs, css, csn, and csd become cs_di, cs_dis, cs_din, and cs_did for the double/int case, cs_cl, cs_cls, cs_cln, and cs_cld for the complex/int64_t case, and so on. See cs_demo.c for a type-generic user program, and cs_cl_demo.c for a type-specific version of the same program (complex/int64_t). Several macros are available in CXSparse (but not in CSparse) to allow user code to be written in a type-generic manner: CS_INT int by default, int64_t if -DCS_LONG compiler flag is used CS_ENTRY double by default, double complex if -DCS_COMPLEX flag is used. CS_ID "%d" or "%"PRId64, for printf and scanf of the CS_INT type. CS_INT_MAX INT32_MAX or INT64_MAX, the largest possible value of CS_INT. CS_REAL(x) x or creal(x) CS_IMAG(x) 0 or cimag(x) CS_CONJ(x) x or conj(x) CS_ABS(x) fabs(x) or cabs(x) Even the name of the include file (cs.h) is the same. To use CXSparse instead of CSparse, simply compile with -ICXSparse/Source instead of -ICSparse/Source, and link against libcxsparse.a instead of the CSparse libcsparse.a library. To determine at compile time if CXSparse or CSparse is being used: #ifdef CXSPARSE CXSparse is in use. The generic functions equivalent to CSparse may be used (cs_add, etc). These generic functions can use different types, depending on the -DCS_LONG and -DCS_COMPLEX compile flags, with the default being double/int. The type-specific functions and data types (cs_di_add, cs_di, CS_INT, etc.) can be used. #else CSparse is in use. Only the generic functions "cs_add", etc., are available, and they are of type double/int. #endif See cs.h for the prototypes of each function, and the book "Direct Methods for Sparse Linear Systems" for full documentation of CSparse and CXSparse. Other changes from CSparse: cs_transpose performs the complex conjugate transpose if 'values' input parameter is >0 (C=A'), the pattern-only transpose if values=0 (C=spones(A') in MATLAB), and the array transpose if values<0 (C=A.' in MATLAB notation). A set of four conversion routines are included in CXSparse, to convert real matrices to/from complex matrices. The Householder reflection constructed by cs_house.c also differs slightly, to accomodate both the real and complex cases properly. CXSparse is generated automatically from CSparse. Refer to http://www.suitesparse.com for details. -------------------------------------------------------------------------------- Contents: -------------------------------------------------------------------------------- Demo/ demo C programs that use CXSparse Doc/ license and change log Makefile Makefile for the whole package Makefile Makefile for the whole package (optional) Matrix/ sample matrices (with extra complex matrices for CXSparse) README.txt this file Source/ primary CXSparse source files Tcov/ CXSparse tests Config/ source for Include/cs.h build/ compiled files -------------------------------------------------------------------------------- ./Doc: license and change log -------------------------------------------------------------------------------- ChangeLog changes in CSparse since first release License.txt license -------------------------------------------------------------------------------- ./Source: Primary source code for CXSparse -------------------------------------------------------------------------------- cs_add.c add sparse matrices cs_amd.c approximate minimum degree cs_chol.c sparse Cholesky cs_cholsol.c x=A\b using sparse Cholesky cs_compress.c convert a triplet form to compressed-column form cs_counts.c column counts for Cholesky and QR cs_convert.c convert real to complex and complex to real (not in CSparse) cs_cumsum.c cumulative sum cs_dfs.c depth-first-search cs_dmperm.c Dulmage-Mendelsohn permutation cs_droptol.c drop small entries from a sparse matrix cs_dropzeros.c drop zeros from a sparse matrix cs_dupl.c remove (and sum) duplicates cs_entry.c add an entry to a triplet matrix cs_ereach.c nonzero pattern of Cholesky L(k,:) from etree and triu(A(:,k)) cs_etree.c find elimination tree cs_fkeep.c drop entries from a sparse matrix cs_gaxpy.c sparse matrix times dense matrix cs.h include file for CXSparse cs_happly.c apply Householder reflection cs_house.c Householder reflection (*** NOTE: different algo. from CSparse) cs_ipvec.c x(p)=b cs_leaf.c determine if j is a leaf of the skeleton matrix and find lca cs_load.c load a sparse matrix from a file cs_lsolve.c x=L\b cs_ltsolve.c x=L'\b cs_lu.c sparse LU factorization cs_lusol.c x=A\b using sparse LU factorization cs_malloc.c memory manager cs_maxtrans.c maximum transveral (permutation for zero-free diagonal) cs_multiply.c sparse matrix multiply cs_norm.c sparse matrix norm cs_permute.c permute a sparse matrix cs_pinv.c invert a permutation vector cs_post.c postorder an elimination tree cs_print.c print a sparse matrix cs_pvec.c x=b(p) cs_qr.c sparse QR cs_qrsol.c solve a least-squares problem cs_randperm.c random permutation cs_reach.c find nonzero pattern of x=L\b for sparse L and b cs_scatter.c scatter a sparse vector cs_scc.c strongly-connected components cs_schol.c symbolic Cholesky cs_spsolve.c x=Z\b where Z, x, and b are sparse, and Z upper/lower triangular cs_sqr.c symbolic QR (also can be used for LU) cs_symperm.c symmetric permutation of a sparse matrix cs_tdfs.c depth-first-search of a tree cs_transpose.c transpose a sparse matrix cs_updown.c sparse rank-1 Cholesky update/downate cs_usolve.c x=U\b cs_util.c various utilities (allocate/free matrices, workspace, etc) cs_utsolve.c x=U'\b README.txt README file for CXSparse/Source cs_*_ci.c complex int32_t versions cs_*_cl.c complex int64_t versions cs_*_dl.c double int64_t versions -------------------------------------------------------------------------------- ./Config: -------------------------------------------------------------------------------- cs.h.in source for cs.h -------------------------------------------------------------------------------- ./Demo: C program demos -------------------------------------------------------------------------------- cs_ci_demo1.c complex/int version of cs_demo1.c cs_ci_demo2.c complex/int version of cs_demo2.c cs_ci_demo3.c complex/int version of cs_demo3.c cs_ci_demo.c complex/int version of cs_demo.c cs_ci_demo.h complex/int version of cs_demo.h cs_cl_demo1.c complex/int64_t version of cs_demo1.c cs_cl_demo2.c complex/int64_t version of cs_demo2.c cs_cl_demo3.c complex/int64_t version of cs_demo3.c cs_cl_demo.c complex/int64_t version of cs_demo.c cs_cl_demo.h complex/int64_t version of cs_demo.h cs_demo1.c read a matrix from a file and perform basic matrix operations cs_demo2.c read a matrix from a file and solve a linear system cs_demo3.c read a matrix, solve a linear system, update/downdate cs_demo.c support routines for cs_demo*.c cs_demo.h include file for demo programs cs_demo.out output of "make", which runs the demos on some matrices cs_di_demo1.c double/int version of cs_demo1.c cs_di_demo2.c double/int version of cs_demo2.c cs_di_demo3.c double/int version of cs_demo3.c cs_di_demo.c double/int version of cs_demo.c cs_di_demo.h double/int version of cs_demo.h cs_dl_demo1.c double/int64_t version of cs_demo1.c cs_dl_demo2.c double/int64_t version of cs_demo2.c cs_dl_demo3.c double/int64_t version of cs_demo3.c cs_dl_demo.c double/int64_t version of cs_demo.c cs_dl_demo.h double/int64_t version of cs_demo.h cs_idemo.c convert real matrices to/from complex (int version) cs_ldemo.c convert real matrices to/from complex (int64_t version) README.txt Demo README file -------------------------------------------------------------------------------- ./MATLAB: MATLAB interface, demos, and tests -------------------------------------------------------------------------------- cs_install.m MATLAB function for compiling and installing CSparse for MATLAB CSparse/ MATLAB interface for CSparse Demo/ MATLAB demos for CSparse Makefile MATLAB interface Makefile README.txt MATLAB README file Test/ MATLAB test for CSparse, and "textbook" routines ssget/ MATLAB interface to SuiteSparse Sparse Matrix Collection -------------------------------------------------------------------------------- ./MATLAB/CSparse: MATLAB interface for CSparse -------------------------------------------------------------------------------- Contents.m Contents of MATLAB interface to CSparse cs_add.m add two sparse matrices cs_add_mex.c cs_amd.m approximate minimum degree cs_amd_mex.c cs_chol.m sparse Cholesky cs_chol_mex.c cs_cholsol.m x=A\b using a sparse Cholesky cs_cholsol_mex.c cs_counts.m column counts for Cholesky or QR (like "symbfact" in MATLAB) cs_counts_mex.c cs_dmperm.m Dulmage-Mendelsohn permutation cs_dmperm_mex.c cs_dmsol.m x=A\b using dmperm cs_dmspy.m plot a picture of a dmperm-permuted matrix cs_droptol.m drop small entries cs_droptol_mex.c cs_esep.m find edge separator cs_etree.m compute elimination tree cs_etree_mex.c cs_gaxpy.m sparse matrix times dense vector cs_gaxpy_mex.c cs_lsolve.m x=L\b where L is lower triangular cs_lsolve_mex.c cs_ltsolve.m x=L'\b where L is lower triangular cs_ltsolve_mex.c cs_lu.m sparse LU factorization cs_lu_mex.c cs_lusol.m x=A\b using sparse LU factorization cs_lusol_mex.c cs_make.m compiles CSparse for use in MATLAB cs_mex.c support routines for CSparse mexFunctions cs_mex.h cs_multiply.m sparse matrix multiply cs_multiply_mex.c cs_must_compile.m determine if a source file needs to be compiled with mex cs_nd.m nested dissection cs_nsep.m find node separator cs_permute.m permute a sparse matrix cs_permute_mex.c cs_print.m print a sparse matrix cs_print_mex.c cs_qleft.m apply Householder vectors to the left cs_qright.m apply Householder vectors to the right cs_qr.m sparse QR factorization cs_qr_mex.c cs_qrsol.m solve a sparse least squares problem cs_qrsol_mex.c cs_randperm.m randdom permutation cs_randperm_mex.c cs_scc.m strongly-connected components cs_scc_mex.c cs_sep.m convert an edge separator into a node separator cs_sparse.m convert a triplet form matrix to a compress-column form cs_sparse_mex.c cs_symperm.m symmetric permutation of a sparse matrix cs_symperm_mex.c cs_sqr.m symbolic QR ordering and analysis cs_sqr_mex.c cs_thumb_mex.c compute small "thumbnail" of a sparse matrix (for cspy). cs_transpose.m transpose a sparse matrix cs_transpose_mex.c cs_updown.m sparse Cholesky update/downdate cs_updown_mex.c cs_usolve.m x=U\b where U is upper triangular cs_usolve_mex.c cs_utsolve.m x=U'\b where U is upper triangular cs_utsolve_mex.c cspy.m a color "spy" Makefile Makefile for CSparse MATLAB interface README.txt README file for CSparse MATLAB interface -------------------------------------------------------------------------------- ./MATLAB/Demo: MATLAB demos for CSparse -------------------------------------------------------------------------------- Contents.m Contents of MATLAB demo for CSparse cs_demo.m run all MATLAB demos for CSparse cs_demo1.m MATLAB version of Demo/cs_demo1.c cs_demo2.m MATLAB version of Demo/cs_demo2.c cs_demo3.m MATLAB version of Demo/cs_demo3.c private/ private functions for MATLAB demos README.txt README file for CSparse MATLAB demo -------------------------------------------------------------------------------- ./MATLAB/Demo/private: private functions for MATLAB demos -------------------------------------------------------------------------------- demo2.m demo 2 demo3.m demo 3 ex_1.m example 1 ex2.m example 2 ex3.m example 3 frand.m generate a random finite-element matrix get_problem.m get a matrix is_sym.m determine if a matrix is symmetric mesh2d1.m construct a 2D mesh (method 1) mesh2d2.m construct a 2D mesh (method 2) mesh3d1.m construct a 3D mesh (method 1) mesh3d2.m construct a 3D mesh (method 2) print_order.m print the ordering method used resid.m compute residual rhs.m create right-hand-side -------------------------------------------------------------------------------- ./MATLAB/Test: Extensive test of CSparse, in MATLAB -------------------------------------------------------------------------------- Makefile Makefile for MATLAB Test directory README.txt README file for MATLAB/Test Contents.m Contents of MATLAB/Test, "textbook" files only chol_downdate.m downdate a Cholesky factorization. chol_left.m left-looking Cholesky factorization. chol_left2.m left-looking Cholesky factorization, more details. chol_right.m right-looking Cholesky factorization. chol_super.m left-looking "supernodal" Cholesky factorization. chol_up.m up-looking Cholesky factorization. chol_update.m update a Cholesky factorization. chol_updown.m update or downdate a Cholesky factorization. cond1est.m 1-norm condition estimate. cs_fiedler.m the Fiedler vector of a connected graph. givens2.m find a Givens rotation. house.m find a Householder reflection. lu_left.m left-looking LU factorization. lu_right.m right-looking LU factorization. lu_rightp.m right-looking LU factorization, with partial pivoting. lu_rightpr.m recursive right-looking LU, with partial pivoting. lu_rightr.m recursive right-looking LU. norm1est.m 1-norm estimate. qr_givens.m Givens-rotation QR factorization. qr_givens_full.m Givens-rotation QR factorization, for full matrices. qr_left.m left-looking Householder QR factorization. qr_right.m right-looking Householder QR factorization. cs_fiedler.m Fiedler vector cs_frand.m generate a random finite-element matrix cs_frand_mex.c cs_ipvec.m x(p)=b cs_ipvec_mex.c cs_maxtransr.m recursive maximum matching algorithm cs_maxtransr_mex.c cs_pvec.m x=b(p) cs_pvec_mex.c interface for cs_pvec cs_reach.m non-recursive reach (interface to CSparse cs_reach) cs_reach_mex.c non-recursive x=spones(L\sparse(b)) cs_reachr.m recursive reach (interface to CSparse cs_reachr) cs_reachr_mex.c cs_rowcnt.m row counts for sparse Cholesky cs_rowcnt_mex.c row counts for sparse Cholesky cs_sparse2.m same as cs_sparse, to test cs_entry function cs_sparse2_mex.c like cs_sparse, but for testing cs_entry cs_test_make.m compiles MATLAB tests check_if_same.m check if two inputs are identical or not choldn.m Cholesky downdate cholup.m Cholesky update, using Given's rotations cholupdown.m Cholesky update/downdate (Bischof, Pan, and Tang method) cs_q1.m construct Q from Householder vectors cs_test_make.m compiles the CSparse, Demo, and Test mexFunctions. dmperm_test.m test cs_dmperm chol_example.m simple Cholesky factorization example etree_sample.m construct a sample etree and symbolic factorization gqr3.m QR factorization, based on Givens rotations happly.m apply Householder reflection to a vector hmake1.m construct a Householder reflection mynormest1.m estimate norm(A,1), using LU factorization (L*U = P*A*Q). myqr.m QR factorization using Householder reflections another_colormap.m try another color map cspy_test.m test cspy and cs_dmspy qr2.m QR factorization based on Householder reflections sample_colormap.m try a colormap for use in cspy signum.m compute and display the sign of a column vector x sqr_example.m test cs_sqr dmspy_test.m test cspy, cs_dmspy, and cs_dmperm test_qr.m test various QR factorization methods test_randperms.m test random permutations testh.m test Householder reflections test_qr1.m test QR factorizations test_qrsol.m test cs_qrsol test_sep.m test cs_sep, and compare with Gilbert's meshpart vtxsep testall.m test all CSparse functions (run tests 1 to 28 below) test1.m test cs_transpose test2.m test cs_sparse test3.m test cs_lsolve, cs_ltsolve, cs_usolve, cs_chol test4.m test cs_multiply test5.m test cs_add test6.m test cs_reach, cs_reachr, cs_lsolve, cs_usolve test7.m test cs_lu test8.m test cs_cholsol, cs_lusol test9.m test cs_qr test10.m test cs_qr test11.m test cs_rowcnt test12.m test cs_qr and compare with svd test13.m test cs_counts, cs_etree test14.m test cs_droptol test15.m test cs_amd test16.m test cs_amd test17.m test cs_qr, cs_qright, cs_q1, cs_qrleft, cs_qrsol test18.m test iterative refinement after backslash test19.m test cs_dmperm, cs_maxtransr, cs_dmspy, cs_scc test20.m test cholupdown test21.m test cs_updown test22.m test cond1est test23.m test cs_dmspy test24.m test cs_fielder test25.m test cs_nd test26.m test cs_dmsol and cs_dmspy test27.m test cs_qr, cs_utsolve, cs_qrsol test28.m test cs_randperm, cs_dmperm -------------------------------------------------------------------------------- ./MATLAB/ssget: MATLAB interface for the SuiteSparse Matrix Collection -------------------------------------------------------------------------------- See MATLAB/ssget/README.txt for details -------------------------------------------------------------------------------- ./Matrix: Sample matrices, most from Rutherford/Boeing collection -------------------------------------------------------------------------------- ash219 overdetermined pattern of Holland survey. Ashkenazi, 1974. bcsstk01 stiffness matrix for small generalized eigenvalue problem bcsstk16 stiffness matrix, Corp of Engineers dam fs_183_1 unsymmetric facsimile convergence matrix lp_afiro NETLIB afiro linear programming problem mbeacxc US economy, 1972. Dan Szyld, while at NYU t1 small example used in Chapter 2 west0067 Cavett problem with 5 components (chemical eng., Westerberg) c_mbeacxc complex version of mbeacxc c_west0067 complex version of west0067 mhd1280b Alfven spectra in magnetohydrodynamics (complex) neumann complex matrix qc324 model of H+ in an electromagnetic field (complex) t2 small complex matrix t3 small complex matrix t4 small complex matrix c4 small complex matrix young1c aeronautical problem (complex matrix) -------------------------------------------------------------------------------- ./Tcov: Exhaustive test coverage of CXSparse -------------------------------------------------------------------------------- covall same as covall.linux cov.awk coverage summary cover print uncovered lines covs print uncovered lines cstcov_malloc_test*.c malloc test cstcov_malloc_test.h cstcov_test*.c main programs for Tcov tests gcovs run gcov (Linux) Makefile Makefile for Tcov tests nil an empty matrix zero a 1-by-1 zero matrix czero a 1-by-1 complex zero matrix README.txt README file for Tcov directory Matrix/inst/doc/SuiteSparse/CXSparse/Doc/0000755000175100001440000000000014576343415017736 5ustar hornikusersMatrix/inst/doc/SuiteSparse/CXSparse/Doc/ChangeLog0000644000175100001440000003346714561103552021513 0ustar hornikusersJan 10, 2024: version 4.3.1 * minor updates to build system Dec 30, 2023: version 4.3.0 * major change to build system: by Markus Mützel * cxsparse_version: added to return CXSparse version Sept 18, 2023: version 4.2.1 * cmake update: add "None" build type, from Antonio Rojas, for Arch Linux Sept 8, 2023: version 4.2.0 * cmake updates: SuiteSparse:: namespace by Markus Muetzel * complex types: more changes for C++, from Markus Muetzel June 16, 2023: version 4.0.4 * cmake build system updates: update by Markus Muetzel * complex type: changed to work better with C++; update from Markus Muetzel Jan 17, 2023: version 4.0.3 * SuiteSparse_config: now v7.0.0 Dec 9, 2022: version 4.0.2 * minor change to build system Nov 12, 2022: version 4.0.0 * using CMake build system * integers: int (32-bit) and SuiteSparse_long (nominally 64-bit) replaced with int32_t and int64_t. cs_long_t changed to int64_t. * double _Complex: changed to "double complex". ANSI C11 required. Sept 12, 2017: version 3.2.0 * replaced UFget with ssget * added comment to cs_lu.c May 4, 2016: version 3.1.9 * minor changes to Makefile Apr 1, 2016: version 3.1.8 * licensing simplified (no other change); refer to CSparse/Doc/License.txt Feb 17, 2016: version 3.1.8beta (not released publically) * minor update to cs_sprealloc, for handling sparse empty matrices. Feb 1, 2016: version 3.1.7 * update to Makefiles Jan 30, 2016: version 3.1.6 * correction to Makefiles * correction to mexFunctions required for MATLAB R2015b, for sparse empty matrices and NULL mxGetPr Jan 1, 2016: version 3.1.5 * Makefile now creates both static (*.a) and shared (*.so / *.dylib) libraries. No change to C code except version number in cs.h. Oct 10, 2014: version 3.1.4 modified cs_make.m. No change to C code except version number. Mar 26, 2014: version 3.1.3 * minor update to UFget Apr 16, 2013: verison 3.1.2 * removed a useless line from cs_sqr.c (no integer overflow can occur in S->lnz, S->unz at that point) Jun 20, 2012: verison 3.1.1 * minor update for Windows (removed filesep) Jun 1, 2012: version 3.1.0 * now based on CSparse v3.1.0 * This version of CXSparse changes the 'long' integer from UF_long to cs_long_t. UF_long is still available to user codes, however, so this change is backward compatible with user codes. Future user codes should use cs_long_t instead of UF_long. * changed unsigned integer in cs_amd.c to signed, for hash code. * in Source, only changes are to cs_demo*.c, cs_print.c Dec 7, 2011: version 3.0.2 * fixed the Makefile to better align with CFLAGS and other standards * minor fix to MATLAB cs_install.m Jan 18, 2010: version 3.0.0 * changed "int" to "csi", which is normally "ptrdiff_t". This way, CSparse can be used on a 64-bit platform (and in 64-bit MATLAB in particular), without the need to use CXSparse. If you wish to use "int", simply edit CSparse/Include/cs.h and change the definition of csi, or compile with -Dcsi=int. Jan 25, 2011: version 2.2.5 * minor fix to "make install" * minor change to cs_util.c, typecast return (cs_free (...)) * minor fixes to UFget: help file, UFsettings.txt Nov 30, 2009: version 2.2.4 * added "make install" and "make uninstall" * minor change to cs_make.m Jan 20, 2009, v2.2.3 * all tabs expanded to 8 spaces (except for Makefiles) * example corrected in cs_gaxpy.m * minor change to cs_sparse to allow for i,j,x to be either row or column vectors (or any mixture) Sept 8, 2008, v2.2.2 * minor change to cs_make.m, to change "/" to filesep ("/" on Unix, "\" on Windows), to handle limitations in some Windows compilers Nov 1, 2007, v2.2.1 * very minor change to Include/cs.h: Changed name of 2nd argument of cs_permute, to match the code. This has no affect on the code itself, since the type ("int *") is unchanged. It's just a documentation issue. * CXSparse/MATLAB/Test ported to Windows * minor lint cleanup in mexFunctions Mar 31, 2007, v2.2.0 * few changes to primary Source/ files. Changes mostly affect MATLAB interface. * Source/cs_house.c: correction to comment * Souce/cs_updown.c: whitespace changed to reflect change in CXSparse, no impact at all on CSparse itself. * Doc/, Lib/ and Include/ directories created. * Source/cs.h moved to Include/cs.h, version number changed to 2.2.0. * modification to Makefiles, cs_make.m * correction to help comments in cs_dmperm.m, cs_qr.m, cs_scc2.m, cs_scc.m * if complex matrix passed to CSparse in MATLAB, error message suggests using CXSparse instead * minor performance fix to cs_sparse_mex.c * cs_randperm added to MATLAB/Makefile; already appeared in cs_make.m * minor improvements to MATLAB/ demos. * back-port to MATLAB 7.2 and earlier (which does not have mwIndex). * more graceful failure in cs_make when attempting complex matrix support (Windows, in particular) * correction to CXSparse/Demo/Makefile * added sizeof(CS_INT) printout to cs_idemo.c, cs_ldemo.c Mar 1, 2007, v2.1.0 * Source/cs_add.c: added test for matrix dimensions * Source/cs_multiply.c: added test for matrix dimensions * correction to MATLAB demo3 (no error in C code version of the demo) * minor corrections to MATLAB m-file help comments. * MATLAB interface added for CXSparse. * cs_complex_t type added (a #define for "double _Complex", which is the complex type used in CXSparse 2.0.x). When compiling with a C++ compiler, the std::complex type is used for the complex case. * bug fix in complex sparse Cholesky (cs_chol.c). * bug fix in complex sparse Cholesky update/downdate (cs_updown.c). * bug fix in cs_symperm for the complex case. * "beta" changed from complex to real, in sparse QR (cs_house.c, cs_happly.c, cs_qr.c), (a performance/memory improvement, not a bug fix). Similar change to "nz2" in cs_cumsum.c. Dec 12, 2006, v2.0.7 * minor MATLAB cleanup Dec 6, 2006, v2.0.6 * Update to UFget. Now relies on the MATLAB urlwrite function instead of my own Java code. Nov 2006, v2.0.5 * Added UFgrep to UFget toolbox. * No changes to C Source code, except for version number and date. * Added two test matrices: ibm32a and ibm32b. ibm32a is the Harwell/ Boeing matrix ibm32, but with the last column removed. ibm32b is the transpose of ibm32a. With optimization enabled (-O), 2 lines in cs_maxtrans.c are not tested; these matrices correct that problem. * Fixed UFget. Earlier version could not download matrices larger than 32MB. * Modified UFget/UFweb, to reflect changes in the UF Sparse Matrix Collection. * Added ccspy.m and cs_scc2.m MATLAB functions * Added examples to help info in each *.m MATLAB file * modified cs_dmspy to speed up the plotting of large matrices with many singletons * minor change to cspy: now draws a box around the matrix. * minor changes to MATLAB demos and tests. Oct 13, 2006, v2.0.4 * minor modification to cs_updown.c. "n" was incorrectly declared "double". It should be "int". This was safe, just a little confusing (n was only used in an argument to cs_malloc, and is thus typecast). Sept 28, 2006, v2.0.3 * minor modifications to MATLAB interface, to allow CSparse to be used in MATLAB 6.5. * added examples to m-files, other minor m-file cleanup. * bug fix to cspy, to handle NaN's properly. Aug 23, 2006: v2.0.2 * change to cs_updown mexFunction, to handle multiple rank updates * symbolic links removed from Tcov/ directory in the distribution. They are now created by Tcov/Makefile as needed. This makes the zip files cleaner. Tcov/*test.c test files renamed. July 19, 2006: * minor fix to cs_must_compile.m and cs_make.m, to allow CSparse to be compiled in MATLAB 6.5 with cs_make. * minor fix to cspy for complex matrices (imaginary part was ignored). * no change to version number or date, since there are no changes that affect the appearance of CSparse in the book ("Direct Methods for Sparse Linear Systems", SIAM, 2006). June 24, 2006: * minor typos in comments corrected. No change in code itself, and no change in version number or date. May 27, 2006, v2.0.1: (this version is printed in the book) * minor bug fix. cs_util.c modified, so that cs_sprealloc (T,0) works properly for a triplet matrix T (setting T->nzmax equal to T->nz). The line in v2.0.0: nzmax = (nzmax <= 0) ? (A->p [A->n]) : nzmax ; changes to the following in v2.0.1: if (nzmax <= 0) nzmax = (CS_CSC (A)) ? (A->p [A->n]) : A->nz ; * minor typographical changes arising from the editting of the book. Apr 12, 2006, v2.0.0: * random permutation option added to cs_maxtrans and cs_dmperm, to help avoid rare cases where the O(|A|n) time complexity is reached in practice (GHS_indef/boyd2 in the UF sparse matrix collection, for example). New cs_randperm function added. Apr 10, 2006: * stylistic changes for the book (except for the bug fix): * "int order" parameter of cs_amd, cs_lusol, cs_cholsol, cs_qrsol, cs_sqr, cs_schol changed. Now 0 means no ordering, 1 is A+A', 2 is S*S', and 3 is A*A'. In v1.2 and earlier, "order" took on a value ranging from -1 to 2. "int n" parameter rearranged for cs_ipvec, cs_pvec, cs_post (int n moved to the end). cs_triplet renamed cs_compress. To ensure that these changes are propagated into user code that calls CSparse, the "order" parameter has been placed as the first parameter in all these routines. Your compiler will complain (gcc will halt) if you upgrade from v1.2 to v2.0 without changing your code. This is much better than a silent error in which you get the wrong ordering by mistake (with a huge penalty in run-time performance and no compiler warnings). New syntax (v2.0 and later): ---------------------------- order = 0: natural ordering order = 1: amd (A+A') order = 2: amd (S'*S), where S=A except dense rows dropped order = 3: amd (A'*A) int cs_cholsol (int order, const cs *A, double *b) ; int cs_lusol (int order, const cs *A, double *b, double tol) ; int cs_qrsol (int order, const cs *A, double *b) ; int *cs_amd (int order, const cs *A) ; css *cs_schol (int order, const cs *A) ; css *cs_sqr (int order, const cs *A, int qr) ; int *cs_post (const int *parent, int n) ; int cs_ipvec (const int *p, const double *b, double *x, int n) ; int cs_pvec (const int *p, const double *b, double *x, int n) ; cs *cs_compress (const cs *T) ; Old syntax (v1.2 and earlier): ------------------------------ order = -1: natural ordering order = 0: amd (A+A') order = 1: amd (S'*S), where S=A except dense rows dropped order = 2: amd (A'*A) int cs_cholsol (const cs *A, double *b, int order) ; int cs_lusol (const cs *A, double *b, int order, double tol) ; int cs_qrsol (const cs *A, double *b, int order) ; int *cs_amd (const cs *A, int order) ; css *cs_schol (const cs *A, int order) ; css *cs_sqr (const cs *A, int order, int qr) ; int *cs_post (int n, const int *parent) ; int cs_ipvec (int n, const int *p, const double *b, double *x) ; int cs_pvec (int n, const int *p, const double *b, double *x) ; cs *cs_triplet (const cs *T) ; * CS_OVERFLOW macro removed (removed from cs_malloc.c; not needed). * S->leftmost added to css (it was tacked onto S->pinv before). * P,Q,R,S components of csd struct changed to p,q,r,s. * Pinv and Q components of css struct changed to pinv and q. * CS_CSC and CS_TRIPLET macros added, to clarify which CSparse functions accept cs matrices in compressed column form, triplet form, or both. * check for negative row/column indices added to cs_entry. * cs_ereach and cs_leaf functions added. * call to cs_sprealloc added to cs_fkeep. * bug fixes in cs_counts and cs_amd (memory leak under rare out-of-memory conditions). Mar 15, 2006: * cs_scc modified so that the row and columns of each component are put in their natural order. cs_dmperm modified so that columns of each block (instead of rows) are placed in their natural order. * cs_splsolve renamed cs_spsolve, generalized to handle both Lx=b and Ux=b, and non-unit diagonal, and placed in its own file (cs_spsolve.c; it was a static function in cs_lu.c). cs_lsolve_mex.c and cs_splsolve_mex.c merged (the latter was removed). cs_spsolve.c file added * cs_dmspy changed, so that block borders line up better with the matrix. Mar 6, 2006: * Makefile modified so that the Tcov tests (which may not be portable) are not compiled and run by the default "make" in the CSparse directory. To compile everything, including the Tcov tests, use "make all". Trivial change to cs.h. Feb 27, 2006: * cs_reach, cs_dfs, cs_splsolve, cs_lu, and cs_scc changed to remove O(n) initialized workspace. * cs_reach and cs_splsolve now user-callable (were static in cs_lu.c). Feb 20, 2006: * various changes to simplify the construction of CXSparse Feb 7, 2006: * changed prototypes, adding "const" where appropriate. Matrix/inst/doc/SuiteSparse/CXSparse/Doc/License.txt0000644000175100001440000000157514552026002022051 0ustar hornikusersCXSparse: a Concise Sparse matrix package - Extended. Copyright (c) 2006, Timothy A. Davis. http://www.suitesparse.com -------------------------------------------------------------------------------- CXSparse is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. CXSparse 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Matrix/inst/doc/SuiteSparse/LICENSE.txt0000644000175100001440000015300714552026002017352 0ustar hornikusersThis file lists all licenses for all packages in SuiteSparse, for your convenience. Each package has its own separate license, which can be found in the lists below. ==> SPEX/License/license.txt <== SPEX: a Sparse Left-looking Integer-Preserving LU Factorization Copyright (c) 2019-2023, Christopher Lourenco, JinHao Chen, Erick Moreno- Centeno, and Timothy A. Davis. Available at: https://github.com/clouren/SPEX http://suitesparse.com Contact Chris Lourenco, chrisjlourenco@gmail.com, or Tim Davis (timdavis@aldenmath.com or DrTimothyAldenDavis@gmail.com) for a commercial license. -------------------------------------------------------------------------------- SPEX is free software; you can redistribute it and/or modify it under the terms of either: * the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. or * 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. or both in parallel, as here. SPEX 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 copies of the GNU General Public License and the GNU Lesser General Public License along with this software. If not, see https://www.gnu.org/licenses/. ==> AMD/Doc/License.txt <== AMD, Copyright (c), 1996-2023, Timothy A. Davis, Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. Availability: http://suitesparse.com ------------------------------------------------------------------------------- AMD License: BSD 3-clause: ------------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the organizations to which the authors are affiliated, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==> BTF/Doc/License.txt <== BTF, Copyright (C) 2004-2023, University of Florida by Timothy A. Davis and Ekanathan Palamadai. BTF is also available under other licenses; contact authors for details. http://suitesparse.com -------------------------------------------------------------------------------- BTF is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. BTF 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ==> CAMD/Doc/License.txt <== CAMD, Copyright (c) by Timothy A. Davis, Yanqing Chen, Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. CAMD is available under alternate licenses, contact T. Davis for details. CAMD License: BSD 3-clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the organizations to which the authors are affiliated, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Availability: http://suitesparse.com ==> CCOLAMD/Doc/License.txt <== CCOLAMD: constrained column approximate minimum degree ordering Copyright (C) 2005-2023, Univ. of Florida. Authors: Timothy A. Davis, Sivasankaran Rajamanickam, and Stefan Larimore. Closely based on COLAMD by Davis, Stefan Larimore, in collaboration with Esmond Ng, and John Gilbert. http://suitesparse.com -------------------------------------------------------------------------------- CCOLAMD license: BSD 3-clause: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the organizations to which the authors are affiliated, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- ==> CHOLMOD/Doc/License.txt <== -------------------------------------------------------------------------------- ==> Check/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Check Module. Copyright (C) 2005-2023, Timothy A. Davis CHOLMOD is also available under other licenses; contact authors for details. http://suitesparse.com Note that this license is for the CHOLMOD/Check module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This Module 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -------------------------------------------------------------------------------- ==> Cholesky/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Cholesky module, Copyright (C) 2005-2023, Timothy A. Davis. CHOLMOD is also available under other licenses; contact authors for details. http://suitesparse.com Note that this license is for the CHOLMOD/Cholesky module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This Module 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -------------------------------------------------------------------------------- ==> Utility/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Utility Module, Copyright (C) 2023, Timothy A. Davis. CHOLMOD is also available under other licenses; contact authors for details. http://suitesparse.com Note that this license is for the CHOLMOD/Utility module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This Module 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -------------------------------------------------------------------------------- ==> Demo/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Demo Module. Copyright (C) 2005-2023, Timothy A. Davis. CHOLMOD is also available under other licenses; contact authors for details. http://suitesparse.com Note that this license is for the CHOLMOD/Demo module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module 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 Module 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 Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -------------------------------------------------------------------------------- ==> Include/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Include/* files. Copyright (C) 2005-2023 CHOLMOD/Include/cholmod.h SPDX-License-Identifier: Apache-2.0 CHOLMOD/Include/cholmod_internal.h SPDX-License-Identifier: Apache-2.0 CHOLMOD/Include/cholmod_template.h SPDX-License-Identifier: Apache-2.0 CHOLMOD/Include/cholmod_types.h SPDX-License-Identifier: Apache-2.0 -------------------------------------------------------------------------------- ==> MATLAB/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/MATLAB Module. Copyright (C) 2005-2023, Timothy A. Davis. CHOLMOD is also available under other licenses; contact authors for details. MATLAB(tm) is a Registered Trademark of The MathWorks, Inc. http://suitesparse.com Note that this license is for the CHOLMOD/MATLAB module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module 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 Module 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 Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -------------------------------------------------------------------------------- ==> MatrixOps/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/MatrixOps Module. Copyright (C) 2005-2023, Timothy A. Davis. CHOLMOD is also available under other licenses; contact authors for details. http://suitesparse.com Note that this license is for the CHOLMOD/MatrixOps module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module 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 Module 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 Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -------------------------------------------------------------------------------- ==> Modify/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Modify Module. Copyright (C) 2005-2023, Timothy A. Davis and William W. Hager. CHOLMOD is also available under other licenses; contact authors for details. http://suitesparse.com Note that this license is for the CHOLMOD/Modify module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module 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 Module 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 Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -------------------------------------------------------------------------------- ==> Partition/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Partition Module. Copyright (C) 2005-2023, Univ. of Florida. Author: Timothy A. Davis CHOLMOD is also available under other licenses; contact authors for details. http://suitesparse.com Note that this license is for the CHOLMOD/Partition module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This Module 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -------------------------------------------------------------------------------- ==> Supernodal/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Supernodal Module. Copyright (C) 2005-2023, Timothy A. Davis CHOLMOD is also available under other licenses; contact authors for details. http://suitesparse.com Note that this license is for the CHOLMOD/Supernodal module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module 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 Module 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 Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -------------------------------------------------------------------------------- ==> Tcov/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Tcov Module. Copyright (C) 2005-2023, Timothy A. Davis CHOLMOD is also available under other licenses; contact authors for details. http://suitesparse.com Note that this license is for the CHOLMOD/Tcov module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module 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 Module 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 Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -------------------------------------------------------------------------------- ==> Valgrind/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Valgrind Module. Copyright (C) 2005-2023, Timothy A. Davis. CHOLMOD is also available under other licenses; contact authors for details. http://suitesparse.com Note that this license is for the CHOLMOD/Valgrind module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module 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 Module 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 Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. ==> COLAMD/Doc/License.txt <== COLAMD, Copyright 1998-2023, Timothy A. Davis. http://suitesparse.com http://suitesparse.com COLAMD License: BSD 3-clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the organizations to which the authors are affiliated, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==> CSparse/Doc/License.txt <== CSparse: a Concise Sparse matrix package. Copyright (c) 2006-2023, Timothy A. Davis. http://suitesparse.com -------------------------------------------------------------------------------- CSparse is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. CSparse 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ==> CXSparse/Doc/License.txt <== CXSparse: a Concise Sparse matrix package - Extended. Copyright (c) 2006-2023, Timothy A. Davis. http://suitesparse.com -------------------------------------------------------------------------------- CXSparse is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. CXSparse 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ==> CXSparse_newfiles/Doc/License.txt <== CXSparse: a Concise Sparse matrix package - Extended. Copyright (c) 2006-2023, Timothy A. Davis. http://suitesparse.com -------------------------------------------------------------------------------- CXSparse is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. CXSparse 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ==> SPQR/GPUQREngine/Doc/License.txt <== SPQR/GPUQREngine Copyright (c) 2013-2023, Timothy A. Davis, Sencer Nuri Yeralan, and Sanjay Ranka. http://suitesparse.com SPQR/GPUQREngine 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. SPQR/GPUQREngine 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 Module; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ==> KLU/Doc/License.txt <== KLU, Copyright (C) 2004-2023, University of Florida by Timothy A. Davis and Ekanathan Palamadai. KLU is also available under other licenses; contact authors for details. http://suitesparse.com -------------------------------------------------------------------------------- KLU is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. KLU 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ==> LDL/Doc/License.txt <== LDL Copyright (c) 2005-2023 by Timothy A. Davis. LDL is also available under other licenses; contact the author for details. http://suitesparse.com -------------------------------------------------------------------------------- LDL is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. LDL 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ==> MATLAB_Tools/Doc/License.txt <== The MATLAB_Tools collection of packages is Copyright (c), Timothy A. Davis, All Rights Reserved, with the exception of the spqr_rank package, which is Copyright (c), Timothy A. Davis and Les Foster, All Rights Reserved, All packages are available under alternative licenses. Contact the authors for details. -------------------------------------------------------------------------------- MATLAB_Tools License, with the exception of SSMULT and SuiteSparseCollection: -------------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the organizations to which the authors are affiliated, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- SuiteSparseCollection License: -------------------------------------------------------------------------------- SuiteSparseCollection 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. SuiteSparseCollection 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 package; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -------------------------------------------------------------------------------- SSMULT License: -------------------------------------------------------------------------------- SSMULT, Copyright (c) 2007-2023, Timothy A. Davis, http://suitesparse.com. SSMULT 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. SSMULT 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 package; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ==> RBio/Doc/License.txt <== RBio toolbox. Copyright (C) 2006-2023, Timothy A. Davis RBio is also available under other licenses; contact authors for details. http://suitesparse.com -------------------------------------------------------------------------------- RBio 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. RBio 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 Module; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ==> SPQR/Doc/License.txt <== SPQR, Copyright 2008-2023 by Timothy A. Davis. All Rights Reserved. SPQR is available under alternate licenses, contact T. Davis for details. SPQR License: Your use or distribution of SPQR or any modified version of SPQR implies that you agree to this License. This library 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 library 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 library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Permission is hereby granted to use or copy this program under the terms of the GNU GPL, 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 this code or any modified version of this 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. Availability: http://suitesparse.com ==> SPQR/GPURuntime/Doc/License.txt <== SPQR/GPURuntime Copyright (c) 2013-2023, Timothy A. Davis, Sencer Nuri Yeralan, and Sanjay Ranka. http://suitesparse.com -------------------------------------------------------------------------------- SPQR/GPURuntime 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. SPQR/GPURuntime 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 Module; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ==> ssget/Doc/License.txt <== Copyright (c), 2009-2023, Timothy A. Davis, All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the organizations to which the authors are affiliated, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==> UMFPACK/Doc/License.txt <== UMFPACK, Copyright 1995-2023, by Timothy A. Davis. All Rights Reserved. UMFPACK is available under alternate licenses, contact T. Davis for details. UMFPACK License: Your use or distribution of UMFPACK or any modified version of UMFPACK implies that you agree to this License. This library 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 library 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 library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Permission is hereby granted to use or copy this program under the terms of the GNU GPL, 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 this code or any modified version of this 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. Availability: http://suitesparse.com ==> CSparse/MATLAB/ssget/Doc/License.txt <== Copyright (c), 2009-2023, Timothy A. Davis, All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the organizations to which the authors are affiliated, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==> CXSparse/MATLAB/ssget/Doc/License.txt <== Copyright (c), 2009-2023, Timothy A. Davis, All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the organizations to which the authors are affiliated, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==> GraphBLAS/LICENSE <== SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved. The following Apache-2.0 applies to all of SuiteSparse:GraphBLAS except for the @GrB MATLAB interface: SPDX-License-Identifier: Apache-2.0 Licensed under the Apache License, Version 2.0 (the "License"); you may not use SuiteSparse:GraphBLAS except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. No files that are compiled and packaged as part of the libgraphblas.so or libgraphblas.a libraries are licensed under the GNU GPLv3. All of those files are licensed under the Apache-2.0 license. ================================================================================ The @GrB MATLAB interface, including its test suite and demos (all files in the GraphBLAS/GraphBLAS folder) are not under the above Apache-2.0 license, but under the GNU GPLv3 (or later) license instead. Refer to the file GraphBLAS/GraphBLAS/@GrB/LICENSE for details. All files throughout this package and the @GrB MATLAB interface are tagged with an SPDX license identifier, file by file. Either: SPDX-License-Identifier: Apache-2.0 or, for the @GrB MATLAB interface, its test suite, and demos: SPDX-License-Identifier: GPL-3.0-or-later ==> Mongoose License <== Mongoose, Copyright 2018-2023, Timothy A. Davis, Scott P. Kolodziej, William W. Hager, S. Nuri Yeralan Licensed under the GNU GENERAL PUBLIC LICENSE, Version 3, 29 June 2007 ==> Example License <== Example package, Copyright (c), 2023, Timothy A. Davis, All Rights Reserved. SPDX-License-Identifier: BSD-3-clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the organizations to which the authors are affiliated, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==> ParU License <== ParU package, Copyright (c), 2023, Mohsen Aznaveh and Timothy A. Davis, All Rights Reserved. SPDX-License-Identifier: GPL-3.0-or-later ==> LAGraph License <== SPDX-License-Identifier: BSD-2-clause File: LICENSE LAGraph Copyright 2019-2023 LAGraph Contributors. All Rights Reserved. (see Contributors.txt for a full list of Contributors; see ContributionInstructions.txt for information on how you can Contribute to this project). BSD Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. ACKNOWLEDGMENTS AND DISCLAIMERS: This program includes and/or can make use of certain third party source code, object code, documentation and other files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and conditions contained in any such Third Party Software or separate license file distributed with such Third Party Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party beneficiaries to this License with respect to the terms applicable to their Third Party Software. Third Party Software licenses only apply to the Third Party Software and not any other portion of this program or this program as a whole. Created, in part, with funding and support from the United States Government. (see Acknowledgments.txt file). NO WARRANTY. THIS MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. THE LAGRAPH CONTRIBUTORS MAKE NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. THE CONTRIBUTORS DO NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT. DM22-0790 Matrix/inst/doc/SuiteSparse/README.md0000644000175100001440000012304014561103552017006 0ustar hornikusers----------------------------------------------------------------------------- SuiteSparse: A Suite of Sparse matrix packages at http://suitesparse.com ----------------------------------------------------------------------------- Jan 20, 2024, SuiteSparse VERSION 7.6.0 SuiteSparse is a set of sparse-matrix-related packages written or co-authored by Tim Davis, available at https://github.com/DrTimothyAldenDavis/SuiteSparse . Primary author of SuiteSparse (codes and algorithms, excl. METIS): Tim Davis Code co-authors, in alphabetical order (not including METIS or LAGraph): Patrick Amestoy, Mohsen Aznaveh, David Bateman, Jinhao Chen, Yanqing Chen, Iain Duff, Joe Eaton, Les Foster, William Hager, Raye Kimmerer, Scott Kolodziej, Chris Lourenco, Stefan Larimore, Lorena Mejia Domenzain, Erick Moreno-Centeno, Markus Mützel, Corey Nolel, Ekanathan Palamadai, Sivasankaran Rajamanickam, Sanjay Ranka, Wissam Sid-Lakhdar, and Nuri Yeralan. LAGraph has been developed by the highest number of developers of any of the packages in SuiteSparse and deserves its own list. The list also appears in LAGraph/Contibutors.txt: Janos B. Antal, Budapest University of Technology and Economics, Hungary Mohsen Aznaveh, Texas A&M University David A. Bader New Jersey Institute of Technology Aydin Buluc, Lawrence Berkeley National Lab Jinhao Chen, Texas A&M University Tim Davis, Texas A&M University Florentin Dorre, Technische Univeritat Dresden, Neo4j Marton Elekes, Budapest University of Technology and Economics, Hungary Balint Hegyi, Budapest University of Technology and Economics, Hungary Tanner Hoke, Texas A&M University James Kitchen, Anaconda Scott Kolodziej, Texas A&M University Pranav Konduri, Texas A&M University Roi Lipman, Redis Labs (now FalkorDB) Tze Meng Low, Carnegie Mellon University Tim Mattson, Intel Scott McMillan, Carnegie Mellon University Markus Muetzel Michel Pelletier, Graphegon Gabor Szarnyas, CWI Amsterdam, The Netherlands Erik Welch, Anaconda, NVIDIA Carl Yang, University of California at Davis, Waymo Yongzhe Zhang, SOKENDAI, Japan METIS is authored by George Karypis. Additional algorithm designers: Esmond Ng and John Gilbert. Refer to each package for license, copyright, and author information. ----------------------------------------------------------------------------- Documentation ----------------------------------------------------------------------------- Refer to each package for the documentation on each package, typically in the Doc subfolder. ----------------------------------------------------------------------------- SuiteSparse branches ----------------------------------------------------------------------------- * dev: the default branch, with recent updates of features to appear in the next stable release. The intent is to keep this branch in fully working order at all times, but the features will not be finalized at any given time. * stable: the most recent stable release. * dev2: working branch. All submitted PRs should made to this branch. This branch might not always be in working order. ----------------------------------------------------------------------------- SuiteSparse Packages ----------------------------------------------------------------------------- Packages in SuiteSparse, and files in this directory: * `AMD` approximate minimum degree ordering. This is the built-in AMD function in MATLAB. authors: Tim Davis, Patrick Amestoy, Iain Duff * `bin` where programs are placed when compiled, for `make local` * `BTF` permutation to block triangular form authors: Tim Davis, Ekanathan Palamadai * `build` folder for default build tree * `CAMD` constrained approximate minimum degree ordering authors: Tim Davis, Patrick Amestoy, Iain Duff, Yanqing Chen * `CCOLAMD` constrained column approximate minimum degree ordering authors: Tim Davis, Sivasankaran Rajamanickam, Stefan Larimore. Algorithm design collaborators: Esmond Ng, John Gilbert (for COLAMD) * `ChangeLog` a summary of changes to SuiteSparse. See `*/Doc/ChangeLog` for details for each package. * `CHOLMOD` sparse Cholesky factorization. Requires AMD, COLAMD, CCOLAMD, the BLAS, and LAPACK. Optionally uses METIS. This is `chol` and `x=A\b` in MATLAB. author for all modules: Tim Davis CHOLMOD/Modify module authors: Tim Davis and William W. Hager CHOLMOD/SuiteSparse_metis: a modified version of METIS, embedded into the CHOLMOD library. See the README.txt files for details. author: George Karypis. This is a slightly modified copy included with SuiteSparse via the open-source license provided by George Karypis. SuiteSparse cannot use an unmodified copy of METIS. * `CITATION.bib` citations for SuiteSparse packages, in bibtex format. * `CMakeLists.txt` optional, to compile all of SuiteSparse. See below. * `CODE_OF_CONDUCT.md` community guidelines * `COLAMD` column approximate minimum degree ordering. This is the built-in COLAMD function in MATLAB. authors (of the code): Tim Davis and Stefan Larimore Algorithm design collaborators: Esmond Ng, John Gilbert * `Contents.m` a list of contents for 'help SuiteSparse' in MATLAB. * `CONTRIBUTING.md` how to contribute to SuiteSparse * `CONTRIBUTOR-LICENSE.txt` required contributor agreement * `CSparse` a concise sparse matrix package, developed for my book, "Direct Methods for Sparse Linear Systems", published by SIAM. Intended primarily for teaching. Note that the code is (c) Tim Davis, as stated in the book. For production, use CXSparse instead. In particular, both CSparse and CXSparse have the same include filename: `cs.h`. This package is used for the built-in DMPERM in MATLAB. author: Tim Davis * `CXSparse` CSparse Extended. Includes support for complex matrices and both int or long integers. Use this instead of CSparse for production use; it creates a libcsparse.so (or dylib on the Mac) with the same name as CSparse. It is a superset of CSparse. Any code that links against CSparse should also be able to link against CXSparse instead. author: Tim Davis, David Bateman * `Example` a simple package that relies on almost all of SuiteSparse * `.github` workflows for CI testing on GitHub. * `GraphBLAS` graph algorithms in the language of linear algebra. https://graphblas.org authors: Tim Davis, Joe Eaton, Corey Nolet * `include` `make install` places user-visible include files for each package here, after `make local`. * `KLU` sparse LU factorization, primarily for circuit simulation. Requires AMD, COLAMD, and BTF. Optionally uses CHOLMOD, CAMD, CCOLAMD, and METIS. authors: Tim Davis, Ekanathan Palamadai * `LAGraph` a graph algorithms library based on GraphBLAS. See also https://github.com/GraphBLAS/LAGraph Authors: many. * `LDL` a very concise LDL' factorization package author: Tim Davis * `lib` `make install` places shared libraries for each package here, after `make local`. * `LICENSE.txt` collected licenses for each package. * `Makefile` optional, to compile all of SuiteSparse using `make`, which is used as a simple wrapper for `cmake` in each subproject. * `make` compiles SuiteSparse libraries. Subsequent `make install` will install in `CMAKE_INSTALL_PATH` (might default to `/usr/local/lib` on Linux or Mac). * `make local` compiles SuiteSparse. Subsequent `make install` will install in `./lib`, `./include`. Does not install in `CMAKE_INSTALL_PATH`. * `make global` compiles SuiteSparse libraries. Subsequent `make install` will install in `/usr/local/lib` (or whatever the configured `CMAKE_INSTALL_PREFIX` is). Does not install in `./lib` and `./include`. * `make install` installs in the current directory (`./lib`, `./include`), or in `/usr/local/lib` and `/usr/local/include`, (the latter defined by `CMAKE_INSTALL_PREFIX`) depending on whether `make`, `make local`, or `make global` has been done. * `make uninstall` undoes `make install`. * `make distclean` removes all files not in distribution, including `./bin`, `./share`, `./lib`, and `./include`. * `make purge` same as `make distclean`. * `make clean` removes all files not in distribution, but keeps compiled libraries and demos, `./lib`, `./share`, and `./include`. Each individual subproject also has each of the above `make` targets. Things you don't need to do: * `make docs` creates user guides from LaTeX files * `make cov` runs statement coverage tests (Linux only) * `MATLAB_Tools` various m-files for use in MATLAB author: Tim Davis (all parts) for `spqr_rank`: author Les Foster and Tim Davis * `Contents.m` list of contents * `dimacs10` loads matrices for DIMACS10 collection * `Factorize` object-oriented `x=A\b` for MATLAB * `find_components` finds connected components in an image * `GEE` simple Gaussian elimination * `getversion.m` determine MATLAB version * `gipper.m` create MATLAB archive * `hprintf.m` print hyperlinks in command window * `LINFACTOR` predecessor to `Factorize` package * `MESHND` nested dissection ordering of regular meshes * `pagerankdemo.m` illustrates how PageRank works * `SFMULT` `C=S*F` where `S` is sparse and `F` is full * `shellgui` display a seashell * `sparseinv` sparse inverse subset * `spok` check if a sparse matrix is valid * `spqr_rank` SPQR_RANK package. MATLAB toolbox for rank deficient sparse matrices: null spaces, reliable factorizations, etc. With Leslie Foster, San Jose State Univ. * `SSMULT` `C=A*B` where `A` and `B` are both sparse. This was the basis for the built-in `C=A*B` in MATLAB, until it was superseded by GraphBLAS in MATLAB R2021a. * `SuiteSparseCollection` for the SuiteSparse Matrix Collection * `waitmex` waitbar for use inside a mexFunction * `Mongoose` graph partitioning. authors: Nuri Yeralan, Scott Kolodziej, William Hager, Tim Davis * `ParU` a parallel unsymmetric pattern multifrontal method. Currently a pre-release. authors: Mohsen Aznaveh and Tim Davis * `RBio` read/write sparse matrices in Rutherford/Boeing format author: Tim Davis * `README.md` this file * `SPEX` solves sparse linear systems in exact arithmetic. Requires the GNU GMP and MPRF libraries. This will be soon replaced by a more general package, SPEX v3 that includes this method (exact sparse LU) and others (sparse exact Cholesky, and sparse exact update/downdate). The API of v3 will be changing significantly. authors: Chris Lourenco, Jinhao Chen, Erick Moreno-Centeno, Lorena Lorena Mejia Domenzain, and Tim Davis. See https://github.com/clouren/SPEX for the latest version. * `SPQR` sparse QR factorization. This the built-in `qr` and `x=A\b` in MATLAB. Also called SuiteSparseQR. Includes two GPU libraries: `SPQR/GPUQREngine` and `SPQR/SuiteSparse_GPURuntime`. author of the CPU code: Tim Davis author of GPU modules: Tim Davis, Nuri Yeralan, Wissam Sid-Lakhdar, Sanjay Ranka * `ssget` MATLAB interface to the SuiteSparse Matrix Collection author: Tim Davis * `SuiteSparse_config` library with common functions and configuration for all the above packages. `CSparse`, `GraphBLAS`, `LAGraph`, and `MATLAB_Tools` do not use `SuiteSparse_config`. author: Tim Davis * `SuiteSparse_demo.m` a demo of SuiteSparse for MATLAB * `SuiteSparse_install.m` install SuiteSparse for MATLAB * `SuiteSparse_paths.m` set paths for SuiteSparse MATLAB mexFunctions * `SuiteSparse_test.m` exhaustive test for SuiteSparse in MATLAB * `UMFPACK` sparse LU factorization. Requires `AMD` and the `BLAS`. This is the built-in `lu` and `x=A\b` in MATLAB. author: Tim Davis algorithm design collaboration: Iain Duff Refer to each package for license, copyright, and author information. All codes are authored or co-authored by Timothy A. Davis (email: davis@tamu.edu), except for METIS (by George Karypis), `GraphBLAS/cpu_features` (by Google), GraphBLAS/lz4, zstd, and xxHash (by Yann Collet, now at Facebook), and GraphBLAS/CUDA/jitify.hpp (by NVIDIA). Parts of GraphBLAS/CUDA are Copyright (c) by NVIDIA. Please refer to each of these licenses. ----------------------------------------------------------------------------- For distro maintainers (Linux, homebrew, spack, R, Octave, Trilinos, ...): ----------------------------------------------------------------------------- Thanks for packaging SuiteSparse! Here are some suggestions: * GraphBLAS takes a long time to compile because it creates many fast "FactoryKernels" at compile-time. If you want to reduce the compile time and library size, enable the `GRAPHBLAS_COMPACT` mode, but keep the JIT compiler enabled. Then GraphBLAS will compile the kernels it needs at run-time, via its JIT compiler. Performance will be the same as the FactoryKernels once the JIT kernels are compiled. User compiled kernels are placed in `~/.SuiteSparse`, by default. You do not need to distribute the source for GraphBLAS to enable the JIT compiler: just `libgraphblas.so` and `GraphBLAS.h` is enough. * GraphBLAS needs OpenMP! It's fundamentally a parallel code so please distribute it with OpenMP enabled. Performance will suffer otherwise. * CUDA acceleration: CHOLMOD and SPQR can benefit from their CUDA kernels. If you do not have CUDA or do not want to include it in your distro, this version of SuiteSparse skips the building of the `CHOLMOD_CUDA` and `SPQR_CUDA` libraries, and does not link against the `GPUQREngine` and `SuiteSparse_GPURuntime` libraries. ----------------------------------------------------------------------------- How to cite the SuiteSparse meta-package and its component packages: ----------------------------------------------------------------------------- SuiteSparse is a meta-package of many packages, each with their own published papers. To cite the whole collection, use the URLs: * https://github.com/DrTimothyAldenDavis/SuiteSparse * http://suitesparse.com (which is a forwarding URL to https://people.engr.tamu.edu/davis/suitesparse.html) Please also cite the specific papers for the packages you use. This is a long list; if you want a shorter list, just cite the most recent "Algorithm XXX:" papers in ACM TOMS, for each package. * For the MATLAB x=A\b, see below for AMD, COLAMD, CHOLMOD, UMFPACK, and SuiteSparseQR (SPQR). * for GraphBLAS, and C=AB in MATLAB (sparse-times-sparse): T. A. Davis. Algorithm 1037: SuiteSparse:GraphBLAS: Parallel Graph Algorithms in the Language of Sparse Linear Algebra. ACM Trans. Math. Softw. 49, 3, Article 28 (September 2023), 30 pages. https://doi.org/10.1145/3577195 T. Davis, Algorithm 1000: SuiteSparse:GraphBLAS: graph algorithms in the language of sparse linear algebra, ACM Trans on Mathematical Software, vol 45, no 4, Dec. 2019, Article No 44. https://doi.org/10.1145/3322125. * for LAGraph: G. Szárnyas et al., "LAGraph: Linear Algebra, Network Analysis Libraries, and the Study of Graph Algorithms," 2021 IEEE International Parallel and Distributed Processing Symposium Workshops (IPDPSW), Portland, OR, USA, 2021, pp. 243-252. https://doi.org/10.1109/IPDPSW52791.2021.00046. * for CSparse/CXSParse: T. A. Davis, Direct Methods for Sparse Linear Systems, SIAM Series on the Fundamentals of Algorithms, SIAM, Philadelphia, PA, 2006. https://doi.org/10.1137/1.9780898718881 * for SuiteSparseQR (SPQR): (also cite AMD, COLAMD): T. A. Davis, Algorithm 915: SuiteSparseQR: Multifrontal multithreaded rank-revealing sparse QR factorization, ACM Trans. on Mathematical Software, 38(1), 2011, pp. 8:1--8:22. https://doi.org/10.1145/2049662.2049670 * for SuiteSparseQR/GPU: Sencer Nuri Yeralan, T. A. Davis, Wissam M. Sid-Lakhdar, and Sanjay Ranka. 2017. Algorithm 980: Sparse QR Factorization on the GPU. ACM Trans. Math. Softw. 44, 2, Article 17 (June 2018), 29 pages. https://doi.org/10.1145/3065870 * for CHOLMOD: (also cite AMD, COLAMD): Y. Chen, T. A. Davis, W. W. Hager, and S. Rajamanickam, Algorithm 887: CHOLMOD, supernodal sparse Cholesky factorization and update/downdate, ACM Trans. on Mathematical Software, 35(3), 2008, pp. 22:1--22:14. https://dl.acm.org/doi/abs/10.1145/1391989.1391995 T. A. Davis and W. W. Hager, Dynamic supernodes in sparse Cholesky update/downdate and triangular solves, ACM Trans. on Mathematical Software, 35(4), 2009, pp. 27:1--27:23. https://doi.org/10.1145/1462173.1462176 * for CHOLMOD/Modify Module: (also cite AMD, COLAMD): T. A. Davis and William W. Hager, Row Modifications of a Sparse Cholesky Factorization SIAM Journal on Matrix Analysis and Applications 2005 26:3, 621-639. https://doi.org/10.1137/S089547980343641X T. A. Davis and William W. Hager, Multiple-Rank Modifications of a Sparse Cholesky Factorization SIAM Journal on Matrix Analysis and Applications 2001 22:4, 997-1013. https://doi.org/10.1137/S0895479899357346 T. A. Davis and William W. Hager, Modifying a Sparse Cholesky Factorization, SIAM Journal on Matrix Analysis and Applications 1999 20:3, 606-627. https://doi.org/10.1137/S0895479897321076 * for CHOLMOD/GPU Modules: Steven C. Rennich, Darko Stosic, Timothy A. Davis, Accelerating sparse Cholesky factorization on GPUs, Parallel Computing, Vol 59, 2016, pp 140-150. https://doi.org/10.1016/j.parco.2016.06.004 * for AMD and CAMD: P. Amestoy, T. A. Davis, and I. S. Duff, Algorithm 837: An approximate minimum degree ordering algorithm, ACM Trans. on Mathematical Software, 30(3), 2004, pp. 381--388. https://dl.acm.org/doi/abs/10.1145/1024074.1024081 P. Amestoy, T. A. Davis, and I. S. Duff, An approximate minimum degree ordering algorithm, SIAM J. Matrix Analysis and Applications, 17(4), 1996, pp. 886--905. https://doi.org/10.1137/S0895479894278952 * for COLAMD, SYMAMD, CCOLAMD, and CSYMAMD: T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, Algorithm 836: COLAMD, an approximate column minimum degree ordering algorithm, ACM Trans. on Mathematical Software, 30(3), 2004, pp. 377--380. https://doi.org/10.1145/1024074.1024080 T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, A column approximate minimum degree ordering algorithm, ACM Trans. on Mathematical Software, 30(3), 2004, pp. 353--376. https://doi.org/10.1145/1024074.1024079 * for UMFPACK: (also cite AMD and COLAMD): T. A. Davis, Algorithm 832: UMFPACK - an unsymmetric-pattern multifrontal method with a column pre-ordering strategy, ACM Trans. on Mathematical Software, 30(2), 2004, pp. 196--199. https://dl.acm.org/doi/abs/10.1145/992200.992206 T. A. Davis, A column pre-ordering strategy for the unsymmetric-pattern multifrontal method, ACM Trans. on Mathematical Software, 30(2), 2004, pp. 165--195. https://dl.acm.org/doi/abs/10.1145/992200.992205 T. A. Davis and I. S. Duff, A combined unifrontal/multifrontal method for unsymmetric sparse matrices, ACM Trans. on Mathematical Software, 25(1), 1999, pp. 1--19. https://doi.org/10.1145/305658.287640 T. A. Davis and I. S. Duff, An unsymmetric-pattern multifrontal method for sparse LU factorization, SIAM J. Matrix Analysis and Computations, 18(1), 1997, pp. 140--158. https://doi.org/10.1137/S0895479894246905 * for the FACTORIZE m-file: T. A. Davis, Algorithm 930: FACTORIZE, an object-oriented linear system solver for MATLAB, ACM Trans. on Mathematical Software, 39(4), 2013, pp. 28:1-28:18. https://doi.org/10.1145/2491491.2491498 * for KLU and BTF (also cite AMD and COLAMD): T. A. Davis and Ekanathan Palamadai Natarajan. 2010. Algorithm 907: KLU, A Direct Sparse Solver for Circuit Simulation Problems. ACM Trans. Math. Softw. 37, 3, Article 36 (September 2010), 17 pages. https://dl.acm.org/doi/abs/10.1145/1824801.1824814 * for LDL: T. A. Davis. Algorithm 849: A concise sparse Cholesky factorization package. ACM Trans. Math. Softw. 31, 4 (December 2005), 587–591. https://doi.org/10.1145/1114268.1114277 * for ssget and the SuiteSparse Matrix Collection: T. A. Davis and Yifan Hu. 2011. The University of Florida sparse matrix collection. ACM Trans. Math. Softw. 38, 1, Article 1 (November 2011), 25 pages. https://doi.org/10.1145/2049662.2049663 Kolodziej et al., (2019). The SuiteSparse Matrix Collection Website Interface. Journal of Open Source Software, 4(35), 1244. https://doi.org/10.21105/joss.01244 * for `spqr_rank`: Leslie V. Foster and T. A. Davis. 2013. Algorithm 933: Reliable calculation of numerical rank, null space bases, pseudoinverse solutions, and basic solutions using suitesparseQR. ACM Trans. Math. Softw. 40, 1, Article 7 (September 2013), 23 pages. https://doi.org/10.1145/2513109.2513116 * for Mongoose: T. A. Davis, William W. Hager, Scott P. Kolodziej, and S. Nuri Yeralan. 2020. Algorithm 1003: Mongoose, a Graph Coarsening and Partitioning Library. ACM Trans. Math. Softw. 46, 1, Article 7 (March 2020), 18 pages. https://doi.org/10.1145/3337792 * for SPEX: Christopher Lourenco, Jinhao Chen, Erick Moreno-Centeno, and T. A. Davis. 2022. Algorithm 1021: SPEX Left LU, Exactly Solving Sparse Linear Systems via a Sparse Left-Looking Integer-Preserving LU Factorization. ACM Trans. Math. Softw. June 2022. https://doi.org/10.1145/3519024 ----------------------------------------------------------------------------- About the BLAS and LAPACK libraries ----------------------------------------------------------------------------- NOTE: if you use OpenBLAS, be sure to use version 0.3.27 or later. To select your BLAS/LAPACK, see the instructions in SuiteSparseBLAS.cmake in `SuiteSparse_config/cmake_modules`. If `SuiteSparse_config` finds a BLAS with 64-bit integers (such as the Intel MKL ilp64 BLAS), it configures `SuiteSparse_config.h` with the `SUITESPARSE_BLAS_INT` defined as `int64_t`. Otherwise, if a 32-bit BLAS is found, this type is defined as `int32_t`. If later on, UMFPACK, CHOLMOD, or SPQR are compiled and linked with a BLAS that has a different integer size, you must override the definition with `-DBLAS64` (to assert the use of 64-bit integers in the BLAS) or `-DBLAS32`, (to assert the use of 32-bit integers in the BLAS). The size of the BLAS integer has nothing to do with `sizeof(void *)`. When distributed in a binary form (such as a Debian, Ubuntu, Spack, or Brew package), SuiteSparse should probably be compiled to expect a 32-bit BLAS, since this is the most common case. The default is to use a 32-bit BLAS, but this can be changed by setting the cmake variable `SUITESPARSE_USE_64BIT_BLAS` to `ON`. By default, SuiteSparse hunts for a suitable BLAS library. To enforce a particular BLAS library use either: CMAKE_OPTIONS="-DBLA_VENDOR=OpenBLAS" make cd Package ; cmake -DBLA_VENDOR=OpenBLAS .. make To use the default (hunt for a BLAS), do not set `BLA_VENDOR`, or set it to `ANY`. In this case, if `SUITESPARSE_USE_64BIT_BLAS` is ON, preference is given to a 64-bit BLAS, but a 32-bit BLAS library will be used if no 64-bit library is found. However, if both `SUITESPARSE_USE_64BIT_BLAS` and `SUITESPARSE_USE_STRICT` are ON, then only a 64-bit BLAS is considered. When selecting a particular BLAS library, the `SUITESPARSE_USE_64BIT_BLAS` setting is strictly followed. If set to true, only a 64-bit BLAS library will be used. If false (the default), only a 32-bit BLAS library will be used. If no such BLAS is found, the build will fail. ----------------------------------------------------------------------------- QUICK START FOR THE C/C++ LIBRARIES: ----------------------------------------------------------------------------- Type the following in this directory (requires system priviledge to do the `sudo make install`): ``` mkdir -p build && cd build cmake .. cmake --build . sudo cmake --install . ``` All libraries will be created and installed into the default system-wide folder (/usr/local/lib on Linux). All include files needed by the applications that use SuiteSparse are installed into /usr/local/include/suitesparse (on Linux). To build only a subset of libraries, set `SUITESPARSE_ENABLE_PROJECTS` when configuring with CMake. E.g., to build and install CHOLMOD and CXSparse (including their dependencies), use the following commands: ``` mkdir -p build && cd build cmake -DSUITESPARSE_ENABLE_PROJECTS="cholmod;cxsparse" .. cmake --build . sudo cmake --install . ``` For Windows (MSVC), import the `CMakeLists.txt` file into MS Visual Studio. Be sure to specify the build type as Release; for example, to build SuiteSparse on Windows in the command window, run: ``` mkdir -p build && cd build cmake .. cmake --build . --config Release cmake --install . ``` Be sure to first install all required libraries: BLAS and LAPACK for UMFPACK, CHOLMOD, and SPQR, and GMP and MPFR for SPEX. Be sure to use the latest libraries; SPEX requires MPFR 4.0.2 and GMP 6.1.2 (these version numbers do NOT correspond to the X.Y.Z suffix of libgmp.so.X.Y.Z and libmpfr.so.X.Y.Z; see the SPEX user guide for details). To compile the libraries and install them only in SuiteSparse/lib (not /usr/local/lib), do this instead in the top-level of SuiteSparse: ``` mkdir -p build && cd build cmake -DCMAKE_INSTALL_PREFIX=.. .. cmake --build . cmake --install . ``` If you add /home/me/SuiteSparse/lib to your library search path (`LD_LIBRARY_PATH` in Linux), you can do the following (for example): ``` S = /home/me/SuiteSparse cc myprogram.c -I$(S)/include/suitesparse -lumfpack -lamd -lcholmod -lsuitesparseconfig -lm ``` To change the C and C++ compilers, and to compile in parallel use: ``` cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER==g++ .. ``` for example, which changes the compiler to gcc and g++. This will work on Linux/Unix and the Mac. It should automatically detect if you have the Intel compilers or not, and whether or not you have CUDA. See `SuiteSparse_config/cmake_modules/SuiteSparsePolicy.cmake` to select your BLAS. You may also need to add SuiteSparse/lib to your path. If your copy of SuiteSparse is in /home/me/SuiteSparse, for example, then add this to your `~/.bashrc` file: ``` LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/me/SuiteSparse/lib export LD_LIBRARY_PATH ``` For the Mac, use this instead: ``` DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/home/me/SuiteSparse/lib export DYLD_LIBRARY_PATH ``` Default install location of files is below, where PACKAGE is one of the packages in SuiteSparse: * `CMAKE_INSTALL_PREFIX/include/suitesparse/`: include files * `CMAKE_INSTALL_PREFIX/lib/`: compiled libraries * `CMAKE_INSTALL_PREFIX/lib/cmake/SuiteSparse/`: `*.cmake` scripts for all of SuiteSparse * `CMAKE_INSTALL_PREFIX/lib/cmake/PACKAGE/`: `*Config.cmake` scripts for a specific package * `CMAKE_INSTALL_PREFIX/lib/pkgconfig/PACKAGE.pc`: `.pc` scripts for a specific package pkgconfig ----------------------------------------------------------------------------- QUICK START FOR MATLAB USERS (Linux or Mac): ----------------------------------------------------------------------------- Suppose you place SuiteSparse in the `/home/me/SuiteSparse` folder. Add the `SuiteSparse/lib` folder to your run-time library path. On Linux, add this to your `~/.bashrc` script, assuming `/home/me/SuiteSparse` is the location of your copy of SuiteSparse: ``` LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/me/SuiteSparse/lib export LD_LIBRARY_PATH ``` For the Mac, use this instead, in your `~/.zshrc` script, assuming you place SuiteSparse in `/Users/me/SuiteSparse`: ``` DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/Users/me/SuiteSparse/lib export DYLD_LIBRARY_PATH ``` Compile all of SuiteSparse with `make local`. Next, compile the GraphBLAS MATLAB library. In the system shell while in the SuiteSparse folder, type `make gbmatlab` if you want to install it system-wide with `make install`, or `make gblocal` if you want to use the library in your own SuiteSparse/lib. Then in the MATLAB Command Window, cd to the SuiteSparse directory and type `SuiteSparse_install`. All packages will be compiled, and several demos will be run. To run a (long!) exhaustive test, do `SuiteSparse_test`. Save your MATLAB path for future sessions with the MATLAB pathtool or savepath commands. If those methods fail because you don't have system-wide permission, add the new paths to your startup.m file, normally in Documents/MATLAB/startup.m. You can also use the `SuiteSparse_paths` m-file to set all your paths at the start of each MATLAB session. ----------------------------------------------------------------------------- Compilation options ----------------------------------------------------------------------------- You can set specific options for CMake with the command (for example): ``` cmake -DCHOLMOD_PARTITION=OFF -DBUILD_STATIC_LIBS=OFF -DCMAKE_BUILD_TYPE=Debug .. ``` That command will compile all of SuiteSparse except for CHOLMOD/Partition Module (because of `-DCHOLMOD_PARTITION=OFF`). Debug mode will be used (the build type). The static libraries will not be built (since `-DBUILD_STATIC_LIBS=OFF` is set). * `SUITESPARSE_ENABLE_PROJECTS`: Semicolon separated list of projects to be built or `all`. Default: `all` in which case the following projects are built: `suitesparse_config;mongoose;amd;btf;camd;ccolamd;colamd;cholmod;cxsparse;ldl;klu;umfpack;paru;rbio;spqr;spex;graphblas;lagraph` Additionally, `csparse` can be included in that list to build CSparse. * `CMAKE_BUILD_TYPE`: Default: `Release`, use `Debug` for debugging. * `SUITESPARSE_USE_STRICT`: SuiteSparse has many user-definable settings of the form `SUITESPARSE_USE_*` or `(package)_USE_*` for some particular package. In general, these settings are not strict. For example, if `SUITESPARSE_USE_OPENMP` is `ON` then OpenMP is preferred, but SuiteSparse can be used without OpenMP so no error is generated if OpenMP is not found. However, if `SUITESPARSE_USE_STRICT` is `ON` then all `*_USE_*` settings are treated strictly and an error occurs if any are set to `ON` but the corresponding package or setting is not available. The `*_USE_SYSTEM_*` settings are always treated as strict. Default: `OFF`. * `SUITESPARSE_USE_CUDA`: If set to `ON`, CUDA is enabled for all of SuiteSparse. Default: `ON`, CUDA on Windows with MSVC appears to be working with this release, but it should be considered as a prototype and may not be fully functional. I have limited resources for testing CUDA on Windows. If you encounter issues, disable CUDA and post this as an issue on GitHub. * `CHOLMOD_USE_CUDA`: Default: `ON`. Both `SUITESPARSE_USE_CUDA` and `CHOLMOD_USE_CUDA` must be enabled to use CUDA in CHOLMOD. * `SPQR_USE_CUDA`: Default: `ON`. Both `SUITESPARSE_USE_CUDA` and `SPQR_USE_CUDA` must be enabled to use CUDA in SPQR. * `CMAKE_INSTALL_PREFIX`: Defines the install location (default on Linux is `/usr/local`). For example, this command while in a folder `build` in the top level SuiteSparse folder will set the install directory to `/stuff`, used by the subsequent `sudo cmake --install .`: ``` cmake -DCMAKE_INSTALL_PREFIX=/stuff .. sudo cmake --install . ``` * `SUITESPARSE_PKGFILEDIR`: Directory where CMake Config and pkg-config files will be installed. By default, CMake Config files will be installed in the subfolder `cmake` of the directory where the (static) libraries will be installed (e.g., `lib`). The `.pc` files for pkg-config will be installed in the subfolder `pkgconfig` of the directory where the (static) libraries will be installed. This option allows to install them at a location different from the (static) libraries. This allows to install multiple configurations of the SuiteSparse libraries at the same time (e.g., by also setting a different `CMAKE_RELEASE_POSTFIX` and `CMAKE_INSTALL_LIBDIR` for each of them). To pick up the respective configuration in downstream projects, set, e.g., `CMAKE_PREFIX_PATH` (for CMake) or `PKG_CONFIG_PATH` (for build systems using pkg-config) to the path containing the respective CMake Config files or pkg-config files. * `SUITESPARSE_INCLUDEDIR_POSTFIX`: Postfix for installation target of header from SuiteSparse. Default: suitesparse, so the default include directory is: `CMAKE_INSTALL_PREFIX/include/suitesparse` * `BUILD_SHARED_LIBS`: If `ON`, shared libraries are built. Default: `ON`. * `BUILD_STATIC_LIBS`: If `ON`, static libraries are built. Default: `ON`, except for GraphBLAS, which takes a long time to compile so the default for GraphBLAS is `OFF` unless `BUILD_SHARED_LIBS` is `OFF`. * `SUITESPARSE_CUDA_ARCHITECTURES`: A string, such as `"all"` or `"35;50;75;80"` that lists the CUDA architectures to use when compiling CUDA kernels with `nvcc`. The `"all"` option requires CMake 3.23 or later. Default: `"52;75;80"`. * `BLA_VENDOR`: A string. Leave unset, or use `"ANY"` to select any BLAS library (the default). Or set to the name of a `BLA_VENDOR` defined by FindBLAS.cmake. See: https://cmake.org/cmake/help/latest/module/FindBLAS.html#blas-lapack-vendors * `SUITESPARSE_USE_64BIT_BLAS`: If `ON`, look for a 64-bit BLAS. If `OFF`: 32-bit only. Default: `OFF`. * `SUITESPARSE_USE_OPENMP`: If `ON`, OpenMP is used by default if it is available. Default: `ON`. GraphBLAS, LAGraph, and ParU will be vastly slower if OpenMP is not used. CHOLMOD will be somewhat slower without OpenMP (as long as it still has a parallel BLAS/LAPACK). Three packages (UMFPACK, CHOLMOD, and SPQR) rely heavily on parallel BLAS/LAPACK libraries and those libraries may use OpenMP internally. If you wish to disable OpenMP in an entire application, select a single-threaded BLAS/LAPACK, or a parallel BLAS/LAPACK that does not use OpenMP (such as the Apple Accelerate Framework). Using a single-threaded BLAS/LAPACK library will cause UMFPACK, CHOLMOD, and SPQR to be vastly slower. WARNING: GraphBLAS may not be thread-safe if built without OpenMP or pthreads (see the GraphBLAS User Guide for details). * `SUITESPARSE_CONFIG_USE_OPENMP`: If `ON`, `SuiteSparse_config` uses OpenMP if it is available. Default: `SUITESPARSE_USE_OPENMP`. It is not essential and only used to let `SuiteSparse_time` call `omp_get_wtime`. * `CHOLMOD_USE_OPENMP`: If `ON`, OpenMP is used in CHOLMOD if it is available. Default: `SUITESPARSE_USE_OPENMP`. * `GRAPHBLAS_USE_OPENMP`: If `ON`, OpenMP is used in GraphBLAS if it is available. Default: `SUITESPARSE_USE_OPENMP`. * `LAGRAPH_USE_OPENMP`: If `ON`, OpenMP is used in LAGraph if it is available. Default: `SUITESPARSE_USE_OPENMP`. * `PARU_USE_OPENMP`: If `ON`, OpenMP is used in ParU if it is available. Default: `SUITESPARSE_USE_OPENMP`. * `SUITESPARSE_DEMOS`: If `ON`, build the demo programs for each package. Default: `OFF`. * `SUITESPARSE_USE_SYSTEM_BTF`: If `ON`, use BTF libraries installed on the build system. If `OFF`, automatically build BTF as dependency if needed. Default: `OFF`. * `SUITESPARSE_USE_SYSTEM_CHOLMOD`: If `ON`, use CHOLMOD libraries installed on the build system. If `OFF`, automatically build CHOLMOD as dependency if needed. Default: `OFF`. * `SUITESPARSE_USE_SYSTEM_AMD`: If `ON`, use AMD libraries installed on the build system. If `OFF`, automatically build AMD as dependency if needed. Default: `OFF`. * `SUITESPARSE_USE_SYSTEM_COLAMD`: If `ON`, use COLAMD libraries installed on the build system. If `OFF`, automatically build COLAMD as dependency if needed. Default: `OFF`. * `SUITESPARSE_USE_SYSTEM_CAMD`: If `ON`, use CAMD libraries installed on the build system. If `OFF`, automatically build CAMD as dependency if needed. Default: `OFF`. * `SUITESPARSE_USE_SYSTEM_CCOLAMD`: If `ON`, use CCOLAMD libraries installed on the build system. If `OFF`, automatically build CCOLAMD as dependency if needed. Default: `OFF`. * `SUITESPARSE_USE_SYSTEM_GRAPHBLAS`: If `ON`, use GraphBLAS libraries installed on the build system. If `OFF`, automatically build GraphBLAS as dependency if needed. Default: `OFF`. * `SUITESPARSE_USE_SYSTEM_SUITESPARSE_CONFIG`: If `ON`, use `SuiteSparse_config` libraries installed on the build system. If `OFF`, automatically build `SuiteSparse_config` as dependency if needed. Default: `OFF`. * `SUITESPARSE_USE_FORTRAN` If `ON`, use the Fortran compiler to determine how C calls Fortan, and to build several optional Fortran routines. If `OFF`, use `SUITESPARSE_C_TO_FORTRAN` to define how C calls Fortran (see `SuiteSparse_config/cmake_modules/SuiteSparsePolicy.cmake` for details). Default: `ON`. Additional options are available for specific packages: * `UMFPACK_USE_CHOLMOD`: If `ON`, UMFPACK uses CHOLMOD for additional (optional) ordering options. Default: `ON`. * `KLU_USE_CHOLMOD`: If `ON`, KLU uses CHOLMOD for additional (optional) ordering options. Default: `ON`. CHOLMOD is composed of a set of Modules that can be independently selected; all options default to `ON`: * `CHOLMOD_GPL` If `OFF`, do not build any GPL-licensed module (MatrixOps, Modify, Supernodal, and GPU modules) * `CHOLMOD_CHECK` If `OFF`, do not build the Check module. * `CHOLMOD_MATRIXOPS` If `OFF`, do not build the MatrixOps module. * `CHOLMOD_CHOLESKY` If `OFF`, do not build the Cholesky module. This also disables the Supernodal and Modify modules. * `CHOLMOD_MODIFY` If `OFF`, do not build the Modify module. * `CHOLMOD_CAMD` If `OFF`, do not link against CAMD and CCOLAMD. This also disables the Partition module. * `CHOLMOD_PARTITION` If `OFF`, do not build the Partition module. * `CHOLMOD_SUPERNODAL` If `OFF`, do not build the Supernodal module. ----------------------------------------------------------------------------- Possible build/install issues ----------------------------------------------------------------------------- One common issue can affect all packages: getting the right #include files that match the current libraries being built. It's possible that your Linux distro has an older copy of SuiteSparse headers in /usr/include or /usr/local/include, or that Homebrew has installed its suite-sparse bundle into /opt/homebrew/include or other places. Old libraries can appear in in /usr/local/lib, /usr/lib, etc. When building a new copy of SuiteSparse, the cmake build system is normally (or always?) able to avoid these, and use the right header for the right version of each library. As an additional guard against this possible error, each time one SuiteSparse package #include's a header from another one, it checks the version number in the header file, and reports an #error to the compiler if a stale version is detected. In addition, the Example package checks both the header version and the library version (by calling a function in each library). If the versions mismatch in any way, the Example package reports an error at run time. For example, CHOLMOD 5.1.0 requires AMD 3.3.0 or later. If it detects an older one in `amd.h`, it will report an `#error`: ``` #include "amd.h" #if ( ... AMD version is stale ... ) #error "CHOLMOD 5.1.0 requires AMD 3.3.0 or later" #endif ``` and the compilation will fail. The Example package makes another check, by calling `amd_version` and comparing it with the versions from the `amd.h` header file. If this error or one like it occurs, check to see if you have an old copy of SuiteSparse, and uninstall it before compiling your new copy of SuiteSparse. There are other many possible build/install issues that are covered by the corresponding user guides for each package, such as finding the right BLAS, OpenMP, and other libraries, and how to compile on the Mac when using GraphBLAS inside MATLAB, and so on. Refer to the User Guides for more details. ----------------------------------------------------------------------------- Interfaces to SuiteSparse ----------------------------------------------------------------------------- MATLAB/Octave/R/Mathematica interfaces: Many built-in methods in MATLAB and Octave rely on SuiteSparse, including `C=A*B` `x=A\b`, `L=chol(A)`, `[L,U,P,Q]=lu(A)`, `R=qr(A)`, `dmperm(A)`, `p=amd(A)`, `p=colamd(A)`, ... See also Mathematica, R, and many many more. The list is too long. Julia interface: https://github.com/JuliaSparse/SparseArrays.jl python interface to GraphBLAS by Anaconda and NVIDIA: https://pypi.org/project/python-graphblas Intel's Go interface to GraphBLAS: https://pkg.go.dev/github.com/intel/forGraphBLASGo See scikit-sparse and scikit-umfpack for the Python interface via SciPy: https://github.com/scikit-sparse/scikit-sparse https://github.com/scikit-umfpack/scikit-umfpack See russell for a Rust interface: https://github.com/cpmech/russell ----------------------------------------------------------------------------- Acknowledgements ----------------------------------------------------------------------------- Markus Mützel contributed the most recent update of the SuiteSparse build system for all SuiteSparse packages, extensively porting it and modernizing it. I would also like to thank François Bissey, Sebastien Villemot, Erik Welch, Jim Kitchen, and Fabian Wein for their valuable feedback on the SuiteSparse build system and how it works with various Linux / Python distros and other package managers. If you are a maintainer of a SuiteSparse packaging for a Linux distro, conda-forge, R, spack, brew, vcpkg, etc, please feel free to contact me if there's anything I can do to make your life easier. I would also like to thank Raye Kimmerer for adding support for 32-bit row/column indices in SPQR v4.2.0. See also the various Acknowledgements within each package. Matrix/inst/doc/SuiteSparse/CCOLAMD/0000755000175100001440000000000014576343415016603 5ustar hornikusersMatrix/inst/doc/SuiteSparse/CCOLAMD/README.txt0000644000175100001440000001267214552026002020271 0ustar hornikusersCCOLAMD: constrained column approximate minimum degree ordering Copyright (C) 2005-2016. Authors: Timothy A. Davis, Sivasankaran Rajamanickam, and Stefan Larimore. Closely based on COLAMD by Davis, Stefan Larimore, in collaboration with Esmond Ng, and John Gilbert. http://www.suitesparse.com ------------------------------------------------------------------------------- SPDX-License-Identifier: BSD-3-clause The CCOLAMD 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. CSYMAMD is a symmetric minimum degree ordering method based on CCOLAMD, also available as a MATLAB-callable function. It constructs a matrix M such that M'*M has the same pattern as A, and then uses CCOLAMD to compute a column ordering of M. Requires SuiteSparse_config, in the ../SuiteSparse_config directory relative to this directory. To compile and install the ccolamd m-files and mexFunctions, just cd to CCOLAMD/MATLAB and type ccolamd_install in the MATLAB command window. A short demo will run. Optionally, type ccolamd_test to run an extensive tests. Type "make" in Unix in the CCOLAMD directory to compile the C-callable library and to run a short demo. CCOLAMD includes a simple top-level Makefile, which is optional. All the work is done via cmake. Windows users can simply import the CMakeLists.txt into MS Visual Studio. "make" targets: make compiles the CCOLAMD library; "make install" will install in /usr/local/lib, /usr/local/include, SuiteSparse/lib, and SuiteSparse/include make demos compiles and runs a few demos make library compiles a C-callable library containing colamd make clean removes all files not in the distribution, but keeps the compiled libraries. make distclean removes all files not in the distribution make local compiles the CCOLAMD library; "make install" will install only in SuiteSparse/lib and SuiteSparse/include make install installs the library make uninstall uninstalls the library See CCOLAMD/Doc/License.txt for the license. ------------------------------------------------------------------------------- Related papers: T. A. Davis and W. W. Hager, Rajamanickam, Multiple-rank updates to a supernodal sparse Cholesky factorization, submitted. T. A. Davis, W. W. Hager, S. Rajamanickam, and Y. Chen, CHOLMOD: a sparse Cholesky update/downdate package, submitted. CHOLMOD's nested dissection ordering relies on CCOLAMD and CSYMAMD to order the matrix after graph partitioning is used to find the ordering constraints. T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, An approximate column minimum degree ordering algorithm, ACM Transactions on Mathematical Software, vol. 30, no. 3., pp. 353-376, 2004. T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, Algorithm 836: COLAMD, an approximate column minimum degree ordering algorithm, ACM Transactions on Mathematical Software, vol. 30, no. 3., pp. 377-380, 2004. "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. 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. Authors: Timothy A. Davis, Sivasankaran Rajamanickam, and Stefan Larimore. Closely based on COLAMD by Stefan I. Larimore and Timothy A. Davis, 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). CCOLAMD files: Demo simple demo Doc additional documentation (see ccolamd.c for more) Include include file Config source for ccolamd.h Makefile optional Makefile CMakeLists.txt for using cmake to build CCOLAMD MATLAB MATLAB functions README.txt this file Source C source code ./Demo: ccolamd_example.c simple example ccolamd_example.out output of colamd_example.c ccolamd_l_example.c simple example, long integers ccolamd_l_example.out output of colamd_l_example.c ./Doc: ChangeLog change log License.txt license ./Include: ccolamd.h include file ./MATLAB: ccolamd.m MATLAB interface for ccolamd ccolamd_demo.m simple demo ccolamd_install.m compile and install ccolamd and csymamd ccolamd_make.m compile colamd2 and symamd2 ccolamdmex.c MATLAB mexFunction for ccolamd ccolamd_test.m extensive test ccolamdtestmex.c test function for ccolamd Contents.m contents of the MATLAB directory luflops.m test code Makefile Makefile for MATLAB functions csymamd.m MATLAB interface for csymamd csymamdmex.c MATLAB mexFunction for csymamd symamdtestmex.c test function for csymamd ./Source: ccolamd.c primary source code ccolamd_l.c primary source code for int64_t version ./build: where CCOLAMD is built .gitignore Matrix/inst/doc/SuiteSparse/CCOLAMD/Doc/0000755000175100001440000000000014576343415017310 5ustar hornikusersMatrix/inst/doc/SuiteSparse/CCOLAMD/Doc/ChangeLog0000644000175100001440000000532314561103552021053 0ustar hornikusersJan 20, 2024: version 3.3.2 * minor updates to build system Jan 10, 2024: version 3.3.1 * minor updates to build system Dec 30, 2023: version 3.3.0 * major change to build system: by Markus Mützel * ccolamd_version: added to return version of CCOLAMD Sept 18, 2023: version 3.2.1 * cmake update: add "None" build type, from Antonio Rojas, for Arch Linux Sept 8, 2023: version 3.2.0 * cmake updates: SuiteSparse:: namespace by Markus Muetzel June 16, 2023: version 3.0.4 * cmake build system updates: update by Markus Muetzel Jan 17, 2023: version 3.0.3 * SuiteSparse_config: now v7.0.0 Dec 9, 2022: version 3.0.2 * minor change to build system Nov 12, 2022: version 3.0.0 * using CMake build system * integers: int (32-bit) and SuiteSparse_long (nominally 64-bit) replaced with int32_t and int64_t. May 4, 2016: version 2.9.6 * minor changes to Makefile Apr 1, 2016: version 2.9.5 * licensing simplified (no other change); refer to CCOLAMD/Doc/License.txt Feb 1, 2016: version 2.9.4 * update to Makefiles Jan 30, 2016: version 2.9.3 * modifications to Makefiles Jan 1, 2016: version 2.9.2 * modified Makefile to create shared libraries No change to C code except version number. The empty file ccolamd_global.c removed. Oct 10, 2014: version 2.9.1 modified MATLAB/ccolamd_make.m. No change to C code except version number. July 31, 2013: version 2.9.0 * changed malloc and printf pointers to use SuiteSparse_config Jun 1, 2012: version 2.8.0 * changed from UFconfig to SuiteSparse_config Dec 7, 2011: version 2.7.4 * fixed the Makefile to better align with CFLAGS and other standards Jan 25, 2011: version 2.7.3 * minor fix to "make install" * fixed stats [CCOLAMD_EMPTY_ROW] output Nov 30, 2009: version 2.7.2 * added "make install" and "make uninstall" Nov 1, 2007: version 2.7.1 * minor changes to MATLAB test code May 31, 2007: version 2.7.0 * ported to 64-bit MATLAB * subdirectories added (Source/, Include/, Lib/, Doc/, MATLAB/, Demo/) Dec 12, 2006, version 2.5.2 * minor MATLAB clean up Apr 30, 2006: version 2.5 * ccolamd_recommended modified. Now returns size_t; 0 on error, > 0 if successful. Version number updated to synchronize with COLAMD. * long replaced with UF_long integer, which is long except on WIN64 Nov 15, 2005 * ccolamd_global.c added to ccolamd_make.m (version is still 1.0). Oct 10, 2005 * changed definition of ccolamd_printf to "extern" Version 1.0, released (Aug. 30, 2005) * CCOLAMD version 1.0 is derived from COLAMD version 2.4. Refer to the COLAMD ChangeLog file for the changes made to COLAMD since COLAMD Version 1.0. Matrix/inst/doc/SuiteSparse/CCOLAMD/Doc/License.txt0000644000175100001440000000372514552026002021422 0ustar hornikusersCCOLAMD: constrained column approximate minimum degree ordering Copyright (C) 2005-2016, Univ. of Florida. Authors: Timothy A. Davis, Sivasankaran Rajamanickam, and Stefan Larimore. Closely based on COLAMD by Davis, Stefan Larimore, in collaboration with Esmond Ng, and John Gilbert. http://www.suitesparse.com -------------------------------------------------------------------------------- CCOLAMD license: BSD 3-clause: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the organizations to which the authors are affiliated, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Matrix/inst/doc/SuiteSparse/AMD/0000755000175100001440000000000014576343415016142 5ustar hornikusersMatrix/inst/doc/SuiteSparse/AMD/README.txt0000644000175100001440000001563514552026002017632 0ustar hornikusersAMD, Copyright (c) 1996-2022 by Timothy A. Davis (http://www.suitesparse.com), Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. AMD is available under alternate licences; contact T. Davis for details. AMD: a set of routines for permuting sparse matrices prior to factorization. Includes a version in C, a version in Fortran, and a MATLAB mexFunction. Requires SuiteSparse_config, in the ../SuiteSparse_config directory relative to this directory. Quick start (Linux or MacOSX): To compile and install the library for system-wide usage: make sudo make install To compile/install for local usage (SuiteSparse/lib and SuiteSparse/include) make local make install To run the demos make demos Quick start (for MATLAB users); To compile, test, and install the AMD mexFunction, cd to the AMD/MATLAB directory and type amd_make at the MATLAB prompt. ------------------------------------------------------------------------------- AMD License: refer to the AMD/Doc/License.txt file for the license. Availability: http://www.suitesparse.com ------------------------------------------------------------------------------- This is the AMD README file. It is a terse overview of AMD. Refer to the User Guide (Doc/AMD_UserGuide.pdf) for how to install and use AMD. Description: AMD is a set of routines for pre-ordering sparse matrices prior to Cholesky or LU factorization, using the approximate minimum degree ordering algorithm. Written in ANSI/ISO C with a MATLAB interface, and in Fortran 77. Authors: Timothy A. Davis (DrTimothyAldenDavis@gmail.com) Patrick R. Amestory, ENSEEIHT, Toulouse, France. Iain S. Duff, Rutherford Appleton Laboratory, UK. Acknowledgements: This work was supported by the National Science Foundation, under grants DMS-9504974, DMS-9803599, and CCR-0203270. Portions of this work were done while on sabbatical at Stanford University and Lawrence Berkeley National Laboratory (with funding from the SciDAC program). I would like to thank Gene Golub, Esmond Ng, and Horst Simon for making this sabbatical possible. ------------------------------------------------------------------------------- Files and directories in the AMD distribution: ------------------------------------------------------------------------------- --------------------------------------------------------------------------- Subdirectories of the AMD directory: --------------------------------------------------------------------------- Doc documentation Source primary source code Include include file for use in your code that calls AMD Demo demo programs. also serves as test of the AMD installation. MATLAB AMD mexFunction for MATLAB, and supporting m-files build where the compiled libraries and demos are placed Config source file to construct amd.h --------------------------------------------------------------------------- Files in the AMD directory: --------------------------------------------------------------------------- Makefile a very simple Makefile (optional); just for simplifying cmake CMakeLists.txt cmake script for building AMD README.txt this file --------------------------------------------------------------------------- Doc directory: documentation --------------------------------------------------------------------------- ChangeLog change log License.txt the AMD License Makefile for creating the documentation AMD_UserGuide.bib AMD User Guide (references) AMD_UserGuide.tex AMD User Guide (LaTeX) AMD_UserGuide.pdf AMD User Guide (PDF) --------------------------------------------------------------------------- Source directory: --------------------------------------------------------------------------- amd_order.c user-callable, primary AMD ordering routine amd_control.c user-callable, prints the control parameters amd_defaults.c user-callable, sets default control parameters amd_info.c user-callable, prints the statistics from AMD amd_1.c non-user-callable, construct A+A' amd_2.c user-callable, primary ordering kernel (a C version of amd.f and amdbar.f, with post-ordering added) amd_aat.c non-user-callable, computes nnz (A+A') amd_dump.c non-user-callable, debugging routines amd_postorder.c non-user-callable, postorder amd_post_tree.c non-user-callable, postorder just one tree amd_valid.c non-user-callable, verifies a matrix amd_preprocess.c non-user-callable, computes A', removes duplic amd_l* same as above, but with int64_t integers amd.f user-callable Fortran 77 version amdbar.f user-callable Fortran 77 version --------------------------------------------------------------------------- Include directory: --------------------------------------------------------------------------- amd.h include file for C programs that use AMD constructed by cmake from Config/amd.h.in amd_internal.h non-user-callable, include file for AMD --------------------------------------------------------------------------- Demo directory: --------------------------------------------------------------------------- amd_demo.c C demo program for AMD amd_demo.out output of amd_demo.c amd_demo2.c C demo program for AMD, jumbled matrix amd_demo2.out output of amd_demo2.c amd_l_demo.c C demo program for AMD (int64_t version) amd_l_demo.out output of amd_l_demo.c amd_simple.c simple C demo program for AMD amd_simple.out output of amd_simple.c amd_f77demo.f Fortran 77 demo program for AMD amd_f77demo.out output of amd_f77demo.f amd_f77simple.c simple Fortran 77 demo program for AMD amd_f77simple.out output of amd_f77simple.f amd_f77cross.f Fortran 77 demo, calls the C version of AMD amd_f77cross.out output of amd_f77cross.f amd_f77wrapper.c Fortran-callable wrapper for C version of AMD --------------------------------------------------------------------------- MATLAB directory: --------------------------------------------------------------------------- Contents.m for "help amd2" listing of toolbox contents amd2.m MATLAB help file for AMD amd_make.m MATLAB m-file for compiling AMD mexFunction amd_install.m compile and install the AMD mexFunction amd_mex.c AMD mexFunction for MATLAB amd_demo.m MATLAB demo for AMD amd_demo.m.out diary output of amd_demo.m can_24.mat input file for AMD demo --------------------------------------------------------------------------- build directory: libamd.a and libamd.so library placed here --------------------------------------------------------------------------- .gitignore only file in the original distribution Matrix/inst/doc/SuiteSparse/AMD/Doc/0000755000175100001440000000000014576343415016647 5ustar hornikusersMatrix/inst/doc/SuiteSparse/AMD/Doc/ChangeLog0000644000175100001440000001542314552026002020406 0ustar hornikusersJan 10, 2024: version 3.3.1 * minor updates to build system Dec 30, 2023: version 3.3.0 * major change to build system: by Markus Mützel * revised test for integer overflow: for CHOLMOD 5.1.0 tests * amd_version: added to return version of AMD Sept 18, 2023: version 3.2.1 * cmake update: add "None" build type, from Antonio Rojas, for Arch Linux Sept 8, 2023: version 3.2.0 * cmake updates: SuiteSparse:: namespace by Markus Muetzel June 16, 2023: version 3.0.4 * cmake build system updates: update by Markus Muetzel Jan 17, 2023: version 3.0.3 * NFORTRAN: option added to disable Fortran entirely * SuiteSparse_config: now v7.0.0 Dec 9, 2022: version 3.0.2 * minor changes to build system * Fortran: allow AMD to be compiled if no Fortran compiler is available. The Fortran source codes (Source/amd.f, Source/amdbar.f) and Demo/*.f are skipped. Nov 12, 2022: version 3.0.0 * using CMake build system * integers: int (32-bit) and SuiteSparse_long (nominally 64-bit) replaced with int32_t and int64_t. May 4, 2016: version 2.4.6 * minor changes to Makefile Apr 1, 2016: version 2.4.5 * licensing simplified (no other change); refer to AMD/Doc/License.txt Feb 1, 2016: version 2.4.4 * update to Makefiles Jan 30, 2016: version 2.4.3 * modifications to Makefiles Jan 1, 2016: version 2.4.2 * modified Makefile to create shared libraries No change to C code except version number Oct 10, 2014: version 2.4.1 modified MATLAB/amd_make.m. No change to C code except version number. July 31, 2013: version 2.4.0 * changed malloc and printf pointers to use SuiteSparse_config Jun 20, 2012: verison 2.3.1 * minor update for Windows (removed filesep) Jun 1, 2012: version 2.3.0 * changed from UFconfig to SuiteSparse_config May 15, 2012: version 2.2.4 * minor fix to SIZE_T_MAX definition (finicky compiler workaround) Dec 7, 2011: version 2.2.3 * fixed the Makefile to better align with CFLAGS and other standards Jan 25, 2011: version 2.2.2 * minor fix to "make install" Nov 30, 2009: version 2.2.1 * added "make install" and "make uninstall" May 31, 2007: version 2.2.0 * port to 64-bit MATLAB * Makefile moved from Source/ to Lib/ * minor changes to printing routines (amd_control.c, amd_info.c) Dec 12, 2006, version 2.0.4 * minor MATLAB code cleanup Nov 29, 2006, version 2.0.3 * changed MATLAB function name to amd2, so as not to conflict with the now built-in version of AMD in MATLAB (which is the same thing as the AMD here...). Sept 28, 2006, version 2.0.2 * #define SIZE_T_MAX not done if already defined (Mac OSX). Aug 31, 2006: * trivial change to comments in amd.m Apr 30, 2006: AMD Version 2.0: * long integer redefined as UF_long, controlled by UFconfig.h. * amd_order no longer requires its input to have sorted columns. It can also tolerate duplicate entries in each column. If these conditions hold, but the matrix is otherwise valid, amd_order returns AMD_OK_BUT_JUMBLED (a warning, not an error). * amd_preprocess no longer deemed user-callable, since it is no longer needed (it was used to ensure the input matrix had sorted columns with no duplicate entries). It still exists, with additional parameters, and is called by amd_order if necessary. amd_wpreprocess and amd_preprocess_valid removed. Fortran interface routine amdpreproc removed. * Integer overflow computations modified, to extend the size of problem that the "int" version can solve when used in an LP64 compilation. * amd_demo2.c simplified (it tests AMD with a jumbled matrix). * amd_valid returned TRUE/FALSE in v1.2. It now returns AMD_OK, AMD_OK_BUT_JUMBLED, or AMD_INVALID. Only in the latter case is the matrix unsuitable as input to amd_order. * amd_internal.h include file moved from AMD/Source to AMD/Include. Nov 15, 2005: * minor editting of comments; version number (1.2) unchanged. Aug. 30, 2005: AMD Version 1.2 * AMD v1.2 is upward compatible with v1.1 and v1.0, except that v1.2 no longer includes the compile-time redefinition of malloc and free. * Makefile modified to use UFconfig.mk. "Make" directory removed. * Easier inclusion in C++ programs. * option to allow compile-time redefinition of malloc and free (added to v1.1) removed for v1.2. Replaced with a run-time redefinition. AMD includes function pointers for malloc, free, calloc, realloc, and printf, so that all those routines can be redefined at compile time. These function pointers are global variables, and so are not technically thread-safe, unless you use defaults and don't need to change them (the common case) or if you change them in one thread before using them in other threads. * added #define'd version number * minor modification to AMD_2 to ensure all lines can be tested, without conditional compilation. * moved the prototype for AMD_2 from amd_internal.h to amd.h * moved the prototype for AMD_valid from amd_internal.h to amd.h * MATLAB mexFunction uses libamd.a (compiled with cc) instead of compiling each AMD source file with the mex command * long demo (amd_l_demo.c) added. 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) Matrix/inst/doc/SuiteSparse/AMD/Doc/License.txt0000644000175100001440000000360314552026002020754 0ustar hornikusersAMD, Copyright (c), 1996-2022, Timothy A. Davis, Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. Availability: http://www.suitesparse.com ------------------------------------------------------------------------------- AMD License: BSD 3-clause: ------------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the organizations to which the authors are affiliated, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Matrix/inst/doc/SuiteSparse/COLAMD/0000755000175100001440000000000014576343415016500 5ustar hornikusersMatrix/inst/doc/SuiteSparse/COLAMD/README.txt0000644000175100001440000001255314552026002020164 0ustar hornikusersCOLAMD, Copyright 1998-2022, Timothy A. Davis. http://www.suitesparse.com ------------------------------------------------------------------------------- SPDX-License-Identifier: BSD-3-clause 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 install the colamd m-files and mexFunctions, just cd to COLAMD/MATLAB and type colamd_install in the MATLAB command window. A short demo will run. Optionally, type colamd_test to run an extensive tests. Colamd is a built-in routine in MATLAB, available from The Mathworks, Inc. Under most cases, the compiled COLAMD from Versions 2.0 to the current version do not differ. Colamd Versions 2.2 and 2.3 differ only in their mexFunction interaces to MATLAB. v2.4 fixes a bug in the symamd routine in v2.3. The bug (in v2.3 and earlier) has no effect on the MATLAB symamd mexFunction. v2.5 adds additional checks for integer overflow, so that the "int" version can be safely used with 64-bit pointers. Refer to the ChangeLog for more details. COLAMD includes a simple top-level Makefile, which is optional. All the work is done via cmake. Windows users can simply import the CMakeLists.txt into MS Visual Studio. "make" targets: make compiles the COLAMD library; "make install" will install in /usr/local/lib, /usr/local/include, SuiteSparse/lib, and SuiteSparse/include make demos compiles and runs a few demos make library compiles a C-callable library containing colamd make clean removes all files not in the distribution, but keeps the compiled libraries. make distclean removes all files not in the distribution make local compiles the COLAMD library; "make install" will install only in SuiteSparse/lib and SuiteSparse/include make install installs the library make uninstall uninstalls the library 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. Requires SuiteSparse_config, in the ../SuiteSparse_config directory relative to this directory. See COLAMD/Doc/License.txt for the License. Related papers: T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, An approximate column minimum degree ordering algorithm, ACM Transactions on Mathematical Software, vol. 30, no. 3., pp. 353-376, 2004. T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, Algorithm 836: COLAMD, an approximate column minimum degree ordering algorithm, ACM Transactions on Mathematical Software, vol. 30, no. 3., pp. 377-380, 2004. "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. 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. Authors: Stefan I. Larimore and Timothy A. Davis, 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: Demo simple demo Doc additional documentation (see colamd.c for more) Include include file Config source for colamd.h Makefile optional Makefile CMakeLists.txt for using cmake to build COLAMD MATLAB MATLAB functions README.txt this file Source C source code ./Demo: colamd_example.c simple example colamd_example.out output of colamd_example.c colamd_l_example.c simple example, long integers colamd_l_example.out output of colamd_l_example.c ./Doc: ChangeLog change log License.txt license ./Include: colamd.h include file ./MATLAB: colamd2.m MATLAB interface for colamd2 colamd_demo.m simple demo colamd_install.m compile and install colamd2 and symamd2 colamd_make.m compile colamd2 and symamd2 colamdmex.ca MATLAB mexFunction for colamd2 colamd_test.m extensive test colamdtestmex.c test function for colamd Contents.m contents of the MATLAB directory luflops.m test code Makefile Makefile for MATLAB functions symamd2.m MATLAB interface for symamd2 symamdmex.c MATLAB mexFunction for symamd2 symamdtestmex.c test function for symamd ./Source: colamd.c primary source code colamd_l.c primary source code for int64_t version ./build: where COLAMD is built .gitignore Matrix/inst/doc/SuiteSparse/COLAMD/Doc/0000755000175100001440000000000014576343415017205 5ustar hornikusersMatrix/inst/doc/SuiteSparse/COLAMD/Doc/ChangeLog0000644000175100001440000001445614561103552020757 0ustar hornikusersJan 20, 2024: version 3.3.2 * minor updates to build system Jan 10, 2024: version 3.3.1 * minor updates to build system Dec 30, 2023: version 3.3.0 * major change to build system: by Markus Mützel * colamd_version: added to return version of COLAMD Sept 18, 2023: version 3.2.1 * cmake update: add "None" build type, from Antonio Rojas, for Arch Linux Sept 8, 2023: version 3.2.0 * cmake updates: SuiteSparse:: namespace by Markus Muetzel June 16, 2023: version 3.0.4 * cmake build system updates: update by Markus Muetzel Jan 17, 2023: version 3.0.3 * SuiteSparse_config: now v7.0.0 Dec 9, 2022: version 3.0.2 * minor change to build system Nov 12, 2022: version 3.0.0 * using CMake build system * integers: int (32-bit) and SuiteSparse_long (nominally 64-bit) replaced with int32_t and int64_t. May 4, 2016: version 2.9.6 * minor changes to Makefile Apr 1, 2016: version 2.9.5 * licensing simplified (no other change); refer to COLAMD/Doc/License.txt Feb 1, 2016: version 2.9.4 * update to Makefiles Jan 30, 2016: version 2.9.3 * modifications to Makefiles Jan 1, 2016: version 2.9.2 * modified Makefile to create shared libraries No change to C code except version number. The empty file colamd_global.c removed. Oct 10, 2014: version 2.9.1 modified MATLAB/colamd_make.m. No change to C code except version number. July 31, 2013: version 2.9.0 * changed malloc and printf pointers to use SuiteSparse_config Jun 1, 2012: version 2.8.0 * UFconfig replaced with SuiteSparse_config Dec 7, 2011: version 2.7.4 * fixed the Makefile to better align with CFLAGS and other standards Jan 25, 2011: version 2.7.3 * minor fix to "make install" Nov 30, 2009: version 2.7.2 * added "make install" and "make uninstall" May 31, 2007: version 2.7.0 * ported to 64-bit MATLAB * subdirectories added (Source/, Include/, Lib/, Doc/, MATLAB/, Demo/) Dec 12, 2006, version 2.5.2 * minor MATLAB cleanup. MATLAB functions renamed colamd2 and symamd2, so that they do not conflict with the built-in versions. Note that the MATLAB built-in functions colamd and symamd are identical to the colamd and symamd functions here. Aug 31, 2006: Version 2.5.1 * minor change to colamd.m and symamd.m, to use etree instead of sparsfun. Apr. 30, 2006: Version 2.5 * colamd_recommended modified, to do more careful integer overflow checking. It now returns size_t, not int. colamd_l_recommended also returns size_t. A zero is returned if an error occurs. A postive return value denotes success. In v2.4 and earlier, -1 was returned on error (an int or long). * long replaced with UF_long integer, which is long except on WIN64. Nov 15, 2005: * minor editting of comments; version number (2.4) unchanged. Changes from Version 2.3 to 2.4 (Aug 30, 2005) * Makefile now relies on ../UFconfig/UFconfig.mk * changed the dense row/col detection. The meaning of the knobs has thus changed. * added an option to turn off aggressive absorption. It was always on in versions 2.3 and earlier. * added a #define'd version number * added a function pointer (colamd_printf) for COLAMD's printing. * added a -DNPRINT option, to turn off printing at compile-time. * added a check for integer overflow in colamd_recommended * minor changes to allow for more simpler 100% test coverage * bug fix. If symamd v2.3 fails to allocate its copy of the input matrix, then it erroneously frees a calloc'd workspace twice. This bug has no effect on the MATLAB symamd mexFunction, since mxCalloc terminates the mexFunction if it fails to allocate memory. Similarly, UMFPACK is not affected because it does not use symamd. The bug has no effect on the colamd ordering routine in v2.3. 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. Matrix/inst/doc/SuiteSparse/COLAMD/Doc/License.txt0000644000175100001440000000340014552026002021305 0ustar hornikusersCOLAMD, Copyright 1998-2022, Timothy A. Davis. http://www.suitesparse.com http://www.suitesparse.com -------------------------------------------------------------------------------- COLAMD License: BSD 3-clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the organizations to which the authors are affiliated, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Matrix/inst/doc/SuiteSparse/CHOLMOD/0000755000175100001440000000000014576343415016626 5ustar hornikusersMatrix/inst/doc/SuiteSparse/CHOLMOD/README.txt0000644000175100001440000000460114552026002020305 0ustar hornikusersCHOLMOD: a sparse CHOLesky MODification package, Copyright (c) 2005-2023. http://www.suitesparse.com ----------------------------------------------- CHOLMOD is a set of routines for factorizing sparse symmetric positive definite matrices of the form A or AA', updating/downdating a sparse Cholesky factorization, solving linear systems, updating/downdating the solution to the triangular system Lx=b, and many other sparse matrix functions for both symmetric and unsymmetric matrices. Its supernodal Cholesky factorization relies on LAPACK and the Level-3 BLAS, and obtains a substantial fraction of the peak performance of the BLAS. Both real and complex matrices are supported. CHOLMOD is written in ANSI/ISO C, with both C and MATLAB interfaces. This code works on Microsoft Windows and many versions of Unix and Linux. CHOLMOD supports single precision sparse matrices (both real and complex), with the introduction of the new CHOLMOD:Utility Module. One CHOLMOD Module is copyrighted by the University of Florida (the Partition Module). The rest are copyrighted by the authors: Timothy A. Davis (all of them), and William W. Hager (the Modify Module). CHOLMOD relies on several other packages: AMD, CAMD, COLAMD, CCOLAMD, SuiteSparse_config, METIS, the BLAS, and LAPACK. All but the BLAS and LAPACK are part of SuiteSparse. AMD is authored by T. Davis, Iain Duff, and Patrick Amestoy. COLAMD is authored by T. Davis and Stefan Larimore, with algorithmic design in collaboration with John Gilbert and Esmond Ng. CCOLAMD is authored by T. Davis and Siva Rajamanickam. CAMD is authored by T. Davis and Y. Chen. LAPACK and the BLAS are authored by Jack Dongarra and many others. LAPACK is available at http://www.netlib.org/lapack METIS 5.1.0 is authored by George Karypis, Univ. of Minnesota. Its use in CHOLMOD is optional. A copy is in SuiteSparse/SuiteSparse_metis, and it is slightly modified from the original METIS 5.1.0 to incorporate it into SuiteSparse. For use in MATLAB (on any system, including Windows): start MATLAB, cd to the CHOLMOD/MATLAB directory, and type cholmod_make in the MATLAB Command Window. Acknowledgements: this work was supported in part by the National Science Foundation (NFS CCR-0203270 and DMS-9803599), and a grant from Sandia National Laboratories (Dept. of Energy) which supported the development of CHOLMOD's Partition Module. Matrix/inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/0000755000175100001440000000000014576343415022276 5ustar hornikusersMatrix/inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/LICENSE.txt0000644000175100001440000000120114552026002024073 0ustar hornikusers Copyright & License Notice --------------------------- Copyright 1995-2013, Regents of the University of Minnesota Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Matrix/inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt0000644000175100001440000000420014552026002023750 0ustar hornikusersMETIS 5.1.0, with minor modifications by Tim Davis to incorporate it into SuiteSparse. This copy of METIS is slightly changed from the original METIS v5.1.0 distribution. The use of METIS in SuiteSparse is optional, but if used, this revised version is required. Do not attempt to use this copy of METIS to build a stand-alone METIS library. (1) In metis-5.1.0/include/metis.h, the default integer size has been changed from 32 bits to 64 (IDXTYPEWIDTH). METIS 5.1.0 gives this flexility to the user, asking the user to modify this file. That has been done here, and as a result, this file is renamed to SuiteSparse_metis.h. Getting the unmodified libmetis.so in a Linux distro (likely with 32-bit integers) combined with a modified metis.h (with 64-bit integers) breaks things badly. So the safest thing is to compile the METIS functions as built into CHOLMOD, rather than creating a new and different libmetis.so. (3) The files metis-5.1.0/GKlib/GKLib.h and metis-5.1.0/GKlib/memory.c have been modified to disable the signal-handling in METIS, which is used when METIS runs out of memory. (4) The abs and iabs functions in the original metis-5.1.0 give compiler warnings when IDXTYPEWIDTH is 64, so they have been replaced with a static inline function, SuiteSparse_metis_abs64. (5) Warnings disabled to avoid compiler warnings of misleading indentation (getopt.c, csr.c). (6) The malloc/calloc/realloc/free functions have been replaced with SuiteSparse_config.(malloc/calloc/realloc/free) throughout. The gkmcore feature is disabled since it can conflict with the use of mxMalloc in the MATLAB interface to SuiteSparse. See GKlib/memory.c. (7) All original files from metis-5.1.0 that have been modified here have been placed in ./include/original, ./libmetis/original, or ./GKlib/original Tim Davis, Jan 19, 2023, Texas A&M University. Any changes made by Tim Davis are released to the original copyright holder, under the original Apache-2.0 license of METIS. METIS, Copyright 1995-2013, Regents of the University of Minnesota. Author: George Karypis SPDX-License-identifier: Apache-2.0 Matrix/inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/Changelog0000644000175100001440000002662714552026002024105 0ustar hornikusers metis-5.1.0 ------------------------------------------------------------------------ r13937 | karypis | 2013-03-29 23:08:21 -0500 (Fri, 29 Mar 2013) - Further extended the 2-hop coarsening scheme introduced in 5.0.2 for for graphs with highly variable degree distribution (e.g., power-law). This coarsening scheme is automatically used when the standard 1-hop-based scheme leaves a large fraction of the vertices of the graph unmatched. It leads to better quality partitionings, lower memory utilization, and faster execution time. In principle, this scheme will never be triggered for graphs/matrices appearing in scientific computations derived from FE meshes. However, if you notice that the quality of the solutions is significantly worse, this 2-hop matching can be turned off by using the '-no2hop' command line option and the associated options[] parameter (as described in the manual). - Fixed 0/1 numbering issue with mesh partitioning routines (flyspray issue #109) metis-5.0.3 ------------------------------------------------------------------------ r13822 | karypis | 2013-03-11 14:40:11 -0500 (Mon, 11 Mar 2013) - Fixed the bug that was introduced in 5.x for creating nodal graphs from meshes (flyspray issue #107). - Changed the license to Apache Version 2. metis-5.0.2 ------------------------------------------------------------------------ r10974 | karypis | 2011-10-29 18:24:32 -0500 (Sat, 29 Oct 2011) - Fixed issue with high-degree vertices and mask-based compression. - Fixed issue with wrong COARSENING_FRACTION. - Modified coarsening schemes to better support non FE graphs. metis-5.0.1 ------------------------------------------------------------------------ r10709 | karypis | 2011-08-31 16:07:57 -0500 (Wed, 31 Aug 2011) - Fixed critical bug in the mesh partitioning routines. metis-5.0 ------------------------------------------------------------------------ r10667 | karypis | 2011-08-04 00:35:30 -0500 (Thu, 04 Aug 2011) - Updated/corrected error messages. - Addressed some build issues. metis-5.0rc3 ------------------------------------------------------------------------ r10560 | karypis | 2011-07-13 08:19:10 -0500 (Wed, 13 Jul 2011) - Fixed various bugs that were identified by testers. - Some minor performance and quality improvements. - Addressed some build issues. metis-5.0rc2 ------------------------------------------------------------------------ r10496 | karypis | 2011-07-06 11:04:45 -0500 (Wed, 06 Jul 2011) - Various run-time and quality optimizations. - Option error-checking. - Signal-based heap cleanup on error. Metis API routines will not return nicely and cleanup all memory that may have allocated. - Reduced memory requirements. - Fixed various bugs identified in rc1. - Added back Fortran support in the form of alternate API names (see libmetis/frename.h). - Minor code changes to accommodate ParMetis 4.0. metis-5.0rc1 ------------------------------------------------------------------------ r10227 | karypis | 2011-06-13 23:35:05 -0500 (Mon, 13 Jun 2011) - A nearly complete re-write of Metis' code-based that changed expanded the functionality of the command-line programs and API routines. - Multi-constraint partitioning can be used in conjunction with minimization of the total communication volume. - All graph and mesh partitioning routines take as input the target sizes of the partitions, which among others, allow them to compute partitioning solutions that are well-suited for parallel architectures with heterogeneous computing capabilities. - When multi-constraint partitioning is used, the target sizes of the partitions are specified on a per partition-constraint pair. - The multilevel k-way partitioning algorithms can compute a partitioning solution in which each partition is contiguous. - All partitioning and ordering routines can compute multiple different solutions and select the best as the final solution. - The mesh partitioning and mesh-to-graph conversion routines can operate on mixed element meshes. - The command-line programs provide full access to the entire set of capabilities provided by Metis' API. - Re-written the memory management subsystem to reduce overall memory requirements. metis-5.0pre2 ------------------------------------------------------------------------ r1437 | karypis | 2007-04-07 23:16:16 -0500 (Sat, 07 Apr 2007) - Added installation instructions and change-logs. - Tested 32bit & 64bit on 64bit architectures and passed tests. - Tested 32bit on 32bit architectures and passed tests. - strtoidx() addition for portable input file parsing - Restructured the internal memory allocation schemes for graph and refinement data. This should enhance portability and make the code easier to maintain. - Fixed some bad memory allocation calls (i.e., sizeof(x)/sizeof(idxtype). However, there are tons of those and need to be corrected once and for all by eliminating workspace and the associated mallocs. - Added mprint/mscanf family of functions for portable formated I/O of the idxtype datatype. The specifier for this datatype is %D. All library routines use this function for printing. The implementation of these routines is not very efficient, but that should do for now (in principle these routines should not be used unless debugging). - Incorporated GKlib into METIS, which replaced many of its internal functions. GKlib's malloc interface will enable graceful and clean aborts (i.e., free all internally allocated memory) on fatal errors. This will probably be available in the next pre-release. - Fixed the problems associated with metis.h that were identified by David (flyspray Issue #9). METIS 4.0.2, 3/10/04 ------------------------------------------------------------------------------ - Fixed a problem with weighted graphs and ometis.c METIS 4.0.1, 11/29/98 ------------------------------------------------------------------------------ This is mostly a bug-fix release - Fixed some bugs in the multi-constraint partitioning routines - Fixed some bugs in the volume-minimization routines METIS 4.0.0, 9/20/98 ------------------------------------------------------------------------------ METIS 4.0 contains a number of changes over the previous major release (ver 3.0.x). Most of these changes are concentrated on the graph and mesh partitioning routines and they do not affect the sparse matrix re-ordering routines. Here is a list of the major changes: Multi-Constraint Partitioning ----------------------------- METIS now includes partitioning routines that can be used to a partition a graph in the presence of multiple balancing constraints. Minimizing the Total Communication Volume ----------------------------------------- METIS now includes partitioning routines whose objective is to minimize the total communication volume (as opposed to minimizing the edge-cut). Minimizing the Maximum Connectivity of the Subdomains ----------------------------------------------------- The k-way partitioning routines in METIS can now directly minimize the number of adjacent subdomains. For most graphs corresponding to finite element meshes, METIS is able to significantly reduce the maximum (and total) number of adjacent subdomains. METIS 3.0.6, 1/28/98 ------------------------------------------------------------------------------- - Fixed some problems when too many partitions were asked, and each partition end up having 0 vertices - Fixed some bugs in the I/O routines - Added support for the g77 compiler under Linux METIS 3.0.5, 12/22/97 ------------------------------------------------------------------------------- - Fixed problems on 64-bit architectures (eg., -64 option on SGIs). - Added some options in Makefile.in METIS 3.0.4, 12/1/97 ------------------------------------------------------------------------------- Fixed a memory leak in the ordering code. METIS 3.0.3, 11/5/97 ------------------------------------------------------------------------------- This is mostly a bug-fix release with just a few additions Added functionality - Added support for quadrilateral elements. - Added a routine METIS_EstimateMemory that estimates the amount of memory that will be allocated by METIS. This is useful in determining if a problem can run on your system. - Added hooks to allow PARMETIS to use the orderings produced by METIS. This is hidden from the user but it will be used in the next release of PARMETIS. Bug-fixes - Fixed a bug related to memory allocation. This should somewhat reduce the overall memory used by METIS. - Fixed some bugs in the 'graphchk' program in the case of weighted graphs. - Removed some code corresponding to unused options. - Fixed some minor bugs in the node-refinement code ------------------------------------------------------------------------------- METIS 3.0 contains a number of changes over METIS 2.0. The major changes are the following: General Changes --------------- 1. Added code to directly partition finite element meshes. 2. Added code to convert finite element meshes into graphs so they can be used by METIS. 1. The names, calling sequences, and options of the routines in METISlib have been changed. 2. Better support has been added for Fortran programs. 3. Eliminated the 'metis' program. The only way to tune METIS's behavior is to use METISlib. 4. Improved memory management. METIS should now only abort if truly there is no more memory left in the system. Graph Partitioning ------------------ 1. Added partitioning routines that can be used to compute a partition with prescribed partition weights. For example, they can be used to compute a 3-way partition such that partition 1 has 50% of the weight, partition 2 has 20% of the way, and partition 3 has 30% of the weight. 2. Improved the speed of the k-way partitioning algorithm (kmetis). The new code has better cache locality which dramatically improves the speed for large graphs. A factor of 4 speedup can be obtained for certain graphs. METIS can now partition a 4 million node graph in well under a minute on a MIPS R10000. 3. Eliminated some of the options that were seldom used. Fill-Reducing Orderings ---------------------- 1. Added a node based ordering code `onmetis' that greatly improves ordering quality. 2. Improved the quality of the orderings produced by the original edge-based ordering code (it is now called 'oemetis'). 3. METIS can now analyze the graph and try to compress together nodes with identical sparsity pattern. For some problems, this significantly reduces ordering time 4. METIS can now prune dense columns prior to ordering. This can be helpful for LP matrices. Mesh Partitioning ----------------- 1. METIS can now directly partition the element node array of finite element meshes. It produces two partitioning vectors. One for the elements and one for the nodes. METIS supports the following elements: triangles, tetrahedra, hexahedra Mesh-To-Graph Conversion Routines --------------------------------- 1. METIS now includes a number of mesh conversion functions that can be used to create the dual and nodal graphs directly from the element connectivity arrays. These are highly optimized routines. Matrix/inst/doc/SuiteSparse/CHOLMOD/Doc/0000755000175100001440000000000014576343415017333 5ustar hornikusersMatrix/inst/doc/SuiteSparse/CHOLMOD/Doc/ChangeLog0000644000175100001440000004165714561103552021110 0ustar hornikusersJan 20, 2024: version 5.2.0 * bug fix: CHOLMOD 5.1.0 added a new variable in the CHOLMOD Common struct for development only but this change broke ABI compatibility since the SOVERSION was not bumped at the same time. v5.2.0 reverts this change so the new variable does not appear in production, thus restoring ABI compatibility with v5.0.x. Jan 10, 2024: version 5.1.1 * MATLAB interface: add -DNO_SSIZE_T for Windows * minor updates to build system Dec 30, 2023: version 5.1.0 * major change to build system: by Markus Mützel * support for single precision matrices: for all Modules, except for the GPU kernels (which are only supported for double and complex double matrices). * GPU: various bug fixes Oct 31, 2023, version 5.0.1 * cholmod.h: remove use of "I" which conflicts with #include . Oct 23, 2023, version 5.0.0 * CHOLMOD v5.0.0: introduces the first part of support for single precision sparse matrices, with the introduction of the new CHOLMOD:Utility Module. The CHOLMOD:Utility Module replaces CHOLMOD:Core in prior versions. Single precision is not yet incorporated into the remaining Modules, however. Oct 18, 2023: version 4.2.2 * CHOLMOD 4.2.2: bug fix to CHOLMOD/Supernodal (heuristic to determine # threads to use for last supernode was incorrect) Sept 18, 2023: version 4.2.1 * cmake update: add "None" build type, from Antonio Rojas, for Arch Linux Sept 8, 2023: version 4.2.0 * cmake updates: SuiteSparse:: namespace by Markus Muetzel * bug fix: typecast was broken in cholmod_postorder.c * minor fixes to debug scaffolding and test code: cholmod_internal.h, cholmod_metis_wrapper.c, Tcov/memory.c. * support for SPQR: minor changes to support SPQR v4.2.0 with 32-bit integers; no change to user-visible API. * METIS now using GKRAND: with threadprivate state variables, to avoid global system lock when using CHOLMON on many user threads June 16, 2023: version 4.0.4 * cmake build system updates: update by Markus Muetzel * METIS: fixed non-standard prototypes in gk_proto.h and gk_mkrandom.h Jan 17, 2022: version 4.0.3 * NFORTRAN: option added to disable Fortran entirely * SuiteSparse_config: now v7.0.0 Dec 9, 2022: version 4.0.2 * minor change to build system * Fortran: no longer required to build CHOLMOD * NPARTITION: if CHOLMOD is compiled with -DNPARTITION, then METIS is not compiled. However, the CHOLMOD interface to METIS is still present; they simply return CHOLMOD_NOT_INSTALLED. This allows methods that depend on CHOLMOD's METIS interface to use a run-time test, instead of requiring them to be compiled with -DNPARTITION (SPQR in particular). Nov 12, 2022: version 4.0.1 * BLAS definitions: no longer exposed to the user application Nov 12, 2022: version 4.0.0 * using CMake build system * integers: int (32-bit) and SuiteSparse_long (nominally 64-bit) replaced with int32_t and int64_t. * cholmod.h: single include file for all Modules * BLAS/LAPACK: relying on SuiteSparse_config and CMake to find and link with the BLAS and LAPACK libraries * libcholmod_cuda.so: CUDA support split into a separate library. * OpenMP: CHOLMOD_OMP_NUM_THREADS removed, replaced with run time controls (Common->nthreads_max, Common->chunk) * METIS: no longer built as a separate libary. A slightly modified version of METIS is embedded into the CHOLMOD library, with a prefix appended to each function name so it won't conflict with a standard METIS library that may already exist in the application. June 30, 2020: no change to version number * minor update to MATLAB tests: no change to compiled library, so version number remains 3.0.14. * replaced UFget with ssget in MATLAB tests Feb 20, 2020: version 3.0.14 * minor update to cholmod_check to print a matrix Dec 20, 2018: version 3.0.13 * bug fix to cholmod_core.h: so that a CUDA include file is properly included in a C++ caller; also required for SPQR. Mar 12, 2018: version 3.0.12 * bug fix to cholmod_rowcolcounts.c (int overflow was possible) May 4, 2016: version 3.0.11 * minor changes to Makefile Apr 1, 2016: version 3.0.10 * licensing simplified (no other change); refer to CHOLMOD/Doc/License.txt Feb 1, 2016: version 3.0.9 * update to Makefiles * minor change to CHOLMOD/Check/cholmod_write.c, when compiling with certain modules disabled. * more verbose error reporting * Demos now compile with MatrixOps module disabled, but they don't compute all residuals (requires the CHOLMOD/MatrixOps package) Jan 30, 2016: version 3.0.8 * better Makefiles for creating and installing shared libraries * CHOLMOD now uses METIS 5.1.0, which is distributed with SuiteSparse * correction to mexFunctions required for MATLAB R2015b, for sparse empty matrices and NULL mxGetPr Jan 1, 2016: version 3.0.7 * modified Makefile to create shared libraries No change to C code except version number July 14, 2015: version 3.0.6 * disabling of MatrixOps, Modify, and Supernodal modules didn't work properly. * added MATLAB interface for row add/delete (lurowmod mexFunction) Jan 19, 2015: version 3.0.5 * minor bug fix to cholmod_symmetry.c for the 'quick return' (option == 0). Jan 7, 2015: version 3.0.4 * serious bug fix to supernodal factorization. The bug was introduced in CHOLMOD v3.0.0 when the GPU acceleration was given a major update. The bug can cause a segfault, whether or not the GPU is used. Oct 23, 2014: version 3.0.3 * minor fix for CHOLMOD/Supernodal/cholmod_super_symbolic.c (was using a non-ANSI C method to declare and initialize a variable). * added additional paper in CHOLMOD/Doc Oct 10, 2014: version 3.0.2 * changes to accomodate GPU-accelerated SPQR * added CHOLMOD/Include/cholmod_function.h for backward compatibility for function pointers (moved from Common to SuiteSparse_config, as of v2.2.0) July 18, 2014: version 3.0.1 * minor correction to 3.0.0 Beta build process, to compile SPQR when CHOLMOD is compiled on the GPU * added cholmod_rowfac_mask2 function for LPDASA * to test the GPU, use 'make big' in CHOLMOD/Demo. You will need to first download the GHS_psdef/audikw_1.mtx: http://sparse.tamu.edu/GHS_psdef/audikw_1 March 26, 2014: version 3.0.0 (beta) * major update to GPU acceleration. Released at NVIDIA GTC 2014. July 31, 2013: version 2.2.0 * modified the CHOLMOD Common so that it is the same size regardless of whether or not the GPU is used. * changed malloc, printf, hypot, and divcomplex pointers to use SuiteSparse_config. Removed CHOLMOD Common-> function pointers. Apr 25, 2013: version 2.1.2 * minor update for CHOLMOD/Cholesky/*solve*.c: version 2.1.0 broke the Microsoft Visual C/C++ compiler Apr 16, 2013: version 2.1.1 * bug fix to Lib/Makefile and Demo/Makefile, to handle -DNCAMD correctly. * changes to Supernodal/t_cholmod_gpu.c: to fix a GPU memory leak, to fix the statistics on TRSM timing, and to reduce CPU-GPU memory traffic. * added cholmod_version function. Mar 27, 2013: version 2.1.0 * added the -DNCAMD option. Formerly, the -DNPARTITION option disabled both METIS and the interface to CAMD, CCOLAMD, and CSYMAMD. Now, -DNPARTITION controls just whether or not the interface to METIS is compiled. The new -DNCAMD option controls whether or not the interfaces to CAMD, CCOLAMD, and CSYMAMD are compiled. Both features remain in the Partition Module, as in prior versions. * added cholmod_lsolve_pattern and modified cholmod_row_lsubtree, to compute nonzero pattern of L\b where b is sparse * added cholmod_solve2 and cholmod_ensure_dense, so that repeated forward/backsolves can be done without the need to malloc/free, memory on each solve. Also provides the option for solving for a subset of the solution vector x (via the Bset and Xset parameters to cholmod_solve2). The last option required an IPerm member to be added to the Cholesky factorization object. It is only allocated and used if cholmod_solve2 solves with Bset. Jun 20, 2012: verison 2.0.1 * minor update for Windows (removed filesep, compiler port fix) * minor changes to format of User Guide * bug fix for GPU code (singular case) Jun 1, 2012: version 2.0.0 * changed from UFconfig to SuiteSparse_config * added interface to CUDA BLAS Dec 7, 2011: version 1.7.4 * fixed the Makefile to better align with CFLAGS and other standards * Makefile now detects whether or not METIS is present, and sets -DNPARTITION if it is not Jan 25, 2011: version 1.7.3 * minor fix to "make install" * minor change to Core/cholmod_memory.c, rename "I" which conflicts with a predefined token in some compilers Nov 30, 2009: version 1.7.2 * added "make install" and "make uninstall" * fixed interface to 64-bit BLAS for MATLAB 7.8 Sept 30, 2008, version 1.7.1 * bug fix to cholmod_symmetry; it reported incorrectly if the matrix had a zero-free diagonal or not. No effect on the use of CHOLMOD in MATLAB. No effect on the mwrite function, either, which uses cholmod_symmetry. Note that the number of nonzeros on the diagonal was (and still is) correctly computed. Only effect is on the UF_Index.cholcand statistic reported in the UFget index, and on the web pages, for the UF Sparse Matrix Collection (the UF_Index.cholcand field). This affects the output of spsym. Sept 20, 2008, version 1.7.0 * update for SuiteSparseQR: - add SuiteSparseQR knobs and stats to CHOLMOD Common - SuiteSparseQR uses CHOLMOD for its multifrontal symbolic analysis - changed (char *) input parameters to (const char *), to avoid spurious compiler warnings when C++ calls C. - minor change to the AMD backup strategy in cholmod_analyze, to better suit SuiteSparseQR - modified cholmod_analyze and cholmod_super_symbolic, to add "for_cholesky" parameter; new function cholmod_analyze_p2. This parameter is false for SuiteSparseQR. - minor correction to comments in cholmod_postorder.c - performance enhancement to supernodal symbolic analysis, when A or AA' is fairly dense Nov 1, 2007, version 1.6.0 * minor lint cleanup (no bugs) * new CHOLMOD_CLEAR_FLAG macro, which speeds up the calls to cholmod_clear_flag, avoiding the function call if not needed. Note that this leads to untested lines in the Tcov test, but the lines of the macro are tested in several places, just not everywhere it appers. * port to MATLAB 7.5 (mex -lmwblas option now required for Linux) * minor bug fix to cholmod_add.c to avoid potential Int overflow * extra option added to cholmod2 mexFunction * sparse2 mexFunction modified to ensure nnz(A) == nzmax(A) always holds (It didn't in v1.5.0 if numerically zero entries were dropped in A). * correction to Help comments for spsym function * bug fix to cholmod_symmetry.c: determination of Hermitian vs non-Hermitian matrices was incorrect if the diagonal was imaginary. * performance fix for cholmod_nesdis.c and nesdis mexFunction May 31, 2007, version 1.5.0 * 64-bit MATLAB interface * MATLAB interface back-ported to MATLAB 6.1. * bug fix: solving Dx=b using a supernodal factorization, in cholmod_l_solve, when sizeof(UF_long) > sizeof(BLAS integer) * changes to Makefiles to reflect directory changes in COLAMD and CCOLAMD v2.7.0 directory structure (CHOLMOD v1.5 requires v2.7.0 of those two packages) * update to Modify/cholmod_updown.c, to allow input vector R to be packed or unpacked. * bug fix to Tcov/huge.c test code, for 64-bit case (this has no effect on the CHOLMOD library itself, just the test code) Dec 12, 2006, version 1.4.0 * added support for large files (larger than 2GB) * minor MATLAB cleanup * renamed MATLAB function from cholmod to cholmod2, to avoid filename clash with itself (the built-in version of cholmod). Dec 2, 2006, version 1.3.0 * Major modification to cholmod_read.c; now fully supports all forms of the Matrix Market format. Added cholmod_read_dense and cholmod_read_matrix functions to cholmod_read.c. Major changes to mread MATLAB function. Added Common->prefer_binary option for cholmod_read. * Added cholmod_write.c (cholmod_write_sparse and cholmod_write_dense functions). Added mwrite MATLAB function. * Added 2nd output argument to sparse2 (Z, binary pattern of explicit zero entries). * Added the function cholmod_symmetry to the MatrixOps module. Added spsym MATLAB function. * 2nd argument to cholmod_triplet_to_sparse changed from int to size_t. * minor correction to cholmod_analyze_ordering, cholmod_dense.c * minor change to cholmod_rowfac.c, cholmod_solve.c, ... to allow for easier testing. Sept 28, 2006, version 1.2.1 * bug fix to cholmod_matlab.c, when working with sparse INT64 matrices in the "sparse2" function Aug 31, 2006, version 1.2 * Common->default_nesdis parameter and Common->called_nd statistic added. Otherwise, no change to user interface. v1.2 is fully upward compatible with v1.1 (even binary compatible). * non-supernodal Lx=b and L'x=b solves simplified, slight increase in performance. * update/downdate performance improved. * ordering options and output statistics added to MATLAB/cholmod mexFunction. July 27, 2006, version 1.1.1 * bug fix for cholmod_rowfac_mask, for the complex case. Has no effect on MATLAB. June 27, 2006: * trivial changes to nested dissection code, and cholmod_read.c (for debugging, and to add explicit typecasts so compilers don't complain). May, 2006: * Added new routines for LPDASA: cholmod_rowfac_mask, cholmod_updown_mask. Added cholmod_collapse_septree. Added nd_oksep, nd_components parameters to Common. Apr 30, 2006: version 1.1 * added interface to CAMD. cholmod_nested_dissection can now call CCOLAMD, CSYMAMD, and CAMD. Common->nd_camd usage extended. New argument added to nesdis mexFunction. New cholmod_camd function added. No other changes to CHOLMOD user interface. * more careful integer overflow checks. Added non-user-callable functions to add and multiply size_t integers, with overflow checks. * added Common->no_workspace_reallocate * flop count is now correct for A*A' case (Common->rowfacfl). Jan 18, 2006: version 1.0.2 * bug fix: MATLAB interface incorrect for full logical matrices. * Tcov tests modified to generate fewer intentional nan's, to make it easier to look for errors in BLAS libraries that incorrectly generate nan's. Dec 16, 2005: version 1.0.1 * bug fix: cholmod_amd allocated too small of a workspace when ordering A*A' Dec 8, 2005: version 1.0 * no real changes. Version 1.0 is the same as version 0.8. Version 1.0 is simply the formal stable release. * known issue: the floating point operation count, Common->rowfacfl, is statistic is incorrect when factorizing A*A'. This will be fixed in version 1.1. Nov 15, 2005: version 0.8 * bug fix in t_cholmod_super_numeric, for [R,p]=chol(A) usage. * Common->quick_return_if_not_posdef added. * Added cholmod_row_lsubtree (required for LPDASA) * bug fix: cholmod_rcond returned sqrt(1/cond) for an LL' factorization; 1/cond is required. * new statistics added: flop counts for cholmod_rowfac, # of factor column reallocations, # of factor reallocations due to column reallocations, and # of times the (non-default) bounds on diag(L) are hit. * factor column reallocation skipped if space already big enough. * bug fix: cholmod_copy_factor did not copy L->is_monotonic. * bug fix: cholmod_change_factor (diagonal entry was wrong in one case) * rcond added to cholmod mexFunction ([x,rcond] = cholmod(A,b)). * cholmod_rowadd, cholmod_rowdel modified. rowdel no longer removes entries from the matrix; it sets them to zero instead. Oct 10, 2005: version 0.7 * minor changes: minor change to Check/cholmod_check.c (coerce sizeof(...) to (int) when printing. Less strict check on A->p for unpacked matrices) , removed a few unused variables in Check/cholmod_read.c and Demo/cholmod*demo.c, changed "exit(0)" to "return(0)" in Demo/cholmod_simple.c. Changed Makefile so that "." is not assumed to be on the $path. Added Cygwin to architecture detection in Include/cholmod_blas.h. Added cparent and cmember to nesdis.m. Space for future expansion added to cholmod_common. * removed "rowmark" from the Modify module, which affects how partial updates to Lx=b solves are done during update/downdate. Should only affect LPDASA. * added CHOLMOD_SUBSUB_VERSION Aug 31, 2005: version 0.6 released. Matrix/inst/doc/SuiteSparse/CHOLMOD/Doc/License.txt0000644000175100001440000003141114552026002021436 0ustar hornikusers-------------------------------------------------------------------------------- ==> Check/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Check Module. Copyright (C) 2005-2022, Timothy A. Davis CHOLMOD is also available under other licenses; contact authors for details. http://www.suitesparse.com Note that this license is for the CHOLMOD/Check module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This Module 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -------------------------------------------------------------------------------- ==> Cholesky/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Cholesky module, Copyright (C) 2005-2022, Timothy A. Davis. CHOLMOD is also available under other licenses; contact authors for details. http://www.suitesparse.com Note that this license is for the CHOLMOD/Cholesky module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This Module 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -------------------------------------------------------------------------------- ==> Utility/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Utility Module. Copyright (C) 2023, Timothy A. Davis, All Rights Reserved. CHOLMOD is also available under other licenses; contact authors for details. http://www.suitesparse.com ---------------------------------------------------------------------------- This Module is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This Module 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -------------------------------------------------------------------------------- ==> Demo/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Demo Module. Copyright (C) 2005-2022, Timothy A. Davis. CHOLMOD is also available under other licenses; contact authors for details. http://www.suitesparse.com Note that this license is for the CHOLMOD/Demo module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module 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 Module 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 Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -------------------------------------------------------------------------------- ==> MATLAB/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/MATLAB Module. Copyright (C) 2005-2022, Timothy A. Davis. CHOLMOD is also available under other licenses; contact authors for details. MATLAB(tm) is a Registered Trademark of The MathWorks, Inc. http://www.suitesparse.com Note that this license is for the CHOLMOD/MATLAB module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module 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 Module 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 Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -------------------------------------------------------------------------------- ==> MatrixOps/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/MatrixOps Module. Copyright (C) 2005-2022, Timothy A. Davis. CHOLMOD is also available under other licenses; contact authors for details. http://www.suitesparse.com Note that this license is for the CHOLMOD/MatrixOps module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module 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 Module 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 Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -------------------------------------------------------------------------------- ==> Modify/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Modify Module. Copyright (C) 2005-2022, Timothy A. Davis and William W. Hager. CHOLMOD is also available under other licenses; contact authors for details. http://www.suitesparse.com Note that this license is for the CHOLMOD/Modify module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module 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 Module 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 Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -------------------------------------------------------------------------------- ==> Partition/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Partition Module. Copyright (C) 2005-2022, Univ. of Florida. Author: Timothy A. Davis CHOLMOD is also available under other licenses; contact authors for details. http://www.suitesparse.com Note that this license is for the CHOLMOD/Partition module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This Module 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -------------------------------------------------------------------------------- ==> Supernodal/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Supernodal Module. Copyright (C) 2005-2022, Timothy A. Davis CHOLMOD is also available under other licenses; contact authors for details. http://www.suitesparse.com Note that this license is for the CHOLMOD/Supernodal module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module 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 Module 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 Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -------------------------------------------------------------------------------- ==> Tcov/License.txt <== -------------------------------------------------------------------------------- CHOLMOD/Tcov Module. Copyright (C) 2005-2022, Timothy A. Davis CHOLMOD is also available under other licenses; contact authors for details. http://www.suitesparse.com Note that this license is for the CHOLMOD/Tcov module only. All CHOLMOD modules are licensed separately. ---------------------------------------------------------------------------- This Module 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 Module 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 Module; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. Matrix/inst/doc/SuiteSparse/SuiteSparse_config/0000755000175100001440000000000014576343415021335 5ustar hornikusersMatrix/inst/doc/SuiteSparse/SuiteSparse_config/README.txt0000644000175100001440000000707014552026002023017 0ustar hornikusersSuiteSparse_config, Copyright (c) 2012-2024, Timothy A. Davis. All Rights Reserved. SPDX-License-Identifier: BSD-3-clause The version of SuiteSparse_config always matches the version of the SuiteSparse meta-package. See the top-level SuiteSparse/ChangeLog for changes to this package. -------------------------------------------------------------------------------- SuiteSparse_config contains configuration settings for all many of the software packages that I develop or co-author. Note that older versions of some of these packages do not require SuiteSparse_config. Files in SuiteSparse_config: CMakeLists.txt for compiling SuiteSparse_config Makefile simple Makefile to control cmake (optional) README.txt this file SuiteSparse_config.c SuiteSparse-wide utilities SuiteSparse_config.h SuiteSparse-wide include file (created from Config/SuiteSparse_config.h) build/ where SuiteSparse_config is compiled Config/SuiteSparse_config.h.in source for SuiteSparse_config.h Config/README.md.in README.md for all of SuiteSparse cmake_modules/FindSuiteSparse_config.cmake how to find SuiteSparse_config cmake_modules/SuiteSparseBLAS.cmake find BLAS for SuiteSparse cmake_modules/SuiteSparseBLAS32.cmake when a 32-bit BLAS is found cmake_modules/SuiteSparseBLAS64.cmake when a 64-bit BLAS is found cmake_modules/SuiteSparseLAPACK.cmake find LAPACK for SuiteSparse cmake_modules/SuiteSparsePolicy.cmake SuiteSparse-wide policies cmake_modules/SuiteSparseReport.cmake SuiteSparse-wide reporting For packages that use cmake and require SuiteSparse_config, see: ../SuiteSparse_config/cmake_modules/FindSuiteSparse_config.cmake To compile/install SuiteSparse_config on Linux/MacOS, in this directory do: make sudo make install To compile all of SuiteSparse for installation only in ../lib and ../include instead: make local Within each package, to install only in ../lib and ../include, for example for UMFPACK: cd UMFPACK make local make install To clean up: make clean See the SuiteSparse/SuiteSparse_config/Makefile for more options. -------------------------------------------------------------------------------- SuiteSparse packages: -------------------------------------------------------------------------------- Package Description ------- ----------- AMD approximate minimum degree ordering CAMD constrained AMD COLAMD column approximate minimum degree ordering CCOLAMD constrained approximate minimum degree ordering UMFPACK sparse LU factorization, with the BLAS CXSparse int/long/real/complex version of CSparse CHOLMOD sparse Cholesky factorization, update/downdate KLU sparse LU factorization, BLAS-free BTF permutation to block triangular form LDL concise sparse LDL' LPDASA LP Dual Active Set Algorithm RBio read/write files in Rutherford/Boeing format SPQR sparse QR factorization (full name: SuiteSparseQR) SPEX sparse left-looking integer-preserving LU factorization SuiteSparse_config is not required by these packages: CSparse a Concise Sparse matrix package MATLAB_Tools toolboxes for use in MATLAB GraphBLAS graph algorithms in the language of linear algebra If you edit this directory then you should do "make purge ; make" in the parent directory to recompile all of SuiteSparse. Otherwise, the changes will not necessarily be applied. Matrix/inst/test-tools-Matrix.R0000644000175100001440000007540214565737512016242 0ustar hornikusers#### Tools for Package Testing --- in Matrix, sourced by ./test-tools.R #### ------------------------- ### ------- Part III -- "Matrix" (classes) specific ---------------------- ## lower.tri() and upper.tri() -- masking base definitions ## R/src/library/base/R/lower.tri.R ## R/src/library/base/R/upper.tri.R ## but we do __not__ want to coerce to "base R" 'matrix' via as.matrix(): ## lower.tri <- function(x, diag = FALSE) if(diag) row(x) >= col(x) else row(x) > col(x) upper.tri <- function(x, diag = FALSE) if(diag) row(x) <= col(x) else row(x) < col(x) lsM <- function(...) { for(n in ls(..., envir=parent.frame())) if(is((. <- get(n)),"Matrix")) cat(sprintf("%5s: '%s' [%d x %d]\n",n,class(.), nrow(.),ncol(.))) } asD <- function(m) { ## as "Dense" if(canCoerce(m, "denseMatrix")) as(m, "denseMatrix") else if(canCoerce(m, (cl <- paste(.M.kind(m), "denseMatrix", sep='')))) as(m, cl) else if(canCoerce(m, "dgeMatrix")) as(m, "dgeMatrix") else stop("cannot coerce to a typical dense Matrix") } ## "normal" sparse Matrix: Csparse, no diag="U" asCsp <- function(x) diagU2N(as(x, "CsparseMatrix")) ##' @title quasi-identical dimnames Qidentical.DN <- function(dx, dy) { stopifnot(is.list(dx) || is.null(dx), is.list(dy) || is.null(dy)) ## "empty" (is.null.DN(dx) && is.null.DN(dy)) || identical(dx, dy) } ##' quasi-identical() for 'Matrix' matrices Qidentical <- function(x,y, strictClass = TRUE) { if(!identical(class(x), cy <- class(y))) { if(strictClass || !is(x, cy)) return(FALSE) ## else try further } slts <- slotNames(x) ## MJ: should be slotNames(y), since is(x, class(y)) ?? if("Dimnames" %in% slts) { ## always (or we have no 'Matrix') slts <- slts[slts != "Dimnames"] if(!Qidentical.DN(x@Dimnames, y@Dimnames) && ## allow for "completion" of (NULL, ) dimnames of symmetricMatrix: !Qidentical.DN(dimnames(x), dimnames(y))) return(FALSE) } if("factors" %in% slts) { ## allow one empty and one non-empty 'factors' slts <- slts[slts != "factors"] ## if both are not empty, they must be the same: if(length(xf <- x@factors) && length(yf <- y@factors)) if(!identical(xf, yf)) return(FALSE) } for(sl in slts) if(!identical(slot(x,sl), slot(y,sl))) return(FALSE) TRUE } ## MJ: It seems intuitive to allow either of is(x, class(y)) ## and is(y, class(x)) when strictClass=FALSE ... .MJ.Qidentical <- function(x, y, strictClass = TRUE, skipSlots = NULL) { isxy <- identical(cx <- class(x), cy <- class(y)) if (!isxy) { if (strictClass) return(FALSE) isxy <- is(x, cy) if (!(isxy || is(y, cx))) return(FALSE) ## else try further } slts <- slotNames(if (isxy) y else x) if (length(skipSlots)) slts <- setdiff(slts, skipSlots) if ("Dimnames" %in% slts) { ## always, or we have no "Matrix" ## allow symmetrization of 'Dimnames' for "symmetricMatrix" : slts <- slts[slts != "Dimnames"] if(!Qidentical.DN(x@Dimnames, y@Dimnames) && !Qidentical.DN(dimnames(x), dimnames(y))) return(FALSE) } if ("factors" %in% slts) { ## allow one empty and one non-empty 'factors' : slts <- slts[slts != "factors"] ## if both are not empty, they must be the same: if (length(xf <- x@factors) && length(yf <- y@factors) && !identical(xf, yf)) return(FALSE) } for (slt in slts) if (!identical(slot(x, slt), slot(y, slt))) return(FALSE) TRUE } ##' quasi-identical() for traditional ('matrix') matrices mQidentical <- function(x,y, strictClass = TRUE) { if(!identical(class(x), cy <- class(y))) { if(strictClass || !is(x, cy)) return(FALSE) ## else try further } if(!Qidentical.DN(dimnames(x), dimnames(y))) return(FALSE) identical(unname(x), unname(y)) } Q.C.identical <- function(x,y, sparse = is(x,"sparseMatrix"), checkClass = TRUE, strictClass = TRUE) { if(checkClass && class(x) != class(y)) { if(strictClass || !is(x, class(y))) return(FALSE) ## else try further } if(sparse) Qidentical(as(x,"CsparseMatrix"), as(y,"CsparseMatrix"), strictClass=strictClass) else Qidentical(x,y, strictClass=strictClass) } ##' ##' ##'

##' @title Quasi-equal for 'Matrix' matrices ##' @param x Matrix ##' @param y Matrix ##' @param superclasses x and y must coincide in (not) extending these; set to empty, ##' if no class/inheritance checks should happen. ##' @param dimnames.check logical indicating if dimnames(.) much match ##' @param tol NA (--> use "==") or numerical tolerance for all.equal() ##' @return logical: Are x and y (quasi) equal ? Q.eq <- function(x, y, superclasses = c("sparseMatrix", "denseMatrix", "dMatrix", "lMatrix", "nMatrix"), dimnames.check = TRUE, tol = NA) { ## quasi-equal - for 'Matrix' matrices if(any(dim(x) != dim(y))) return(FALSE) if(dimnames.check && !identical(dimnames(x), dimnames(y))) return(FALSE) xcl <- getClassDef(class(x)) ycl <- getClassDef(class(y)) for(SC in superclasses) { if( extends(xcl, SC) && !extends(ycl, SC)) return(FALSE) } asC <- ## asCommon if((isDense <- extends(xcl,"denseMatrix"))) function(m) as(m, "matrix") else function(m) as(as(as(m,"CsparseMatrix"), "dMatrix"), "generalMatrix") # => "dgC" if(is.na(tol)) { if(isDense) all(x == y | (is.na(x) & is.na(y))) else ## 'x == y' blows up for large sparse matrices: isTRUE(all.equal(asC(x), asC(y), tolerance = 0., check.attributes = dimnames.check)) } else if(is.numeric(tol) && tol >= 0) { isTRUE(all.equal(asC(x), asC(y), tolerance = tol, check.attributes = dimnames.check)) } else stop("'tol' must be NA or non-negative number") } Q.eq2 <- function(x, y, superclasses = c("sparseMatrix", "denseMatrix"), dimnames.check = FALSE, tol = NA) Q.eq(x,y, superclasses=superclasses, dimnames.check=dimnames.check, tol=tol) ##' ##' ##'
##' @title Quasi-equality of symmpart(m) + skewpart(m) with m ##' @param m Matrix ##' @param tol numerical tolerance for all.equal() ##' @return logical ##' @author Martin Maechler Q.eq.symmpart <- function(m, tol = 8 * .Machine$double.eps) { ss <- symmpart(m) + skewpart(m) if(hasNA <- any(iNA <- is.na(ss))) { ## ss has the NA's symmetrically, but typically m has *not* iiNA <- which(iNA) # <- useful! -- this tests which() methods! ## assign NA's too -- using correct kind of NA: m[iiNA] <- as(NA, Matrix:::.type.kind[Matrix:::.M.kind(m)]) } Q.eq2(m, ss, tol = tol) } ##' sample.int(n, size, replace=FALSE) for really large n: sampleL <- function(n, size) { if(n < .Machine$integer.max) sample.int(n, size) else { i <- unique(round(n * runif(1.8 * size))) while(length(i) < size) { i <- unique(c(i, round(n * runif(size)))) } i[seq_len(size)] } } ## Useful Matrix constructors for testing: ##' @title Random Sparse Matrix ##' @param n ##' @param m number of columns; default (=n) ==> square matrix ##' @param density the desired sparseness density: ##' @param nnz number of non-zero entries; default from \code{density} ##' @param repr character string specifying the sparseness kind of the result. ##' @param giveCsparse *deprecated* logical specifying if result should be CsparseMatrix ##' @return a [CTR]sparseMatrix, n x m ##' @author Martin Maechler, Mar 2008; July 2020 ('repr' instead og 'giveCsparse') rspMat <- function(n, m = n, density = 1/4, nnz = round(density * n*m), repr = c("C","T","R"), giveCsparse) { stopifnot(length(n) == 1, n == as.integer(n), length(m) == 1, m == as.integer(m), 0 <= density, density <= 1, 0 <= nnz, nnz <= (N <- n*m)) in0 <- sampleL(N, nnz) x <- sparseVector(i = in0, x = as.numeric(1L + seq_along(in0)), length = N) dim(x) <- c(n,m)#-> sparseMatrix ## silent, back compatible (not yet warning about 'giveCsparse' deprecation): repr <- if(missing(repr) && !missing(giveCsparse)) if(giveCsparse) "C" else "T" else match.arg(repr) switch(repr, "C" = as(x, "CsparseMatrix"), "T" = x,# TsparseMatrix "R" = as(x, "RsparseMatrix")) } ## __DEPRECATED__ !! rSparseMatrix <- function(nrow, ncol, nnz, rand.x = function(n) round(rnorm(nnz), 2), ...) { stopifnot((nnz <- as.integer(nnz)) >= 0, nrow >= 0, ncol >= 0, nnz <= nrow * ncol) .Deprecated("rsparsematrix") ##========= sparseMatrix(i = sample(nrow, nnz, replace = TRUE), j = sample(ncol, nnz, replace = TRUE), x = rand.x(nnz), dims = c(nrow, ncol), ...) } rUnitTri <- function(n, upper = TRUE, ...) { ## Purpose: random unit-triangular sparse Matrix .. built from rspMat() ## ---------------------------------------------------------------------- ## Arguments: n: matrix dimension ## upper: logical indicating if upper or lower triangular ## ... : further arguments passed to rspMat(), eg. 'density' ## ---------------------------------------------------------------------- ## Author: Martin Maechler, Date: 5 Mar 2008, 11:35 r <- (if(upper) triu else tril)(rspMat(n, ...)) ## make sure the diagonal is empty diag(r) <- 0 r <- drop0(r) r@diag <- "U" r } ##' Construct a nice (with exact numbers) random artificial \eqn{A = L D L'} ##' decomposition with a sparse \eqn{n \times n}{n x n} matrix \code{A} of ##' density \code{density} and square root \eqn{D} determined by \code{d0}. ##' ##' If one of \code{rcond} or \code{condest} is true, \code{A} must be ##' non-singular, both use an \eqn{LU} decomposition requiring ##' non-singularity. ##' @title Make Nice Artificial A = L D L' (With Exact Numbers) Decomposition ##' @param n matrix dimension \eqn{n \times n}{n x n} ##' @param density ratio of number of non-zero entries to total number ##' @param d0 The sqrt of the diagonal entries of D default \code{10}, to be ##' \dQuote{different} from \code{L} entries. More generally these can be negative ##' @param rcond logical indicating if \code{\link{rcond}(A, useInv=TRUE)} ##' should be returned which requires non-singular A and D. ##' @param condest logical indicating if \code{\link{condest}(A)$est} ##' should be returned which requires non-singular A and D. ##' @return list with entries A, L, d.half, D, ..., where A inherits from ##' class \code{"\linkS4class{symmetricMatrix}"} and should be equal to ##' \code{as(L \%*\% D \%*\% t(L), "symmetricMatrix")}. ##' @author Martin Maechler, Date: 15 Mar 2008 mkLDL <- function(n, density = 1/3, d0 = 10, d.half = d0 * sample.int(n), # random permutation rcond = (n < 99), condest = (n >= 100)) { stopifnot(n == round(n), density <= 1) n <- as.integer(n) stopifnot(n >= 1, is.numeric(d.half), length(d.half) == n)# no longer (2023-05-24): d.half >= 0 L <- Matrix(0, n,n) nnz <- round(density * n*n) L[sample(n*n, nnz)] <- seq_len(nnz) L <- tril(L, -1L) diag(L) <- 1 ### FIXME: allow *negative* d.half[] entries! dh2 <- d.half^2 non.sing <- sum(dh2 > 0) == n D <- Diagonal(x = dh2) A <- tcrossprod(L * rep(d.half, each=n)) ## = as(L %*% D %*% t(L), "symmetricMatrix") list(A = A, L = L, d.half = d.half, D = D, rcond.A = if (rcond && non.sing) rcond(A, useInv=TRUE), cond.A = if(condest && non.sing) condest(A)$est) } eqDeterminant <- function(m1, m2, NA.Inf.ok=FALSE, tol=.Machine$double.eps^0.5, ...) { d1 <- determinant(m1) ## logarithm = TRUE d2 <- determinant(m2) d1m <- as.vector(d1$modulus)# dropping attribute d2m <- as.vector(d2$modulus) if((identical(d1m, -Inf) && identical(d2m, -Inf)) || ## <==> det(m1) == det(m2) == 0, then 'sign' may even differ ! (is.na(d1m) && is.na(d2m))) ## if both are NaN or NA, we "declare" that's fine here return(TRUE) else if(NA.Inf.ok && ## first can be NA, second infinite: ## wanted: base::determinant.matrix() sometimes gives -Inf instead ## of NA,e.g. for matrix(c(0,NA,0,0,NA,NA,0,NA,0,0,1,0,0,NA,0,1), 4,4)) is.na(d1m) && is.infinite(d2m)) return(TRUE) ## else if(is.infinite(d1m)) d1$modulus <- sign(d1m)* .Machine$double.xmax if(is.infinite(d2m)) d2$modulus <- sign(d2m)* .Machine$double.xmax ## now they are finite or *one* of them is NA/NaN, and all.equal() will tell so: all.equal(d1, d2, tolerance=tol, ...) } ##' @param A a non-negative definite sparseMatrix, typically "dsCMatrix" ##' ##' @return a list with components resulting from calling ##' Cholesky(., perm = .P., LDL = .L., super = .S.) ##' ##' for all 2*2*3 combinations of (.P., .L., .S.) allCholesky <- function(A, verbose = FALSE, silentTry = FALSE) { ## Author: Martin Maechler, Date: 16 Jul 2009 ##' @param r list of CHMfactor objects, typically with names() as '. | .' ##' ##' @return an is(perm,LDL,super) matrix with interesting and *named* rownames CHM_to_pLs <- function(r) { is.perm <- function(.) if(inherits(., "try-error")) NA else .@type[1L] != 0L is.LDL <- function(.)if(inherits(., "try-error")) NA else isLDL(.) r.st <- cbind(perm = sapply(r, is.perm), LDL = sapply(r, is.LDL), super = sapply(r, class) == "dCHMsuper") names(dimnames(r.st)) <- list(" p L s", "") r.st } my.Cholesky <- { if(verbose) function (A, perm = TRUE, LDL = !super, super = FALSE, Imult = 0, ...) { cat(sprintf("Chol..(*, perm= %1d, LDL= %1d, super=%1d):", perm, LDL, super)) r <- Cholesky(A, perm=perm, LDL=LDL, super=super, Imult=Imult, ...) cat(" [Ok]\n") r } else Cholesky } logi <- c(FALSE, TRUE) d12 <- expand.grid(perm = logi, LDL = logi, super = c(logi,NA), KEEP.OUT.ATTRS = FALSE) r1 <- lapply(seq_len(nrow(d12)), function(i) try(do.call(my.Cholesky, c(list(A = A), as.list(d12[i,]))), silent=silentTry)) names(r1) <- apply(d12, 1, function(.) paste(symnum(.), collapse=" ")) dup.r1 <- duplicated(r1) r.all <- CHM_to_pLs(r1) if(!identical(dup.r1, duplicated(r.all))) warning("duplicated( ) differs from duplicated( )", immediate. = TRUE) list(Chol.A = r1, dup.r.all = dup.r1, r.all = r.all, r.uniq = CHM_to_pLs(r1[ ! dup.r1])) } ##' Cheap Boolean Arithmetic Matrix product ##' Should be equivalent to %&% which is faster [not for large dense!]. ##' Consequently mainly used in checkMatrix() ## The first version (up to Aug.2022) -- possibly what we should use for dense case (!?) boolProd0 <- function(x,y) as((abs(x) %*% abs(y)) > 0, "nMatrix") ## New since Aug.13, 2022, ensuring that zeros are dropped isCRT <- function(x, cl = getClass(class(x))) extends(cl, "CsparseMatrix") || extends(cl, "TsparseMatrix") || extends(cl, "RsparseMatrix") boolProd <- function(x,y) { ## treat x & y, drop0() & coercing to "n" -- this treats NA <==> 1 (!) x <- if(isCRT(x)) .sparse2kind(x, kind="n", drop0=TRUE) else as(drop0(x), "nMatrix") y <- if(isCRT(y)) .sparse2kind(y, kind="n", drop0=TRUE) else as(drop0(y), "nMatrix") r <- (abs(x) %*% abs(y)) > 0 if(isCRT(r)) .sparse2kind(r, kind="n", drop0=TRUE) else # also for "sparseMatrix" cases "indMatrix" (incl "pMatrix") or "diagonalMatrix" ## NB: "diagonalMatrix already *does* drop0(.) when coerced to "nMatrix" as(r, "nMatrix") } .sparse2kind <- Matrix:::.sparse2kind # (FIXME -- a version of this should be exported!) ###----- Checking a "Matrix" ----------------------------------------- ##' Check the compatibility of \pkg{Matrix} package Matrix with a ##' \dQuote{traditional} \R matrix and perform a host of internal consistency ##' checks. ##' ##' @title Check Compatibility of Matrix Package Matrix with Traditional R Matrices ##' ##' @param m a "Matrix" ##' @param m.m as(m, "matrix") {if 'do.matrix' } ##' @param do.matrix logical indicating if as(m, "matrix") should be applied; ##' typically false for large sparse matrices ##' @param do.t logical: is t(m) "feasible" ? ##' @param doNorm ##' @param doOps ##' @param doSummary ##' @param doCoerce ##' @param doCoerce2 ##' @param do.prod ##' @param verbose logical indicating if "progress output" is produced. ##' @param catFUN (when 'verbose' is TRUE): function to be used as generalized cat() ##' @return TRUE (invisibly), unless an error is signalled ##' @author Martin Maechler, since 11 Apr 2008 checkMatrix <- function(m, m.m = if(do.matrix) as(m, "matrix"), do.matrix = !isSparse || prod(dim(m)) < 1e6, do.t = TRUE, doNorm = TRUE, doOps = TRUE, doSummary = TRUE, doCoerce = TRUE, doCoerce2 = doCoerce && !isRsp, doDet = do.matrix, do.prod = do.t && do.matrix && !isRsp, verbose = TRUE, catFUN = cat, MSG = if(interactive() || capabilities("long.double") || isTRUE(get0("doExtras"))) message else function(...) {} ) { ## is also called from dotestMat() in ../tests/Class+Meth.R stopifnot(is(m, "Matrix")) validObject(m) # or error(....) clNam <- class(m) cld <- getClassDef(clNam) ## extends(cld, FOO) is faster than is(m, FOO) isGen <- extends(cld, "generalMatrix") isSym <- extends(cld, "symmetricMatrix") isTri <- extends(cld, "triangularMatrix") isCor <- isSym && (extends(cld, "corMatrix") || extends(cld, "copMatrix")) if(isSparse <- extends(cld, "sparseMatrix")) { # also true for these isCsp <- extends(cld, "CsparseMatrix") isRsp <- extends(cld, "RsparseMatrix") isTsp <- extends(cld, "TsparseMatrix") isDiag <- extends(cld, "diagonalMatrix") isInd <- extends(cld, "indMatrix") isPerm <- extends(cld, "pMatrix") } else isCsp <- isRsp <- isTsp <- isDiag <- isInd <- isPerm <- FALSE is.n <- extends(cld, "nMatrix") nonMatr <- clNam != (Mcl <- MatrixClass(clNam, cld)) Cat <- function(...) if(verbose) cat(...) CatF <- function(...) if(verbose) catFUN(...) ## warnNow <- function(...) warning(..., call. = FALSE, immediate. = TRUE) DO.m <- function(expr) if(do.matrix) eval(expr) else TRUE vec <- function(x) { dim(x) <- c(length(x), 1L) dimnames(x) <- list(NULL,NULL) x } eps16 <- 16 * .Machine$double.eps ina <- is.na(m) if(do.matrix) { stopifnot(all(ina == is.na(m.m)), all(is.nan(m) == is.nan(m.m)), all(is.finite(m) == is.finite(m.m)), all(is.infinite(m) == is.infinite(m.m)), all(m == m | ina), ## check all() , "==" [Compare], "|" [Logic] if(ncol(m) > 0) identical3(unname(m[,1]), unname(m.m[,1]), as(m[,1,drop=FALSE], "vector")) else identical(as(m, "vector"), as.vector(m.m))) if(any(m != m & !ina)) stop(" any (m != m) should not be true") } else { if(any(m != m)) stop(" any (m != m) should not be true") if(ncol(m) > 0) stopifnot(identical(unname(m[,1]), as(m[,1,drop=FALSE], "vector"))) else stopifnot(identical(as(m, "vector"), as.vector(as(m, "matrix")))) } if(do.t) { tm <- t(m) if(isSym) ## check that t() swaps 'uplo' L <--> U : stopifnot(c("L","U") == sort(c(m@uplo, tm@uplo))) ttm <- t(tm) ## notInd: "pMatrix" ok, but others inheriting from "indMatrix" are not notInd <- (!isInd || isPerm) if(notInd && (isCsp || isGen || isDiag)) stopifnot(Qidentical(m, ttm, strictClass = !nonMatr)) else if(do.matrix) { if(notInd) stopifnot(nonMatr || class(ttm) == clNam) stopifnot(all(m == ttm | ina)) ## else : not testing } ## crossprod() %*% etc if(do.prod) { c.m <- crossprod(m, boolArith = FALSE) tcm <- tcrossprod(m, boolArith = FALSE) tolQ <- if(isSparse) NA else eps16 stopifnot(dim(c.m) == rep.int(ncol(m), 2), dim(tcm) == rep.int(nrow(m), 2), ## FIXME: %*% drops dimnames Q.eq2(c.m, tm %*% m, tol = tolQ), Q.eq2(tcm, m %*% tm, tol = tolQ), ## should work with dimnames: Q.eq(m %&% tm, boolProd(m, tm), superclasses=NULL, tol = 0) , Q.eq(tm %&% m, boolProd(tm, m), superclasses=NULL, tol = 0) ) } } if(!do.matrix) { CatF(" will *not* coerce to 'matrix' since do.matrix is FALSE\n") } else if(doNorm) { CatF(sprintf(" norm(m [%d x %d]) :", nrow(m), ncol(m))) for(typ in c("1","I","F","M")) { Cat('', typ, '') stopifnot(all.equal(norm(m,typ), norm(m.m,typ))) } Cat(" ok\n") } if(do.matrix && doSummary) { summList <- lapply(getGroupMembers("Summary"), get, envir = asNamespace("Matrix")) CatF(" Summary: ") for(f in summList) { ## suppressWarnings(): e.g. any() would warn here: r <- suppressWarnings(identical(f(m), f(m.m))) if(!isTRUE(r)) { ## typically for prod() f.nam <- sub("..$", '', sub("^\\.Primitive..", '', format(f))) ## sum() and prod() are sensitive to order of f. p. operations ## particularly on systems where sizeof(long double) == sizeof(double) (if(any(f.nam == c("sum", "prod"))) MSG else stop)( sprintf("%s(m) [= %g] differs from %s(m.m) [= %g]", f.nam, f(m), f.nam, f(m.m))) } } if(verbose) cat(" ok\n") } ## and test 'dim()' as well: d <- dim(m) isSqr <- d[1] == d[2] if(do.t) stopifnot(identical(diag(m), diag(t(m)))) ## TODO: also === diag(band(m,0,0)) if(prod(d) < .Machine$integer.max && !extends(cld, "modelMatrix")) { vm <- vec(m) stopifnot(is(vm, "Matrix"), validObject(vm), dim(vm) == c(d[1]*d[2], 1)) } if(!isInd) m.d <- local({ m. <- m diag(m.) <- diag(m) ## << *assigning* to 'm.' now typically annihilates @factor if(.hasSlot(m, "factors") && length(f <- m@factors)) m.@factors <- f m. }) if(do.matrix) stopifnot(identical(dim(m.m), dim(m)), ## now that "pMatrix" subsetting gives *LOGICAL* ## if(isPerm) { ## identical(as.integer(unname(diag(m))), unname(diag(m.m))) ## } else identical(diag(m), # base:: *and* Matrix diag() now keep names diag(m.m)),## not for NA: diag(m) == diag(m.m), identical(nnzero(m), sum(m.m != 0)), identical(nnzero(m, na.counted = FALSE), sum(m.m != 0, na.rm = TRUE)), identical(nnzero(m, na.counted = TRUE), sum(m.m != 0 | is.na(m.m))) ) if(isSparse) { n0m <- drop0(m) #==> n0m is Csparse has0 <- !Qidentical(n0m, as(m,"CsparseMatrix")) } if(isDiag) stopifnot(exprs = { .MJ.Qidentical(m, m.d, strictClass = FALSE, skipSlots = if(m@diag != "N") c("diag", "x")) m@diag == "N" || (m.d@diag == "N" && identical(m.d@x, diag(m, names = FALSE))) }) else if(isTri && m@diag != "N") stopifnot(exprs = { is(m.d, "triangularMatrix") && m.d@diag == "N" .MJ.Qidentical(m, m.d, strictClass = FALSE, skipSlots = c("diag", "p", "i", "j", "x")) isSparse || all(m == m.d) }) else if(!isInd) stopifnot(.MJ.Qidentical(m, m.d, strictClass = FALSE, skipSlots = if(((isCsp || isRsp) && has0) || isTsp) c("p", "i", "j", "x"))) ## use non-square matrix when "allowed": ## m12: sparse and may have 0s even if this is not: if(isSparse && has0) m12 <- as(as( m, "lMatrix"),"CsparseMatrix") m12 <- drop0(m12) if(do.matrix) { ## "!" should work (via as(*, "l...")) : m11 <- as(as(!!m,"CsparseMatrix"), "lMatrix") if(!Qidentical(m11, m12)) stopifnot(Qidentical(as(m11, "generalMatrix"), as(m12, "generalMatrix"))) } if(isSparse && !isDiag && !is.n) { ## ensure that as(., "nMatrix") gives nz-pattern CatF("as(., \"nMatrix\") giving full nonzero-pattern: ") n1 <- as(m, "nMatrix") ns <- as(m, "nsparseMatrix") stopifnot(identical(n1,ns), ## only testing [CR]sparseMatrix and indMatrix here ... ## sum() excludes duplicated (i,j) pairs whereas ## length(diagU2N(<[^n].T>)) includes them ... isTsp || (if(isSym) length(if(.hasSlot(n1, "i")) n1@i else n1@j) else sum(n1)) == length(if(isInd) m@perm else diagU2N(m)@x)) Cat("ok\n") } if(doOps) { ## makes sense with non-trivial m (!) CatF("2*m =?= m+m: ") if(identical(2*m, m+m)) Cat("identical\n") else if(do.matrix) { eq <- as(2*m,"matrix") == as(m+m, "matrix") # but work for NA's: stopifnot(all(eq | (is.na(m) & is.na(eq)))) Cat("ok\n") } else {# !do.matrix stopifnot(identical(as(2*m, "CsparseMatrix"), as(m+m, "CsparseMatrix"))) Cat("ok\n") } if(do.matrix) { ## m == m etc, now for all, see above CatF("m >= m for all: "); stopifnot(all(m >= m | ina)); Cat("ok\n") } if(prod(d) > 0) { CatF("m < m for none: ") mlm <- m < m if(!any(ina)) stopifnot(!any(mlm)) else if(do.matrix) stopifnot(!any(mlm & !ina)) else { ## !do.matrix & any(ina) : !ina can *not* be used mlm[ina] <- FALSE stopifnot(!any(mlm)) } Cat("ok\n") } if(isSqr) { if(do.matrix) { ## determinant() "fails" for triangular with NA such as ## (m <- matrix(c(1:0,NA,1), 2)) CatF("symmpart(m) + skewpart(m) == m: ") Q.eq.symmpart(m) CatF("ok; determinant(): ") if(!doDet) Cat(" skipped (!doDet): ") else if(any(is.na(m.m)) && isTri) Cat(" skipped: is triang. and has NA: ") else stopifnot(eqDeterminant(m, m.m, NA.Inf.ok=TRUE)) Cat("ok\n") } } else assertError(determinant(m)) }# end{doOps} if(doCoerce && do.matrix && canCoerce("matrix", clNam)) { CatF("as(, ",clNam,"): ", sep='') m3 <- as(m.m, clNam) Cat("valid:", validObject(m3), "\n") ## m3 should ``ideally'' be identical to 'm' } if(doCoerce2 && do.matrix) { ## not for large m: !m will be dense if(is.n) { mM <- if(nonMatr) as(m, Mcl) else m stopifnot(identical(mM, as(as(m, "dMatrix"),"nMatrix")), identical(mM, as(as(m, "lMatrix"),"nMatrix")), identical(which(m), which(m.m))) } else if(extends(cld, "lMatrix")) { ## should fulfill even with NA: stopifnot(all(m | !m | ina), !any(!m & m & !ina)) if(isTsp) # allow modify, since at end here m <- asUniqueT(m, isT = TRUE) stopifnot(identical(m, m & TRUE), identical(m, FALSE | m)) ## also check the coercions to [dln]Matrix m. <- if(isSparse && has0) n0m else m m1. <- m. # replace NA by 1 in m1. , carefully not changing class: if(any(ina)) m1.@x[is.na(m1.@x)] <- TRUE stopifnot(identical(m. , as(as(m. , "dMatrix"),"lMatrix")), clNam == "ldiMatrix" || # <- there's no "ndiMatrix" ## coercion to n* and back: only identical when no extra 0s: identical(m1., as(as(m1., "nMatrix"),"lMatrix")), identical(which(m), which(m.m))) } else if(extends(cld, "dMatrix")) { m. <- if(isSparse && has0) n0m else m m1 <- m1. <- (m. != 0)*1 ## replace NA by 1 in m1. , carefully not changing class: if(any(ina)) m1.@x[is.na(m1.@x)] <- 1 ## coercion to n* (nz-pattern!) and back: only identical when no extra 0s and no NAs: stopifnot(Q.C.identical(m1., as(as(m., "nMatrix"),"dMatrix"), isSparse, checkClass = FALSE), Q.C.identical(m1 , as(as(m., "lMatrix"),"dMatrix"), isSparse, checkClass = FALSE)) } maybeDense <- if(isSparse) identity else function(.) as(., "denseMatrix") if(isTri) { mm. <- m i0 <- if(m@uplo == "L") upper.tri(mm.) else lower.tri(mm.) n.catchWarn <- if(is.n) suppressWarnings else identity n.catchWarn( mm.[i0] <- 0 ) # ideally, mm. remained triangular, but can be dge* ## Aug.2022 - Coercion deprecations: No longer do as(*, clNam): CatF("as(mm., \"triangularMatrix\"): ") tm <- as(mm., "triangularMatrix") Cat("valid:", validObject(tm), "\n") if(m@uplo == tm@uplo) { ## otherwise, the matrix effectively was *diagonal* if(!isSparse && Matrix:::.isPacked(m)) m <- unpack(m) # to match tm ## note that diagU2N() |-> dtC, now dtT: stopifnot(Qidentical(tm, maybeDense(diagU2N(m)))) } } else if(isDiag) { ## TODO } else { ## TODO } }# end {doCoerce2 && ..} if(doCoerce && isSparse) { ## coerce to sparseVector and back : v <- as(m, "sparseVector") stopifnot(length(v) == prod(d)) dim(v) <- d stopifnot(Q.eq2(m, v)) } invisible(TRUE) } ## {checkMatrix} ### --- These use ##' Check QR-consistency of dense and sparse chk.qr.D.S <- function(d., s., y, Y = Matrix(y), force = FALSE, tol = 1e-10) { stopifnot(is.qr(d.), is(s., "sparseQR")) cc <- qr.coef(d.,y) rank.def <- any(is.na(cc)) && d.$rank < length(d.$pivot) if(rank.def && force) cc <- mkNA.0(cc) ## set NA's to 0 .. ok, in some case ## when system is rank deficient, have differing cases, not always just NA <-> 0 coef ## FIXME though: resid & fitted should be well determined if(force || !rank.def) stopifnot( is.all.equal3( cc , qr.coef (s.,y), drop(qr.coef (s.,Y)), tol=tol), is.all.equal3(qr.resid (d.,y), qr.resid (s.,y), drop(qr.resid (s.,Y)), tol=tol), is.all.equal3(qr.fitted(d.,y), qr.fitted(s.,y), drop(qr.fitted(s.,Y)), tol=tol) ) } ##' "Combi" calling chkQR() on both "(sparse)Matrix" and 'traditional' version ##' ------ and combine the two qr decompositions using chk.qr.D.S() ##' [ chkQR() def. in >>>>> ./test-tools-1.R <<<<< ] ##' ##' @title check QR-decomposition, and compare sparse and dense one ##' @param A a 'Matrix' , typically 'sparseMatrix' ##' @param Qinv.chk ##' @param QtQ.chk ##' @param quiet ##' @return list with 'qA' (sparse QR) and 'qa' (traditional (dense) QR) ##' @author Martin Maechler checkQR.DS.both <- function(A, Qinv.chk, QtQ.chk=NA, quiet=FALSE, giveRE=TRUE, tol = 1e-13) { stopifnot(is(A,"Matrix")) if(!quiet) cat("classical: ") qa <- chkQR(as(A, "matrix"), Qinv.chk=TRUE, QtQ.chk=TRUE, tol=tol, giveRE=giveRE)# works always if(!quiet) cat("[Ok] --- sparse: ") qA <- chkQR(A, Qinv.chk=Qinv.chk, QtQ.chk=QtQ.chk, tol=tol, giveRE=giveRE) validObject(qA) if(!quiet) cat("[Ok]\n") chk.qr.D.S(qa, qA, y = 10 + 1:nrow(A), tol = 256*tol)# ok [not done in rank deficient case!] invisible(list(qA=qA, qa=qa)) } non0.ij <- function(M) Matrix:::non0.i(as(M, "sparseMatrix")) triuChk <- function(x, k) { ans <- triu(x, k) ij <- non0.ij(ans) stopifnot(identical(dim(x), dim(ans)), (ij %*% c(-1,1)) >= k) ans } trilChk <- function(x, k) { ans <- tril(x, k) ij <- non0.ij(ans) stopifnot(identical(dim(x), dim(ans)), (ij %*% c(-1,1)) <= k) ans } Matrix/inst/include/0000755000175100001440000000000014576343415014150 5ustar hornikusersMatrix/inst/include/Matrix.h0000644000175100001440000000030314513651320015545 0ustar hornikusers/* For backwards compatibility only. Packages should start using */ /* LinkingTo: Matrix (>= 1.6-2) and #include . */ #include #include "Matrix/Matrix.h" Matrix/inst/include/cholmod.h0000644000175100001440000000024614511307715015740 0ustar hornikusers/* For backwards compatibility only. Packages should start using */ /* LinkingTo: Matrix (>= 1.6-2) and #include . */ #include "Matrix/cholmod.h" Matrix/inst/include/Matrix/0000755000175100001440000000000014577245211015410 5ustar hornikusersMatrix/inst/include/Matrix/Matrix.h0000644000175100001440000000046314515651531017026 0ustar hornikusers#ifndef R_MATRIX_MATRIX_H #define R_MATRIX_MATRIX_H #include "version.h" #include "cholmod.h" #ifndef R_MATRIX_NO_CHOLMOD_UTILS # include "cholmod-utils.h" #endif #ifndef R_MATRIX_NO_ALLOCA # include "alloca.h" #endif #ifndef R_MATRIX_NO_REMAP # include "remap.h" #endif #endif /* R_MATRIX_MATRIX_H */ Matrix/inst/include/Matrix/stubs.c0000644000175100001440000004346514575137654016741 0ustar hornikusers#include #include #include #include #ifndef R_MATRIX_INLINE # define R_MATRIX_INLINE #endif /* ==== cholmod.h =================================================== */ #include "cholmod.h" #ifdef __cplusplus extern "C" { #endif R_MATRIX_INLINE CHM_SP attribute_hidden R_MATRIX_CHOLMOD(aat)(CHM_SP A, int *fset, size_t fsize, int mode, CHM_CM Common) { static CHM_SP (*fn)(CHM_SP, int *, size_t, int, CHM_CM) = NULL; if (!fn) fn = (CHM_SP (*)(CHM_SP, int *, size_t, int, CHM_CM)) R_GetCCallable("Matrix", "cholmod_aat"); return fn(A, fset, fsize, mode, Common); } R_MATRIX_INLINE CHM_SP attribute_hidden R_MATRIX_CHOLMOD(add)(CHM_SP A, CHM_SP B, double alpha[2], double beta[2], int values, int sorted, CHM_CM Common) { static CHM_SP (*fn)(CHM_SP, CHM_SP, double[2], double[2], int, int, CHM_CM) = NULL; if (!fn) fn = (CHM_SP (*)(CHM_SP, CHM_SP, double[2], double[2], int, int, CHM_CM)) R_GetCCallable("Matrix", "cholmod_add"); return fn(A, B, alpha, beta, values, sorted, Common); } R_MATRIX_INLINE CHM_DN attribute_hidden R_MATRIX_CHOLMOD(allocate_dense)(size_t nrow, size_t ncol, size_t d, int xtype, CHM_CM Common) { static CHM_DN (*fn)(size_t, size_t, size_t, int, CHM_CM) = NULL; if (!fn) fn = (CHM_DN (*)(size_t, size_t, size_t, int, CHM_CM)) R_GetCCallable("Matrix", "cholmod_allocate_dense"); return fn(nrow, ncol, d, xtype, Common); } R_MATRIX_INLINE CHM_SP attribute_hidden R_MATRIX_CHOLMOD(allocate_sparse)(size_t nrow, size_t ncol, size_t nzmax, int sorted, int packed, int stype, int xtype, CHM_CM Common) { static CHM_SP (*fn)(size_t, size_t, size_t, int, int, int, int, CHM_CM) = NULL; if (!fn) fn = (CHM_SP (*)(size_t, size_t, size_t, int, int, int, int, CHM_CM)) R_GetCCallable("Matrix", "cholmod_allocate_sparse"); return fn(nrow, ncol, nzmax, sorted, packed, stype, xtype, Common); } R_MATRIX_INLINE CHM_TR attribute_hidden R_MATRIX_CHOLMOD(allocate_triplet)(size_t nrow, size_t ncol, size_t nzmax, int stype, int xtype, CHM_CM Common) { static CHM_TR (*fn)(size_t, size_t, size_t, int, int, CHM_CM) = NULL; if (!fn) fn = (CHM_TR (*)(size_t, size_t, size_t, int, int, CHM_CM)) R_GetCCallable("Matrix", "cholmod_allocate_triplet"); return fn(nrow, ncol, nzmax, stype, xtype, Common); } R_MATRIX_INLINE CHM_FR attribute_hidden R_MATRIX_CHOLMOD(analyze)(CHM_SP A, CHM_CM Common) { static CHM_FR (*fn)(CHM_SP, CHM_CM) = NULL; if (!fn) fn = (CHM_FR (*)(CHM_SP,CHM_CM)) R_GetCCallable("Matrix", "cholmod_analyze"); return fn(A, Common); } R_MATRIX_INLINE CHM_FR attribute_hidden R_MATRIX_CHOLMOD(analyze_p)(CHM_SP A, int *Perm, int *fset, size_t fsize, CHM_CM Common) { static CHM_FR (*fn)(CHM_SP, int *, int *, size_t, CHM_CM) = NULL; if (!fn) fn = (CHM_FR (*)(CHM_SP, int *, int *, size_t, CHM_CM)) R_GetCCallable("Matrix", "cholmod_analyze_p"); return fn(A, Perm, fset, fsize, Common); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(band_inplace)(int k1, int k2, int mode, CHM_SP A, CHM_CM Common) { static int (*fn)(int, int, int, CHM_SP, CHM_CM) = NULL; if (!fn) fn = (int (*)(int, int, int, CHM_SP, CHM_CM)) R_GetCCallable("Matrix", "cholmod_band_inplace"); return fn(k1, k2, mode, A, Common); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(change_factor)(int to_xtype, int to_ll, int to_super, int to_packed, int to_monotonic, CHM_FR L, CHM_CM Common) { static int (*fn)(int, int, int, int, int, CHM_FR, CHM_CM) = NULL; if (!fn) fn = (int (*)(int, int, int, int, int, CHM_FR, CHM_CM)) R_GetCCallable("Matrix", "cholmod_change_factor"); return fn(to_xtype, to_ll, to_super, to_packed, to_monotonic, L, Common); } R_MATRIX_INLINE CHM_SP attribute_hidden R_MATRIX_CHOLMOD(copy)(CHM_SP A, int stype, int mode, CHM_CM Common) { static CHM_SP (*fn)(CHM_SP, int, int, CHM_CM) = NULL; if (!fn) fn = (CHM_SP (*)(CHM_SP, int, int, CHM_CM)) R_GetCCallable("Matrix", "cholmod_copy"); return fn(A, stype, mode, Common); } R_MATRIX_INLINE CHM_DN attribute_hidden R_MATRIX_CHOLMOD(copy_dense)(CHM_DN A, CHM_CM Common) { static CHM_DN (*fn)(CHM_DN, CHM_CM) = NULL; if (!fn) fn = (CHM_DN (*)(CHM_DN, CHM_CM)) R_GetCCallable("Matrix", "cholmod_copy_dense"); return fn(A, Common); } R_MATRIX_INLINE CHM_FR attribute_hidden R_MATRIX_CHOLMOD(copy_factor)(CHM_FR L, CHM_CM Common) { static CHM_FR (*fn)(CHM_FR, CHM_CM) = NULL; if (!fn) fn = (CHM_FR (*)(CHM_FR, CHM_CM)) R_GetCCallable("Matrix", "cholmod_copy_factor"); return fn(L, Common); } R_MATRIX_INLINE CHM_SP attribute_hidden R_MATRIX_CHOLMOD(copy_sparse)(CHM_SP A, CHM_CM Common) { static CHM_SP (*fn)(CHM_SP, CHM_CM) = NULL; if (!fn) fn = (CHM_SP (*)(CHM_SP, CHM_CM)) R_GetCCallable("Matrix", "cholmod_copy_sparse"); return fn(A, Common); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(defaults)(CHM_CM Common) { static int (*fn)(CHM_CM) = NULL; if (!fn) fn = (int (*)(CHM_CM)) R_GetCCallable("Matrix", "cholmod_defaults"); return fn(Common); } R_MATRIX_INLINE CHM_SP attribute_hidden R_MATRIX_CHOLMOD(dense_to_sparse)(CHM_DN X, int values, CHM_CM Common) { static CHM_SP (*fn)(CHM_DN, int, CHM_CM) = NULL; if (!fn) fn = (CHM_SP (*)(CHM_DN, int, CHM_CM)) R_GetCCallable("Matrix", "cholmod_dense_to_sparse"); return fn(X, values, Common); } R_MATRIX_INLINE CHM_SP attribute_hidden R_MATRIX_CHOLMOD(factor_to_sparse)(CHM_FR L, CHM_CM Common) { static CHM_SP (*fn)(CHM_FR, CHM_CM) = NULL; if (!fn) fn = (CHM_SP (*)(CHM_FR, CHM_CM)) R_GetCCallable("Matrix", "cholmod_factor_to_sparse"); return fn(L, Common); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(factorize)(CHM_SP A, CHM_FR L, CHM_CM Common) { static int (*fn)(CHM_SP, CHM_FR, CHM_CM) = NULL; if (!fn) fn = (int (*)(CHM_SP, CHM_FR, CHM_CM)) R_GetCCallable("Matrix", "cholmod_factorize"); return fn(A, L, Common); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(factorize_p)(CHM_SP A, double beta[2], int *fset, size_t fsize, CHM_FR L, CHM_CM Common) { static int (*fn)(CHM_SP, double[2], int *, size_t, CHM_FR, CHM_CM) = NULL; if (!fn) fn = (int (*)(CHM_SP, double[2], int *, size_t, CHM_FR, CHM_CM)) R_GetCCallable("Matrix", "cholmod_factorize_p"); return fn(A, beta, fset, fsize, L, Common); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(finish)(CHM_CM Common) { static int (*fn)(CHM_CM) = NULL; if (!fn) fn = (int (*)(CHM_CM)) R_GetCCallable("Matrix", "cholmod_finish"); return fn(Common); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(free_dense)(CHM_DN *A, CHM_CM Common) { static int (*fn)(CHM_DN *, CHM_CM) = NULL; if (!fn) fn = (int (*)(CHM_DN *,CHM_CM)) R_GetCCallable("Matrix", "cholmod_free_dense"); return fn(A, Common); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(free_factor)(CHM_FR *L, CHM_CM Common) { static int (*fn)(CHM_FR *,CHM_CM) = NULL; if (!fn) fn = (int (*)(CHM_FR *, CHM_CM)) R_GetCCallable("Matrix", "cholmod_free_factor"); return fn(L, Common); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(free_sparse)(CHM_SP *A, CHM_CM Common) { static int (*fn)(CHM_SP *, CHM_CM) = NULL; if (!fn) fn = (int (*)(CHM_SP *, CHM_CM)) R_GetCCallable("Matrix", "cholmod_free_sparse"); return fn(A, Common); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(free_triplet)(CHM_TR *T, CHM_CM Common) { static int (*fn)(CHM_TR *, CHM_CM) = NULL; if (!fn) fn = (int (*)(CHM_TR *,CHM_CM)) R_GetCCallable("Matrix", "cholmod_free_triplet"); return fn(T, Common); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(nnz)(CHM_SP A, CHM_CM Common) { static int (*fn)(CHM_SP, CHM_CM) = NULL; if (!fn) fn = (int (*)(CHM_SP, CHM_CM)) R_GetCCallable("Matrix", "cholmod_nnz"); return fn(A, Common); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(scale)(CHM_DN S, int scale, CHM_SP A, CHM_CM Common) { static int (*fn)(CHM_DN, int, CHM_SP, CHM_CM) = NULL; if (!fn) fn = (int (*)(CHM_DN, int, CHM_SP, CHM_CM)) R_GetCCallable("Matrix", "cholmod_scale"); return fn(S, scale, A, Common); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(sdmult)(CHM_SP A, int transpose, double alpha[2], double beta[2], CHM_DN X, CHM_DN Y, CHM_CM Common) { static int (*fn)(CHM_SP, int, double[2], double[2], CHM_DN, CHM_DN, CHM_CM) = NULL; if (!fn) fn = (int (*)(CHM_SP, int, double[2], double[2], CHM_DN, CHM_DN, CHM_CM)) R_GetCCallable("Matrix", "cholmod_sdmult"); return fn(A, transpose, alpha, beta, X, Y, Common); } R_MATRIX_INLINE CHM_DN attribute_hidden R_MATRIX_CHOLMOD(solve)(int sys, CHM_FR L, CHM_DN B, CHM_CM Common) { static CHM_DN (*fn)(int, CHM_FR, CHM_DN, CHM_CM) = NULL; if (!fn) fn = (CHM_DN (*)(int, CHM_FR, CHM_DN, CHM_CM)) R_GetCCallable("Matrix", "cholmod_solve"); return fn(sys, L, B, Common); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(solve2)(int sys, CHM_FR L, CHM_DN B, CHM_DN *X_Handle, CHM_DN *Y_Handle, CHM_DN *E_Handle, CHM_CM Common) { static int (*fn)(int, CHM_FR, CHM_DN, CHM_SP, CHM_DN *, CHM_SP *, CHM_DN *, CHM_DN *, CHM_CM) = NULL; if (!fn) fn = (int (*)(int, CHM_FR, CHM_DN, CHM_SP, CHM_DN *, CHM_SP *, CHM_DN *, CHM_DN *, CHM_CM)) R_GetCCallable("Matrix", "cholmod_solve2"); return fn(sys, L, B, NULL, X_Handle, NULL, Y_Handle, E_Handle, Common); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(sort)(CHM_SP A, CHM_CM Common) { static int (*fn)(CHM_SP, CHM_CM) = NULL; if (!fn) fn = (int (*)(CHM_SP, CHM_CM)) R_GetCCallable("Matrix", "cholmod_sort"); return fn(A, Common); } R_MATRIX_INLINE CHM_DN attribute_hidden R_MATRIX_CHOLMOD(sparse_to_dense)(CHM_SP A, CHM_CM Common) { static CHM_DN (*fn)(CHM_SP, CHM_CM) = NULL; if (!fn) fn = (CHM_DN (*)(CHM_SP, CHM_CM)) R_GetCCallable("Matrix", "cholmod_sparse_to_dense"); return fn(A, Common); } R_MATRIX_INLINE CHM_TR attribute_hidden R_MATRIX_CHOLMOD(sparse_to_triplet)(CHM_SP A, CHM_CM Common) { static CHM_TR (*fn)(CHM_SP, CHM_CM) = NULL; if (!fn) fn = (CHM_TR (*)(CHM_SP, CHM_CM)) R_GetCCallable("Matrix", "cholmod_sparse_to_triplet"); return fn(A, Common); } R_MATRIX_INLINE CHM_SP attribute_hidden R_MATRIX_CHOLMOD(speye)(size_t nrow, size_t ncol, int xtype, CHM_CM Common) { static CHM_SP (*fn)(size_t, size_t, int, CHM_CM) = NULL; if (!fn) fn = (CHM_SP (*)(size_t, size_t, int, CHM_CM)) R_GetCCallable("Matrix", "cholmod_speye"); return fn(nrow, ncol, xtype, Common); } R_MATRIX_INLINE CHM_SP attribute_hidden R_MATRIX_CHOLMOD(spsolve)(int sys, CHM_FR L, CHM_SP B, CHM_CM Common) { static CHM_SP (*fn)(int, CHM_FR, CHM_SP, CHM_CM) = NULL; if (!fn) fn = (CHM_SP (*)(int,CHM_FR, CHM_SP, CHM_CM)) R_GetCCallable("Matrix", "cholmod_spsolve"); return fn(sys, L, B, Common); } R_MATRIX_INLINE CHM_SP attribute_hidden R_MATRIX_CHOLMOD(ssmult)(CHM_SP A, CHM_SP B, int stype, int values, int sorted, CHM_CM Common) { static CHM_SP (*fn)(CHM_SP, CHM_SP, int, int, int, CHM_CM) = NULL; if (!fn) fn = (CHM_SP (*)(CHM_SP, CHM_SP, int, int, int, CHM_CM)) R_GetCCallable("Matrix", "cholmod_ssmult"); return fn(A, B, stype, values, sorted, Common); } R_MATRIX_INLINE CHM_SP attribute_hidden R_MATRIX_CHOLMOD(submatrix)(CHM_SP A, int *rset, int rsize, int *cset, int csize, int values, int sorted, CHM_CM Common) { static CHM_SP (*fn)(CHM_SP, int *, int, int *, int, int, int, CHM_CM) = NULL; if (!fn) fn = (CHM_SP (*)(CHM_SP, int *, int, int *, int, int, int, CHM_CM)) R_GetCCallable("Matrix", "cholmod_submatrix"); return fn(A, rset, rsize, cset, csize, values, sorted, Common); } R_MATRIX_INLINE CHM_SP attribute_hidden R_MATRIX_CHOLMOD(transpose)(CHM_SP A, int values, CHM_CM Common) { static CHM_SP (*fn)(CHM_SP, int, CHM_CM) = NULL; if (!fn) fn = (CHM_SP (*)(CHM_SP, int, CHM_CM)) R_GetCCallable("Matrix", "cholmod_transpose"); return fn(A, values, Common); } R_MATRIX_INLINE CHM_SP attribute_hidden R_MATRIX_CHOLMOD(triplet_to_sparse)(CHM_TR T, int nzmax, CHM_CM Common) { static CHM_SP (*fn)(CHM_TR, int, CHM_CM) = NULL; if (!fn) fn = (CHM_SP (*)(CHM_TR, int, CHM_CM)) R_GetCCallable("Matrix", "cholmod_triplet_to_sparse"); return fn(T, nzmax, Common); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(updown)(int update, CHM_SP C, CHM_FR L, CHM_CM Common) { static int (*fn)(int, CHM_SP, CHM_FR, CHM_CM) = NULL; if (!fn) fn = (int (*)(int, CHM_SP, CHM_FR, CHM_CM)) R_GetCCallable("Matrix", "cholmod_updown"); return fn(update, C, L, Common); } R_MATRIX_INLINE CHM_SP attribute_hidden R_MATRIX_CHOLMOD(vertcat)(CHM_SP A, CHM_SP B, int values, CHM_CM Common) { static CHM_SP (*fn)(CHM_SP, CHM_SP, int, CHM_CM) = NULL; if (!fn) fn = (CHM_SP (*)(CHM_SP, CHM_SP, int, CHM_CM)) R_GetCCallable("Matrix", "cholmod_vertcat"); return fn(A, B, values, Common); } /* ---- cholmod_start ----------------------------------------------- */ /* NB: keep synchronized with analogues in ../../src/cholmod-common.c */ R_MATRIX_INLINE void attribute_hidden R_MATRIX_CHOLMOD(error_handler)(int status, const char *file, int line, const char *message) { /* NB: Matrix itself uses cholmod_common_env(ini|set|get) to preserve settings through error calls. Consider defining *your* own error handler and restoring the instance of cholmod_common that *you* use. */ if (status < 0) Rf_error("CHOLMOD error '%s' at file '%s', line %d", message, file, line); else Rf_warning("CHOLMOD warning '%s' at file '%s', line %d", message, file, line); } R_MATRIX_INLINE int attribute_hidden R_MATRIX_CHOLMOD(start)(CHM_CM Common) { static int (*fn)(CHM_CM) = NULL; if (!fn) fn = (int (*)(CHM_CM)) R_GetCCallable("Matrix", "cholmod_start"); int ans = fn(Common); Common->error_handler = R_MATRIX_CHOLMOD(error_handler); return ans; } #ifdef __cplusplus } #endif /* ==== cholmod-utils.h ============================================= */ #ifndef R_MATRIX_NO_CHOLMOD_UTILS #include "cholmod-utils.h" #ifdef __cplusplus extern "C" { #endif R_MATRIX_INLINE CHM_FR attribute_hidden M_sexp_as_cholmod_factor(CHM_FR L, SEXP from) { static CHM_FR (*fn)(CHM_FR, SEXP) = NULL; if (!fn) fn = (CHM_FR (*)(CHM_FR, SEXP)) R_GetCCallable("Matrix", "sexp_as_cholmod_factor"); return fn(L, from); } R_MATRIX_INLINE CHM_SP attribute_hidden M_sexp_as_cholmod_sparse(CHM_SP A, SEXP from, Rboolean checkUnit, Rboolean sortInPlace) { static CHM_SP (*fn)(CHM_SP, SEXP, Rboolean, Rboolean) = NULL; if (!fn) fn = (CHM_SP (*)(CHM_SP, SEXP, Rboolean, Rboolean)) R_GetCCallable("Matrix", "sexp_as_cholmod_sparse"); return fn(A, from, checkUnit, sortInPlace); } R_MATRIX_INLINE CHM_TR attribute_hidden M_sexp_as_cholmod_triplet(CHM_TR A, SEXP from, Rboolean checkUnit) { static CHM_TR (*fn)(CHM_TR, SEXP, Rboolean) = NULL; if (!fn) fn = (CHM_TR (*)(CHM_TR, SEXP, Rboolean)) R_GetCCallable("Matrix", "sexp_as_cholmod_triplet"); return fn(A, from, checkUnit); } R_MATRIX_INLINE CHM_DN attribute_hidden M_sexp_as_cholmod_dense(CHM_DN A, SEXP from) { static CHM_DN (*fn)(CHM_DN, SEXP) = NULL; if (!fn) fn = (CHM_DN (*)(CHM_DN, SEXP)) R_GetCCallable("Matrix", "sexp_as_cholmod_dense"); return fn(A, from); } R_MATRIX_INLINE CHM_DN attribute_hidden M_numeric_as_cholmod_dense(CHM_DN A, double *data, int nrow, int ncol) { static CHM_DN (*fn)(CHM_DN, double *, int, int) = NULL; if (!fn) fn = (CHM_DN (*)(CHM_DN, double *, int, int)) R_GetCCallable("Matrix", "numeric_as_cholmod_dense"); return fn(A, data, nrow, ncol); } R_MATRIX_INLINE SEXP attribute_hidden M_cholmod_factor_as_sexp(CHM_FR L, int doFree) { static SEXP (*fn)(CHM_FR, int) = NULL; if (!fn) fn = (SEXP (*)(CHM_FR, int)) R_GetCCallable("Matrix", "cholmod_factor_as_sexp"); return fn(L, doFree); } R_MATRIX_INLINE SEXP attribute_hidden M_cholmod_sparse_as_sexp(CHM_SP A, int doFree, int ttype, int doLogic, const char *diagString, SEXP dimnames) { static SEXP (*fn)(CHM_SP, int, int, int, const char *, SEXP) = NULL; if (!fn) fn = (SEXP (*)(CHM_SP, int, int, int, const char *, SEXP)) R_GetCCallable("Matrix", "cholmod_sparse_as_sexp"); return fn(A, doFree, ttype, doLogic, diagString, dimnames); } R_MATRIX_INLINE SEXP attribute_hidden M_cholmod_triplet_as_sexp(CHM_TR A, int doFree, int ttype, int doLogic, const char *diagString, SEXP dimnames) { static SEXP (*fn)(CHM_TR, int, int, int, const char *, SEXP) = NULL; if (!fn) fn = (SEXP (*)(CHM_TR, int, int, int, const char *, SEXP)) R_GetCCallable("Matrix", "cholmod_triplet_as_sexp"); return fn(A, doFree, ttype, doLogic, diagString, dimnames); } R_MATRIX_INLINE SEXP attribute_hidden M_cholmod_dense_as_sexp(CHM_DN A, int doFree) { static SEXP (*fn)(CHM_DN, int) = NULL; if (!fn) fn = (SEXP (*)(CHM_DN, int)) R_GetCCallable("Matrix", "cholmod_dense_as_sexp"); return fn(A, doFree); } R_MATRIX_INLINE double attribute_hidden M_cholmod_factor_ldetA(CHM_FR L) { static double (*fn)(CHM_FR) = NULL; if (!fn) fn = (double (*)(CHM_FR)) R_GetCCallable("Matrix", "cholmod_factor_ldetA"); return fn(L); } R_MATRIX_INLINE CHM_FR attribute_hidden M_cholmod_factor_update(CHM_FR L, CHM_SP A, double beta) { static CHM_FR (*fn)(CHM_FR, CHM_SP, double) = NULL; if (!fn) fn = (CHM_FR (*)(CHM_FR, CHM_SP, double)) R_GetCCallable("Matrix", "cholmod_factor_update"); return fn(L, A, beta); } #ifdef __cplusplus } #endif #endif /* !defined(R_MATRIX_NO_CHOLMOD_UTILS) */ Matrix/inst/include/Matrix/cholmod.h0000644000175100001440000053333114561103552017210 0ustar hornikusers//------------------------------------------------------------------------------ // CHOLMOD/Include/cholmod.h: include file for CHOLMOD //------------------------------------------------------------------------------ // CHOLMOD/Include/cholmod.h. Copyright (C) 2005-2023, Timothy A. Davis. // All Rights Reserved. // Each Module of CHOLMOD has its own license, and a shared cholmod.h file. // CHOLMOD/Check: SPDX-License-Identifier: LGPL-2.1+ // CHOLMOD/Cholesky: SPDX-License-Identifier: LGPL-2.1+ // CHOLMOD/Utility: SPDX-License-Identifier: LGPL-2.1+ // CHOLMOD/Partition: SPDX-License-Identifier: LGPL-2.1+ // CHOLMOD/Demo: SPDX-License-Identifier: GPL-2.0+ // CHOLMOD/GPU: SPDX-License-Identifier: GPL-2.0+ // CHOLMOD/MATLAB: SPDX-License-Identifier: GPL-2.0+ // CHOLMOD/MatrixOps: SPDX-License-Identifier: GPL-2.0+ // CHOLMOD/Modify: SPDX-License-Identifier: GPL-2.0+ // CHOLMOD/Supernodal: SPDX-License-Identifier: GPL-2.0+ // CHOLMOD/Tcov: SPDX-License-Identifier: GPL-2.0+ //------------------------------------------------------------------------------ // CHOLMOD consists of a set of Modules, each with their own Copyright and // license: either LGPL-2.1+ or GPL-2.0+. This cholmod.h file includes // definitions of the CHOLMOD API for all Modules, and this cholmod.h file // itself is provided to you with a permissive license (Apache-2.0). You are // permitted to provide the hooks for an optional interface to CHOLMOD in a // non-GPL/non-LGPL code, without requiring you to agree to the GPL/LGPL // license of the Modules, as long as you don't use the *.c files in the // relevant Modules. The Modules themselves can only be functional if their // GPL or LGPL licenses are used, or if you obtain a different license from the // respective copyright holders. // // For the files in CHOLMOD/Include: // CHOLMOD/Include/cholmod.h SPDX-License-Identifier: Apache-2.0 // CHOLMOD/Include/cholmod_internal.h SPDX-License-Identifier: Apache-2.0 // CHOLMOD/Include/cholmod_template.h SPDX-License-Identifier: Apache-2.0 // CHOLMOD/Include/cholmod_types.h SPDX-License-Identifier: Apache-2.0 // // The Modify Module is co-authored by William W. Hager. // // Acknowledgements: this work was supported in part by the National Science // Foundation (NFS CCR-0203270 and DMS-9803599), and a grant from Sandia // National Laboratories (Dept. of Energy) which supported the development of // CHOLMOD's Partition Module. // ----------------------------------------------------------------------------- #ifndef R_MATRIX_CHOLMOD_H #define R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // CHOLMOD conventions //------------------------------------------------------------------------------ // Each routine in CHOLMOD follows the following conventions: // // Naming convention: // ------------------ // // All routine names, data types, and CHOLMOD library files use the cholmod_ // prefix. All macros and other #define's use the CHOLMOD prefix. // // Return value: // ------------- // // Most CHOLMOD routines return an int (TRUE (1) if successful, or FALSE // (0) otherwise. An int32_t, int64_t, double, or float return value // is >= 0 if successful, or -1 otherwise. A size_t return value // is > 0 if successful, or 0 otherwise. // // If a routine returns a pointer, it is a pointer to a newly allocated // object or NULL if a failure occured, with one exception. cholmod_free // always returns NULL. // // "Common" parameter: // ------------------ // // The last parameter in all CHOLMOD routines is a pointer to the CHOLMOD // "Common" object. This contains control parameters, statistics, and // workspace used between calls to CHOLMOD. It is always an input/output // parameter. // // Input, Output, and Input/Output parameters: // ------------------------------------------- // // Input parameters are listed first. They are not modified by CHOLMOD. // // Input/output are listed next. They must be defined on input, and // are modified on output. // // Output parameters are listed next. If they are pointers, they must // point to allocated space on input, but their contents are not defined // on input. // // Workspace parameters appear next. They are used in only two routines // in the Supernodal module. // // The cholmod_common *Common parameter always appears as the last // parameter. It is always an input/output parameter. //------------------------------------------------------------------------------ // CHOLMOD matrix formats //------------------------------------------------------------------------------ // A CHOLMOD sparse, dense, or triplet matrix A, or a sparse factorization L // can hold numeric values of 8 different types, according to its A->xtype and // A->dtype parameters (or L->xtype and L->dtype for a sparse factor object). // These values are held in the A->x array, and also A->z for "zomplex" // matrices. // // A->xtype: the matrix is real, complex, "zomplex", or pattern-only. // // (0): CHOLMOD_PATTERN: A->x and A->z are NULL. The matrix has no // numerical values. Only the pattern is stored. // // (1): CHOLMOD_REAL: The matrix is real, and the values are held in // A->x, whose size (in terms of double or float // values) is given by A->nzmax. The kth value in // the matrix is held in A->x [k]. // // (2): CHOLMOD_COMPLEX: The matrix is complex, with interleaved real and // imaginary parts. The kth value in the matrix // is held in A->x [2*k] and A->x [2*k+1], where // A->x can hold up to 2*A->nzmax values. // // (3): CHOLMOD_ZOMPLEX: The matrix is complex, with separate array for // the real and imaginary parts. The kth value in // the matrix is held in A->x [k] and A->z [k], // where A->x and A->z can hold up to A->nzmax // values each. // A->xtype values: #define CHOLMOD_PATTERN 0 #define CHOLMOD_REAL 1 #define CHOLMOD_COMPLEX 2 #define CHOLMOD_ZOMPLEX 3 // A->dtype: this parameter determines the type of values in A->x (and A->z // if zomplex). // // (0) CHOLMOD_DOUBLE: A->x (and A->z for zomplex matrices) is double. // If A is real, A->x has a size of A->nzmax * // sizeof (double). If A is complex, A->x has // size A->nzmax * 2 * sizeof (double). If // zomplex, both A->x and A->z have size A->nzmax // * sizeof (double). // // (4) CHOLMOD_SINGLE: A->x (and A->z for zomplex matrices) is float. // If A is real, A->x has a size of A->nzmax * // sizeof (float). If A is complex, A->x has size // A->nzmax * 2 * sizeof (float). If zomplex, // both A->x and A->z have size A->nzmax * sizeof // (float). This feature is new to CHOLMOD v5. // // A->dtype values: #define CHOLMOD_DOUBLE 0 #define CHOLMOD_SINGLE 4 // Unless stated otherwise, the xtype and dtypes of all inputs to a method must // be the same. // // Many methods accept an xdtype parameter, which is simply xtype + dtype, // combining the two parameters into a single number handling all 8 cases: // // (0) CHOLMOD_DOUBLE + CHOLMOD_PATTERN a pattern-only matrix // (1) CHOLMOD_DOUBLE + CHOLMOD_REAL a double real matrix // (2) CHOLMOD_DOUBLE + CHOLMOD_COMPLEX a double complex matrix // (3) CHOLMOD_DOUBLE + CHOLMOD_ZOMPLEX a double zomplex matrix // (4) CHOLMOD_SINGLE + CHOLMOD_PATTERN a pattern-only matrix // (5) CHOLMOD_SINGLE + CHOLMOD_REAL a float real matrix // (6) CHOLMOD_SINGLE + CHOLMOD_COMPLEX a float complex matrix // (7) CHOLMOD_SINGLE + CHOLMOD_ZOMPLEX a float zomplex matrix // // This approach was selected for backward compatibility with CHOLMOD v4 and // earlier, where only the first four values were supported, and where the // parameter was called "xtype" instead of "xdtype". Several function names // reflect the older parameter name (cholmod_*_xtype), but they have not been // renamed "_xdtype", for backward compatibility. // // A CHOLMOD sparse or triplet matrix A can held in three symmetry formats // according to its A->stype parameter. Dense matrices do not have this // parameter and are always treated as unsymmetric. A sparse factor object L // is always held in lower triangular form, with no entries ever held in the // strictly upper triangular part. // // 0: the matrix is unsymmetric with both lower and upper parts stored. // // <0: the matrix is symmetric, with just the lower triangular part and // diagonal stored. Any entries in the upper part are ignored. // // >0: the matrix is symmetric, with just the upper triangular part stored // and diagonal. Any entries in the upper part are ignored. // // If a sparse or triplet matrix A is complex or zomplex, most methods treat // the matrix as Hermitian, where A(i,j) is the complex conjugate of A(j,i), // when i is not equal to j. Some methods can also interpret the matrix as // complex symmetric, where A(i,j) == A(j,i) when i != j. This is not // determined by the matrix itself, but by a "mode" parameter of the function. // This mode parameter also determines if the values of any matrix are to be // ignored entirely, in which case only the pattern is operated on. Any output // matrix will have an xtype of CHOLMOD_PATTERN. // // The valid mode values are given below, except that many methods do not // handle the negative cases. Values below the range accepted by the method // are treated as its lowest accepted value, and values above the range // accepted by the method are treated as its highest accepted value. // // mode = 2: the numerical values of a real, complex, or zomplex matrix are // handled. If the matrix is complex or zomplex, an entry A(i,j) // that not stored (or in the ignored part) is treated as the // complex conjugate of A (j,i). Use this mode to treat a // complex or zomplex matrix as Hermitian. // // mode = 1: the numerical values of a real, complex, or zomplex matrix are // handled. If the matrix is complex or zomplex, an entry A(i,j) // that not stored (or in the ignored part) is treated as equal A // (j,i). Use this mode to treat a complex or zomplex matrix as // complex symmetric. // // mode = 0: the numerical values are ignored. Any output matrix will have // an xtype of CHOLMOD_PATTERN. This mode allows inputs to have // different dtypes. // // mode = -1: the same as mode = 0, except that the diagonal entries are // ignored, and do not appear in any output matrix. // // mode = -2: the same as mode = -1, except that the output matrix is given an // additional slack space so that it can hold about 50% more // entries. This mode is documented here but it is primarily // meant for internal use, for CHOLMOD's interface to the AMD, // CAMD, COLAMD, and CCOLAMD ordering methods. // // The integer arrays in all objects are either int32 or int64, as determined // by A->type. This integer type must be identical for all inputs, and must // also match both the function name (cholmod_method for int32, or // cholmod_l_method for int64) and the Common->itype as defined when CHOLMOD // was initialized (via cholmod_start for int32, or cholmod_l_start for int64). // itype values: #define CHOLMOD_INT 0 /* int32, for cholmod_* methods (no _l_) */ #define CHOLMOD_LONG 2 /* int64, for cholmod_l_* methods */ //------------------------------------------------------------------------------ // version control //------------------------------------------------------------------------------ #define CHOLMOD_DATE "Jan 20, 2024" #define CHOLMOD_MAIN_VERSION 5 #define CHOLMOD_SUB_VERSION 2 #define CHOLMOD_SUBSUB_VERSION 0 #define CHOLMOD_VER_CODE(main,sub) SUITESPARSE_VER_CODE(main,sub) #define CHOLMOD_VERSION CHOLMOD_VER_CODE(5,2) #define CHOLMOD_HAS_VERSION_FUNCTION #ifdef __cplusplus extern "C" { #endif #ifndef R_MATRIX_CHOLMOD_H int cholmod_version // returns CHOLMOD_VERSION, defined above ( // if version is not NULL, then cholmod_version returns its contents as: // version [0] = CHOLMOD_MAIN_VERSION // version [1] = CHOLMOD_SUB_VERSION // version [2] = CHOLMOD_SUBSUB_VERSION int version [3] ) ; int cholmod_l_version (int version [3]) ; #endif /* !defined(R_MATRIX_CHOLMOD_H) */ #ifdef __cplusplus } #endif //------------------------------------------------------------------------------ // Large file support //------------------------------------------------------------------------------ // CHOLMOD assumes large file support. If problems occur, compile with // -DNLARGEFILE // Definitions required for large file I/O, which must come before any other // #includes. These are not used if -DNLARGEFILE is defined at compile time. // Large file support may not be portable across all platforms and compilers; // if you encounter an error here, compile your code with -DNLARGEFILE. In // particular, you must use -DNLARGEFILE for MATLAB 6.5 or earlier (which does // not have the io64.h include file). #ifndef R_MATRIX_CHOLMOD_H // skip all of this if NLARGEFILE is defined at the compiler command line #ifndef NLARGEFILE #if defined(MATLAB_MEX_FILE) || defined(MATHWORKS) // CHOLMOD compiled as a MATLAB mexFunction, or for use in MATLAB #include "io64.h" #else // CHOLMOD is being compiled in a stand-alone library #undef _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE #undef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 #endif #endif #endif /* !defined(R_MATRIX_CHOLMOD_H) */ //------------------------------------------------------------------------------ // SuiteSparse_config: definitions for all SuiteSparse packages //------------------------------------------------------------------------------ #ifndef R_MATRIX_CHOLMOD_H #include "SuiteSparse_config.h" #define CHOLMOD__VERSION SUITESPARSE__VERCODE(5,2,0) #if !defined (SUITESPARSE__VERSION) || \ (SUITESPARSE__VERSION < SUITESPARSE__VERCODE(7,6,0)) #error "CHOLMOD 5.2.0 requires SuiteSparse_config 7.6.0 or later" #endif #else #include #include #endif /* !defined(R_MATRIX_CHOLMOD_H) */ //------------------------------------------------------------------------------ // CHOLMOD configuration //------------------------------------------------------------------------------ // You do not have to edit any CHOLMOD files to compile and install CHOLMOD. // However, if you do not use all of CHOLMOD's modules, you need to compile // with the appropriate flag, or edit this file to add the appropriate #define. // // Compiler flags for CHOLMOD // // -DNCHECK do not include the Check module. // -DNCHOLESKY do not include the Cholesky module. // -DNPARTITION do not include the Partition module. // -DNCAMD do not include the interfaces to CAMD, // CCOLAMD, CSYMAND in Partition module. // -DNMATRIXOPS do not include the MatrixOps module. // -DNMODIFY do not include the Modify module. // -DNSUPERNODAL do not include the Supernodal module. // // -DNPRINT do not print anything // // The Utility Module is always included in the CHOLMOD library. // Use the compiler flag, or uncomment the definition(s), if you want to use // one or more non-default installation options: // #define NCHECK // #define NCHOLESKY // #define NCAMD // #define NPARTITION // #define NMATRIXOPS // #define NMODIFY // #define NSUPERNODAL // #define NPRINT // #define NGPL // The NGPL option disables the MatrixOps, Modify, and Supernodal modules. The // existence of this #define here, and its use in these 3 modules, does not // affect the license itself; see CHOLMOD/Doc/License.txt for your actual // license. #ifndef R_MATRIX_CHOLMOD_H #ifdef NGPL #undef NMATRIXOPS #define NMATRIXOPS #undef NMODIFY #define NMODIFY #undef NSUPERNODAL #define NSUPERNODAL #endif #endif /* !defined(R_MATRIX_CHOLMOD_H) */ //============================================================================== // CHOLMOD:Utility Module //============================================================================== // the CHOLMOD:Utility Module is always required #if 1 //------------------------------------------------------------------------------ // CUDA BLAS //------------------------------------------------------------------------------ // Define buffering parameters for GPU processing #ifndef SUITESPARSE_GPU_EXTERN_ON #ifdef CHOLMOD_HAS_CUDA #include #endif #endif #define CHOLMOD_DEVICE_SUPERNODE_BUFFERS 6 #define CHOLMOD_HOST_SUPERNODE_BUFFERS 8 #define CHOLMOD_DEVICE_STREAMS 2 //------------------------------------------------------------------------------ // CHOLMOD objects //------------------------------------------------------------------------------ // CHOLMOD object enums #define CHOLMOD_COMMON 0 /* parameters, statistics, and workspace */ #define CHOLMOD_SPARSE 1 /* a sparse matrix in CSC form (and variants) */ #define CHOLMOD_FACTOR 2 /* a sparse factorization */ #define CHOLMOD_DENSE 3 /* a dense matrix in column-oriented form */ #define CHOLMOD_TRIPLET 4 /* a sparse matrix in triplet form */ //------------------------------------------------------------------------------ // CHOLMOD Common object //------------------------------------------------------------------------------ #ifdef __cplusplus extern "C" { #endif typedef struct cholmod_common_struct { //-------------------------------------------------------------------------- // primary parameters for factorization and update/downdate //-------------------------------------------------------------------------- double dbound ; // Bounds the diagonal entries of D for LDL' // factorization and update/downdate/rowadd. Entries outside this // bound are replaced with dbound. Default: 0. dbound is used for // double precision factorization only. See sbound for single // precision factorization. double grow0 ; // default: 1.2 double grow1 ; // default: 1.2 size_t grow2 ; // default: 5 // Initial space for simplicial factorization is max(grow0,1) times the // required space. If space is exhausted, L is grown by max(grow0,1.2) // times the required space. grow1 and grow2 control how each column // of L can grow in an update/downdate; if space runs out, then // grow1*(required space) + grow2 is allocated. size_t maxrank ; // maximum rank for update/downdate. Valid values are // 2, 4, and 8. Default is 8. If a larger update/downdate is done, it // is done in steps of maxrank. double supernodal_switch ; // default: 40 int supernodal ; // default: CHOLMOD_AUTO. // Controls supernodal vs simplicial factorization. If // Common->supernodal is CHOLMOD_SIMPLICIAL, a simplicial factorization // is always done; if CHOLMOD_SUPERNODAL, a supernodal factorization is // always done. If CHOLMOD_AUTO, then a simplicial factorization is // down if flops/nnz(L) < Common->supernodal_switch. #define CHOLMOD_SIMPLICIAL 0 /* always use simplicial method */ #define CHOLMOD_AUTO 1 /* auto select simplicial vs supernodal */ #define CHOLMOD_SUPERNODAL 2 /* always use supernoda method */ int final_asis ; // if true, other final_* parameters are ignored, // except for final_pack and the factors are left as-is when done. // Default: true. int final_super ; // if true, leave factor in supernodal form. // if false, convert to simplicial. Default: true. int final_ll ; // if true, simplicial factors are converted to LL', // otherwise left as LDL. Default: false. int final_pack ; // if true, the factorize are allocated with exactly // the space required. Set this to false if you expect future // updates/downdates (giving a little extra space for future growth), // Default: true. int final_monotonic ; // if true, columns are sorted when done, by // ascending row index. Default: true. int final_resymbol ; // if true, a supernodal factorization converted // to simplicial is reanalyzed, to remove zeros added for relaxed // amalgamation. Default: false. double zrelax [3] ; size_t nrelax [3] ; // The zrelax and nrelax parameters control relaxed supernodal // amalgamation, If ns is the # of columns in two adjacent supernodes, // and z is the fraction of zeros in the two supernodes if merged, then // the two supernodes are merged if any of the 5 following condition // are true: // // no new zero entries added if the two supernodes are merged // (ns <= nrelax [0]) // (ns <= nrelax [1] && z < zrelax [0]) // (ns <= nrelax [2] && z < zrelax [1]) // (z < zrelax [2]) // // With the defaults, the rules become: // // no new zero entries added if the two supernodes are merged // (ns <= 4) // (ns <= 16 && z < 0.8) // (ns <= 48 && z < 0.1) // (z < 0.05) int prefer_zomplex ; // if true, and a complex system is solved, // X is returned as zomplex (with two arrays, one for the real part // and one for the imaginary part). If false, then X is returned as // a single array with interleaved real and imaginary parts. // Default: false. int prefer_upper ; // if true, then a preference is given for holding // a symmetric matrix by just its upper triangular form. This gives // the best performance by the CHOLMOD analysis and factorization // methods. Only used by cholmod_read. Default: true. int quick_return_if_not_posdef ; // if true, a supernodal factorization // returns immediately if it finds the matrix is not positive definite. // If false, the failed supernode is refactorized, up to but not // including the failed column (required by MATLAB). int prefer_binary ; // if true, cholmod_read_triplet converts a symmetric // pattern-only matrix to a real matrix with all values set to 1. // if false, diagonal entries A(k,k) are set to one plus the # of // entries in row/column k, and off-diagonals are set to -1. // Default: false. //-------------------------------------------------------------------------- // printing and error handling options //-------------------------------------------------------------------------- int print ; // print level. Default is 3. int precise ; // if true, print 16 digits, otherwise 5. Default: false. int try_catch ; // if true, ignore errors (CHOLMOD is assumed to be inside // a try/catch block. No error messages are printed and the // error_handler function is not called. Default: false. void (*error_handler) (int status, const char *file, int line, const char *message) ; // User error handling routine; default is NULL. // This function is called if an error occurs, with parameters: // status: the Common->status result. // file: filename where the error occurred. // line: line number where the error occurred. // message: a string that describes the error. //-------------------------------------------------------------------------- // ordering options //-------------------------------------------------------------------------- // CHOLMOD can try many ordering options and then pick the best result it // finds. The default is to use one or two orderings: the user's // permutation (if given), and AMD. // Common->nmethods is the number of methods to try. If the // Common->method array is left unmodified, the methods are: // (0) given (skipped if no user permutation) // (1) amd // (2) metis // (3) nesdis with defaults (CHOLMOD's nested dissection, based on METIS) // (4) natural // (5) nesdis: stop at subgraphs of 20000 nodes // (6) nesdis: stop at subgraphs of 4 nodes, do not use CAMD // (7) nesdis: no pruning on of dense rows/cols // (8) colamd // To use all 9 of the above methods, set Common->nmethods to 9. The // analysis will take a long time, but that might be worth it if the // ordering will be reused many many times. // Common->nmethods and Common->methods can be revised to use a different // set of orderings. For example, to use just a single method // (AMD with a weighted postordering): // // Common->nmethods = 1 ; // Common->method [0].ordering = CHOLMOD_AMD ; // Common->postorder = TRUE ; // // int nmethods ; // Number of methods to try, default is 0. // The value of 0 is a special case, and tells CHOLMOD to use the user // permutation (if not NULL) and then AMD. Next, if fl is lnz are the // flop counts and number of nonzeros in L as found by AMD, then the // this ordering is used if fl/lnz < 500 or lnz/anz < 5, where anz is // the number of entries in A. If this condition fails, METIS is tried // as well. // // Otherwise, if Common->nmethods > 0, then the methods defined by // Common->method [0 ... Common->nmethods-1] are used. int current ; // The current method being tried in the analysis. int selected ; // The selected method: Common->method [Common->selected] // The Common->method parameter is an array of structs that defines up // to 9 methods: struct cholmod_method_struct { //---------------------------------------------------------------------- // statistics from the ordering //---------------------------------------------------------------------- double lnz ; // number of nonzeros in L double fl ; // Cholesky flop count for this ordering (each // multiply and each add counted once (doesn't count complex // flops). //---------------------------------------------------------------------- // ordering parameters: //---------------------------------------------------------------------- double prune_dense ; // dense row/col control. Default: 10. // Rows/cols with more than max (prune_dense*sqrt(n),16) are // removed prior to orderingm and placed last. If negative, // only completely dense rows/cols are removed. Removing these // rows/cols with many entries can speed up the ordering, but // removing too many can reduce the ordering quality. // // For AMD, SYMAMD, and CSYMAMD, this is the only dense row/col // parameter. For COLAMD and CCOLAMD, this parameter controls // how dense columns are handled. double prune_dense2 ; // dense row control for COLAMD and CCOLAMD. // Default -1. When computing the Cholesky factorization of AA' // rows with more than max(prune_dense2*sqrt(n),16) entries // are removed prior to ordering. If negative, only completely // dense rows are removed. double nd_oksep ; // for CHOLMOD's nesdis method. Default 1. // A node separator with nsep nodes is discarded if // nsep >= nd_oksep*n. double other_1 [4] ; // unused, for future expansion size_t nd_small ; // for CHOLMOD's nesdis method. Default 200. // Subgraphs with fewer than nd_small nodes are not partitioned. double other_2 [4] ; // unused, for future expansion int aggressive ; // if true, AMD, COLAMD, SYMAMD, CCOLAMD, and // CSYMAMD perform aggresive absorption. Default: true int order_for_lu ; // Default: false. If the CHOLMOD analysis/ // ordering methods are used as an ordering method for an LU // factorization, then set this to true. For use in a Cholesky // factorization by CHOLMOD itself, never set this to true. int nd_compress ; // if true, then the graph and subgraphs are // compressed before partitioning them in CHOLMOD's nesdis // method. Default: true. int nd_camd ; // if 1, then CHOLMOD's nesdis is followed by // CAMD. If 2: followed by CSYMAMD. If nd_small is very small, // then use 0, which skips CAMD or CSYMAMD. Default: 1. int nd_components ; // CHOLMOD's nesdis can partition a graph and then // find that the subgraphs are unconnected. If true, each of these // components is partitioned separately. If false, the whole // subgraph is partitioned. Default: false. int ordering ; // ordering method to use: #define CHOLMOD_NATURAL 0 /* no preordering */ #define CHOLMOD_GIVEN 1 /* user-provided permutation */ #define CHOLMOD_AMD 2 /* AMD: approximate minimum degree */ #define CHOLMOD_METIS 3 /* METIS: mested dissection */ #define CHOLMOD_NESDIS 4 /* CHOLMOD's nested dissection */ #define CHOLMOD_COLAMD 5 /* AMD for A, COLAMD for AA' or A'A */ #define CHOLMOD_POSTORDERED 6 /* natural then postordered */ size_t other_3 [4] ; // unused, for future expansion } #define CHOLMOD_MAXMETHODS 9 /* max # of methods in Common->method */ method [CHOLMOD_MAXMETHODS + 1] ; int postorder ; // if true, CHOLMOD performs a weighted postordering // after its fill-reducing ordering, which improves supernodal // amalgamation. Has no effect on flop count or nnz(L). // Default: true. int default_nesdis ; // If false, then the default ordering strategy // when Common->nmethods is zero is to try the user's permutation // if given, then AMD, and then METIS if the AMD ordering results in // a lot of fill-in. If true, then nesdis is used instead of METIS. // Default: false. //-------------------------------------------------------------------------- // METIS workarounds //-------------------------------------------------------------------------- // These workarounds were put into place for METIS 4.0.1. They are safe // to use with METIS 5.1.0, but they might not longer be necessary. double metis_memory ; // default: 0. If METIS terminates your // program when it runs out of memory, try 2, or higher. double metis_dswitch ; // default: 0.66 size_t metis_nswitch ; // default: 3000 // If a matrix has n > metis_nswitch and a density (nnz(A)/n^2) > // metis_dswitch, then METIS is not used. //-------------------------------------------------------------------------- // workspace //-------------------------------------------------------------------------- // This workspace is kept in the CHOLMOD Common object. cholmod_start // sets these arrays to NULL, and cholmod_finish frees them. size_t nrow ; // Flag has size nrow, Head has size nrow+1 int64_t mark ; // Flag is cleared if Flag [0..nrow-1] < mark. size_t iworksize ; // size of Iwork, in Ints (int32 or int64). // This is at most 6*nrow + ncol. size_t xworkbytes ; // size of Xwork, in bytes. // NOTE: in CHOLMOD v4 and earlier, this variable was called xworksize, // and was in terms of # of doubles, not # of bytes. void *Flag ; // size nrow. If this is "cleared" then // Flag [i] < mark for all i = 0:nrow-1. Flag is kept cleared between // calls to CHOLMOD. void *Head ; // size nrow+1. If Head [i] = EMPTY (-1) then that // entry is "cleared". Head is kept cleared between calls to CHOLMOD. void *Xwork ; // a double or float array. It has size nrow for most // routines, or 2*nrow if complex matrices are being handled. // It has size 2*nrow for cholmod_rowadd/rowdel, and maxrank*nrow for // cholmod_updown, where maxrank is 2, 4, or 8. Xwork is kept all // zero between calls to CHOLMOD. void *Iwork ; // size iworksize integers (int32's or int64's). // Uninitialized integer workspace, of size at most 6*nrow+ncol. int itype ; // cholmod_start (for int32's) sets this to CHOLMOD_INT, // and cholmod_l_start sets this to CHOLMOD_LONG. It defines the // integer sizes for th Flag, Head, and Iwork arrays, and also // defines the integers for all objects created by CHOLMOD. // The itype of the Common object must match the function name // and all objects passed to it. int other_5 ; // unused: for future expansion int no_workspace_reallocate ; // an internal flag, usually false. // This is set true to disable any reallocation of the workspace // in the Common object. //-------------------------------------------------------------------------- // statistics //-------------------------------------------------------------------------- int status ; // status code (0: ok, negative: error, pos: warning) // Common->status for error handling: 0 is ok, negative is a fatal // error, and positive is a warning #define CHOLMOD_OK (0) #define CHOLMOD_NOT_INSTALLED (-1) /* module not installed */ #define CHOLMOD_OUT_OF_MEMORY (-2) /* malloc/calloc/realloc failed */ #define CHOLMOD_TOO_LARGE (-3) /* integer overflow */ #define CHOLMOD_INVALID (-4) /* input invalid */ #define CHOLMOD_GPU_PROBLEM (-5) /* CUDA error */ #define CHOLMOD_NOT_POSDEF (1) /* matrix not positive definite */ #define CHOLMOD_DSMALL (2) /* diagonal entry very small */ double fl ; // flop count from last analysis double lnz ; // nnz(L) from last analysis double anz ; // in last analysis: nnz(tril(A)) or nnz(triu(A)) if A // symmetric, or tril(A*A') if A is unsymmetric. double modfl ; // flop count from last update/downdate/rowadd/rowdel, // not included the flops to revise the solution to Lx=b, // if that was performed. size_t malloc_count ; // # of malloc'd objects not yet freed size_t memory_usage ; // peak memory usage in bytes size_t memory_inuse ; // current memory usage in bytes double nrealloc_col ; // # of column reallocations double nrealloc_factor ;// # of factor reallocations due to col. reallocs double ndbounds_hit ; // # of times diagonal modified by dbound double rowfacfl ; // flop count of cholmod_rowfac double aatfl ; // flop count to compute A(:,f)*A(:,f)' int called_nd ; // true if last analysis used nesdis or METIS. int blas_ok ; // true if no integer overflow has occured when trying to // call the BLAS. The typical BLAS library uses 32-bit integers for // its input parameters, even on a 64-bit platform. CHOLMOD uses int64 // in its cholmod_l_* methods, and these must be typecast to the BLAS // integer. If integer overflow occurs, this is set false. //-------------------------------------------------------------------------- // SuiteSparseQR control parameters and statistics //-------------------------------------------------------------------------- // SPQR uses the CHOLMOD Common object for its control and statistics. // These parameters are not used by CHOLMOD itself. // control parameters: double SPQR_grain ; // task size is >= max (total flops / grain) double SPQR_small ; // task size is >= small int SPQR_shrink ; // controls stack realloc method int SPQR_nthreads ; // number of TBB threads, 0 = auto // statistics: double SPQR_flopcount ; // flop count for SPQR double SPQR_analyze_time ; // analysis time in seconds for SPQR double SPQR_factorize_time ; // factorize time in seconds for SPQR double SPQR_solve_time ; // backsolve time in seconds double SPQR_flopcount_bound ; // upper bound on flop count double SPQR_tol_used ; // tolerance used double SPQR_norm_E_fro ; // Frobenius norm of dropped entries //-------------------------------------------------------------------------- // Revised for CHOLMOD v5.0 //-------------------------------------------------------------------------- // was size 10 in CHOLMOD v4.2; reduced to 8 in CHOLMOD v5: int64_t SPQR_istat [8] ; // other statistics //-------------------------------------------------------------------------- // Added for CHOLMOD v5.0 //-------------------------------------------------------------------------- // These terms have been added to the CHOLMOD Common struct for v5.0, and // on most systems they will total 16 bytes. The preceding term, // SPQR_istat, was reduced by 16 bytes, since those last 2 entries were // unused in CHOLMOD v4.2. As a result, the Common struct in v5.0 has the // same size as v4.0, and all entries would normally be in the same offset, // as well. This mitigates any changes between v4.0 and v5.0, and may make // it easier to upgrade from v4 to v5. double nsbounds_hit ; // # of times diagonal modified by sbound. // This ought to be int64_t, but ndbounds_hit was double in // v4 (see above), so nsbounds_hit is made the same type // for consistency. float sbound ; // Same as dbound, // but for single precision factorization. float other_6 ; // for future expansion //-------------------------------------------------------------------------- // GPU configuration and statistics //-------------------------------------------------------------------------- int useGPU ; // 1 if GPU is requested for CHOLMOD // 0 if GPU is not requested for CHOLMOD // -1 if the use of the GPU is in CHOLMOD controled by the // CHOLMOD_USE_GPU environment variable. size_t maxGpuMemBytes ; // GPU control for CHOLMOD double maxGpuMemFraction ; // GPU control for CHOLMOD // for SPQR: size_t gpuMemorySize ; // Amount of memory in bytes on the GPU double gpuKernelTime ; // Time taken by GPU kernels int64_t gpuFlops ; // Number of flops performed by the GPU int gpuNumKernelLaunches ; // Number of GPU kernel launches #ifdef CHOLMOD_HAS_CUDA // these three types are pointers defined by CUDA: #define CHOLMOD_CUBLAS_HANDLE cublasHandle_t #define CHOLMOD_CUDASTREAM cudaStream_t #define CHOLMOD_CUDAEVENT cudaEvent_t #else // they are (void *) if CUDA is not in use: #define CHOLMOD_CUBLAS_HANDLE void * #define CHOLMOD_CUDASTREAM void * #define CHOLMOD_CUDAEVENT void * #endif CHOLMOD_CUBLAS_HANDLE cublasHandle ; // a set of streams for general use CHOLMOD_CUDASTREAM gpuStream [CHOLMOD_HOST_SUPERNODE_BUFFERS] ; CHOLMOD_CUDAEVENT cublasEventPotrf [3] ; CHOLMOD_CUDAEVENT updateCKernelsComplete ; CHOLMOD_CUDAEVENT updateCBuffersFree [CHOLMOD_HOST_SUPERNODE_BUFFERS] ; void *dev_mempool ; // pointer to single allocation of device memory size_t dev_mempool_size ; void *host_pinned_mempool ; // pointer to single alloc of pinned mem size_t host_pinned_mempool_size ; size_t devBuffSize ; int ibuffer ; double syrkStart ; // time syrk started // run times of the different parts of CHOLMOD (GPU and CPU): double cholmod_cpu_gemm_time ; double cholmod_cpu_syrk_time ; double cholmod_cpu_trsm_time ; double cholmod_cpu_potrf_time ; double cholmod_gpu_gemm_time ; double cholmod_gpu_syrk_time ; double cholmod_gpu_trsm_time ; double cholmod_gpu_potrf_time ; double cholmod_assemble_time ; double cholmod_assemble_time2 ; // number of times the BLAS are called on the CPU and the GPU: size_t cholmod_cpu_gemm_calls ; size_t cholmod_cpu_syrk_calls ; size_t cholmod_cpu_trsm_calls ; size_t cholmod_cpu_potrf_calls ; size_t cholmod_gpu_gemm_calls ; size_t cholmod_gpu_syrk_calls ; size_t cholmod_gpu_trsm_calls ; size_t cholmod_gpu_potrf_calls ; double chunk ; // chunksize for computing # of OpenMP threads to use. // Given nwork work to do, # of threads is // max (1, min (floor (work / chunk), nthreads_max)) int nthreads_max ; // max # of OpenMP threads to use in CHOLMOD. // Defaults to SUITESPARSE_OPENMP_MAX_THREADS. #ifdef BLAS_DUMP FILE *blas_dump ; // only used if CHOLMOD is compiled with -DBLAS_DUMP #endif } cholmod_common ; // size_t BLAS statistcs in Common: #define CHOLMOD_CPU_GEMM_CALLS cholmod_cpu_gemm_calls #define CHOLMOD_CPU_SYRK_CALLS cholmod_cpu_syrk_calls #define CHOLMOD_CPU_TRSM_CALLS cholmod_cpu_trsm_calls #define CHOLMOD_CPU_POTRF_CALLS cholmod_cpu_potrf_calls #define CHOLMOD_GPU_GEMM_CALLS cholmod_gpu_gemm_calls #define CHOLMOD_GPU_SYRK_CALLS cholmod_gpu_syrk_calls #define CHOLMOD_GPU_TRSM_CALLS cholmod_gpu_trsm_calls #define CHOLMOD_GPU_POTRF_CALLS cholmod_gpu_potrf_calls // double BLAS statistics in Common: #define CHOLMOD_CPU_GEMM_TIME cholmod_cpu_gemm_time #define CHOLMOD_CPU_SYRK_TIME cholmod_cpu_syrk_time #define CHOLMOD_CPU_TRSM_TIME cholmod_cpu_trsm_time #define CHOLMOD_CPU_POTRF_TIME cholmod_cpu_potrf_time #define CHOLMOD_GPU_GEMM_TIME cholmod_gpu_gemm_time #define CHOLMOD_GPU_SYRK_TIME cholmod_gpu_syrk_time #define CHOLMOD_GPU_TRSM_TIME cholmod_gpu_trsm_time #define CHOLMOD_GPU_POTRF_TIME cholmod_gpu_potrf_time #define CHOLMOD_ASSEMBLE_TIME cholmod_assemble_time #define CHOLMOD_ASSEMBLE_TIME2 cholmod_assemble_time2 #ifndef R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // cholmod_start: first call to CHOLMOD //------------------------------------------------------------------------------ int cholmod_start (cholmod_common *Common) ; int cholmod_l_start (cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_finish: last call to CHOLMOD //------------------------------------------------------------------------------ int cholmod_finish (cholmod_common *Common) ; int cholmod_l_finish (cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_defaults: set default parameters //------------------------------------------------------------------------------ int cholmod_defaults (cholmod_common *Common) ; int cholmod_l_defaults (cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_maxrank: return valid maximum rank for update/downdate //------------------------------------------------------------------------------ size_t cholmod_maxrank // return validated Common->maxrank ( // input: size_t n, // # of rows of L and A cholmod_common *Common ) ; size_t cholmod_l_maxrank (size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_allocate_work: allocate workspace in Common //------------------------------------------------------------------------------ // This method always allocates Xwork as double, for backward compatibility // with CHOLMOD v4 and earlier. See cholmod_alloc_work for CHOLMOD v5. int cholmod_allocate_work ( // input: size_t nrow, // size of Common->Flag (nrow int32's) // and Common->Head (nrow+1 int32's) size_t iworksize, // size of Common->Iwork (# of int32's) size_t xworksize, // size of Common->Xwork (# of double's) cholmod_common *Common ) ; int cholmod_l_allocate_work (size_t, size_t, size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_alloc_work: allocate workspace in Common //------------------------------------------------------------------------------ // Added for CHOLMOD v5: allocates Xwork as either double or single. int cholmod_alloc_work ( // input: size_t nrow, // size of Common->Flag (nrow int32's) // and Common->Head (nrow+1 int32's) size_t iworksize, // size of Common->Iwork (# of int32's) size_t xworksize, // size of Common->Xwork (# of entries) int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE cholmod_common *Common ) ; int cholmod_l_alloc_work (size_t, size_t, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_free_work: free workspace in Common //------------------------------------------------------------------------------ int cholmod_free_work (cholmod_common *Common) ; int cholmod_l_free_work (cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_clear_flag: clear Flag workspace in Common //------------------------------------------------------------------------------ // This macro is deprecated; do not use it: #define CHOLMOD_CLEAR_FLAG(Common) \ { \ Common->mark++ ; \ if (Common->mark <= 0 || Common->mark >= INT32_MAX) \ { \ Common->mark = EMPTY ; \ CHOLMOD (clear_flag) (Common) ; \ } \ } int64_t cholmod_clear_flag (cholmod_common *Common) ; int64_t cholmod_l_clear_flag (cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_error: called when CHOLMOD encounters an error //------------------------------------------------------------------------------ int cholmod_error ( // input: int status, // Common->status const char *file, // source file where error occurred int line, // line number where error occurred const char *message, // error message to print cholmod_common *Common ) ; int cholmod_l_error (int, const char *, int, const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_dbound and cholmod_sbound: for internal use in CHOLMOD only //------------------------------------------------------------------------------ // These were once documented functions but no are no longer meant to be used // by the user application. They remain here for backward compatibility. double cholmod_dbound (double, cholmod_common *) ; double cholmod_l_dbound (double, cholmod_common *) ; float cholmod_sbound (float, cholmod_common *) ; float cholmod_l_sbound (float, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_hypot: compute sqrt (x*x + y*y) accurately //------------------------------------------------------------------------------ double cholmod_hypot (double x, double y) ; double cholmod_l_hypot (double, double) ; //------------------------------------------------------------------------------ // cholmod_divcomplex: complex division, c = a/b //------------------------------------------------------------------------------ int cholmod_divcomplex // return 1 if divide-by-zero, 0 if OK ( // input: double ar, double ai, // a (real, imaginary) double br, double bi, // b (real, imaginary) double *cr, double *ci // c (real, imaginary) ) ; int cholmod_l_divcomplex (double, double, double, double, double *, double *) ; #endif /* !defined(R_MATRIX_CHOLMOD_H) */ //============================================================================== // cholmod_sparse: a sparse matrix in compressed-column (CSC) form //============================================================================== typedef struct cholmod_sparse_struct { size_t nrow ; // # of rows of the matrix size_t ncol ; // # of colums of the matrix size_t nzmax ; // max # of entries that can be held in the matrix // int32_t or int64_t arrays: void *p ; // A->p [0..ncol], column "pointers" of the CSC matrix void *i ; // A->i [0..nzmax-1], the row indices // for unpacked matrices only: void *nz ; // A->nz [0..ncol-1], is the # of nonzeros in each col. // This is NULL for a "packed" matrix (conventional CSC). // For a packed matrix, the jth column is held in A->i and A->x in // postions A->p [j] to A->p [j+1]-1, with no gaps between columns. // For an "unpacked" matrix, there can be gaps between columns, so // the jth columns appears in positions A-p [j] to // A->p [j] + A->nz [j] - 1. // double or float arrays: void *x ; // size nzmax or 2*nzmax, or NULL void *z ; // size nzmax, or NULL int stype ; // A->stype defines what parts of the matrix is held: // 0: the matrix is unsymmetric with both lower and upper parts stored. // >0: the matrix is square and symmetric, with just the upper // triangular part stored. // <0: the matrix is square and symmetric, with just the lower // triangular part stored. int itype ; // A->itype defines the integers used for A->p, A->i, and A->nz. // if CHOLMOD_INT, these arrays are all of type int32_t. // if CHOLMOD_LONG, these arrays are all of type int64_t. int xtype ; // pattern, real, complex, or zomplex int dtype ; // x and z are double or single int sorted ; // true if columns are sorted, false otherwise int packed ; // true if packed (A->nz ignored), false if unpacked } cholmod_sparse ; #ifndef R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // cholmod_allocate_sparse: allocate a sparse matrix //------------------------------------------------------------------------------ cholmod_sparse *cholmod_allocate_sparse ( // input: size_t nrow, // # of rows size_t ncol, // # of columns size_t nzmax, // max # of entries the matrix can hold int sorted, // true if columns are sorted int packed, // true if A is be packed (A->nz NULL), false if unpacked int stype, // the stype of the matrix (unsym, tril, or triu) int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_sparse *cholmod_l_allocate_sparse (size_t, size_t, size_t, int, int, int, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_free_sparse: free a sparse matrix //------------------------------------------------------------------------------ int cholmod_free_sparse ( // input/output: cholmod_sparse **A, // handle of sparse matrix to free cholmod_common *Common ) ; int cholmod_l_free_sparse (cholmod_sparse **, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_reallocate_sparse: change max # of entries in a sparse matrix //------------------------------------------------------------------------------ int cholmod_reallocate_sparse ( // input: size_t nznew, // new max # of nonzeros the sparse matrix can hold // input/output: cholmod_sparse *A, // sparse matrix to reallocate cholmod_common *Common ) ; int cholmod_l_reallocate_sparse (size_t, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_nnz: # of entries in a sparse matrix //------------------------------------------------------------------------------ int64_t cholmod_nnz // return # of entries in the sparse matrix ( // input: cholmod_sparse *A, // sparse matrix to query cholmod_common *Common ) ; int64_t cholmod_l_nnz (cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_speye: sparse identity matrix (possibly rectangular) //------------------------------------------------------------------------------ cholmod_sparse *cholmod_speye ( // input: size_t nrow, // # of rows size_t ncol, // # of columns int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_sparse *cholmod_l_speye (size_t, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_spzeros: sparse matrix with no entries //------------------------------------------------------------------------------ // Identical to cholmod_allocate_sparse, with packed = true, sorted = true, // and stype = 0. cholmod_sparse *cholmod_spzeros // return a sparse matrix with no entries ( // input: size_t nrow, // # of rows size_t ncol, // # of columns size_t nzmax, // max # of entries the matrix can hold int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_sparse *cholmod_l_spzeros (size_t, size_t, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_transpose: transpose a sparse matrix //------------------------------------------------------------------------------ cholmod_sparse *cholmod_transpose // return new sparse matrix C ( // input: cholmod_sparse *A, // input matrix int mode, // 2: numerical (conj) // 1: numerical (non-conj.) // 0: pattern (with diag) cholmod_common *Common ) ; cholmod_sparse *cholmod_l_transpose (cholmod_sparse *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_transpose_unsym: transpose an unsymmetric sparse matrix //------------------------------------------------------------------------------ // Compute C = A', A (:,f)', or A (p,f)', where A is unsymmetric and C is // already allocated. See cholmod_transpose for a routine with a simpler // interface. int cholmod_transpose_unsym ( // input: cholmod_sparse *A, // input matrix int mode, // 2: numerical (conj) // 1: numerical (non-conj.), // 0: pattern (with diag) int32_t *Perm, // permutation for C=A(p,f)', or NULL int32_t *fset, // a list of column indices in range 0:A->ncol-1 size_t fsize, // # of entries in fset // input/output: cholmod_sparse *C, // output matrix, must be allocated on input cholmod_common *Common ) ; int cholmod_l_transpose_unsym (cholmod_sparse *, int, int64_t *, int64_t *, size_t, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_transpose_sym: symmetric permuted transpose //------------------------------------------------------------------------------ // C = A' or C = A(p,p)' where A and C are both symmetric and C is already // allocated. See cholmod_transpose or cholmod_ptranspose for a routine with // a simpler interface. int cholmod_transpose_sym ( // input: cholmod_sparse *A, // input matrix int mode, // 2: numerical (conj) // 1: numerical (non-conj.), // 0: pattern (with diag) int32_t *Perm, // permutation for C=A(p,p)', or NULL // input/output: cholmod_sparse *C, // output matrix, must be allocated on input cholmod_common *Common ) ; int cholmod_l_transpose_sym (cholmod_sparse *, int, int64_t *, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_ptranspose: C = A', A(:,f)', A(p,p)', or A(p,f)' //------------------------------------------------------------------------------ cholmod_sparse *cholmod_ptranspose // return new sparse matrix C ( // input: cholmod_sparse *A, // input matrix int mode, // 2: numerical (conj) // 1: numerical (non-conj.) // 0: pattern (with diag) int32_t *Perm, // permutation for C=A(p,f)', or NULL int32_t *fset, // a list of column indices in range 0:A->ncol-1 size_t fsize, // # of entries in fset cholmod_common *Common ) ; cholmod_sparse *cholmod_l_ptranspose (cholmod_sparse *, int, int64_t *, int64_t *, size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_sort: sort the indices of a sparse matrix //------------------------------------------------------------------------------ int cholmod_sort ( // input/output: cholmod_sparse *A, // input/output matrix to sort cholmod_common *Common ) ; int cholmod_l_sort (cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_band_nnz: # of entries within a band of a sparse matrix //------------------------------------------------------------------------------ int64_t cholmod_band_nnz // return # of entries in a band (-1 if error) ( // input: cholmod_sparse *A, // matrix to examine int64_t k1, // count entries in k1:k2 diagonals int64_t k2, bool ignore_diag, // if true, exclude any diagonal entries cholmod_common *Common ) ; int64_t cholmod_l_band_nnz (cholmod_sparse *, int64_t, int64_t, bool, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_band: C = tril (triu (A,k1), k2) //------------------------------------------------------------------------------ cholmod_sparse *cholmod_band // return a new matrix C ( // input: cholmod_sparse *A, // input matrix int64_t k1, // count entries in k1:k2 diagonals int64_t k2, int mode, // >0: numerical, 0: pattern, <0: pattern (no diag) cholmod_common *Common ) ; cholmod_sparse *cholmod_l_band (cholmod_sparse *, int64_t, int64_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_band_inplace: A = tril (triu (A,k1), k2) //------------------------------------------------------------------------------ int cholmod_band_inplace ( // input: int64_t k1, // count entries in k1:k2 diagonals int64_t k2, int mode, // >0: numerical, 0: pattern, <0: pattern (no diag) // input/output: cholmod_sparse *A, // input/output matrix cholmod_common *Common ) ; int cholmod_l_band_inplace (int64_t, int64_t, int, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_aat: C = A*A' or A(:,f)*A(:,f)' //------------------------------------------------------------------------------ cholmod_sparse *cholmod_aat // return sparse matrix C ( // input: cholmod_sparse *A, // input matrix int32_t *fset, // a list of column indices in range 0:A->ncol-1 size_t fsize, // # of entries in fset int mode, // 2: numerical (conj) // 1: numerical (non-conj.), // 0: pattern (with diag) // -1: pattern (remove diag), // -2: pattern (remove diag; add ~50% extra space in C) cholmod_common *Common ) ; cholmod_sparse *cholmod_l_aat (cholmod_sparse *, int64_t *, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_copy_sparse: C = A, create an exact copy of a sparse matrix //------------------------------------------------------------------------------ // Creates an exact copy of a sparse matrix. For making a copy with a change // of stype and/or copying the pattern of a numerical matrix, see cholmod_copy. // For changing the xtype and/or dtype, see cholmod_sparse_xtype. cholmod_sparse *cholmod_copy_sparse // return new sparse matrix ( // input: cholmod_sparse *A, // sparse matrix to copy cholmod_common *Common ) ; cholmod_sparse *cholmod_l_copy_sparse (cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_copy: C = A, with possible change of stype //------------------------------------------------------------------------------ cholmod_sparse *cholmod_copy // return new sparse matrix ( // input: cholmod_sparse *A, // input matrix, not modified int stype, // stype of C int mode, // 2: numerical (conj) // 1: numerical (non-conj.) // 0: pattern (with diag) // -1: pattern (remove diag) // -2: pattern (remove diag; add ~50% extra space in C) cholmod_common *Common ) ; cholmod_sparse *cholmod_l_copy (cholmod_sparse *, int, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_add: C = alpha*A + beta*B //------------------------------------------------------------------------------ cholmod_sparse *cholmod_add // return C = alpha*A + beta*B ( // input: cholmod_sparse *A, // input matrix cholmod_sparse *B, // input matrix double alpha [2], // scale factor for A (two entires used if complex) double beta [2], // scale factor for A (two entires used if complex) int mode, // 2: numerical (conj) if A and/or B are symmetric, // 1: numerical (non-conj.) if A and/or B are symmetric. // 0: pattern int sorted, // ignored; C is now always returned as sorted cholmod_common *Common ) ; cholmod_sparse *cholmod_l_add (cholmod_sparse *, cholmod_sparse *, double [2], double [2], int, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_sparse_xtype: change the xtype and/or dtype of a sparse matrix //------------------------------------------------------------------------------ int cholmod_sparse_xtype ( // input: int to_xdtype, // requested xtype and dtype // input/output: cholmod_sparse *A, // sparse matrix to change cholmod_common *Common ) ; int cholmod_l_sparse_xtype (int, cholmod_sparse *, cholmod_common *) ; #endif /* !defined(R_MATRIX_CHOLMOD_H) */ //============================================================================== // cholmod_factor: symbolic or numeric factorization (simplicial or supernodal) //============================================================================== typedef struct cholmod_factor_struct { size_t n ; // L is n-by-n size_t minor ; // If the factorization failed because of numerical issues // (the matrix being factorized is found to be singular or not positive // definte), then L->minor is the column at which it failed. L->minor // = n means the factorization was successful. //-------------------------------------------------------------------------- // symbolic ordering and analysis //-------------------------------------------------------------------------- void *Perm ; // int32/int64, size n, fill-reducing ordering void *ColCount ;// int32/int64, size n, # entries in each column of L void *IPerm ; // int32/int64, size n, created by cholmod_solve2; // containing the inverse of L->Perm //-------------------------------------------------------------------------- // simplicial factorization (not supernodal) //-------------------------------------------------------------------------- // The row indices of L(:,j) are held in L->i [L->p [j] ... L->p [j] + // L->nz [j] - 1]. The numeical values of L(:,j) are held in the same // positions in L->x (and L->z if L is zomplex). L->next and L->prev hold // a link list of columns of L, that tracks the order they appear in the // arrays L->i, L->x, and L->z. The head and tail of the list is n+1 and // n, respectively. size_t nzmax ; // # of entries that L->i, L->x, and L->z can hold void *p ; // int32/int64, size n+1, column pointers void *i ; // int32/int64, size nzmax, row indices void *x ; // float/double, size nzmax or 2*nzmax, numerical values void *z ; // float/double, size nzmax or empty, imaginary values void *nz ; // int32/int64, size ncol, # of entries in each column void *next ; // int32/int64, size n+2 void *prev ; // int32/int64, size n+2 //-------------------------------------------------------------------------- // supernodal factorization (not simplicial) //-------------------------------------------------------------------------- // L->x is shared with the simplicial structure above. L->z is not used // for the supernodal case since a supernodal factor cannot be zomplex. size_t nsuper ; // # of supernodes size_t ssize ; // # of integers in L->s size_t xsize ; // # of entries in L->x size_t maxcsize ; // size of largest update matrix size_t maxesize ; // max # of rows in supernodes, excl. triangular part // the following are int32/int64 and are size nsuper+1: void *super ; // first column in each supernode void *pi ; // index into L->s for integer part of a supernode void *px ; // index into L->x for numeric part of a supernode // int32/int64, of size ssize: void *s ; // integer part of supernodes //-------------------------------------------------------------------------- // type of the factorization //-------------------------------------------------------------------------- int ordering ; // the fill-reducing method used (CHOLMOD_NATURAL, // CHOLMOD_GIVEN, CHOLMOD_AMD, CHOLMOD_METIS, CHOLMOD_NESDIS, // CHOLMOD_COLAMD, or CHOLMOD_POSTORDERED). int is_ll ; // true: an LL' factorization; false: LDL' instead int is_super ; // true: supernodal; false: simplicial int is_monotonic ; // true: columns appear in order 0 to n-1 in L, for a // simplicial factorization only // Two boolean values above (is_ll, is_super) and L->xtype (pattern or // otherwise, define eight types of factorizations, but only 6 are used: // If L->xtype is CHOLMOD_PATTERN, then L is a symbolic factor: // // simplicial LDL': (is_ll false, is_super false). Nothing is present // except Perm and ColCount. // // simplicial LL': (is_ll true, is_super false). Identical to the // simplicial LDL', except for the is_ll flag. // // supernodal LL': (is_ll true, is_super true). A supernodal symbolic // factorization. The simplicial symbolic information is present // (Perm and ColCount), as is all of the supernodal factorization // except for the numerical values (x and z). // // If L->xtype is CHOLMOD_REAL, CHOLMOD_COMPLEX, or CHOLMOD_ZOMPLEX, // then L is a numeric factor: // // simplicial LDL': (is_ll false, is_super false). Stored in compressed // column form, using the simplicial components above (nzmax, p, i, // x, z, nz, next, and prev). The unit diagonal of L is not stored, // and D is stored in its place. There are no supernodes. // // simplicial LL': (is_ll true, is_super false). Uses the same storage // scheme as the simplicial LDL', except that D does not appear. // The first entry of each column of L is the diagonal entry of // that column of L. // // supernodal LL': (is_ll true, is_super true). A supernodal factor, // using the supernodal components described above (nsuper, ssize, // xsize, maxcsize, maxesize, super, pi, px, s, x, and z). // A supernodal factorization is never zomplex. int itype ; // integer type for L->Perm, L->ColCount, L->p, L->i, L->nz, // L->next, L->prev, L->super, L->pi, L->px, and L->s. // These are all int32 if L->itype is CHOLMOD_INT, or all int64 // if L->itype is CHOLMOD_LONG. int xtype ; // pattern, real, complex, or zomplex int dtype ; // x and z are double or single int useGPU; // if true, symbolic factorization allows for use of the GPU } cholmod_factor ; #ifndef R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // cholmod_allocate_factor: allocate a numerical factor //------------------------------------------------------------------------------ // L is returned as double precision cholmod_factor *cholmod_allocate_factor // return the new factor L ( // input: size_t n, // L is factorization of an n-by-n matrix cholmod_common *Common ) ; cholmod_factor *cholmod_l_allocate_factor (size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_alloc_factor: allocate a numerical factor (double or single) //------------------------------------------------------------------------------ cholmod_factor *cholmod_alloc_factor // return the new factor L ( // input: size_t n, // L is factorization of an n-by-n matrix int dtype, // CHOLMOD_SINGLE or CHOLMOD_DOUBLE cholmod_common *Common ) ; cholmod_factor *cholmod_l_alloc_factor (size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_free_factor: free a factor //------------------------------------------------------------------------------ int cholmod_free_factor ( // input/output: cholmod_factor **L, // handle of sparse factorization to free cholmod_common *Common ) ; int cholmod_l_free_factor (cholmod_factor **, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_reallocate_factor: change the # entries in a factor //------------------------------------------------------------------------------ int cholmod_reallocate_factor ( // input: size_t nznew, // new max # of nonzeros the factor matrix can hold // input/output: cholmod_factor *L, // factor to reallocate cholmod_common *Common ) ; int cholmod_l_reallocate_factor (size_t, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_change_factor: change the type of factor (e.g., LDL' to LL') //------------------------------------------------------------------------------ int cholmod_change_factor ( // input: int to_xtype, // CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX; // L->dtype remains unchanged. int to_ll, // if true: convert to LL'; else to LDL' int to_super, // if true: convert to supernodal; else to simplicial int to_packed, // if true: pack simplicial columns; else: do not pack int to_monotonic, // if true, put simplicial columns in order // input/output: cholmod_factor *L, // factor to change. cholmod_common *Common ) ; int cholmod_l_change_factor (int, int, int, int, int, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_pack_factor: pack a factor //------------------------------------------------------------------------------ // Removes all slack space from all columns in a factor. int cholmod_pack_factor ( // input/output: cholmod_factor *L, // factor to pack cholmod_common *Common ) ; int cholmod_l_pack_factor (cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_reallocate_column: reallocate a single column L(:,j) //------------------------------------------------------------------------------ int cholmod_reallocate_column ( // input: size_t j, // reallocate L(:,j) size_t need, // space in L(:,j) for this # of entries // input/output: cholmod_factor *L, // L factor modified, L(:,j) resized cholmod_common *Common ) ; int cholmod_l_reallocate_column (size_t, size_t, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_factor_to_sparse: create a sparse matrix copy of a factor //------------------------------------------------------------------------------ cholmod_sparse *cholmod_factor_to_sparse // return a new sparse matrix ( // input/output: cholmod_factor *L, // input: factor to convert; output: L is converted // to a simplicial symbolic factor cholmod_common *Common ) ; cholmod_sparse *cholmod_l_factor_to_sparse (cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_copy_factor: create a copy of a factor //------------------------------------------------------------------------------ cholmod_factor *cholmod_copy_factor // return a copy of the factor ( // input: cholmod_factor *L, // factor to copy (not modified) cholmod_common *Common ) ; cholmod_factor *cholmod_l_copy_factor (cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_factor_xtype: change the xtype and/or dtype of a factor //------------------------------------------------------------------------------ int cholmod_factor_xtype ( // input: int to_xdtype, // requested xtype and dtype // input/output: cholmod_factor *L, // factor to change cholmod_common *Common ) ; int cholmod_l_factor_xtype (int, cholmod_factor *, cholmod_common *) ; #endif /* !defined(R_MATRIX_CHOLMOD_H) */ //============================================================================== // cholmod_dense: a dense matrix, held by column //============================================================================== typedef struct cholmod_dense_struct { size_t nrow ; // the matrix is nrow-by-ncol size_t ncol ; size_t nzmax ; // maximum number of entries in the matrix size_t d ; // leading dimension (d >= nrow must hold) void *x ; // size nzmax or 2*nzmax, if present void *z ; // size nzmax, if present int xtype ; // pattern, real, complex, or zomplex int dtype ; // x and z double or single } cholmod_dense ; #ifndef R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // cholmod_allocate_dense: allocate a dense matrix (contents not initialized) //------------------------------------------------------------------------------ cholmod_dense *cholmod_allocate_dense ( // input: size_t nrow, // # of rows size_t ncol, // # of columns size_t d, // leading dimension int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_dense *cholmod_l_allocate_dense (size_t, size_t, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_zeros: allocate a dense matrix and set it to zero //------------------------------------------------------------------------------ cholmod_dense *cholmod_zeros ( // input: size_t nrow, // # of rows size_t ncol, // # of columns int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_dense *cholmod_l_zeros (size_t, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_ones: allocate a dense matrix of all 1's //------------------------------------------------------------------------------ cholmod_dense *cholmod_ones ( // input: size_t nrow, // # of rows size_t ncol, // # of columns int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (_REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_dense *cholmod_l_ones (size_t, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_eye: allocate a dense identity matrix //------------------------------------------------------------------------------ cholmod_dense *cholmod_eye // return a dense identity matrix ( // input: size_t nrow, // # of rows size_t ncol, // # of columns int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (_REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_dense *cholmod_l_eye (size_t, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_free_dense: free a dense matrix //------------------------------------------------------------------------------ int cholmod_free_dense ( // input/output: cholmod_dense **X, // handle of dense matrix to free cholmod_common *Common ) ; int cholmod_l_free_dense (cholmod_dense **, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_ensure_dense: ensure a dense matrix has a given size and type //------------------------------------------------------------------------------ cholmod_dense *cholmod_ensure_dense ( // input/output: cholmod_dense **X, // matrix to resize as needed (*X may be NULL) // input: size_t nrow, // # of rows size_t ncol, // # of columns size_t d, // leading dimension int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_dense *cholmod_l_ensure_dense (cholmod_dense **, size_t, size_t, size_t, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_sparse_to_dense: create a dense matrix copy of a sparse matrix //------------------------------------------------------------------------------ cholmod_dense *cholmod_sparse_to_dense // return a dense matrix ( // input: cholmod_sparse *A, // input matrix cholmod_common *Common ) ; cholmod_dense *cholmod_l_sparse_to_dense (cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_dense_nnz: count # of nonzeros in a dense matrix //------------------------------------------------------------------------------ int64_t cholmod_dense_nnz // return # of entries in the dense matrix ( // input: cholmod_dense *X, // input matrix cholmod_common *Common ) ; int64_t cholmod_l_dense_nnz (cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_dense_to_sparse: create a sparse matrix copy of a dense matrix //------------------------------------------------------------------------------ cholmod_sparse *cholmod_dense_to_sparse // return a sparse matrix C ( // input: cholmod_dense *X, // input matrix int mode, // 1: copy the values // 0: C is pattern cholmod_common *Common ) ; cholmod_sparse *cholmod_l_dense_to_sparse (cholmod_dense *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_copy_dense: create a copy of a dense matrix //------------------------------------------------------------------------------ cholmod_dense *cholmod_copy_dense // returns new dense matrix ( // input: cholmod_dense *X, // input dense matrix cholmod_common *Common ) ; cholmod_dense *cholmod_l_copy_dense (cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_copy_dense2: copy a dense matrix (pre-allocated) //------------------------------------------------------------------------------ int cholmod_copy_dense2 ( // input: cholmod_dense *X, // input dense matrix // input/output: cholmod_dense *Y, // output dense matrix (already allocated on input) cholmod_common *Common ) ; int cholmod_l_copy_dense2 (cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_dense_xtype: change the xtype and/or dtype of a dense matrix //------------------------------------------------------------------------------ int cholmod_dense_xtype ( // input: int to_xdtype, // requested xtype and dtype // input/output: cholmod_dense *X, // dense matrix to change cholmod_common *Common ) ; int cholmod_l_dense_xtype (int, cholmod_dense *, cholmod_common *) ; #endif /* !defined(R_MATRIX_CHOLMOD_H) */ //============================================================================= // cholmod_triplet: a sparse matrix in triplet form //============================================================================= typedef struct cholmod_triplet_struct { size_t nrow ; // # of rows of the matrix size_t ncol ; // # of colums of the matrix size_t nzmax ; // max # of entries that can be held in the matrix size_t nnz ; // current # of entries can be held in the matrix // int32 or int64 arrays (depending on T->itype) void *i ; // i [0..nzmax-1], the row indices void *j ; // j [0..nzmax-1], the column indices // double or float arrays: void *x ; // size nzmax or 2*nzmax, or NULL void *z ; // size nzmax, or NULL int stype ; // T->stype defines what parts of the matrix is held: // 0: the matrix is unsymmetric with both lower and upper parts stored. // >0: the matrix is square and symmetric, where entries in the lower // triangular part are transposed and placed in the upper // triangular part of A if T is converted into a sparse matrix A. // <0: the matrix is square and symmetric, where entries in the upper // triangular part are transposed and placed in the lower // triangular part of A if T is converted into a sparse matrix A. // // Note that A->stype (for a sparse matrix) and T->stype (for a // triplet matrix) are handled differently. In a triplet matrix T, // no entry is ever ignored. For a sparse matrix A, if A->stype < 0 // or A->stype > 0, then entries not in the correct triangular part // are ignored. int itype ; // T->itype defines the integers used for T->i and T->j. // if CHOLMOD_INT, these arrays are all of type int32_t. // if CHOLMOD_LONG, these arrays are all of type int64_t. int xtype ; // pattern, real, complex, or zomplex int dtype ; // x and z are double or single } cholmod_triplet ; #ifndef R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // cholmod_allocate_triplet: allocate a triplet matrix //------------------------------------------------------------------------------ cholmod_triplet *cholmod_allocate_triplet // return triplet matrix T ( // input: size_t nrow, // # of rows size_t ncol, // # of columns size_t nzmax, // max # of entries the matrix can hold int stype, // the stype of the matrix (unsym, tril, or triu) int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX) cholmod_common *Common ) ; cholmod_triplet *cholmod_l_allocate_triplet (size_t, size_t, size_t, int, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_free_triplet: free a triplet matrix //------------------------------------------------------------------------------ int cholmod_free_triplet ( // input/output: cholmod_triplet **T, // handle of triplet matrix to free cholmod_common *Common ) ; int cholmod_l_free_triplet (cholmod_triplet **, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_reallocate_triplet: change max # of entries in a triplet matrix //------------------------------------------------------------------------------ int cholmod_reallocate_triplet ( // input: size_t nznew, // new max # of nonzeros the triplet matrix can hold // input/output: cholmod_triplet *T, // triplet matrix to reallocate cholmod_common *Common ) ; int cholmod_l_reallocate_triplet (size_t, cholmod_triplet *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_sparse_to_triplet: create a triplet matrix copy of a sparse matrix //------------------------------------------------------------------------------ cholmod_triplet *cholmod_sparse_to_triplet ( // input: cholmod_sparse *A, // matrix to copy into triplet form T cholmod_common *Common ) ; cholmod_triplet *cholmod_l_sparse_to_triplet (cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_triplet_to_sparse: create a sparse matrix from of triplet matrix //------------------------------------------------------------------------------ cholmod_sparse *cholmod_triplet_to_sparse // return sparse matrix A ( // input: cholmod_triplet *T, // input triplet matrix size_t nzmax, // allocate space for max(nzmax,nnz(A)) entries cholmod_common *Common ) ; cholmod_sparse *cholmod_l_triplet_to_sparse (cholmod_triplet *, size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_copy_triplet: copy a triplet matrix //------------------------------------------------------------------------------ cholmod_triplet *cholmod_copy_triplet // return new triplet matrix ( // input: cholmod_triplet *T, // triplet matrix to copy cholmod_common *Common ) ; cholmod_triplet *cholmod_l_copy_triplet (cholmod_triplet *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_triplet_xtype: change the xtype and/or dtype of a triplet matrix //------------------------------------------------------------------------------ int cholmod_triplet_xtype ( // input: int to_xdtype, // requested xtype and dtype // input/output: cholmod_triplet *T, // triplet matrix to change cholmod_common *Common ) ; int cholmod_l_triplet_xtype (int, cholmod_triplet *, cholmod_common *) ; #endif /* !defined(R_MATRIX_CHOLMOD_H) */ //------------------------------------------------------------------------------ // memory allocation: malloc/calloc/realloc/free //------------------------------------------------------------------------------ // These methods act like malloc/calloc/realloc/free, with some differences. // They are simple wrappers around the memory management functions in // SuiteSparse_config. cholmod_malloc and cholmod_calloc have the same // signature, unlike malloc and calloc. If cholmod_free is given a NULL // pointer, it safely does nothing. cholmod_free must be passed the size of // the object being freed, but that is just to keep track of memory usage // statistics. cholmod_realloc does not return NULL if it fails; instead, it // returns the pointer to the unmodified block of memory. #ifndef R_MATRIX_CHOLMOD_H void *cholmod_malloc // return pointer to newly allocated memory ( // input: size_t n, // number of items size_t size, // size of each item cholmod_common *Common ) ; void *cholmod_l_malloc (size_t, size_t, cholmod_common *) ; void *cholmod_calloc // return pointer to newly allocated memory ( // input: size_t n, // number of items size_t size, // size of each item cholmod_common *Common ) ; void *cholmod_l_calloc (size_t, size_t, cholmod_common *) ; void *cholmod_free // returns NULL to simplify its usage ( // input: size_t n, // number of items size_t size, // size of each item // input/output: void *p, // memory to free cholmod_common *Common ) ; void *cholmod_l_free (size_t, size_t, void *, cholmod_common *) ; void *cholmod_realloc // return newly reallocated block of memory ( // input: size_t nnew, // # of items in newly reallocate memory size_t size, // size of each item // input/output: void *p, // pointer to memory to reallocate (may be NULL) size_t *n, // # of items in p on input; nnew on output if success cholmod_common *Common ) ; void *cholmod_l_realloc (size_t, size_t, void *, size_t *, cholmod_common *) ; int cholmod_realloc_multiple // returns true if successful, false otherwise ( // input: size_t nnew, // # of items in newly reallocate memory int nint, // 0: do not allocate I_block or J_block, 1: just I_block, // 2: both I_block and J_block int xdtype, // xtype + dtype of the matrix: // (CHOLMOD_DOUBLE, _SINGLE) + // (CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX) // input/output: void **I_block, // integer block of memory (int32_t or int64_t) void **J_block, // integer block of memory (int32_t or int64_t) void **X_block, // real or complex, double or single, block void **Z_block, // zomplex only: double or single block size_t *n, // current size of I_block, J_block, X_block, and/or Z_block // on input, changed to nnew on output, if successful cholmod_common *Common ) ; int cholmod_l_realloc_multiple (size_t, int, int, void **, void **, void **, void **, size_t *, cholmod_common *) ; #endif /* !defined(R_MATRIX_CHOLMOD_H) */ //------------------------------------------------------------------------------ // numerical comparisons //------------------------------------------------------------------------------ // These macros were different on Windows for older versions of CHOLMOD. // They are no longer needed but are kept for backward compatibility. #ifndef R_MATRIX_CHOLMOD_H #define CHOLMOD_IS_NAN(x) isnan (x) #define CHOLMOD_IS_ZERO(x) ((x) == 0.) #define CHOLMOD_IS_NONZERO(x) ((x) != 0.) #define CHOLMOD_IS_LT_ZERO(x) ((x) < 0.) #define CHOLMOD_IS_GT_ZERO(x) ((x) > 0.) #define CHOLMOD_IS_LE_ZERO(x) ((x) <= 0.) #endif /* !defined(R_MATRIX_CHOLMOD_H) */ #endif //============================================================================== // CHOLMOD:Check Module //============================================================================== // Routines that check and print the 5 basic data types in CHOLMOD, and 3 kinds // of integer vectors (subset, perm, and parent), and read in matrices from a // file: // // cholmod_check_common check/print the Common object // cholmod_print_common // // cholmod_check_sparse check/print a sparse matrix in column-oriented form // cholmod_print_sparse // // cholmod_check_dense check/print a dense matrix // cholmod_print_dense // // cholmod_check_factor check/print a Cholesky factorization // cholmod_print_factor // // cholmod_check_triplet check/print a sparse matrix in triplet form // cholmod_print_triplet // // cholmod_check_subset check/print a subset (integer vector in given range) // cholmod_print_subset // // cholmod_check_perm check/print a permutation (an integer vector) // cholmod_print_perm // // cholmod_check_parent check/print an elimination tree (an integer vector) // cholmod_print_parent // // cholmod_read_triplet read a matrix in triplet form (any Matrix Market // "coordinate" format, or a generic triplet format). // // cholmod_read_sparse read a matrix in sparse form (same file format as // cholmod_read_triplet). // // cholmod_read_dense read a dense matrix (any Matrix Market "array" // format, or a generic dense format). // // cholmod_write_sparse write a sparse matrix to a Matrix Market file. // // cholmod_write_dense write a dense matrix to a Matrix Market file. // // cholmod_print_common and cholmod_check_common are the only two routines that // you may call after calling cholmod_finish. // // Requires the Utility module. Not required by any CHOLMOD module, except when // debugging is enabled (in which case all modules require the Check module). // // See cholmod_read.c for a description of the file formats supported by the // cholmod_read_* routines. #ifndef R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // cholmod_check_common: check the Common object //------------------------------------------------------------------------------ int cholmod_check_common ( cholmod_common *Common ) ; int cholmod_l_check_common (cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_print_common: print the Common object //------------------------------------------------------------------------------ int cholmod_print_common ( // input: const char *name, // printed name of Common object cholmod_common *Common ) ; int cholmod_l_print_common (const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_gpu_stats: print the GPU / CPU statistics //------------------------------------------------------------------------------ int cholmod_gpu_stats (cholmod_common *) ; int cholmod_l_gpu_stats (cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_check_sparse: check a sparse matrix //------------------------------------------------------------------------------ int cholmod_check_sparse ( // input: cholmod_sparse *A, // sparse matrix to check cholmod_common *Common ) ; int cholmod_l_check_sparse (cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_print_sparse //------------------------------------------------------------------------------ int cholmod_print_sparse ( // input: cholmod_sparse *A, // sparse matrix to print const char *name, // printed name of sparse matrix cholmod_common *Common ) ; int cholmod_l_print_sparse (cholmod_sparse *, const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_check_dense: check a dense matrix //------------------------------------------------------------------------------ int cholmod_check_dense ( // input: cholmod_dense *X, // dense matrix to check cholmod_common *Common ) ; int cholmod_l_check_dense (cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_print_dense: print a dense matrix //------------------------------------------------------------------------------ int cholmod_print_dense ( // input: cholmod_dense *X, // dense matrix to print const char *name, // printed name of dense matrix cholmod_common *Common ) ; int cholmod_l_print_dense (cholmod_dense *, const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_check_factor: check a factor //------------------------------------------------------------------------------ int cholmod_check_factor ( // input: cholmod_factor *L, // factor to check cholmod_common *Common ) ; int cholmod_l_check_factor (cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_print_factor: print a factor //------------------------------------------------------------------------------ int cholmod_print_factor ( // input: cholmod_factor *L, // factor to print const char *name, // printed name of factor cholmod_common *Common ) ; int cholmod_l_print_factor (cholmod_factor *, const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_check_triplet: check a sparse matrix in triplet form //------------------------------------------------------------------------------ int cholmod_check_triplet ( // input: cholmod_triplet *T, // triplet matrix to check cholmod_common *Common ) ; int cholmod_l_check_triplet (cholmod_triplet *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_print_triplet: print a triplet matrix //------------------------------------------------------------------------------ int cholmod_print_triplet ( // input: cholmod_triplet *T, // triplet matrix to print const char *name, // printed name of triplet matrix cholmod_common *Common ) ; int cholmod_l_print_triplet (cholmod_triplet *, const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_check_subset: check a subset //------------------------------------------------------------------------------ int cholmod_check_subset ( // input: int32_t *Set, // Set [0:len-1] is a subset of 0:n-1. Duplicates OK int64_t len, // size of Set (an integer array) size_t n, // 0:n-1 is valid range cholmod_common *Common ) ; int cholmod_l_check_subset (int64_t *, int64_t, size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_print_subset: print a subset //------------------------------------------------------------------------------ int cholmod_print_subset ( // input: int32_t *Set, // Set [0:len-1] is a subset of 0:n-1. Duplicates OK int64_t len, // size of Set (an integer array) size_t n, // 0:n-1 is valid range const char *name, // printed name of Set cholmod_common *Common ) ; int cholmod_l_print_subset (int64_t *, int64_t, size_t, const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_check_perm: check a permutation //------------------------------------------------------------------------------ int cholmod_check_perm ( // input: int32_t *Perm, // Perm [0:len-1] is a permutation of subset of 0:n-1 size_t len, // size of Perm (an integer array) size_t n, // 0:n-1 is valid range cholmod_common *Common ) ; int cholmod_l_check_perm (int64_t *, size_t, size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_print_perm: print a permutation vector //------------------------------------------------------------------------------ int cholmod_print_perm ( // input: int32_t *Perm, // Perm [0:len-1] is a permutation of subset of 0:n-1 size_t len, // size of Perm (an integer array) size_t n, // 0:n-1 is valid range const char *name, // printed name of Perm cholmod_common *Common ) ; int cholmod_l_print_perm (int64_t *, size_t, size_t, const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_check_parent: check an elimination tree //------------------------------------------------------------------------------ int cholmod_check_parent ( // input: int32_t *Parent, // Parent [0:n-1] is an elimination tree size_t n, // size of Parent cholmod_common *Common ) ; int cholmod_l_check_parent (int64_t *, size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_print_parent //------------------------------------------------------------------------------ int cholmod_print_parent ( // input: int32_t *Parent, // Parent [0:n-1] is an elimination tree size_t n, // size of Parent const char *name, // printed name of Parent cholmod_common *Common ) ; int cholmod_l_print_parent (int64_t *, size_t, const char *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_read_sparse: read a sparse matrix from a file (double only) //------------------------------------------------------------------------------ cholmod_sparse *cholmod_read_sparse // return sparse matrix (double) ( // input: FILE *f, // file to read from, must already be open cholmod_common *Common ) ; cholmod_sparse *cholmod_l_read_sparse (FILE *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_read_sparse2: read a sparse matrix from a file (float or double) //------------------------------------------------------------------------------ cholmod_sparse *cholmod_read_sparse2 // return sparse matrix (double/single) ( // input: FILE *f, // file to read from, must already be open int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE cholmod_common *Common ) ; cholmod_sparse *cholmod_l_read_sparse2 (FILE *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_read_triplet: read a triplet matrix from a file (double only) //------------------------------------------------------------------------------ cholmod_triplet *cholmod_read_triplet // return triplet matrix (double) ( // input: FILE *f, // file to read from, must already be open cholmod_common *Common ) ; cholmod_triplet *cholmod_l_read_triplet (FILE *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_read_triplet: read a triplet matrix from a file (float or double) //------------------------------------------------------------------------------ cholmod_triplet *cholmod_read_triplet2 // return triplet matrix (double/single) ( // input: FILE *f, // file to read from, must already be open int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE cholmod_common *Common ) ; cholmod_triplet *cholmod_l_read_triplet2 (FILE *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_read_dense: read a dense matrix from a file (double only) //------------------------------------------------------------------------------ cholmod_dense *cholmod_read_dense // return dense matrix (double) ( // input: FILE *f, // file to read from, must already be open cholmod_common *Common ) ; cholmod_dense *cholmod_l_read_dense (FILE *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_read_dense2: read a dense matrix from a file (float or double) //------------------------------------------------------------------------------ cholmod_dense *cholmod_read_dense2 // return dense matrix (double/single) ( // input: FILE *f, // file to read from, must already be open int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE cholmod_common *Common ) ; cholmod_dense *cholmod_l_read_dense2 (FILE *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_read_matrix: read a sparse or dense matrix from a file (double only) //------------------------------------------------------------------------------ void *cholmod_read_matrix // return sparse/triplet/double matrix (double) ( // input: FILE *f, // file to read from, must already be open int prefer, // If 0, a sparse matrix is always return as a // cholmod_triplet form. It can have any stype // (symmetric-lower, unsymmetric, or symmetric-upper). // If 1, a sparse matrix is returned as an unsymmetric // cholmod_sparse form (A->stype == 0), with both upper and // lower triangular parts present. This is what the MATLAB // mread mexFunction does, since MATLAB does not have an // stype. // If 2, a sparse matrix is returned with an stype of 0 or // 1 (unsymmetric, or symmetric with upper part stored). // This argument has no effect for dense matrices. // output: int *mtype, // CHOLMOD_TRIPLET, CHOLMOD_SPARSE or CHOLMOD_DENSE cholmod_common *Common ) ; void *cholmod_l_read_matrix (FILE *, int, int *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_read_matrix2: read a sparse or dense matrix (float or double) //------------------------------------------------------------------------------ void *cholmod_read_matrix2 // sparse/triplet/double matrix (double/single) ( // input: FILE *f, // file to read from, must already be open int prefer, // see cholmod_read_matrix int dtype, // CHOLMOD_DOUBLE or CHOLMOD_SINGLE // output: int *mtype, // CHOLMOD_TRIPLET, CHOLMOD_SPARSE or CHOLMOD_DENSE cholmod_common *Common ) ; void *cholmod_l_read_matrix2 (FILE *, int, int, int *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_write_sparse: write a sparse matrix to a file //------------------------------------------------------------------------------ #endif /* !defined(R_MATRIX_CHOLMOD_H) */ // return values of cholmod_symmetry and cholmod_write: #define CHOLMOD_MM_RECTANGULAR 1 #define CHOLMOD_MM_UNSYMMETRIC 2 #define CHOLMOD_MM_SYMMETRIC 3 #define CHOLMOD_MM_HERMITIAN 4 #define CHOLMOD_MM_SKEW_SYMMETRIC 5 #define CHOLMOD_MM_SYMMETRIC_POSDIAG 6 #define CHOLMOD_MM_HERMITIAN_POSDIAG 7 #ifndef R_MATRIX_CHOLMOD_H int cholmod_write_sparse // see above, or -1 on error ( // input: FILE *f, // file to write to, must already be open cholmod_sparse *A, // matrix to print cholmod_sparse *Z, // optional matrix with pattern of explicit zeros const char *comments, // optional filename of comments to include cholmod_common *Common ) ; int cholmod_l_write_sparse (FILE *, cholmod_sparse *, cholmod_sparse *, const char *c, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_write_dense: write a dense matrix to a file //------------------------------------------------------------------------------ int cholmod_write_dense // CHOLMOD_MM_UNSYMMETRIC or _RECTANGULAR, or ( // -1 on error // input: FILE *f, // file to write to, must already be open cholmod_dense *X, // matrix to print const char *comments, // optional filename of comments to include cholmod_common *Common ) ; int cholmod_l_write_dense (FILE *, cholmod_dense *, const char *, cholmod_common *) ; #endif /* !defined(R_MATRIX_CHOLMOD_H) */ //============================================================================== // CHOLMOD:Cholesky Module //============================================================================== // Sparse Cholesky routines: analysis, factorization, and solve. // // The primary routines are all that a user requires to order, analyze, and // factorize a sparse symmetric positive definite matrix A (or A*A'), and // to solve Ax=b (or A*A'x=b). The primary routines rely on the secondary // routines, the CHOLMOD Utility module, and the AMD and COLAMD packages. They // make optional use of the CHOLMOD Supernodal and Partition modules, the // METIS package, and the CCOLAMD package. // // Primary routines: // ----------------- // // cholmod_analyze order and analyze (simplicial or supernodal) // cholmod_factorize simplicial or supernodal Cholesky factorization // cholmod_solve solve a linear system (simplicial or supernodal) // cholmod_solve2 like cholmod_solve, but reuse workspace // cholmod_spsolve solve a linear system (sparse x and b) // // Secondary routines: // ------------------ // // cholmod_analyze_p analyze, with user-provided permutation or f set // cholmod_factorize_p factorize, with user-provided permutation or f // cholmod_analyze_ordering analyze a fill-reducing ordering // cholmod_etree find the elimination tree // cholmod_rowcolcounts compute the row/column counts of L // cholmod_amd order using AMD // cholmod_colamd order using COLAMD // cholmod_rowfac incremental simplicial factorization // cholmod_rowfac_mask rowfac, specific to LPDASA // cholmod_rowfac_mask2 rowfac, specific to LPDASA // cholmod_row_subtree find the nonzero pattern of a row of L // cholmod_resymbol recompute the symbolic pattern of L // cholmod_resymbol_noperm recompute the symbolic pattern of L, no L->Perm // cholmod_postorder postorder a tree // // Requires the Utility module, and two packages: AMD and COLAMD. // Optionally uses the Supernodal and Partition modules. // Required by the Partition module. #ifndef R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // cholmod_analyze: order and analyze (simplicial or supernodal) //------------------------------------------------------------------------------ // Orders and analyzes A, AA', PAP', or PAA'P' and returns a symbolic factor // that can later be passed to cholmod_factorize. cholmod_factor *cholmod_analyze // returns symbolic factor L ( // input: cholmod_sparse *A, // matrix to order and analyze cholmod_common *Common ) ; cholmod_factor *cholmod_l_analyze (cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_analyze_p: analyze, with user-provided permutation or f set //------------------------------------------------------------------------------ // Orders and analyzes A, AA', PAP', PAA'P', FF', or PFF'P and returns a // symbolic factor that can later be passed to cholmod_factorize, where // F = A(:,fset) if fset is not NULL and A->stype is zero. // UserPerm is tried if non-NULL. cholmod_factor *cholmod_analyze_p // returns symbolic factor L ( // input: cholmod_sparse *A, // matrix to order and analyze int32_t *UserPerm, // user-provided permutation, size A->nrow int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset cholmod_common *Common ) ; cholmod_factor *cholmod_l_analyze_p (cholmod_sparse *, int64_t *, int64_t *, size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_analyze_p2: analyze for sparse Cholesky or sparse QR //------------------------------------------------------------------------------ // This is normally not need by the user application. cholmod_factor *cholmod_analyze_p2 ( // input: int for_whom, // FOR_SPQR (0): for SPQR but not GPU-accelerated // FOR_CHOLESKY (1): for Cholesky (GPU or not) // FOR_SPQRGPU (2): for SPQR with GPU acceleration cholmod_sparse *A, // matrix to order and analyze int32_t *UserPerm, // user-provided permutation, size A->nrow int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset cholmod_common *Common ) ; cholmod_factor *cholmod_l_analyze_p2 (int, cholmod_sparse *, int64_t *, int64_t *, size_t, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_factorize: simplicial or supernodal Cholesky factorization //------------------------------------------------------------------------------ // Factorizes PAP' (or PAA'P' if A->stype is 0), using a factor obtained // from cholmod_analyze. The analysis can be re-used simply by calling this // routine a second time with another matrix. A must have the same nonzero // pattern as that passed to cholmod_analyze. int cholmod_factorize // simplicial or superodal Cholesky factorization ( // input: cholmod_sparse *A, // matrix to factorize // input/output: cholmod_factor *L, // resulting factorization cholmod_common *Common ) ; int cholmod_l_factorize (cholmod_sparse *, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_factorize_p: factorize, with user-provided permutation or fset //------------------------------------------------------------------------------ // Same as cholmod_factorize, but with more options. int cholmod_factorize_p ( // input: cholmod_sparse *A, // matrix to factorize double beta [2], // factorize beta*I+A or beta*I+A'*A int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset // input/output: cholmod_factor *L, // resulting factorization cholmod_common *Common ) ; int cholmod_l_factorize_p (cholmod_sparse *, double [2], int64_t *, size_t, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_solve: solve a linear system (simplicial or supernodal) //------------------------------------------------------------------------------ // Solves one of many linear systems with a dense right-hand-side, using the // factorization from cholmod_factorize (or as modified by any other CHOLMOD // routine). D is identity for LL' factorizations. #endif /* !defined(R_MATRIX_CHOLMOD_H) */ #define CHOLMOD_A 0 /* solve Ax=b */ #define CHOLMOD_LDLt 1 /* solve LDL'x=b */ #define CHOLMOD_LD 2 /* solve LDx=b */ #define CHOLMOD_DLt 3 /* solve DL'x=b */ #define CHOLMOD_L 4 /* solve Lx=b */ #define CHOLMOD_Lt 5 /* solve L'x=b */ #define CHOLMOD_D 6 /* solve Dx=b */ #define CHOLMOD_P 7 /* permute x=Px */ #define CHOLMOD_Pt 8 /* permute x=P'x */ #ifndef R_MATRIX_CHOLMOD_H cholmod_dense *cholmod_solve // returns the solution X ( // input: int sys, // system to solve cholmod_factor *L, // factorization to use cholmod_dense *B, // right-hand-side cholmod_common *Common ) ; cholmod_dense *cholmod_l_solve (int, cholmod_factor *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_solve2: like cholmod_solve, but with reusable workspace //------------------------------------------------------------------------------ int cholmod_solve2 // returns TRUE on success, FALSE on failure ( // input: int sys, // system to solve cholmod_factor *L, // factorization to use cholmod_dense *B, // right-hand-side cholmod_sparse *Bset, // output: cholmod_dense **X_Handle, // solution, allocated if need be cholmod_sparse **Xset_Handle, // workspace: cholmod_dense **Y_Handle, // workspace, or NULL cholmod_dense **E_Handle, // workspace, or NULL cholmod_common *Common ) ; int cholmod_l_solve2 (int, cholmod_factor *, cholmod_dense *, cholmod_sparse *, cholmod_dense **, cholmod_sparse **, cholmod_dense **, cholmod_dense **, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_spsolve: solve a linear system with a sparse right-hand-side //------------------------------------------------------------------------------ cholmod_sparse *cholmod_spsolve // returns the sparse solution X ( // input: int sys, // system to solve cholmod_factor *L, // factorization to use cholmod_sparse *B, // right-hand-side cholmod_common *Common ) ; cholmod_sparse *cholmod_l_spsolve (int, cholmod_factor *, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_etree: find the elimination tree of A or A'*A //------------------------------------------------------------------------------ int cholmod_etree ( // input: cholmod_sparse *A, // output: int32_t *Parent, // size ncol. Parent [j] = p if p is the parent of j cholmod_common *Common ) ; int cholmod_l_etree (cholmod_sparse *, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowcolcounts: compute the row/column counts of L //------------------------------------------------------------------------------ int cholmod_rowcolcounts ( // input: cholmod_sparse *A, // matrix to analyze int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int32_t *Parent, // size nrow. Parent [i] = p if p is the parent of i int32_t *Post, // size nrow. Post [k] = i if i is the kth node in // the postordered etree. // output: int32_t *RowCount, // size nrow. RowCount [i] = # entries in the ith // row of L, including the diagonal. int32_t *ColCount, // size nrow. ColCount [i] = # entries in the ith // column of L, including the diagonal. int32_t *First, // size nrow. First [i] = k is the least // postordering of any descendant of i. int32_t *Level, // size nrow. Level [i] is the length of the path // from i to the root, with Level [root] = 0. cholmod_common *Common ) ; int cholmod_l_rowcolcounts (cholmod_sparse *, int64_t *, size_t, int64_t *, int64_t *, int64_t *, int64_t *, int64_t *, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_analyze_ordering: analyze a fill-reducing ordering //------------------------------------------------------------------------------ int cholmod_analyze_ordering ( // input: cholmod_sparse *A, // matrix to analyze int ordering, // ordering method used int32_t *Perm, // size n, fill-reducing permutation to analyze int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset // output: int32_t *Parent, // size n, elimination tree int32_t *Post, // size n, postordering of elimination tree int32_t *ColCount, // size n, nnz in each column of L // workspace: int32_t *First, // size n workspace for cholmod_postorder int32_t *Level, // size n workspace for cholmod_postorder cholmod_common *Common ) ; int cholmod_l_analyze_ordering (cholmod_sparse *, int, int64_t *, int64_t *, size_t, int64_t *, int64_t *, int64_t *, int64_t *, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_amd: order using AMD //------------------------------------------------------------------------------ // Finds a permutation P to reduce fill-in in the factorization of P*A*P' // or P*A*A'P' int cholmod_amd ( // input: cholmod_sparse *A, // matrix to order int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset // output: int32_t *Perm, // size A->nrow, output permutation cholmod_common *Common ) ; int cholmod_l_amd (cholmod_sparse *, int64_t *, size_t, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_colamd: order using COLAMD //------------------------------------------------------------------------------ // Finds a permutation P to reduce fill-in in the factorization of P*A*A'*P'. // Orders F*F' where F = A (:,fset) if fset is not NULL int cholmod_colamd ( // input: cholmod_sparse *A, // matrix to order int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int postorder, // if TRUE, follow with a coletree postorder // output: int32_t *Perm, // size A->nrow, output permutation cholmod_common *Common ) ; int cholmod_l_colamd (cholmod_sparse *, int64_t *, size_t, int, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowfac: incremental simplicial factorization //------------------------------------------------------------------------------ // Partial or complete simplicial factorization. Rows and columns kstart:kend-1 // of L and D must be initially equal to rows/columns kstart:kend-1 of the // identity matrix. Row k can only be factorized if all descendants of node // k in the elimination tree have been factorized. int cholmod_rowfac ( // input: cholmod_sparse *A, // matrix to factorize cholmod_sparse *F, // used for A*A' case only. F=A' or A(:,f)' double beta [2], // factorize beta*I+A or beta*I+AA' size_t kstart, // first row to factorize size_t kend, // last row to factorize is kend-1 // input/output: cholmod_factor *L, cholmod_common *Common ) ; int cholmod_l_rowfac (cholmod_sparse *, cholmod_sparse *, double [2], size_t, size_t, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowfac_mask: incremental simplicial factorization //------------------------------------------------------------------------------ // cholmod_rowfac_mask and cholmod_rowfac_mask2 are version of cholmod_rowfac // that are specific to LPDASA. It is unlikely to be needed by any other // application, and is not documented in the CHOLMOD User Guide. int cholmod_rowfac_mask ( // input: cholmod_sparse *A, // matrix to factorize cholmod_sparse *F, // used for A*A' case only. F=A' or A(:,f)' double beta [2], // factorize beta*I+A or beta*I+AA' size_t kstart, // first row to factorize size_t kend, // last row to factorize is kend-1 int32_t *mask, // size A->nrow. if mask[i] >= 0 row i is set to zero int32_t *RLinkUp, // size A->nrow. link list of rows to compute // input/output: cholmod_factor *L, cholmod_common *Common ) ; int cholmod_l_rowfac_mask (cholmod_sparse *, cholmod_sparse *, double [2], size_t, size_t, int64_t *, int64_t *, cholmod_factor *, cholmod_common *) ; int cholmod_rowfac_mask2 ( // input: cholmod_sparse *A, // matrix to factorize cholmod_sparse *F, // used for A*A' case only. F=A' or A(:,f)' double beta [2], // factorize beta*I+A or beta*I+AA' size_t kstart, // first row to factorize size_t kend, // last row to factorize is kend-1 int32_t *mask, // size A->nrow. if mask[i] >= maskmark row i is set // to zero int32_t maskmark, // for mask [i] test int32_t *RLinkUp, // size A->nrow. link list of rows to compute // input/output: cholmod_factor *L, cholmod_common *Common ) ; int cholmod_l_rowfac_mask2 (cholmod_sparse *, cholmod_sparse *, double [2], size_t, size_t, int64_t *, int64_t, int64_t *, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_row_subtree: find the nonzero pattern of a row of L //------------------------------------------------------------------------------ // Find the nonzero pattern of x for the system Lx=b where L = (0:k-1,0:k-1) // and b = kth column of A or A*A' (rows 0 to k-1 only) int cholmod_row_subtree ( // input: cholmod_sparse *A, // matrix to analyze cholmod_sparse *F, // used for A*A' case only. F=A' or A(:,f)' size_t krow, // row k of L int32_t *Parent, // elimination tree // output: cholmod_sparse *R, // pattern of L(k,:), 1-by-n with R->nzmax >= n cholmod_common *Common ) ; int cholmod_l_row_subtree (cholmod_sparse *, cholmod_sparse *, size_t, int64_t *, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_lsolve_pattern: find the nonzero pattern of y=L\b //------------------------------------------------------------------------------ int cholmod_lsolve_pattern ( // input: cholmod_sparse *B, // sparse right-hand-side (a single sparse column) cholmod_factor *L, // the factor L from which parent(i) is derived // output: cholmod_sparse *Yset, // pattern of Y=L\B, n-by-1 with Y->nzmax >= n cholmod_common *Common ) ; int cholmod_l_lsolve_pattern (cholmod_sparse *, cholmod_factor *, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_row_lsubtree: find the nonzero pattern of a row of L //------------------------------------------------------------------------------ // Identical to cholmod_row_subtree, except that it finds the elimination tree // from L itself. int cholmod_row_lsubtree ( // input: cholmod_sparse *A, // matrix to analyze int32_t *Fi, // nonzero pattern of kth row of A', not required // for the symmetric case. Need not be sorted. size_t fnz, // size of Fi size_t krow, // row k of L cholmod_factor *L, // the factor L from which parent(i) is derived // output: cholmod_sparse *R, // pattern of L(k,:), n-by-1 with R->nzmax >= n cholmod_common *Common ) ; int cholmod_l_row_lsubtree (cholmod_sparse *, int64_t *, size_t, size_t, cholmod_factor *, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_resymbol: recompute the symbolic pattern of L //------------------------------------------------------------------------------ // Remove entries from L that are not in the factorization of P*A*P', P*A*A'*P', // or P*F*F'*P' (depending on A->stype and whether fset is NULL or not). // // cholmod_resymbol is the same as cholmod_resymbol_noperm, except that it // first permutes A according to L->Perm. A can be upper/lower/unsymmetric, // in contrast to cholmod_resymbol_noperm (which can be lower or unsym). int cholmod_resymbol // recompute symbolic pattern of L ( // input: cholmod_sparse *A, // matrix to analyze int *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int pack, // if TRUE, pack the columns of L // input/output: cholmod_factor *L, // factorization, entries pruned on output cholmod_common *Common ) ; int cholmod_l_resymbol (cholmod_sparse *, int64_t *, size_t, int, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_resymbol_noperm: recompute the symbolic pattern of L, no L->Perm //------------------------------------------------------------------------------ // Remove entries from L that are not in the factorization of A, A*A', // or F*F' (depending on A->stype and whether fset is NULL or not). int cholmod_resymbol_noperm ( // input: cholmod_sparse *A, // matrix to analyze int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int pack, // if TRUE, pack the columns of L // input/output: cholmod_factor *L, // factorization, entries pruned on output cholmod_common *Common ) ; int cholmod_l_resymbol_noperm (cholmod_sparse *, int64_t *, size_t, int, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rcond: compute rough estimate of reciprocal of condition number //------------------------------------------------------------------------------ double cholmod_rcond // return rcond estimate ( // input: cholmod_factor *L, // factorization to query; not modified cholmod_common *Common ) ; double cholmod_l_rcond (cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_postorder: Compute the postorder of a tree //------------------------------------------------------------------------------ int32_t cholmod_postorder // return # of nodes postordered ( // input: int32_t *Parent, // size n. Parent [j] = p if p is the parent of j size_t n, int32_t *Weight, // size n, optional. Weight [j] is weight of node j // output: int32_t *Post, // size n. Post [k] = j is kth in postordered tree cholmod_common *Common ) ; int64_t cholmod_l_postorder (int64_t *, size_t, int64_t *, int64_t *, cholmod_common *) ; #endif /* !defined(R_MATRIX_CHOLMOD_H) */ //============================================================================== // CHOLMOD:MatrixOps Module //============================================================================== // Basic operations on sparse and dense matrices. // // cholmod_drop A = entries in A with abs. value >= tol // cholmod_norm_dense s = norm (X), 1-norm, inf-norm, or 2-norm // cholmod_norm_sparse s = norm (A), 1-norm or inf-norm // cholmod_horzcat C = [A,B] // cholmod_scale A = diag(s)*A, A*diag(s), s*A or diag(s)*A*diag(s) // cholmod_sdmult Y = alpha*(A*X) + beta*Y or alpha*(A'*X) + beta*Y // cholmod_ssmult C = A*B // cholmod_submatrix C = A (i,j), where i and j are arbitrary vectors // cholmod_vertcat C = [A ; B] // // A, B, C: sparse matrices (cholmod_sparse) // X, Y: dense matrices (cholmod_dense) // s: scalar or vector // // Requires the Utility module. Not required by any other CHOLMOD module. #ifndef R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // cholmod_drop: drop entries with small absolute value //------------------------------------------------------------------------------ int cholmod_drop ( // input: double tol, // keep entries with absolute value > tol // input/output: cholmod_sparse *A, // matrix to drop entries from cholmod_common *Common ) ; int cholmod_l_drop (double, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_norm_dense: s = norm (X), 1-norm, inf-norm, or 2-norm //------------------------------------------------------------------------------ double cholmod_norm_dense // returns norm (X) ( // input: cholmod_dense *X, // matrix to compute the norm of int norm, // type of norm: 0: inf. norm, 1: 1-norm, 2: 2-norm cholmod_common *Common ) ; double cholmod_l_norm_dense (cholmod_dense *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_norm_sparse: s = norm (A), 1-norm or inf-norm //------------------------------------------------------------------------------ double cholmod_norm_sparse // returns norm (A) ( // input: cholmod_sparse *A, // matrix to compute the norm of int norm, // type of norm: 0: inf. norm, 1: 1-norm cholmod_common *Common ) ; double cholmod_l_norm_sparse (cholmod_sparse *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_horzcat: C = [A,B] //------------------------------------------------------------------------------ // C is returned as an unsymmetric matrix with C->stype of zero. If A and/or // B are symmetric, they are converted first to unsymmetric, and the conversion // is governed by the mode input parameter. cholmod_sparse *cholmod_horzcat // returns C = [A B] ( // input: cholmod_sparse *A, // left matrix to concatenate cholmod_sparse *B, // right matrix to concatenate int mode, // 2: numerical (conj) if A and/or B are symmetric, // 1: numerical (non-conj.) if A and/or B are symmetric. // 0: pattern cholmod_common *Common ) ; cholmod_sparse *cholmod_l_horzcat (cholmod_sparse *, cholmod_sparse *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_scale: A = diag(s)*A, A*diag(s), s*A or diag(s)*A*diag(s) //------------------------------------------------------------------------------ #endif /* !defined(R_MATRIX_CHOLMOD_H) */ // scaling modes, selected by the scale input parameter: #define CHOLMOD_SCALAR 0 /* A = s*A */ #define CHOLMOD_ROW 1 /* A = diag(s)*A */ #define CHOLMOD_COL 2 /* A = A*diag(s) */ #define CHOLMOD_SYM 3 /* A = diag(s)*A*diag(s) */ #ifndef R_MATRIX_CHOLMOD_H int cholmod_scale ( // input: cholmod_dense *S, // scale factors (scalar or vector) int scale, // type of scaling to compute // input/output: cholmod_sparse *A, // matrix to scale cholmod_common *Common ) ; int cholmod_l_scale (cholmod_dense *, int, cholmod_sparse *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_sdmult: Y = alpha*(A*X) + beta*Y or alpha*(A'*X) + beta*Y //------------------------------------------------------------------------------ // Sparse matrix times dense matrix int cholmod_sdmult ( // input: cholmod_sparse *A, // sparse matrix to multiply int transpose, // use A if 0, otherwise use A' double alpha [2], // scale factor for A double beta [2], // scale factor for Y cholmod_dense *X, // dense matrix to multiply // input/output: cholmod_dense *Y, // resulting dense matrix cholmod_common *Common ) ; int cholmod_l_sdmult (cholmod_sparse *, int, double [2], double [2], cholmod_dense *, cholmod_dense *Y, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_ssmult: C = A*B //------------------------------------------------------------------------------ // Sparse matrix times sparse matrix. // If A and/or B are symmetric, they are converted first to unsymmetric, and // the conversion is governed by the mode input parameter. cholmod_sparse *cholmod_ssmult // return C=A*B ( // input: cholmod_sparse *A, // left matrix to multiply cholmod_sparse *B, // right matrix to multiply int stype, // requested stype of C int mode, // 2: numerical (conj) if A and/or B are symmetric, // 1: numerical (non-conj.) if A and/or B are symmetric. // 0: pattern int sorted, // if TRUE then return C with sorted columns cholmod_common *Common ) ; cholmod_sparse *cholmod_l_ssmult (cholmod_sparse *, cholmod_sparse *, int, int, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_submatrix: C = A (r,c), where i and j are arbitrary vectors //------------------------------------------------------------------------------ // rsize < 0 denotes ":" in MATLAB notation, or more precisely 0:(A->nrow)-1. // In this case, r can be NULL. An rsize of zero, or r = NULL and rsize >= 0, // denotes "[ ]" in MATLAB notation (the empty set). // Similar rules hold for csize. // C is returned as an unsymmetric matrix with C->stype of zero. If A and/or // B are symmetric, they are converted first to unsymmetric, and the conversion // is governed by the mode input parameter. cholmod_sparse *cholmod_submatrix // return C = A (rset,cset) ( // input: cholmod_sparse *A, // matrix to subreference int32_t *rset, // set of row indices, duplicates OK int64_t rsize, // size of rset, or -1 for ":" int32_t *cset, // set of column indices, duplicates OK int64_t csize, // size of cset, or -1 for ":" int mode, // 2: numerical (conj) if A and/or B are symmetric, // 1: numerical (non-conj.) if A and/or B are symmetric. // 0: pattern int sorted, // if TRUE then return C with sorted columns cholmod_common *Common ) ; cholmod_sparse *cholmod_l_submatrix (cholmod_sparse *, int64_t *, int64_t, int64_t *, int64_t, int, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_vertcat: C = [A ; B] //------------------------------------------------------------------------------ // C is returned as an unsymmetric matrix with C->stype of zero. If A and/or // B are symmetric, they are converted first to unsymmetric, and the conversion // is governed by the mode input parameter. cholmod_sparse *cholmod_vertcat // returns C = [A ; B] ( // input: cholmod_sparse *A, // top matrix to concatenate cholmod_sparse *B, // bottom matrix to concatenate int mode, // 2: numerical (conj) if A and/or B are symmetric, // 1: numerical (non-conj.) if A and/or B are symmetric // 0: pattern cholmod_common *Common ) ; cholmod_sparse *cholmod_l_vertcat (cholmod_sparse *, cholmod_sparse *, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_symmetry: determine if a sparse matrix is symmetric //------------------------------------------------------------------------------ // return values of cholmod_symmetry and cholmod_write: // #define CHOLMOD_MM_RECTANGULAR 1 // #define CHOLMOD_MM_UNSYMMETRIC 2 // #define CHOLMOD_MM_SYMMETRIC 3 // #define CHOLMOD_MM_HERMITIAN 4 // #define CHOLMOD_MM_SKEW_SYMMETRIC 5 // #define CHOLMOD_MM_SYMMETRIC_POSDIAG 6 // #define CHOLMOD_MM_HERMITIAN_POSDIAG 7 int cholmod_symmetry // returns the matrix symmetry (see above) ( // input: cholmod_sparse *A, int option, // option 0, 1, or 2 // output: int32_t *xmatched, // # of matched numerical entries int32_t *pmatched, // # of matched entries in pattern int32_t *nzoffdiag, // # of off diagonal entries int32_t *nzdiag, // # of diagonal entries cholmod_common *Common ) ; int cholmod_l_symmetry (cholmod_sparse *, int, int64_t *, int64_t *, int64_t *, int64_t *, cholmod_common *) ; #endif /* !defined(R_MATRIX_CHOLMOD_H) */ //============================================================================== // CHOLMOD:Modify Module //============================================================================== //------------------------------------------------------------------------------ // CHOLMOD:Modify Module. Copyright (C) 2005-2023, Timothy A. Davis and William // W. Hager. http://www.suitesparse.com //------------------------------------------------------------------------------ // Sparse Cholesky modification routines: update / downdate / rowadd / rowdel. // Can also modify a corresponding solution to Lx=b when L is modified. This // module is most useful when applied on a Cholesky factorization computed by // the Cholesky module, but it does not actually require the Cholesky module. // The Utility module can create an identity Cholesky factorization (LDL' where // L=D=I) that can then by modified by these routines. // // Primary routines: // ----------------- // // cholmod_updown multiple rank update/downdate // cholmod_rowadd add a row to an LDL' factorization // cholmod_rowdel delete a row from an LDL' factorization // // Secondary routines: // ------------------- // // cholmod_updown_solve update/downdate, and modify solution to Lx=b // cholmod_updown_mark update/downdate, and modify solution to partial Lx=b // cholmod_updown_mask update/downdate for LPDASA // cholmod_updown_mask2 update/downdate for LPDASA // cholmod_rowadd_solve add a row, and update solution to Lx=b // cholmod_rowadd_mark add a row, and update solution to partial Lx=b // cholmod_rowdel_solve delete a row, and downdate Lx=b // cholmod_rowdel_mark delete a row, and downdate solution to partial Lx=b // // Requires the Utility module. Not required by any other CHOLMOD module. #ifndef R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // cholmod_updown: multiple rank update/downdate //------------------------------------------------------------------------------ // Compute the new LDL' factorization of LDL'+CC' (an update) or LDL'-CC' // (a downdate). The factor object L need not be an LDL' factorization; it // is converted to one if it isn't. int cholmod_updown // update/downdate ( // input: int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // the incoming sparse update // input/output: cholmod_factor *L, // factor to modify cholmod_common *Common ) ; int cholmod_l_updown (int, cholmod_sparse *, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_updown_solve: update/downdate, and modify solution to Lx=b //------------------------------------------------------------------------------ // Does the same as cholmod_updown, except that it also updates/downdates the // solution to Lx=b+DeltaB. x and b must be n-by-1 dense matrices. b is not // need as input to this routine, but a sparse change to b is (DeltaB). Only // entries in DeltaB corresponding to columns modified in L are accessed; the // rest must be zero. int cholmod_updown_solve ( // input: int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // the incoming sparse update // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; int cholmod_l_updown_solve (int, cholmod_sparse *, cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_updown_mark: update/downdate, and modify solution to partial Lx=b //------------------------------------------------------------------------------ // Does the same as cholmod_updown_solve, except only part of L is used in // the update/downdate of the solution to Lx=b. This routine is an "expert" // routine. It is meant for use in LPDASA only. See cholmod_updown.c for // a description of colmark. int cholmod_updown_mark ( // input: int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // the incoming sparse update int32_t *colmark, // array of size n. See cholmod_updown.c for details // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; int cholmod_l_updown_mark (int, cholmod_sparse *, int64_t *, cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_updown_mask: update/downdate, for LPDASA //------------------------------------------------------------------------------ // Does the same as cholmod_updown_mark, except has an additional "mask" // argument. This routine is an "expert" routine. It is meant for use in // LPDASA only. See cholmod_updown.c for a description of mask. int cholmod_updown_mask ( // input: int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // the incoming sparse update int32_t *colmark, // array of size n. See cholmod_updown.c for details int32_t *mask, // size n // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; int cholmod_l_updown_mask (int, cholmod_sparse *, int64_t *, int64_t *, cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; int cholmod_updown_mask2 ( // input: int update, // TRUE for update, FALSE for downdate cholmod_sparse *C, // the incoming sparse update int32_t *colmark, // array of size n. See cholmod_updown.c for details int32_t *mask, // size n int32_t maskmark, // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; int cholmod_l_updown_mask2 (int, cholmod_sparse *, int64_t *, int64_t *, int64_t, cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowadd: add a row to an LDL' factorization (a rank-2 update) //------------------------------------------------------------------------------ // cholmod_rowadd adds a row to the LDL' factorization. It computes the kth // row and kth column of L, and then updates the submatrix L (k+1:n,k+1:n) // accordingly. The kth row and column of L must originally be equal to the // kth row and column of the identity matrix. The kth row/column of L is // computed as the factorization of the kth row/column of the matrix to // factorize, which is provided as a single n-by-1 sparse matrix R. int cholmod_rowadd // add a row to an LDL' factorization ( // input: size_t k, // row/column index to add cholmod_sparse *R, // row/column of matrix to factorize (n-by-1) // input/output: cholmod_factor *L, // factor to modify cholmod_common *Common ) ; int cholmod_l_rowadd (size_t, cholmod_sparse *, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowadd_solve: add a row, and update solution to Lx=b //------------------------------------------------------------------------------ // Does the same as cholmod_rowadd, and also updates the solution to Lx=b // See cholmod_updown for a description of how Lx=b is updated. There is on // additional parameter: bk specifies the new kth entry of b. int cholmod_rowadd_solve ( // input: size_t k, // row/column index to add cholmod_sparse *R, // row/column of matrix to factorize (n-by-1) double bk [2], // kth entry of the right-hand-side b // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; int cholmod_l_rowadd_solve (size_t, cholmod_sparse *, double [2], cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowadd_mark: add a row, and update solution to partial Lx=b //------------------------------------------------------------------------------ // Does the same as cholmod_rowadd_solve, except only part of L is used in // the update/downdate of the solution to Lx=b. This routine is an "expert" // routine. It is meant for use in LPDASA only. int cholmod_rowadd_mark ( // input: size_t k, // row/column index to add cholmod_sparse *R, // row/column of matrix to factorize (n-by-1) double bk [2], // kth entry of the right hand side, b int32_t *colmark, // int32_t array of size 1. See cholmod_updown.c // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; int cholmod_l_rowadd_mark (size_t, cholmod_sparse *, double [2], int64_t *, cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowdel: delete a row from an LDL' factorization (a rank-2 update) //------------------------------------------------------------------------------ // Sets the kth row and column of L to be the kth row and column of the identity // matrix, and updates L(k+1:n,k+1:n) accordingly. To reduce the running time, // the caller can optionally provide the nonzero pattern (or an upper bound) of // kth row of L, as the sparse n-by-1 vector R. Provide R as NULL if you want // CHOLMOD to determine this itself, which is easier for the caller, but takes // a little more time. int cholmod_rowdel // delete a rw from an LDL' factorization ( // input: size_t k, // row/column index to delete cholmod_sparse *R, // NULL, or the nonzero pattern of kth row of L // input/output: cholmod_factor *L, // factor to modify cholmod_common *Common ) ; int cholmod_l_rowdel (size_t, cholmod_sparse *, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowdel_solve: delete a row, and downdate Lx=b //------------------------------------------------------------------------------ // Does the same as cholmod_rowdel, but also downdates the solution to Lx=b. // When row/column k of A is "deleted" from the system A*y=b, this can induce // a change to x, in addition to changes arising when L and b are modified. // If this is the case, the kth entry of y is required as input (yk). int cholmod_rowdel_solve ( // input: size_t k, // row/column index to delete cholmod_sparse *R, // NULL, or the nonzero pattern of kth row of L double yk [2], // kth entry in the solution to A*y=b // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; int cholmod_l_rowdel_solve (size_t, cholmod_sparse *, double [2], cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_rowdel_mark: delete a row, and downdate solution to partial Lx=b //------------------------------------------------------------------------------ // Does the same as cholmod_rowdel_solve, except only part of L is used in // the update/downdate of the solution to Lx=b. This routine is an "expert" // routine. It is meant for use in LPDASA only. int cholmod_rowdel_mark ( // input: size_t k, // row/column index to delete cholmod_sparse *R, // NULL, or the nonzero pattern of kth row of L double yk [2], // kth entry in the solution to A*y=b int32_t *colmark, // int32_t array of size 1. See cholmod_updown.c // input/output: cholmod_factor *L, // factor to modify cholmod_dense *X, // solution to Lx=b (size n-by-1) cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; int cholmod_l_rowdel_mark (size_t, cholmod_sparse *, double [2], int64_t *, cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; #endif /* !defined(R_MATRIX_CHOLMOD_H) */ //============================================================================== // CHOLMOD:Partition Module (CAMD, CCOLAMD, and CSYMAMD) //============================================================================== //------------------------------------------------------------------------------ // CHOLMOD/Partition: // Copyright (C) 2005-2023, Univ. of Florida. Author: Timothy A. Davis //------------------------------------------------------------------------------ // CHOLMOD Partition module, interface to CAMD, CCOLAMD, CSYMAMD, and METIS, // and graph partitioning and graph-partition-based orderings. Includes an // interface to CCOLAMD and CSYMAMD, constrained minimum degree ordering // methods which order a matrix following constraints determined via nested // dissection. // // These functions do not require METIS. They are installed unless NCAMD // is defined: // cholmod_ccolamd interface to CCOLAMD ordering // cholmod_csymamd interface to CSYMAMD ordering // cholmod_camd interface to CAMD ordering // // These functions require METIS: // cholmod_nested_dissection CHOLMOD nested dissection ordering // cholmod_metis METIS nested dissection ordering (METIS_NodeND) // cholmod_bisect graph partitioner (currently based on METIS) // cholmod_metis_bisector direct interface to METIS_ComputeVertexSeparator // // Requires the Utility and Cholesky modules, and three packages: METIS, CAMD, // and CCOLAMD. Optionally used by the Cholesky module. #ifndef R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // cholmod_ccolamd //------------------------------------------------------------------------------ // Order AA' or A(:,f)*A(:,f)' using CCOLAMD. int cholmod_ccolamd ( // input: cholmod_sparse *A, // matrix to order int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int32_t *Cmember, // size A->nrow. Cmember [i] = c if row i is in the // constraint set c. c must be >= 0. The # of // constraint sets is max (Cmember) + 1. If Cmember is // NULL, then it is interpretted as Cmember [i] = 0 for // all i. // output: int32_t *Perm, // size A->nrow, output permutation cholmod_common *Common ) ; int cholmod_l_ccolamd (cholmod_sparse *, int64_t *, size_t, int64_t *, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_csymamd //------------------------------------------------------------------------------ // Order A using CSYMAMD. int cholmod_csymamd ( // input: cholmod_sparse *A, // matrix to order // output: int32_t *Cmember, // size nrow. see cholmod_ccolamd.c for description int32_t *Perm, // size A->nrow, output permutation cholmod_common *Common ) ; int cholmod_l_csymamd (cholmod_sparse *, int64_t *, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_camd: order A using CAMD //------------------------------------------------------------------------------ int cholmod_camd ( // input: cholmod_sparse *A, // matrix to order int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int32_t *Cmember, // size nrow. see cholmod_ccolamd.c for description. // output: int32_t *Perm, // size A->nrow, output permutation cholmod_common *Common ) ; int cholmod_l_camd (cholmod_sparse *, int64_t *, size_t, int64_t *, int64_t *, cholmod_common *) ; #endif /* !defined(R_MATRIX_CHOLMOD_H) */ //------------------------------------------------------------------------------ // CHOLMOD:Partition Module (graph partition methods) //------------------------------------------------------------------------------ // These routines still exist if CHOLMOD is compiled with -DNPARTITION, // but they return Common->status = CHOLMOD_NOT_INSTALLED in that case. #ifndef R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // cholmod_nested_dissection //------------------------------------------------------------------------------ // Order A, AA', or A(:,f)*A(:,f)' using CHOLMOD's nested dissection method // (METIS's node bisector applied recursively to compute the separator tree // and constraint sets, followed by CCOLAMD using the constraints). Usually // finds better orderings than METIS_NodeND, but takes longer. int64_t cholmod_nested_dissection // returns # of components, or -1 if error ( // input: cholmod_sparse *A, // matrix to order int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset // output: int32_t *Perm, // size A->nrow, output permutation int32_t *CParent, // size A->nrow. On output, CParent [c] is the parent // of component c, or EMPTY if c is a root, and where // c is in the range 0 to # of components minus 1 int32_t *Cmember, // size A->nrow. Cmember [j] = c if node j of A is // in component c cholmod_common *Common ) ; int64_t cholmod_l_nested_dissection (cholmod_sparse *, int64_t *, size_t, int64_t *, int64_t *, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_metis //------------------------------------------------------------------------------ // Order A, AA', or A(:,f)*A(:,f)' using METIS_NodeND. int cholmod_metis ( // input: cholmod_sparse *A, // matrix to order int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int postorder, // if TRUE, follow with etree or coletree postorder // output: int32_t *Perm, // size A->nrow, output permutation cholmod_common *Common ) ; int cholmod_l_metis (cholmod_sparse *, int64_t *, size_t, int, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_bisect //------------------------------------------------------------------------------ // Finds a node bisector of A, A*A', A(:,f)*A(:,f)'. int64_t cholmod_bisect // returns # of nodes in separator ( // input: cholmod_sparse *A, // matrix to bisect int32_t *fset, // subset of 0:(A->ncol)-1 size_t fsize, // size of fset int compress, // if TRUE, compress the graph first // output: int32_t *Partition, // size A->nrow. Node i is in the left graph if // Partition [i] = 0, the right graph if 1, and in the // separator if 2. cholmod_common *Common ) ; int64_t cholmod_l_bisect (cholmod_sparse *, int64_t *, size_t, int, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_metis_bisector //------------------------------------------------------------------------------ // Find a set of nodes that bisects the graph of A or AA' (direct interface // to METIS_ComputeVertexSeperator). int64_t cholmod_metis_bisector // returns separator size ( // input: cholmod_sparse *A, // matrix to bisect int32_t *Anw, // size A->nrow, node weights, can be NULL, // which means the graph is unweighted. int32_t *Aew, // size nz, edge weights (silently ignored). // This option was available with METIS 4, but not // in METIS 5. This argument is now unused, but // it remains for backward compatibilty, so as not // to change the API for cholmod_metis_bisector. // output: int32_t *Partition, // size A->nrow cholmod_common *Common ) ; int64_t cholmod_l_metis_bisector (cholmod_sparse *, int64_t *, int64_t *, int64_t *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_collapse_septree //------------------------------------------------------------------------------ // Collapse nodes in a separator tree. int64_t cholmod_collapse_septree ( // input: size_t n, // # of nodes in the graph size_t ncomponents, // # of nodes in the separator tree (must be <= n) double nd_oksep, // collapse if #sep >= nd_oksep * #nodes in subtree size_t nd_small, // collapse if #nodes in subtree < nd_small // output: int32_t *CParent, // size ncomponents; from cholmod_nested_dissection int32_t *Cmember, // size n; from cholmod_nested_dissection cholmod_common *Common ) ; int64_t cholmod_l_collapse_septree (size_t, size_t, double, size_t, int64_t *, int64_t *, cholmod_common *) ; #endif /* !defined(R_MATRIX_CHOLMOD_H) */ //============================================================================== // CHOLMOD:Supernodal Module //============================================================================== // Supernodal analysis, factorization, and solve. The simplest way to use // these routines is via the Cholesky module. It does not provide any // fill-reducing orderings, but does accept the orderings computed by the // Cholesky module. It does not require the Cholesky module itself, however. // // Primary routines: // ----------------- // cholmod_super_symbolic supernodal symbolic analysis // cholmod_super_numeric supernodal numeric factorization // cholmod_super_lsolve supernodal Lx=b solve // cholmod_super_ltsolve supernodal L'x=b solve // // Prototypes for the BLAS and LAPACK routines that CHOLMOD uses are listed // below, including how they are used in CHOLMOD. Only the double methods are // listed, but CHOLMOD also uses the corresponding single, single complex, and // double complex routines. // // BLAS routines: // -------------- // dtrsv solve Lx=b or L'x=b, L non-unit diagonal, x and b stride-1 // dtrsm solve LX=B or L'X=b, L non-unit diagonal // dgemv y=y-A*x or y=y-A'*x (x and y stride-1) // dgemm C=A*B', C=C-A*B, or C=C-A'*B // dsyrk C=tril(A*A'), zherk for the double complex case // // LAPACK routines: // ---------------- // dpotrf LAPACK: A=chol(tril(A)) // // Requires the Utility module, and two external packages: LAPACK and the BLAS. // Optionally used by the Cholesky module. #ifndef R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // cholmod_super_symbolic //------------------------------------------------------------------------------ // Analyzes A, AA', or A(:,f)*A(:,f)' in preparation for a supernodal numeric // factorization. The user need not call this directly; cholmod_analyze is // a "simple" wrapper for this routine. int cholmod_super_symbolic ( // input: cholmod_sparse *A, // matrix to analyze cholmod_sparse *F, // F = A' or A(:,f)' int32_t *Parent, // elimination tree // input/output: cholmod_factor *L, // simplicial symbolic on input, // supernodal symbolic on output cholmod_common *Common ) ; int cholmod_l_super_symbolic (cholmod_sparse *, cholmod_sparse *, int64_t *, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_super_symbolic2 //------------------------------------------------------------------------------ // Analyze for supernodal Cholesky or multifrontal QR #endif /* !defined(R_MATRIX_CHOLMOD_H) */ #define CHOLMOD_ANALYZE_FOR_SPQR 0 #define CHOLMOD_ANALYZE_FOR_CHOLESKY 1 #define CHOLMOD_ANALYZE_FOR_SPQRGPU 2 #ifndef R_MATRIX_CHOLMOD_H int cholmod_super_symbolic2 ( // input: int for_whom, // FOR_SPQR (0): for SPQR but not GPU-accelerated // FOR_CHOLESKY (1): for Cholesky (GPU or not) // FOR_SPQRGPU (2): for SPQR with GPU acceleration cholmod_sparse *A, // matrix to analyze cholmod_sparse *F, // F = A' or A(:,f)' int32_t *Parent, // elimination tree // input/output: cholmod_factor *L, // simplicial symbolic on input, // supernodal symbolic on output cholmod_common *Common ) ; int cholmod_l_super_symbolic2 (int, cholmod_sparse *, cholmod_sparse *, int64_t *, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_super_numeric //------------------------------------------------------------------------------ // Computes the numeric LL' factorization of A, AA', or A(:,f)*A(:,f)' using // a BLAS-based supernodal method. The user need not call this directly; // cholmod_factorize is a "simple" wrapper for this routine. int cholmod_super_numeric ( // input: cholmod_sparse *A, // matrix to factorize cholmod_sparse *F, // F = A' or A(:,f)' double beta [2], // beta*I is added to diagonal of matrix to factorize // input/output: cholmod_factor *L, // factorization cholmod_common *Common ) ; int cholmod_l_super_numeric (cholmod_sparse *, cholmod_sparse *, double [2], cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_super_lsolve //------------------------------------------------------------------------------ // Solve Lx=b where L is from a supernodal numeric factorization. The user // need not call this routine directly. cholmod_solve is a "simple" wrapper // for this routine. int cholmod_super_lsolve ( // input: cholmod_factor *L, // factor to use for the forward solve // input/output: cholmod_dense *X, // b on input, solution to Lx=b on output // workspace: cholmod_dense *E, // workspace of size nrhs*(L->maxesize) cholmod_common *Common ) ; int cholmod_l_super_lsolve (cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_super_ltsolve //------------------------------------------------------------------------------ // Solve L'x=b where L is from a supernodal numeric factorization. The user // need not call this routine directly. cholmod_solve is a "simple" wrapper // for this routine. int cholmod_super_ltsolve ( // input: cholmod_factor *L, // factor to use for the backsolve // input/output: cholmod_dense *X, // b on input, solution to L'x=b on output // workspace: cholmod_dense *E, // workspace of size nrhs*(L->maxesize) cholmod_common *Common ) ; int cholmod_l_super_ltsolve (cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; #endif /* !defined(R_MATRIX_CHOLMOD_H) */ #ifdef __cplusplus } #endif //============================================================================== // CHOLMOD:SupernodalGPU Module //============================================================================== //------------------------------------------------------------------------------ // cholmod_score_comp: for sorting descendant supernodes with qsort //------------------------------------------------------------------------------ #ifdef __cplusplus extern "C" { #endif typedef struct cholmod_descendant_score_t { double score ; int64_t d ; } descendantScore ; #ifndef R_MATRIX_CHOLMOD_H int cholmod_score_comp (struct cholmod_descendant_score_t *i, struct cholmod_descendant_score_t *j) ; int cholmod_l_score_comp (struct cholmod_descendant_score_t *i, struct cholmod_descendant_score_t *j) ; #endif /* !defined(R_MATRIX_CHOLMOD_H) */ #ifdef __cplusplus } #endif //------------------------------------------------------------------------------ // remainder of SupernodalGPU Module //------------------------------------------------------------------------------ #ifdef CHOLMOD_HAS_CUDA #include "omp.h" #include #ifndef SUITESPARSE_GPU_EXTERN_ON #include #include #endif // CHOLMOD_GPU_PRINTF: for printing GPU debug error messages // #define CHOLMOD_GPU_PRINTF(args) printf args #define CHOLMOD_GPU_PRINTF(args) // define supernode requirements for processing on GPU #define CHOLMOD_ND_ROW_LIMIT 256 /* required descendant rows */ #define CHOLMOD_ND_COL_LIMIT 32 /* required descendnat cols */ #define CHOLMOD_POTRF_LIMIT 512 /* required cols for POTRF & TRSM on GPU */ // # of host supernodes to perform before checking for free pinned buffers #define CHOLMOD_GPU_SKIP 3 #define CHOLMOD_HANDLE_CUDA_ERROR(e,s) {if (e) {ERROR(CHOLMOD_GPU_PROBLEM,s);}} #ifdef __cplusplus extern "C" { #endif typedef struct cholmod_gpu_pointers { double *h_Lx [CHOLMOD_HOST_SUPERNODE_BUFFERS] ; double *d_Lx [CHOLMOD_DEVICE_STREAMS] ; double *d_C ; double *d_A [CHOLMOD_DEVICE_STREAMS] ; void *d_Ls ; void *d_Map ; void *d_RelativeMap ; } cholmod_gpu_pointers ; #ifndef R_MATRIX_CHOLMOD_H int cholmod_gpu_memorysize // GPU memory size available, 1 if no GPU ( size_t *total_mem, size_t *available_mem, cholmod_common *Common ) ; int cholmod_l_gpu_memorysize // GPU memory size available, 1 if no GPU ( size_t *total_mem, size_t *available_mem, cholmod_common *Common ) ; int cholmod_gpu_probe ( cholmod_common *Common ) ; int cholmod_l_gpu_probe ( cholmod_common *Common ) ; int cholmod_gpu_deallocate ( cholmod_common *Common ) ; int cholmod_l_gpu_deallocate ( cholmod_common *Common ) ; int cholmod_gpu_start ( cholmod_common *Common ) ; int cholmod_l_gpu_start ( cholmod_common *Common ) ; void cholmod_gpu_end ( cholmod_common *Common ) ; void cholmod_l_gpu_end ( cholmod_common *Common ) ; int cholmod_gpu_allocate ( cholmod_common *Common ) ; int cholmod_l_gpu_allocate ( cholmod_common *Common ) ; #endif /* !defined(R_MATRIX_CHOLMOD_H) */ #ifdef __cplusplus } #endif #endif /* <<<< Matrix <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ /* We declare a minimal subset of the above as "API" : */ #ifndef R_MATRIX_CHOLMOD # define R_MATRIX_CHOLMOD(_NAME_) M_cholmod_ ## _NAME_ #endif #ifndef R_MATRIX_INLINE # define R_MATRIX_INLINE #endif #ifdef __cplusplus extern "C" { #endif typedef cholmod_common * CHM_CM; typedef cholmod_factor * CHM_FR; typedef cholmod_sparse * CHM_SP; typedef cholmod_triplet * CHM_TR; typedef cholmod_dense * CHM_DN; R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(aat)( CHM_SP, int *, size_t, int, CHM_CM); R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(add)( CHM_SP, CHM_SP, double[2], double[2], int, int, CHM_CM); R_MATRIX_INLINE CHM_DN R_MATRIX_CHOLMOD(allocate_dense)( size_t, size_t, size_t, int, CHM_CM); R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(allocate_sparse)( size_t, size_t, size_t, int, int, int, int, CHM_CM); R_MATRIX_INLINE CHM_TR R_MATRIX_CHOLMOD(allocate_triplet)( size_t, size_t, size_t, int, int, CHM_CM); R_MATRIX_INLINE CHM_FR R_MATRIX_CHOLMOD(analyze)( CHM_SP, CHM_CM); R_MATRIX_INLINE CHM_FR R_MATRIX_CHOLMOD(analyze_p)( CHM_SP, int *, int *, size_t, CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(band_inplace)( int, int, int, CHM_SP, CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(change_factor)( int, int, int, int, int, CHM_FR, CHM_CM); R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(copy)( CHM_SP, int, int, CHM_CM); R_MATRIX_INLINE CHM_DN R_MATRIX_CHOLMOD(copy_dense)( CHM_DN, CHM_CM); R_MATRIX_INLINE CHM_FR R_MATRIX_CHOLMOD(copy_factor)( CHM_FR, CHM_CM); R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(copy_sparse)( CHM_SP, CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(defaults)( CHM_CM); R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(dense_to_sparse)( CHM_DN, int, CHM_CM); R_MATRIX_INLINE void R_MATRIX_CHOLMOD(error_handler)( int, const char *, int, const char *); R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(factor_to_sparse )( CHM_FR, CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(factorize)( CHM_SP, CHM_FR, CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(factorize_p)( CHM_SP, double[2], int *, size_t, CHM_FR, CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(finish)( CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(free_dense)( CHM_DN *, CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(free_factor)( CHM_FR *, CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(free_sparse)( CHM_SP *, CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(free_triplet)( CHM_TR *, CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(nnz)( CHM_SP, CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(scale)( CHM_DN, int, CHM_SP, CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(sdmult)( CHM_SP, int, double[2], double[2], CHM_DN, CHM_DN, CHM_CM); R_MATRIX_INLINE CHM_DN R_MATRIX_CHOLMOD(solve)( int, CHM_FR, CHM_DN, CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(solve2)( int, CHM_FR, CHM_DN, CHM_DN *, CHM_DN *, CHM_DN *, CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(sort)( CHM_SP, CHM_CM); R_MATRIX_INLINE CHM_DN R_MATRIX_CHOLMOD(sparse_to_dense)( CHM_SP, CHM_CM); R_MATRIX_INLINE CHM_TR R_MATRIX_CHOLMOD(sparse_to_triplet)( CHM_SP, CHM_CM); R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(speye)( size_t, size_t, int, CHM_CM); R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(spsolve)( int, CHM_FR, CHM_SP, CHM_CM); R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(ssmult)( CHM_SP, CHM_SP, int, int, int, CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(start)( CHM_CM); R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(submatrix)( CHM_SP, int *, int, int *, int, int, int, CHM_CM); R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(transpose)( CHM_SP, int, CHM_CM); R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(triplet_to_sparse)( CHM_TR, int, CHM_CM); R_MATRIX_INLINE int R_MATRIX_CHOLMOD(updown)( int, CHM_SP, CHM_FR, CHM_CM); R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(vertcat)( CHM_SP, CHM_SP, int, CHM_CM); #ifdef __cplusplus } #endif /* >>>> Matrix >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */ #endif /* !defined(R_MATRIX_CHOLMOD_H) */ Matrix/inst/include/Matrix/version.h0000644000175100001440000000123514561103552017241 0ustar hornikusers#ifndef R_MATRIX_VERSION_H #define R_MATRIX_VERSION_H /* Users wanting to do version comparison will include Rversion.h then do, */ /* e.g., R_MATRIX_PACKAGE_VERSION R_version(major, minor, patch) : */ /* (version)_{10} = (major minor patch)_{256} */ #define R_MATRIX_PACKAGE_VERSION 67328 #define R_MATRIX_PACKAGE_MAJOR 1 #define R_MATRIX_PACKAGE_MINOR 7 #define R_MATRIX_PACKAGE_PATCH 0 #define R_MATRIX_ABI_VERSION 2 /* (version)_{10} = (major minor patch)_{256} */ #define R_MATRIX_SUITESPARSE_VERSION 460288 #define R_MATRIX_SUITESPARSE_MAJOR 7 #define R_MATRIX_SUITESPARSE_MINOR 6 #define R_MATRIX_SUITESPARSE_PATCH 0 #endif /* R_MATRIX_VERSION_H */ Matrix/inst/include/Matrix/cholmod-utils.h0000644000175100001440000000211214531175657020346 0ustar hornikusers#ifndef R_MATRIX_CHOLMOD_UTILS_H #define R_MATRIX_CHOLMOD_UTILS_H #include #include "cholmod.h" #ifdef __cplusplus extern "C" { #endif #ifndef R_MATRIX_INLINE # define R_MATRIX_INLINE #endif R_MATRIX_INLINE CHM_FR M_sexp_as_cholmod_factor( CHM_FR, SEXP); R_MATRIX_INLINE CHM_SP M_sexp_as_cholmod_sparse( CHM_SP, SEXP, Rboolean, Rboolean); R_MATRIX_INLINE CHM_TR M_sexp_as_cholmod_triplet( CHM_TR, SEXP, Rboolean); R_MATRIX_INLINE CHM_DN M_sexp_as_cholmod_dense( CHM_DN, SEXP); R_MATRIX_INLINE CHM_DN M_numeric_as_cholmod_dense( CHM_DN, double *, int, int); R_MATRIX_INLINE SEXP M_cholmod_factor_as_sexp( CHM_FR, int); R_MATRIX_INLINE SEXP M_cholmod_sparse_as_sexp( CHM_SP, int, int, int, const char *, SEXP); R_MATRIX_INLINE SEXP M_cholmod_triplet_as_sexp( CHM_TR, int, int, int, const char *, SEXP); R_MATRIX_INLINE SEXP M_cholmod_dense_as_sexp( CHM_DN, int); R_MATRIX_INLINE double M_cholmod_factor_ldetA( CHM_FR); R_MATRIX_INLINE CHM_FR M_cholmod_factor_update( CHM_FR, CHM_SP, double); #ifdef __cplusplus } #endif #endif /* R_MATRIX_CHOLMOD_UTILS_H */ Matrix/inst/include/Matrix/remap.h0000644000175100001440000000115314531175657016673 0ustar hornikusers#ifndef R_MATRIX_REMAP_H #define R_MATRIX_REMAP_H /* MJ: backwards compatibility with Matrix < 1.6-2 */ #define M_as_cholmod_sparse M_sexp_as_cholmod_sparse #define M_as_cholmod_dense M_sexp_as_cholmod_dense #define M_chm_factor_to_SEXP M_cholmod_factor_as_sexp #define M_chm_sparse_to_SEXP M_cholmod_sparse_as_sexp #define M_chm_triplet_to_SEXP M_cholmod_triplet_as_sexp #define M_chm_factor_ldetL2 M_cholmod_factor_ldetA #define M_chm_factor_update M_cholmod_factor_update #define M_R_cholmod_error M_cholmod_error_handler #define M_R_cholmod_start M_cholmod_start #endif /* R_MATRIX_REMAP_H */ Matrix/inst/include/Matrix/alloca.h0000644000175100001440000000240714510651525017013 0ustar hornikusers#ifndef R_MATRIX_ALLOCA_H #define R_MATRIX_ALLOCA_H /* MJ: alloca-using macros (currently opt-out, eventually opt-in) */ /* Copy and paste from Defn.h : */ /* 'alloca' is neither C99 nor POSIX */ #ifdef __GNUC__ /* This covers GNU, Clang and Intel compilers */ /* #undef needed in case some other header, e.g. malloc.h, already did this */ # undef alloca # define alloca(x) __builtin_alloca((x)) #else # ifdef HAVE_ALLOCA_H /* This covers native compilers on Solaris and AIX */ # include # endif /* It might have been defined via some other standard header, e.g. stdlib.h */ # if !HAVE_DECL_ALLOCA extern void *alloca(size_t); # endif #endif #define AS_CHM_FR(x) \ M_sexp_as_cholmod_factor((CHM_FR) alloca(sizeof(cholmod_factor)), x) #define AS_CHM_SP(x) \ M_sexp_as_cholmod_sparse((CHM_SP) alloca(sizeof(cholmod_sparse)), x, \ (Rboolean) 1, (Rboolean) 0) #define AS_CHM_SP__(x) \ M_sexp_as_cholmod_sparse((CHM_SP) alloca(sizeof(cholmod_sparse)), x, \ (Rboolean) 0, (Rboolean) 0) #define AS_CHM_DN(x) \ M_sexp_as_cholmod_dense ((CHM_DN) alloca(sizeof(cholmod_dense )), x) #define N_AS_CHM_DN(x, m, n) \ M_numeric_as_cholmod_dense((CHM_DN) alloca(sizeof(cholmod_dense)), x, m, n) #endif /* R_MATRIX_ALLOCA_H */ Matrix/inst/include/Matrix_stubs.c0000644000175100001440000000033114511523670016765 0ustar hornikusers/* For backwards compatibility only. Packages should start using */ /* LinkingTo: Matrix (>= 1.6-2) and #include . */ #include "Matrix/alloca.h" #include "Matrix/remap.h" #include "Matrix/stubs.c" Matrix/inst/external/0000755000175100001440000000000014576343415014347 5ustar hornikusersMatrix/inst/external/utm300.rua0000644000175100001440000024553510275433311016111 0ustar hornikusersUTM300 UTM300 1290 16 122 1052 100 RUA 300 300 3155 1 (20I4) (26I3) (3D21.15) (3D21.15) FNN 1 1 3 9 13 17 20 22 28 32 36 44 46 52 56 60 68 69 70 72 74 82 83 84 86 88 96 97 98 100 102 110 111 112 114 116 124 126 132 136 140 148 150 156 160 164 172 174 178 182 186 189 191 196 201 208 217 225 242 257 279 297 306 324 339 355 374 382 399 415 431 451 458 475 491 511 531 538 555 571 591 611 619 637 653 669 689 697 714 729 744 763 771 775 790 812 831 833 837 842 849 858 860 865 870 877 886 895 912 928 950 970 979 9971013103110511060107710931111 11311140115711731195121512241241125712791299130813261342136013801389140614221440 14601469147314891511153115331537154215491558156015651570157715861594161116271649 16691677169417101732175217611778179418161836184518621878190019201929194619621984 20042013203020462068208820972114213021522172218021842200222222422244224822532260 22692271227622812288229723052322233723592379238724042419244124612470248725022524 25442553257025852607262726362653266826902710271927362751277327922800281728322854 28742883288729022924294329452949295429612970297229782980298229852987299329952997 30053007301330153017302530273033303530373045304730533055305730653067307330753077 30853087309330953097310431063112311431163124312631323134313631433145314931513153 3156 1 51 1 2 6 51 52 56 1 3 51 53 1 4 51 54 5 10 55 6 56 6 7 11 56 57 61 6 8 56 58 6 9 56 59 6 8 9 10 56 58 59 60 11 61 11 12 36 61 62 86 11 13 61 63 11 14 61 64 11 13 14 15 61 63 64 65 16 17 16 18 16 19 16 18 19 20 66 68 69 70 21 22 21 23 21 24 21 23 24 25 71 73 74 75 26 27 26 28 26 29 26 28 29 30 76 78 79 80 31 32 31 33 31 34 31 33 34 35 81 83 84 85 36 86 36 37 41 86 87 91 36 38 86 88 36 39 86 89 36 38 39 40 86 88 89 90 41 91 41 42 46 91 92 96 41 43 91 93 41 44 91 94 41 43 44 45 91 93 94 95 46 96 46 47 96 97 46 48 96 98 46 49 96 99 45 50100 51 56 51 52 53 54 56 51 52 53 56 58 51 52 54 56 57 59 61 51 52 53 54 55 56 58 59 60 6 51 52 56 57 58 60106 6 7 11 51 52 56 57 58 59 61 62 63 64 86106107111 6 8 51 52 53 56 57 58 59 60 61 63106108109 1 2 6 7 9 11 51 52 54 56 57 58 59 60 61 64101102106107109111 6 9 10 51 54 55 56 58 59 60 61 63 64 65106108109110 11 56 57 61 62 63 65 86111 11 12 36 56 57 61 62 63 64 86 87 88 89 91111112116136 11 13 56 57 58 61 62 63 64 65 86 88111113114 6 7 11 14 56 57 59 61 62 63 64 65 86 89111114 11 14 15 56 58 59 60 61 63 64 65 86 88 89 90111113114115 16 66 67 68 70 81 82116 16 17 21 66 67 68 69 71 72 73 74 76 81 82116117121 16 18 19 66 67 68 69 70 71 73 81 82 83116118119 16 17 19 32 66 67 68 69 70 71 74 81 82 84116119 16 18 19 20 66 68 69 70 71 73 74 75 81 83 84 85116118119120 21 67 71 72 73 75121 21 22 26 66 67 71 72 73 74 76 77 78 79 81121122126 21 23 24 66 67 68 71 72 73 74 75 76 78121123124 17 21 22 24 66 67 69 71 72 73 74 75 76 79116117121122124126 21 23 24 25 66 68 69 70 71 73 74 75 76 78 79 80121123124125 26 72 76 77 78 80126 26 27 31 66 71 72 76 77 78 79 81 82 83 84126127131 26 28 29 71 72 73 76 77 78 79 80 81 83126128129 22 26 27 29 71 72 74 76 77 78 79 80 81 84121122126127129131 26 28 29 30 71 73 74 75 76 78 79 80 81 83 84 85126128129130 31 66 77 81 82 83 85131 16 31 32 66 67 68 69 71 76 77 81 82 83 84116131132136 31 33 34 66 68 76 77 78 81 82 83 84 85131 133134 27 31 32 34 66 69 76 77 79 81 82 83 84 85131134 31 33 34 35 66 68 69 70 76 78 79 80 81 83 84 85131133134135 36 61 62 86 87 88 90136 36 37 41 61 62 86 87 88 89 91 92 93 94 96136137141 36 38 61 62 63 86 87 88 89 90 91 93136138139 36 37 39 61 62 64 86 87 88 89 90 91 94136139 36 39 40 61 63 64 65 86 88 89 90 91 93 94 95136138139140 41 86 87 91 92 93 95141 91 92 96 97 41 43 86 87 88 91 92 93 94 95 96 98141143144 36 37 41 42 44 46 86 87 89 91 92 93 94 95 96 99136 137141142144146 41 44 45 86 88 89 90 91 93 94 95 96 98 99100141143144145 91 96 96 97 98 99 91 92 93 96 98 86 87 91 92 94 96 99 91 92 93 94 95 96 98 99100101 106101102103104106101102103106108101102104106107109111101102103104105106108109 110 56101102106107108110111156 56 57 61101102106107108109111112113114116156157 161 56 58 59101102103106107108109110111113156158159 51 52 56 57 59 61101102104 106107108109110111114151152156157159161 56 58 59 60101103104105106108109110111 113114115156158159160 61106107111112113115116161 61 62 86106107111112113114116 117118119121136161162166 61 63 64106107108111112113114115116118161163164 61 64 106107109111112113114115116119156157161162164166 61 63 64 65106108109110111113 114115116118119120161163164165 66111112116117118120121166 66 67 71111112116117 118119121122123124126166167171 66 68 69111112113116117118119120121123166168169 66 69111112114116117118119120121124161162166167169171 66 68 69 70111113114115 116118119120121123124125166168169170 71116117121122123125126171 71 72 76116117 121122123124126127128129131171172176 71 73 74116117118121122123124125126128171 173174 66 67 71 72 74 76116117119121122123124125126129166167171172174176 71 73 74 75116118119120121123124125126128129130171173174175 76121122126127128130131 176 76 77 81121122126127128129131132133134136176177181 76 78 79121122123126127 128129130131133176178179 71 72 76 77 79 81121122124126127128129130131134171172 176177179181 76 78 79 80121123124125126128129130131133134135176178179180 81126 127131132133135136181 66 81 82116126127131132133134136137138139141181182186 81 83 84126127128131132133134135136138181183184 81 84126127129131132133134135136 139176177181182184186 81 83 84 85126128129130131133134135136138139140181183184 185 86131132136137138140141186 86 87 91131132136137138139141142143144146186187 191 86 88 89131132133136137138139140141143186188189 86 89131132134136137138139 140141144181182186187189191 86 88 89 90131133134135136138139140141143144145186 188189190 91136137141142143145146191141142146147 91 93 94136137138141142143144 145146148191193194 86 87 91 92 94 96136137139141142143144145146149186187191192 194196 91 93 94 95136138139140141143144145146148149150191193194195141146146147 148149141142143146148136137141142144146149141142143144145146148149150151156151 152153154156151152153156158151152154156157159161151152153154155156158159160106 151152156157158160206106107111151152156157158159161162163164166206207211106108 109151152153156157158159160161163206208209101102106107109111151152154156157158 159160161164201202206207209211106108109110151153154155156158159160161163164165 206208209210111157161162163165166211111112116156157161162163164166167168169171 211212216111113114156157158161162163164165166168211213214106107111112114116156 157159161162163164165166169206207211212214216111113114115156158159160161163164 165166168169170211213214215116161162166167168170171216116117121161162166167168 169171172173174176216217221116118119161162163166167168169170171173216218219111 112116117119121161162164166167168169170171174211212216217219221116118119120161 163164165166168169170171173174175216218219220121166167171172173175176221121122 126166167171172173174176177178179181221222226121123124166167168171172173174175 176178221223224116117121122124126166167169171172173174175176179216217221222224 226121123124125166168169170171173174175176178179180221223224225126171172176177 178180181226126127131171172176177178179181182183184186226227231126128129171172 173176177178179180181183226228229121122126127129131171172174176177178179180181 184221222226227229231126128129130171173174175176178179180181183184185226228229 230131176177181182183185186231131132136176177181182183184186187188189191231232 236131133134176177178181182183184185186188231233234126127131132134136176177179 181182183184185186189226227231232234236131133134135176178179180181183184185186 188189190231233234235136181182186187188190191236136137141181182186187188189191 192193194196236237241136138139181182183186187188189190191193236238239131132136 137139141181182184186187188189190191194231232236237239241136138139140181183184 185186188189190191193194195236238239240141186187191192193195241191192196197141 143144186187188191192193194195196198241243244136137141142144146186187189191192 193194195196199236237241242244246141143144145186188189190191193194195196198199 200241243244245191196196197198199191192193196198186187191192194196199191192193 194195196198199200201206201202203204206201202203206208201202204206207209211201 202203204205206208209210156202206207208210211256156157161201202206207208209211 212213214216256257261156158159201202203206207208209210211213256258151152156157 159161201202204206207208209210211214251252256257259261156158159160201203204205 206208209210211213214215256258259260161207211212213215216261161162166206207211 212213214216217218219221261262266161163164206207208211212213214215216218261263 156157161162164166206207209211212213214215216219256257261262264266161163164165 206208209210211213214215216218219220261263264265166211212216217218220221266166 167171211212216217218219221222223224226266267271166168169211212213216217218219 220221223266268161162166167169171211212214216217218219220221224261262266267269 271166168169170211213214215216218219220221223224225266268269270171216217221222 223225226271171172176216217221222223224226227228229231271272276171173174216217 218221222223224225226228271273166167171172174176216217219221222223224225226229 266267271272274276171173174175216218219220221223224225226228229230271273274275 176221222226227228230231276176177181221222226227228229231232233234236276277281 176178179221222223226227228229230231233276278171172176177179181221222224226227 228229230231234271272276277279281176178179180221223224225226228229230231233234 235276278279280181226227231232233235236281181182186226227231232233234236237238 239241281282286181183184226227228231232233234235236238281283176177181182184186 226227229231232233234235236239276277281282284286181183184185226228229230231233 234235236238239240281284285186231232236237238240286186187191231232236237238239 241242243244246286287291186188189231232233236237238239240241243286288181182186 187189191231232234236237238239240241244281282286287289291186188189190231233234 235236238239240241243244245286288289290191236237241242243245246291241242246247 191193194236237238241242243244245246248291293186187191192194196236237239241242 243244245246249286287291292294296191193194195236238239240241243244245246248249 250291294295241246246247248249241242243246248236237241242244246249241242243244 245246248249250201251201202206251252256251253251254205255260206256206207211256 257261256258256259206208209210256258259260211261211212216261262266261263261264 211213214215261263264265216266216217221266267271266268266269216218219220266268 269270221271221222226271272276271273271274221223224225271273274275226276226227 231276277281276278276279226228229230276278279280231281231232236281282286281283 281284231233234235281284285236286236237241286287291286288286289236238239240286 288289290241291241242246291292296291293291294241243244245291294295246296246247 296297296298296299250295300 -.707106816579618E+000.707106745793467E+00-.844334130890272E-01 -.696951911168316E+00-.844334130890552E-010.844333971430866E-01 0.696951959550198E+000.844333971430866E-010.169379293548785E-01 -.706903887803993E+00-.169379269811943E-010.706903887799719E+00 0.245538507221060E-01-.706680324381466E+00-.245538469074249E-01 0.706680363494609E+00-.816418512372678E+000.416234647777442E+00 0.400261827613855E+00-.707106816579739E+000.707106745793357E+00 -.692246657276026E-01-.700297003669988E+00-.692246686484270E-01 0.692246561667109E-010.700297003664129E+000.692246429669856E-01 0.201259425073776E-01-.706820307066788E+00-.201259404946509E-01 0.706820307062134E+000.247547275541103E-01-.706673335798275E+00 -.247547250784765E-010.706673335793667E+000.244951179721711E-01 0.141798045683355E-19-.699515386900931E+00-.100390257306135E+00 -.244951125432383E-010.403797585699602E-130.699515399846145E+00 0.100390257306048E+00-.707106840518851E+000.707106721854245E+00 -.132398684210425E-02-.707104302076665E+00-.132398682112846E-02 0.132398661033321E-020.707104302222497E+000.132398652689601E-02 0.251871166539414E-01-.706658056811822E+00-.251871127758866E-01 0.706658056805146E+000.264048027660490E-01-.706613622993380E+00 -.264047987662912E-010.706613586618012E+000.250107227346610E-01 0.259324348882091E-18-.669582765977545E+00-.225905619309715E+00 -.250107188007798E-010.166054197615496E-120.669582814615445E+00 0.225905627940471E+00-.999999999999996E+00-.100000000000000E+01 0.707106751263410E+00-.707106811109693E+000.707106751263400E+00 -.707106811109696E+000.594184615923025E-04-.522534802243499E-12 -.594354881940039E-04-.764126330976698E+00-.654895649435869E-04 -.555850754291422E-100.775951072359707E-040.645066611238772E+00 -.999999999999996E+00-.100000000000000E+010.707106751263410E+00 -.707106811109693E+000.707106751263407E+00-.707106811109700E+00 0.265041818209181E-04-.508541053041430E-12-.265118042346652E-04 -.757862392871900E+00-.311410747072004E-04-.431724688636464E-10 0.361816791523382E-040.652414431007056E+00-.999999999999996E+00 -.100000000000000E+010.707106751263410E+00-.707106811109693E+00 0.707106794782394E+00-.707106767590709E+000.247298538585594E-04 0.173057137779142E-12-.247369664563574E-04-.758133034802306E+00 -.288203567500599E-04-.373198365066270E-100.335135601768647E-04 0.652099914402839E+00-.999999999999996E+00-.100000000000000E+01 0.707106751263410E+00-.707106811109693E+000.707106773022893E+00 -.707106789350199E+000.526001426328733E-04-.686257777907160E-12 -.526151918089806E-04-.763904838719903E+00-.579153207211495E-04 -.480634147895882E-100.685730564085902E-040.645328895826580E+00 -.707106816579021E+000.707106745794075E+000.907453690126752E-01 -.695363616933204E+000.907453584845728E-01-.907453530938325E-01 0.695363616931083E+00-.907453541634382E-010.388412996851262E-01 -.706039176488765E+00-.388412958008106E-010.706039225852471E+00 0.405384669021764E-01-.705943788823106E+00-.405384601326821E-01 0.705943788819880E+000.374910477226837E-010.836910668696327E-19 -.653009130497729E+00-.268651354886250E+00-.374910441557599E-01 0.139197855810201E-120.653009053988256E+000.268651341635424E+00 -.707106816577767E+000.707106745795336E+000.110699028877342E+00 -.689558863568468E+000.110699028877342E+00-.110699023342189E+00 0.689558899694259E+00-.110699023342207E+000.353901421432703E-01 -.706220615039452E+00-.353901386042155E-010.706220587934077E+00 0.400455576932894E-01-.705971921162636E+00-.400455536886817E-01 0.705971921161698E+000.397033469335430E-010.518711104785870E-19 -.700067560303143E+00-.912639778518622E-01-.397033514193168E-01 0.669670689866494E-130.700067476628409E+000.912639778518489E-01 -.707106816577706E+000.707106745795397E+000.216163600604371E+00 -.673255732353994E+00-.216163567662612E+000.673255767625957E+00 0.343171978221466E-01-.706273565834579E+00-.343171943903884E-01 0.706273537877586E+000.384789098875664E-01-.706059044020112E+00 -.384789060396264E-010.706059044019181E+000.428340687803781E+00 -.816002001388647E+000.388155882219383E+00-.707106781186546E+00 0.707106781186546E+000.919164088258896E-12-.323903147050126E+00 -.668411207904565E+00-.668411136933422E+00-.392397821342358E-01 0.126741961371568E-010.848341585451701E-02-.686488249101334E+00 -.164737403383030E-010.726794259837522E+000.253811998949423E-01 0.427304877010395E-02-.713017416797165E+00-.242972297547323E-01 -.379326587583946E-020.700241968358579E+00-.374966055507997E-03 0.244954510496371E-01-.107305914771803E-020.854576884136081E-09 -.704999716109445E+00-.101177314154959E+00-.240417637527367E-01 0.106896353468138E-020.693652910717219E+000.101999329282549E+00 0.369802367784965E-02-.998478946766033E-080.628213615438288E+00 -.111695501554557E-01-.639775962557707E+000.441805243310407E+00 0.264916681259199E-010.150179388402961E-02-.323621717853948E-03 0.878267323059556E-020.250020432185017E-03-.492283767812116E-02 -.406353565923736E-010.234750587315863E-02-.173455232422632E+00 0.500624797585161E+000.467986775089445E+00-.171309845650195E-01 0.108659111149954E+00-.500624772325725E+00-.485548310627230E+00 0.203453546805473E-030.924723892346221E-040.596021551608855E-02 0.144977252778252E-030.727990528604067E-040.170446169406913E-02 -.713900928598815E-020.219802264290567E-010.370608562041904E+00 0.207893595583177E-01-.258848244250827E-01-.903242099366874E+00 0.922248994905455E-01-.305257817801369E-02-.700818827730815E-02 0.191302757843644E+000.148579185954640E-040.171121650781410E-02 0.486934889722714E-030.150620182701511E-040.124328766057256E-03 0.239016721169981E-030.115323810912666E-030.404520413743159E-02 0.113998101983268E-04-.207057801906026E-020.590390599498483E-01 0.229989382973123E+000.126638864121696E-01-.636607683510642E-01 0.320190435990360E+00-.860187903320348E+000.144893930539319E-02 -.120356442673852E-010.311102756171715E+00-.160900125595186E-05 -.788680156986552E-05-.220582013341250E-04-.808877643315356E-05 0.290559263145904E-02-.124362898928145E-05-.455696078386797E-02 0.130134687021089E+000.186761496719130E-01-.209760100786787E-01 0.603707240598609E+000.866404279134079E-010.268410288213005E-01 -.160761288050858E-02-.771455917360623E+00-.118795008750806E+00 0.233433259368892E-030.357198977531906E-020.125468663142325E-01 0.105518298214813E-01-.219409073721873E-03-.516770485999043E-03 0.155737420002396E-020.475170697294222E-020.375437524196078E-02 0.125599035320910E-080.160955314931229E+00-.223800543931700E-01 -.167424614451373E+000.958946814478864E+000.161130765277663E+00 0.196534771283384E-030.229515992283831E-020.576258431242573E-05 0.123745953025444E-01-.106995672755502E-04-.451052406900802E-04 -.456298622807265E-03-.275196027305474E-03-.305282850369034E+00 0.519423576775914E+000.505241937641198E+00-.130908849130573E-01 0.201635085589468E-01-.519423633116087E+00-.333293227117524E+00 -.263134929283539E-020.118328199171819E-030.104150622740462E-01 0.193141117505181E-03-.154345791282011E-030.173868931704905E-03 0.325208290050746E-02-.373216687782401E-030.149265726829690E-01 0.635804228599679E-010.820369767656903E-02-.212632332341540E-01 -.863649530175426E+000.489006964790317E+00-.348933539662262E-01 -.515727866020910E-020.944324418994364E-010.774875938152194E-04 0.482971314170869E-020.112759618007829E-020.222168874154256E-11 -.469066568608033E-100.220035735034216E-030.392555412688333E-02 0.141255360917606E-030.174989934363485E-010.515531740150388E-01 -.461588326613025E-03-.250983472579693E-010.684732202756503E+00 -.726228124582573E+000.842387322611238E-02-.317841553099293E-03 0.582455539039689E-02-.217823676656004E-040.446878338884266E-02 -.200617977872690E-010.537091052490130E+000.181205202614563E+00 -.379058590472633E-02-.114631325054326E-020.100346775148016E+00 0.271648560515299E-010.259196853345346E-01-.272445450180131E-01 -.728159919978982E+00-.314123286436018E+00-.938624176704406E-02 -.362203896936131E-020.153775041043447E+000.781378322348654E-01 0.426720954014265E-030.112760204809835E-02-.167938108847192E-02 0.854993026183699E-010.457577468747559E-03-.644980511474331E-03 -.215375382943762E-020.354875964291731E-050.999992692546311E+00 0.164898274978811E-070.304934046331858E-020.228760962681150E-03 -.247128995183060E-100.118007080764899E+00-.123564497591530E-09 0.162728422837746E-01-.819861260960444E+000.141941206609466E+00 0.125775224074353E+000.393535557751079E-020.178021559472064E+00 -.141941215640452E+00-.147146706681122E+000.753144190049640E-03 0.236859750590249E-020.447439294418169E+000.359129436315990E-02 0.627754930398190E-01-.139244701906877E-020.214783034756772E-03 0.131512191293389E-030.124438240310255E-040.487697648747908E+00 -.148174054632193E-02-.535785553537011E+000.309890918116741E-03 -.688115252161152E-01-.283340125674097E-010.310257496437506E-01 -.461205326885983E+000.191293743934847E-020.505833990447865E+00 0.750983511657879E-040.705267092317584E-04-.786060719406271E-05 0.565417053429881E-020.369600487362671E-040.443122584382949E-02 0.369600487362671E-040.389809678124690E+00-.480919973513487E-01 0.104050264453308E-01-.489891790728507E+000.512175326664710E+00 -.251878239510859E-010.293966079442228E-01-.374941991066111E+00 0.641782125495638E-010.443884509856657E+000.415631588510590E-02 0.291724739467156E-02-.315602200752062E-040.276258179505761E-12 0.315692669405107E-040.405867061011481E+000.378690131926348E-04 -.918882285479390E-06-.585087468913459E-04-.901978941696008E+00 0.113474779210659E-090.132088859541395E-090.452016593238905E-08 0.153981616917685E-03-.187604508266648E-060.449094630629618E-09 0.238044864556349E-060.236695170296057E-02-.429542502073789E-04 -.134103249836867E-040.103819281934490E-030.147310120826308E+00 0.289572954091881E-010.166544091372661E-01-.414623249348314E-01 -.271830205766233E-01-.834413463006351E-060.998136392031476E+00 0.122395916553052E-010.632739099986892E-090.212633687143486E+00 0.632739099986892E-09-.110266703181475E-030.137411102806595E+00 -.541373056555355E-02-.813199727026674E+000.185364035933384E+00 0.189529013238867E+000.865340666265890E-020.342605965282138E+00 -.185364035366044E+00-.194177150813847E+000.294623504846971E-02 -.481686497086705E-030.121545876488085E+00-.530804639167663E-03 0.456286581451462E-020.286575521807902E-020.404296415827950E-03 -.687084666871018E-010.346805266614458E-020.753574515516031E-01 0.505627623174092E+00-.574252270940695E-02-.564511679616764E+00 -.357473139901688E-04-.231037907805869E-01-.434238694510366E+00 0.475492620831160E+000.115770063050651E-020.134140728510668E-02 -.263260049701307E-030.105471222881001E-020.116593856850648E+00 0.105471222881001E-020.922493324714324E-01-.579437302697594E-01 0.121570291545597E+000.685873943808266E-010.273378233184083E+00 -.204837707484476E+000.360576001215734E-02-.677988803582434E+00 0.173174484916547E+00-.380656063886276E+000.442368547231428E+00 -.558513583720547E-04-.823757328985934E-030.669330729666884E-01 -.959833802074539E-030.601389213056274E-010.962184060000759E-05 -.187827323783031E-040.360387968584401E-120.187881360370489E-04 0.537074764821504E+00-.241847150836626E-08-.239399430153665E-10 0.201204711161572E-080.245123711639579E-040.343859473382981E-04 0.142820901368339E-07-.395427510919049E-04-.803141296002529E+00 -.308798916471791E-080.372565513480860E-110.372134699667619E-08 0.695751722977721E-04-.206823361952197E-04-.867594640014316E-07 0.320490380387678E-040.257904527488446E+000.251527713105688E-01 0.160670486494815E-01-.359427383128825E-01-.208315603223150E-01 -.106749103877009E-050.998634620717329E+000.105947158447703E-01 0.786357166775589E-090.644554062825855E-010.147441968768947E-09 0.283415543445799E-020.685059169690794E-030.161928254063469E+00 -.734658112367259E-02-.795436981644603E+000.112005113951728E+00 0.116112410074604E+00-.122748344137133E-010.535385505713645E+00 -.112005114710728E+00-.101694000626255E+000.376112318286562E-03 0.337223222160585E-01-.160461773121821E-020.572257030714030E-02 0.358983271090535E-020.483648722770236E-03-.374378469350919E+00 0.491681099797348E-020.409889093974485E+000.530964917213129E+00 -.627250620485439E-02-.595098741464305E+00-.241170615534876E-04 -.334285861829879E-01-.157354286153396E+000.172548982335806E+00 0.149808311102240E-020.164824307470865E-02-.307153539074260E-03 -.106756314785166E-020.139626387190351E+00-.106756314785166E-02 0.110156897634196E+00-.309911159440874E+000.167408292491309E+00 0.360213501196167E+000.241963975861273E+00-.208694806147609E+00 0.493267448076731E-02-.709971239067276E+000.237100559219863E+00 -.131217716617825E+000.154290771975884E+00-.959074851003528E-05 0.956731538415544E-030.794297126275660E-010.783541617392965E-03 0.693456870140263E-01-.453325254228497E-04-.176585350383745E-04 -.123562725125358E-120.176636156078052E-040.541350527616704E+00 -.240773125362821E-08-.233457660732528E-110.271455532902927E-08 0.477531482574202E-040.318748202945685E-040.168773004647976E-07 -.366100077933934E-04-.802382883088274E+00-.189243713536815E-08 -.175937555189488E-100.161357154454997E-080.220750984082187E-04 -.182827311837541E-04-.810192048052132E-070.287394278084876E-04 0.251239543599436E+000.460154655563629E-030.109020541892817E-07 0.301020760096669E-02-.676020538863894E-03-.201397582313553E-02 0.265255685432536E-050.999993076694352E+000.245686508966199E-03 0.528725086162795E-100.528725086162795E-100.139137638304773E-01 -.931476122820135E-020.187667088561186E+00-.806168464489319E-01 -.741318518217202E-01-.150594948497854E-030.496927937442151E-02 0.577857814421090E+000.106703220081005E-01-.779133836752166E+00 0.806168453826879E-010.695241882699640E-01-.515203579148082E-04 -.229418112929880E-030.809403648149187E-02-.283211984912348E-03 0.309218219416329E-030.189421944285213E-030.177162332103893E-04 -.436862641845423E+000.479152582846512E+00-.712381219969140E-01 0.294435744654024E-020.780917998203279E-010.502921115640390E+00 -.181070913767124E-02-.552926222784265E+000.443750531523610E-03 -.985965310703518E-010.118852928374641E-030.109862679157740E-03 -.109006539468286E-040.144672961940265E-030.716786890076843E-02 0.144672961940265E-030.561128618870810E-02-.311695309851634E+00 0.369140461343607E+00-.564818818963682E-010.843996016463362E-01 0.683479449787785E-010.353180746937538E+00-.525397161080030E-01 0.131036844385976E-01-.456640065049356E+000.644420456556119E+00 0.559396888735261E-020.394650581663461E-02-.276030758828090E-04 0.359262044720999E-120.276109760275352E-040.400875800538385E+00 -.153565440406287E-06-.284270058405151E-090.171772862729932E-06 0.153454876917201E-02-.233754388154802E-090.978810924525225E-10 0.373622626632746E-080.130985708337576E-030.345983153605038E-04 -.692008542158418E-06-.515924281953249E-04-.901011303111012E+00 -.327069748284931E-04-.724156296312873E-050.719917974521585E-04 0.165755363482073E+000.474803594620760E-020.116474496930673E-03 0.161427927008894E+00-.319233613834862E-01-.199249049476415E+00 0.943952542138753E+000.205279273142504E+000.363324353033546E-02 -.108482676139213E-020.157536226523168E-010.130255045013827E-02 0.301913162646137E-030.161243332301578E+000.606695718965107E-01 -.397526540444055E+000.554748860175678E+000.383966542560385E+00 -.236530864243820E-010.493155556414269E-01-.554748767500591E+00 -.214301755749183E+00-.791692179238457E-02-.552245530472999E-03 0.117804913038090E-010.534077055607152E-040.359651953275203E-03 0.435838693521165E-020.413002012631367E-030.215005754443115E-01 -.121296060755018E-010.287291230583004E-01-.295083695975163E-01 -.936024399941001E+000.150963209808127E+00-.471083210162908E-01 -.930017973181041E-020.310435446284620E+000.200383312665818E-03 0.797662512256087E-020.202677154721335E-020.821695118252034E-03 0.185995596284431E-090.953942751065062E-020.579222037124909E-04 0.419784017723221E-01-.482975532332040E-030.904470811910962E-02 -.574430934800443E-010.451700983218531E+00-.847632099722912E+00 0.206216564248354E-01-.952089249595826E-030.267683914514290E+00 -.442089263297538E-040.130227346463139E-01-.334575236633050E-01 0.582754336569465E+000.239748154997497E+00-.232703116519158E-02 0.632586030004597E-030.656015033332231E-010.269019293740100E-01 0.372932091845224E-01-.227602290610941E-01-.680109638438260E+00 -.349237624883250E+00-.320426217305454E-02-.232449893005120E-02 0.496936332823237E-010.161945477273113E-010.379014284144202E-03 0.396327632422365E-03-.858744763106854E-030.871345710795191E-01 0.870146384175541E-020.110748991451490E-070.647459393211122E+00 -.211020858629368E-01-.655608719224489E+000.387108539259607E+00 0.241779008380115E-010.386469431151273E-020.112081023309811E+00 -.698167490986286E+00-.112081012101691E+000.698167490986229E+00 0.609105524539040E-040.810324884139280E-03-.604954208771893E-02 0.822458556079886E-020.108535292536380E+000.377476685106857E-01 -.774936024964465E-02-.787880717753179E+000.225369702812543E-02 -.562892718869109E-03-.285497312308102E-010.604196076303872E+00 0.134876218565383E-040.885850836022477E-030.240861803747173E-03 0.320725483445566E-04-.245765498175867E-030.518563563274593E-03 -.258064430088833E-030.523073530082049E-020.414286362962317E-04 -.134296280739007E-010.454147960865441E-010.246095955438665E+00 0.381810162664600E-01-.458578109756278E-010.309247721541881E-01 -.840168641477295E+000.726706384663128E-03-.200805330145389E-01 0.475756927113320E+00-.348987049372346E-050.163014746453075E-04 -.406433530604126E-040.174811555826052E-040.416347324487490E-02 -.503900886600453E-05-.243879091555047E-010.430018804227158E+00 0.560591961221790E-010.114237883088519E-020.652452798290859E-02 -.245918402416141E-020.608972012498249E-020.461425942228189E-01 -.102539319935843E-02-.815026724296231E+00-.117156972700854E+00 -.195325680784950E-010.236697927830689E-080.358408016308951E+00 0.467236881616071E-01-.528487928757052E-03-.344478060267522E-03 0.327754210659766E-020.101409566262696E-010.707106781186500E+00 -.707106781186603E+000.662262870273973E-01-.412532285002360E+00 0.642429494386874E+000.642429402719959E+00-.339222881485481E-01 -.440624356497263E-020.721314558783405E+000.318354889292678E-01 -.691029429413945E+00-.298330170970555E-020.228604569444274E-01 -.372782349555383E-01-.271115201819383E-010.688164533706434E+00 0.441086820619143E-01-.722376492423855E+00-.383619480806987E-01 0.123858524819484E-020.211675332716350E-020.682478888494490E+00 0.970441548327741E-010.390369360953282E-01-.238759561039506E-08 -.716298578374737E+00-.933799186770630E-01-.707106781186575E+00 0.707106781186525E+00-.167263560147883E-07-.497215731964989E+00 -.609297473009121E+00-.609297508136205E+00-.101437921164760E+00 0.396808464685394E-010.145837777501628E-01-.681042143793224E+00 -.504664615069257E-010.729278738542803E+000.681269617691656E-01 0.666444114418943E-02-.712408745146810E+00-.648638844371203E-01 -.636842463844503E-020.695369860658179E+00-.979129339670780E-03 0.300892878154688E-01-.298674746023331E-010.482956299067998E-07 -.322605724633322E+00-.646186912478413E+00-.121318406636933E-01 0.582015570576082E-010.215407605396003E+000.653173445595279E+00 0.570507474805564E-030.942716646294706E-080.298476109835370E+00 -.229767996041610E-01-.303221070862048E+000.602037576303353E+00 0.675266720258527E+000.245053547811273E-020.585960686889018E-03 0.513031006915004E-030.865194342723113E-020.787352240189772E-03 -.123009456216638E-01-.602952293381838E-010.100813384569477E-01 -.235623029749862E+000.486151508253275E+000.442775079628557E+00 -.405512246939388E-010.216904069577573E+00-.486151536353640E+00 -.472136317138705E+000.126301180815325E-010.792403668237731E-04 0.413297540850655E-020.352171169359473E-03-.329573224578663E-04 0.652940718111332E-03-.256262482273700E-03-.234114335976204E-01 0.337110002433409E-010.381021013468887E+000.601463636725532E-01 -.545256280105584E-01-.868532468572194E+000.679937091073461E-01 -.847858651657671E-01-.411597864503930E-010.280521986517897E+00 0.105879134718726E-040.416765143704468E-03-.123099030948993E-03 0.301756375767690E-040.249083843067110E-030.209120900143790E-03 0.231043094154576E-030.257036870345741E-020.228387047244176E-04 -.574755821099979E-020.974467519929338E-010.236333894525561E+00 0.396680034546653E-01-.132253076018475E+000.265114915419996E+00 -.853424947855451E+000.479397847921161E-01-.427817436974369E-01 0.335850084444527E+00-.148408460429058E-04-.748161136435617E-04 0.110753604160756E-03-.706119611472251E-040.152624617518191E-02 -.110951858901099E-04-.644113284807349E-020.650828991401486E-02 0.228749967414610E+000.600635730865104E-01-.223553067564437E-01 -.358150776105921E-070.239684957296783E+000.480094650288983E+00 0.192145309729517E-01-.836123635137684E-01-.225899275367096E+00 -.765138432844402E+000.313411371419374E-020.742995638243971E-02 -.136119349521726E-010.825709237069057E-01-.389328976578801E-02 0.308727616620548E-020.502762790374560E-010.457631940177901E-01 0.210671082150144E-030.136670157899477E-030.177999280509586E-01 -.174707401413546E-02-.146934442009727E-010.371048542182972E-01 0.999042801658376E+000.917293575579656E-030.136933469979301E-03 0.442668224180858E-030.123494540316625E-010.557234391914227E-04 -.570137556406672E-02-.370827223466650E-01-.472433665133362E-02 -.278122948398114E+000.410144945494006E+000.397557322797068E+00 0.448319999663166E-030.493871784844263E+00-.410144933519769E+00 -.425418904107767E+000.334848699759163E-010.127375877370595E-03 0.110532019406746E-020.237091582126644E-01-.113844312723035E-03 -.380925034819731E-040.158908676155912E-02-.494574442295410E-03 -.136516243012434E-020.289433905657649E-010.514912248937955E-01 -.303914167730759E-02-.422251074843907E-01-.203227767720065E+00 0.153753347019584E+00-.917153830215156E+00-.763258755002147E-01 0.287706323687985E+000.216506567822838E-040.829796579240233E-03 -.283433609785619E-030.559390318691268E-030.633501377261939E-02 0.131319120514597E-020.701963998257549E-010.905217459477781E-01 0.357923735038388E-01-.123891945774251E+000.395903508691244E+00 -.702671794969916E+000.557691797337480E+00-.205098607153493E-01 0.909184509497725E-01-.190654151029481E-04-.121336165082983E-03 0.328915099482047E-03-.149272779124686E-030.338462654696031E-02 -.112851204297636E-04-.445463552536016E-02-.835576313571940E-02 0.752932544467666E-010.137534847523132E+00-.259114738485208E-03 -.563852731001187E-030.190774804903477E-020.242779688270085E-01 -.194309000886799E-02-.285769460002899E-010.895054924400790E-02 -.983116941827859E+000.212645158251803E-030.125707197364705E-03 -.350836204080841E-030.430592564883796E-01-.853469359816533E-03 -.777078218862946E-030.742620013435782E-020.734967290854320E-01 0.381446313628261E-030.124845056146456E-030.414383331747861E-02 -.940271526508416E-03-.404221951901942E-020.644204016897479E-03 0.999982450334638E+000.102526910708690E-030.342667220082544E-03 0.539407713885730E-030.112182650588275E+000.291963953692846E-02 0.243306172940037E-020.417843161548503E-01-.339945353959363E-01 -.797488637176752E+000.274980044994610E+000.286636867608651E+00 -.136712222555940E+000.267568964966806E+00-.274980025426080E+00 -.117859587300834E+00-.268224051763144E-020.846984655215149E-02 0.104013252256216E+00-.706725077066978E-020.221871308732617E-02 0.219868236428274E-020.201981444706414E-030.458618437592934E-02 0.126809928213090E-01-.320380956077024E-010.204506522896203E-01 -.148582793941879E-01-.113780442017961E+000.374335203551583E-01 -.990721098034612E+00-.210726169380195E-010.426373790397174E-01 0.136555208806411E-030.224198476974885E-02-.571391145031755E-03 0.566586344120537E-020.959780379361985E-020.318911180367516E-02 0.620827710669931E-01-.568901108942749E-02-.180691343789712E-01 -.740521161628900E-010.209179385162360E+00-.195609548916247E+00 0.952445669749881E+00-.250646268674595E-010.131476157327279E-01 -.369071287024797E-04-.488185333132813E-030.346924020436468E-02 -.801030241372621E-030.135234270359219E-01-.699427244703543E-04 -.227371817304806E-040.305526739861381E-070.280327128925278E-04 0.499079983149445E+00-.678543881782044E-05-.141311621891559E-04 0.323882026853012E-040.296376197095334E-020.557320090650802E-05 -.203285194749962E-03-.242749015745857E-03-.829871103648760E+00 0.275295157139778E-080.407862664671703E-080.240492921342678E-07 0.447132367465700E-03-.196841317648305E-03-.835445317130868E-04 0.803921598880989E-030.249446072407021E+000.188844328303154E-01 0.538455289838268E-030.291708523636470E-01-.372703108642742E-01 -.496393478982733E-010.254758647814956E-050.997313376037241E+00 0.179944080258892E-040.174653471249788E-01-.387280835249212E-03 0.135120879213858E+00-.332591407056297E-030.839200840958193E-02 0.123774549670626E+000.710355862613081E-01-.816903955833649E+00 0.259111769955954E+000.169922195433962E+00-.967589717675854E-01 0.295181562913193E+00-.259111775222573E+00-.121879896040359E+00 -.170780062460303E-01-.456215445186038E-030.138493391082666E+00 -.756584484839288E-030.462615585354142E-020.747070123653290E-02 0.121523955801067E-020.121318890601466E-020.855595803629244E-02 -.618607852540523E-020.306525760240591E+00-.136562251008736E-01 -.673592315256137E+000.589580615384586E-03-.573566359288367E-01 -.288004951243023E+000.604707526771186E+000.152712274111098E-02 0.506016895702041E-02-.105440009914927E-02-.424305489168350E-06 0.528751207416300E-030.254336715238593E-010.543992283805514E-03 0.769918527154085E-010.230146570594166E-050.776291852346123E-02 0.118061461199013E+00-.143472302037430E-010.270617786854460E+00 -.198234957495660E+000.136950886553168E-01-.726560688324639E+00 0.141188296603900E+00-.294523042192644E+000.472157830749985E+00 -.110872557472870E-03-.126978546655609E-020.577296043463924E-01 -.144384353054288E-020.752577368093954E-010.243418539483478E-04 -.142888328684564E-04-.114490935915299E-070.161979153767801E-04 0.390904820917777E+00-.107263660415500E-07-.465323015112817E-08 0.223347461190187E-070.281951787649733E-040.642263470427003E-04 0.343724131105744E-06-.989576291726829E-04-.832242768277343E+00 -.120177009576371E-070.103799950061146E-090.199722827564297E-07 0.126564714211728E-03-.692324238576580E-04-.138592840130219E-05 0.152324103553164E-030.393147982873812E+000.154917438959898E-01 0.104654297961220E-040.278259108674488E-01-.303490991488291E-01 -.354216368215474E-01-.374358936472513E-060.998306540843242E+00 0.583345098154626E-030.139166982303768E-01-.219188756453223E-02 0.757662900455562E-01-.152524631871661E-03-.321278040358060E-02 0.320493204006391E+000.101985556245574E+00-.783316817911260E+00 0.276533341997327E+000.164610994180330E+000.186915934215290E-01 0.109466950808409E+00-.276533344763605E+00-.262128799339971E+00 -.711582411610634E-020.316741118718987E-020.798075059151104E-01 -.549305914149587E-020.680591161936855E-020.103957194354297E-01 0.165449572551216E-02-.297305272856413E+000.133512169424708E-01 0.620313041634109E+000.288681103087594E+00-.177630992643315E-01 -.657895338706556E+000.101100937639440E-02-.995075900155844E-01 0.378031371560238E-03-.715073997670865E-020.226932302359274E-02 0.680513181941886E-02-.134886288914828E-02-.489664457071443E-05 -.115741943188504E-020.340181330921379E-01-.112000827068954E-02 0.949249299187529E-01-.963143805549435E-05-.279314130074537E+00 0.159118172145863E+000.440690486502383E+000.219264647394360E+00 -.223531848223986E+000.209613224177962E-01-.730529530601576E+00 0.216119903392971E+000.149639207047947E-01-.229194735289877E-01 -.501177261368179E-040.297277225627281E-020.694032145798862E-01 0.257686371432962E-020.885479588062585E-01-.207970163074130E-03 -.138923090909384E-04-.127238716380106E-070.157058480423797E-04 0.409492189251564E+00-.102996885080796E-07-.678584712436506E-10 0.157848450480880E-070.936451399983214E-040.583579087160737E-04 0.356385494683888E-06-.910641984638006E-04-.829776111590451E+00 -.749823348792695E-08-.249102776330744E-080.140200580837383E-07 0.281551872354774E-04-.595312905301544E-04-.125463596060752E-05 0.134246582370566E-030.379193497185602E+000.426249993318591E-03 0.138136677625042E-030.600027532935093E-02-.104715937420707E-02 -.410412425692858E-020.360816358907135E-030.999972748532237E+00 0.815344840941258E-040.470003277126032E-03-.975581912704339E-03 -.758387765641282E-030.311201162620555E-010.163127700276862E-03 -.379406664406015E-010.655778353245633E+000.196424421346421E-01 -.478876541054886E+000.310326047253723E+000.286814367728409E+00 0.475138107439813E-02-.411328427070017E-01-.310326040307785E+00 -.244615833492320E+000.880585133137490E-02-.212605409102574E-02 0.364624809606826E-01-.259201452975158E-020.224527879066681E-02 0.209234382545644E-020.156319489577705E-03-.307758905489842E-01 0.220261326059213E-010.671643419853845E-010.118321296739216E+00 -.103277528307138E-01-.428144170934312E+000.286625510817101E-01 -.869306495280380E+00-.510672066662528E-010.193647111457262E+00 -.378647105337771E-040.317666846458886E-02-.835552638858626E-03 0.701619192360112E-020.105374907692704E-01-.522925349009331E-01 0.132709858923520E+000.526721064437783E-01-.202405945294266E-01 -.725368516726221E-010.194688239718319E+00-.189260055568609E+00 0.946300940701786E+000.792544711088228E-02-.355764043826012E-01 -.246135745872575E-030.304975551354759E-020.420239640621067E-02 0.261040112096898E-020.218379335165771E-01-.341978135298371E-03 -.172457015309441E-040.431356008346286E-070.219590871210806E-04 0.442659543701007E+000.620442416979269E-090.258920030491552E-08 0.168861954232395E-070.306596243662881E-030.323138773456644E-04 -.960348097112365E-04-.218166081265305E-03-.838067704175618E+00 -.589914917310024E-05-.416409183798882E-050.216992518203371E-04 0.171734903009034E-02-.172262703654395E-03-.255366933603604E-04 0.588840143324276E-030.318891160231964E+000.323051769754980E-03 0.527812440603705E-030.184483412376782E-010.172904899351989E-02 -.209517265408227E-010.158263229092178E-010.999483262596492E+00 0.789622357502747E-090.215857232441392E-03-.225609164740967E-02 0.149823816969244E-01-.499062773662014E-03-.236548692000563E-01 0.363896924656256E+000.107483034761124E+00-.391270672966822E+00 0.502192301820578E+000.405412180298002E+00-.678056199914652E-01 -.960614884631456E-02-.502192338841198E+00-.169129058584629E+00 0.276901186419182E-02-.169243266660495E-020.927155007066666E-02 0.145412623807367E-030.264674993738985E-040.763553538678154E-03 -.274044971065333E-03-.206553196141291E+000.192544222065392E-01 0.710409976253818E+000.130366138371823E+00-.228795553119039E-01 -.549279079167324E+000.144877887368590E-01-.339041201676814E+00 -.242405803695270E-010.131562971065629E+00-.258376806382172E-05 0.656278446202110E-03-.236769424458550E-030.141355471070267E-02 0.105244043606728E-01-.660332708148621E-010.210625908749795E+00 0.206019596480891E+000.666155188911710E-01-.131785375279779E+00 0.629358709986443E-01-.579139160435087E+000.687848108070714E+00 0.249885689824524E-020.272623878087522E+00-.189083942331165E-03 0.144332387792429E-02-.964970276958600E-040.142997186912260E-02 0.905906105727050E-02-.335003383098555E-03-.761567012733616E-02 -.106277964677985E-010.104274987796965E+000.200717863329688E+00 0.167157754026795E-030.800103307358312E-04-.239487412514881E-03 0.288613812865254E-01-.280311412689388E-02-.102833078885913E-01 -.246652115998060E-02-.958907097949439E+00-.199282635800055E-03 -.133451307121677E-030.122389068203788E-020.121150111192682E-01 -.553097739420755E-02-.738697421077239E-030.291299759234546E-01 0.164877272058817E+000.176933543460421E-020.636048637279320E-08 0.386389399803415E+000.837523572201287E-02-.392389715572957E+00 0.177968659061121E+000.815465158463628E+000.145621272878538E-07 0.199985867714712E-020.195851833059782E+00-.679442478235078E+00 -.195851722041146E+000.679442478235217E+00-.357201584439584E-05 0.104508299723225E-03-.430429753409975E-04-.161992044701792E-01 0.665913332291113E-020.627943984135420E-010.158766162588137E+00 -.580681991929644E-02-.725442566426469E+000.389377340629332E-03 -.543997834523727E-02-.141418550919330E+000.651316976488143E+00 0.103704333512308E-040.760162068660251E-04-.215295048130131E-04 0.814462510058118E-04-.624103587955855E-030.512727498773690E-03 -.655337427526513E-030.405937494843178E-020.105205018006757E-03 -.430493797466982E-010.888089058101809E-010.296501401773398E+00 0.820849426591335E-01-.704003772035664E-010.934683955500087E-02 -.849557747276744E+000.299284353890857E-01-.307351278117629E-01 0.408597009486543E+00-.477326696952231E-040.203748305369640E-03 0.145051551564250E-030.213311096242107E-030.268327332614296E-02 -.611874011102725E-04-.337262668853664E-010.924166207019878E-02 0.621949633428841E+000.161210309761146E+000.165557847623496E-02 0.133402559164063E-02-.540323718323402E-020.349527344820291E-01 0.158972038010233E-01-.191896754436189E-01-.167295225035774E+00 -.680665052123196E+00-.120576509551053E-01-.194282041054332E-07 0.106218810781638E+000.201171754213052E+00-.152846247993426E-01 0.126495382860975E-020.105728483537333E+000.171716077268080E+00 0.707106781186532E+00-.707106781186564E+000.179199321427276E+00 -.621672299758036E+000.539171163068275E+000.539171226818681E+00 -.150859012548334E+00-.346779801559453E-020.696421358249040E+00 0.147705689688260E+00-.685864311448068E+00-.549676070744279E-02 0.256758327647866E-01-.750726041803840E-01-.317246623417171E-01 0.668536882366567E+000.938655702018445E-01-.732745439276634E+00 0.170870172221987E-010.583898068138768E-010.619301667958476E-01 0.600138230146652E-010.677664207154702E+000.385190232285779E-01 0.619119497642184E-07-.339323566159786E+00-.642657517212704E+00 -.707106781186557E+000.707106781186543E+00-.245736663857741E-07 -.487017594237811E+00-.613791894359277E+00-.613791883445462E+00 -.966069207569462E-010.429174371243619E-010.113832073170950E-01 -.678381985760620E+00-.504298591343777E-010.731630526211845E+00 0.635386735290795E-010.125742853429528E-01-.716745907330516E+00 -.583613871779776E-01-.110212329091957E-010.691772730437950E+00 -.173175445674593E-020.383841621124299E-01-.110416382473008E-01 0.256741288464596E-07-.453880443429687E+00-.554991234753238E+00 -.318174114684711E-010.218019157967283E-010.404853975196401E+00 0.564789870930429E+000.102068503593475E-020.285623013061450E-07 0.492754819127494E+00-.203842046987441E-01-.499362468921001E+00 0.587824361647918E+000.402336839078275E+000.918169007117501E-03 0.700012494926306E-040.377013393139683E-020.158061746585615E-03 -.923345838286210E-02-.465479735545722E-010.161317275038019E-01 -.241725710157609E+000.498377849088563E+000.419438718550452E+00 -.424078491233497E-010.210523737367770E+00-.498377789898282E+00 -.469006127421801E+000.159157362192407E-010.971442723612329E-04 0.370429343061676E-020.185402222885231E-030.140361401801025E-04 0.454359178768059E-030.828774296805545E-04-.312157931261559E-01 0.221644959830577E-010.467147250894710E+000.605956757459247E-01 -.286080598138955E-01-.839766996204144E+000.216291917452147E-01 -.219985152720672E-01-.281124096984636E-010.262424344259733E+00 0.116417805123626E-040.267635114197098E-03-.672215219544455E-04 -.813735173184751E-06-.398866592646904E-050.204362284917030E-04 -.409081302153415E-050.158462400066490E-02-.628949975187434E-06 -.111533654039953E-010.945756611763469E-010.309305220492670E+00 0.491707927664971E-01-.110293923293886E+000.131202023612183E+00 -.859274284355457E+000.187676429483093E-01-.364156143118406E-01 0.351325562001735E+000.302673825658693E-050.179685592317993E-04 0.140441788487869E-030.172457286836458E-040.142844320681775E-02 0.256541507301178E-05-.135974180846842E-02-.135228523273871E-02 0.124160279154033E-010.226781889854867E-01-.333271203637093E-01 -.223082863493948E-070.394082533781187E+000.481872165055281E+00 0.354794598302177E-01-.290941802402022E-01-.430896016118760E+00 -.640798137718591E+000.185037448827823E-020.962525823705057E-02 -.494931284124744E-020.815259078185888E-01-.366652507262709E-02 0.308654674398379E-020.634740521082287E-010.386973240214517E-01 0.920203922416232E-030.108629350498719E+00-.143184031301651E-01 -.103310610340044E+000.268157434783449E+000.951507667518300E+00 0.667459177312360E-020.957709173457184E-030.603352690579251E-03 0.211234307770364E-01-.913404167729270E-04-.490567395888047E-02 -.312206895692159E-01-.377826865054100E-02-.253367241251457E+00 0.457238405489630E+000.431443403923000E+00-.580916488736549E-02 0.327729924464284E+00-.457238455836453E+00-.470035771580013E+00 0.286160495778913E-010.162251095002671E-020.295291942973934E-01 -.510593888156111E-030.133176045858044E-030.288550864294607E-02 0.326671120515064E-03-.119940694302481E-010.493611977238944E-01 0.200835967502284E+000.375222748159743E-01-.763181518223535E-01 -.607170442032405E+000.141924071866228E+00-.357268263812569E+00 -.111584072433367E+000.648806072874006E+000.101939051155568E-03 0.200605309319850E-02-.579965588212036E-030.258630208821450E-05 0.168217775562306E-040.144330153595768E-030.232887229287876E-04 0.675044602369196E-020.135607924906647E-05-.512253262244723E-03 0.115533485002037E+000.143965680843651E+000.283648332042478E-01 -.214797768570874E+000.391457522572237E+00-.810085558883003E+00 0.188501006513896E+00-.442767460955475E-010.268178435111368E+00 -.134851379999611E-04-.906524042141700E-040.706947400427236E-03 -.102644794357619E-030.682221155305948E-02-.107940584113467E-04 0.116235358609001E-030.166025085883410E-020.156776146399450E-02 0.189682979375326E+00-.361695504819792E-02-.346080365688096E-02 0.364161680538411E-010.123107662892829E+000.479565835504608E-02 -.696332330928824E-01-.557688540661065E-01-.907343267826924E+00 0.167427784956671E-020.249525019706888E-02-.429288818316120E-02 0.715872231770214E-01-.122267448202732E-01-.590040106779471E-02 0.156528369965063E+000.293967791211871E+000.175081783184165E-02 0.771184964438607E-030.221373065832482E-01-.621763107712101E-02 -.194592641016047E-010.714969543950864E-020.999514994545450E+00 0.597860704577673E-030.269402465479075E-020.515023791883851E-02 0.121292326773534E+00-.392528020472177E-020.118992126450666E-02 0.157395445789034E-01-.394082381129670E-01-.733003478782031E+00 0.337599559770288E+000.349142686729564E+00-.139463400368514E+00 0.227145186540549E+00-.337599510291875E+00-.916649623724561E-01 -.382942486348092E-020.925240648625014E-020.129158226356516E+00 -.853888047471263E-020.140096596740043E-020.126071176579125E-01 0.124720535117440E-020.303634316616343E-020.377300486494654E-01 -.294767602556083E-010.567360891048372E-01-.465498595571141E-01 -.420230611207414E+000.880228217424541E-01-.881922252676869E+00 -.505991235370717E-010.165262464703570E+000.146288106742103E-02 0.119437537909616E-01-.215022129020119E-020.937096633811036E-05 0.160932871380580E-030.293463833607639E-020.286155735433417E-03 0.429322788825650E-010.194015643940606E-040.838523134684283E-02 0.161717170334286E+00-.203051876371348E-02-.246917146462747E-01 -.230101940514772E+000.430203686138714E+00-.518676737549693E+00 0.666606010923658E+00-.696498178573828E-010.109439876538281E+00 -.849241779494426E-04-.807577859098053E-030.152659284083099E-01 -.110538323322089E-020.532650783719748E-01-.106908413345438E-03 0.521037564689083E-050.395491098356925E-040.916942038480008E-04 0.267445501897429E+00-.146929108520377E-04-.414381105364060E-04 0.883752978684304E-040.203583744031505E-020.552720532282201E-03 -.353106948059371E-03-.268158909150081E-02-.877321689364557E+00 0.129483762335851E-060.943389430578574E-07-.520801832045056E-07 0.542619061617278E-03-.897761281568731E-03-.531645372045277E-03 0.721153625769991E-020.398389736428573E+000.339439726157846E-01 0.127008998561281E-020.558849142773434E-01-.700047885835571E-01 -.972864026383786E-010.120387721105454E-030.990042699494239E+00 0.104923379909149E-030.342517600102390E-01-.374697094457425E-03 0.152312877545830E+00-.478817790311942E-030.872860861790242E-02 0.999657868488493E-010.761029238391244E-01-.789918683778005E+00 0.312925273563142E+000.179124695926111E+00-.106456692876792E+00 0.254396861436815E+00-.312925287652934E+00-.969397708740387E-01 -.205315405806358E-010.172023645205085E-030.152210304270155E+00 -.330338109710651E-030.459563407489116E-020.143990070124588E-01 0.222644377622351E-020.800563370830329E-030.104489137273485E-01 -.602561369632559E-020.201418904467542E+00-.171281646426121E-01 -.737384008805705E+000.102553883472058E-02-.588018158817250E-01 -.181397584082343E+000.615273770267933E+000.216302320816593E-02 0.949387888312259E-02-.138702989735942E-020.152795495644916E-04 0.225359384945996E-030.225891473319397E-010.262583707734798E-03 0.105723087052347E+00-.263236897139808E-050.655669812546020E-02 0.110649523915327E+00-.129806789078049E-010.165077126998700E+00 -.192799365643284E+000.282186057827035E-01-.807718334950653E+00 0.102142581525374E+00-.192428566915823E+000.444747023264972E+00 -.548606964381622E-04-.567233548395388E-030.635340804994158E-01 -.626317548109333E-030.945045541747214E-010.789273378979099E-05 -.288979693703195E-04-.182319839053481E-060.443515421301361E-04 0.379919944695107E+00-.409896592504587E-07-.502833020468807E-07 0.120494589988032E-060.308036843749235E-040.140521908879047E-03 0.816277654525576E-05-.295259341239829E-03-.861438578734898E+00 -.277471726737075E-070.876533127563630E-090.662575211226712E-07 0.129028505756325E-03-.126377308405864E-03-.370449666662370E-04 0.550391609228765E-030.337022199602707E+000.254458699117238E-01 0.592584625065294E-040.514303172879869E-01-.512809050778411E-01 -.660648944428663E-010.951604713061685E-040.994540487621631E+00 0.100924642958156E-020.245217454649157E-010.184864876070133E-02 0.884721194989155E-01-.324244362088066E-02-.510930961910458E-02 0.303062330901710E+000.112878700333972E+00-.734565742176333E+00 0.347055364976695E+000.162412105382276E+00-.955021556489723E-03 0.848583542242443E-01-.347055368580516E+00-.250105923935497E+00 -.111169531807995E-010.355726590647559E-020.103808638914381E+00 -.419452883677787E-020.629179201941255E-020.186690274364628E-01 0.284594451775678E-02-.187651556580809E+000.162329962057502E-01 0.630915974421175E+000.187697560444679E+00-.210296554317769E-01 -.720224407521837E+000.223339360929664E-02-.104660843730164E+00 -.610626897833574E-020.229830867380655E-010.282458435792497E-02 0.118792023957512E-01-.170210445347221E-020.280196207015836E-05 -.279505004776387E-030.277071634101624E-01-.228909652598038E-03 0.119275380848415E+000.132437572800541E-04-.187601509624841E+00 0.141896128311551E+000.422365578665326E+000.128760036033913E+00 -.204838957235195E+000.434078772092150E-01-.806694510076191E+00 0.157787515993729E+000.591835161997387E-020.747010198847334E-02 -.805107391111651E-050.638873231222047E-030.680896813628902E-01 0.535850756882113E-030.102376722309374E+00-.412953070633613E-04 -.276931733144833E-04-.197474903775786E-060.430124026148356E-04 0.398149815745455E+00-.263184149901006E-07-.620746678004172E-09 0.576570088020053E-070.103875521776964E-030.125421883145019E-03 0.739661812433390E-05-.270405853635920E-03-.857409440491406E+00 -.277976071921764E-07-.193794904133083E-070.662509931437069E-07 0.348154383702452E-04-.110067008670377E-03-.330352097595245E-04 0.493295101362000E-030.326075781848338E+000.261637800500639E-02 0.593341606111460E-030.314880806247675E-01-.856875384808786E-02 -.235422243388757E-010.258747526082075E-020.999168100504882E+00 0.319275874645435E-030.547296896534694E-02-.116992826176418E-02 0.338370513154134E-01-.142777025302056E-02-.406778354377311E-01 0.504020403061023E+000.882092418045004E-01-.541496381623848E+00 0.411585398853575E+000.256567719316976E+00-.245588779787715E-01 0.823411976718524E-02-.411585419791624E+00-.183646426853795E+00 -.192903059548171E-020.123785362328905E-030.558759547771277E-01 -.250818717172438E-020.733379618122733E-030.955412980135956E-02 0.892865110995397E-03-.540490019218027E-010.372660426311295E-01 0.185501518436011E+000.158352234759734E+00-.216219089020215E-01 -.753414549089406E+000.241909096941899E-01-.408978751559392E+00 -.892679382602970E-010.438255593031304E+000.202475991596905E-02 0.108697778577146E-01-.151558617647810E-020.158189155579921E-04 -.273419002779876E-030.226951112635693E-02-.192207014371830E-03 0.576369410134945E-010.124942742956545E-04-.131329073179166E+00 0.305611774621079E+000.254739263535127E+000.552445048191232E-01 -.164344958886550E+000.206564820276684E+00-.662834178384440E+00 0.544315066876567E+00-.396148205477567E-020.698461846680987E-01 -.954984862955493E-040.123919551849472E-020.329652662042095E-01 0.103982753519749E-020.824191920632282E-01-.137575992812755E-03 -.118262824998473E-040.123526003258420E-040.707450826197362E-04 0.199578367733588E+000.363708976451750E-070.321899201930129E-07 -.250041569150016E-080.225985817010339E-030.399465008189380E-03 -.383274536444598E-04-.146616509322618E-02-.883662801063188E+00 -.664010684521299E-05-.735402308780296E-050.216923907460852E-04 0.824256599274688E-03-.523153796336422E-03-.266383346326575E-03 0.361288604263049E-020.423428960439017E+000.173851036205211E-02 0.222870073788660E-020.147323973899202E+00-.145602763087638E-02 -.153553351053440E+000.124330762289657E+000.969144432517211E+00 -.670088769709058E-080.279928963613627E-02-.535336505050603E-03 0.571786431162824E-020.501111613013933E-04-.375294159509387E-01 0.286470981196203E+000.189845534980769E+00-.635875367893217E+00 0.398691041336605E+000.186217324361401E+00-.114177856312955E+00 0.244995441534964E+00-.398691042678259E+000.213291086621552E+00 -.702759278074976E-01-.285865195571977E-030.607323396528475E-02 0.177522666938543E-030.232624905150071E-040.871528520081471E-03 0.104242811764133E-03-.117190708001031E+000.172804418631202E-01 0.531354146114651E+000.147827925084915E+00-.173568415846287E-01 -.754028144632404E+000.362393328445694E-02-.504753734217587E-01 -.606045340700605E-010.326623017330199E+000.140948202581589E-03 0.702783387652478E-03-.107036079108171E-030.590209447893790E-07 -.908741189140752E-06-.537857176299051E-04-.821800159702671E-06 0.742259477778545E-020.175891555799017E-06-.127575373639961E+00 0.173884621836369E+000.488642885545859E+000.101063732588886E+00 -.130420282060893E+000.415306618536464E-01-.760148095701464E+00 0.976580937993439E-01-.254359609712527E-010.312471985413515E+00 -.574123283391161E-060.433910605356674E-050.205862756366894E-02 0.430410468022567E-050.783406586305063E-02-.778456164311075E-06 -.423214058359036E-030.919140921167062E-030.661874120526856E-02 0.117109755045484E+000.562189141098998E-030.519894877621451E-03 -.109887397286355E-020.184158676355906E-010.128559805126469E-01 -.985063481572301E-02-.793770939849137E-01-.885499725592162E+00 -.183772385564369E-02-.887523056274150E-030.105538790154888E-01 0.403343983135072E-01-.178576536206106E-01-.109963830700987E-01 0.165007678884550E+000.407206303906568E+000.306348529486999E-02 0.239930764984804E-070.601420059751685E+00-.141146313644592E-02 -.605225595551520E+000.230075880325225E+000.468016488374206E+00 0.318887906876394E-020.194968143237539E+00-.679696569745449E+00 -.194968123740749E+000.679696569745495E+000.433921650703326E-05 0.686239809673315E-040.134914310172025E-04-.158714965443381E-01 0.332719906827371E-020.784843725910340E-010.139678381750007E+00 -.317681035662774E-02-.734092568722168E+000.988288218555025E-04 -.128106164851903E-02-.122669376425973E+000.648163369247435E+00 0.894069909141543E-050.405720798599522E-04-.531085987799746E-05 -.171919591025308E-050.803049222354254E-050.130444794348500E-04 0.861156968395583E-050.110231449582210E-02-.248231645536447E-05 -.375937616255964E-010.355819759338922E-010.229692292043488E+00 0.108667338908260E+00-.264758743157882E-010.393712049859257E-02 -.813756878731386E+000.512266270133843E-02-.668002364102831E-01 0.515117604605447E+000.492260750079268E-05-.272219895394282E-04 0.208694217366870E-03-.283952525261720E-040.917376031998474E-03 0.581122815426736E-05-.455060985419248E-02-.919535789492620E-03 0.349190607723191E-010.763767596648188E-010.265591381650204E-02 0.521301039994967E-02-.401859423332637E-020.732525315960548E-01 0.535241281320955E-01-.115977550287200E-01-.375723852306493E+00 -.771464840486708E+00-.315965957352218E-01-.143459287868964E-07 0.227393868069098E+000.322787116054316E+00-.215711586956064E-01 0.108257024347966E-020.242983985741911E+000.178264096966029E+00 0.707106766183749E+00-.707106796189347E+000.177843854234752E+00 -.619997921177283E+000.540358273709987E+000.540358286028759E+00 -.131869994779899E+00-.196304501085975E-020.698246561864295E+00 0.130169226789683E+00-.691457997403106E+00-.128013211249068E-01 0.546427753459058E-01-.934052075111080E-01-.664941001276631E-01 0.678859335665877E+000.119191372805422E+00-.713195424947486E+00 -.404938617540185E-010.181062659918079E-010.232791185547601E-01 0.321138225103363E+000.619279730616487E+000.570137931646475E-01 0.258785337293530E-07-.410315942496114E+00-.582446223508185E+00 -.707106781186560E+000.707106781186535E+00-.721341536320415E-08 -.428989822532113E+00-.636689094459996E+00-.636689104237412E+00 -.722614261203267E-010.282343743720400E-010.938364903717614E-02 -.678889534403801E+00-.334569836275536E-010.732874066643181E+00 0.490057224614373E-010.139296369817684E-01-.713288124764123E+00 -.453244904721617E-01-.128587843097479E-010.697424647376202E+00 -.191282821385874E-020.400397255563485E-01-.392330176179403E-02 0.585593361868326E-08-.614848650012675E+00-.364459981119449E+00 -.378769195029760E-010.669732104564358E-020.591610797545009E+00 0.368820602608620E+000.123195855168806E-020.621112322271792E+00 -.142906888883486E-01-.629115104083898E+000.451903369348001E+00 0.118349072475903E+00-.110429569969675E-070.218385917379393E-02 0.474020131646410E-040.341856293650974E-020.106540652945231E-03 -.645360819374788E-02-.383127542619521E-010.125973858299685E-01 -.215314667589504E+000.493886045857771E+000.440903158857425E+00 -.363141787614656E-010.220456050264233E+00-.493886011421948E+00 -.468226459066813E+000.231829628021786E-01-.362744711248249E-04 0.492042069801937E-020.330696552912518E-040.202644371713308E-04 0.496659907643311E-030.736840121878654E-04-.198191879706170E-01 0.183303009260840E-010.449742417866469E+000.410829172385245E-01 -.221035301005096E-01-.845083570129830E+000.229988122217302E-01 -.633862858502668E-02-.190597419343020E-010.282360542508567E+00 -.915253709884024E-050.467860617318541E-03-.936082013898601E-06 -.471900999515919E-050.360154552581113E-04-.445382936066878E-05 0.161761440053278E-02-.699826636234017E-06-.100518297978727E-01 0.813344640279481E-010.322240982462986E+000.365348966340719E-01 -.898377311847809E-010.138505009350467E+00-.847528994615232E+00 0.484822858208514E-02-.286713955100532E-010.376428436355344E+00 0.305214288653784E-050.181194673226224E-040.148033919232344E-03 0.173905350410810E-040.178925671284225E-020.258695791232144E-05 -.135493060354600E-02-.135066372724518E-020.135603142952304E-01 0.185868253362159E-01-.352836497074884E-01-.511901396462545E-08 0.541814512743478E+000.321167993263074E+000.399514083113646E-01 -.879433456844653E-02-.619330290540681E+00-.454991628886887E+00 -.105596987591205E-020.705649764873231E-020.285295653675024E-01 0.585189397982255E-01-.120981119976275E-02-.164054205324875E-07 0.605748606344640E-010.359064075394220E-010.286188393180971E-02 0.302723797596224E+00-.393634811399195E-01-.303819324099225E+00 0.770938930261185E+000.468969096158830E+000.138220192540853E-01 0.495490516333219E-020.992452014486792E-030.282067170458185E-01 -.526320537210620E-03-.626140892699711E-02-.420916642531304E-01 -.372664848981284E-02-.271564230509885E+000.464750601983194E+00 0.441452754120364E+00-.154463635706786E-010.286305584915958E+00 -.464750603183541E+00-.459710281950070E+000.276903753399330E-01 0.164107973795033E-020.494331015087113E-01-.288169856338215E-02 0.181384528842341E-030.371596182844276E-020.528440319457944E-03 -.941885934972875E-020.370997823273176E-010.231848896187434E+00 0.366243340421597E-01-.532260858845199E-01-.799048803738820E+00 0.134190051866849E+00-.785968234612202E-01-.524280946553506E-01 0.524565851490170E+00-.969902988985165E-040.332166998097683E-02 0.178393887634442E-050.113533332194821E-040.181974060923368E-03 0.139673311333751E-040.748922993006937E-020.105594089085603E-05 -.125119713273718E-020.902096536931047E-010.147246951099762E+00 0.149737886688360E-01-.133913301824410E+000.418936033466391E+00 -.811341515728799E+000.369333524141069E-01-.333282371384749E-01 0.340069402844183E+00-.681313090765745E-05-.458006071986632E-04 0.684063550008274E-03-.518596031454553E-040.780440694537957E-02 -.545350364764260E-05-.188819474609356E-020.169410258829227E-02 0.212175769390214E-010.173958315025131E+00-.797638722213490E-02 -.293947799718114E-020.113587530023477E+000.109694252187022E+00 0.142919996767946E-01-.337701654742926E-01-.209384087697011E+00 -.845567642095652E+000.201133506974394E-020.616308901856066E-02 -.971356627744613E-020.292603070320401E-01-.560758539688166E-02 -.946440555507977E-070.280843258259704E+000.322810651789196E+00 0.100624941112454E-010.259672364681204E-020.817713789100689E-01 -.378487363357314E-01-.713365278141413E-010.523743917330373E-01 0.991717031383619E+000.197738512819566E-020.208413168788660E-01 0.650446596813922E-020.135072660963680E+00-.621746918612862E-02 -.966281355133967E-03-.918875977233796E-02-.289501236543810E-01 -.685382822420014E+000.361708105505221E+000.357137550448023E+00 -.266613412827571E-010.782040935170842E-01-.361708121793891E+00 -.239799476892995E+00-.985520373764162E-030.124217593525461E-01 0.238575082904427E+00-.196146477726306E-010.488773826113334E-02 0.349527507620209E-010.379484360472854E-02-.190335388122274E-02 0.447950884527639E-010.432841152042769E-010.388755048096654E-01 -.538304662046303E-01-.789807137487042E+000.235705022604824E+00 -.513957403747273E+00-.370616288007413E-010.209032049105300E+00 -.288368196965015E-020.432040578288786E-010.127521601121691E-04 0.168677884713730E-030.617877501892261E-020.276772111811215E-03 0.600611597756269E-010.241666265834041E-040.303528049568012E-02 0.942997003617236E-010.379042102331497E-01-.330454305947829E-01 -.128113287104398E+000.555973181880454E+00-.775895571131535E+00 0.198144727494078E+00-.310709714778411E-010.100592357864689E+00 -.672609772397682E-04-.639611891632221E-030.104051260731826E-01 -.875477524731695E-030.832817668969010E-01-.846727903271358E-04 -.207408821420728E-030.486560668082637E-050.979491912068454E-03 0.277397787870578E+00-.138842323987768E-04-.406202819318755E-04 0.110309257668976E-030.939959189060195E-030.569551259786794E-03 -.294882488065178E-03-.498973942338665E-02-.880817149857464E+00 0.187425605060980E-060.501129676429758E-06-.300671605978139E-06 0.241872213478973E-03-.255178043170943E-03-.120288168640803E-07 0.127780982294317E-010.383433180051282E+000.725838932670944E-01 0.252083195843648E-020.117006173486548E+00-.223393012118206E+00 -.208342404872242E+000.234209847200587E-020.930605964661460E+00 0.173828081375503E-030.147277990800831E+000.181434246890757E-03 0.170536287384264E+00-.309107241232440E-030.259166691097343E-02 0.267966291631130E-010.188199924025729E-01-.669691184768908E+00 0.369388402445399E+000.298437454764436E+00-.279860191285971E-01 0.602660083184696E-01-.369388385141567E+00-.248022967896360E+00 -.464439367770653E-020.500024221342130E-030.305677755406208E+00 -.444449132690379E-030.124526942124952E-010.412389063954632E-01 0.477962868100348E-020.121324350674267E-030.172316413671693E-01 0.206626091962812E-020.826042674682101E-01-.291949989074805E-01 -.807935585115537E+000.719562126724321E-02-.844418266345479E-01 -.865202850613294E-010.565496269575906E+00-.854734894082898E-02 0.534551683245710E-010.248113583813972E-040.284156083985196E-03 0.468661828942036E-010.323108007624496E-030.188307985273998E+00 -.544725160151694E-050.322850342593503E-020.113497207464359E+00 0.155469184155135E-01-.196939954403634E+00-.194657514389626E+00 0.969404504569904E-01-.859164413239739E+000.872264017923245E-01 -.388952182996452E-010.189593190383465E+00-.795671796675343E-04 -.822688558144623E-030.606453458049934E-01-.908377415704067E-03 0.276089968873254E+000.114472964265622E-04-.488773078956015E-04 -.396188336235372E-050.999659673670207E-040.310777183676489E+00 -.571298251501996E-07-.143066131598022E-060.317328824163547E-06 0.183060084594285E-040.886359900474387E-040.190300654410858E-04 -.393117861683414E-03-.877646247157486E+00-.373857766313145E-07 0.404625131158292E-080.185231894502927E-060.706529209549547E-04 -.204895952319792E-04-.194471437864013E-080.102610554232600E-02 0.364901867847999E+000.517095658659024E-010.980626985835659E-04 0.109751994430230E+00-.156570782738845E+00-.139532788543006E+00 0.213245059817445E-020.964892906217063E+000.251687159024994E-02 0.101329163413399E+000.277117162597201E-020.118636768143132E+00 -.352176514804628E-02-.151217924652192E-020.119996119063301E+00 0.301941926097845E-01-.609479618054216E+000.407610676820285E+00 0.303999762041851E+000.761324043901745E-020.710147150771023E-02 -.407610668100491E+00-.356147653325360E+00-.939570530183214E-03 0.763317786414497E-020.217680817050759E+00-.493762301165418E-02 0.146000447120399E-010.479479620035907E-010.566504813998350E-02 -.844499638835638E-010.256283929519846E-010.544801062552938E+00 0.737368671651306E-01-.326618131262042E-01-.812123287123367E+00 0.154297518539648E-01-.144246520083369E+00-.462193369264405E-02 0.445557502386635E-01-.935867171427351E-020.605927338092271E-01 -.336190661502138E-050.199412672691505E-030.450587704881531E-01 0.172855825862255E-030.183127683802625E+00-.139506417990564E-04 -.371032128812401E-010.136441962315432E+000.173292355829121E+00 -.191031363946136E+00-.181314220103855E+000.140001406724419E+00 -.858012964858887E+000.124946578064121E+000.319424061996110E-02 0.399157810449760E-010.690865516433771E-05-.548226189109581E-03 0.563223050755544E-01-.459820360442181E-030.262427675882098E+00 0.354360602071234E-04-.450936989333873E-04-.377667649549115E-05 0.945332035517973E-040.319025562226798E+00-.368743805844936E-07 -.308404229414676E-080.169494334962014E-060.602269526486935E-04 0.812755972306230E-040.174914793561078E-04-.370843264734492E-03 -.875757998566261E+00-.335945798006633E-07-.675440572999075E-07 0.170899586778266E-060.198556153617846E-04-.186285422087375E-04 -.200657120064962E-080.932994787873637E-030.362311452102434E+00 0.191936222893093E-010.258518345891082E-020.109774305627631E+00 -.678956495743090E-01-.847535774245336E-010.232392489249417E-01 0.986521218946578E+000.106117819809660E-020.449024629045529E-01 0.124017224428534E-030.574386556615052E-01-.199965617249553E-02 -.247780638305697E-010.321522084088771E+000.379770340137811E-01 -.428306904638573E+000.454704028913566E+000.379204249645586E+00 -.148852886838934E-02-.367461131823450E-01-.454704049118167E+00 -.369132510355556E+000.664495198760334E-020.334719861886340E-02 0.113293303776695E+00-.281077382106382E-020.819596959668489E-02 0.379111551975742E-010.321568225388857E-02-.459084942734722E-01 0.541417868140426E-010.284992838760775E+000.576708222071649E-01 -.319166382924372E-01-.850884680215138E+000.981709154419468E-01 -.314558014739248E+00-.238292299646862E-010.267247900942539E+00 -.476409274846684E-020.572696388851242E-01-.253434325420875E-05 0.314019523401166E-040.175619612277255E-010.268781992242801E-04 0.102137732079325E+00-.352118389928833E-05-.431151846300100E-01 0.194195952369355E+000.171383771689655E+00-.727889707064056E-01 -.105037796330727E+000.373070405104482E+00-.832876291198495E+00 0.185201328324870E+00-.210719287242549E-020.883704590081362E-01 0.759148616038630E-05-.985068757445580E-040.241611227450762E-01 -.826584349992673E-040.168592324349136E+000.109363536546192E-04 -.140286296725473E-03-.128215836815657E-040.494558244488533E-03 0.280847654126040E+000.321515679088376E-070.120434247248497E-06 -.156044392922250E-070.887469968549317E-040.309083310171081E-03 -.137384777211738E-04-.226540409047954E-02-.880128001169638E+00 -.382651653993193E-05-.108131101348007E-040.233963836825757E-04 0.270492489874145E-03-.122252666299678E-030.612356227618477E-02 0.382695975727179E+000.732428021226023E-020.547713996664140E-02 0.396049984501415E+00-.481141822977436E-01-.405642629586525E+00 0.635749564952352E+000.521347508869209E+000.148024935841334E-01 -.301295407799686E-030.723544959371664E-020.207642865415858E-03 -.348694792387385E-010.263550631173699E+000.889595566279424E-01 -.418984214602752E+000.500266357695299E+000.408119429597393E+00 -.363233885356471E-010.804413318688337E-01-.500266373002098E+00 -.265517664767941E+00-.164627094124487E-01-.292271209593851E-03 0.124794323490641E-010.336449804275239E-030.498076969884902E-03 0.271691736959086E-020.231277279264080E-03-.567655532785492E-01 0.271848648436447E-010.503661384603298E+000.655366565640398E-01 -.243230693129746E-01-.789632788520066E+000.183179034548534E-01 -.311651765431028E-01-.255025625534976E-010.334633855693646E+00 -.190063900887600E-030.353945762482508E-02-.977710956462515E-05 0.746309618330485E-040.131595722141013E-020.739405964402529E-04 0.119008502370693E-01-.173222930707446E-04-.555999356456072E-01 0.142824249504943E+000.430859451845448E+000.458944077528358E-01 -.115195465102762E+000.132957232431433E+00-.828429389734122E+00 0.298427846700954E-01-.960653777292320E-020.264770324901898E+00 0.294775292625976E-04-.222797414239782E-030.199648632405749E-02 -.221026344617562E-030.169463786498493E-010.399691019732668E-04 -.412776023938866E-020.252572320635840E-030.233873710864906E-01 0.259719891251546E+000.415140740182975E-030.113529818985204E-02 -.174804710873652E-020.578214115132270E-020.122117368574587E-01 -.751426870967600E-02-.124904020763724E+00-.845228958797211E+00 -.212620236485092E-02-.168622369330729E-020.211514253839871E-01 0.215369670240951E-01-.534820692965796E-02-.144346899834284E-06 0.267863054400291E+000.359203496211911E+000.331086374854943E-02 -.845474757581534E-080.632504086378518E+00-.235118751978227E-01 -.638143102372112E+000.422974828693201E+000.114871343439142E+00 0.183672600439000E-070.671269422302639E-020.141774326820363E+00 -.692748182182047E+00-.141774300990027E+000.692748182182314E+00 0.481957392698951E-040.270388157735588E-030.258091963527867E-04 -.154613472923139E-010.788913409868525E-020.166281063480095E+00 0.631548573348084E-01-.719098717124253E-02-.783605853008467E+00 0.133352995840027E-02-.155351765852490E-02-.469231283040379E-01 0.593097595003567E+00-.145124296629042E-040.363129440721168E-03 -.755130544285567E-050.322329789563514E-040.162865732101339E-03 0.337458039242355E-040.188676716333058E-02-.967983875236429E-05 -.280294852982924E-010.560451599699661E-010.283514625914695E+00 0.623656558031793E-01-.513514652564355E-010.206258387156799E-01 -.826238746166489E+000.239687498883366E-02-.329344008682935E-01 0.474308373685584E+000.161872833336829E-04-.895145426991688E-04 0.315360387518861E-03-.933730942829438E-040.280130679481694E-02 0.191092696904015E-04-.835451218901018E-02-.224824288339140E-02 0.516928270523294E-010.109704348827131E+000.108269387812490E-02 0.107731305293616E-010.427800356853278E-020.368562069578784E-01 0.485484135495873E-01-.102507986038446E-01-.552216485696899E+00 -.594260620325315E+00-.316691755671850E-01-.132825140699132E-07 0.364597166754599E+000.174700089420081E+00-.717406486290489E-02 0.359222945921040E+000.172123612118179E+000.707106781186543E+00 -.707106781186557E+000.101992154740172E+00-.498361637024495E+00 0.608782920354223E+000.608782912866900E+00-.563724703278934E-01 -.438434828311532E-020.716766147603742E+000.537258122841962E-01 -.692937766919190E+00-.627170199294769E-020.346820800292373E-01 -.597760582014308E-01-.390085053120361E-010.691950856253261E+00 0.704045963162265E-01-.714079956171652E+00-.518737623309080E-01 0.761022812732684E-020.159550167655143E-010.604843345813386E+00 0.321896613542082E+000.567209593954754E-010.237137403293247E-07 -.653010405795925E+00-.312895948443595E+000.707106728865803E+00 -.707106833507286E+000.115866760025710E+000.687858841009181E+00 0.115866760025706E+00-.115866777390875E+00-.687858841015537E+00 -.115866765820121E+000.199959993541363E-01-.999800060016923E+00 0.199959993541364E-01-.999800060016920E+000.591447559760272E+00 -.774079952713837E+000.225809678402336E+000.707106745792210E+00 -.707106816580882E+000.102933637605961E+000.691960495020240E+00 0.102933654691574E+00-.102933654674223E+00-.691960495026485E+00 -.102933660046180E+000.199959993541364E-01-.999800060016920E+00 0.199960012762684E-01-.999800059978472E+00-.127452310568665E-01 -.132034018886979E-060.193643357350621E+000.641757529728320E+00 0.127452468624267E-010.175461378776522E-06-.638150377049360E+00 -.378270719499168E+000.707106745792551E+00-.707106816580538E+00 0.735498311658631E-010.699414631300659E+000.735498231523910E-01 -.735498255093039E-01-.699414659275387E+00-.735498261761447E-01 0.199960012762683E-01-.999800059978476E+000.199960003152027E-01 -.999800059997703E+00-.793687288626499E-02-.801466233668395E-07 0.109332282606681E+000.788133320380449E+000.793689353370808E-02 0.133933796941923E-06-.397501359005163E+00-.456901524012506E+00 0.707106745794469E+00-.707106816578630E+000.677577761723365E-01 0.700583874311953E+000.677577840360550E-01-.677577956934772E-01 -.700583874313761E+00-.677577869993615E-010.199960022373348E-01 -.999800059959256E+000.199960012762687E-01-.999800059978472E+00 -.319883555175909E-03-.118986023366735E-070.281838347380330E-02 0.876754646848632E+000.319884871920509E-030.150806759592284E-07 -.160183057271965E-01-.480662620945026E+000.707106745795564E+00 -.707106816577532E+00-.890947474946424E-020.706994528505650E+00 -.890947463346475E-020.890947671897219E-02-.706994499014701E+00 0.890947653156449E-020.199960022373347E-01-.999800059959259E+00 0.199960012762683E-01-.999800059978472E+00-.260858972545533E-04 -.191844269302226E-080.122620469735823E-030.885535385661900E+00 0.260860624298151E-040.247588712962808E-08-.130637283259506E-02 -.464570078388519E+000.707106732355502E+00-.707106830017597E+00 -.541723283909854E-010.702944338249317E+00-.541723317379545E-01 0.541723443718538E-01-.702944299891371E+000.541723452463965E-01 0.199960003152022E-01-.999800059997696E+000.199959993541364E-01 -.999800060016920E+00-.239127687416373E-04-.151460465105004E-08 0.115672896862657E-030.885262435736919E+000.239129677845735E-04 0.257585781747041E-08-.119766065837865E-02-.465090282588456E+00 0.707106725206366E+00-.707106837166720E+00-.919589760709782E-01 0.695044669841039E+00-.919589734520017E-010.919589804407779E-01 -.695044669843202E+000.919589782786625E-010.199960022373347E-01 -.999800059959252E+000.199960022373348E-01-.999800059959256E+00 -.151924628664646E-03-.510312341108572E-080.114456686280757E-02 0.879637007792521E+000.151925412556267E-03-.760985148748386E-02 -.475583292900870E+000.707106745794441E+00-.707106816578655E+00 -.123882094148375E+000.685059468109205E+00-.123882083877434E+00 0.123882100598866E+00-.685059436248697E+000.123882101836301E+00 0.199960012762683E-01-.999800059978476E+000.199960012762682E-01 -.999800059978480E+00-.678767592186647E-02-.117643398718500E-06 0.687172030420897E-010.819622591650248E+000.678770879243693E-02 0.183330445795151E-06-.339959963271509E+00-.455885765406123E+00 0.707106745794739E+00-.707106816578357E+00-.139007785337744E+00 0.679230170872582E+00-.139007785337747E+000.139007815139815E+00 -.679230226703378E+000.139007815139786E+000.199960003152020E-01 -.999800059997686E+000.199960003152021E-01-.999800059997696E+00 -.141044682813303E-01-.262174622790849E-060.157938172071501E+00 0.601128701028703E+000.141045167897438E-01-.706247527620910E+00 -.338402681597202E+000.707106745794821E+00-.707106816578275E+00 -.267856550417132E+000.654410317897785E+000.267856566195439E+00 -.654410317899671E+000.199960012762682E-01-.999800059978476E+00 0.199960012762681E-01-.999800059978476E+000.593949158047806E+00 0.223352700169129E+00-.772876425427416E+00 0.202394105899437E-120.274823389968666E-14-.554892366794151E-15 -.819274160312709E-15-.668810055472496E-160.212241558104048E-12 0.526299506130443E-14-.489385623532121E-15-.677032376568762E-15 -.451623379287585E-150.374666605049989E-120.222425138831361E-13 -.181544572943050E-14-.147988975572570E-14-.186104552378963E-14 0.000000000000000E+000.000000000000000E+000.435189840959789E-14 -.382967060044728E-130.505291153767714E-160.000000000000000E+00 0.000000000000000E+000.435189840959789E-14-.226298717299133E-13 0.121146683837838E-140.000000000000000E+000.000000000000000E+00 0.435189840959789E-140.130556952287927E-130.445674391403092E-14 0.000000000000000E+000.000000000000000E+000.435189840959789E-14 -.783341737833116E-140.234227328474855E-140.108206124046458E-12 -.215883859283577E-14-.403946870939676E-15-.686616926286516E-15 -.862012111631899E-150.303533244284811E-130.138010344467711E-14 -.404018824222715E-15-.286385196638407E-15-.390704401891710E-15 0.273411624622911E-13-.765610157434584E-15-.268141684612874E-15 -.132194093079351E-15-.601621965854667E-150.000000000000000E+00 0.384762796083885E-13-.193731562836694E-15-.413645768293773E-14 -.114278485295537E-050.807508878162117E-13-.380818779406990E-13 0.223648500602427E-14-.909889585701067E-140.331562834926780E-05 0.285043306029678E-12-.207058352673703E-13-.636970533077854E-14 0.524252010357629E-140.269297853105648E-050.171627453082871E-14 0.717975632069722E-14-.527448437137286E-140.464287948246645E-13 0.771098257180396E-080.234809096656618E-14-.359395808792810E-14 0.665552106043155E-140.757280959611803E-140.143718570281886E-11 0.222572869532307E-14-.139716009607018E-130.780446860517369E-15 0.362157028369366E-130.536540168957500E-100.307875265929601E-14 -.705504318733115E-140.337799402074240E-140.500401555294291E-13 0.426280731858752E-080.913287848754867E-130.103614716445489E-13 -.522859350784418E-140.499148370186354E-140.478624017132153E-05 0.121456366975691E-130.101624213254850E-140.216701101200512E-14 -.345271197980365E-140.110880789697911E-050.301216196618491E-14 -.540428228214019E-14-.222140164388316E-140.434955330079947E-15 -.160601989555048E-050.157559231112031E-130.420001628718037E-12 0.150572252957974E-13-.606223423353496E-13-.281774303279372E-03 -.161762764929301E-12-.342092744508673E-120.108249355143259E-12 -.615731698119600E-120.114252946436998E-030.846620542762694E-13 -.152621157809399E-12-.109809342763844E-12-.217943874621490E-12 0.797723962847499E-050.180888084740301E-130.122644376958020E-12 0.888551767886481E-130.204169584974151E-120.639904466172473E-07 0.102694065070745E-130.185542222646612E-13-.980356568716921E-14 0.213689007015383E-130.148657983204524E-100.938171534597355E-14 0.386707150480676E-130.185686924559307E-130.629279530815653E-13 0.178538186267594E-090.303591605636916E-130.247507485473141E-12 0.601948765785340E-130.259328208787118E-130.825012119453497E-07 0.165489865824259E-130.126909717971805E-12-.809972621173125E-15 0.260221066762617E-120.440673145488575E-04-.577391192374903E-13 -.141685739715840E-13-.898379506962308E-14-.587589075806416E-13 0.854336895419281E-040.695114309023588E-14-.183400756501765E-12 -.351268034790456E-13-.212800439402798E-13-.786196346629773E-03 0.231704757800883E-140.428729786047385E-12-.921006657969298E-13 -.722393149668797E-13-.500822403978593E-04-.114151854183011E-12 -.219912598762636E-120.126673756206235E-12-.382620831589828E-12 0.297225488674877E-040.234508048410960E-12-.218856288176897E-12 -.406403766139363E-12-.198463290029409E-120.217128723459237E-04 0.756454004598282E-130.728205498076627E-130.218097882502026E-12 0.166565512837028E-120.194699855455599E-060.325953303999443E-13 0.141059018716547E-120.163148755045124E-140.168350227066847E-13 0.364655761535216E-100.318693236147873E-130.629300865896806E-12 0.832072227609808E-130.104391586556431E-120.219566882979375E-08 0.966294840559207E-130.105322792611619E-120.154817975688185E-11 -.129150687222302E-120.159284559755380E-060.255359618793750E-12 -.669568573719880E-12-.140319512989452E-11-.148808193119654E-11 0.174243935653877E-040.235964900478605E-13-.158921691210278E-14 0.427286687073893E-13-.383875253964354E-130.209458122839295E-04 0.695114255617233E-15-.778936609739444E-12-.555263495967613E-13 0.178057460686566E-12-.931728111057866E-040.162193337546363E-14 0.192082021351027E-12-.338830504552759E-13-.259959064560709E-13 -.102908168635522E-040.119780901141838E-12-.705626182733349E-13 0.477777856036666E-13-.122188353215107E-120.628204494195552E-05 0.360502341905674E-12-.158458353411481E-12-.107460877005768E-12 -.543852067739607E-130.999832651169842E-050.223928511470390E-12 0.219031617335137E-130.683930191759728E-130.993011534250549E-13 0.421065904949251E-070.795593192526987E-130.200393330802057E-14 -.544643938855520E-14-.129085088280889E-130.307220157212393E-10 0.769647462983260E-13-.708645844756138E-130.190209280278036E-13 0.140249871726619E-15-.129729632851381E-080.200188825456105E-12 0.416378030603160E-130.430348021674659E-13-.704010864682257E-14 0.216263094106671E-080.146886604283455E-120.841533706518667E-13 -.661595658689806E-13-.941058011231196E-140.391430381205002E-05 -.756476598943381E-13-.606765392737815E-140.229242559524678E-13 -.319044605764485E-130.548350629631716E-050.695114303103693E-15 -.146061553715816E-12-.276900163448222E-130.327090370418689E-14 -.241110654148327E-040.497470124823223E-120.178190122707317E-13 -.335610877544072E-150.269804823123547E-15-.754610311602206E-14 0.504652984537124E-120.132811426043152E-130.276385428565550E-15 0.171095749713042E-15-.565706170888985E-090.495616483348267E-12 0.270460386923519E-140.213967823565366E-160.114116167083434E-15 -.307378214952379E-090.148059343055948E-120.704938251717327E-15 0.796554343080852E-160.134418545397471E-15-.214702302708836E-10 0.264143427774681E-13-.393383383587686E-15-.224429000369457E-15 -.166387009518229E-15-.956414562064006E-130.275728664863706E-13 -.252625379126553E-140.290067003721533E-16-.372943254642494E-16 -.292904363272568E-110.108669533011201E-12-.373828633891879E-14 -.135252686834076E-150.811516121004296E-16-.248539101337132E-10 0.179802895868020E-12-.101106161740470E-13-.776828549128017E-16 -.185243730945928E-15-.969762553748463E-090.132071717589703E-12 -.156903353468787E-14-.269565415329845E-15-.275066750336520E-16 -.168359295253083E-080.123035231649352E-12-.239352379930970E-14 -.225554746116851E-150.935226996093998E-16-.392547043891108E-14 Matrix/inst/external/lund_a.mtx0000644000175100001440000010575510275502035016343 0ustar hornikusers%%MatrixMarket matrix coordinate real symmetric 147 147 1298 1 1 7.5000000000000e+07 2 1 9.6153881000000e+05 8 1 -1.2179486000000e+07 9 1 -2.6175210000000e+06 10 1 2.8846144000000e+07 11 1 5.7692300000000e+06 2 2 7.5000000000000e+07 3 2 9.6153869000000e+05 9 2 -7.4786312000000e+04 10 2 9.6153840000000e+06 11 2 -1.2179486000000e+07 12 2 -2.6175210000000e+06 13 2 2.8846144000000e+07 14 2 5.7692300000000e+06 3 3 7.5000000000000e+07 4 3 9.6153844000000e+05 12 3 -7.4786375000000e+04 13 3 9.6153840000000e+06 14 3 -1.2179486000000e+07 15 3 -2.6175210000000e+06 16 3 2.8846144000000e+07 17 3 5.7692310000000e+06 4 4 7.5000000000000e+07 5 4 9.6153869000000e+05 15 4 -7.4786312000000e+04 16 4 9.6153840000000e+06 17 4 -1.2179487000000e+07 18 4 -2.6175210000000e+06 19 4 2.8846144000000e+07 20 4 5.7692300000000e+06 5 5 7.5000000000000e+07 6 5 9.6153894000000e+05 18 5 -7.4786375000000e+04 19 5 9.6153840000000e+06 20 5 -1.2179486000000e+07 21 5 -2.6175210000000e+06 22 5 2.8846160000000e+07 23 5 5.7692310000000e+06 6 6 7.5000000000000e+07 7 6 9.6153894000000e+05 21 6 -7.4786312000000e+04 22 6 9.6153850000000e+06 23 6 -1.2179488000000e+07 24 6 -2.6175220000000e+06 25 6 2.8846160000000e+07 26 6 5.7692310000000e+06 7 7 4.4230768000000e+07 24 7 -7.4786312000000e+04 25 7 9.6153850000000e+06 26 7 -1.2179488000000e+07 27 7 -1.5405980000000e+06 28 7 1.4423078000000e+07 8 8 7.5000000000000e+07 9 8 2.6175210000000e+06 10 8 5.7692300000000e+06 11 8 2.8846144000000e+07 29 8 9.6153831000000e+05 9 9 5.0256406000000e+05 10 9 7.8125000000000e-03 11 9 7.8125000000000e-03 12 9 -1.2564100000000e+05 13 9 7.4786312000000e+04 14 9 -2.6175210000000e+06 29 9 7.4786312000000e+04 30 9 -1.2564100000000e+05 31 9 2.6175210000000e+06 32 9 -7.4786312000000e+04 10 10 1.4999998000000e+08 11 10 1.2820510000000e+06 12 10 -7.4786312000000e+04 13 10 1.9230770000000e+06 14 10 5.7692310000000e+06 29 10 -1.2179486000000e+07 30 10 -2.6175210000000e+06 31 10 2.8846144000000e+07 32 10 5.7692300000000e+06 11 11 1.4999998000000e+08 12 11 2.6175210000000e+06 13 11 5.7692300000000e+06 14 11 2.8846144000000e+07 29 11 9.6153840000000e+06 30 11 7.4786312000000e+04 31 11 5.7692300000000e+06 32 11 1.9230770000000e+06 12 12 5.0256406000000e+05 13 12 -1.0937500000000e-01 14 12 5.4687500000000e-02 15 12 -1.2564100000000e+05 16 12 7.4786312000000e+04 17 12 -2.6175210000000e+06 30 12 -2.4414062000000e-04 31 12 7.4786375000000e+04 32 12 7.4786312000000e+04 33 12 -1.2564100000000e+05 34 12 2.6175210000000e+06 35 12 -7.4786250000000e+04 13 13 1.4999998000000e+08 14 13 1.2820520000000e+06 15 13 -7.4786312000000e+04 16 13 1.9230770000000e+06 17 13 5.7692300000000e+06 30 13 -7.4786312000000e+04 31 13 9.6153840000000e+06 32 13 -1.2179487000000e+07 33 13 -2.6175210000000e+06 34 13 2.8846144000000e+07 35 13 5.7692300000000e+06 14 14 1.4999998000000e+08 15 14 2.6175210000000e+06 16 14 5.7692300000000e+06 17 14 2.8846144000000e+07 30 14 -7.4786375000000e+04 31 14 -1.2179486000000e+07 32 14 9.6153840000000e+06 33 14 7.4786312000000e+04 34 14 5.7692310000000e+06 35 14 1.9230770000000e+06 15 15 5.0256406000000e+05 16 15 1.4843750000000e-01 17 15 -1.1718750000000e-01 18 15 -1.2564100000000e+05 19 15 7.4786312000000e+04 20 15 -2.6175210000000e+06 33 15 -3.6621094000000e-04 34 15 7.4786375000000e+04 35 15 7.4786250000000e+04 36 15 -1.2564100000000e+05 37 15 2.6175210000000e+06 38 15 -7.4786312000000e+04 16 16 1.4999998000000e+08 17 16 1.2820510000000e+06 18 16 -7.4786312000000e+04 19 16 1.9230770000000e+06 20 16 5.7692310000000e+06 33 16 -7.4786250000000e+04 34 16 9.6153840000000e+06 35 16 -1.2179488000000e+07 36 16 -2.6175210000000e+06 37 16 2.8846160000000e+07 38 16 5.7692310000000e+06 17 17 1.4999998000000e+08 18 17 2.6175210000000e+06 19 17 5.7692310000000e+06 20 17 2.8846144000000e+07 33 17 -7.4786375000000e+04 34 17 -1.2179485000000e+07 35 17 9.6153830000000e+06 36 17 7.4786375000000e+04 37 17 5.7692300000000e+06 38 17 1.9230770000000e+06 18 18 5.0256406000000e+05 19 18 -1.3281250000000e-01 20 18 1.7187500000000e-01 21 18 -1.2564100000000e+05 22 18 7.4786312000000e+04 23 18 -2.6175210000000e+06 36 18 4.8828125000000e-04 37 18 7.4786312000000e+04 38 18 7.4786312000000e+04 39 18 -1.2564100000000e+05 40 18 2.6175210000000e+06 41 18 -7.4786250000000e+04 19 19 1.4999998000000e+08 20 19 1.2820510000000e+06 21 19 -7.4786375000000e+04 22 19 1.9230770000000e+06 23 19 5.7692300000000e+06 36 19 -7.4786250000000e+04 37 19 9.6153840000000e+06 38 19 -1.2179488000000e+07 39 19 -2.6175210000000e+06 40 19 2.8846144000000e+07 41 19 5.7692300000000e+06 20 20 1.4999998000000e+08 21 20 2.6175210000000e+06 22 20 5.7692300000000e+06 23 20 2.8846144000000e+07 36 20 -7.4786375000000e+04 37 20 -1.2179487000000e+07 38 20 9.6153850000000e+06 39 20 7.4786375000000e+04 40 20 5.7692310000000e+06 41 20 1.9230760000000e+06 21 21 5.0256412000000e+05 22 21 3.2031250000000e-01 23 21 -6.8750000000000e-01 24 21 -1.2564106000000e+05 25 21 7.4786375000000e+04 26 21 -2.6175220000000e+06 39 21 -1.2207031000000e-04 40 21 7.4786437000000e+04 41 21 7.4786187000000e+04 42 21 -1.2564106000000e+05 43 21 2.6175220000000e+06 44 21 -7.4786375000000e+04 22 22 1.5000002000000e+08 23 22 1.2820520000000e+06 24 22 -7.4786312000000e+04 25 22 1.9230770000000e+06 26 22 5.7692320000000e+06 39 22 -7.4786250000000e+04 40 22 9.6153840000000e+06 41 22 -1.2179490000000e+07 42 22 -2.6175220000000e+06 43 22 2.8846160000000e+07 44 22 5.7692320000000e+06 23 23 1.5000000000000e+08 24 23 2.6175220000000e+06 25 23 5.7692320000000e+06 26 23 2.8846160000000e+07 39 23 -7.4786437000000e+04 40 23 -1.2179483000000e+07 41 23 9.6153830000000e+06 42 23 7.4786312000000e+04 43 23 5.7692320000000e+06 44 23 1.9230770000000e+06 24 24 5.0256419000000e+05 25 24 4.1406250000000e-01 26 24 8.5937500000000e-02 27 24 -1.2564106000000e+05 28 24 7.4786375000000e+04 42 24 3.6621094000000e-04 43 24 7.4786312000000e+04 44 24 7.4786375000000e+04 45 24 -1.2564106000000e+05 46 24 2.6175220000000e+06 47 24 -7.4786375000000e+04 25 25 1.5000002000000e+08 26 25 1.2820510000000e+06 27 25 -7.4786312000000e+04 28 25 1.9230770000000e+06 42 25 -7.4786312000000e+04 43 25 9.6153860000000e+06 44 25 -1.2179491000000e+07 45 25 -2.6175220000000e+06 46 25 2.8846160000000e+07 47 25 5.7692320000000e+06 26 26 1.5000002000000e+08 27 26 2.6175220000000e+06 28 26 5.7692320000000e+06 42 26 -7.4786375000000e+04 43 26 -1.2179491000000e+07 44 26 9.6153880000000e+06 45 26 7.4786375000000e+04 46 26 5.7692320000000e+06 47 26 1.9230770000000e+06 27 27 2.5128206000000e+05 28 27 4.6367550000000e+05 45 27 3.6621094000000e-04 46 27 7.4786312000000e+04 47 27 7.4786375000000e+04 48 27 -6.2820531000000e+04 49 27 1.0769230000000e+06 28 28 7.5000016000000e+07 45 28 -7.4786312000000e+04 46 28 9.6153860000000e+06 47 28 -1.2179491000000e+07 48 28 -1.5405990000000e+06 49 28 1.4423080000000e+07 29 29 7.5000000000000e+07 30 29 2.6175210000000e+06 31 29 5.7692300000000e+06 32 29 2.8846144000000e+07 50 29 9.6153831000000e+05 30 30 5.0256406000000e+05 31 30 -1.0937500000000e-01 32 30 5.4687500000000e-02 33 30 -1.2564100000000e+05 34 30 7.4786250000000e+04 35 30 -2.6175210000000e+06 50 30 7.4786312000000e+04 51 30 -1.2564100000000e+05 52 30 2.6175210000000e+06 53 30 -7.4786312000000e+04 31 31 1.4999998000000e+08 32 31 1.2820520000000e+06 33 31 -7.4786312000000e+04 34 31 1.9230770000000e+06 35 31 5.7692310000000e+06 50 31 -1.2179486000000e+07 51 31 -2.6175210000000e+06 52 31 2.8846144000000e+07 53 31 5.7692300000000e+06 32 32 1.4999998000000e+08 33 32 2.6175210000000e+06 34 32 5.7692300000000e+06 35 32 2.8846144000000e+07 50 32 9.6153840000000e+06 51 32 7.4786312000000e+04 52 32 5.7692300000000e+06 53 32 1.9230770000000e+06 33 33 5.0256412000000e+05 34 33 2.4218750000000e-01 35 33 -3.8281250000000e-01 36 33 -1.2564106000000e+05 37 33 7.4786375000000e+04 38 33 -2.6175220000000e+06 51 33 -4.8828125000000e-04 52 33 7.4786312000000e+04 53 33 7.4786312000000e+04 54 33 -1.2564100000000e+05 55 33 2.6175210000000e+06 56 33 -7.4786375000000e+04 34 34 1.4999998000000e+08 35 34 1.2820510000000e+06 36 34 -7.4786312000000e+04 37 34 1.9230770000000e+06 38 34 5.7692310000000e+06 51 34 -7.4786250000000e+04 52 34 9.6153820000000e+06 53 34 -1.2179487000000e+07 54 34 -2.6175210000000e+06 55 34 2.8846160000000e+07 56 34 5.7692300000000e+06 35 35 1.4999998000000e+08 36 35 2.6175220000000e+06 37 35 5.7692310000000e+06 38 35 2.8846160000000e+07 51 35 -7.4786375000000e+04 52 35 -1.2179485000000e+07 53 35 9.6153840000000e+06 54 35 7.4786312000000e+04 55 35 5.7692310000000e+06 56 35 1.9230770000000e+06 36 36 5.0256412000000e+05 37 36 -2.3437500000000e-02 38 36 3.4375000000000e-01 39 36 -1.2564100000000e+05 40 36 7.4786250000000e+04 41 36 -2.6175210000000e+06 54 36 2.4414062000000e-04 55 36 7.4786312000000e+04 56 36 7.4786312000000e+04 57 36 -1.2564100000000e+05 58 36 2.6175210000000e+06 59 36 -7.4786312000000e+04 37 37 1.5000000000000e+08 38 37 1.2820520000000e+06 39 37 -7.4786312000000e+04 40 37 1.9230770000000e+06 41 37 5.7692310000000e+06 54 37 -7.4786312000000e+04 55 37 9.6153850000000e+06 56 37 -1.2179488000000e+07 57 37 -2.6175210000000e+06 58 37 2.8846144000000e+07 59 37 5.7692300000000e+06 38 38 1.5000000000000e+08 39 38 2.6175210000000e+06 40 38 5.7692310000000e+06 41 38 2.8846144000000e+07 54 38 -7.4786312000000e+04 55 38 -1.2179488000000e+07 56 38 9.6153850000000e+06 57 38 7.4786375000000e+04 58 38 5.7692300000000e+06 59 38 1.9230770000000e+06 39 39 5.0256406000000e+05 40 39 1.9531250000000e-01 41 39 -2.7343750000000e-01 42 39 -1.2564100000000e+05 43 39 7.4786312000000e+04 44 39 -2.6175210000000e+06 57 39 4.8828125000000e-04 58 39 7.4786312000000e+04 59 39 7.4786250000000e+04 60 39 -1.2564100000000e+05 61 39 2.6175210000000e+06 62 39 -7.4786312000000e+04 40 40 1.4999998000000e+08 41 40 1.2820510000000e+06 42 40 -7.4786375000000e+04 43 40 1.9230770000000e+06 44 40 5.7692310000000e+06 57 40 -7.4786250000000e+04 58 40 9.6153820000000e+06 59 40 -1.2179488000000e+07 60 40 -2.6175210000000e+06 61 40 2.8846144000000e+07 62 40 5.7692300000000e+06 41 41 1.4999998000000e+08 42 41 2.6175210000000e+06 43 41 5.7692300000000e+06 44 41 2.8846160000000e+07 57 41 -7.4786375000000e+04 58 41 -1.2179485000000e+07 59 41 9.6153850000000e+06 60 41 7.4786375000000e+04 61 41 5.7692310000000e+06 62 41 1.9230770000000e+06 42 42 5.0256412000000e+05 43 42 -5.5468750000000e-01 44 42 -3.2812500000000e-01 45 42 -1.2564106000000e+05 46 42 7.4786250000000e+04 47 42 -2.6175220000000e+06 60 42 -2.4414062000000e-04 61 42 7.4786312000000e+04 62 42 7.4786312000000e+04 63 42 -1.2564100000000e+05 64 42 2.6175210000000e+06 65 42 -7.4786375000000e+04 43 43 1.5000002000000e+08 44 43 1.2820510000000e+06 45 43 -7.4786375000000e+04 46 43 1.9230770000000e+06 47 43 5.7692320000000e+06 60 43 -7.4786312000000e+04 61 43 9.6153830000000e+06 62 43 -1.2179486000000e+07 63 43 -2.6175210000000e+06 64 43 2.8846144000000e+07 65 43 5.7692310000000e+06 44 44 1.5000002000000e+08 45 44 2.6175220000000e+06 46 44 5.7692320000000e+06 47 44 2.8846160000000e+07 60 44 -7.4786312000000e+04 61 44 -1.2179486000000e+07 62 44 9.6153830000000e+06 63 44 7.4786312000000e+04 64 44 5.7692300000000e+06 65 44 1.9230760000000e+06 45 45 5.0256419000000e+05 46 45 5.3906250000000e-01 47 45 1.5625000000000e-02 48 45 -1.2564106000000e+05 49 45 7.4786250000000e+04 63 45 -7.3242187000000e-04 64 45 7.4786562000000e+04 65 45 7.4786125000000e+04 66 45 -1.2564106000000e+05 67 45 2.6175220000000e+06 68 45 -7.4786250000000e+04 46 46 1.5000005000000e+08 47 46 1.2820520000000e+06 48 46 -7.4786375000000e+04 49 46 1.9230770000000e+06 63 46 -7.4786125000000e+04 64 46 9.6153870000000e+06 65 46 -1.2179498000000e+07 66 46 -2.6175230000000e+06 67 46 2.8846160000000e+07 68 46 5.7692320000000e+06 47 47 1.5000002000000e+08 48 47 2.6175220000000e+06 49 47 5.7692320000000e+06 63 47 -7.4786625000000e+04 64 47 -1.2179486000000e+07 65 47 9.6153900000000e+06 66 47 7.4786500000000e+04 67 47 5.7692330000000e+06 68 47 1.9230770000000e+06 48 48 2.5128206000000e+05 49 48 4.6367500000000e+05 66 48 -6.1035156000000e-04 67 48 7.4786312000000e+04 68 48 7.4786375000000e+04 69 48 -6.2820516000000e+04 70 48 1.0769230000000e+06 49 49 7.5000000000000e+07 66 49 -7.4786312000000e+04 67 49 9.6153830000000e+06 68 49 -1.2179487000000e+07 69 49 -1.5405980000000e+06 70 49 1.4423077000000e+07 50 50 7.5000000000000e+07 51 50 2.6175210000000e+06 52 50 5.7692310000000e+06 53 50 2.8846144000000e+07 71 50 9.6153856000000e+05 51 51 5.0256406000000e+05 52 51 1.8750000000000e-01 53 51 2.3437500000000e-02 54 51 -1.2564100000000e+05 55 51 7.4786312000000e+04 56 51 -2.6175210000000e+06 71 51 7.4786312000000e+04 72 51 -1.2564100000000e+05 73 51 2.6175210000000e+06 74 51 -7.4786312000000e+04 52 52 1.4999998000000e+08 53 52 1.2820510000000e+06 54 52 -7.4786312000000e+04 55 52 1.9230770000000e+06 56 52 5.7692300000000e+06 71 52 -1.2179487000000e+07 72 52 -2.6175210000000e+06 73 52 2.8846160000000e+07 74 52 5.7692310000000e+06 53 53 1.4999998000000e+08 54 53 2.6175210000000e+06 55 53 5.7692310000000e+06 56 53 2.8846144000000e+07 71 53 9.6153830000000e+06 72 53 7.4786312000000e+04 73 53 5.7692310000000e+06 74 53 1.9230770000000e+06 54 54 5.0256406000000e+05 55 54 -2.4218750000000e-01 56 54 -6.2500000000000e-02 57 54 -1.2564100000000e+05 58 54 7.4786250000000e+04 59 54 -2.6175210000000e+06 73 54 7.4786375000000e+04 74 54 7.4786250000000e+04 75 54 -1.2564100000000e+05 76 54 2.6175210000000e+06 77 54 -7.4786250000000e+04 55 55 1.5000000000000e+08 56 55 1.2820510000000e+06 57 55 -7.4786437000000e+04 58 55 1.9230760000000e+06 59 55 5.7692290000000e+06 72 55 -7.4786312000000e+04 73 55 9.6153850000000e+06 74 55 -1.2179488000000e+07 75 55 -2.6175210000000e+06 76 55 2.8846144000000e+07 77 55 5.7692300000000e+06 56 56 1.4999998000000e+08 57 56 2.6175210000000e+06 58 56 5.7692300000000e+06 59 56 2.8846144000000e+07 72 56 -7.4786375000000e+04 73 56 -1.2179487000000e+07 74 56 9.6153840000000e+06 75 56 7.4786375000000e+04 76 56 5.7692310000000e+06 77 56 1.9230770000000e+06 57 57 5.0256412000000e+05 58 57 2.0312500000000e-01 59 57 -2.4218750000000e-01 60 57 -1.2564100000000e+05 61 57 7.4786312000000e+04 62 57 -2.6175210000000e+06 75 57 8.5449219000000e-04 76 57 7.4786375000000e+04 77 57 7.4786250000000e+04 78 57 -1.2564100000000e+05 79 57 2.6175210000000e+06 80 57 -7.4786312000000e+04 58 58 1.4999998000000e+08 59 58 1.2820510000000e+06 60 58 -7.4786312000000e+04 61 58 1.9230770000000e+06 62 58 5.7692310000000e+06 75 58 -7.4786250000000e+04 76 58 9.6153850000000e+06 77 58 -1.2179488000000e+07 78 58 -2.6175210000000e+06 79 58 2.8846160000000e+07 80 58 5.7692320000000e+06 59 59 1.5000000000000e+08 60 59 2.6175210000000e+06 61 59 5.7692320000000e+06 62 59 2.8846160000000e+07 75 59 -7.4786312000000e+04 76 59 -1.2179485000000e+07 77 59 9.6153820000000e+06 78 59 7.4786312000000e+04 79 59 5.7692310000000e+06 80 59 1.9230770000000e+06 60 60 5.0256412000000e+05 61 60 2.2656250000000e-01 62 60 2.5000000000000e-01 63 60 -1.2564100000000e+05 64 60 7.4786375000000e+04 65 60 -2.6175210000000e+06 78 60 2.4414062000000e-04 79 60 7.4786312000000e+04 80 60 7.4786312000000e+04 81 60 -1.2564100000000e+05 82 60 2.6175210000000e+06 83 60 -7.4786312000000e+04 61 61 1.5000000000000e+08 62 61 1.2820510000000e+06 63 61 -7.4786312000000e+04 64 61 1.9230770000000e+06 65 61 5.7692300000000e+06 78 61 -7.4786312000000e+04 79 61 9.6153850000000e+06 80 61 -1.2179489000000e+07 81 61 -2.6175210000000e+06 82 61 2.8846160000000e+07 83 61 5.7692310000000e+06 62 62 1.5000000000000e+08 63 62 2.6175210000000e+06 64 62 5.7692310000000e+06 65 62 2.8846144000000e+07 78 62 -7.4786312000000e+04 79 62 -1.2179489000000e+07 80 62 9.6153860000000e+06 81 62 7.4786312000000e+04 82 62 5.7692320000000e+06 83 62 1.9230770000000e+06 63 63 5.0256412000000e+05 64 63 1.8750000000000e-01 65 63 -8.2031250000000e-01 66 63 -1.2564106000000e+05 67 63 7.4786125000000e+04 68 63 -2.6175220000000e+06 81 63 3.6621094000000e-04 82 63 7.4786500000000e+04 83 63 7.4786187000000e+04 84 63 -1.2564100000000e+05 85 63 2.6175210000000e+06 86 63 -7.4786187000000e+04 64 64 1.5000002000000e+08 65 64 1.2820520000000e+06 66 64 -7.4786500000000e+04 67 64 1.9230780000000e+06 68 64 5.7692330000000e+06 81 64 -7.4786250000000e+04 82 64 9.6153880000000e+06 83 64 -1.2179493000000e+07 84 64 -2.6175220000000e+06 85 64 2.8846160000000e+07 86 64 5.7692310000000e+06 65 65 1.5000002000000e+08 66 65 2.6175220000000e+06 67 65 5.7692330000000e+06 68 65 2.8846160000000e+07 81 65 -7.4786437000000e+04 82 65 -1.2179487000000e+07 83 65 9.6153850000000e+06 84 65 7.4786437000000e+04 85 65 5.7692310000000e+06 86 65 1.9230770000000e+06 66 66 5.0256425000000e+05 67 66 -6.9531250000000e-01 68 66 -1.5625000000000e-01 69 66 -1.2564106000000e+05 70 66 7.4786437000000e+04 84 66 -8.5449219000000e-04 85 66 7.4786312000000e+04 86 66 7.4786312000000e+04 87 66 -1.2564106000000e+05 88 66 2.6175220000000e+06 89 66 -7.4786500000000e+04 67 67 1.5000003000000e+08 68 67 1.2820520000000e+06 69 67 -7.4786250000000e+04 70 67 1.9230770000000e+06 84 67 -7.4786312000000e+04 85 67 9.6153820000000e+06 86 67 -1.2179484000000e+07 87 67 -2.6175210000000e+06 88 67 2.8846160000000e+07 89 67 5.7692320000000e+06 68 68 1.5000003000000e+08 69 68 2.6175220000000e+06 70 68 5.7692330000000e+06 84 68 -7.4786312000000e+04 85 68 -1.2179484000000e+07 86 68 9.6153820000000e+06 87 68 7.4786187000000e+04 88 68 5.7692310000000e+06 89 68 1.9230770000000e+06 69 69 2.5128212000000e+05 70 69 4.6367594000000e+05 87 69 9.7656250000000e-04 88 69 7.4786375000000e+04 89 69 7.4786375000000e+04 90 69 -6.2820547000000e+04 91 69 1.0769240000000e+06 70 70 7.5000016000000e+07 87 70 -7.4786375000000e+04 88 70 9.6153890000000e+06 89 70 -1.2179494000000e+07 90 70 -1.5405990000000e+06 91 70 1.4423084000000e+07 71 71 7.5000000000000e+07 72 71 2.6175210000000e+06 73 71 5.7692300000000e+06 74 71 2.8846144000000e+07 92 71 9.6153831000000e+05 72 72 5.0256406000000e+05 73 72 -1.5625000000000e-01 74 72 7.0312500000000e-02 75 72 -1.2564100000000e+05 76 72 7.4786250000000e+04 77 72 -2.6175210000000e+06 92 72 7.4786312000000e+04 93 72 -1.2564100000000e+05 94 72 2.6175210000000e+06 95 72 -7.4786312000000e+04 73 73 1.4999998000000e+08 74 73 1.2820520000000e+06 75 73 -7.4786375000000e+04 76 73 1.9230770000000e+06 77 73 5.7692310000000e+06 92 73 -1.2179486000000e+07 93 73 -2.6175210000000e+06 94 73 2.8846144000000e+07 95 73 5.7692300000000e+06 74 74 1.4999998000000e+08 75 74 2.6175210000000e+06 76 74 5.7692300000000e+06 77 74 2.8846144000000e+07 92 74 9.6153840000000e+06 93 74 7.4786375000000e+04 94 74 5.7692300000000e+06 95 74 1.9230760000000e+06 75 75 5.0256406000000e+05 76 75 7.0312500000000e-02 77 75 -1.4843750000000e-01 78 75 -1.2564100000000e+05 79 75 7.4786312000000e+04 80 75 -2.6175210000000e+06 93 75 -8.5449219000000e-04 94 75 7.4786375000000e+04 95 75 7.4786250000000e+04 96 75 -1.2564100000000e+05 97 75 2.6175210000000e+06 98 75 -7.4786312000000e+04 76 76 1.4999998000000e+08 77 76 1.2820510000000e+06 78 76 -7.4786375000000e+04 79 76 1.9230770000000e+06 80 76 5.7692310000000e+06 93 76 -7.4786250000000e+04 94 76 9.6153820000000e+06 95 76 -1.2179487000000e+07 96 76 -2.6175210000000e+06 97 76 2.8846144000000e+07 98 76 5.7692300000000e+06 77 77 1.4999998000000e+08 78 77 2.6175210000000e+06 79 77 5.7692300000000e+06 80 77 2.8846144000000e+07 93 77 -7.4786375000000e+04 94 77 -1.2179484000000e+07 95 77 9.6153830000000e+06 96 77 7.4786312000000e+04 97 77 5.7692300000000e+06 98 77 1.9230770000000e+06 78 78 5.0256412000000e+05 79 78 -2.4218750000000e-01 80 78 -2.5000000000000e-01 81 78 -1.2564100000000e+05 82 78 7.4786312000000e+04 83 78 -2.6175210000000e+06 96 78 -2.4414062000000e-04 97 78 7.4786312000000e+04 98 78 7.4786312000000e+04 99 78 -1.2564100000000e+05 100 78 2.6175210000000e+06 101 78 -7.4786375000000e+04 79 79 1.5000000000000e+08 80 79 1.2820510000000e+06 81 79 -7.4786312000000e+04 82 79 1.9230770000000e+06 83 79 5.7692320000000e+06 96 79 -7.4786312000000e+04 97 79 9.6153830000000e+06 98 79 -1.2179486000000e+07 99 79 -2.6175210000000e+06 100 79 2.8846144000000e+07 101 79 5.7692310000000e+06 80 80 1.5000000000000e+08 81 80 2.6175210000000e+06 82 80 5.7692310000000e+06 83 80 2.8846160000000e+07 96 80 -7.4786312000000e+04 97 80 -1.2179486000000e+07 98 80 9.6153830000000e+06 99 80 7.4786312000000e+04 100 80 5.7692300000000e+06 101 80 1.9230760000000e+06 81 81 5.0256419000000e+05 82 81 5.9375000000000e-01 83 81 -6.0937500000000e-01 84 81 -1.2564106000000e+05 85 81 7.4786375000000e+04 86 81 -2.6175220000000e+06 99 81 -7.3242187000000e-04 100 81 7.4786437000000e+04 101 81 7.4786250000000e+04 102 81 -1.2564106000000e+05 103 81 2.6175220000000e+06 104 81 -7.4786312000000e+04 82 82 1.5000003000000e+08 83 82 1.2820520000000e+06 84 82 -7.4786375000000e+04 85 82 1.9230770000000e+06 86 82 5.7692330000000e+06 99 82 -7.4786187000000e+04 100 82 9.6153850000000e+06 101 82 -1.2179493000000e+07 102 82 -2.6175220000000e+06 103 82 2.8846160000000e+07 104 82 5.7692320000000e+06 83 83 1.5000003000000e+08 84 83 2.6175220000000e+06 85 83 5.7692320000000e+06 86 83 2.8846160000000e+07 99 83 -7.4786500000000e+04 100 83 -1.2179487000000e+07 101 83 9.6153880000000e+06 102 83 7.4786375000000e+04 103 83 5.7692330000000e+06 104 83 1.9230770000000e+06 84 84 5.0256412000000e+05 85 84 8.5937500000000e-02 86 84 1.5781250000000e+00 87 84 -1.2564100000000e+05 88 84 7.4786250000000e+04 89 84 -2.6175200000000e+06 103 84 7.4786312000000e+04 104 84 7.4786312000000e+04 105 84 -1.2564100000000e+05 106 84 2.6175210000000e+06 107 84 -7.4786187000000e+04 85 85 1.5000000000000e+08 86 85 1.2820520000000e+06 87 85 -7.4786312000000e+04 88 85 1.9230770000000e+06 89 85 5.7692300000000e+06 102 85 -7.4786375000000e+04 103 85 9.6153870000000e+06 104 85 -1.2179490000000e+07 105 85 -2.6175210000000e+06 106 85 2.8846144000000e+07 107 85 5.7692300000000e+06 86 86 1.5000000000000e+08 87 86 2.6175200000000e+06 88 86 5.7692290000000e+06 89 86 2.8846144000000e+07 102 86 -7.4786375000000e+04 103 86 -1.2179490000000e+07 104 86 9.6153870000000e+06 105 86 7.4786437000000e+04 106 86 5.7692300000000e+06 107 86 1.9230770000000e+06 87 87 5.0256400000000e+05 88 87 -1.2890625000000e+00 89 87 -1.1250000000000e+00 90 87 -1.2564100000000e+05 91 87 7.4786187000000e+04 105 87 -8.5449219000000e-04 106 87 7.4786250000000e+04 107 87 7.4786312000000e+04 108 87 -1.2564100000000e+05 109 87 2.6175200000000e+06 110 87 -7.4786312000000e+04 88 88 1.4999998000000e+08 89 88 1.2820510000000e+06 90 88 -7.4786437000000e+04 91 88 1.9230770000000e+06 105 88 -7.4786312000000e+04 106 88 9.6153800000000e+06 107 88 -1.2179482000000e+07 108 88 -2.6175200000000e+06 109 88 2.8846144000000e+07 110 88 5.7692280000000e+06 89 89 1.4999998000000e+08 90 89 2.6175220000000e+06 91 89 5.7692310000000e+06 105 89 -7.4786375000000e+04 106 89 -1.2179482000000e+07 107 89 9.6153820000000e+06 108 89 7.4786312000000e+04 109 89 5.7692280000000e+06 110 89 1.9230760000000e+06 90 90 2.5128206000000e+05 91 90 4.6367419000000e+05 108 90 -8.5449219000000e-04 109 90 7.4786250000000e+04 110 90 7.4786312000000e+04 111 90 -6.2820488000000e+04 112 90 1.0769230000000e+06 91 91 7.5000000000000e+07 108 91 -7.4786312000000e+04 109 91 9.6153800000000e+06 110 91 -1.2179482000000e+07 111 91 -1.5405980000000e+06 112 91 1.4423071000000e+07 92 92 7.5000000000000e+07 93 92 2.6175210000000e+06 94 92 5.7692310000000e+06 95 92 2.8846160000000e+07 113 92 9.6153850000000e+05 93 93 5.0256412000000e+05 94 93 7.0312500000000e-01 95 93 -1.3281250000000e-01 96 93 -1.2564106000000e+05 97 93 7.4786375000000e+04 98 93 -2.6175220000000e+06 113 93 7.4786312000000e+04 114 93 -1.2564106000000e+05 115 93 2.6175220000000e+06 116 93 -7.4786375000000e+04 94 94 1.5000000000000e+08 95 94 1.2820510000000e+06 96 94 -7.4786250000000e+04 97 94 1.9230770000000e+06 98 94 5.7692310000000e+06 113 94 -1.2179488000000e+07 114 94 -2.6175220000000e+06 115 94 2.8846160000000e+07 116 94 5.7692320000000e+06 95 95 1.5000000000000e+08 96 95 2.6175220000000e+06 97 95 5.7692320000000e+06 98 95 2.8846160000000e+07 113 95 9.6153840000000e+06 114 95 7.4786250000000e+04 115 95 5.7692320000000e+06 116 95 1.9230770000000e+06 96 96 5.0256412000000e+05 97 96 2.8906250000000e-01 98 96 3.9843750000000e-01 99 96 -1.2564100000000e+05 100 96 7.4786375000000e+04 101 96 -2.6175210000000e+06 114 96 2.4414062000000e-04 115 96 7.4786250000000e+04 116 96 7.4786375000000e+04 117 96 -1.2564100000000e+05 118 96 2.6175210000000e+06 119 96 -7.4786312000000e+04 97 97 1.5000000000000e+08 98 97 1.2820510000000e+06 99 97 -7.4786312000000e+04 100 97 1.9230770000000e+06 101 97 5.7692300000000e+06 114 97 -7.4786437000000e+04 115 97 9.6153870000000e+06 116 97 -1.2179488000000e+07 117 97 -2.6175210000000e+06 118 97 2.8846160000000e+07 119 97 5.7692310000000e+06 98 98 1.5000000000000e+08 99 98 2.6175210000000e+06 100 98 5.7692310000000e+06 101 98 2.8846144000000e+07 114 98 -7.4786250000000e+04 115 98 -1.2179491000000e+07 116 98 9.6153850000000e+06 117 98 7.4786312000000e+04 118 98 5.7692310000000e+06 119 98 1.9230770000000e+06 99 99 5.0256412000000e+05 100 99 2.5000000000000e-01 101 99 -2.7343750000000e-01 102 99 -1.2564100000000e+05 103 99 7.4786187000000e+04 104 99 -2.6175210000000e+06 117 99 3.6621094000000e-04 118 99 7.4786500000000e+04 119 99 7.4786187000000e+04 120 99 -1.2564100000000e+05 121 99 2.6175210000000e+06 122 99 -7.4786187000000e+04 100 100 1.5000000000000e+08 101 100 1.2820520000000e+06 102 100 -7.4786437000000e+04 103 100 1.9230780000000e+06 104 100 5.7692310000000e+06 117 100 -7.4786250000000e+04 118 100 9.6153880000000e+06 119 100 -1.2179493000000e+07 120 100 -2.6175220000000e+06 121 100 2.8846160000000e+07 122 100 5.7692310000000e+06 101 101 1.5000000000000e+08 102 101 2.6175220000000e+06 103 101 5.7692320000000e+06 104 101 2.8846160000000e+07 117 101 -7.4786437000000e+04 118 101 -1.2179487000000e+07 119 101 9.6153850000000e+06 120 101 7.4786437000000e+04 121 101 5.7692310000000e+06 122 101 1.9230770000000e+06 102 102 5.0256412000000e+05 103 102 -1.5234375000000e+00 104 102 -7.8125000000000e-02 105 102 -1.2564100000000e+05 106 102 7.4786250000000e+04 107 102 -2.6175210000000e+06 120 102 -8.5449219000000e-04 121 102 7.4786312000000e+04 122 102 7.4786312000000e+04 123 102 -1.2564100000000e+05 124 102 2.6175200000000e+06 125 102 -7.4786250000000e+04 103 103 1.5000000000000e+08 104 103 1.2820520000000e+06 105 103 -7.4786437000000e+04 106 103 1.9230770000000e+06 107 103 5.7692300000000e+06 120 103 -7.4786312000000e+04 121 103 9.6153820000000e+06 122 103 -1.2179484000000e+07 123 103 -2.6175200000000e+06 124 103 2.8846144000000e+07 125 103 5.7692280000000e+06 104 104 1.5000000000000e+08 105 104 2.6175210000000e+06 106 104 5.7692300000000e+06 107 104 2.8846144000000e+07 120 104 -7.4786312000000e+04 121 104 -1.2179484000000e+07 122 104 9.6153820000000e+06 123 104 7.4786312000000e+04 124 104 5.7692300000000e+06 125 104 1.9230760000000e+06 105 105 5.0256419000000e+05 106 105 9.4531250000000e-01 107 105 -1.0156250000000e+00 108 105 -1.2564106000000e+05 109 105 7.4786625000000e+04 110 105 -2.6175230000000e+06 123 105 -1.2207031000000e-04 124 105 7.4786312000000e+04 125 105 7.4786250000000e+04 126 105 -1.2564106000000e+05 127 105 2.6175230000000e+06 128 105 -7.4786625000000e+04 106 106 1.5000002000000e+08 107 106 1.2820510000000e+06 108 106 -7.4786062000000e+04 109 106 1.9230780000000e+06 110 106 5.7692330000000e+06 123 106 -7.4786312000000e+04 124 106 9.6153820000000e+06 125 106 -1.2179482000000e+07 126 106 -2.6175220000000e+06 127 106 2.8846160000000e+07 128 106 5.7692340000000e+06 107 107 1.5000002000000e+08 108 107 2.6175220000000e+06 109 107 5.7692350000000e+06 110 107 2.8846160000000e+07 123 107 -7.4786250000000e+04 124 107 -1.2179482000000e+07 125 107 9.6153790000000e+06 126 107 7.4786062000000e+04 127 107 5.7692330000000e+06 128 107 1.9230780000000e+06 108 108 5.0256425000000e+05 109 108 4.2109375000000e+00 110 108 1.6250000000000e+00 111 108 -1.2564100000000e+05 112 108 7.4786500000000e+04 127 108 7.4786687000000e+04 128 108 7.4786250000000e+04 129 108 -1.2564119000000e+05 130 108 2.6175240000000e+06 131 108 -7.4786125000000e+04 109 109 1.5000006000000e+08 110 109 1.2820520000000e+06 111 109 -7.4786187000000e+04 112 109 1.9230770000000e+06 126 109 -7.4786250000000e+04 127 109 9.6154010000000e+06 128 109 -1.2179514000000e+07 129 109 -2.6175250000000e+06 130 109 2.8846192000000e+07 131 109 5.7692380000000e+06 110 110 1.5000005000000e+08 111 110 2.6175210000000e+06 112 110 5.7692320000000e+06 126 110 -7.4786687000000e+04 127 110 -1.2179502000000e+07 128 110 9.6154010000000e+06 129 110 7.4786687000000e+04 130 110 5.7692390000000e+06 131 110 1.9230790000000e+06 111 111 2.5128194000000e+05 112 111 4.6367419000000e+05 129 111 9.7656250000000e-04 130 111 7.4785812000000e+04 131 111 7.4786750000000e+04 132 111 -6.2820441000000e+04 133 111 1.0769220000000e+06 112 112 7.4999952000000e+07 129 112 -7.4786750000000e+04 130 112 9.6153810000000e+06 131 112 -1.2179472000000e+07 132 112 -1.5405970000000e+06 133 112 1.4423061000000e+07 113 113 7.5000000000000e+07 114 113 2.6175220000000e+06 115 113 5.7692310000000e+06 116 113 2.8846160000000e+07 134 113 9.6153850000000e+05 114 114 5.0256419000000e+05 115 114 -4.6875000000000e-02 116 114 -2.1093750000000e-01 117 114 -1.2564106000000e+05 118 114 7.4786375000000e+04 119 114 -2.6175220000000e+06 134 114 7.4786312000000e+04 135 114 -1.2564106000000e+05 136 114 -7.4786375000000e+04 115 115 1.5000002000000e+08 116 115 1.2820510000000e+06 117 115 -7.4786312000000e+04 118 115 1.9230770000000e+06 119 115 5.7692310000000e+06 134 115 -1.2179488000000e+07 135 115 -2.6175220000000e+06 136 115 5.7692320000000e+06 116 116 1.5000002000000e+08 117 116 2.6175220000000e+06 118 116 5.7692320000000e+06 119 116 2.8846160000000e+07 134 116 9.6153840000000e+06 135 116 7.4786250000000e+04 136 116 1.9230770000000e+06 117 117 5.0256419000000e+05 118 117 7.8125000000000e-03 119 117 -1.4843750000000e-01 120 117 -1.2564106000000e+05 121 117 7.4786312000000e+04 122 117 -2.6175220000000e+06 135 117 2.4414062000000e-04 136 117 7.4786375000000e+04 137 117 -1.2564100000000e+05 138 117 -7.4786312000000e+04 118 118 1.5000002000000e+08 119 118 1.2820510000000e+06 120 118 -7.4786437000000e+04 121 118 1.9230770000000e+06 122 118 5.7692310000000e+06 135 118 -7.4786437000000e+04 136 118 -1.2179488000000e+07 137 118 -2.6175210000000e+06 138 118 5.7692310000000e+06 119 119 1.5000002000000e+08 120 119 2.6175220000000e+06 121 119 5.7692310000000e+06 122 119 2.8846160000000e+07 135 119 -7.4786250000000e+04 136 119 9.6153850000000e+06 137 119 7.4786312000000e+04 138 119 1.9230770000000e+06 120 120 5.0256412000000e+05 121 120 2.3437500000000e-02 122 120 2.8125000000000e-01 123 120 -1.2564106000000e+05 124 120 7.4786500000000e+04 125 120 -2.6175220000000e+06 137 120 2.4414062000000e-04 138 120 7.4786375000000e+04 139 120 -1.2564100000000e+05 140 120 -7.4786500000000e+04 121 121 1.5000000000000e+08 122 121 1.2820510000000e+06 123 121 -7.4786187000000e+04 124 121 1.9230770000000e+06 125 121 5.7692310000000e+06 137 121 -7.4786437000000e+04 138 121 -1.2179482000000e+07 139 121 -2.6175210000000e+06 140 121 5.7692320000000e+06 122 122 1.5000002000000e+08 123 122 2.6175210000000e+06 124 122 5.7692320000000e+06 125 122 2.8846160000000e+07 137 122 -7.4786125000000e+04 138 122 9.6153810000000e+06 139 122 7.4786187000000e+04 140 122 1.9230770000000e+06 123 123 5.0256400000000e+05 124 123 1.1640625000000e+00 125 123 1.3359375000000e+00 126 123 -1.2564100000000e+05 127 123 7.4786312000000e+04 128 123 -2.6175200000000e+06 139 123 9.7656250000000e-04 140 123 7.4786375000000e+04 141 123 -1.2564100000000e+05 142 123 -7.4786187000000e+04 124 124 1.4999998000000e+08 125 124 1.2820510000000e+06 126 124 -7.4786312000000e+04 127 124 1.9230760000000e+06 128 124 5.7692280000000e+06 139 124 -7.4786375000000e+04 140 124 -1.2179494000000e+07 141 124 -2.6175220000000e+06 142 124 5.7692310000000e+06 125 125 1.4999998000000e+08 126 125 2.6175200000000e+06 127 125 5.7692280000000e+06 128 125 2.8846144000000e+07 139 125 -7.4786312000000e+04 140 125 9.6153890000000e+06 141 125 7.4786500000000e+04 142 125 1.9230770000000e+06 126 126 5.0256406000000e+05 127 126 -3.1093750000000e+00 128 126 -2.7187500000000e+00 129 126 -1.2564106000000e+05 130 126 7.4785812000000e+04 131 126 -2.6175220000000e+06 141 126 -1.2207031000000e-04 142 126 7.4786250000000e+04 143 126 -1.2564094000000e+05 144 126 -7.4786125000000e+04 127 127 1.5000000000000e+08 128 127 1.2820520000000e+06 129 127 -7.4786937000000e+04 130 127 1.9230780000000e+06 131 127 5.7692350000000e+06 141 127 -7.4786312000000e+04 142 127 -1.2179482000000e+07 143 127 -2.6175190000000e+06 144 127 5.7692270000000e+06 128 128 1.5000002000000e+08 129 128 2.6175230000000e+06 130 128 5.7692330000000e+06 131 128 2.8846160000000e+07 141 128 -7.4786250000000e+04 142 128 9.6153790000000e+06 143 128 7.4786375000000e+04 144 128 1.9230750000000e+06 129 129 5.0256425000000e+05 130 129 -3.5390625000000e+00 131 129 1.3046875000000e+00 132 129 -1.2564100000000e+05 133 129 7.4786562000000e+04 143 129 7.3242187000000e-04 144 129 7.4786250000000e+04 145 129 -1.2564100000000e+05 146 129 -7.4786562000000e+04 130 130 1.5000005000000e+08 131 130 1.2820500000000e+06 132 130 -7.4786062000000e+04 133 130 1.9230760000000e+06 143 130 -7.4786250000000e+04 144 130 -1.2179474000000e+07 145 130 -2.6175200000000e+06 146 130 5.7692300000000e+06 131 131 1.5000000000000e+08 132 131 2.6175200000000e+06 133 131 5.7692300000000e+06 143 131 -7.4786250000000e+04 144 131 9.6153740000000e+06 145 131 7.4786000000000e+04 146 131 1.9230760000000e+06 132 132 2.5128200000000e+05 133 132 4.6367700000000e+05 145 132 9.7656250000000e-04 146 132 7.4786375000000e+04 147 132 -6.2820547000000e+04 133 133 7.4999984000000e+07 145 133 -7.4786375000000e+04 146 133 -1.2179494000000e+07 147 133 -1.5405990000000e+06 134 134 4.4230768000000e+07 135 134 1.5405980000000e+06 136 134 1.4423078000000e+07 135 135 2.5128206000000e+05 136 135 -4.6367525000000e+05 137 135 -6.2820520000000e+04 138 135 -1.0769230000000e+06 136 136 7.5000000000000e+07 137 136 1.5405980000000e+06 138 136 1.4423078000000e+07 137 137 2.5128206000000e+05 138 137 -4.6367462000000e+05 139 137 -6.2820488000000e+04 140 137 -1.0769230000000e+06 138 138 7.4999984000000e+07 139 138 1.5405980000000e+06 140 138 1.4423071000000e+07 139 139 2.5128206000000e+05 140 139 -4.6367625000000e+05 141 139 -6.2820543000000e+04 142 139 -1.0769240000000e+06 140 140 7.5000016000000e+07 141 140 1.5405990000000e+06 142 140 1.4423084000000e+07 141 141 2.5128206000000e+05 142 141 -4.6367419000000e+05 143 141 -6.2820488000000e+04 144 141 -1.0769230000000e+06 142 142 7.5000000000000e+07 143 142 1.5405980000000e+06 144 142 1.4423071000000e+07 143 143 2.5128187000000e+05 144 143 -4.6367400000000e+05 145 143 -6.2820441000000e+04 146 143 -1.0769220000000e+06 144 144 7.4999936000000e+07 145 144 1.5405970000000e+06 146 144 1.4423061000000e+07 145 145 2.5128200000000e+05 146 145 -4.6367694000000e+05 147 145 -6.2820543000000e+04 146 146 7.4999984000000e+07 147 146 1.5405990000000e+06 147 147 1.2564106000000e+05 Matrix/inst/external/CAex_slots.rda0000644000175100001440000000321010464427703017072 0ustar hornikuserskXi:P I$9)PɤR%+l$eqQE(.j)PH'9r_w~uz};9@Y2~SsG_7EZ(x񸟫_m lk AcQod EH CNH !g-j8rA8@&2A5DHBnH""34CHtrGXI?B4Y#$B6h2F#}pkI:u Ѐ߃s0`=?.cs>h*Gh6 B(-BKP8@+*C(%$3@P ڇtteLNlt")GW5TQ HEkT͚~),? 3&vnX=z;HD_ߋ4s`yVw #/8h28hwdA=@'8I7,惽`FiKSQHrک7䑎̺.:n~?#a0Lޣ9P[hmͽu+p5z^lV=O´ּы-vh8,Xu+m0u`ˍ?pt$0Mg)* aJ]8!S?A⍟ƮyeJe'|[SUV8ڵe,XEtS.jtL8w57ulsEu#=:sbCI{l73(7zQ,Zr؉]1V<*ߎ7ܰBG>T9>nZurÊծ [)7vmeIwC(7 f{sC [kZұrJ_Nˬ Z]k)N(7DM) D_Ga"֍z5kSnXygPS`Q50rnX VK UKܰ2hזB͠O 3Iv#lj1T-&SnX빬owfHa'4A2kܸfŌ4Nhx^faYMatJٞ; N}CaE'J0&o(7Lqru,0a{c- 冽g~= y*^QPnlEx |srd' J^jSPn,Aկ ?2M}Ca^kRPnlX|9 0 4jQPn|}A7&SSk99ދrM>7nLɍsZ7$1=rӝOo(7L%|p7I T)N{+ s1 Matrix/inst/external/USCounties_slots.rda0000644000175100001440000007321310770571602020323 0ustar hornikusers},=On!&@$ <[p@[m՛oUWW̬/FQ9t% Ր+.1*jIΧa"6)[8*1rYP]ռ߮$#/x{Ȼwu =^I18ȣB}Q,LPk9ڗ ~<>uK$(mY|m/u|)ӓ+yEs:z#r' 6M#+"]+"ö:y?`GVvS>tէ^G Ę P.18BB#M%f~#NKowy.4ab6Cy!?C>^~9_̒ƉY1x!KLg= ye)^'\_ qQbQ_KKyG%V\Rlsl\[̦,^Z_%XڔcIKUk1u=$ZzLkPV؉yxɻ&ۼWe=Rw /jebw5)ŲJr:Nobb6,'a|O`O?!q)K捠w77K IHWb/˵dRqMbwx1NbON̂WB@,=bzM_~7lړ؟Gx_xH;.#CmdڼAǁNμrǘ8m=e13c{t ą ^D3xO>kOy`w^]aPOYϼsS&}9nCނ `*Xb1q(徎zZٳXϿԋx"q6v]##$Kb؈`<s\Gr8ۅ%x%qޤyzp8mQ$9חg]϶ODЕxulStr*y Ǩ?YLR)ƞ=3OkMذء=>?_&~WcYȁج{/;BlYŞ/Uu /׉׉Lr-}|c];ዘ/>Mw>]Y}8pajlGllXlqΟahhdlETUCʟMS-Oщ_~H},)냔S|'bgԩg3w,$$a1ke4*%N{ݠ~\<1+MP^>HYkO^Ϭ\«I^Ιog6~ƙ.ђے{0*(Oow 1Wq\r߈'+1b$bCϒ듫,45XUra \e%1_Rfy]m:\Mxˋ?f]{sk9\i?%{{)Թ딲\~L-b,/va{:َ/Lٷbg'.pr۲ϣM8`JESy][v"_ޞ^1I"&OnF,v`_F;Yëg_o1b ܃299m{|L~{ zXK;"~t-yE ֥KcuvicֱaGb&XDV$Ls8!I& [QfF~!iԱXjfY?zݚv`NaLbHblLG9GDؖ8DܒĸD X<|Og0A뿌]I9YןV"򹊲9z\H~z|$N6aEk{uqwKK]w{ŷ ^Q]k-rv;y oɇ`umԱQ?AG_X^=l{r򈭒!Nc36-r"Ƨy:;em KgXXz=?;Yd}>!>OFL\߹"b䳔Ip|xg]zm<=zO3&Kw;~BܙyYw*#bVė!FM%kG<|Āc[SCmhR]-88%1Z;|MO}z.#=SW1榳^/ȜX, |]O=E:iM= Qgȴ{C-q=g]N?]x FZ=Ӵlt@z2u1pOQg_uKJX#փyOp1uZ~Kc%߈?Ә3C'|&mYR_M|1ye]2j䱴Յ<2Wc)~r]${qli˺<ڠ/B^k, oI{-ݩ;.n](ԳZ1Ʀ&Nk3jӥm<0F˦#n{2:%^'Oˆ{\u9]I{7'i{z-uu+Yf wimJ]9qCcJz?4}x<&yg++d~kuy MbBJ=q̧҇zO`{-{9Gl^K۴1}>¦ ckr5}:KIceZZl {nq\qV`qhqat3ϳ^Q̹kiĤiĚiYGXM%Vø$k+Aõ1}=ӯ1u*濌en&t)@4ƌ]w1Va._ͺe ݻ~/yJn'vKf0n?"ߍ~r>sw9׆xd8~XAY%ƹ bb|a=3l,^ >U^YNHvԱ 'ü.u;_~L^[Kl˳ś1fgu1Õ)]ޓIʃ/3W43wM"-adg#.D=>-b,(g%#3:i),2v̬Nf؂<2KSco #,|O8"e'K.yوƴ^AY+2ۺ "yGoըc?^[Vڶlڹg梎k50Z=!O+P"t?;D6m{Ư23ۣg2,ĕ`Q^]F$mێ<$^;2]:ynn[ޔ weeB93gxq2-l,'G{2S,]m;$#F̖,3Kܶ+ycfО` ume0،o@|!K;aڵ7lF0[w%;KL|^Vi㦖u=OnG0eܟ6e!1OObt ~fehA9ޓɾqk1ށE?N GrLn}G[{6Bx߅+s@~Q#\"~ `N.<*Oh6,/ene224sl^G\2mkxwdJ9gĹW뭲_r%mqf5#󼇭AyfdE{3W3/Y;{m=:0ϱA|yu^um%u(F|KϞg^7S_יwt0a[ټػ-^"t|{?^ d>:}Rt1۳Wj3}Gv^L'w-_\KDϣ hGO7g3QgAٔg7Snνr/o~ inףل+ܶCkr%}_x~+9NJh_Fc'wUlofwc5dضf+6I0ExײAά rgg1f7bӘ>afǘ?f1|`ym5fw鈿s++簉˔}sF3l^^.+!t.i[l9ʚ$kdo䘽˔yNg'O}o7{1s-M>ļ˲G=~Oxe$?Wq{Ҟe>8Ҽc%{"̾z|/Y뒞EELg%io2c"Li_X#&.yauk/?g!2{=!GryPTu\0 1u9׹A]g]=|7̃ri0A[ʍ`_*#-7μ^YxiB>fI[ o9e=<=m,|d+I!F(/bĩ6&LE-Qe}Rn!꧟(^FY-&f,9cCNGR?Ƨb2<^ݞY;~w,u;w2M~#N˝ubxcգN[^V'FǃND{%8"I܇9oۓX/+"&!!!]jf״~by~%\k7bܟ49L+t =M޿m,W kswz^7yzt6t1"gMOr<;8.Rޗ1yb*󼢔A|5'eOd˝voIb˼.u[g{o8 )&0?!!>OR.Y[wiD=>SsyD%7YW e^(rA|mg6Oxgʲ+rK{XVλyH>oui0vX~)#yLk\+P_'/Z[26/_^ߦK~הu|:72?7o#,2=֦sʢ XZ^;І߇<O>km  Ɍ8 L_'M6!o3c]0ɽ!5y]~[ܓ}ϓe9{-;^u=1mX@,ߒ2msW~gY;`݊ v yoPVti u&zl?1ْ^>umyw߂eXʷ]'m{[_9F~3qyy><9GܬkGe KNy',+,~c?a{dsv+f<d^Ўy̧1~<~˜#m0iSP>Ke>"q)oe]P[/%ϬΉVo)1^ y6O!i2u!53'SlZ!ө^x-YffJ5s B ԽӼUM%fwM'w=|lqnaz|(K3K?esbP@(lߗ cRYݷSUw~!osf0=02O?߳o<s!@K~[KA8k#n,4lZaܢ0ofeyٳM9(!EI.VƯyda~::.1}^a@[++uGAa ֍Xur18u{6;Sgʳ e²V2L[ڦ;;0 ^[:p:V vnB6=(u';/hy(sŨId2rήf\2OLszCšxi ?`%w۬3`-M]ᱜ0x坟8JWr5X-kIb['d ]X^6GeDt/`Sږ-l4#dAGZ@Yݨv̏]#*~ߖy=A{Q#;oMݛ2rt,uݟʴ: RϾy Q&OCw,۷ Gq ?dwޏ1ޔwӮ3G+{xf~^~#m[Qތl'PW@xU؇uI=G|SqW}wuM7v Qؽg 2Fwg6~DXY{*ake3B‰kg穴؞<ŤcQ83j6=N؎iQ66gt>}a<3"jeጨA$ 暅ChQ>){6o7ŸyMƵ 䵗A<FI+/ -\L{gki{ؒ m32O_b.\82tUJd ➂p3d/mBX-0o+`SDA{ͼWB9- kd~ >k:nb9,h0)`.XYs3u< /Ŭ}8>Sܦp'!>i#o1]bl준yKeY ۶ k[YdM2 ^!oGy+<2f?2WO,&23mJzb[\;>r5ͽbQFPO1CE^oY~vi?ߓ:]y]BekźՃë_e }CL0*|E<`T%a1߱3SNaJal)|ѓ`PU8k@RwUx>[8'ՠLyGVDl\O>آnb7c)9غQ3utou16Oq1VRwq {B*.no_N;Y%Opzacbyi>"&b;8k1&:/'<>c!Nv FN^/IQۧ^:>M"rʺپ"bl;DVeqg{%k9?>(1ť;0x2_\ (Cw%5 )6̊Ul_)9TQkO}|{Q]M.оe?GiI<`ͩe=)˄}o!cKі$NNёK+bnUͿO~ ;`E_pY;2'$ӷ_v3]bUKhٻ+bSڻGRǏ@?`l=+`m7+[1W*JM"wqQGY/78")biߖkXht~TD]܏vY?ދoC/llBӷ|Q-kSLwd-D~mc1mv;2P7`}ag޽=MⲶmFҶCN<[1}K^V'2v~%v+b?h@;=_DWZƺ[)ӲVQ[_'H"khwbˋ㴁٭΋|'<Zu>n`""X~~ 脨=$o [\^ۏC;E F3[R>}O)/.uF؈;ֶWXȳc_s0~3WM|饙1}$siSGlE3x#cՈd\mǟEQ|y2["pųy݉֊''xM13<^yB{DۓE\GyC.䛒&zG,t`=/dK+wumc滖_[{~j6u[::ne7Tmum7l7:m#v]'/Xba0rr\wfWw00ɺYW YSٺJ'?!\+-oVtʋN%{e}P%ћ\$1y)elwsnxlfOf]d_>޻6m1k+5~h1(mFS4QF4szz8~@Vn)S)b<-=|A/yr`L. } J]H/ؤ5,k0iQy u&::y^~N[K)Lm*Sw<|,21re;sKfU¸W^J=܅ǜؑǮ~eq4u!+~B 6,M˛6/h1(-չ41ճ9HZ3v.7ؔ) iCܤ E[N)mal՝>"GG}<d:KK%̗Jkv:R%Xf'#&)!m!>,=_Wk/;;&~6t :Od[GͲGo5YǯY}X^7h7bp2xnYM;wuƲ{NNS:i[^`4G:;lۆ)b>x* s-[)yJ?X^?׍&|^ q~XI,֏%L^Ky 'kS˜Eߕf?w})]\ηy_'%{agߖi1wמӬFƄ_ٗ*T+G~.b]a+Z(.`"^@lNaڅ^~(]ѩ o[W,oӴ3tJ_t[c u-[mzH{%nXSUt(]as/uRlNtgY[0 1x3))xH'}ge,R'Mx1+' 39W]g3o2dplfiɜXvە{OIt/}Ⱦq\㵺~ʡ7u&yIe !oL ?f=w噧 Gٮ=yk2߿2<u;qu3oiJae}>+[:ʳEῄdĠ%t]p;w'š rZy/=v̷8|} 6шGĨ}o7hi&,|c.^y}̷wB?;ǵa =ol@B_1B1E144FIb^-3gNm`&**֩#}d|T#y=LЋtc¸c%HE_Dg,elMI.~'ަ$g ߏwço§oAVds9B/曆#AAݏ-AW\wlO?hoEHAbNhv|MPB;kGEE=Iз&ک$A 2;~))7o̷.!%yl|o|>< o 8p||O| z4(B?4ߓ̷0^oɞ5M=w'|/Hqxg;۽p/'@d1|e9ޛDjse~?4߄A?2Ɯ=~uKTmמҧEz|42-F7 $nG,]wcsvw=ΰS$ڸКueٷ1+YHo_1x`Osdߕ L̻uNnئy5p1XwT -s.nө E`M*Ⱦ/ZӼfposԧH_Oo]!杰2ǁ̻J0d`=I]I杷gKk fw"bܖwfks cM!_Gy:6\ƣYذyO$'2 }wA{w2ă~{נ6جyC:ɞnݲЇy5~Hxt+6nW$d<#vG7ͻ0_c~0 ~*'"{e;X|W9#,H r@CYx qjN1yRQD=,'; OռcGryٓ,iO{eߪywC9lރ!On'A>s`H{5rcj 4ͻw(84;dY<;d 4$\?K󬼬3;]y fSE3yЗ}!3}AlR$F<$ٛqO7ϓIItψ)"Ϝ!{?aTG {耱oٗ-{e le}>b ]8?j._=jsWvÐ= =A0|ǑrSy^QE9&_6,= r?HɺG77&侗sK${Kg*{̷̞">EHj~ٗ ?ny 7{G>/H>=!Ї }E$Ec>@@>ٟb=}`s}/-kS.,&eH=ar?oWɽ?%QJ| ~%`P%]^'3ڛ /{(例ܳ{V*VK ~X?lָd_ֳO"Y5nY5Evm1YGaֹ[Y[kcs =u&$kٵ|E%oiЮy[.L[-N˲q8 {,˺0./lx ;,˲[,ʰ2tQ-8WƜد 6YF<\]a=H?S $ {-^˿Wt"Q$ R=2|LESIsH_TF|S2A:-Ce6ee| s2Dz.#,_7ʈW_?[]e!e2Ɛ224eYxх1 AX}. eڅ҅ k!K.. ꂎwtt4˻#@8޵ }kwEa\|MӅVUtttO8uA/]Gi$. z_}tuA]W0>tA]At0Nwou.]#uBL؅إ 8w!nBO `\AlRA`|Wq}>S_Wg*' RqiS6'T+O*' IXW' TuVG*V?`_\A?T*VA ExW* \Wkv^W``ZAS<<q6\[V* b WUgquS\U*{co6[VecdZVaUiUU_xU!ۑKTwTOu0**IT`U*&WxUC*l ܪ *|}1b ܪU*&**b*첊إ ,U*l9KqdYUfxVUh3ݘt#/ ;ݰ {7nh7|A7nh7vWwn_7Xuc< u#6h7ލvw^uh_7֍uF1ucF\֍yB{nOI&_k8mA[{_`ۃ~փv=Zϧ$WWU/ Ջ~ E[{=C/ދv֋N#zE/b^7zaszas藽eHˑkDZz{acy/p]ًs^-Oz+{{{{1{awzac,&C:t v׋@/|^/Ɗ^\/|@U$_/|_/t{G7`^.t ы1p/Ɨ^YƗ^^Ezau:v]QzCu袎_AY_[h:CguK+:lzCOuꈏ#Oڐ֡:F}sN}x1_m}~SG

T_1ա:Y_G#OGg:Cu};S}7u:SG_C/uu}>CzN0V-=Z#>>z胟>>z>`sIƾ>`ۇxx!}X!CЇ~,eNFn}}E}>vlcB`}z_ՇXE }o)}}?>}+3Cgg'OO~1D?~}~a|V?X~~ԏح~~`Ǹُqڏ9^???i?ƾ~f?ƹ~ڏ>T?b~~a?b~ OBz#ՏmbwAF?|? sma~e 7ƽ6OBoqlzf>s7}0- ^t }ls9m.пpn6`n `7ЇUG inЀ_EH$404 +i> 1i~o@@|hyc{|iؗ6?#cH O |j>Ҁ_m4[c4bƕ   Ħ Kh j Nm4? Dxx@Հ/-Bϣ(8 1 ]BGGF(]txQĚF(ơQ7gQ`6~0}xbE> ; F(((O.csQĚ`}bEGF_ݣh} 6;cc1lk mC팡ch16=sla >r Ц1~ }| :О1xcht;=Achƈ1a l ~l AocM~ڄcM&{M&Dj ͹IЦ&MD_i}M&zlMD_hBMŚ_cqCvބޚ[mlMM 55&M̷kMvzlMyƇ&l LS$&&NH`GI0N4M&C \&m">nKBDhbhҨ?-LDkvZO˜B|Y zhZ/-`BiR ~j쪅r >ӂMgZ7Zpoam!^ka--%-ނOin|H cH \[/-`f-N-ƑpjZ;-Ľ-`Ղ^alm/0[ cM 1J ص] J cO J _K0fgq̍ǁ8xxq8{81>Lx1>0|m8LOx{aǍq8!qZ$`v?ݏC}1\d{:?tG8t2>?~G㈥?O_ïc/3_ߏcG?hq86]CGqc};?1ǁ0zN`Lscp:ۜ]NO fXM$h1p9?8qs1F$}& `8 '`pb| rN ~o1OF/;'0vN b 7xsv?_2?211 '&`os 7&`Ӏ44`6 M-N;: }zj94AiЯoOn0^LNӀ42 41 }{i`44;qmgtƅx~:^%{\i{efoպn\nqo+vq6,~OΧsѥ߼LǬ<&wWն^];Γߤzuswt|.N^-Cu{Ck$;QZO:}rk i,ӏnwHICvʷq'^MU!{sG]_CImq(ݾS!td[[,g'Ofp_kǚGοsw|C?׸9Z?Zm\^ߐrr$$_vUh\ yH>ߴCT9~Oq*58'$~Ƶֶ#Luĵ_O˫>5.q94NOCqj8Jo\qW q#hsyG=y}=PcÕw͓NNw œݮ^w]厮~>둏;>,4}m'Bۭ;WG˥ehN5JZO!pqyN[ yT}hϵs8F۝g-҉ uqrL?~I/'o;ɧNo'=.yֿrN/:PҷύFk\W^q_ˣn{zoɣPA'34'[u|P\n<1Oz)</<uMӖ*Nи P|g<^pw^rG7}hlÃk~U}tVr_WqrG'gh].Qm:^rTOq\tzwq^G~N7y_i; Aߵ׵>٩8qJۛ:iߓ1߸xKnvмYۇwh?_;y9Nτ/U]w~U+~ߖ[us(}1nfR|i=jz~wC/eS}CB 5qG;;uGk`'Ou>ݹ_yDh~7Bߴyth 3Bq7K^qv~Rкr( ʇ'wj?ߠq?nqSzT}h%4؇1>5:>C6t_JB _C.n}_A#4^t<w=[ˡ}1z[?n էOcrqܡЍ:~UǛ=}j!BVxBQ=/ ݷ{qz]oǸ}5q5qACv2}'q'tzbh܎'ǁq;nJ۟r=w^׊/ 5[ ; 5dRtx8;&4._q,Ws}rq:~S5x_w~-B?wIԸ}!?磓8ZW7CshouvSMzh?ohiz\ymq|s:~hhߡ^xCZ(ɡ}vh7ƭCi'ွw}GZz<\wンP<:JS=]['q Ow ko)ԟ:PkyBOsaqg[hꧡC oIL1^BrpBAJum=kzvzߏήܡq G(dߡCNރߏ󐪧3^_jOH]`j>i ͅPܬ7}[rsO{h#BSG/qMu]y@A;Lڗ oCgU߉о2W.}C{cռIsSgup ww=zv=q5^__[珩qBCgu⣟ ţqwCݞ`K:;Oϗu\zv!|IzUC\珓/v=^}䯺яvgn^ g~[7;k14ǝi}~zOׯ~hX>~ޜ ==9Bu=.n\U/OGbuh;I^:f z=NcHq+[w}'4GL=S]N92>I=~➃׭&//H_t{Bϻ=ZlCTwch}<. o1#u=\./8?^+ޱ~Pyܸ4UŽn?}A'Ouqv1v=ZOyZpqG^mz<~jo!Bz.n|`~u딺|p '=?3PǍ[q<-4$.㈋CqTCGjy|Z\;>}_qGyC\KBTW뺥9~J({Bz>Eyn~Bb٩8oOu'ƽMǍqvS==ƭLu}$n[߸uIk%?&n$4NAzghH[ w10Ԕ׏z y7~7kqr١>4;řQC9Nb^qdh 1=/O;&3)wg_cz__r*q5nVg8fv{G}\'Wgh?'BCW:_m7^_G~ISۗ~/.W軦EtpN_OǫZql{١uu^U; unۇU=uMravyz߼],=}Bq뵁 ݟxcw:~>8?g4`/4)qw׮2hҺt!yB|:Y/V7Z o+敺ŽaҼ(6i~4ygz]#=tS}ڎB>קB*߅_M47Bq{q;^\; CϕIvx>m}cܺI}mq&׍9RXwGe:%֯~=Vƴ|:>=w 7^wyr/?{coq_?al#_XqzqpN}N|է5yu8Τ~;vi? =O/_i=CS#~NWOBrG= Gv:;}?0Lz(0tѸs3_VwjlRoG'y{hJoz'n^ˍj}AĽO4.8;1w?0<7C.ڟyB>|MG~Jic?K<Nf>=;eywϓl(>1GU{7{v?rϥ_>w +B|'t6byGPzfLg7NGW>kw߼"l>?=kyMl3?+zޟj8%Xyf&ך1?iAhZy_6ƯN2Y1{ۼ%pF=xW[Mޤޏz|uQN&J6O( SxXslL>Ӿ1dGqM_8FOfWO;eu Z^ho- 3G~~?7l[ĵx>n"sח krI>[P30z> 0_Շox/2ʟ2L1oy]8jܟN(c4Q:tozO;m"G_^sԟ{-/80zopIE \ֹ-}H2.h\r`[OkW~:)v:a yOL&͏~xv؟~,z6XD[_go_`4:*8/īLd啙jrfw0/, pVubwœ-ږC|,d8ɭ} }l= G;g19.Cfu_Yf0~ԎS}avZ{k Os+<\ }~6O:5Dqɢ_9.Fw-z/睖7N|C<=^ )G>¦o⼲/Iփ֝:-S-v>gdp ͮE.weݨ嗘dYϽ IƝB/|EOwuۯ~ZB}i֏|sY[ ^/k Ȱ>Ēg-v>G0cÝ_j7]l~8qGJ;}>2ߏaܑ3S~$^a_p'[(W|?=_ pS!by7cH;a]-LW}-٥Kޓі{'GvKz̑|D>ҏѽ~T^oMA-Z\)z'C:G x~J$j?J>WnujhS`7?e/$}|-jr g27xXaمYZ<)4U%ϧi0~cYeی޴||Ym/_q}[Ȗ?v~ߢUϑ>HӼS]/xh~^I,}/br0;t??YoZ%ϫ͏?,n#I: VtFMatrix/inst/external/test3comp.rda0000644000175100001440000001062110463734405016752 0ustar hornikusers{XL7SMM3SMRL(DH%d$%$"$"GŦrcKJR)Jݕ~ح>;9<;5k^ߵg}grwS(F*2h*z:uҥkVQ(tjo;n1"ex P%o:/L v}O\>ZtUo3}-YZ/[~], 1o^y=?xLΘei)].KevӾ{I*?M]-UK:ua//\Im5m9֫yҹ45Ch]V䌒kDcfIwMk APpBb`X(hڋa6Mа=nx{s<3 Ll{\\tN?pNcn?+zbRiBỊ|^raCdw[}w5 :/ vrqb=`ԭm_a]MCe,N٤ЛS^tNbqtky)I47^h~̶UQIS-d cB&niv@t2Hh;bZ n1aԂ[37њC -5d25 4$Gd!TIۀγBj`ymI{%ExoGH8{nGD 7˶cʈfo`o RiǨ>iYI@8C$4<07V{ ,b+O,@-,䘇HT SkH;%_#wyX7#v%0J'_ >N˕ty.n[Q0㪇ȹpVR?p#'4VB[if|-J0dӃ"-{<Lʋ~N@7uű;/rA.;" Բ?Q6fi͟rp~'Wc|zw`-~П DsaZ`au. m_2a 2Xt_+'޻f FjN6Sҹq_M`Hm&3pyVXk_HXOR}GJrwx21{rgNyC}eHg!X һXMB^&୴So1ʀv-{;ֹvFٶp&Xֈl>k Syg sf8zbԭ4,e9X}qąV/USdk^os/┿^;k'aܮDN{r-V Ws.m=c%9ᙩĜ]Tӧ7% fÁSVkTZ'Xb.0&!R8`Zd;QQ؇:]Wz#%: ׿]U'5/Vf"k}xk|'k OEMפ1R/@bE6W7!qCG#vҀG}cog:ؖb-BV^˝}K'NMY Ozђjz ڬ6e9PLqb fkLUVX.Yg+\7w9 NfܯStKφ\E'0WT\hوWnDuŵiV(;rbfmQ|~46yb(֪^T|{["t{$:RsMq@;U4Vgͳ#ioჱ"xK .K ϷmXE7L|mտFFy6i%{֜𔂝 1xЫ̢zld6@!RhZ?VpλXClniO!Uz_!@:yIl6Ķ?s,Gl 26IZnڄWM`>?nr!-Q ו'bXWX\^m9X[&uP,rdLÉOu |gGpۀi> h&Fl unbg\syYFs a//gIggZt@Ga`h9]Ou+|GnU,]j;߼6V8ڊļt>KWTi=m v}=W{=Wv{Koߝ,~>^}\<.&H?5y`}Al%DIN$+")$aHCB0$!! aHCBR0!% )aH CJR0d!# aCF20d!' 9a CNr0!' 9aXaXaXaXaXa(CA P0 a(CAJP0$ %a( CIJP5aX5aX5aX5aX5aXt%dQJFd"J2Ĥ&&51IMLjbRĤ&!5 IHMBjR$&!5 IIMJjRRԤ&%5)IIMJj2RdHMFj2R&'59IMNjrRԾ2uUIoO˫7!Matrix/inst/external/pores_1.mtx0000644000175100001440000001131210275433311016432 0ustar hornikusers%%MatrixMarket matrix coordinate real general 30 30 180 1 1 -9.4810113490000e+02 2 1 -7.1785016460000e+06 3 1 4.7312729960000e+00 4 1 3.5742618540000e+04 11 1 9.4625459920000e+02 12 1 7.1341308750000e+06 1 2 2.3349693090000e+04 2 2 -2.4613410870000e+07 3 2 -3.0051645960000e+03 4 2 1.2934346290000e+07 11 2 -3.6807151210000e+03 12 2 6.1495431850000e+06 1 3 4.7312729960000e+00 2 3 3.5670210950000e+04 3 3 -3.1208606780000e+03 4 3 -3.2500820450000e+06 5 3 1.5522075550000e+01 6 3 1.6287803340000e+04 13 3 3.1044151100000e+03 14 3 3.1914882100000e+06 3 4 2.9953986350000e+04 4 4 -1.0035133800000e+07 5 4 -7.8658863460000e+03 6 4 6.3330904920000e+06 13 4 -5.2284380090000e+03 14 4 -1.1610330070000e+06 3 5 1.5522075550000e+01 4 5 1.5956339430000e+04 5 5 -5.9720828860000e+03 6 5 -1.6395834630000e+06 7 5 2.9661271480000e+01 8 5 8.7000917550000e+03 15 5 5.9322542970000e+03 16 5 1.6097273710000e+06 5 6 1.7473258330000e+04 6 6 -4.1182170880000e+06 7 6 -2.7076007450000e+02 8 6 -7.3466724480000e+04 15 6 -4.0817635000000e+01 16 6 -1.1075258970000e+04 5 7 2.9661271480000e+01 6 7 8.0481454440000e+03 7 7 -5.9475459880000e+03 8 7 -1.3740635160000e+06 9 7 2.9419951740000e+01 10 7 6.7909579670000e+03 17 7 5.8839903490000e+03 18 7 1.3581915900000e+06 7 8 1.1788389530000e+01 8 8 -6.0472270900000e+03 10 8 7.0730320960000e+02 18 8 7.7968763160000e+01 7 9 2.9419951740000e+01 8 9 6.7909579510000e+03 9 9 -5.9713573530000e+03 10 9 -1.3323692060000e+06 19 9 5.9491819500000e+03 20 9 1.3189422360000e+06 9 10 1.8213815350000e+04 10 10 -2.5059847620000e+06 19 10 -2.4969274700000e+02 20 10 -5.5328319620000e+04 1 11 9.4625459920000e+02 2 11 7.1340421910000e+06 11 11 -2.7807437790000e+03 12 11 -7.7182097420000e+06 13 11 4.4060542710000e+00 14 11 1.4480734490000e+03 21 11 1.8358559460000e+03 22 11 5.7572487430000e+05 11 12 2.5797297290000e+04 12 12 -9.2407184210000e+06 13 12 -1.1588958390000e+02 14 12 2.3027380050000e+05 21 12 -6.8657039450000e+02 22 12 7.1253609460000e+05 3 13 3.1044151100000e+03 4 13 3.1912678870000e+06 11 13 4.4060542710000e+00 12 13 1.3807829320000e+03 13 13 -4.7848602210000e+03 14 13 -3.5808334290000e+06 15 13 3.9963378410000e+00 16 13 9.2558550540000e+02 23 13 1.6651407670000e+03 24 13 3.8566062220000e+05 13 14 1.8139423920000e+01 14 14 -8.4585448840000e+03 16 14 1.0738622860000e+02 24 14 2.6158080350000e+02 5 15 5.9322542970000e+03 6 15 1.6096290890000e+06 13 15 3.9963378410000e+00 14 15 9.2558549330000e+02 15 15 -7.6610458140000e+03 16 15 -2.0016469780000e+06 17 15 4.1131980110000e+00 18 15 9.3265571700000e+02 25 15 1.7138325050000e+03 26 15 3.8860654870000e+05 15 16 1.8316189080000e+01 16 16 -8.4066950400000e+03 18 16 1.0674546920000e+02 26 16 8.0723176430000e+01 7 17 5.8839903490000e+03 8 17 1.3581915900000e+06 15 17 4.1131980110000e+00 16 17 9.3265571690000e+02 17 17 -7.6966204670000e+03 18 17 -1.7682272950000e+06 19 17 4.3138675330000e+00 20 17 9.7583624590000e+02 27 17 1.7974448050000e+03 28 17 4.0659843580000e+05 17 18 1.8104876340000e+01 18 18 -8.2868969120000e+03 20 18 1.0561495530000e+02 28 18 5.1700319220000e+01 9 19 5.9491819500000e+03 10 19 1.3182531100000e+06 17 19 4.3138675330000e+00 18 19 9.7583624590000e+02 19 19 -7.8034482760000e+03 20 19 -1.7423949200000e+06 29 19 1.8608642830000e+03 30 19 4.1338216070000e+05 19 20 2.7213686810000e+04 20 20 -3.7862462010000e+06 29 20 -2.7268589770000e+02 30 20 -6.0465513710000e+04 11 21 1.8358559460000e+03 12 21 5.7532622180000e+05 21 21 -1.8730197800000e+03 22 21 -5.8390768360000e+05 23 21 2.5519125110000e+01 24 21 5.8925928100000e+03 21 22 3.0689873960000e+01 22 22 -1.4220855320000e+04 24 22 5.2041902550000e+02 13 23 1.6651407670000e+03 14 23 3.8566062220000e+05 21 23 2.5519125110000e+01 22 23 5.8925927520000e+03 23 23 -1.7282309830000e+03 24 23 -4.0006143080000e+05 25 23 2.5979289500000e+01 26 23 5.8831777310000e+03 23 24 3.1037943720000e+01 24 24 -1.4640445490000e+04 26 24 7.0608811070000e+02 15 25 1.7138325050000e+03 16 25 3.8860654870000e+05 23 25 2.5979289500000e+01 24 25 5.8831777300000e+03 25 25 -1.7785733520000e+03 26 25 -4.0325726390000e+05 27 25 2.7334717910000e+01 28 25 6.1828826750000e+03 25 26 3.0617826380000e+01 26 26 -1.4459345430000e+04 28 26 7.1015603570000e+02 17 27 1.7974448050000e+03 18 27 4.0659843580000e+05 25 27 2.7334717910000e+01 26 27 6.1828826750000e+03 27 27 -1.8647846840000e+03 28 27 -4.2182964720000e+05 29 27 2.8739153910000e+01 30 27 6.5001941810000e+03 27 28 3.0184152090000e+01 28 28 -1.4268956760000e+04 30 28 7.1493041500000e+02 19 29 1.8608642830000e+03 20 29 4.1262902020000e+05 27 29 2.8739153910000e+01 28 29 6.5001941810000e+03 29 29 -1.8714356470000e+03 30 29 -4.3693045430000e+05 29 30 4.4912526670000e+04 30 30 -6.3991790180000e+06 Matrix/inst/external/symW.rda0000644000175100001440000000251012214433704015760 0ustar hornikusersV PTe]ayc\ Dh9B#:?Fc>AN} O$y21F.Ð#6T&iTSE%b**$SOJ5#TjrJ=nBsY$gۃG ! bMKd w@~̞5u,HHб<\>& zqh{dG=]+ eߪ$mgGWZI`ud}/BzE~qbx'PW]tˀW5jp> `GxegO>R~EhX}9T2x]Z>4G5pݾ 0WwP!ylDF Ծw'/dG}(\,6@6lrn 4ku s_RdvfTNf3KZgwr=M< )>~c6ATsv1alSR7Mi7c)bޜѧLij/K)fr Matrix/inst/external/KNex_slots.rda0000644000175100001440000015620010464427703017127 0ustar hornikusers}XT:TFc/c9b{E#슢+v{=* b8$by;̝k3}ft:% "GLolpN]!G|hѶG{_ө+n3 M5~ E{po4 s\hxxߥ='8^K4+<zk4O^4;4\/g=s-Km5Z~h0( \p/^Eh=%J~ Zrxh*9 \+UB5V D_:Z 4셮6ZFh5jAchњ5go{w]zhߣzn Z3x/o؁5Z[x= '6h:R^ 3ZW~ '.hzx ߫yuG 7Z_c>h 븇c hCц C6m$ڏhSO9 m Xxcc&MD suzړIhS~B6gh3pƢfBs{6h:ƫ'mh<Жu.tжvB[`m=BTFݫ.=ulRY up_m=7;*=0m#&-6SJ}->`z‰/hvAۋC"?0U=*U GuOc4U{' D;vZ Y|z0݋Q0^@>X=a0Qh'NB;>TshhahE}v -cmu:520!/*lL% _C> Ld`GTآJD'& X8% 쩰_~S0e`H^dQ&|͓7tc|*:||=D\` @NTF;ȀaK:qC #D( uyˣwaF!谟:6:؈Cau1lG@ g1D@غ§ ⊀X`L >*| _! 3& vdKC*|" * $  *(79*I/qE@[6- &` PZ+{R`O*bU~]WTSOw~O| } N!{*⺊Ǹ~D/!. K@PuqJ@!^I' "SFd`Lƽep )dO*|x& Sb8%`^⛀&2,c}d`HdCuTTM@|@ 5XW1~Vk̻\H@ e}a20"X_@FqMl[dy!2A+iL|u11~v&Þdؓ {SdG'segY>2 ('i2|\)_"9|"' .Ⰰ8, &JaO24g.cme&#>2 b$`Z<(#Ȱ#Snq)ne+/[w lXF̒a{2Q˴OɰMlf0'S'S^;W26yɰ9lIXG,Q/*fe"1B =Sy=P~!g G*NOoG;J؈(/X{~Ph`TvT#ؼ`lW-*a b}gv*lPmW)O*DO؍x/!~Obk|=*^SlK Xo'!^֒ ' ~ *'HqZ@<`'!Is☄#!H|/KoabKc#;ؼ8. bx- @ ~C%/!KX# k*/Jb-!^Kb-!>Kb (<|5>p8 (xOx!zpۖ`SlJ I+ v$v$؃{Pz= XCc0.s  ؑ qF&$4 >MKo -H v.l]mKw +f%ئ`lWBH ^BL%` WB(/ )buM\6$y) =UC [wFA?T` % H> c(?R)\r 3A^HATQA!◄%!Hۗ?HD10"#|D8|P,`C{1 % 8 .a%zuzYV. (/  "⻈$ C/<= "M"ⰈBD~!"ÖE\$"ö{[&u^w<="0 —XKs19 0> "&-"DD BD1dzG~+ L(iW5"P&.c1n)zi[wD_"Q?{'b?dW_9z[ua#"!-R!_Ly|cz"YD."r8*R*0"<9\AM E"V~IX;v`h>ZV H;DD'"'"v" CDbNyѺ"K 1EDlD4lb D$`@"\ 戰cFX=PEVD lP"_쩈*<@_Hq &a/%3mWf*>ѓ"."ǒR^a"|KD~%$⧀'=I]"| "p"5"bH G=H#F(*qwzD' ՓƵ"bx#"(LGO~E\+"1fHy lQ%WEq?1w~@D$6%_C"HĺX_%ʏU_qY$_(/F\WE;"rQCB#"Oytz_ĸDK8 o*⹈{>yI{"(>A`D/#gг,QEQ1"G)GnTC"rz"lG=ϑ@n %>*8?"6PUJ,n)czw} gx`/UJy<ݛJ~*!H+u_XHc$ /H F,!HDO?O%R P/O%C T_W%C ~U[U؆%Y ~]lzϕ$ov%{ UB<$1 VB<$`2^c{+c}j=U=*CE,RWTGY*| KOy3|DN%rSlR)O%Lp*;2VƞXw(eآĹNYvb}U쇊U*q9`TJEk!/2lS  [8za*]%^{bOTW'*@=@L J'HLKS `a$;d؁Ɉ2bLZq2 !{d)#ʈ2 .Ï2| .2rrC&nBgnA_eZZkOd_ndlY*cV b)`. @!ؤ߫`< \K(W1^P Ư T)Y b*[v ~) Q! ` 8%`n `. RA^ F*XsS+)Xk3'lRORzN\( bB5 L)qvPL؉x`_0 F( Q("N* I916 p V*g  bؠ ) ( b;VHׂRzn"E_R_T](EQ9 SAS( 8bTQ\ cWw Q1WR*UPwĜU=PDzX7yQ1n4"HazG⑉[GIմF#D1,BI3tP I tC 1fH醤Ni/VAi9VD:郤FHl0K$1M$ tAI$-4?MBH34? II3胤 i}އ<ɠG|XcGrGZ|!~gizƳ<`6K#tEb`.EiښE:ԚH7BҎRuȠD:AkԄH!G{H!GwH1:hZ8F&K!}C'm"ҍ4%қ ZiVYS-*M!8G/퐆c~H/#r,=tNtCZ,ocI!M8c┉w&mgI!tbH{\BI=; QHC!-tEHKѴ<Azi^AYY@qԽt4⻉s4&@>qaO=oII4hk<4xM$x@  'GII??#8@ oF\S3` # 7p`wY\ q^ciY8,⦀?Eoঈo'~ 'oF|qS"> 7pR9/E3Y\qLg"^ 'n)^8-x,~$?O"7GY|q?gD=!~x!xe,n8d#7L\2o 47N7oII0pIq<C<q=gx?7?q8^87c!N$ \'C< 2čC| ŻD ,ע+ąǢc?qdx?k!N7*ğxQ$^܈Ɖh<ƍo8?$bg]3%~ǛbGRȍ4#I< oىG&_H#L<1q'O<8i ?qK<0ħfI%o+4-q.ij'8)|'ħJY~IZQO}_8#s7"N##g : w?1jc'7īS]ĥWjG8sƉ&N8pʼn'tYYM5ɤGi3FM6iS̀+T/ +? IS 4&fAiA@:՗i&T/E5UTsF5pTFuT7HZ=1S>30tޅδY:#BgK tփu;ΠgvFgt7 TGMj5jyz}fi3Tm IFN1vzvgjaXa8#@g*GF].Q+` 5"t: GqQ(e9M5uF٨sT1j&ՌH .BG-RǨ0BH.B:KcԨ47j*PTɡ7t4IZkU\Ig%UwZXzZfl 32tδzP=Sjjl0۠TK*o8@Lй:@tj9:Bgg3itδYC}=xQfP:pP ,T_Kzz :Q.jZ$֏jڨNM;2zC%TbcPK@=S \NP@T/A5ZՉP- ՊPzP]iꤣS}WP OTA+T[B#ZmՂO;tPePBP]P݀HA"ꩀCMoZRΊj^j.HZɡZC͞]Q R=%Lj-9R]#իR-աR.S2R4OSDw%lOt49E:sHg|UsMt΃Y1:GF5TSNutL;FsZ3G93G8s}3G7s}3Gfmh9fmh9fmh9fmh9iDtH#K[uRrf/jzi!ݗ=YMI3%ߊ%UX׺>`I{tWt_Io%tRCuyJz咞C߷w\I` KI&mXӅ)>P|%M4bMR%bM'E#';F6?mTyH$M٨%B%-t`)٦;J1ƤqZwq%F!7Fu7FI#%-t|3lOi~;T)ϧ:Mקg\7B@gݺZwAցjH$/;?ӜCn>{T_A1eR1`ȎC 1j[>j9^o|R~PLݯ)owR͇VO;TB+TB*'TժP a4f[z78Fj8ؤ ǤmмhݨV3i4vj/A\.3%/3VA19xMMRL&aj^%'Wj(EzZQ ab c}^jꗨFC$/&%3;񼔣_8_W^_H&-tdҐI;&ݘ4c҉!H!ޗt`H!텞kYMh4.!'4kҫItjҨI&-th#ލ8fz蹕4h(>6u Mc~_y$9I$)9SB\\ιs%9JrΕ+9Ws$wrΖ-9[s9[9[s$lI]]ْ%9gKrΖ-γ%8H$͒4IIW$ݐBI$=H#mt9Hk#M3H#݋-ҲH"݊4*ҢHo"$ҎH'"mtF8ZaHW!-=H !Hs }4'ޞyW_YU˪4y(#h䫍s8b⃉%XW3%Gg\dv8~"ȣEq`=/EN1?D=B| #e#[bʉ9{9_陓#y9yYfVUANY!ʘ0mʭ)\eʉ)Xc#)gܐr>(_l1,-CtP16'79=]! ?B P@qb1_(.Q<3V}F5F}7c#>5? e>׽5(kg3~?[z|=ƮsAW=c9qTOgTu=WOL\TJæc|zj=O`L_M06ز 0d?dq G1L&;"&  c3 ~ n V`M0F kl5M&k`c5XM& j}7MOL?L^+1ŸMMMMMShSeS)j<))(SNXkSy))ly))1-"W0ŚbNS6l l"VŽMM)1El4|Laf)f a}0>03333rE3fr>3 h71ͰfXO3` {olç#&cGaSK.a0Cn37hnUnm7; @zX-&X r =X ءcX` , `>Z`%k{ZbΖ=KľY,Z%|%UK>Y".,a{;K&,oY˖ KKvK`6e |ZV'+| oXa`3V Bkϵ½Z!Ya`VVw+غ 6aoWY=yƽa)Xk5g YVso?56j1Xc_5P|w`#0\k5 bblmžm+l"Nl1v[ر-1y-|cg0;vka '0;ثv;; ; vX;;v#;ر;*;;|ݫwe]=={{=8{=a7=>ص>?;U{ت=e=:F`#Upȃ9`l68 q;9#lcwsĞ;;a1fG%GXGV[GTG`pD>|pwq<1G%G{w>9a`kNrV':'` 6A'؆9' 'B'ؘ QN9' w0'l q:?/?V) rӂcAB OX ÖE_E΂zSǻO}iҲ̡&6^SW6晗?g|>nu֎>8?Fuu>5{?>?ucӧvl?>O#;n:gP@On:?)=savq}}),]]:*S?')އ_u=u.{X]ȮC'Cjgwv>~i>§F?Tq8R*OǎS[?Z?}|sŗ?d|nи?ȇϽ>>|>>s_\|K]Z/f:SO5Zs?]גw}T\ޗOn_J'eJ7Tvnj+^OpdOߗ>W/}S\RR<ǭL9D8|p.9}N/FY/s}@Ԡ=9Hbs~r?>ux8tFy9}N9}Ngϯlwa?r#Rlz;£}f_/*;U 51ێkoV,"DnxK7%Oo>UFes4!cK.s {xɳNpdAbU.ڥ+]ͻ?o::o}]"?jC.<kaJKCc%T{sK<9~\ExMz.3+/|~ymS y+[p>ٹ~klXXAyigYԽc<iI_H7b;sm=j%n/q璘*迢< n{Vˋ=;"xڌxꂨq#x|y ]ްQvy9[˅S͞uG,\o8ZYm̷ Ìf7O+{ԴQt|f:.xz)13.gR]kgjỹv>?֝cƟ݄G;,.?Xk%2[QEH-z]v,r+ξ.8ыExͬY#`IvÆ6:ƛUl=ĩ"z_hǎw.ᦓVWe-srعlgWhpI5ؕ[Wns]-J.֎Ùuf%{#NIB{+p_|hzZTUf6ݿYؽ~Y7Eu_Źw}&K_zo}C9xbJ7~#;m7<ж/ٶ>5A`Qd,ͣ,G/w 2}#u}/ŽF%F󀄾b6Z[NխZ:u>,ZA-ɓ dR£N.gvdZ2^ٕ>O_'oQ1Oj_fT嶴5iQeYc;߭q+}ѬVDzw孝"VשssKnJZ7]g?-cܘR)h ,F8Qij4ѽ2b O[^!Zm~ժbIzyعO *l\l݁_ΩQPο`vء[Wݮ6.Zz;{'߷sV2ry%KL=Oo%!<; ug2i@լ~]ɽkPv46BbksjE\{q?>W{K~,ЧW"c!FYlM- \4g&wkq00j#ʲw;:۴yt׋VU<-BO/b5aaңoc/|鷘]r/3|?2K[`Ğ,zc~mk?VX*(?N < co#.)P&=&<Ү^`^ӥCbg'S\wig׋XC~5tEؖq7xxʱW;zv4n,c^<ÿ.~_/;V" sߜVp]*{UFe4z1c yNykDɁ=Yi1\"4?+`?~j!AֱI6^{MϗEݹ?ڄk5t32j<-e^<~bcqRmّX&yHc7 ߶2ٰ]wvGOfuڷn)rF~YwIcQB,/oy)#n6pYvġBf>_~uCF#ZcV0A0zqϔ"?ݠ+{|I<Vfǔ\x{^VL"Ktdrv)cO%c].HX6ka0wth|߅ѡޓytdaWa+xYxaSƶ.^3#mx}YBN1b+)dVz*Oye[ =??,QVydjuncZ[gz :E9dm;iXr7RZ ;yFMjW\nIFHcԎ+S};cީ↡,n.5[6H}3l |N{ܚM kGzݪR흹'mO _\;O ?)i`~5GŶ>m0ym3,c#65ژ9v]~l<ȷ4?ш} C'=>?(=ҟ]pWvl:֎oѤB|S|t7y2eEN|FIws-Iԗ=T wµ̲姉no6X 8< 3ىwuv-Z?"ltUlJSw:}lܳykJWbëEflGN*1*;-`k:ve/[,ʸMإ %ǞˎԶqvɛE;#;}c~1϶&;t;zLvRYԹ;6p_ةRaɂk/XhԀOV >pp~,bggfu&2~Psaœ-$aׯ{oSwΎ[Y&r jlAalBxfҞi8~,:pttO἟Xc >ԇqUe|'g~IloؽaW a, ;>URwْ8;5q2 z]6s!mRXXrkJbnd> _WZw"r6cs,Ǹ v\cZw:bx1Fٵ>aNN8cj>uY-C;20EXގb{gs{gB^!(sZPbzmxgvMf#Ѐq3'*{N/Nfg&5 :;Seכ_Bu.;v)ZnaO{=yb~Z1)~j'I lp@!U5Nwsby~}Arp*8||OY}~Wo's1_oZ򛛾׆əy2B3=]/1eK]NڕfΡֳy޶"zls &]öa5;fvٍG6[]7~A5R D-/1/'C.b'ܨ /x# 4V,yU#O mP8~)d}ހpEug8laZtrk_U޶ ?Њ{z}X]콼z b,YӐGuMrxTg}Z(!W2Ct/ӊUޅo7SoOW)m:/Z G3Y y"Z|lzzcsYۏ,x"Z q-M6Ve #+n/Mh.?|`Q=j 'ȬO5]bqw~ ;c}|NBNMĥU2mQM}5per؅nv?]5%XHkT75ռ_$nL=~1t/mw4|{j1~.@\ڊT Rঞb+V:&~U{Ӊֱ\T}8?[v iձlkuq>E/~ưcsխf;^jqw/޽7f`SJ+βզsws|{LU;xv<]|hwv)n?pq~,q7XԴ m>]>BSU>3,֏ X]4zwυOu{j}ljͿ͕g ai߲}޵ {<eG\Y.RCVvG|去Ž$x>v_Bɽ>tOK]kF"ܻZ/{l~|} g JyngMkT.7[>В'sBQ-vT,I;a llYO-;'>{׬w^-X^Yo>{]uJWrtʷhY lG>0< u|Fcu泤>g6IiV;Yᇉ8q%3rϺ|FdG%e %'X3wӡ&w*'빾!w-vInkYn[C:z*[)݊l0kw,>kE>!ɮB8~nftMF%խ˧]̳V#رq|ZaŃf|j#'U˧,D;SzK);*3)þ1^O4Ѫ|19[ɵ/N_q1ړŏ}h,~WnFX:d?jZ?cHԺX|,~nj!k~a^,ߢ[æ-~1j23'qwaUukEA1@ B@AD2(P.Utt# b"b}w?ܗǽw]c9kXZk6Xݩ(ٻ_y.ⱡ2?,ȱg6.X8ȡ:BAg-DF<+{Ҕ9cLH0/W;ƈna k0|7V)a=U41x %פ`Kk1Tpc9?aڣEB&MIigQ+bܝяͿ!}kZ'գC/xk}rЋG;ofBA/wT6(=t&?"l8e/7@ڡ~&\1" ء#N%)o,]2.gwǐa)8tx3ڹS d͠6NԦhʴPSjT*O⁨acT M,+)qETxTe‹r'=nUWٛxy=-ofO؎9S}X\!s̀Ű@rJ="3 P/!mcO X_=L(搈p zpuY.QR'y"ܙ.~J8 l,{ rU½ %tLJ`UK4r C~rG͍:0.~_] |8 GYIVֈ<>ڻa _/3}_+`KR.x0^i^e(xo׃uB( 7C )9k(JM @!0itlOfz~A'LvX]} AjbTAn1YCPm 3 d9 dp}tC< Xv}|)S9}b)^m?D~+63.kQ}0L(Sz|y^֦Uة8Tx C 7 LA[R3q^=ɖZ>A#_;;*YR s֬]E {ߧKoD_#lJ:utK'E@| :v@ 8RAR`ȭRH-]IcWNC%A ѐuRnT27d#{_pvM}H8Cs1$ȪĸBY;~H~{W{V Ͷ6md ꒐Ð6tfh[%M;fBڦG }whjqU$ҥbVC5NMԐnl%!9%%=Q=tHZwK#1z(2;xU!C{a{Ȱ4yuԕ Mٱo(|_!%8 Du5jb M@t0r:Dެ@msb2]m) &V;oWAr*dSnCޙk@ɨurCG 9.q5֫>yWn&@vʕkg(Rk4wzA< &R| &TE:A~~^ b`=tlm :2&󴐜o$xb'g\),؇-TOܻAئ!Vb.nH=yXOȆE<.h!ܩn3᳏E%dm;G䊃ko[,g@d4 ba{\@ `ٜ4 .G틡kQ,Dhx%k4Ik˒A iL1\387v{\o]v1W.J\$ۏϤ}F6Sst`f4j ʼn<©Wi ^ 8\.[C9v%*o[/+H>~i- ͥj=Y|d-eбC6}!6Qf]DӱXt/66wm¦Th@f8t\<|^$7bc, g^xEoR E|.e5H1C]^l؞scj/)W&cV͠>L8 [8\_Ae:vykyD\9L܇ahc}HR'D~|;kX ~Րvm{d'd+6U iK7Tj^ ZWeƗ@aBʲPBlȳPͦ`z:窹Pr)P!D)Th|7[?u@圂2IR\ǐ 5 4B-o6JR1BC_dZz]\N^䤷`'Fpw1:̟~r: ZM$_|/95Jg#]^: ;a>qWg_6XwyozϯOSbs `ZmkaΦBt-P"v)bnPʝkM7Pe^]:-ېjZJ)W ŸwHXyk4RZ@r gyH>"&g|Gs{>dg%H]CIODBa}UH!X4 #n(aXS)lߵ2̶XЊ|[/)Mի9ftl1#\_a;#%x!f1dH `vq RYs{~#cI;f^so[ү YBUɬbŶ3tԳz5KL*9ኘPw\Pw!`d~aD%&-ä5;vϞγX%)Mr]PJ՘Dǹ U ,Gd1A"LyTJ?jgQ0dGƻ5XxS7Ka<_.Tl3utR}=RqaдSY;mKɭt8.k™w;:5a[ivyagx7.0Ks1l U=m~ڳ najCULM08};MWASAJcXMbQ7lHT8uH4#\Z)v %hi/hsݫlopg'JЌ-OZ *mwD44wz/"Y|$R\ՍƝeߡJ2k6j&3&$jڮK P!煿;뽭 ٛP80bo^f*\{[rY<,6 áVox#~*U:3ͽ!$|?w3E劂wGq>o"'{P `d<C`"^}ywvqF8!*}Z!pNCԦ};k fni'Īn gKhJ$ GK1Q;qs2|Uwg.LdQOy@s$Tcv8"킄@+m*exnR|x'@jO- v ]6i^+t jV*9>9>t&4?7_}x]ldNW.yR `GwG Lׅo2F[ p(sW%"HQ mɪ Wa,n6 Gjj.2m= $kMWMڔHN=S@}Kmt2PO e_ 2+ϳل#Y 4!ѩ-w06ttuǁܲF}VȣK B&NmZի вLrBn̕"/ $yK-VZSzm!TGU,}[7m~+-%O"QKk9s ]V\EA߂X5!oνJ(j(]!umt}Alw7n1BΠm0(wiR ]BmNYL>'=r߽|Nݫ߼ Z3#(O{-xo-imӕ|OqKwDI_ ]z6}qZ!7 b}ɴG$[[Yu\',b$[T?GmJ-sLW< VُG4Jh.헶Q:~wǫxn9ܡ < JO -kJ?kd4ufAk^eì{_Q_oc K_ z6g_R􏭲9si*jlZ.LJƆboSzwaۺ bWk%TꍬPb{W+**OŮ#3nej۶,ua7ŞڲLo+oZ>?׿%ZdJ(HѡFqumVe0x#uZ> [{k;+:\.qXBIۊܠ./mb04n_soP6>ȭg(AQբ]yoc[* #,ϡ`{7џ5W uH z*?z!bډ_ =,RV9VhƉ O>ٿqۯ*xQ'AڂXpXٟ o&^1[8{AN} yt3T3{?ZB}[̫&^\(u ,q-:ܼiKc Qmny|; OeRxw_@wш$U߅򡥏mo٦ɒq? _4i=mNt|ƛh{lՏ80quBYݑAEJ>\aAq2+p S3tF;proLJѿZ>u?hgqYe?Éx+>M'J(j[~V*a|VXO;WN1::d[G@eŮ{# ׸|g1[,ܺ v0W퉹;]r_/s֯6W+ ;qɬY![wpeVC G55cXU  O_4k#Q_T( a4Wr<[[#SwWbFS6~%rI_.D}Ms%;m_.=u~'ԮW I#D7^OkʇڼV? с+? 5kx ([{b&wbW{mscbvi*grï=a,z[j:֕UTOן]xn%*JW7df\Ξ{$ML^a?:<1/_IƵ/]%4pT3Ƨ #~IR7WBMLIbpM|^6>] 3i?40wLsBs$sAb$tTR`{?_O/G).څ9'u=ћrE;&Zp~Kg5Kf@v@ggV +]6KI`ߢwWXoz.7t9۟[wG]>xUКRwUS{3O^[sK~i~dN堁CBiz&R*^Yem/FWsLWh-P?6ʽtHI u"V%cK Ӛw^p况NCTQtiH7< g91umKF<~~h#G.]~$nϑ}KN\͓;$-z6_qPeG/V N!ΝHamq ~=px~FWcAnbMzfR`W]Vu!;CvZld \0n|F !?o4P\B sE ­=[Jդ]r[W3]On[B'gOCB)壾2B3o J=o6$w|}^vHZh#nb[_u?wBI !BnBm ?,e^,UQpB&OBz,4W_(Ww)AQTmrg/|Gw)gUey{(Ty+:uO>&xyIW?Y73"}]T?GYs' G|kʽ9+~S$1uá6;^HvM5TbsfSi-)ڥ'0GE9#\umb,y)*ckL_BdBuH-Lzr"  ZTNNLSyp i4vY`Bcơې=n{ҟ_J0c3h^K3ƙϯ|Iݳ>^Ÿ[UW.ƩUJ]ѳ5xGRW}{ =֦,+B^{We@liRiha)Ė-qڀmoR|s$?x(I>{wb:KwS$$7IVnpnJ;t GנNT 7c?I ='0:̊am8`}сK=4>cMG7j) J|};SE|1#Nŀ[^aJ{i]4_B , u7JM3+~J-Ђ$`ШK䩊:[ڔ_A ;ɪXSbGG!P^}Pqbzdܥg%^g-A{H~C Kq trOs/Bcu,KGOɹoRy@b{f-||"U1De8!?r޼CN.H\}L*k 0KPru.)-Đ<}KdU. ,PԐڮ:[(X=E3r8%`R-~@o , vKvDr=\= X~jӄ eh}ӧXS`A3fSIo6>:GzŒ lޛ|4_:bӳt$ 24#]ڲ?/lCb?4X"5dP95?❛(lOPb?իs[DN&t{TEd P$n~8Ϣ|p? ,ӯDڵg$7hV W + q"YpT;uT'``bke䟩.\H2 H\3d,w:а"F;'5F2H ډvM} Zĭ0A/;5&N^z_kI;uS G8zSB;drbw<3 ^s7N=BE+ @^rB;u>AE^,̒G KO2xC^[b%[6lw/(`e,l畇i%B!n9 (,n@1[W_랗>(P]&{P,nh_,y@BGmylW^yV=Mz{gN:BBvϼV *[tr!>,0 xuJp16R261c gu! yuw[f06ޚ~naގ!M!~N8HXXI$!a7+RsnۮzLU.xWm1հ1։ ?>b{ծ6>!#p0L \ /~q;sp+j`֚ s]SgC+twрۼy/ضkN+3 1[^^w),YR#ePLC/oB#[+42əH1$FYy/Rnq-N[OZb'c0!oؽ=!jޙ#tn;8p+ 3eR :M@*(b1`hǕ |ypҠ_|)lE & ' S|(dM17ի yӚt&fi+ }%wYA]|*mc>pdLj(71R8{ɟ6V|!EO x@RrmLp?|xC:#h"M%T]|͌,$JuCKF7,uڳs+{f]'8|zѲ$F *5yA:=R'19+GY.2=(Y~ @-b6c:8=z _ WJ E>%mC]'BB'7Π E>a YD? /\Ld:HB{Dڐ`u:>\l/<Gb3+e@fy=Fv1)\:皳K) .2g!$Nv-*CRQN-3u([{@a/*bNۉɧA07kKٹÂ1PAҼ7*C iHs%r6bgH>i mỶXW!ݚתbHKhu8~L'±,}2' xPKvI#eX=t^_,#n}`R. d=_@d8LQfsH2>1NkS%>]Be˻ӫR}^^IVKAs7)Ȼŵ`b)?NxߊxkcT># Q/w?SH}5 W?\cׯipNF#LI]x2D_bAI*gO3mCyw(M2"R1@6Yrp $yUkr $nktM!jϣu,5k!XmH/+k?mxyUFwjɷ WNPO.Ę+/oρBTᘴKȨڪ2u{#b?8IyGGW!]zիYHM-^*ŌoKC =ܮ&99tqٷtoڧ^E´{Ksr5wL X[ h͙pMe##7O 1Fx:@dJUP @+UZY& n^}sgFh첡=` Oe1+s-#`z44fyθ cvDDϊ'1]˻  RZVF46]1ygoЯRo,n۠?'eE frz;Odɲ4'!͓{d/$>δT(|K#6ar D.|GR5ܦVK0i1a-Ks>äaMfX8ȶ/+ɟ.xO.yY=gy̺L^Ƌ9dCf7{k^E d_v UfۃM܋q=;ܤ }lu?GM0} ]c?܎l]zI)A?Sco smM6'G^k ݲj&Nv:$wFEh[ehi!+>hGK||o;M དྷCkӦ%+#4j8Z/x5) =6oGJ4À7KjY84JY,r;]1njL4_~+^j޽c3 @[g7atqtR?U\5㾸G>:v,x221fZw cHaܣg:lw<ڎ=БO/rc WOIc,n}G8󬟽| hݽw|<;NR"Io$y 44*c7^W)sG~+:P%?^ĤUZhfƓ +=Nؤb'F(T|g;v̱3 DzLc9BwQr2h˜ؚF E9fGl_8*6)x>"&$Hʓ< }\/Cu3+C~ĤFW ` TVO֯NŤcH,Z&GJ -F$ kSC{!C}i󶣐|F .o^'*2.oBG ӊ(]S~|40o׀.]TL!$3H9 a W7E"a>|#,B4+X,aO˓־j2`[3 4w鈦P{N9ٜ5Rant#lRkn4oad\gF ()עw3_:$ClA˜qqvW?bq{NW1PIev|Jt %Ǐtc<.Wn|c?,ٛ1_G‘g!%3L)0Ny֒p|hSu:%FBm^w-;``Ѹ܇+C}1Ŏ5 ~礰c-7MC_ele;ߙStcǙu)ۜni]MKPg͉-V OFQXY 2CW(fTΞI8xdv<ř|^T{PI}ehޏ_9g-K ]x4xs8WeM%K+lLP|z!J0x 5߆漍^Bu*;Tj&Rqco] y_\FWA!2~'4Rb (|*U կ?>T#5q˯'RzJs=6,w]( ˶T=Pڹ۸%~%4lt"2J_d>ٗ PVPu: UIZkv]~ik#uRS̏pa&#,炲kW(tt'Fn®41߱+˰+aKFY3MhYW]?):{>Ѷ9!,6u zVbSr#P^5P򸄅nI9 _Iw%Y.,B| t9_p!kWuD(>rK&||[^*#TVm{*;Yy4Z(R$K>yO r2BQDZ*X#݉ĈH #,jO}k8|Br'H.^)h _˥ٸ뫿Aܑks|)e&Hnr-^UDXBrCrkh$wy@kK ?h9vzr0 _Ǟ_ >TBP5VCq"&mnA@r-m,YvȘ}џ9jT~EɧdOxP4"і ǜ.\G캻c|ۯkՏrI0[uN)!cIO>{⢱Ac׬6X9M#{֟X}RbGϷ-EeA(Me lar=15Ƀ,#B}_6Ym>9 [ٴGWf~7!c+͋a٦^E>{"E'zޢ dQ]tH>@}b!B99 ~ztLSUo^gx'mK~#NpݏѸ3Tg[,5t\+EBwf-A3[cB35ދCX뵨HEPne.Dl^+ξGAN]Wa~UĕyG&_cZYfJ_V,/QYs//=;v KP"aR~9CQ֝CLc8.ݕMQ~aA)[3z dA :XЃmRҽ*sr׀$HX"72w 1炪Li3 w?¸6az7uMVL=F5$x +B/c Aנ-fFL6c\RmQ2x~=UõyH>GJf|vBx GJQ%H9X=7S,総_d';rvTK̡4i%̌k>Q>Jod0B~݋EH!CYԕ05J>pj>,2:Ec"fa^A{uqz?vaݣPbg 6ԁ߬VO\rs{~pnW);:lgnnp$)#헑wd+ȖMV2|PJ %$ZF~_q>9}~Xص[B͖X^ę󰲻Ňb[Z |UX6Xyʠ,]$km|'hk<[pU8_Vn|C`Uo~*M]W^Xi,E05cj?] %]c1rS}L%S^fRxTKQVb,ϊQ`3.A-9 5p`^I`zzMXㅴm=Xťo~c&?*-gCv2}][O6~@k%')D <bɄIMc<-ʓv X%X곩汯;1mݰVkG`vkjLm-حIn اX>g' Rj)QM) ej Xܑ@\MVM,!p)Z3QOb?Ӛs~hg}w:ԝT>ݜ`]W&-e18WॎTX!,ۈ)Yn9͇v=3`%oΩ3bWvӮ7 ~Xc:|MK$!jwvSh vj=f],J׳8,8x\%4,]v+,%XsP~<t|k`(|W/3~M]ȴbX c_,}X輑smL9 Ƽy4ۇ nRRV<1 .ళ,UY-^v@e,I ?U,),`edURVt3^ӑ߼]OpW2?YۅW*8)!:=Rhg:~ҮQV@F],?ZMP$2X8yEsd[cQz-5?'ߺ[9o>y+klKVHX뺍r {އ}_fX~tE6 U]XO}Ex^R |'q^C}%u1k[$aCIse3<-hҐs%s]gMPi,R=wa-;B>(Nx?n-Nu_ q|+P_1':%p}HEoH+896סf0~ E6⒗ńg_ .KggWr)|kĉ?g㊌Yp?vo[K*^uoFy>ZW}}b656pL kh/N|x4X#KEtb.k[>OV=yMTkI P] qC^=wt/،ڇE %tmcw?&؝ n9Ny?I$VIsWe"/ޤ1G 7~YIH">ͱ4__ V&]v6prCIr`]Bk &Sa#ܾ 4]nI38gO4E"If`OS"굊^kF tx' פe44*OF~˯xl0e)\Tcӄ ~_KgV. P8"쎍ȥҴ|A?e6Av`﫰 Yu^WA;y'4-ުSQPڡJ`hǺ =FV~eU]U\7ϗM攇E[G/b=^5Hzt=*Njo>~.G0\%{.G7ߤidkZ-7+_9 {~oK(⹊oz3fV<ËB?>5F%xQTYqoo~5VPM&9۬ ۬%jMvZߢH.6<#{:pT^.fuXMH,I6TezW6db~Ӗ/cƛs/L7+(y20Pf`aɧ0.sѴ5/cqOڟN 'NOzR+ 2Kύ_K+ƍǨq72^Oy*C ixEٓg;CJuR)!rK/x _]x~tXj)vyR38Eڨ^ƻ`G37ԑuڼߌ)"zX[_ݫ:rX=b64^_ou>#~ r;OrVkc9JGadkc/LnbtݜvXeJC.>/5%U$A}oZT*mؙ~)7ҿ[(r-+wӎ͑6$wx5B zG!o-!22Jy0kI_`Ne {%旭w}c&J}0QSQJcz< pRnr\`HqJG`륧7N]q)y 4 Xu{duwuFA̸HEI|&@{pcwwM%|)/Hlg9,z?`mw|I~}-Y0=خR@&y~: EGN$7q |/.xF0y;] M0y3W;w}_m:4n)[WćSA2P 4O0Qn!`*l:҃ \Po Xzp~G5["%~W{@۹GrGKǁdGz^'Yܼ-%3@o(#AaAUB$(xr0vjv TULH)SU Rl>KWIwhLI\`4~80sg;ӇyACj?w8?A[[Р;;;ÉA*`W"nayLh].\(fyL?t/X$tӂ:UB{w^ Ews9Y1d`>G-ƂD~UUMh\EFtr n'UJ|@cNh% 489l4A ~Wc5zФ4 eS{yHn_! Z /+k׏S- .Wܟ1f*N{!f#a g: PYGשO$LC~gv[.0|񙥸w ߾n"uG~C/KjZrU(lebS)'ރҥ{eI |Z|OC.~doGFs`IhhO˶]V ڹT"fL`01Yf^clo:"e㺇\pbw%HyWH\7Y 6/BZh9U&if5¢FN_gw 78-UP^/`k׃ NL(pFF6=q:3p^XFv 4l<4xï^w{̣xV zv.{ˠJzQl~bAȨ߉S$- \:cB@Iɺ ()3gAC#n0nk%ŀ.t[o! r㨸xSPgE1 Ew ynj Mz )g{؎J.$vwcTdj1|̕^P(xh9 rAu4|Фjj+:%A I)Q~k GP;dRk˂ۖ1`Z /4 PDqH<HڞtR ҆E-KM{oiSn@ե(E;q|.OƢ@>*e->;,kԖܯ =8$#p; [RAM$Pod_RFUq83h>4-ZvAK@EO_K492O:jT͹r`XGu^VTpkު? "`}|r)%j^ϑ{UP[%Z#5]3KF pXpD~$ ۫Ak\ˠzx#gi9,LL3|R  Z`ty0J\wk='Gho)ߏ@Mf~RH? eܺ\+K0ĿHKDh'nFՖ3@"F' aV1S0p: ] p/Z& s`Fi5 dkyj(NdS&Lٗsq)V4TxL疳6sK|?]y|?tM?eu4 F0"9u<+,چz'&x/XGh> A 0zli'KTi>j]kD5&aM8)_9ځ癹'Ekř]ТuĦA+7/w̍E(G􎛉SgimTؘ0j{HQ!]:^ w)>`@XN-0yy`1~D' <Wҁjh&ARz+$M9/q+޾FWA̵䓂`)(?ꈁAA{l OjH])B;wD|P> b]6)L8{zͣi觾K  ֮5$ҡ.p62R{g_Xcs !SNh)KQnK78RJk)|,^rEzI qXKPd%κLhoG>78{ +0ulz@T|j[Mv΂w%<+8LLkܼ&K{X]-AyQO꣋Qd7@ŵ PcߕA| ؜;vc1﷪5Uˑj@[7op4Edt]mlHց*4?EFm0#SMHbzn^߫U!&P%zL}ι`~ʁs0ge\g/q-? exJ[2LjPC>P\: ͝ҠcDS0-fr癯Ҟ0"6ؼCuSPG+YL/mVg~`lȹ?>ˡgP1|h 2Rڴt@i/8Yf2nj>3KD롋}a>YLט :Gw&Κwc~0M)ZvCBs"hp,H*wkf :7^#zlTT78\3ѿHxhF=ָ#\\͏Q00~UbTwy8G#˚G?ҀS]*&8&LOK7I~@ꎷo!P-|xpnL^uZ> ~ Ѩ2lqO#YVBuW}1`2ofѻlkR:T`I@g3?ޯJX\`7d/bK^6+ϔJO AGLJk|Χ&(P$7 UU?"AsJTwd(A崃O/40 %!ꏟ1 Ni{Obw)'hQj/kpk&B_=Z-?S]SYvM0|ySO(S7 r 4h7T0a09&3FryJ#As`ud6h*|ȥpS\k2%dm}*[L{>tIm,@QߌףD~qUʗ1@q?A]kL'Z}AEku0U A\ɠ3Gt6itE$ \8p( t?:YwzV~u %FŘzڂt XM )MvA=$It1S>0`N0Lq򳀮\R &h, ]`U0;qrX$XD̃鰠*#WPI .(]~jm)Y%)y?&y{dAw7[ /4?ƫ@>HQ>G#t9K%#ow-|c+ABֶ3C hgĝ  MPF4 cy6vʹ%;h:> s^Mo `U"g[F*Qdːd?O]qO`3 G`xmgSW?o{c?Wʘ4oh .; "^Ŷ*FWߍ< LߡQ9 7pzwglFsc ``z'Yj %+:dPw ?S"=SKu2Vem`Jw3*$mu*Ztɳy灷5ӓr z2ȌٜgU= 7~nP%18KT#{d\9=0 f=kRZۜ  sѮ/&MopɹLhbj)ɉPuTMl`P hXXsF_ *\62 p`{h-U+0{a8K pl#4µS>N|i^}AC:3m]*db3!:XE0ZȭEh(I3[gf5YWL,L\韃lSR<Ӊii3-WƖ!4J԰Qﯽ) v.Wׁ!om+c.:K~Z 1fP] @1x#0r̨O_Brjv6="7v2@^:fwK%'+@3iN:C ]U'%6@:s?(3|T&&ojmT88Aɽns¾N/Rq{i/zp(a ipH-uO`wHZ~?D SkGrND 鼼ʢ$ʦ)tS:^ QotP6+]P6}|>lVuU4Ch&xupq+]B+#3gwaCwUP΁@W"x۫C򚜽/>`!{@s(ip"J.*gFܢʨx};V_OsʧĜh m1x!}o?!D%p4z=6G!KS".?Mg ~A ޶f#*slm1E~PFy"tgt*2!@t(% f'{(?<:°5axHª#!\NSv*u!z r;9iB?Oۦ<(o[<^慐ۋfֿhشs |W}dzZ̐bt  2{=FyJhO;+-]Fٳ7y <0|,E*Uo`y&#e52O`nӴ#Q ^:/Ͻ/gJA~+^꺳h?/}~$gAN?BzOfJKHBOмݝF$#4{KﲂO[ǣ~Z)e=ovp4<7KpcA8t4 G}CNQ:F{5A=8_D% .3\EupijAr/eG\)<}q{n3~a$8ɺ<ټ@(Qh,ZUiW끨L$DVQco8t莥 Kfsp!Zni.>hD\>0 S6/|\ #mU~q}` .cEGy<{}'}>p~J:~[]<̀99@ruq?k˯G[ .aq./$G<" ZlF\]o 0W 5w55pzWqEBP0и :t3nH]! *0GDցJ#g>F p9t=6:[\AL'nceK!^R q|MvWmP^38הœM"BNęϬ*mֽǾ26F nL*N ܒ> dp}VbqP0,TkA6(d;k6o_4/lOk]= Cz*QVshۮmk4m"vm.dzzp?)͝ uAfTF/(s=+Z; M8}L5 YF9euz^Z b [ @C3'Z'zr0=%\[xrҼ fqĚT`(ܫy#ttW-R1p i:4n6Z󟖂x%3jJӿWH2^ r=a>,K``P Cͯl@øΆK aplAM0 "d(,m7'۪pT%ЯnGk#o2#tz'6}׾}FۛxxS: 1{}{ s^IJ߀M1mLӘ06Sib<+hb,^k /mFZu9䩯x#=.D0)h.{am4OUi=&J@l]#xw^N﹍0vr qa.#(a(>-'J"j>aFHeS̽z@>WA>|:O{"dIk ;|v[Ȁٳ6F?(^374kjS v3.dc,w=l30&Ýw`2"hJ;;zg]6o͂w|DfSV3S<5 Aj/b ? RvVld)`JgwJX1{.~5" _4cA®) HgϙE=@ =Yf*q̲y*!r_/!E}3!4:T5Mn&H F}dIZ4 )5?;Ce6sXe5w |aSJ@v?ׄ/}!B$H)B8ꍄpVJ>k/՛A 5Voڷj<7mu2^ԃrjjo]fFgGq8թsȟ!8XnOSDHJǷ#7|*{[#aöBqF_N(mНF`ARP@9uk~~?PTvaqr~. KOHY y_m!(LzQGOG/, _]A*ҫlRB2-X+Xh)_]<5>BeE'G ɵSI^?$HR#RzIj4* i*6t 287'HBqSUOG?kҷK8v]~n,.i@y?yys"?ǷN#$kKpTq 8&T4 BMi:Ğ޻yat瑮 bO%; K&u?B=A ϱޏ&GhU=owozU@P;FȓVOȓ&vk= ʧW&%+k nR˥5F? mMBi ! %H-YvN>+4J*%>,f#^ t١:} 4&8%EopV'6гL+8GT@v m%FmqYB-鏉J;!_Y.8O ȱ< .a>傺V瞲^)2ȍ 9F;Sr@MÔD] -wy,MzCd|YW5I~w ^f nao>< ZvzVtUgToZL°X:x~z]s{4Z5r<<4K&/7>4pa*_e;V"zerlK_JMu^g 4oPw-”^a \}]m׵4d#9%1.W36WrV|5B3 LKJ~׿ aڳ# p0G%  S|]WѾlY[村iR/YH Cakuc2)dMA=`Fx՞_tK@ҙRI;Ԟ3!qHvb2XC ٛfB3xQ+d}s=8 Q;b]k0uxl5?=dQwKcĿȞ!7Z 1vR~%k;ܕj.;5g$YEppVAby5*F|HoԷܼSU|w!J8>;"ƜɃ{I@yzK+9}Fҡ(xjY wҊ#xoJopbMĦ5|sގOs!r:kO'fe>( AztO P{+ Lx- B,Arތ/(/lS׸*BʇAp.+Zv@ .0 AGVbN7 p:Ş >—fm|nQG|f&,Ȯn&#be2%gdE%oœ9mBy!pŏN"oʏܣgsqG9NuN!wV}ϊVz(.aRCP6fWZ-58Mww$Br']Ap$B|qHn89Gf0 EvBỎtoPX(&5FphX5b V\ Xx#yf>ȫաyMj${ɇJ{d-"~?ɢ!jOZZf"$,s~ܻmcEKB/ҿ!WKDQ-_#3/ѿSԁW~ }xzKT&>Fuvi[ ,ӌwaw, ’?ޫ[88+ߝ >#$Q O\OtJIqx3( B+iA6MTNruקD\ B yj&x#!O9:u)#LESLxԭN%a}NC! ۘ %?8'"q{g  .ք= |jA@7aӝ@XS̮$U ك i*Uf'C5#0c VL&cg ;CGݩ+8abtqlD35 fhvF5K8#k;Oz&Ҧx|4'7aNDlלŽ+K ҄=M{0an '{)5gnp/(6?Xي {|sׄcd핒+D^YB\7ۍ^gm9QiGXS˽6GXjO )!]R &ؙ^Ί汣]~ːtksž~wa&ȷg&pq+ф;K0wӳ:LO}+ʎ}#wGG;Ym‘7v > yOұ4]0IC&<AIASWxpc%lFFΔUjkC/cNZ0|cZLDL+"O$|*y@l7d8="<>DB~Ҫ%<ζ{!~ٔXygPЉ<ꯣZ0'n ,v>^>ZB>% h1c}h_w?jӗz!иo(X4;/>7)W6K֥zLҁ7 QxJ(TPbK.O%hXRI(g$LJt^IHVjxg&$2JfFZ-ZQJMc7D i05$$>z9y~9PŢ ݠ\H$-캊_šEΚوy! }5Oes"\i,Vi]~ W UG|`X:B!"QN4kKEEg4';kȱ~j^m~%6mht;KιN0fs):!p=fq E7` X@p I:k@MzfOXެ9rC#aMIS{3Á!o\R^ 8^wNG)Bk ;<ie;crjP uF4ˆ- cZ`==Yp"w^m׸V[1nI1),ᗚA< JL3qLwa.PA}6ۙN@|Y4psHN-iW% $o[%6>\*nn9/DJqEP&S4lMe~*/')#{)?>^538_TdA8?}h3a"ڗ9O1FgbfN!}޲;˜;% p+V[YHnVs] I@6P|onsnB^f_{tH{z@ʴqpLB늶VH[~LA8lRc)H{)Qߦ !V4Q=^/|= q}֌уCsA*8 Ʌ5m㑇 , *w}*v#lGѫ?^!B@<%Y/;!oi2hvaaV?9O4GV|08k̩sc΃[3F~|^X5BӱkDҎHj%+u0؇991wmHcfwq>bhy4 Y8NU8ʃ"Z|rY-|rdFW~I#%R_$j'h{u<_c6OhQ?sR[Ʃroϣ %?; Y^E _"7o lamĩt[`u;4om\XIsgd}(QTo4r{6寅lS3q^QձϮu\=Q}?,Cfg($qк5[#<?/(Ł,n}9@PU&J&V|vt&x,T /UA@Matrix/inst/external/jgl009.mtx0000644000175100001440000000040014037532666016100 0ustar hornikusers%%MatrixMarket matrix coordinate pattern general 9 9 50 1 1 2 1 4 1 5 1 6 1 7 1 8 1 9 1 2 2 3 2 8 2 9 2 2 3 3 3 4 3 5 3 6 3 7 3 8 3 9 3 4 4 5 4 6 4 7 4 8 4 9 4 4 5 5 5 6 5 7 5 8 5 9 5 4 6 5 6 6 6 7 6 8 6 9 6 1 7 2 7 3 7 8 7 9 7 8 8 9 8 1 9 2 9 3 9 8 9 9 9 Matrix/inst/external/symA.rda0000644000175100001440000000153712215114135015735 0ustar hornikusersmTiHTa}3c˨9-:iP RI%{n)ea4樥6e9DDK4HRAd?ȐH2"Z{{̢䠢 EQ̊bR>,LbqQ1 QS ֢gB|ϜalW_sP Ն ͕s"µo~ >Q9Y۪t˜vEj%f/m_LEH2zp,XM΍3p\΋o <4ǰX Q(lRm.l"a&udVղ<QY9lE݄E;H; tLHԶ$ j'3DTۘ?<|7ID-՟ꞟxY=)+b/ <v>B-n"u YO&?0_}?.7 Բ6HO3𦾢} Ro=50s#ÚMOD?[iǹQ~ ov'źQ?eƼCg-^xL hw;ꎡ18xW:h0`2x*PM~x1zzT_J{u&&huc/WSPp]ѬӄnȀ:z}'r3 G<7o?!0k{r}ں{Nr}G>G{OУ^4uI~[ A:~ù=E>ו L/sp_dfWM꿗@ 8,ko~=j"i77f9Z\βjg~P/Q<vMatrix/inst/external/lund_a.rsa0000644000175100001440000007024410275502035016312 0ustar hornikusers1SYMMETRIC MATRIX A OF LUND EIGENVALUE PROBLEM, MAY 1974 LUND A 352 10 82 260 0 RSA 147 147 1298 0 (16I5) (16I5) (5E16.8) 1 7 15 23 31 39 47 53 58 68 77 85 97 108 118 130 141 151 163 174 184 196 207 217 228 238 247 254 260 265 275 284 292 304 315 325 337 348 358 370 381 391 403 414 424 435 445 454 461 467 472 482 491 499 510 521 531 543 554 564 576 587 597 609 620 630 641 651 660 667 673 678 688 697 705 717 728 738 750 761 771 783 794 804 815 826 836 847 857 866 873 879 884 894 903 911 923 934 944 956 967 977 989 1000 1010 1022 1033 1043 1053 1063 1072 1079 1085 1090 1099 1107 1114 1124 1133 1141 1151 1160 1168 1178 1187 1195 1205 1214 1222 1231 1239 1246 1251 1255 1258 1262 1265 1269 1272 1276 1279 1283 1286 1290 1293 1296 1298 1299 1 2 8 9 10 11 2 3 9 10 11 12 13 14 3 4 12 13 14 15 16 17 4 5 15 16 17 18 19 20 5 6 18 19 20 21 22 23 6 7 21 22 23 24 25 26 7 24 25 26 27 28 8 9 10 11 29 9 10 11 12 13 14 29 30 31 32 10 11 12 13 14 29 30 31 32 11 12 13 14 29 30 31 32 12 13 14 15 16 17 30 31 32 33 34 35 13 14 15 16 17 30 31 32 33 34 35 14 15 16 17 30 31 32 33 34 35 15 16 17 18 19 20 33 34 35 36 37 38 16 17 18 19 20 33 34 35 36 37 38 17 18 19 20 33 34 35 36 37 38 18 19 20 21 22 23 36 37 38 39 40 41 19 20 21 22 23 36 37 38 39 40 41 20 21 22 23 36 37 38 39 40 41 21 22 23 24 25 26 39 40 41 42 43 44 22 23 24 25 26 39 40 41 42 43 44 23 24 25 26 39 40 41 42 43 44 24 25 26 27 28 42 43 44 45 46 47 25 26 27 28 42 43 44 45 46 47 26 27 28 42 43 44 45 46 47 27 28 45 46 47 48 49 28 45 46 47 48 49 29 30 31 32 50 30 31 32 33 34 35 50 51 52 53 31 32 33 34 35 50 51 52 53 32 33 34 35 50 51 52 53 33 34 35 36 37 38 51 52 53 54 55 56 34 35 36 37 38 51 52 53 54 55 56 35 36 37 38 51 52 53 54 55 56 36 37 38 39 40 41 54 55 56 57 58 59 37 38 39 40 41 54 55 56 57 58 59 38 39 40 41 54 55 56 57 58 59 39 40 41 42 43 44 57 58 59 60 61 62 40 41 42 43 44 57 58 59 60 61 62 41 42 43 44 57 58 59 60 61 62 42 43 44 45 46 47 60 61 62 63 64 65 43 44 45 46 47 60 61 62 63 64 65 44 45 46 47 60 61 62 63 64 65 45 46 47 48 49 63 64 65 66 67 68 46 47 48 49 63 64 65 66 67 68 47 48 49 63 64 65 66 67 68 48 49 66 67 68 69 70 49 66 67 68 69 70 50 51 52 53 71 51 52 53 54 55 56 71 72 73 74 52 53 54 55 56 71 72 73 74 53 54 55 56 71 72 73 74 54 55 56 57 58 59 73 74 75 76 77 55 56 57 58 59 72 73 74 75 76 77 56 57 58 59 72 73 74 75 76 77 57 58 59 60 61 62 75 76 77 78 79 80 58 59 60 61 62 75 76 77 78 79 80 59 60 61 62 75 76 77 78 79 80 60 61 62 63 64 65 78 79 80 81 82 83 61 62 63 64 65 78 79 80 81 82 83 62 63 64 65 78 79 80 81 82 83 63 64 65 66 67 68 81 82 83 84 85 86 64 65 66 67 68 81 82 83 84 85 86 65 66 67 68 81 82 83 84 85 86 66 67 68 69 70 84 85 86 87 88 89 67 68 69 70 84 85 86 87 88 89 68 69 70 84 85 86 87 88 89 69 70 87 88 89 90 91 70 87 88 89 90 91 71 72 73 74 92 72 73 74 75 76 77 92 93 94 95 73 74 75 76 77 92 93 94 95 74 75 76 77 92 93 94 95 75 76 77 78 79 80 93 94 95 96 97 98 76 77 78 79 80 93 94 95 96 97 98 77 78 79 80 93 94 95 96 97 98 78 79 80 81 82 83 96 97 98 99 100 101 79 80 81 82 83 96 97 98 99 100 101 80 81 82 83 96 97 98 99 100 101 81 82 83 84 85 86 99 100 101 102 103 104 82 83 84 85 86 99 100 101 102 103 104 83 84 85 86 99 100 101 102 103 104 84 85 86 87 88 89 103 104 105 106 107 85 86 87 88 89 102 103 104 105 106 107 86 87 88 89 102 103 104 105 106 107 87 88 89 90 91 105 106 107 108 109 110 88 89 90 91 105 106 107 108 109 110 89 90 91 105 106 107 108 109 110 90 91 108 109 110 111 112 91 108 109 110 111 112 92 93 94 95 113 93 94 95 96 97 98 113 114 115 116 94 95 96 97 98 113 114 115 116 95 96 97 98 113 114 115 116 96 97 98 99 100 101 114 115 116 117 118 119 97 98 99 100 101 114 115 116 117 118 119 98 99 100 101 114 115 116 117 118 119 99 100 101 102 103 104 117 118 119 120 121 122 100 101 102 103 104 117 118 119 120 121 122 101 102 103 104 117 118 119 120 121 122 102 103 104 105 106 107 120 121 122 123 124 125 103 104 105 106 107 120 121 122 123 124 125 104 105 106 107 120 121 122 123 124 125 105 106 107 108 109 110 123 124 125 126 127 128 106 107 108 109 110 123 124 125 126 127 128 107 108 109 110 123 124 125 126 127 128 108 109 110 111 112 127 128 129 130 131 109 110 111 112 126 127 128 129 130 131 110 111 112 126 127 128 129 130 131 111 112 129 130 131 132 133 112 129 130 131 132 133 113 114 115 116 134 114 115 116 117 118 119 134 135 136 115 116 117 118 119 134 135 136 116 117 118 119 134 135 136 117 118 119 120 121 122 135 136 137 138 118 119 120 121 122 135 136 137 138 119 120 121 122 135 136 137 138 120 121 122 123 124 125 137 138 139 140 121 122 123 124 125 137 138 139 140 122 123 124 125 137 138 139 140 123 124 125 126 127 128 139 140 141 142 124 125 126 127 128 139 140 141 142 125 126 127 128 139 140 141 142 126 127 128 129 130 131 141 142 143 144 127 128 129 130 131 141 142 143 144 128 129 130 131 141 142 143 144 129 130 131 132 133 143 144 145 146 130 131 132 133 143 144 145 146 131 132 133 143 144 145 146 132 133 145 146 147 133 145 146 147 134 135 136 135 136 137 138 136 137 138 137 138 139 140 138 139 140 139 140 141 142 140 141 142 141 142 143 144 142 143 144 143 144 145 146 144 145 146 145 146 147 146 147 147 0.75000000E+08 0.96153881E+06 -0.12179486E+08 -0.26175210E+07 0.28846144E+08 0.57692300E+07 0.75000000E+08 0.96153869E+06 -0.74786312E+05 0.96153840E+07 -0.12179486E+08 -0.26175210E+07 0.28846144E+08 0.57692300E+07 0.75000000E+08 0.96153844E+06 -0.74786375E+05 0.96153840E+07 -0.12179486E+08 -0.26175210E+07 0.28846144E+08 0.57692310E+07 0.75000000E+08 0.96153869E+06 -0.74786312E+05 0.96153840E+07 -0.12179487E+08 -0.26175210E+07 0.28846144E+08 0.57692300E+07 0.75000000E+08 0.96153894E+06 -0.74786375E+05 0.96153840E+07 -0.12179486E+08 -0.26175210E+07 0.28846160E+08 0.57692310E+07 0.75000000E+08 0.96153894E+06 -0.74786312E+05 0.96153850E+07 -0.12179488E+08 -0.26175220E+07 0.28846160E+08 0.57692310E+07 0.44230768E+08 -0.74786312E+05 0.96153850E+07 -0.12179488E+08 -0.15405980E+07 0.14423078E+08 0.75000000E+08 0.26175210E+07 0.57692300E+07 0.28846144E+08 0.96153831E+06 0.50256406E+06 0.78125000E-02 0.78125000E-02 -0.12564100E+06 0.74786312E+05 -0.26175210E+07 0.74786312E+05 -0.12564100E+06 0.26175210E+07 -0.74786312E+05 0.14999998E+09 0.12820510E+07 -0.74786312E+05 0.19230770E+07 0.57692310E+07 -0.12179486E+08 -0.26175210E+07 0.28846144E+08 0.57692300E+07 0.14999998E+09 0.26175210E+07 0.57692300E+07 0.28846144E+08 0.96153840E+07 0.74786312E+05 0.57692300E+07 0.19230770E+07 0.50256406E+06 -0.10937500E+00 0.54687500E-01 -0.12564100E+06 0.74786312E+05 -0.26175210E+07 -0.24414062E-03 0.74786375E+05 0.74786312E+05 -0.12564100E+06 0.26175210E+07 -0.74786250E+05 0.14999998E+09 0.12820520E+07 -0.74786312E+05 0.19230770E+07 0.57692300E+07 -0.74786312E+05 0.96153840E+07 -0.12179487E+08 -0.26175210E+07 0.28846144E+08 0.57692300E+07 0.14999998E+09 0.26175210E+07 0.57692300E+07 0.28846144E+08 -0.74786375E+05 -0.12179486E+08 0.96153840E+07 0.74786312E+05 0.57692310E+07 0.19230770E+07 0.50256406E+06 0.14843750E+00 -0.11718750E+00 -0.12564100E+06 0.74786312E+05 -0.26175210E+07 -0.36621094E-03 0.74786375E+05 0.74786250E+05 -0.12564100E+06 0.26175210E+07 -0.74786312E+05 0.14999998E+09 0.12820510E+07 -0.74786312E+05 0.19230770E+07 0.57692310E+07 -0.74786250E+05 0.96153840E+07 -0.12179488E+08 -0.26175210E+07 0.28846160E+08 0.57692310E+07 0.14999998E+09 0.26175210E+07 0.57692310E+07 0.28846144E+08 -0.74786375E+05 -0.12179485E+08 0.96153830E+07 0.74786375E+05 0.57692300E+07 0.19230770E+07 0.50256406E+06 -0.13281250E+00 0.17187500E+00 -0.12564100E+06 0.74786312E+05 -0.26175210E+07 0.48828125E-03 0.74786312E+05 0.74786312E+05 -0.12564100E+06 0.26175210E+07 -0.74786250E+05 0.14999998E+09 0.12820510E+07 -0.74786375E+05 0.19230770E+07 0.57692300E+07 -0.74786250E+05 0.96153840E+07 -0.12179488E+08 -0.26175210E+07 0.28846144E+08 0.57692300E+07 0.14999998E+09 0.26175210E+07 0.57692300E+07 0.28846144E+08 -0.74786375E+05 -0.12179487E+08 0.96153850E+07 0.74786375E+05 0.57692310E+07 0.19230760E+07 0.50256412E+06 0.32031250E+00 -0.68750000E+00 -0.12564106E+06 0.74786375E+05 -0.26175220E+07 -0.12207031E-03 0.74786437E+05 0.74786187E+05 -0.12564106E+06 0.26175220E+07 -0.74786375E+05 0.15000002E+09 0.12820520E+07 -0.74786312E+05 0.19230770E+07 0.57692320E+07 -0.74786250E+05 0.96153840E+07 -0.12179490E+08 -0.26175220E+07 0.28846160E+08 0.57692320E+07 0.15000000E+09 0.26175220E+07 0.57692320E+07 0.28846160E+08 -0.74786437E+05 -0.12179483E+08 0.96153830E+07 0.74786312E+05 0.57692320E+07 0.19230770E+07 0.50256419E+06 0.41406250E+00 0.85937500E-01 -0.12564106E+06 0.74786375E+05 0.36621094E-03 0.74786312E+05 0.74786375E+05 -0.12564106E+06 0.26175220E+07 -0.74786375E+05 0.15000002E+09 0.12820510E+07 -0.74786312E+05 0.19230770E+07 -0.74786312E+05 0.96153860E+07 -0.12179491E+08 -0.26175220E+07 0.28846160E+08 0.57692320E+07 0.15000002E+09 0.26175220E+07 0.57692320E+07 -0.74786375E+05 -0.12179491E+08 0.96153880E+07 0.74786375E+05 0.57692320E+07 0.19230770E+07 0.25128206E+06 0.46367550E+06 0.36621094E-03 0.74786312E+05 0.74786375E+05 -0.62820531E+05 0.10769230E+07 0.75000016E+08 -0.74786312E+05 0.96153860E+07 -0.12179491E+08 -0.15405990E+07 0.14423080E+08 0.75000000E+08 0.26175210E+07 0.57692300E+07 0.28846144E+08 0.96153831E+06 0.50256406E+06 -0.10937500E+00 0.54687500E-01 -0.12564100E+06 0.74786250E+05 -0.26175210E+07 0.74786312E+05 -0.12564100E+06 0.26175210E+07 -0.74786312E+05 0.14999998E+09 0.12820520E+07 -0.74786312E+05 0.19230770E+07 0.57692310E+07 -0.12179486E+08 -0.26175210E+07 0.28846144E+08 0.57692300E+07 0.14999998E+09 0.26175210E+07 0.57692300E+07 0.28846144E+08 0.96153840E+07 0.74786312E+05 0.57692300E+07 0.19230770E+07 0.50256412E+06 0.24218750E+00 -0.38281250E+00 -0.12564106E+06 0.74786375E+05 -0.26175220E+07 -0.48828125E-03 0.74786312E+05 0.74786312E+05 -0.12564100E+06 0.26175210E+07 -0.74786375E+05 0.14999998E+09 0.12820510E+07 -0.74786312E+05 0.19230770E+07 0.57692310E+07 -0.74786250E+05 0.96153820E+07 -0.12179487E+08 -0.26175210E+07 0.28846160E+08 0.57692300E+07 0.14999998E+09 0.26175220E+07 0.57692310E+07 0.28846160E+08 -0.74786375E+05 -0.12179485E+08 0.96153840E+07 0.74786312E+05 0.57692310E+07 0.19230770E+07 0.50256412E+06 -0.23437500E-01 0.34375000E+00 -0.12564100E+06 0.74786250E+05 -0.26175210E+07 0.24414062E-03 0.74786312E+05 0.74786312E+05 -0.12564100E+06 0.26175210E+07 -0.74786312E+05 0.15000000E+09 0.12820520E+07 -0.74786312E+05 0.19230770E+07 0.57692310E+07 -0.74786312E+05 0.96153850E+07 -0.12179488E+08 -0.26175210E+07 0.28846144E+08 0.57692300E+07 0.15000000E+09 0.26175210E+07 0.57692310E+07 0.28846144E+08 -0.74786312E+05 -0.12179488E+08 0.96153850E+07 0.74786375E+05 0.57692300E+07 0.19230770E+07 0.50256406E+06 0.19531250E+00 -0.27343750E+00 -0.12564100E+06 0.74786312E+05 -0.26175210E+07 0.48828125E-03 0.74786312E+05 0.74786250E+05 -0.12564100E+06 0.26175210E+07 -0.74786312E+05 0.14999998E+09 0.12820510E+07 -0.74786375E+05 0.19230770E+07 0.57692310E+07 -0.74786250E+05 0.96153820E+07 -0.12179488E+08 -0.26175210E+07 0.28846144E+08 0.57692300E+07 0.14999998E+09 0.26175210E+07 0.57692300E+07 0.28846160E+08 -0.74786375E+05 -0.12179485E+08 0.96153850E+07 0.74786375E+05 0.57692310E+07 0.19230770E+07 0.50256412E+06 -0.55468750E+00 -0.32812500E+00 -0.12564106E+06 0.74786250E+05 -0.26175220E+07 -0.24414062E-03 0.74786312E+05 0.74786312E+05 -0.12564100E+06 0.26175210E+07 -0.74786375E+05 0.15000002E+09 0.12820510E+07 -0.74786375E+05 0.19230770E+07 0.57692320E+07 -0.74786312E+05 0.96153830E+07 -0.12179486E+08 -0.26175210E+07 0.28846144E+08 0.57692310E+07 0.15000002E+09 0.26175220E+07 0.57692320E+07 0.28846160E+08 -0.74786312E+05 -0.12179486E+08 0.96153830E+07 0.74786312E+05 0.57692300E+07 0.19230760E+07 0.50256419E+06 0.53906250E+00 0.15625000E-01 -0.12564106E+06 0.74786250E+05 -0.73242187E-03 0.74786562E+05 0.74786125E+05 -0.12564106E+06 0.26175220E+07 -0.74786250E+05 0.15000005E+09 0.12820520E+07 -0.74786375E+05 0.19230770E+07 -0.74786125E+05 0.96153870E+07 -0.12179498E+08 -0.26175230E+07 0.28846160E+08 0.57692320E+07 0.15000002E+09 0.26175220E+07 0.57692320E+07 -0.74786625E+05 -0.12179486E+08 0.96153900E+07 0.74786500E+05 0.57692330E+07 0.19230770E+07 0.25128206E+06 0.46367500E+06 -0.61035156E-03 0.74786312E+05 0.74786375E+05 -0.62820516E+05 0.10769230E+07 0.75000000E+08 -0.74786312E+05 0.96153830E+07 -0.12179487E+08 -0.15405980E+07 0.14423077E+08 0.75000000E+08 0.26175210E+07 0.57692310E+07 0.28846144E+08 0.96153856E+06 0.50256406E+06 0.18750000E+00 0.23437500E-01 -0.12564100E+06 0.74786312E+05 -0.26175210E+07 0.74786312E+05 -0.12564100E+06 0.26175210E+07 -0.74786312E+05 0.14999998E+09 0.12820510E+07 -0.74786312E+05 0.19230770E+07 0.57692300E+07 -0.12179487E+08 -0.26175210E+07 0.28846160E+08 0.57692310E+07 0.14999998E+09 0.26175210E+07 0.57692310E+07 0.28846144E+08 0.96153830E+07 0.74786312E+05 0.57692310E+07 0.19230770E+07 0.50256406E+06 -0.24218750E+00 -0.62500000E-01 -0.12564100E+06 0.74786250E+05 -0.26175210E+07 0.74786375E+05 0.74786250E+05 -0.12564100E+06 0.26175210E+07 -0.74786250E+05 0.15000000E+09 0.12820510E+07 -0.74786437E+05 0.19230760E+07 0.57692290E+07 -0.74786312E+05 0.96153850E+07 -0.12179488E+08 -0.26175210E+07 0.28846144E+08 0.57692300E+07 0.14999998E+09 0.26175210E+07 0.57692300E+07 0.28846144E+08 -0.74786375E+05 -0.12179487E+08 0.96153840E+07 0.74786375E+05 0.57692310E+07 0.19230770E+07 0.50256412E+06 0.20312500E+00 -0.24218750E+00 -0.12564100E+06 0.74786312E+05 -0.26175210E+07 0.85449219E-03 0.74786375E+05 0.74786250E+05 -0.12564100E+06 0.26175210E+07 -0.74786312E+05 0.14999998E+09 0.12820510E+07 -0.74786312E+05 0.19230770E+07 0.57692310E+07 -0.74786250E+05 0.96153850E+07 -0.12179488E+08 -0.26175210E+07 0.28846160E+08 0.57692320E+07 0.15000000E+09 0.26175210E+07 0.57692320E+07 0.28846160E+08 -0.74786312E+05 -0.12179485E+08 0.96153820E+07 0.74786312E+05 0.57692310E+07 0.19230770E+07 0.50256412E+06 0.22656250E+00 0.25000000E+00 -0.12564100E+06 0.74786375E+05 -0.26175210E+07 0.24414062E-03 0.74786312E+05 0.74786312E+05 -0.12564100E+06 0.26175210E+07 -0.74786312E+05 0.15000000E+09 0.12820510E+07 -0.74786312E+05 0.19230770E+07 0.57692300E+07 -0.74786312E+05 0.96153850E+07 -0.12179489E+08 -0.26175210E+07 0.28846160E+08 0.57692310E+07 0.15000000E+09 0.26175210E+07 0.57692310E+07 0.28846144E+08 -0.74786312E+05 -0.12179489E+08 0.96153860E+07 0.74786312E+05 0.57692320E+07 0.19230770E+07 0.50256412E+06 0.18750000E+00 -0.82031250E+00 -0.12564106E+06 0.74786125E+05 -0.26175220E+07 0.36621094E-03 0.74786500E+05 0.74786187E+05 -0.12564100E+06 0.26175210E+07 -0.74786187E+05 0.15000002E+09 0.12820520E+07 -0.74786500E+05 0.19230780E+07 0.57692330E+07 -0.74786250E+05 0.96153880E+07 -0.12179493E+08 -0.26175220E+07 0.28846160E+08 0.57692310E+07 0.15000002E+09 0.26175220E+07 0.57692330E+07 0.28846160E+08 -0.74786437E+05 -0.12179487E+08 0.96153850E+07 0.74786437E+05 0.57692310E+07 0.19230770E+07 0.50256425E+06 -0.69531250E+00 -0.15625000E+00 -0.12564106E+06 0.74786437E+05 -0.85449219E-03 0.74786312E+05 0.74786312E+05 -0.12564106E+06 0.26175220E+07 -0.74786500E+05 0.15000003E+09 0.12820520E+07 -0.74786250E+05 0.19230770E+07 -0.74786312E+05 0.96153820E+07 -0.12179484E+08 -0.26175210E+07 0.28846160E+08 0.57692320E+07 0.15000003E+09 0.26175220E+07 0.57692330E+07 -0.74786312E+05 -0.12179484E+08 0.96153820E+07 0.74786187E+05 0.57692310E+07 0.19230770E+07 0.25128212E+06 0.46367594E+06 0.97656250E-03 0.74786375E+05 0.74786375E+05 -0.62820547E+05 0.10769240E+07 0.75000016E+08 -0.74786375E+05 0.96153890E+07 -0.12179494E+08 -0.15405990E+07 0.14423084E+08 0.75000000E+08 0.26175210E+07 0.57692300E+07 0.28846144E+08 0.96153831E+06 0.50256406E+06 -0.15625000E+00 0.70312500E-01 -0.12564100E+06 0.74786250E+05 -0.26175210E+07 0.74786312E+05 -0.12564100E+06 0.26175210E+07 -0.74786312E+05 0.14999998E+09 0.12820520E+07 -0.74786375E+05 0.19230770E+07 0.57692310E+07 -0.12179486E+08 -0.26175210E+07 0.28846144E+08 0.57692300E+07 0.14999998E+09 0.26175210E+07 0.57692300E+07 0.28846144E+08 0.96153840E+07 0.74786375E+05 0.57692300E+07 0.19230760E+07 0.50256406E+06 0.70312500E-01 -0.14843750E+00 -0.12564100E+06 0.74786312E+05 -0.26175210E+07 -0.85449219E-03 0.74786375E+05 0.74786250E+05 -0.12564100E+06 0.26175210E+07 -0.74786312E+05 0.14999998E+09 0.12820510E+07 -0.74786375E+05 0.19230770E+07 0.57692310E+07 -0.74786250E+05 0.96153820E+07 -0.12179487E+08 -0.26175210E+07 0.28846144E+08 0.57692300E+07 0.14999998E+09 0.26175210E+07 0.57692300E+07 0.28846144E+08 -0.74786375E+05 -0.12179484E+08 0.96153830E+07 0.74786312E+05 0.57692300E+07 0.19230770E+07 0.50256412E+06 -0.24218750E+00 -0.25000000E+00 -0.12564100E+06 0.74786312E+05 -0.26175210E+07 -0.24414062E-03 0.74786312E+05 0.74786312E+05 -0.12564100E+06 0.26175210E+07 -0.74786375E+05 0.15000000E+09 0.12820510E+07 -0.74786312E+05 0.19230770E+07 0.57692320E+07 -0.74786312E+05 0.96153830E+07 -0.12179486E+08 -0.26175210E+07 0.28846144E+08 0.57692310E+07 0.15000000E+09 0.26175210E+07 0.57692310E+07 0.28846160E+08 -0.74786312E+05 -0.12179486E+08 0.96153830E+07 0.74786312E+05 0.57692300E+07 0.19230760E+07 0.50256419E+06 0.59375000E+00 -0.60937500E+00 -0.12564106E+06 0.74786375E+05 -0.26175220E+07 -0.73242187E-03 0.74786437E+05 0.74786250E+05 -0.12564106E+06 0.26175220E+07 -0.74786312E+05 0.15000003E+09 0.12820520E+07 -0.74786375E+05 0.19230770E+07 0.57692330E+07 -0.74786187E+05 0.96153850E+07 -0.12179493E+08 -0.26175220E+07 0.28846160E+08 0.57692320E+07 0.15000003E+09 0.26175220E+07 0.57692320E+07 0.28846160E+08 -0.74786500E+05 -0.12179487E+08 0.96153880E+07 0.74786375E+05 0.57692330E+07 0.19230770E+07 0.50256412E+06 0.85937500E-01 0.15781250E+01 -0.12564100E+06 0.74786250E+05 -0.26175200E+07 0.74786312E+05 0.74786312E+05 -0.12564100E+06 0.26175210E+07 -0.74786187E+05 0.15000000E+09 0.12820520E+07 -0.74786312E+05 0.19230770E+07 0.57692300E+07 -0.74786375E+05 0.96153870E+07 -0.12179490E+08 -0.26175210E+07 0.28846144E+08 0.57692300E+07 0.15000000E+09 0.26175200E+07 0.57692290E+07 0.28846144E+08 -0.74786375E+05 -0.12179490E+08 0.96153870E+07 0.74786437E+05 0.57692300E+07 0.19230770E+07 0.50256400E+06 -0.12890625E+01 -0.11250000E+01 -0.12564100E+06 0.74786187E+05 -0.85449219E-03 0.74786250E+05 0.74786312E+05 -0.12564100E+06 0.26175200E+07 -0.74786312E+05 0.14999998E+09 0.12820510E+07 -0.74786437E+05 0.19230770E+07 -0.74786312E+05 0.96153800E+07 -0.12179482E+08 -0.26175200E+07 0.28846144E+08 0.57692280E+07 0.14999998E+09 0.26175220E+07 0.57692310E+07 -0.74786375E+05 -0.12179482E+08 0.96153820E+07 0.74786312E+05 0.57692280E+07 0.19230760E+07 0.25128206E+06 0.46367419E+06 -0.85449219E-03 0.74786250E+05 0.74786312E+05 -0.62820488E+05 0.10769230E+07 0.75000000E+08 -0.74786312E+05 0.96153800E+07 -0.12179482E+08 -0.15405980E+07 0.14423071E+08 0.75000000E+08 0.26175210E+07 0.57692310E+07 0.28846160E+08 0.96153850E+06 0.50256412E+06 0.70312500E+00 -0.13281250E+00 -0.12564106E+06 0.74786375E+05 -0.26175220E+07 0.74786312E+05 -0.12564106E+06 0.26175220E+07 -0.74786375E+05 0.15000000E+09 0.12820510E+07 -0.74786250E+05 0.19230770E+07 0.57692310E+07 -0.12179488E+08 -0.26175220E+07 0.28846160E+08 0.57692320E+07 0.15000000E+09 0.26175220E+07 0.57692320E+07 0.28846160E+08 0.96153840E+07 0.74786250E+05 0.57692320E+07 0.19230770E+07 0.50256412E+06 0.28906250E+00 0.39843750E+00 -0.12564100E+06 0.74786375E+05 -0.26175210E+07 0.24414062E-03 0.74786250E+05 0.74786375E+05 -0.12564100E+06 0.26175210E+07 -0.74786312E+05 0.15000000E+09 0.12820510E+07 -0.74786312E+05 0.19230770E+07 0.57692300E+07 -0.74786437E+05 0.96153870E+07 -0.12179488E+08 -0.26175210E+07 0.28846160E+08 0.57692310E+07 0.15000000E+09 0.26175210E+07 0.57692310E+07 0.28846144E+08 -0.74786250E+05 -0.12179491E+08 0.96153850E+07 0.74786312E+05 0.57692310E+07 0.19230770E+07 0.50256412E+06 0.25000000E+00 -0.27343750E+00 -0.12564100E+06 0.74786187E+05 -0.26175210E+07 0.36621094E-03 0.74786500E+05 0.74786187E+05 -0.12564100E+06 0.26175210E+07 -0.74786187E+05 0.15000000E+09 0.12820520E+07 -0.74786437E+05 0.19230780E+07 0.57692310E+07 -0.74786250E+05 0.96153880E+07 -0.12179493E+08 -0.26175220E+07 0.28846160E+08 0.57692310E+07 0.15000000E+09 0.26175220E+07 0.57692320E+07 0.28846160E+08 -0.74786437E+05 -0.12179487E+08 0.96153850E+07 0.74786437E+05 0.57692310E+07 0.19230770E+07 0.50256412E+06 -0.15234375E+01 -0.78125000E-01 -0.12564100E+06 0.74786250E+05 -0.26175210E+07 -0.85449219E-03 0.74786312E+05 0.74786312E+05 -0.12564100E+06 0.26175200E+07 -0.74786250E+05 0.15000000E+09 0.12820520E+07 -0.74786437E+05 0.19230770E+07 0.57692300E+07 -0.74786312E+05 0.96153820E+07 -0.12179484E+08 -0.26175200E+07 0.28846144E+08 0.57692280E+07 0.15000000E+09 0.26175210E+07 0.57692300E+07 0.28846144E+08 -0.74786312E+05 -0.12179484E+08 0.96153820E+07 0.74786312E+05 0.57692300E+07 0.19230760E+07 0.50256419E+06 0.94531250E+00 -0.10156250E+01 -0.12564106E+06 0.74786625E+05 -0.26175230E+07 -0.12207031E-03 0.74786312E+05 0.74786250E+05 -0.12564106E+06 0.26175230E+07 -0.74786625E+05 0.15000002E+09 0.12820510E+07 -0.74786062E+05 0.19230780E+07 0.57692330E+07 -0.74786312E+05 0.96153820E+07 -0.12179482E+08 -0.26175220E+07 0.28846160E+08 0.57692340E+07 0.15000002E+09 0.26175220E+07 0.57692350E+07 0.28846160E+08 -0.74786250E+05 -0.12179482E+08 0.96153790E+07 0.74786062E+05 0.57692330E+07 0.19230780E+07 0.50256425E+06 0.42109375E+01 0.16250000E+01 -0.12564100E+06 0.74786500E+05 0.74786687E+05 0.74786250E+05 -0.12564119E+06 0.26175240E+07 -0.74786125E+05 0.15000006E+09 0.12820520E+07 -0.74786187E+05 0.19230770E+07 -0.74786250E+05 0.96154010E+07 -0.12179514E+08 -0.26175250E+07 0.28846192E+08 0.57692380E+07 0.15000005E+09 0.26175210E+07 0.57692320E+07 -0.74786687E+05 -0.12179502E+08 0.96154010E+07 0.74786687E+05 0.57692390E+07 0.19230790E+07 0.25128194E+06 0.46367419E+06 0.97656250E-03 0.74785812E+05 0.74786750E+05 -0.62820441E+05 0.10769220E+07 0.74999952E+08 -0.74786750E+05 0.96153810E+07 -0.12179472E+08 -0.15405970E+07 0.14423061E+08 0.75000000E+08 0.26175220E+07 0.57692310E+07 0.28846160E+08 0.96153850E+06 0.50256419E+06 -0.46875000E-01 -0.21093750E+00 -0.12564106E+06 0.74786375E+05 -0.26175220E+07 0.74786312E+05 -0.12564106E+06 -0.74786375E+05 0.15000002E+09 0.12820510E+07 -0.74786312E+05 0.19230770E+07 0.57692310E+07 -0.12179488E+08 -0.26175220E+07 0.57692320E+07 0.15000002E+09 0.26175220E+07 0.57692320E+07 0.28846160E+08 0.96153840E+07 0.74786250E+05 0.19230770E+07 0.50256419E+06 0.78125000E-02 -0.14843750E+00 -0.12564106E+06 0.74786312E+05 -0.26175220E+07 0.24414062E-03 0.74786375E+05 -0.12564100E+06 -0.74786312E+05 0.15000002E+09 0.12820510E+07 -0.74786437E+05 0.19230770E+07 0.57692310E+07 -0.74786437E+05 -0.12179488E+08 -0.26175210E+07 0.57692310E+07 0.15000002E+09 0.26175220E+07 0.57692310E+07 0.28846160E+08 -0.74786250E+05 0.96153850E+07 0.74786312E+05 0.19230770E+07 0.50256412E+06 0.23437500E-01 0.28125000E+00 -0.12564106E+06 0.74786500E+05 -0.26175220E+07 0.24414062E-03 0.74786375E+05 -0.12564100E+06 -0.74786500E+05 0.15000000E+09 0.12820510E+07 -0.74786187E+05 0.19230770E+07 0.57692310E+07 -0.74786437E+05 -0.12179482E+08 -0.26175210E+07 0.57692320E+07 0.15000002E+09 0.26175210E+07 0.57692320E+07 0.28846160E+08 -0.74786125E+05 0.96153810E+07 0.74786187E+05 0.19230770E+07 0.50256400E+06 0.11640625E+01 0.13359375E+01 -0.12564100E+06 0.74786312E+05 -0.26175200E+07 0.97656250E-03 0.74786375E+05 -0.12564100E+06 -0.74786187E+05 0.14999998E+09 0.12820510E+07 -0.74786312E+05 0.19230760E+07 0.57692280E+07 -0.74786375E+05 -0.12179494E+08 -0.26175220E+07 0.57692310E+07 0.14999998E+09 0.26175200E+07 0.57692280E+07 0.28846144E+08 -0.74786312E+05 0.96153890E+07 0.74786500E+05 0.19230770E+07 0.50256406E+06 -0.31093750E+01 -0.27187500E+01 -0.12564106E+06 0.74785812E+05 -0.26175220E+07 -0.12207031E-03 0.74786250E+05 -0.12564094E+06 -0.74786125E+05 0.15000000E+09 0.12820520E+07 -0.74786937E+05 0.19230780E+07 0.57692350E+07 -0.74786312E+05 -0.12179482E+08 -0.26175190E+07 0.57692270E+07 0.15000002E+09 0.26175230E+07 0.57692330E+07 0.28846160E+08 -0.74786250E+05 0.96153790E+07 0.74786375E+05 0.19230750E+07 0.50256425E+06 -0.35390625E+01 0.13046875E+01 -0.12564100E+06 0.74786562E+05 0.73242187E-03 0.74786250E+05 -0.12564100E+06 -0.74786562E+05 0.15000005E+09 0.12820500E+07 -0.74786062E+05 0.19230760E+07 -0.74786250E+05 -0.12179474E+08 -0.26175200E+07 0.57692300E+07 0.15000000E+09 0.26175200E+07 0.57692300E+07 -0.74786250E+05 0.96153740E+07 0.74786000E+05 0.19230760E+07 0.25128200E+06 0.46367700E+06 0.97656250E-03 0.74786375E+05 -0.62820547E+05 0.74999984E+08 -0.74786375E+05 -0.12179494E+08 -0.15405990E+07 0.44230768E+08 0.15405980E+07 0.14423078E+08 0.25128206E+06 -0.46367525E+06 -0.62820520E+05 -0.10769230E+07 0.75000000E+08 0.15405980E+07 0.14423078E+08 0.25128206E+06 -0.46367462E+06 -0.62820488E+05 -0.10769230E+07 0.74999984E+08 0.15405980E+07 0.14423071E+08 0.25128206E+06 -0.46367625E+06 -0.62820543E+05 -0.10769240E+07 0.75000016E+08 0.15405990E+07 0.14423084E+08 0.25128206E+06 -0.46367419E+06 -0.62820488E+05 -0.10769230E+07 0.75000000E+08 0.15405980E+07 0.14423071E+08 0.25128187E+06 -0.46367400E+06 -0.62820441E+05 -0.10769220E+07 0.74999936E+08 0.15405970E+07 0.14423061E+08 0.25128200E+06 -0.46367694E+06 -0.62820543E+05 0.74999984E+08 0.15405990E+07 0.12564106E+06 Matrix/inst/external/Z_NA_rnk.rds0000644000175100001440000001303013507406613016510 0ustar hornikusersUFww'wN$H2;33;38{_.=럵޼SյKns)FIO0Y[O#6rށѨ^Fvo4!j<<Ƌa̶B4x&ǘφxN0x.2k‹ 72^OϱxA֟xQx %9vaRIc_`DkKOh<:Ӱ023Ƌ|Jcmx9xFᙌY6013^0@xUyX|k m<;'+_m\6?5x|#cklxܘk1nckwכ_s41kŇk1cA}cS9Wos/7c̹hbܹ^ecƖƌU͗3V5e|2V4?벽 ~va o`cF^/1> xce,x#?a|<˷4>xjh^fgÍ/Yr]_?_ xu 4'd||1aC;/8Ɨ{_ l||;m|k6ߘχ)_81σ816Nc̱_ c\?sK/3f 7x錹_Ϸ81Zј{)d̹3soYlda\ߚ?e}<-7zksŵ9q#͍0[/p=]πw5>͘/ne|4ɘ{?3ގ;so{/D-{wN5f<_n|=|D}ˏ4>&ƌhK}K~ƌ%qccx1g<*.Xr8Xc8cxmg[3& bИX)\dL.6& ? _n|]}]wçltcbp Ħcbp1uΘX<\o*|kg? m|cbp1J՘&fNj|$g;n̳*aL4~ܘ,&O?i31_˘\*mL1~x4ƿ{?7&w +2 ~wy;S1^rxix"^2&/Og]G~>7 ˜<|iLl2ژ|8bL^5& ׍gMcqm<T7[cbx;|o<6x[ÏK'cջ~ xA4^2^xQxcW1Vs곿쭒^ 83^xxbeIɵs=sp05&'7/grqAcr1P\٘\(bL.W5&ՍE"qMc~k qcr1`\̘\0.ṉKťqCcb1KԘ&nbL76&ufǍ;_N2& obՌ9aec򽰃1Q8e (6Ɩa cbpUĮPcr0Ҙ\$lL,FA2a1P8֘cw?r0И?W8ژ\3ḵ C¶cr1MØX>fLFݍÉBa/cbp1pXxxEcrp1HcƧz63ޅ9͟bƌga~c]5=,j̵4w˘s5\̘Y01~k/,\a6'5sœƜ˰D_0]x|Ϙ~372fh>kܹS5m7ɘ\ >h'wKoĖE[Nnr>}=^۞rmorxO_5&+"[X_=ac5o̶y]\$>bLn/6&7sƣGuƸӌɍ?߇1VPȎ=\akGQͪ/`̵ך?_۞G~ձm ?ܞO:f1؟|U̘sX[}M:F n*V(y>mw6c,ƚ/zxpjVdƚXƊ&7޺}~kVnk.kNcŲ`1VVbu5W7rEu-niar-{oocF +X: +V[Xuo 6V컖bemks1cvkXf-64Vl1Z+Yz2V.6Xƺ?ھkV쾹rdwucb+w[X 6V켐ru`+)[X:۵LJ5jd cBkkdnS}^mVmibi;1js>56XύOƪ=6UyfC}c|֬Z]o{ǻxYU[Me^j3&ǟOjƪ Nlz''c}elxD;^Y4mޥ/ԼS^z>5֎wxd~OPc%۷~|Y]Wt5w7|5녙4J0t5^ j׋"z9B/袗?^ЋzA/$%yP * *ΪўHQ *W5IZ*\ P\ ךQԀ&*52YI AjQ#i԰O5B /jBQ@&5~B jJĽ&5!I^Mkr\ܚd_jUS5Y OM"j"PeӤ&4aI:M|i2K jTc &J5"O rjrS㞚Ԡ/UVADErT"K +QCIQ%Jd)S2^E%J@hFk߾&ҍS zhAZ" T*Pp@A/=*R N7 2zi@tTd׋"zYE/^ы` [ЋKzJ/84᠗x4q4$“&הi]ajV5+5%Mi2H/5kIj8SӠl85qLdj IDjRԌ5D$jQW, jBBo%>D[W-JoMkGEA߫ RUt{( VЍY{ÿW>=TĿW^{ſWB*H߫[%5ѭ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))~{o|t=F1fĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿĿWWW@\TOIO9żz}?;o;z_ˈzF!J˯1xԈخ4x(bOpdMAMatrix/inst/external/wrong.mtx0000644000175100001440000000010311204272304016206 0ustar hornikusers%%MatrixMarket matrix coordinate integer general 2 3 2 0 1 1 1 3 4 Matrix/inst/external/wrld_1deg_slots.rda0000644000175100001440000035070210770571602020133 0ustar hornikusers\lՕ޸ !xp%wwwww^U|s7!vz|,li:kؿ[:a]1w)~[Z?oٓ~Ҟʞڞƞ{3ƴg,{ƶg{Ƶg<{Ʒg{&Y?'2ᆴ)~5N3ԃu{g:{g{fg&{fg{ך}1Xganw?ysw?~ ~ ~a,wޖ}M8xO,cϲg=+س=ٳ`]ybϟY՞Yݞ5Zu{r^{Nj_+u|c=g>;dž|F6r泲3?Ck 5ڤ59۴5۬5ۼ5YyV{tʞm֞ޞўŞ]=ٳ[y3:[Lg_|&p33ɽgog>8י~|&| .eAl!Ж>??n fh ~l j v}3cg>85'Nl I왓78wNuf:ݙ=t3{LgYs3{gйC;.pf]ș=t3{gХ˜C;pڞ+W횖ݵ=x]kx?^ޛ7s=;Þ;˞{מߞyGiϣΏ yž'yʞyƞg[3ޙə3g-C^~ݙ_g7o9vf/^~י3{}g9?vf/^ԙ3{sgΧ3{+go:sf/^3{'g_˿:_gr-vOf/eu;Xf=Nex;mf:̓nfncϲOs~mڻmf6>n-2{=̞n/2{=̞nO,^_׶msYf_mfmS42=nO' 2=n$3,2=n&۳2=n%s<2=n'ew{^Pfew{^Tfew{ g[K:ۿr^wOζ8n/{wԶ;nlJζ+;n<׶kWfc{vc:}^b/>> >퍝}s>M>͝>->>m>>>;翽}ۻ8翽}p{7gwg>r3=og>8י~|w3g9jV櫶Tm6;m^jیԶ9mO敶5o{gc>ڼѶ=s`e\~ԙr3rg+/W9_vf\~֙r3zg /79_nvf~ՙr3vg;/w9_vf~יr3~g/9_vf<~yԙ3qg'/O9_vf<~y֙=3{YY`i`e7X{;>pf~̞5??n OZ5?wi`eaaava^aFa.a9ݞ3/3o[{惎1~N)챹=o>tWޯm뛎n=[fwƑqexg<=_fw& exg"=ޙXfw&Iex2{3L.;SΔ2{3L-;δ2{3L/;3Ό2{3,;ά2{3.;sΜ2{3-:8;Xmls!ζ;:>lsοmwp}9ҙ9Qζ;G;>lsqζ;;>ls 5낎uAfw9ͽ}mб>Xtl|߱cso/nfڽn>\X׭9s9p3Μw9s9p3Μ9s93Μ9s<93Μ9s<93ΜO9s<93Μ9s<93Μ/9s9`}p6X5:ǜܻܭܧܡ;^kxߙ3g΍97>rؙsg΍O97>sܙs g΍/97rڙsg΍o97sޙsg΍97~rٙsgί2cVvtk 5@fyԍ[R7i QTeΜjҵZtm.Ztζud1X7ccmѵkJcg`wB;̹؝5tFv'i I[Cggs;ܹ~=搮]76ctm2;ܝ5zwg;ۯgve2̶;G)wsݝ5twm ]{[O.5FW:=>{;+w{tunbK+wѻ{uo*[]YWk{jcjwVFgkMa[Y[S9>X]۝vWknl۽Ǚ;85vut{c݇>lXQgǺ9=}vut{cݧ>lXYgǺ9=} vu_t{cݗlXUgǺ9=ֵ3xrgq/qm0xcC+wwwڧѻqϝ~l\KgW7vqǍvuuo~l[Ggߺ?9/vuu޹b?s2K3[+sz2[/z֋d^,soL~2[z֫d^-s7"sƐzcod2[o7O~/s&zod2[o;7]ܵM<`{cٛjN=Xc9{+wfo:c>_K{3ܥYdެ2jo6;7{k{{s]\sVwzv~ٽҳgE=#zv/y߳3gz=lݯ-+ss{ܹdފrZʃ2 Z{ V;{ܽ7ڰ[G+s֓{ͽ dކ2so#;ܵ~oZ`ye~حvW{սmev2wuo{]Q$sW.sWv{ս]e?dn2wu2wuow/]S%wkqrZGVN{F!rZwa3;C=;F+w-{9s}:x(s#sN{'Sdީr׺wywFe)3 Βzgsdf޹2@gz;,{fރ6 rYG u ǝmf=lCIg!zO9,{f36[umlFEg5z/9۬{f+6k^uYםmי gf7[[Nkxfy5<eo 5g}{97|V|s`~߹cѹ,XSf> ֒ӂe/2s[+3o2s\Ll(u76 -g`+{7|&hh8ڜ"]_+#jb{eNd6]m. =e`/1[fF }ef`?1_fF ef 18XfF Cef018\fF -3#G̈23bp̌-3#̈23bp̌/3#'̈23b18IfF NSdfT18MfF N3dfL18KfF Ζsdf\18OfF Η dfB1HfF .KdfR1LfF .+dfJ1JfF kdfZ1NfF dfF1IfF n[dfV1MfF n;dfN1KfF {df^1OfF dfA1xHfF GdQ1xLYs;?_/'[sfܳv~fwj <7XٜWZCkrkh ^i ʹ6x54=ko V~6#WY9f#gmV>qY9f3g/;ۼ|33WylMkx5 `2 >$`2 >"`2 >&a2->!c2=>%d2m>#h2>'l2 o2$o2"o2&o2 W7d.|5x[ ߖw5ah=ݴ8n ?c ?S ?s K k [ { G g WV[2]uZCu[Cd1 d1 e:2dz2e2Jd2Je2d2e2*d2*e2d2e2jd2h ƌƔih,n 5h4LFh4LFˡp46&ꯡΓ Vk4s'M1XG#4֍7#k2J~+M"{G:_hڟlMIg-iCV>icV>iSV>isViKVik^[k t`#ňF{̭}m^;2wez9rrrrrrrrr\r\r\r\rr<"2)X2-82+x2/2O(D2O,$2O*dz9Lez9Bcc|O-ӻ42O+ӽt2O/ 2=jx&9;yJ/dzW9M[C-xPcsz;5<m 5y<J W=^Pd=^XEd=^TȾxq%+m/_x)t=MO/+r2// 2վxeU_L u.=xվx fהix-fזi/2#2'2o 2o$2Uɑ}1 c_kLǛɴ|L[ȴ|L[ɴ|Lȴ|L35Ѳվx{.wxG.wrd_G.Z1?'.xhx6ix/6ix6ix?6i6i 6i6i06i2m!2m%GG;_|`iAzW:>>Ie:>>ESe:>>Me:>>C3e:>>Ke:>>Gse:>>Oe:>@ e:>He:>DKe:>Le:>B+e:>Je:>Fke:>Ne:>Ae:>Ie:>E[e:>Me:>C;e:>Ke:>G{e:>Oe:>~@e:>~He:>~DGe:>~Le:>~B'e:>~Je:>~Fge:>~Ne:>~Ae:>~Ie:>~EWe:>~Me:>Lot|Lot|Lt|Lt|Lt|Lt|Lǟt|Lǟt|L_t|L_t|Lt|Lt|L?t|L?t|Lǿt|L'-O2td:>t|ғ$$$4<>$2-OP'lIJ gk:/KξdJ'ct2L't2L't2L't2L't2L't2L'd2O&d Od*OdOd:OdOfd&OfdOfd6OfdOd.Od9U2|Zj?dOd!OdOd1Od wɒ2d$K˼H$ YF@;d9w2d$+ʼHVy,> YE}@gɪ2d$˼H֐y)N YK@v~{sXέ}'ɴ~L'ȱ}ɆW?'=uV:Md=Tߓd=\ߓ-d=Rߓd=Zߓmd=M91^L„Ftו&?eZ<]œɴxL'{ʴxL'{vkp׻L'wrL'wrL'˴xr[':6XZ~6ɑvOihOXOxONDO#I2,)2*i2.2)Y2-92+y2/2-\(E2M\,%2}\*e2͟\.2ݟ\)U2ݟ\-52ݟ\+u2ݟ\/ 2ݟ(M2ݟ,-2ݟ*m2ݟ.2ݟ)]2ݟ-=2ݟ+}2ݟ/2ݟ<(C2ݟ<,#2ݟ<*c2ݟ<.2ݟ<)S2ݟ<-32ݟ<+s2ݟi#O>iO>i3O>i Oi+OiOi;OiO~i'O~iO~i%i[ӎL]O{222F22&22f2222V22624~:Lc4~:Lc4~:L4~:^izZGWRwtbO'itJޣ}-d2ݝN.2ݝN)T2ݝN-42ݝN+t2ݝN/ 2ݝ(L2ݝ,,2ݝ*l2ݝ.2ݝ)\2ݝ-<2ݝ+|2ݝ/e;]@e;]HӅe;]DEe;]Le<]BNkKt^jZlyLee<]Ne<]Ae<]Iӕe<]E?tyLtyLktyLktyLt.Oוt=.Oחt.O7t#.O72]Mt9%yҗԚ1NL SkZ߭};tzL;zw9#yJz|/ j_oLtNOt/NOt9A35=5遭Oj ~zpkCľPgz[{O-2)Q2-12+'t} OO?2$2"2& =]]@z#=J&= =WAz̻|w2 eɼ;H/yw^" TAz̻rw2+eWɼ;Hyw^# VAz̻zw 2e7ɼ;Hoyw" UAz̻vw2;ewɼ;Hyw# WAz̻~w2eɼ;Hyw>" }TA̻qw2'eOɼ;Hyw># }VA̻yw 2e/ɼ;H_yw" }UA̻uweoȼ;Hߔyw% }[A̻]w{2eȼ;H?yw~$ XA̻Swg2e_ȼ;Hyw~% ZA̻[ww2e?ȼ;Hyw$'Lv!!kɼCh0~n>ul'> dd,y2D}@ʼ2Y.> +ddy2F}@6"> C}@6l,2qddʼƓy/> @}@6l"2Iddʼ > L}@6l ٔ2ddS˼ȦyM+> N}@6l9U6L5Y6`eҏ|oվlv~lN~ln~l^~l~~(2-(B2-,"2-*b2-.2-)R2--ٟd=[F߳ee=[N߳e=[A߳e=[I߳e=[E߳?{Lg4|Lgkt}Lgk4~Lgil֕il=֗il6il#6i2Mil6il36il ϶il+϶il϶il;϶ilvil'huk٭e֓475/-ilil/ilil?SsF_Ґt5afkJ'ZeW:8;\3g:8s3g:8s3|Nˎi8͎ig6ZtZe'lvLfȴmvLftnvLfgtnvLfgtnvLftnvLftnvLftnvLftnvLftnvLftnvLfWtnvLfWtnvLftnvLftnvLf7tnvLf7tnvLftnvLftnvLfwtnvLfwtnvLftnvLftnvLftnLftnLftnLftnLfOtnLfOtnLftnLftnLf/tnLf/tnLftnLftnLf ޔ-ޖޕ=ޗ>#>>3> ;+;;i;;w~p~t~ryvu[ޒi߼-ӾyG}L=C#cS3s K+kGd7C}1e7K}e7G}qe7O}e7@} e7H}e7D}I+K뎮րd2O.ӹ2O)ӹT2O-ӹ42O+ӻt2ݛO/ӿ rf <`៥ +]!2]%2]#2]'2]Qd8_Pd8_XEd8_Td8_\%d8_Rd8_Z?tqLtqLtqL+tqL+tqL|U.W|u.א|M.ג|m.":2]+z2]/2]o(F2]o,_e8L'&2]o*f2]o.2]o)V2]o-62]o+v2]o/2](N2]]ά{w.ݛӿiGWk|w%ӳ2=)ӳ^2==5ڲ|i@i`iP9su6?Bm#:8?Jg'6?Nme6?Ame6Oki:6?YcSd:6?Ucd:6?]c3d:6?Scd:6?[csd:6?Wcd:6?_c d:6Pcd:6XcKd:6Tcd:6\c+d:6Rcd:6Zckd:6Vcd:6^cd:6Qcd:6Yc[d:6Ucd:6]c;d:6Scd:6[c{d:6Wcd:6_cd:6Pcd:6XcGd:6Tcd:6\c'd:6Rcd:6Zcgd:6Vcd:6^cd:6Qcd:6YcWd:6Ucd:6]ctlLotlLotlLtlLtlLtlLtlLtlLtlL_tlL_4mY౮Ϳwptrvqu-Z2][etmѕڢ'ӵE ӵE(ӵE$ӵE,ӵE"ӵE*ӵE&ӵE.ӵE!ӵE)ӵE%ӵE-ӵE#ӵňLY40;[Q vc-Z#ӢŸ2-Z'Ӣ2-ZL Ӣń2-ZL$Ӣ_Ϭў,&2mYL&Ӗ2mYL!ӖŔ2mYL%Ӗ2mYL#ӖŴ2mYL'Ӗ2mY ӖŌ2mY$Ӗ2mY"ӖŬ2mY&Ӗ2mY!ӖŜ2mY%Ӗ2mY#Ӗż2mY'Ӗ2mYQ-dڲXP-dڲXX-EdڲXT-dڲX\-%dڲXR-dڲXZ-?ɴeL[ʴeL[˴eL[+ʴeL[,HqZbUN,VbuN,֐bMN,֒bmN,"Ӊ:2X+Ӊz2X/Ӊ2Xl(ӉF2Xl,ӌuva?~&?~&|t!=8Z [ʴ`L [˹ud3'[ezAezI`L`Lskb7V~G kb6,b/N,skbg~֌t"-H'i-گ8}A2W,}!2W*}a2W.}ſe8B#e8Je8Fce8Ne8AeL't_qLt_qLt_qLgt_qLgt_qLt_qLt_qLt_qLt_qLt_qLt_qLWt_qLWt_qLt_qLt_qL7t_qL7t_qLt_qLt_qLwt_qLwt_qLt_qLt_qLt_Lt_Lt_Lt_LOt_LOt_Lt_Lt_L/t_L/t_Lt_Lt_zxCέ'7t_vwdxWdx_dٚٚٚٚٚٚٚٚҙʙڙƙ֙Ιޙљəٙřg5ె+2 Wvd4\ٓi2i2i}Fce"ce*ce&ce.ce!ce)ce%ce-ce#cLcWZ]ʱdګRZtNZWtU9LWtU9LWtU9LWtU9LWtU*'rr*rJ*rj*rZ*rz*grF*grf*grV*grv,psߙV9Oye:Oe:Lg tVLg tVLgtVLgtVLgKtVLgKtVLg ӒkrP˷ڬ\A.EW]n;Z35wp5VLck4VLckW]ʿTLSʴU\Xo;3-iHkZؿV~3믴RL/RL/RL/[RL/[RL/RL/RL/;RL/rg^*wrW^*!Kn2TSezL/{RL/{RL/RL/RL/RyL/RyL/RyL/RyL/^*(^*J+GQyL˴QyL'ʴQ6*Oid6*OiT6*Oit6*ϐiL6*ϒil6*ϑi\6*ϓi|6*/iB6*/ib6*/iR6*/ir6*iJ6*ij6*iZ6*iz6*oiF6*oif6*oiV,osIF*.V*^*>^*^*!^*^*1^* ^*)^*^*9^*^*_쯿n6*_igȒτ5R߽ MB _*t)r)v)q)u)sέ?hf}f#gˏm/?q>u>s>wžpžtžržvžqžužsžwGg'ggg_m/ujU[f:2Օi'U U(U$U,U"U*U&U.U!U)U%U-U#ՈLTc4@5LTcɥZ58z]mƓe@ eH.ɪmT|i5j5_M)Z{kڬ_M#3Wt2~}S8XLۼ__YdjVfijvijNijnij^ij~(2-P-(B2-P-,"2-P-*b2-P-.2-P-)R2-P--՟dZZFeeZZNeZZAeZZIeZZE?˴@L Tɴ@L Tkȴ@L Tkɴ@L Tij֕ij=֗ij6tި&*+=@6Wզ2_m.3W[Ֆ2_m-3Wն2_m/3W;Վ2_]fv]djW_&3We_2_)3W{2_+3W2u_(3W2uLTt@uL T˴@oiHihiXixNiD#I2-P,)2-P*i2-PWlޮ쯥5U~`Nf6~ϭ6 WȥuNu3ٗyS|[]_mpͲE2lu,[]"3V̲e2lu,[]!3VW̲U2lu,[]#3V̲u6V;,[lluͲM6V7;,[lluͲm6VVc]GW[;mnrg&{mnsg[mnrzg]Gǵ1gx)g_m~qz9gf睭_/c[YU+`fWUfMg-gXVf=g]mv>pٵf#g]iOiOiϜiϝi/i/iiioioiiiiiii_i_mv[2kݖ]Zwef׺'3ցZ2k̮u,3։Z2k̮u.3օZ2k]̮u-3֍Z̮2k=Z%3c̮82k=Z'3̯23l=[O$3˕u^=Ce'gez yRfgezyVfgezyQfggezyUfggezySf璙gezyWf瓙ge2l<[/(3 ̳2l<[/*3֋̳2l<[/)3K̳2l'y^Ffgdzyy^AfWgdzey^Ef,3̳֫j2l<[!3k̳Z2l\Y՜'6Wz=ޫw`rNЄt F]VC̡ddz9Tf7Cez 9RfCez9VfCez9QfwC˕uX.޵2Gd2h\f-3G̦2sj}\b>[_edfx~Op>q߰^ee}ۭ֜μyg ln}ve֭ϑusef_f֭/u ef"YXf֭/uKef2Y\f֭u+ef*YZf֭ukef:Y^f֭ouef&gu뛝m֭oqYf6gu۝m֭pYf.gu뻝m֭qYf>gum֭pY~f!gF뇝m֭qY~f1guǝm֭pY~f)gu망m֭qY~f9gum֭_pY~f%gw뗝m_q~5g{םmlsoͽ6o9[lsoͽ69[lsoͽ69[lsoͽ6֟9[lsoͽ6_9[lsoͽ69[lsoͽ6?9[lsoͽ66-i̽MGfm2soӓ{@fmBd&{DfmRd&{BfmJdަ{FfmFdf Sfmƒ{eކbc3o3ی/36̿̈́rmL̹`ܰigzjn3̬L.36S̺͔2n3̬L-36̺ʹ2n3̬L/363̺͌2n3̬,36̺ͬ2n3̼.36s̽͜2so3-36̽ͼ2so3/36{dfAYHfm{EdfQYLfm%dfInr^zrepLܬ 37+J23qLܬ"37Uef5Y]f>n֐5eff-nvs)Zu+{FO<6G7Yll,3;7&2sl&3;72sl%3;7[62sl'3;72s$3;7effٹUfvn!3;7?effwٹ!3;7{^2s#3;7~2s 3;7A2ss"3;7a2ss[fvn#ef(ٹ9Zfvncef8ٹ9^fvnNef?2ssܜ,3;7ͩ2ssܜ.3;7g͙2ssܜ-3;7͹2ssܜ/3;7ͅ2ss\,3;7ͥ2ss\.3;7W͕2ss\-3;7͵2ss\/3;77͍2ss,3;78lss6;7w8lss6;78lss6;78:}ukg7o9[wNl>:}ugg/_9[~wNd:=MӃe:=CӃ1e:=KӃe:=GӃqe:=OӃe:=@Ӄ e:=HӃe:=DӃIe:=LӃLLLLLLLLLLLLLLLLL#d:=\Ӄ)d:=RӃd:=ZӃid:=VӃd:=^Ӄd:=QӃd:=L3tz0LtzWNf`vN`NNo2-<2]Ӄye:=OӃe:=X@Ӄe:=XHӃe:=XDӃEe:=XLئy?>2},%2},#2},'2} 2}$2}"2}&2}!2}%2}#2}'2}l l:c]w1]ݵn6` vkl-62l+v2l/2(N2,.2*n2.2)^2->2+~2/2(A2,!2*a2>޷k)Q2-12+q2/ 2(I2 <NSi|giw1wՃ3eZ=8KՃeZ=8GՃseZ=8OՃeZ=@Ճ eZ=HՃeZ=DՃKeZ=LՃez=Bۃ+e>J~vf{Шnol7;2|w.{e!shVnӆӞӶd6H $2$xDf1]<.K2$xBfO)]<-KgdvI. %2$xvI%g%ζKWm:. ^s]l$xvI-g%ζKwm:. s]l$vI#g%|l$vIsg%ζK/m_9. v]|l$vI{g%ζKm?9. ~v]l$vIwg%. G%2$Cfcp,]-KqdvI8. Ǔ%2$@fp"]N,KIdvI8. '%@f. C]F2$evI0%a&K\f. K]V2$evI쒰%a'~e]N.K)dvI8. %2$Ffp:]N/KdvI8. g%_dvI8. g%2$. g%2$Cfsp.]Mfslp]fi iDŽiӄ i߄ ʁp!Gw.];!!6{[wmKp).-_edK~ /2%\Af+p%,_UdK~ W/2%\Cfkp--_udK~ ד/2%@fr`;:ș]}Ulpcn"UMeJV 7*2[%Rf[lpkn#Wm6v37YN w)N2;%YfpW&SevJN )^2;%[fp_'SevJxN *A2%#ge6Pmyg@ ζm/9 _v l(|6Pmug@ζ7mo9 v l(|6Pm}g@ζm9?Tmg@ζϜm; p ~l(6Pmg@ζm; N G l? _;ζw_տ:sfWl{';h2{']fDchL%weN4މƕ;x2{'_fDhBM$weN4މ&;d2{'(;Q(wHfDމ2{'d6Ol3y ݈m̨k[&jeLl2-M.e)dL4̖22[&FfDlh:-M/edL4̖f2_dL4̖f2Ѭ2[&̖f22[&CfDsh.9-ygyeL4̞32{&ZPfD ha=-"gEeL̞4rh:ZywkeevM̮5 2&ZQfD+he]"kUevM̮V52&ZSfDkhm]#kuevM̮֗6rh9Й8766owvI&6$f2$\fD[lhKMm%Ie6I&$v2$^fD;lhGM$Ie6I&v$n2$]fD{lhOM%Ie6I&$~2$_fDl@M$Ie6It&$a2$:\fDGlHM%Ie6It&$q2$:^fD'lDM$Ie6It&N$i2$:]fDglLM%Ie6It&Ε$y2$:_fDlBM]$Ie6It&.$e2$\fDWlJM]%Ie6It&$u2$^fD7lFM$Ie6It&n$m2$]fDwlNM%Ie6It&$}2$_fDl?2$zPfDlaM="IGp×m#/[%zBfDOl)=-UgmD:Vs=l[%zٶJm%g*ζUWmD:V^sl[%zٶJm-g*ζUwmD:Vsl[%ٶJE9V>v}l[%ٶJmsg__Y?>K";g!ζCmD?:~rl;$ř-3[7gζC!&CevH<ǔ!X2;$[fx\'CevH<'!D2[$XfēȑmxRF^6J<y'q OPfđ>c}'2$NeI8'q!ORfĕ>k72[%nvs9×xO!])eKHfl*Qd6J|F(2%>JfGl+Qd6J|FO(2%>If'l*Qd6J|Fϐ(2;%>Kfg+]dK|v/.2%Hfl_*]dK|v.2%JfWl_+]dK|vo.2%If7l*]dK|v.2%Kfwl+_d6L|پp{Ow=󽻶_GF?OV*2[%V'U'mO:Vr?l[%~ٶJm9g*ζUm/:V_rl[%~ٶJm5g*ζU7mo:^rl%~vK=gwl%vKcg-'ζ[Omğ9n?wl%vKmkg07ζeom9۞w=l{&Lgg3/ζg_߿9w= d4=.gIHyx2;#_fg$dBL$3evF2H&d2;#$I(3Hfg$H2;#dvF쌤I)3Jfg$H2;#dvFdH&2;#Rfg$SdjL#3ievF2H 2;#Qfg$3/2;#Yfg$dVUfg$dv!39evF2H&3evF2H.3yevF2H2;#YPfg$ da,"3EevFH2;#YRfg$Kdi,#3eevFH 2;#YQfg$+de"3UevFHV2;#YSfg$kdm#3uevFH֗2;#Pfg$F2;#H%3dcl"3MevFH62;#Rfg$[dkl#3mevFH2;#Qfg$;dg"3]evFHv2;#Sfg${do#3}evFH2;#9Pfg$`"3CevFrH2;#9Rfg$Gh#3ceFrfNw=]_wmG$4.#3dvDr̎HΒ2;"9GfG$</# dvDr̎H.2;"DfG$2\.#+dvDr̎H2;"FfG$:\/#dvDr̎Hn2;"EfG$䶑 񕻶;d6CrfH 2!Gf3$l>͐/d6C͐<(d6Cmg ɣζǜm3$1?7X _30|mo$/:H^rl{#yF5gζ77mo$o:Hrl{#yF=gGMw|l{#Fcg'ζ7Omo$9H>w|l{#Fkg7ζ7omo$9Hwl{#Fgg/ζ7_mo$9wt4.71dF:Hǒ2{#Gfotl->l->l->l->l0s K+k[;:uӏӏٞ8=?uf{~ܙ3KgWlϯٞ8=uf{~ޙ3GgOlϟٞ8=uf{ٺ;l4Fl Ɣl,Ɩlƕl<Ɨl&l"&l&l22ݝ2ݝ2ݝE2ݝ2ݝ%2ݝ2ݝe2ݝ2ݝrj3+ꑗZ:z9;ٚkM)T2M-42M+t2M/ 2(L2Eez;EYez;Logv6Logsv6Logsv7l.ټ2'2- ق2-$!y[?dc͝-!ْ2͝-%2͝-#ٲ2͝-'2͝ ي2͝$2͝"٪2흭&2!E5=?ٜk-'2-m ن2-CdZ:LKgi2-m,&2-m*f2-m.2-m)V2-m-62-m+v2-m/2-(N2-,.2-*n2-.O3٫lܵw8G}e8Oe8;@e8;H3ֺ١2&Ӻ2!Ӻ4.]ֱ2#ӱٱ2'ӱ2 ӱى2$ӱ2"ӱ٩rj;3;yLΒlΑ\Γ|.B.b.R.rͮJͮjͮZͮznFg&gfggVg6gvggNg.gngg^g>g~gg?ֳكֳCֳֳ#ֳ٣ֳcֳֳg9?|lll5mummmmmm܌willlllllllllllllllllllllllllll3'ggg6/ο_o× _6,u9wY1d5SYd5[Yqd5WYd5_Y d5PYd5X_Ih>dސލֱy,ӱy"ӱy*ӱy&ӱy.ӱy!ӱy)ӱy%ӱy-ӱy#ӱy+ӱy'ӱ9o]֤2MO!Ӥ2MO%Ӥ2MO#Ӥ2MO'Ӥ2M Ӥ2M$g7s޺9o>k2-&Ӣ2-!Ӣ2-%Ӣ6e>3ui>K4i>L 4i٦yؘcݵi|Qi|q̗i|I̗i|i̗|Y̗|yW|EW|eW|UW|uא|Mג|mב|]ד|}7|C!ӟF2S?go7|7|37| ̷|+̷|̷|;̷|w|'w|w|7w||/||? 09fѡkݙ#ӝ2ݙ'ӝ2ݙ ӝ2ݙ$ӝ2ݙ"ӝ2ݙ&ӝ2ݙ!ӝ2ݙ%ӝ2ݙ#ӝ2ݙ'ӝ2ݙ_ ӝ2ݙ_$ӝ2ݙ_"ӝ2ݙ_&ӝ2ݙ_!ӝ2_%ӟ2 _l_l=_l7-㽲AQך3ٚ3ٚ3ٚ3ٚ3ٚ3ٚ3ٚ3ٚ3ٚ3ٚ3ٺ3o{y9Q33򇝭1G1G1ǜ1ǝ1s'kI1×fG]kigkgkYgk9gkygkgkEgk%gkegkgۘфt 7Zo8[o:[o9[o;[86u].G]kgkCgk#gkcgۃ'Ο_ ޝE?օօW¯ o o     ٞ?;=qf{͙ua1$Ӆh2]X.Ӆ2]X)ӅX2]X-Ӆ82]X+Ӆx2]X/Ӆ2]XL(ӅD2]XL,Ӆ$2]XL*Ӆd2]X ddedeHdHede(d(edehdhede!Ӆ2]XL!ӅŔ2]XL%Ӆ2]XL#ӅŴ2]XL'Ӆ2]X ӅŌ2]X$Ӆ_dY YdU ta1Lta1Lsta1ۮ-x7)N֋4k}X/Ӈ2}X,(ӇB2}X,,Ӈ"2}X,*Ӈb2}X,.Ӈ2}X,)ӇR2}X,-Ӈ22}X,+Ӈr2}X,/Ӈ 2}X(ӇJ2}X,Ӈ*2}X*Ӈj2}X.Ӈ2}X)ӇZ2}X-Ӈ:2}X+Ӈz2}X/ӇrnЙw~Iͳ~,6yiǂwF p:Le:B-e:Mlgc]WQ?yN#/W,x.2W*xn2WlSŞ×7>ɞsG}eOe8@e8HÊ`BsYok]U&U2mU!#7MPű2U'S2mU ݊Oyi䑗*NT*Nt*ΐL*Βl*Α\*Γ|*.Bg"gbggRg2grg gJg*gjggZg:gzggFg&gfggVg6gvggNg.gnggSlUlUlUF+irF+ir!F+irF+ir1F+ir F+ir)F+irF+ir9F+irF+Wir%F+WirF+Wir5F+Wir F+הir-F+זirF+וir=F+חirF+7i2Vn$h?eLircF+7irSF+7irsF+irKF+irkF+ir[F+ir{F+wirGF+wirgF+wirWF+wirwF+irOF+iroF+ir_F+irF+i6hܵ*iP*ip*iH*ih*iX*ix*OiD*Oid*OiT*Oit*ϐiL*ϒil*q*u*s*w*/p*/t*/r*/v*/q*/uZ^kEgYZ%uU9ڪfZ_:[c9[c;[c78[c7:[c79-oYըk]UlUUU]UU=U%op3SʹfF]k!gkagkgk&WFHζ'ysmgaP ||||Z|yn}c菶cMUlMUlMUlMUlMUlMUlMU~lMU~lMU~lMU~lMU~lMU~lMU~lMU~lMU~lMU~lMU~lMU~lMU~lMU~lMU~lMU~lMUlMUlMUlMUlMUlMUlMUlMUlMU 4U5LSU4U5LSUc4U5LSUc4U5LSU4U5LSU4U5LSU4U5LSU4U5LSU4U5LSUB"bR2r J*jZ:zF4U5-E?LR5L/USR5L/UȥmjZg`v*Pwe:ItR5L'UtR5L'Uj6NfjNj.N&I2T#Ie:Wd:_d:ZPd:ZXEd:ZTd:Z\%d:ZRd:ZZed:ZV6i #/T8MJriZykljMU>T2MU)TZ2MU-T:2MU+T)tK2Tm(K?dzHR/Yۙ7JDk Tm& +G~*MDkj둗>ij[Fj{^vijǡ?uTПyO}U"Yծ2U&Z2U!Z՞2U%Z2U#]վri۱⭤hwܵƪi@ƪi`ƪiPƪipƪiHƪihƪiXƪixƪNiDƪNidƪNiTƪNitƪΐiLƪrƪvƪqƪuƪsƪwƪ.pƪ.tƪ.rƪ.vƪ.qƪ.uƪ.sƪ.wƪpƪtƪrƪvƪqƪuƪsƪwƪnpƪntƪnrƪnvƪnqƪnuƪnsƪnwpX՝X]XX=XսX}XSv,}Ǻzp菞Q׺wa[mD#GG9[UO8[UO:[UO9[UO;[U8[U:[U9[U;[U/8[U/:[U/9[U/;[U8[U:[U9[U;[Uo8[Uo:[Uo9[Uo;[U8[U:[U9[U;[U8[U:[U9[U;[U8[U:[#U9['U;[+U_8[+U_:[/U_9M_;[CU8[KU:[OU9[OU;[pfnə3gvμl ݵdZMeZC1ezKlc;VO٤[ּ=EKR2-UO(RD2-UO,R$2-UO*Rd2-UdZdZeZdZeZNdZNeZdZeZ.dZ.eZvg];6Itde!P2 UO!P2 UO%P2 UO#P2 UO'P2 U P2 U$P_dYYdU4T=LCճ4T=LCs4T=LCizni2 U+P|2 U/P2 U/(PB2 U/,P"2 U/*Pb2 U/.P2 U/)PR2 U/-P22 U/+Pr2 U//P 2 U(PJ2 U,P*2 U*Pj2 U.P2 U)PZ2 U-P:2 U+P5o>}ntcșwfuQo.7z.7z3.7z .z+.z.z;.z.wz'.wz.wz7.wz.z/.z.z?.. ..0..(..8.y"۰t3Z'9[';[ԧ8[ԧ:[ԧ9[ԧ;Nkz|wy}QZ>ZZZZZZZZZZZZZZZZc78[7:or歷wF]kVgk6gkvgkgkNgk.gkngkgk^gk>gk~gkgk?::C::#::c::u9[O8[O:[O9[O;[8[:[9[;[/8[/:[/9[/;[ԯ8[ԯ:[ԯ9[ԯ;[o8[o:[o9[o;[8[:[9[;[8[:[9[;[ԟ8[ԟ:[ԟ9[ԟ;[_8[_:[_9[_;[8[:[9֭wau T_CtШk۶7˾]kftiƐifLiƒifliƑif\iƓif|i&ifBi&ifbi&ifRi&if 8M 8M(8M$8M,8M"8M*8M&8M.8M!8M)8M%8M-8M#8M+8M'8M/8i&if iif*iifiif:ik 3m 9]kffififV]oEcco~c|co{{N'k=]GyezOGezY@GezYHGezYDGEezYLGezYBG%ezYJGeYFmg6:/7|nxiܵ6iVife6iVifU6iVifu6i֐ifM6i֒ifm6i֑if]6i֓if}6i6ifC6i!&F2mSMɴIo6i6if6i6if36i6if 6iif+6iif6iif;6iif6ivif'6ivif6ivif76ivif6iif/6iif6iif?6ii6ii 6ii6ii06ii6i(Nii |[ۮm4omNr7iNuӝyۭohQz9z9z9z9z9z9zzzzzzzzzzzzzzzzzzzzzc6:[49[4;[4w8[4w:[4w9[4w;[48[4:[49[4;[48[4qitiriviq<.؆mO_:!Cng9ym6#41Zs4/:[s4/9[s4/;[s48[s4:[s49[s4;[s4o8[s4o:[w4o9o;[48~lu~o[4_#gcggSg3gsg gKg+gkgg[g;g{ggGg'ggg6/'ͯ'o''LI;LcI;LcI;LI;LI;LI;LI;LI;LI;66666666银银银银银银银银vLI;LSI;LS4J;LJ;myϭWIyiܵ~igiv}Vghsܵfigivfiiv.fi&,2#,eWYd_Yd]PYڅd]XYEd]TYd]\Y%d]RYڥd]ZYed]VYd]^Yd]QYڕd]YYUd]UYd]]Y5d]SYڵd][Yud]WYd]_nl߶8oMk'[an<4wMdTd\-d:Rڭd:Zmn3 KZ;OL;OLOLOL{OL{4PL tQL4R{L#4R{L#4R{L#4R{L#4R{L#G4R{L#G4R{L#4R{L#4R{L#'4R{L#'4R{L#:[#9[#;[#g8[#g:[#g9[#g;[#8[#:[#9[#;[#8[#:[#9[#;[#8[#:[#9[#;[#W8[#W:[#W9[#W;[#8[#:[#9[#;[#78[#7:[#79[#7;[#8[#:6gkvgkgkNgk.gkngkgk^gk>gk~gkgk?Hζy[~Wh ~'=&j;|h cF]kIgk)gkigkgkYgk9gkygkgkEgk%gkegkgkUgk5gkugk gkMgk-gkmgkgk]gk=gk}gkgkCgk#gkcgkgkSgk3gksgk gkKgk+gkkgkgk[gk;gk{gkgkGg:'g- o~s6iwdMeC1eKeGqeOe:@nm#w:󶳗wrDIeLLuLuLuLuLuLuLuLuLuLuLuLuLuLuLuLuLu#d\)dRdZidVd^dQdLu34P7Lu4PWfinvinNio2 -@<2 ]yeOe[@e[He[DEe[Le[B%e[Je[Fee[Ne[Ae[Ie[EUe[Me[C5e[Ke[Gue[OnmCw;o0|=:hm8ݿeXqMdTqd\q-dRqdZqmdVqd^qdQqdYq]dUqd]q=dSqd[q}dWqd_qd;Pqd;XqCd;Tqd;\q:~_~XtG4Mw5Mw5Mw5Mw5Mw5Mw5Mw5Mw5Mw5Mw5Mw5Mw5Mw5MwuMwm,糇/-2ZZZZZZZZZZZZZZZZZپM::-:ݭ:m:::ݝ:]::=:ݽ:}:::uuuuGuGuǜuǝu:[tsptrvqusw^p^t^r^v^q^u^s^wptrvqusw>p>t>r>v>q>u>s>wptrvqusw~pMo/C4Pg7tmCόߝe!Gi~tǐi~Lǒi~lǑi~\Ǔi~|'i~B'i~b'i~R'i~ 2} 2}(2}$2},2}"2}*2}&2}.2}!2})2}%2}-2}#2}+2}'2}/w{~_XSȴL?LSɴL?LȴL?LɴL?L3ȴL?L3ɴLgi~gi2=&521;\qO?߆~z~.X# 4RL#4RL#4RL#K4RL#K4RL#4RL#4RL#+4RL#+4RL#4RL#4RL#k4RL#k4RL#4RL#4RL#4RL#i~#F)HdL#4RL#4RL#4RL#[4RL#[4RL#4RL#4RL#;4RL#;4RL#4RL#4RL#{4RL#{4RL#4RL#4RL#4RL#4RL#4RL#4RL#G4RL#G4RL#4RL#4RL''ʝm$g~;(nD#E5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q}ۜ۝msnXCPPPPPPPPgkAgk!gkagkgkQgk1gkqgkB''颧gm[:?7|wk?:/=Пڪuk×w7w7ښZ8[:[9[;[8[:[9[;[_8[_:[_9[_;[8[:[9[;[?8[?:[?9[?;[8[:[9[;[؈ezl2=6bL1L[F#c#ƕ؈ezl2=6bB1LXFL"c#&؈LdzlD(c#"؈DF2=6"L(dzlD)c#*QDž=KrO?m'۶mض7mvm;vr?8;w>WuǂYd`V{,M cA s=D2XcA"s=d2XcA!s-{,(e-s{,dǂF 2XГǂA{,] 搹ǂ9e`.{,[ 摹ɂya3p n/n Een`1+X\ %en`)+XZ een`9+X^ Ven`%+XY VUen`5+X] ֐5en`-+X[ ֑uen`=+X_ 6<`*X 6Men`3*\ -en`+*Z men`;*^ ven`'*Y v]en`7*] Z]^0|k{/Xߨ;,_ łen ,8x?[-8d?-8t?.8l?{.8|?.8b?;/8R en/8V en/8Q Nen/8U Nen`!szw؋=-ss2\p=oƞ .0c炋sf3\p{.̌=\nƞ 0cW炫sf3\p{.Ό=\oƞ n0c7炛sf3\p{.͌=nƞ 0cw炻sf3\p{.ό=oƞ 0c炇5crflK3\[.ڌ-|cƖ 5cߙrflG3\[.ٌ-bƖ ~5crfl]47{y#{l?p4+] ǐ1ep,+[ Ǒqep<+_ ' ep"+X 'Iep2+\ )ep*+Z iep:,^ gep&,Y. gYep6,&s]2wYea,s]2wYea.s]d¶]vdZ. ,eaO. epv,C. |se3n2,W 瓹enp,\P …enp,\T enp ,\R ¥enp,\V enp,\Q W•enp,\U Wenp ,\S גµenp,\W דenp,P 7enp,T 7enp ,R ­enp,V enp,Q wenp,U wenp, )s{`27X +sa2Xx9 4gbo[2Vx̽.soG[2Vx̽-so[2Vx̽/so'[2VsazCl=n 3Cf,3Px{(<nj=k 3c盱 Cf"3Px{(Č=^j /3c+Cf*3Px{(ƌ=^k 3cכCf&3Px{(Ō=j o3c&Ì=i 2cw{Cf>3Px{(|=>h B?C/O'|Ԍ>f 7cO}'>Sfli3O'|֌9zy—2cD}b]&z;fK3vG#ڌ}c5cwDߙ= f|F?yϰ71^W3i3w3i0O3i2o3i1_3E< s_ģ2E<})s_c2E<}+s_2E<}O(s_2E<}O*s_ē2E<}O)s_S2E<}O+s_2E<}(s_32E<}*s_ij0"d8/H澈c"Nd8/L澈s".d%s_ĥ}e#s_ĕ}2EqW=*{'9dxN{"K枈疹'ydx^{"O枈痹)ߺ/mzc.n;ƈ1%dnxI#^Jƈ1ednxY#^Nƈ1dnxE#^IƈW1UdnxU#^MƈW15dnxM#^Kƈז1udnx]#^Oƈח1 dnxC#Hƈ71MdnxS#Lƈ71-dnxK#Jƈ1mdnx[#Nƈ1dnxG#Iƈw3]/owbg3=ex/;#[Έ3}ex?;#_Έ5AGc6l 7~}0Gq̸f3{|=>Όo}O0'q̸f3{|=>͌n}q3̸f,3{|=>njk}3q ̸f"3{|=Č_j}/3Ǘq+̸f#2Wqk̸f:3{|=h}o27q[̸f63{|=Ìؘp:o9Ћg7vq͸Cfa3ww<~Ԍј7nnu:~Ҍ[?eƭ6VϘqg͸sfy3nu:~ь[dƭ_6VǯqW͸kfx:~݌[aƭ4Voq͸;f]3nu:~ߌ[`ƭ?4Vq͸'fS3nu:܌[aƭ4V_q͸7f[3nu:ތ[`ƭ4V?qvo_vo zߨߨqw:MNFy1ddL:K-m& &n{27Ʒi2w7h{qIddR7;LN&y)ddJ7;JNyiddZ7;NNyddF7;INfyYddV7;MNɼI f'̛D2ov˼I"f'̛d2ov˼I!f'-7;)e-f'7;d줖yFN2ovғyA7;]Ny9ed.7;[Nyyed>9wjV~V>?`/q{,"'ʼb2q{,!L4>mNyeed99Y^mNVyed%9YYmNVyUed59Y]mN֐y5ed-9Y[mN֑yued=9Y_mN6y ed#9XmN6yMed39\mNy-ed+9ZmNymed;9^mNvyed'9YmNvy]ed79]mNyɼɞ2os-1ygyy799hMN2&'qC̸ɡf03nrrw99|h3wr7<9֌;gnr;ۋ{>w{NN5n'q͸p3vrw;9ӌeN6n'qs͸yf|3vrw;Ќ\dN.6n'qK͸efr3%Wq+͸Ufj3vrw;֌\gN7n'7q͸Mff3vrw;ՌfNn7n'wq;͸]fn3vrw;׌gN78N-{ͻ<&'qG̸ɣf13rfjc`l7:yΌ3F'q/̸ɗf+3nt7:ƌ|kƍN3F'ߛq̸ɏf'3nt7:ŌjƍN~3F'q?̸ɟf/3nt7:nj;kƽNh/,:KNǖyqdt\:ONǗy dtB:HN'yIdtR:LN'y)dtJwft_3h߫fVTѡ74=Ȍl M1ㆦqC̸f3nhz74=ʌm M1ㆦǚqC̸f3nhzw4=Ɍ{lwkʛ7sŽLO7^͸fL3ez2=ی{cƽL5^q/ǒ^`ƽL/4^C/_z/Ԍ^fK/7Wq+͸Ufܿj3_z/֌^gK7Ӹsmg]WC/nUz*Ō[jƭJo3^ݘa1w,oЋ>dJ6~qG͸_cfܯq3W+}Ҍ>eJ6~Ϙqg͸_sfܯy3W+}ьdJ_6~qW͸_kfܯt+}݌aJ4~oqҷ͸_;fܯ]3W+}ߌ~`J?4~qҏ͸_'fܯS3W+܌~aJ4~_qү͸_7fܯ[3W{3fޯͼ_?y~60śuQy0Fi73oԿfܨl@Fyeިl 7*Sƒyeިl9ŷ`ƛ4^ܢl|(@-&ydޢlb(D-&ydޢlr(B-ʦS|eSyyx.w'Vɦyweޝlw'Qfyweޝlw'UfS|f.佹^ܗ,y_X}%Keޘ,yk\NfEvޏzPoV_tީ]z2R6(.e˼K2R6̻%.es˼K<2R6̻'.e˼K2R̻-$.e ˼K"2R̻-&.e˼K2R̻-%.eK˼K22R̻-'.e˼K 2R̻$.e+˼K*2R̻&.e˼K2R̻%.ek˼K:2R̻'.e˼K2R̻m$.e˼K&2R̻m&6e)#-Q؋m-&eȼIٶ2oR̛moMv0&e;q̸Ifܤl3nR7)͌nM0;27i=6eq}͸G~fܣl3Qv(;Ќ{d=6eq2 ޙ7&;܌aƍɎ4dGqc͸11fܘX3nLvߍfM[2d#;ՌےfmN7d05psxg^|Kf瘹/!p_xS^ܓb3Iv$Ԍ{]f=.7dWqO+͸'Ufܓj3Iv$֌{]g=ɮ7d7qO͸'Mfܓf3Iv$Ռ{f=n7dwqO;͸']fܓn3Iv$׌{g=7dqO͸'Cfܓa3I${Ԍ{=f=7dOqO'͸'Sfܓi3I${֌{=g=ɞ7d/qO͸'Kfܓe3I7%{Ռ5[›2doqO͸';fޓwͼ'yO7|`={c3'fޓOͼ)!˛7K3oWfތͼߘy35f|g̛ߢ7>l}73fއ?̼y#2[o?"N-`ۋcl~>c'_ yq G Dro|b3މK]'y)dޅ|Jw!J]ȧyidޅ|Zw!N]ȧydޅ|Fw!I]gyYdޅ|Vw!M]ȇɼ y .̻G2B˼ y".̻g2B˼ y!.-w!/eޅ-.w!dޅyF]Ȼ2BޓyAw!]]y9eޅ|.w![]yyeޅ|>w!_]yeޅ|!w!_X]yEeވ|1"_\/ax^܆|i!_Fmȗydކ|y!_AmWydކ|e!_Es_6|e/.2)Z2-:2+g̹-_E F#[h{̶l{̶{bf75n-0?֧/]e#3ϛV-^4cl'{Om^U3[-af _![x dž[Vcf5㛯~cةSe>0K٥fv3].}nf0K_٥fv3].}of~0K?٥fv3].nf0K٥OeSk@fZSkt}j!O1e5>Ɩ٧82WfZSk|}jM O e5>&٧$2ԚTfZSkr}jM!O)e5>٧42՚VfZlUkzjq˱M ?d65\۱-Fvmy^|Q/ GJ+ |b3¦g/Z;-^ՖَVGf;Zvjh52lG'Ah.9d5vَ2њGf;ZlGk>h/dvَ2ZDf;ZlGk1h-.%d̆2#Hk3:Z֌3#Hk3:ZьV2#Hk3:ZՌV3#Hk 3:Zӌ2#Hk3:Z׌3#Hk3:Ќ62#Hk3:Ԍ63㛰y}kawveESZۛ}7"¦%C/ZŌv5'ka%lHe/W [}ŎЋV0hE 3Z:،V1ChE03Z:܌V0#hE(3Z:ڌV1chE83Z:ތVN0hE$3Z:ٌVN1ShE43Z:݌Vي3lřf,3[q8Vkf+3ي lŅf"3[qV\jf+.3ي+lŕf*3[qV\kf+3כيlōf&3[qnjw]6;k@{ݹnjoֽf>6h{ٝkq<01 [nicm{siך{z\^ka׸Ѹءew^5;ٝfvu3yefw6;ٝw{fv}3|dfw>6;ٝOgfvs3|efw6;ߘٝowfv{3dfw~6;ٝ_ofvw3efw6;ٝN9 ;h2S.;2S);X2S-;82S+;x2S/;2SN(AD2{TN,K$2TN*Md2TN.Or ߟfn:}zHo-oP~wGO+J쫒]z^&Xp6Ѩm*c**Ӂӱ2OBnᛳlrیcF؋̞̞]=+{2{VY9̞sY9̞sY9̞Y9̞Y9̞ Y̞ Y̞Y̞Y̞KY̞KY̞Y̞Y̞+Y̞+Y̞Y̞Y̞kѳrM3zVeFʵY=+5gzf\ߌѳrC3zVndFʍY=+75gff܌[ѳrK3zVneFʭY=+5ivf|ft?lr6YMV{ܭbٹ~Jlߒ[WEʽ[+5s~ftߌΕѹ@3:WdFʃ\yClaf<܌۫bAoEc^y+7{ ft<ь'ѽd3WbFS^y+O7{p3WaF3^y+6{9ft<׌ѽ|3W^`F ^y+/6{%ftԌѽr3W^aF+^y+6{5ft֌יѽz3W`fn4{7ٽ-fvV3wݻaf4{wٽ=fv^3wݻ=`f4{ٽ#fvQ3ߤ%d/620lr{{=gf7u/ٺlKfe3[{ֽffFٺlfM3{{c7g;-d}hf>2wٻOݧf33{}if5\{ٮol׷f;3vhf~2]?ٮ_lׯf73vif2]ٮl׿f= ]d=vǐٮ2KfclW{j+]d=v'ٮ2՞HflW{jO*]d=vٮ2՞JfSlW{7i{Z373ߪ7){Ѣ2[ԞMfdlQ;٢v$EXfډS-jg2[e]lQ%ERfmcc/v]{Mb>idv-Ǿ)&|g/ОSfsl@{n h#ye6=ـ2^Pf l@{a h/"Ee67%h@{I3^ʌ6eh@{Y3^Ό7h@{E3^ɌW6Uh@{U3^͌W75h@{M3^ˌ6uh@{]3^ό7 @{C3pm촑m/61-_l?4hokF#ۙшf4hhF#;шf4hjF#ڻшf4H3=D{/3{hcƷ`{_~;mƞkcõfۇnn}fGnm}fǙ> fO4w}]bT3ק>p3g>Yf6w}s]g|3Ef/6w}K]_fr3WF7aon/ךFohWێo;{[fo3~;io.3w[f3~?ho!3{f6ుቁvI3Oz#Vn/mx6`f^4 /نl+fU3maf^7 oن7l[fm3mx6gf7 نlGfc3m6|ff>7 _ن/lWfk3m6|gf7۰ͽN\>e؅.>ff~737-?o3}׌>td3>tFه2Sf:cCgl}#qe3>tƗه2ЙPf:Cgb}L"Ie3>t&و2[љRn3ZљVf+:lEgz e3Vtfي,2[љUf+:lEgبwd'޲]2ЉdvB'مN* Lf:.t ]dvSB- .t*]2idvӕمNOf:2Й]f:sBgN];vd~E:z6g΂2YHn{zYLf:уf=,eF:Kу2f=,gF:˛у f=dF:+у*f=fF:уf=eF:kу:fMgƷfg}3(;6 Bg#3،.t61 MBg33܌.t0 -/ ݺm/Z֌t3hAg3Zьtv2hAg3ZՌtv3ogw3ZÌtgF :{т^f-cF :т~f-`حl{0[so6k۔шΑf4smF':ǘ-9|\`g#lЋntN6ٍSifvt31naf74gٍ9fv\3q8n\`f7.4ٍ%fvR3qݸn\af74W-۹|Mٓe?77ُMff3q߻[ͷ_˞afS4)wٔl=f6^3rM̦<`fS4)ٔl 7)[~e/{񘙽x^3ٍ/Ɨfv+3n|kf73ߛٍƏfv'3vjfC~3[Ýʆ`/fmf31эj@f;d]f?1dSf?d[f?qdWf?d_f? dPf?dX۵ʎ4I٤l'f6S3YeN|if2?_ٟoϷf;3hf~2Q?WmZϸF^o3}׌>2T&O2T!O2T%O2T#O2T'O2TO O2TO$Q2;UO"U2[UO&U2[UO!U2[UO%Urz3wV=h/C^ˑ%)ٗhK=먗mg٘zSr:2;NFPP]Pݒ١١-CuGfJfZfFf=ev]f9dvSfF#z?^Of{e^@f{e^Hf{e^Df{Ee^Lf{e^Bf{%e^JmX/m^f6 5^n?+|+WZ5nW5Sjft^݌NkѩzM3:UeFT5Szft^ߌNѩzC3:UodFTItT^4̌&՛Ѥz 3ToiFhR]1۰bآzF{j|5 2'NfٌԻٖ]L~=/6X=C/SmFw}Nݩ3;fc0;ft>Ȍѝ3SjFwN}ݩ0;>|TE/:TcFchQ}-7E f>ь'Ѣd3ZTbFShQ}-O7Ep3ZTaF3Q}M6K9ft>׌.Ѧ|3u/4{|qcF6^23{u^]if2WW٫kյf:3{u^hfn2W7Xbc6Naf4Sw٩=f| vgW{ٙ̃f!3yČoQcv٥}e6CϘ١gsfvy3;zdf^6C١Wkfvh-zaf4Io٤l;f6]3Mz&}`f>4I٤l'f6S3M&}af4I_٤l7f6[3M&`f~4O?Xlrr[Naf4S٩?fv_3: T3N5T3N5cT3N5clU3\<ިj[2L([D2L,[$2L*]drofr3^M`5n wƎ=d/ [͌2$]2"mf5s e׳WM WM(WM$WM,WM"WM*WM&WM.WM!WMKfRf^5j*jjjj2{d٫fvj٫fNj٫fnj٫f^j٫f~j٫fAj٫faj٫fQj٫fqj٫fIj٬fijٱfYjMcjV٭f%jV6[*ftYՌn5ѭfu3լaF5Vj6[:fY׌~5Ѱf}3l'լj62WfČ^5٬Fm67c6eFʼuk5lEǚXkv4cNkٻKFd.jEhUjgF=hUj6U>f׌V5Ѫf3Z`FdFhUsj5Uaf9܌V5GѪH3ZeFhUsj5Uqf9ތV5'ѪD3Z՜dFhUsjN5Uif9݌V5hUsj4UYf9یV5ѫ\3Y؆[5SͅftN]lf.1S٩fv 3;uN]mf1Sך٩Vm7٬/{u^bfn5W٬vm0srq߱ENcg9){ˆ4!ِl'f6S3 ̆|afG4Ȧ\d/ ̆|ofC~0!?ِlf63 ̆nfC0!ّlf3{=Iw4=.'1d;̦tǒ|Sv6؝Gur hFwN*d6;ftٌ2ѝJf3SlFwN+d6;ftgٌ2ѝIf33lFw*d6;Lf3ftCF2эe6lF7ٌn&\f3ft[2-e6ٌۖnGf3ftk62lF'A.7Nr+l ݹd;6tن2НOflCwm.( ݅d6tن2]Lfцfm.eFKц2wQ-zтrf4߁+ߕF zbjfaZfkczfn`FfnbffnaVf[ncvfۛ`Nf;b`nw4[>C/~}w5όzw3~w4=Ȍz`3~Cw5=̌zp3~#io(3G[?ƌoflבo3'{?Ɍo.6ktoz3]i,3g>f3w} ]_h"3f/3w}+]_i*3Wf3w}]h&37fo3w};]i.3w}ڽnj:7?7m?doa3ۏ~cf7'm?eoi3Ϙ~sf7ߦܾh/ۯ~Ռk; x⻴˽ʍԑ]8^vC3;|bf>5فfvK3;|cf5ߙفfvG3;bf~5فfvO3;cf5&ev7ƔفX2; zܫ'_o7~oBD2e{&M&ߛ\o7~oJT2e{M'ߛ^77noF3.[f*.k{ܸoqϾC+z^22+.g{-3zܥ [hGَ^#vz2َ2ћCf;zslGo.-yd7vَ2[@f;z lGo!-,Edvَ2[Bf;zKlGo)-mF;z˘ю޲f-oF;z+юފflƷnoz† Gou3[Ì~4Gom3[nj~5Go}3~64Goc3Č~65Gos3Œ4㛹yIo[3zΌ7)nhvekF᛹;vآl MoO3zˌ6-*{؝=lM6zќAflFszќޡf4wnFszGќޑf4wmFszǘќޱf4woFsz'ќމf4wlFszќީf4wnFszhN 3;efs69ٜslyf6|3s͹\dƷtb3a/s͹\afs49Wٜl5f6Z3s͹`fsn497ٜl-f6V3s͹af{4?wٟ=f^3s ߌ)[N=d&ݽ.=j7r1zQO٨l3f|/5?/ٮe^4[;b}z>ffF٧fM3}z>cf5O٧fC3}>}bf>5O٧fK3}>}cf5Oߙ٧fG3ٌo/fnOr{٧fO3}>cf5O248> .Oc248> -O248> /O248> N,O248w v $58ըZxp3#h 258v $_3,258~ &adl0{& QF&d^m sr u{ѳ̞ V2{6X`#g]=̞ .gs2{68̞ -?J "DHK&O;u=O{کu|oggg9{kӕϬ3khᙵk3Zxf-<YugVh4Zxf-<YF Ϭg֩3h2ZxfYF Ӭ%J>(|z3F Ϭk-aha Xa8aJw0CJ >0#J >0cJ >0J >0SJ >03J >0sJ >p J pKJ +J kJ 4weJ˾(\>V=}RZm}QZ]}SZ}}?PZC}?RZc}?QZS}?SZs}PZK}RZk}QZ[}SZ{}PZJ OJ /Js?J=qWZw¸(-¸) 8;h01Zg-!qv8;l0Ύ-F 8{ha7Zg'I-¸+ikvhUZ9q8{ha=f0-ǍF Iqvha=e0Ξ6Zg-F Yq8{ha]2Zg/-KF eq9{hnm(z:{hamή--umvٮ:3ZXgW5u:{hag7ZXg-F :i>4ZXg-'F Su:en-ύ eo]0ξ8F k* k) k+ ( * ) + ( * ) + ( * ) + [( [*׾;a'|/UٷU};!mDPg>.J>J>nJ>J>J>J>^J>J>>J>J>~J>J>2aa@a a`aaPa0a}Ұ~Ұ~~G) G+ͽ~ҏIa'\4\4 d?Qih?Iih?Yih?Eih?Uih?Mih?]ih?Cih?Sih?Kih_4\4\4\4\4\Sih?_ih@ihPihHihXihDihTihLih\i+foN ~(-,|)-,|7(-,|7)-,|·(-,|·)-,|w(-,|w)-,|(=~ҲG^a&^pJseV~(`aQZQSZqPZIRZiQZYSZy_PZE_RZe_QZU_SZuPZ?J ?[J ?;J ?{J CJs׶'p'J GpgJ GpJ GpWJ Gp7J GpwJ GpJ GWiIi蟕Ei_Miߕ^pJ Gp_JQ'` mswd?F=gp -tn:aNh5ZČn:F 7M'apI-tRF 7ANhᦓ1Zdn:CF ;amNNi W'tƌ~:ymθҲ ~?p)-\u:F WNh3kpՙ3Z-\uJF W΢Ugh᪳lpY1Z-\u֌:F W Nh᪳ip2Zl-\u*F Whc-\ukp:UNh᪳cp5Zmsv>|yܟ'u:GF ccΉXhasf0i-uF csNhasXjF c-ua0ֹXZF ck-uc0ֹXzF c-un`0ֹ0ֹ0ֹ0ֹ^`p:7W:P:T:R:V:Q:* S* S) S+ S;( S;* S;) S;+ S( S* S) W+}۹~X᪰:V{sԋOx_ix\4IiFW-J-nJ-J-J-J-^J-J->J-J-~J-J-2@ `P0{p}p}p}p}4hX8J-J- J-J-IJ-J-)J.J0iJsu4;Lv g) +__s_s__*-z¯(-z¯)-z¯(-z¯)-z¯W(-z¯W)- {g]3a­puJ ^p J ިpMJ ެp-J ުpmJ ޮpJ ީp]J ޭ4w\=J^*f]=QSZ~QW*-¨*-oQRZaQQZQQSZqQPZIQRZiQQZYQSZyQ_PZEQ_RZeQ_QZUQ_SZuQPZ?J 0[J 0;J p{Jsu¬+S#Q?VZQ?UZ3Q?WZ QTZ+QVZQUZ;QWZQ0J 0J]/JN+zz RZQTZ/a0ZFy=F ^Q^(/d07Z免FyS^h{';0 $/a0K-LRF AI^ha1Ze&yCF aI^ha7b05Z-LF qIބ$ohaW0ZM-L&y3F $oha7g0ɛ7Z䕌&y F EIޒ$ohab0[5Z-L֍.yFܱҲ?6ZU6y&6Z9F yF ]؞)a?y-aVyJ"4,.QyWSyWWyPyTyRyVyQw ,s.>w}wwCw#wcwwSw3wsw wKw+wkwwƻƻƻƻƻƻƻƻƻƻƻƻƻƻƻƻƻƻƻ0ǻLif {7{Ұ{Ұ{40awҰ{Ұ{Ұ{Ұ{Ұ{Ұ{Ұ{Ұ{ҰaxaaDa$ad{aŧpiJ WpJ WpYJ WPZl+QZ\+SZJsqLz C^0EJ C^0%J C^0eJ C^0J C^0UJ C^05J C^0uJ C^0 J Cި0MJ Cެ0-J Cު0mJ Cޮ0J Cީ0]J Cޭ0=J Cޫ0俔Oia\0J G>4weᅰ]|DiG|LiǕ|Bi'|Jiȧ|Fig|Ni|Ai|Iiȗ|EiW|MiוW"yz 7p[J 7p;J 7p{J 7pJ 7~4wcˍp'J '~pgJ '~pJ '~pWJ '~p7J '~pwJ '~pB]0)=GUZzoJK]iTZz_JՀՠ竽FKWq׭WXQ1FKWFKWFKWFKWSFKWޯޯfޯfޯ-_6Zz3Zz:b~uhռqF{oKK=i׫3FKWFKWg^-^7ZzZ2.[=XzIoWޮ.-]]1Zzjvuh eJ_J/E={Պ{Uh齪m^1Zz-WUjMiz4WUޫ)MUJ{պ_4wjBI]|o#[Diz4V=S~ߪm[4VDiz5ՕߪP~^Siz-굕ߪQ~^WiUvg7鱋Oz 7RXizM7S{fYKz~Riz+ꭕQ~^4TS]YzGEzBNJꝕ^ wUZznJK/]i{(-pO½^^8VO_dJKdAJKd!JKdaJK/WZp%PZH%RZh%QZX7VُzJd;N~~܇Sw識7(-J{y^ެ(-J{y^ޮw(͝N<'VZ{w^Nާ+-J|@iy'TZ+-CJ;]QS|ߨ'?x)O+-^FiJןSZ__PQO+J_UZו?JTZ])-_i@~?VZ|Os_(-^RiȎe>ViwJϿWZ|*->QiOJVZ|_w竔]|O{s37N;?o^ -"FKR{-f^0Zjōk Zh2Zj -FK__gmHi 5J]TQjJSSmLij啦ڸTPjJSS45զڴߛUZ9WZw-(-עw-)-ײw(͝4w~]9mJ(-mU?kJO[JTZCo9RZcN>ZK)Ku5w]]i}PݾvM 7\+-J︡;n+^{Λ);^ҷ{+ZiQZ~Jュ]kugQiYwRZ~֝uoϹw{(-?Jϸs4w}s艹s.SZ~@g=HiVD!|zx3.WZ~Õ3SG+-cJsO=w<^ig4~?A=ykOw>QQ{ j2G/Oas\_ZY`~YT ~AN`,`=fM`Y/s?`0.w6ρm:p,(0'cp"@=W~ 99 9^* ~!}xw~: ^s ܙ܃mW3;x=:^` Gv{]=-~Y氛ba cثNNyAa]y'AsdAKd.y?A`9y/AEAAAwAGA A;H  >6H w  Kw[S0A< ~?P=< ;v:]u9Ȯd?{H8Ak4d k2>d qCO?=L}Co=L=܃=xþу=ڃ=ڃ=ڃ=ڃ=ڃ=ڃ=ڃ=ڃ=ڃ=ڃ=ڃ=ڃ=ڃ=ڃ=ڃ=ڃ=ڃ=ڃ=YK=xý{z;Zw2C{\G/'0nŠޜ]/ˆ^K{B/\ 䯗…^~ z^v^z~ev2{oa2{{̮^fP/3P Ͻv/K/ýз/弒Z9{rr]rW%sI{w~?-{z\/^^2K/ým/=KzO}0>xڇ?}ǮGO3c> `;X}>_}>`_cK3C~ϳCyL[80|a߫jk?}dye{7}r>q_#}t>ѷ}ed#}dLdLdLd<`;Kȁ!Z߇C̣3(b1gB!;e0%RУ!rCφewb ѿ!2b >B4DWB"!( 1wBs&s; wCx5z5!< !fQ1Bzyy1B !U6?oCd=DCp!KC37Cp37Cp3 ]>~aA?|~~~~~~< ̄|~z6y?l 6Æ~O~x?>m?g?l W~Y?É~8B?>S?>S?>S?>S?>_ua SƧ0>)Oa| SƧ0>)Oa| SfjY)a| È0 _f/ga| 3_̗0 3_̗0%| 3_̗0|Ã0% 1L/L_*&03'Vucy<3L&d2~m!a|s\d0\0+arr`r&_aWf ;azYa_""KRaVEx9aGx9aGx9aG?#d5r=?xaG?C"0$?"d7BV#!=)("p!"p!"p!"p!"p!#p BG;g"xE._<EiFiY0"5gX"̲?8l~F`oFaoDaoFaoFqQ<(.ZG̿(/Jޣ9Z2 (GtNGtGauwQz Jx(^G:Qux(^G:Qux(^G:Qux(^GjxQfWlF/4Q4Q|wxeo7b 1{C!^b÷{C!W17b 1{Cb2co7`i v`f9co7b 1{C fƞó,ƾ1Xc~/܊|,=ûi bx+_11<12#1||1}>>>>>>>>>>>>>>:pvy4̤f3i <~6=li,Y dq,8@74wx7@; x6@O^8ǣ8o)N8S)N8S)NO8=b^QƙCqz2e978g3hhӣqz4N&7qfR(N/WƙU+qrgvřq8s,qg?8~ƙMqfR|5ά8>N>̝883?̏383d2N&d2N&d2I  r r r r r r r r rLMOyx'$!I|HAy$I2$cIr$SI2$SIORԟ$'?IIOR_簷$oqK$KQ%ZG$K$3;ɜN2.IR,o)YK_ 8=S.)v{h 5U4E.SxbGJh*{j?6ŻH1SP)v;T*bJ1SPeSR)K}6>bMnR&cS)8bMMYM_S4KS)X))>lJh5Ů⮔I)z?ŻJ+ÜOR̪H H1Ş.;J^R̥!{H H1S8;I_!)S{A†Af j4{= y?AA|0b ; wA + rdOɃx. „Ax0u ,dF 2Qܛ7 rovAf ~4]`?ȌAķA9>\dA>H psi 1tR?ƃ4 M,])MiOSԟ4?MiOSԟ4?MiOSL4{P=(iz?i?ii8i8i8iHÁ49KKu if1|c3 ̰sgع33C/fY/Kedxŷ,¶,߲,39LYϲ̙,ewaNg=Y2.YfvefgY5=aF9#0gF6Bo#6Bo#6Bo#6Bo#6Bo#o#6Bo#6Bo#6Bo#6Bo#6BQ|%_j~%Kg~FQ23Jofތ›Qx3 oF(7fR(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(QQ1zi^#cx1F&#cdbL121F&#cdbL1sh94c1ƘCc̡1cDcDcGr?cAcAcAcAcAcAcAcc0g 13s`9c0g 1cG1zdcV1ǘcGaN$'y2LJ<ȓ)Oy|8>Ïq1?8y'+de8Y'+deq88qivǧqr3Nngggggggggofofofofo8\puq:/df/b/b/b/&b/&b/&b/&b/&b/&b/&b/&bo&aLPOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPO=gd>OrOd.OpċIg;$$x;$=4,dO2'Óc< $Izg2ܝddddddddddddddddddddNL’II|dddddddd'$2?j;$wIPܡ&a&PXR]`g)0a'),pHH pG p@H|=XR#fMYS`5fMYS`5>RxMS`?)U ErT GrT GrT GrT GrT`R,R d@ d@ p ]\`N`Ng v;`}R`_)`O`\M)r5Eyb"CSdh M)24wSdh M)24Em Ϧ"CSdh M)24E£)|"CSdh M)24E"CSdh M)hy4s`^L)꟢)꟢)꟢)꟢)꟢)ꟺmLi3 v80v4|~=Mn=gdelLNNNNNNNNNNsw?B`/b/b/b/b/b/b/b,̓y00000000000000000000000O J_CJ0OKpCJP_(((((ҹ`F;p Ɩ`G oJxS›ޔ7%QŸ?%)----1oJ0ļ)ļ)1oJ̛ļ)1oJ̛ļ)ļ)1oJ̛ľVb_+Z}m}mYY`,0kfYY( tYY`,0kffYYffYY`,0k5 ̚ffY@ Կ@ Կ@ Կ@ Կ@ Կ@ Կ@ Կ@ Կ@ Կ@ Կ@ Կ@ Կ@ Կ@ Կ@ Կ@ Կ@ԿH̘E2}f,'"}H,Ed>YOEd>YOEd\,'da,,EH"9X$`,Ed>YOEdaaaaaawE"}///////K/Kb\,%rD.X"Kb\,%rD.X"Kb\,%rD.X"Kb\,%rD.X"Kb\,~,~,~,~,~,~,X"KԿDKԿDKKc{>,,,,,,%!!dd=d,Ðe ?ر ;2X&c?2,2,2,2e3g,sY>̮}f2we.Wy牜ryleeeeeeee2L.//ǖǖd}l/b/b/b/VaVaVaVaVaV9v+V׭0WWعVطVZ}nWWWWWWWWWWWWWWWrB.V X!+ yX/VbX/VJ_*}J_*}J_*}J_*ŠUrJV*9X%`X7V*J*J*J*J*J*J*JkkkkkFYX# kkda,5FYX# kda,5v\c_#kxF>X#kc=| _e _e _e _e _e _;w5555r?gv50YisY.NԿNԿNԿNԿNԿAԿAԿAԿAԿAԿAԿAԿAl0W79 < < < < < < < < < < < < <؀A6C7C7%K~)/eYeYeYeY_K~)/eL2R_P_K~)/eL2RWG(ezeQf(#e(G?QƏ2~e(G?xQƋ2^e(E(Î2}QeQfL6xR!eQ&eQ&eloo{mwmwm‘M|děMM S6h6h6h6h6h6h6h6h6h6h6h6h~l&e|dl2_6/̗M&eIN6a&e|dl2_7M&ؤ_6M<٤_6c?6c?6c~٢_-e~٢_-e -e~-e~ق[b ^l-ze^٢W-ze^٢W-ze^٢W-zel+[[s ` ` ` ` ` ` ` ` ` `cllclclcll?Clklkl/6Mlm2Mlo3kmf6;6;6sv9 ;m6sv9͌fn3c̖m63v͌ݦ_x,fl3K%̒mf6dY,fl3cmf63vMl'x 76ئOm 7 fffI~/BT 3rRaV?zBT RW*J^+zBT RW*J^+zBT RW*J^+zBTITITITITITITITITITBN*BN*Jo*RaG?*aEF,2bXd"#Xx`၅Xx`၅Xx`၅Xx`၅Xx`၅Xx`၅Xx`၅Xx`၅Xx`၅Xx`၅Xx`၅Xx`  Zxa3=c Xdb,f}fl2a}̆6b+6b+6b+6b+6b+6bㅍ6^xaㅍ6^xaㅍ6^xaㅍ6^Ob3_l|/6~-_7YcC6'c3slf!_6~e㗍W6'lb&/yqȋC^{NzxvtrqNonm<~5uGoƣ.Q=x>`^^\Z~,~t'tt3t t~Pt?]w;$III{I;II;II;I{I`j{`j;`j`j{`j;`j`j;`j2ަ.|9~/~tt;\tÇ~y~ y~ y~ y~ˏC$/*? ~o~t??SIEEsEsEo|w}.|~:Y9k$'3 '3&3&3ϼƣgRQsxLe<~1u?c ]<~϶g1Kt?~+=LTzL3E*=O~&t?oK7χěg3g/RćA3JgQwl:~^w?F7g},kfרV|)~~w?ÉD5~w?+Dǃt?!#Ϝ/r\'o aRË^5E /jxQË^5E /jxQË^5E /jxQËed=u_vEvEvF9;;g;UNSv;v՝s\޺sm퐓ś]%'KNv.9%'d쒓]rKNv.9%'d쒓]|%'ԿKԿKԿKԿKԿKԿKԿKԿKԿKԿKԿKԿKԿKԿKԿKԿKԿKԿKԿKԿKԿKԿG{ԿG{ԿG{ԿG{ԿG{a<쑇=G\p#{b\ry# {ܘss,ݻNq8<3=d9̖=f 9/弒Ì{#筜wr˹Þ1Χ8ﱳﱏ1cvu{w=2{̗=1/>}v}}zd_1x?2n>}wxϬ~n~~Os~n9ns~|~nn>>>swlln}l]l=l=l=l>w}|u}|Ǐ}Ǐ}Ǐ}Ǐ8888~{8 dlq@68 dlq@68 dlsp;O>9OxPg稳sahQg稳sCQg稳s9uv:F7`uv:VguH]Vg`uv:;XU^[^[gwչֹA밢uPw_N6dN6dN6dN6dN6dN6dN6dN6d.Vou@4ݷA~p fP,5Ax S Pk0pwpwpsoooooooooAdAdAdAdAdAxjjjjjjjpkpksՅjqMp9ܤ&7IMoRߤ&7IMoRߤ&7IMoRd4&}դU4J4J4J4J4J4R4N4N4N4N4i&^4Q62$SM2$SMiMo(+p7xs7xs7xs7xs7xs7xs7xs7xs9ěC9ěC9ěC9ěC9ěCz^;Cz^;Cz^;Cz^;ˇxs7xs7xs7xs7xs7xs7xsH_!!!}u0{ߡxA_OGqD?Gxr3#Xt`,:EG#Xt`|{q>>|}#G܇#2r}#G܇O?a1 9c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?c?w18~Ïcq ?18~Ïcz瘞9~Ïcz|_ucO =rBN =rB#' ''''f |l>a60O'f |l>a60O'f 9!'0rCN` 9!'p,pBN Y8! 'd,pBN Y8a=8888#)^)^)^)^‹S|8<)>ŒS8px 7N)~)~)~)~)~)~)~)~)~)~)8pnSq 7N)8pnSq 7N)8pnSq<>eW;c1wϘgz\=cW;cW;cW;cW;cW;cW;#gpgxpFy8#gFgFgFgFgFgFgFgFgFgFgFgFgFgFgFgFgFgFg9rgxpgxpgxp-'Ct}ҡO:I>'Ct}ҡO:I>'XсCtYCtѡ?:|谇wxavfiYavfiYavfiYavCt=ҡG:H#zzzzp ^\%xq ^\aBr` B4`L$B @QQqz^{kz5 ((9(*DFIM bg3^ĺbXC!~u?ĺbXC!~u?ĺbv"NډX;k'bDv"Nډ>ߐo7-|6"vw;|7ߋ/}X>wD,&\K{"+buWĺ7c3;c3;c3X888888888888888888888888888,838qqqq!a   $D~$G~$G~$G~$G~$G~$G~$G~$G? ߏK34K34K34K34C33C62"/2"/2"/2"/2"/2"/2"?33?3lJoffoffoffoffKfF\dggeg&fg&fgx㑏G>x㐏A>cA{{{{{{L>cA>cA>cA>cA>cA>cEX`PA`PA`PA㓋-kmmm<mQGxQGxt~n)K K K V?N)>pl`T` o *;U` 8Nة;UY]MXMnMMM!M!M!M!M!M!MNM!rM!f|[ȷ|[ȷ|[ȷxmm!m!m!m!NbTQ!FbS(;|[K!8m!m!m!bP_c +Rhw NڞB~)B~)rEn"7~ѿ;En"\۾m_-ESĹE';Eo"w\E~IE~\$E~HQERCH>](ҧ";]ddHVq|"("("("7LH1E:USE:UM?VaTQFE"wL1so1so1so1so1so1c1S1S1S1S1S1SS:US:US:US:UOSKcS1ŘsLK1NK1K1K1J1QE1XcP/R/2R/?YX K K K K K Kx `P"#%2RC`QE %X`QE %X`QE %X`QE %X`QE %X`QE %X`QE %X`QE %X`QE %X`QE %X`QE %X`QRX)XbQ+P*P*P*P*xK)oQʷnR-R-R-R-uۖmKݶnR[-u痺kKݳR})š;JTWJ;J;J;J;J;J;J;J;J;KT/J;K;K;˸;˸;˸;˸;˸;˸;˸ 2,2,2,2,2,2,2,2,2,2,2,àM_NeQ&eQeQeQeQ/{>}_H{̭VV+>([geYƟeYΟYΟ2QΟYΟYΟYΟY.YΟQYΟYΟXE^E^EEy'帔H9G|G|XK9&~rm,;֖XΡZΡZΡZΡzR.Q.Q.Q.Q.Q.Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!Q!TG|TG|TG|TGQ!Q!QrQQQQQQQQA\T7|T`QxTQaO*lm#vŽTؑ ;RiG*H#QQQQvҍVQQQQQQQQ2Q)2Q)2Q)Y7p%&TbRI?L%VI%NSU%VXUbUU%VXUrITSM%6R)+R)+R)+Rl?^%3U2S%3U2S%3U2S%3U2S%3U2S%3U2S%3U2S%3U2S%3U2S%3U2S%3U2S%3U2S%3U2S%3U2S%3U2S%3U2S%3U2S%3U2S%3U2SO>UTSKU8TPCU8TPCU8TPCU8TPCU8TPCT{Tۗj mLݭƣZfmo5&՘TcRI5&՘TcRI5&՘TcRI5&՘TcRI5&՘TcRI5&՘TcRI5&՘TcRI5&՘TcRI5&՘TcRI5&՘TcRI5&՘TcRI5&՘Tw6<[?j=֣j=֣j=6;jlp F5SK{H{=R÷5TKޭޭޭޭwkZnq8jܭ5wk ָ[kܭ5aqSݩ;5vP؝ScwjNݩ;5v_jx,jNݩ;5v؝ScwjtڝZSkwjeڝZSkwjN-vkk9SjdQ+Q+Rk{jmO=ڞZSkojdnZ7Y׺jyֺjdnZ7Y-ԺjdnZ7YMV&uk[kdnZ7YMV&Zy :yc\qlRǵu2R'#u2R'#u2R'#un:٨sֹYO>u[ǹu[ǹuqnqnqn֑XPqnqnqn:;\gpuZgpuv:TLKwuR+uR+uRgslNۜz>9xPosۜzSosۜzS__________?H=\R/+:S'|R'|R'|R'|R'|R'|R'|R'|R#[[ϱ[ϱ[ϱ[ϱ `cA>lL6ؘ>m>mh>m>mhЙiЙiNmNmNmNmNmNm;0i;;;;;;;;;;;;;;Q_u;;;;;Q7FlFlFlFlFlFlFlFlFoFoFoFoFoFoFoFoFoFoFhĠFhFhFhFhFӰ&h&h%M<M<M<M<M<M~6mğM~6=l߳MĝMĝMĝMĝMĝM:ğMğMѤMğMğMğMğMğMğMX4D^4ߏOi¦I6pi¥I6dI6dI6dI6dI6eY6eY6eY6eY6eY6eY6eY6eY6eY6eY6eY6eY6eY6eY6eY6eY6eY6eY6eY6eY6eY6eY6eY6eY6hƠ[[[~8g|G|G|G|G|G|G|G|G|G|G|G|GlFlFlFlFlFlFlF ih"-žI}m-:Ң#-:Ң#-:Ң#-:Ң#a:Ҫ#xڑVlť՞bӪ3vG[mK+6նږVj[ZmKmi-նږVj[ZmKmi-նږVj[ZmKҶMmiVjOZmkmmնVj[[mk+.նViնVնVj[[mkmmmͶ6LڰhàۼۼۼۼۼۼۼۼۼۼdMOHi#mv͎mmfKli-mm͖6[fKli-mmfKli6[fKli-mm͖6[fK3  g@?Џ~#G@?Џ~#G+8i3xC@# F7 '> )SN8p )SN8p )SN8p )SN8pjws9hוv.iws9nv7Ghws9vF{ݽhwohwo7v,GjvovovovovovovovovovovoוvNmחv}ivivivi* 됕Y鐕Y鐕Y鐕Y鐕Y鐕Y鐕Y鐕Y鐕Y鐕Y鐕Y鐕:p:p:p:p:p:p:p3:lKotivivi8tЁC8t@[a8tЉC'8tЉC'8tЉC'8tЉC}ӾvNi_;ktJ}i_;uS/:ӾvNi_;k}ӾvNi_;k}ӾvN :k}i_;k}ӾvNi_k}']vˆt.r_t/].E}]]]]% ]e[lkm.]< ]e[lkm]˶v.e[lkm]ˮv%]6 .څG]xtхG]xtхG]xtхG]xtэG7xtэG7xtэG7xtэG7xtэG7xtэGC>C>C>C>C>^Չ^Չ>Ӊ>tO'tO'tO'tO'tO'tO'tO'tO'tO'tO'tO'tO'tO'tO'tO'tO'tO'tO'tO't#8#88> 0à> 0à> 0à_ ЯzѯzѯzѯzѯzѯzяCۡ~C~w?e?W~o7f췛vn~o7f췛vn~vn~ϓv_7~C~w?O~yw?uCl6s@'tb@'tb@'tb@'tb@Ћ,pAAԉAԉAԉAԉA`P'ݑz1tKà,  ,  ,  , W0ȗ21ș9ș9ș9ș9ș9ș9ș9ș9ș9ș9ș9ș|9ȗ|9ȗ|9ȗ|9ȗ|9ȗ|9ȗ|9(C|9ėC6cH7tcH7tcH7tcH7db!<bHaHaHaHa(!!!!!!!!!!!!!!r? }>{r=9rO'ܓC!{r+ܓCIQ ֍a֍a֍a֍a֍auc^ Ű^ ۋa{1l/Űb~c1ú121ú1ú1ú18 İL Ȱ Ȱ Ȱ Ȱ Ȱ Ȱ Ȱ Ȱ Ȱ Ȱ Ȱ Ȱ Ȱ Ȱ ȈȈȈȈȈȈLĈLĈLĈLĈ~1##:2##21##:2—#1—#|9—#|9#&#:2LjȈȈȈȈȈȈȈȈȈȈȈȈȈȈȨȨȨȨȨڏQ1ʙc~ڏQwըj]5QQQQQQ=QQQQQQQQQQQQQQQQ111111111c 1<ưӓ1w;s̝9Ɲc9ƙc9c1gȘcx1cx1cx1cx1cx1cx1cx1cx18x18x18x18x1Ǹs8&1/1.qqqqqLc\6Ʊbq,Ʊbq,Ʊbq,Ʊbq,Ʊbq,Ʊbq,Ʊbq,Ʊbq,&b ,&b ,&b ,&G'c <&cžLؓ {2#:2#:2L`0LLȄ\L`1<:ޚpoM&[ ք{k½5ޚpoM&[ ք{k½5ޚpoM&[ ք{k½5ޚpoM&[6G|?3?sK>,&XL3&2ΘIɸߏK'qԛIԛIԛIԛIƤ[cI$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$NNNNNN)L씝);;eg씮LɔLɔLɔLɔLȔ;cʝ1S1ÔLŧb ),b ),b ),b ),S)Ɣ{cʽ1ޘroL7S)Ɣ{cʽ1ޘroL72lڽ1ޘvoL7cZ>cZ>cZ>+Lʹ16fLۘiiNii٘i٘i٘i٘dZ6ci3,>3,>3,>3,>b3,6b3,6b3,6b3˧|:˧|:˧|:˧|:˧|:˧|:ͬb33:33:33:33xb03:33:339 0`9 0`9 0`9 d?c?c?c?dd?c?cNWl̜1s6fCcζ9,^{e9K,᳄>K,᳄ϒ ^K6x/%dlϒY%Ld %}KzGKz-ђ-ʒ,ʒ,ʒ,ʒ,.q~ _v/ʲ,ɲ,se,M-Ӗiz̳<̳<̳<_cen] n nd <6c <6c <6bo' Ȇ{d=Æl~ݰvxo N 9b ,6pn,ܰ5flؚ [ak6lٰ͆5flؚ 7ۆmͶXl`Xl`&Xl7ueo?W|vf٘Mɯ6flژMic6m̦bMnMnݔMyaS6aS6aS6#MȦ{dMnM^ԙMؔNtm~lⲉ&.lⲉ&.lⲉ&.lⲉ&.lⲉ&.lᲅ˖lȖlȖlȖlȖlȖlȖlȖl'gwb| _/͖llƖllƖlla&[l᱅[ .[6gKN8eS8eKoxeKwtgKwtgKwp-7N[V[XmaV[XmaV[XmaVAX b*U VAX b*U VAX b*U VAX b*U VAX b*CAl:u(h97(3A[EA[ .AӮ>̞>Ӟ>Ӟʞʞʞ᳇{Þ>Ӟ>Ӟ>Ӟ>Ӟ>Ӟ>Ӟ ۓ=,aݷ۳{=wߞoݷ{{{vk}{=wmeO^eO^eO^eO^eO^eO^b},b},b},b},b},b},b},b}n}yؗ}Yؗ}Yؗ}Yؗ}Yؗ}Y`_~?/c>&con}w ﻅ;iwv_>qe}\8-|>w΁;s9ps9zt%zs3r9ps9w΁;s9ps92r9w΁{;pz}s9p`qpq)r`p9r`_@^@^@^@^@^~9~9C~9C\݀rs5!!!!!!!!!!!!!!!!!!!F|rh9dC9C|9C|9C|9C|909#<8ҧ#9#L09#L09#L09#L09#L09#L09#L09#L09ˑ :#Y9#=:#]:ҥ#]:H5G~?tG~[evyرѱȱѱ1ztGztGx1&ǘcr1&ǘcr1&ǘcr3Ӿ/-{6 m->====LN ǜ .'r .'r .'r .'r .'r &'x=p=љ ʉʉʉ￟>9Wͩܜͩܜͩܜͩܜͩܜͩܜ̜ͩ)sʿ{ʿ{ʿ2s^9S9եS]:TNuTN9ѧ<|ç<|ç<|ç<|ç<|ç~-rOtʹr*/r).r*+SY9S7˩StjNѩ=:gǜqǜqǜqǜq˙>ҙ.ҙ.ҙ.ҙ.r&gar&gn& 3w˙rn9s[-g3}n9Ig6˙>3^939ӡ3y9ӡ3L09sÝqǙϙ|ar&#g2u92r.#2r9\v1:s1:s1:s1:s1:s1:s9s>s>׫s9\~\~\~\~&ۤs9.u.?sչυ\`uV޻½w޻O l.|so~tN8]tN8]tN8]tN8]tN8]tN l. l..d y .肋.肋.xB.dB.dB.d .0 .0 ar 6!NSHB܄&MHnB{8! a$I/p qs(On V! C~Cx;wTC~G _HBҿ/$S! _HBҿ/!E qR-rlYȎ8;!!tC< }yBn' y.9钏.R.1K.1K]KK.KK\.1ҭ|)G\K7<]ڳK{vחҞ]bs)Sw%o_%o_%o_%o_%F]bt%F]btѥ]ӥ=K.qKvQtO+ҹ+J߮8_+;vsW]ݕ]Օ\]uw֕YW~g]++W +W2sϕ\̕\̕\.W\&WvoWvoWvoWvoW\ܕ]']q']q']asIWtIWtIW|t%7W2skW+lQ߰klZ׮95.ھ_kzvm߯}Z\'dek8bpwap;wsΝw~?wN^NN;ӥ;L0;L0;L0;L0;L0;L0;L0;L0;>;Y;Y;Y;Y;Awzs'N˰{>{L1{L1O{q{ݹ?|r~to=.{ϻ{ϻ{ϻ{ϻtomV{[}o=ޭ|Vw+ʽʽʽʽʽʽʽ<ʃ<ʃ<.))) #)<d'/ / / / / / / / / / / / / / /fypy7Gɣ}>yG3'yҙ'yҙ'xҙ'yҙ'yҙ'y 'px 'px 'px 'px 'px'yx'YxF~?x'x'x'x'x'x'x'x'x'x'x'x'x'x'xgxgxgxgxgxg3&ϘyvyqO^'/.y.y.y >/ >/ >/ >/ >/n7ʋϋɋ Ǿp Ǿp Ǿ Ͼ 6/ؼ` 6/ؼ` 6/ؼ` 6/ؼ` 6/ؼ`+6ؼb+6ؼb+6ؼb+.˫yůnW;j_~ïv޼W;j_ܼ+.+.b+r+r+8ʫbKU^1yWL^1yWzAؼr+׼r+׼r+׼r+׼r Uq׼q׼q׼q׼q׼q͛}~o͝Nys(o7ovo\߈oؼ7[fssl-~ӣ7[&+oؼɛɛț-~ox7[fl-~o8Ǽɛ7yox?*km;߼;߼̻߇~}}{+>7MYefywY,w7ʻ};&c;&c;&cn9S9S9S]V]Fe]Fe]F]6wto>o>o>o>o>o>&胋?oЩ|>|>|>|>Cn>Cn>d.}إyKv.}إOYSN>Oi>ҧ]K6s?mɧ|ɧ|'X|Ч}Ч}Ч}*}Fs|˧|r'x|ǧ}r'|r'|˧IOw˧)O.O.O.OԝO%_\%'_r%_\%_x|ȗ|ȗ|ȗ|_x|_X|͗|͗|͗|͗|͗|~q~a%_X|a_X|Ɨl|Ɨl|Ɨl|Ɨl|Ɨl|Ɨl|Ɨl|Η|Η||a_XQ7X|c7X|cͫ߼ͫ߼ͫ߼ͫ߼+:ͫ߼ͫ2-2-2msy|ۜomsqo196fv}پlno{mk7~᷇|<|sL|ķL|ķL|ķL|78|a?8?8?8Ïď <~<~<~GG~tGG~tGG~tGG~tGG~k?nڏOncg~̏3?v<~;cg~u.'&@t LT(HTPA$D̑ĉC&HLk߫v]l9//xfJ7]O5o֪w]U߆ӟvկ.^Yzn #|=G>bL|{}FЩ&@w @6f d3lcd d2L2@&d d2L2@&d d2`` 0N'dq28` dq28` ` `````` CСt:t:`@.셇  !!0ĺ2ĺ2ĺ2Bg 3C!t:c1Bg !!BCb ?C!c1B ?ztuwuwuw[d:-2b 1F#C!cd12b 1F#C!c1Bw !!!cd12al`{```````0WFWGWGWGXcGX[GX[GXOFA#bq1¸a\0.F#se2\a0WF+#̕rA#a9 ֓֓֓֓֓c1A#tc1Aw;F/Pc1tc1c~1?Ƙc̏1c1c}cl!1d1Ccc y!11<ƐCcc y!11<ƐCcc y!1tcuuuudddddd e8Əc=c=c=c=cL1&c1cb11Ƙc`j@b[cy2<`L0O&'̓ dy2<`L0O&dy2`m`m`m`m`nL07&̍ sc1ܘ`nL07&̍ sc1ܘ`nL @bq1`LL0&& cb11`LL0&& cb11`LL0&'戀6rBoNasMasMasMacLasMasMasMLasMasM1&{)rS妐rBSMbmbmbmbmbmbmBoN3ЙS)t:s 9Μb~L3ЙS)t:s 9ΜBgN3ЙS)t:s 9ΜBgN3ЙS)rbLL1&S zb=1AO̠'f3 zb=1AO̠'f3̋ zb=1üa^0/f3̋ by1üa^0/f3̋ by1üa^ 0f rA3a9 0f rA3a9 0f rA3acc{{{{0Xc,1 s9ca̡#rCsa9!90r9֌9!sC؇̱c2>d}9!s̋9a0xCsa9!90rCsa9!90~Cs9t:b1CG̡#s9a0xc<,0 axX`<,0rX@ a9, 䰀rX@ a9, 䰀~X`^,0/ ̋byX@ a9, 䰀rX@ a9, 䰀Г rX@ `, d 2X@ `, lɻ%zr5c5c5c5c5c5c5cĚĚĚĚMZZZĜXbN,1'K̉%sb9ĜXbN,1'K̉%sb9ĜXbN,!%zr =\b\b\b\b\†X†X†X†X†X†X†X†X†X†X\\\BG.!%a =\Bw+a9 䰂V rXA+a90V+ axXa<0V+ a¼Xa^0/V+̋ by| a+V؃[al= { ca90V XA+d,V XA+++++5l5l5l55555䰆֐rXc<1k5axXc<1~ VV1'֘k̉5sb9ƜXcN1'֘k̉5a9ƜXcN1'֘k̉5sb9nXC7 k5t:r \CG#טk` !5d ֐2@`l d 666666666X37X37X37X37X37X372@`l dvvvv`Nl0'6̉ sb9`Nl0'6 `q8`l06 2@`l drbNl1'[̉-sbXb,l1 [-caXb,l1 [-ŜbNl1'[̉-sb9ŜbNl1'[-a --- xb s|9@>dslv9@>c1sĘ9ba{a{a{a{a{!##s|9B>G!#sq5:8B[-G#tY[XsWGGGGGGGGGgCOG!Gyaa###G]WGz|>BvGٝ ֢wN ;A~'u9AN?' zO't y0N :A^'y  6 :A^'ywN :a|NC'N'n'1;8~d.ug~O?7 o~_V0._[_}?w~/s}cW׃}+~W77Co׋>;+C{p{˹o}fV{].E~ωsx \z3u=>-{uje>?>xo^^/S8G~<8 3~_qzː[Wq&WwJmmMT|_&.;mxy֑y5?ۚfs^WBu#>W\~#n.'2c ^.{x8?ޏ-]4M3źy~j?Cz&_~XϾGc#Ko}7qʎ/A/V;/}^w){- EWbT~ЯoH_>i8.ߓbb} ~/4M,W#~TOn|ޗLy1z^oT>N0/֥X7y?$kerkf l8z*<۲^!g{iTy㸕e}Z^]sv;No70o}W^Y|NJob9vA>\Wba^ */z>'ϿR~+Hك"?~הI>$}y\(y.U'sw:#cƏU<ױuh< z["cS}`xs|n3GAK*M~KC;TvfX^7wյ?;>]yۖq-.}:w}N׹\~rU|]re>?8\9_Scyc#Lž˾GsUWmW/S>bq3U'TM {,~/Շ7K_[!cq_-Vl]Ta}|4M,cj}uw*4c'Qtyu#߫/w~ܾlF?>ۙ*?)W~>Z)8 ngyWR~*N}zU<+ryK3ťΏ'fDzK~qPN|j (}+R^{~a{H]msU<i{i_fyu}>m;O?_Rv"x]R>~ @Tz>j O庒ѿT (RSƩzuϳ|?8';"7฾]N͕z]ʎS~kj~Tyoo9DJMcoij>nߓ[[!^/|/qλz=z[כ:&Szu~uo~sqTvuWp^SWWug@Ui<.U}i:)/!oe\4Z,SzQye*.ڮNEmϟlq~9QCMx[*]A*4M4M6v/Uw\y}U ur5>Ǻ~'z,]S~#Տ*^#pPybj|ݚǑ0 S~@>TTg?[#U\oazki7,J?vM4vXw}I_y?~2WwWV5u'w/ous76M^'m=~ޫ_G|Bkr?Q]7y{"ǏYNsP _r9_P+5O9R35u:橼uw=?M4>2Mϥr=e,]7?jA>0\/{/m?yo6寖}i|Ȇs넣>ʃ|8Z1祟 2/`Gxz\6=ĸc>Awr}Ru*;گK奤;mݟz'_I!'9y5#G~oa[vEߕ۷>ii}CS~W+3W~ U|Sѷq|4Δ=/K/s\,⬹)||>꼃JŎ*r&}䩞J}ͷ*_80RYS:uL\S[N]W罨y4M4M4{}c9l\l}LyVLu'>'SӏڮGPrU} C]>}뙦i?aZ~fL*hu~>s]g_+#nr>(3<[f\OUa;77?T$@uMT7giižөzc׹խ}l̦[DsMzݶT|2|^v߰vo\F虦Y_cvQnܑ󭸿G r\N'z/ۨ|>틦UjqRexPS}y^벎F}i(|4MQWS\j v?W/5y?~IJOO-WU,*Ec`:*n?K2_9}'1Kr5^量.3K=SWŪ娮+yj~=yuljGQ'NJH*牚i>'s5Uu4g-㥩: >*,i>=>=ύ%}e7tul*Ozc:-Ggz?ǺtUW~|~aGUϵ4MӬö WS=~ti34;u~>#}Ծ_}cpl<Ƕ?_xq{(e|[5[ȍםZwRy|:OWsOz5b}sz}sii>"fi7 ]?S5'y:?ӹwnc>?_uU~Y/RsM9T s"}QX.xA;c=M+4M4MS3WsC,_#6<}WV}"θ|i>/u_ϰz opݏM4M4>1S\~+3/yq~|/_[}u(Oyʦ_:|~~XGoCsT?'{5qy1{?a7qky>C~KM4M4M _wI=]4ۘWXOa>y>s׭}Oy7m5/5gߍ>:D|N߄=|d*Anpg/ov˺crQ#ʮsZ3ޗu=s _e;*~׃\T܃;^aiiT~W08??BE)vg y;ss]kz>I6yܲ]y'-ʼn.?4M4M4Ro:S42Ws##:"0x̫`6SU8 ί>fljzHnu꼳o-'Mջp_GU4M4M4b>l,&8N Fk5>&|Tfg'(?/:8n΋x׉竛iiiͿ}}@"_5|T:r*׿4Ms,Ώ|=^>RdiԹg5M4>H>^k?G1ǡ `9 k>4S?VT}B\:xוcscx]*=ϜB,oS)^UgY?}'u增B(4MӼK R^G ZMU+Fy~s~ Mw}ZgRzy*P篛yf(;F_Sm}[{g-Sc_iO<\ܟ%GS|2E߆su.go:㾞`/!b8\ܿ-ّ_P7~Ր׽ΏOX<};4M4Mu\n.sL|\m{.}ib+=i?[is~=A1y`+g[[M#2Pp?fCYK֏xG_ٯxcy<6M4MٷMؿq~OqWɗ1M~͇ }z.b][z:=E>T}cs̓{++u-|Sa1744M4MS<<u7׏>q~-4" 7~qx}<~_ZITbr<ܷ7U~{#Cs/^L4M4ǺorWo ~Ͼo1M;GWozߔO/y}ߔ"ˣ}}Ϫs[LTU>`aܗEMGU^z]N5oyDsܹ$#׹ii6Ϧ9Ogx&9ߋ J]4îOWmߛ5귞Ϳu#Kg%ߗǙ\czyni@?Rq>gyN[s=D_ie\wC;%"_VD]կ3z7 r)~܍)W9:gi+0e׫z墨γ)}qW}TM4͟0wP~3p>*'Uڇ#}M?c]̭Uq8(? 4M+䞳f-~L_> lg*ŸtҮi棰0[y)g TėuZ׉9%eQvii>K문~/!J+r{Wng9C:z|L4[ڨ<}S~T%՗7/NRu+W3fifG> #`+ '8O84ge ~j 6'Du>-2M4M4K!-sh&Y8QP(,+މ`i^_:A%~4M4M6\w-C}?iR ){7ƛ^Hé7d7~L4M4MK͇?*P;R!Q4Mb?[M[]o?s>74W̶h=U_-Eu>[3M4M٘[} {g{ȺՏzxwߋA֘̾{usږG~f]?~jMux:4M4Ɣ}v-~g>)Oߔ~__?VټRS~~>LKr~~>]Gos4M4T~ 5_Iԭr~ϕ:.@ {s_ॎFi2ywzochEM4MS}_ai q>_3Q(/`?L4ۥTͰ4Ourks 4MSqg]~?~s*64`.^aʯ}qxsoiT(=}t;ޞjy]{\?:0wTD})L4~1~.st< ߿}5M|l9UՓ0Kis{5~\:짿վr4~~^:4M]_ K|uݾ_ۋTe -//=/(f/=?S]ۣjݟί7Wp4M5V?^պo>8OۊE]c_ctqmO{6vQϫk?;.u|Poymi%֝}Wo*n:g:J{4ѩ9S'7?eGߧڷ$RŸ1M43s2eK,|9_UV﫚azoǰ/ze<'gMM~q_[ifpb<֍g^w0M4`> ᇏބp'nT3>Qt2xGkW+s^WSʿ㪯+_~|W}hY}hGU$7x5M4__V~>d}GSyF}=mG]k]8W~m#U|ω/+>י?i'Ͽwܹm{<W7eﲿ[q.K~vhylfLsoh6Z9z:ar| ?o7eGzkni}sESߨ7d5eع/6**?ل]z}/S Ou=7ncҪ)c}zO8KZoK|^?üWYSz/Nݏ'n}=띔~fqTHS맪 Q}ݠ)}Rjp}Oɍϲܕֿ^O}i_*&3M3=?>cݎr2Rqİ>NXl/ٿc?3t;w_)|il+_d8s·T&}NNe??O+#p>s?\Չ|8Q_W|*>xiiuT,Ϊ<#횰 `IU)q_;SNJ#?!+u}Pg>ysv!۵>4M4g.Oc><;}Þ㸛{f]PJ_=|VSEU]QsU|¾jLųf\_ {ǜ~8ef7k_r^T@oٵWu|~=MۦƋi<_W>wfn|'8OlWpe0*;+)W,,Vẽ˹Hy/M1ާs}{NvL?afxk߀G/:67Y?KۮW/?qTz>]~YN+XQÔ_k(}V|Ϧy^Pוgd{&Ʀ>.WYZUCp&םs] 9~D{^/<=?e[WߩA]{~n_NezQ= w`*_c"^Fp{WoίL[+ٱTΔsrǫ5Y7ey<~u'|ʸ*%Oҗ\:Sq燘_^);vFT}u^>~]]}yhܚGu3Z11?V>|-/xxK?܏-as8bg3e|sK]o>:'qp?uf,=HrܦoʛS9>#z[6 =q0WꝹ_ڏzhT]MC'i> exxq:m|م>sߩƕx>*W2_<8z"Wij]Tn=~b*zfnP^V~8єb,y[:|gq1/5UXS˔^o?:l_s[W}GU?TΫܺG7+wߗ?c?:948:%bֿsAASso ?_ +qj \M4usuXC L>32er=^*4MͦH=6_G65̰gT2MOCSyAU}LyϪϙq>OҰ6VOU|XUuV翰}vku=7~G|<ͯq_AXjrQn)/Kq0E%>}q0[SכR|ǿH,=dʏC#Ӧz=ߋn\k|%rџɝ?e=\y˜Oq\]J#si,Tvi6?/o&sVlǖuYQ}c4p?жfXMod;VKalc<7wx4KY7"h+lc~s̒qYs:/}x,4f_ݽO6T>kN]6M)In|s8yG/y &s`unM4벩>cWp\9xk]_=4MmN쒩8V<|&|c6M̵%mM0}A:l}Yj?y oiv\;T=j:Q,5Vq f<>7?X̵g{i_' ɳ.q˳i@_} dܻهq׳w|.|7WIun}>%ˣ^zyf˺z=!:oQ},O2/~8svY/C\C*֔'l/]V멺ek]_O؎}Us2cu`̳omlڿWzϠ%we9>con7=bC*}/inst/NEWS.Rd")) \name{NEWS} \title{News for \R{} Package \pkg{Matrix}} \encoding{UTF-8} %% NB: The date (yyyy-mm-dd) is the "Packaged: " date in ../DESCRIPTION \section{Changes in version 1.7-0 (2024-03-16 r4662)}{ \subsection{Significant User-Visible Changes}{ \itemize{ \item The internal collection of SuiteSparse libraries is updated from version 5.10.1 to version 7.6.0. Hence the \pkg{Matrix} ABI version is incremented from 1 to 2. Reverse \code{LinkingTo} built under earlier versions of \pkg{Matrix} should be rebuilt from sources by users and maintainers of binary repositories.\cr \cr We have so far identified one backwards incompatible change: since SuiteSparse version 7.3.0, \code{cholmod_sort(A)} sorts but \emph{does not pack} the matrix \code{A}. It seems that now \code{cholmod_sort} and \code{cholmod_copy} must be used in conjuction if a sorted \emph{and packed} result is desired. This change affects only reverse \code{LinkingTo} relying on the old behaviour. (It seems that currently there are no such packages on CRAN or Bioconductor.) \item The diagonal elements of the \code{R} factor computed by \code{qr()} are no longer constrained to be non-negative, due to differences in the implementation of function \code{cs_house} between SuiteSparse libraries CSparse and CXSparse. Accordingly, the validity method for class \code{sparseQR} no longer complains about negative \code{diag(R)}. \item \code{indMatrix} no longer extends virtual class \code{compMatrix} and so no longer inherits a (never used) \code{factors} slot. Objects serialized under \pkg{Matrix} \eqn{<} 1.7-0 and unserialized under \pkg{Matrix} \eqn{\ge}{>=} 1.7-0 remain valid, retaining a harmless \code{factors} \emph{attribute}. \item \pkg{Matrix} version 1.7-0 and higher strictly depend on \R{} \eqn{\ge}{>=} 4.4.0. } } \subsection{New Features}{ \itemize{ \item CHOLMOD component Partition is now compiled along with its dependencies (METIS, CAMD, CCOLAMD). \item CXSparse is now compiled instead of CSparse, which did not support complex matrices. } } \subsection{Bug Fixes}{ \itemize{ \item CHOLMOD sources are patched to address the significant number of compiler warnings surfaced by \option{-Wall}. \item The unary subscript \code{x[i]} is correct again for \code{x} of class \code{.s[CT]Matrix} and logical \code{i} indexing entries outside of the stored triangle. } } \subsection{Misc}{ \itemize{ \item Unexported class union \code{replValueSp} is effectively removed, now having zero members. Actual removal is delayed until package binaries caching the old definition are rebuilt under \pkg{Matrix} 1.7-0. } } } \section{Changes in version 1.6-5 (2024-01-06 r4560)}{ \subsection{Bug Fixes}{ \itemize{ \item \code{x[]} works for \code{x} inheriting from virtual class \code{sparseVector}. \item \code{length(x)} is always an integer for \code{x} inheriting from virtual class \code{sparseVector}. Truncation did not occur for \code{x@length} of type \code{"double"} equal to or greater than \code{.Machine[["integer.max"]] + 1}. \item \code{tril(, -n)} now works again. \item \code{tri[ul](, k)} now works correctly for \code{k != 0}. \item \proglang{C} API function \code{cholmod_triplet_as_sexp} transposes entries \dQuote{opposite} the \code{stype} when that is nonzero, following CHOLMOD. \item \code{R_init_Matrix} did not register \code{cholmod_defaults}, so calls to the corresponding stub did not work. } } \subsection{Misc}{ \itemize{ \item \code{\%||\%} is defined in the \pkg{Matrix} namespace only for \R{} \eqn{<} 4.4.0. } } } \section{Changes in version 1.6-4 (2023-11-29 r4523)}{ \subsection{Bug Fixes}{ \itemize{ \item \code{printf} format mismatches detected by R-devel are fixed in 3 \file{src/*.c}. \item better deprecation message for \code{..2dge()}. } } \subsection{Misc}{ \itemize{ \item Entry point \code{M_chm_triplet_to_SEXP}, removed in \pkg{Matrix} version 1.6-2, is restored (as a macro). It was \dQuote{covertly} used by package \pkg{Rmosek}. } } } \section{Changes in version 1.6-3 (2023-11-13 r4513)}{ \subsection{Misc}{ \itemize{ \item With an \R{} built with \command{configure} option \option{--disable-long-double}, \code{prod(M)} now very slightly differs for two differently classed versions of \code{M}. \item \code{checkMatrix()} from \file{test-tools-Matrix.R} gets optional \code{MSG} argument for suppressing \code{prod()} differences. } } } \section{Changes in version 1.6-2 (2023-11-05 r4503)}{ \subsection{Significant User-Visible Changes}{ \itemize{ \item Methods for generic functions \code{rbind2}, \code{cbind2}, \code{\%*\%}, \code{\%&\%}, \code{crossprod}, and \code{tcrossprod} determine the class of the result using more strict rules, designed to avoid \dQuote{surprising} coercions where possible. Notably, operations involving \code{RsparseMatrix} now return an \code{RsparseMatrix} in more cases. \code{TsparseMatrix} and \code{diagonalMatrix} may be handled as \code{CsparseMatrix} or as \code{RsparseMatrix}, depending on context. } } \subsection{New Features}{ \itemize{ \item New \R{} function \code{Matrix.Version}, taking no arguments and returning \code{list(package, abi, suitesparse)}, a list containing the numeric versions of the package, its ABI, and the internal SuiteSparse library. ABI versioning is new: the version is 1 in this release and will be incremented by 1 in each future release that changes the ABI. Versions and their components are defined in a header for use by packages with \code{LinkingTo: Matrix} in \file{DESCRIPTION}. See \file{inst/include/Matrix/version.h}. %% TODO {for 1.6-3}: Ops using (x@x | is.na(x@x)) for ndiMatrix 'x' \item New nonvirtual class \code{ndiMatrix}, extending virtual classes \code{diagonalMatrix} and \code{nMatrix}, for nonzero pattern diagonal matrices. It is used to represent the result of \code{is.na}, \code{is.nan}, \code{is.infinite} applied to \code{diagonalMatrix}, as well as diagonal boolean products. Coercions \code{as(, "nMatrix")} now give \code{ndiMatrix} instead of \code{ntCMatrix}. The latter can for now still be obtained by coercing to \code{nsparseMatrix} instead of \code{nMatrix}. \item New C-level validity methods for \code{sparseVector} and \code{[nlidz]sparseVector}, now requiring \code{length} not exceeding \code{2^53}, which on most platforms is the maximum integer representable exactly as \code{double}. \item \code{mean(, trim=)} now works efficiently for nonzero values of \code{trim}. \item \code{rep(, each=)} now works efficiently, avoiding \code{rep(., times = rep(each, times = length(.)))}. \item \code{.m2dense} and \code{.m2sparse} gain an argument \code{trans} indicating if vectors that are not matrices should be coerced to 1-row matrices rather than 1-column matrices. \item \code{.m2dense} and \code{.m2sparse} can be called with one argument. Their \code{class} arguments admit new default values \code{".ge"} and \code{".gC"}. \item \code{.diag2dense} and \code{.diag2sparse} gain an argument \code{kind} indicating the \dQuote{kind} of the result. \item New exports \code{.M2V} and \code{.m2V}, for coercing \code{Matrix} and \code{matrix} (and in fact \code{vector}) to \code{sparseVector}. \item New exports \code{isUniqueT} and \code{asUniqueT}, with optional argument \code{byrow} allowing for row-major ordering of entries. \code{asUniqueT} supercedes \code{uniqTsparse}, which is no longer documented. \item New export \code{aggregateT}, for aggregating \code{TsparseMatrix} \emph{without} sorting. \item Methods for \code{all.equal} now report the packages where S4 classes are defined. \item \code{sum(x)} and \code{prod(x)} no longer require a coercion from \code{symmetricMatrix} to \code{generalMatrix}. Results where coercions are now avoided may differ numerically due to reordering of adds and multiplies, most commonly on systems where \code{sizeof(long double) == sizeof(double)}. } } \subsection{Bug Fixes}{ \itemize{ \item Methods for \code{cbind2} and \code{rbind2} did not in all cases handle vectors as 1-column and 1-row matrices, respectively. \item Methods for \code{cbind2} and \code{rbind2} did not handle 0-length vectors (including \code{NULL}) correctly where the result would have 0 rows and columns, respectively. \item Methods for \code{cbind2} and \code{rbind2} did not handle \code{NA} in the \code{x} slot of \code{ndenseMatrix} correctly (i.e., as \code{TRUE}). \item \code{cbind2(, )} gave \code{ngeMatrix} instead of \code{lgeMatrix}. \code{cbind2(, )} gave \code{dgCMatrix} instead of \code{lgCMatrix}. Methods for \code{rbind2} had similar problems. \item \code{rcond(<0-by-0>)} now returns \code{Inf}; see \PR{18543}. \item \code{round()} and \code{signif()} now return \code{ds[yp]Matrix} rather than \code{dp[op]Matrix} and now discard \code{factors}. \item Methods for \code{length} now return \code{integer} rather than \code{double} if the result does not exceed \code{INT_MAX}. \item \code{dsparseVector} with \code{x} slot of type \code{integer} are now formally invalid, as always intended. \item Methods for subscripting \code{sparseVector} did not behave compatibly with \pkg{base} when supplied with fractional, \code{NA}, or out-of-bounds subscripts. \item \code{symmpart(x)}, \code{skewpart(x)}, \code{band(x, k1, k2)}, \code{triu(x, k)}, and \code{tril(x, k)} now always return a \code{.diMatrix} for \code{x} inheriting from \code{diagonalMatrix}. \item \code{colSums(<(n|l|ind)Matrix>)} and \code{rowSums(<(n|l|ind)Matrix>)} now always give a result of type \code{"integer"}. Methods differed previously, some giving \code{"double"} (as \pkg{base} does, suboptimally, traditional matrices of type \code{"logical"}). \item Some methods for generic function \code{lu} did not transmit \code{Dimnames} to the result. \item Some methods for group generic function \code{Summary} ignored arguments matching \code{\dots}. Other methods did not ignore the \dQuote{garbage} elements of the \code{x} slot of dense, triangular matrices. \item \code{kronecker(, )} threw an error for attempting to access the nonexistent \code{x} slot of its first argument. \item Matrix products now behave exactly as \pkg{base} when testing for conformable arguments. \item Numeric products (\code{\%*\%}) did not always return a \code{dMatrix}. \item Methods for \code{all.equal} now \dQuote{see} attributes of S4 objects that are not slots. This can be disabled by setting argument \code{check.attributes} to \code{NA}, which is otherwise equivalent to \code{TRUE}. \item \code{prod(x)} is computed more diligently for \code{x} inheriting from \code{sparseMatrix}, \code{sparseVector}, or \code{.t[rp]Matrix}, i.e., those \code{x} that can be understood to have \dQuote{structural} zeros. Now, multiplication by zero occurs at the position of the first structural zero in the matrix or vector (when traversed by row in the case of \code{RsparseMatrix}). An exception is \code{TsparseMatrix}, for which multiplication by zero occurs before multiplication by any stored entry, regardless of the position of the first structural zero in the corresponding sorted matrix (to avoid the cost of sorting). \item \code{tri[ul](<.t[rp]Matrix>, k)} was often wrong for nonzero \code{k}, setting too many bands to zero. \item C-level \code{tCsparse_diag} (formerly \code{diag_tC}) now handles structural zeros and \code{NaN} on the main diagonal correctly. Option \code{"diagBack"} now works correctly. \item The prototype of API function \code{M_cholmod_band_inplace} was wrongly copied from \code{cholmod_band}, instead of from \code{cholmod_band_inplace}. \item Many API function prototypes wrongly used \code{const} qualifiers where the registered routines do not. \item \code{expm(x)} failed for \code{x} of class \code{dtpMatrix} or \code{dspMatrix}, since \pkg{Matrix} version 1.6-1. \item \code{.m2dense(x, ".ge")} allocated unnecessarily for \code{x} without attributes. } } \subsection{Misc}{ \itemize{ \item C code now refers to the symbol \code{factors} as \code{Matrix_factorsSym}, rather than \code{Matrix_factorSym}. \item Certain never or seldom used class unions are removed. \item The content of \file{src/Mutils.[ch]} has been migrated to more transparently named files: \file{src/attrib.[ch]}, \file{src/objects.[ch]}, etc. Similarly, much of \file{src/factorizations.[ch]} have been migrated to \file{src/solve.[ch]} and \file{src/determinant.[ch]}. \item All matrix product code has been migrated to \file{products.[Rch]}. \item Files in \file{po/} and \file{inst/po/} have been updated due to more frequent use of \code{gettextf} in \file{R/*.R}. \item C code is prepared to handle complex matrices and their factorizations. Notably, new machinery in \file{src/cs-etc.[ch]} will enable linking the CXSparse library instead of the CSparse library, the latter supporting numeric types but not complex ones. \item Some API declarations and macros not used by \emph{any} reverse \code{LinkingTo} are removed or remapped. \item API headers are now nested under \file{inst/include/Matrix/} for better namespacing. Where possible, packages should start to use \code{LinkingTo: Matrix (>= 1.6-2)} and include files from the new subdirectory, e.g., with \code{#include }. \item Users including API headers can define macro \code{R_MATRIX_INLINE}, typically with \code{#define R_MATRIX_INLINE inline}, to allow the compiler to inline stubs for registered routines. \item \pkg{Matrix} did not pass its checks under \R{} 3.5.0, implicitly violating \code{Depends: R (>= 3.5.0)}. This release restores compatibility. } } } \section{Changes in version 1.6-1.1 (2023-09-08)}{ \subsection{Misc}{ \itemize{ \item Export the generics \code{crossprod()} and \code{tcrossprod()} explicitly, needed for R-devel when they become primitive internal generics. } } } \section{Changes in version 1.6-1 (2023-08-11 r4228)}{ \subsection{New Features}{ \itemize{ \item Several new coercion utilities, exported and documented in \code{help("fastMisc")}. Some of these supercede ones made available (experimentally) in \pkg{Matrix} 1.5-4; for example, \code{.M2m} makes both \code{.dense2m} and \code{.sparse2m} redundant. The superceded ones are not yet formally deprecated, but are no longer documented. \item \code{drop0} is now implemented independently of \code{CHOLMOD}, becoming more efficient notably for logical arguments, no longer requiring a coercion to double. \item \code{drop0} gains an argument \code{give.Csparse} to complement \code{is.Csparse}. \code{FALSE} indicates that \code{RsparseMatrix}, \code{TsparseMatrix}, and \code{indMatrix} arguments should be handled directly, without a coercion to \code{CsparseMatrix}. The default value is \code{TRUE}, for backwards compatibility. } } \subsection{Bug Fixes}{ \itemize{ \item Fix four Valgrind-detected memory bugs. %% \item \code{[cr]bind(, )} now behaves as %% \code{[cr]bind(, )} in more cases, always %% handling the vector as a 1-column (\code{cbind}) or 1-row %% (\code{rbind}) matrix. \item \code{ \%*\% } works again. \item \code{diag() <- value} works again, no longer giving a \code{p} slot of length \code{Dim[2]} rather than \code{Dim[1]}. \item \code{as(, "symmetricMatrix")} now checks for symmetric \code{Dimnames}, for consistency. \item as(, "[nld](sparse)?Matrix") now returns a \code{.gRMatrix} or a \code{.gCMatrix} depending on the \code{margin} slot. \item \code{as(<[CR]sparseMatrix>, "generalMatrix")} now checks if the number of nonzero entries in the result would exceed \code{INT_MAX} and throws an error in that case. \item Validity checks on the \code{perm} slot of classes \code{Cholesky} and \code{pCholesky} have been enabled (forgotten in \pkg{Matrix} 1.6-0). \item API C function \code{chm_sparse_to_SEXP} now sorts and packs its first argument \emph{before} assigning struct members to variables, no longer accessing blocks of memory freed by \code{cholmod_sort}. } } \subsection{Misc}{ \itemize{ \item Run speed-measuring tests only \code{if(doExtras)}: these were too slow when run under Valgrind. \item Most coercion code has been migrated to \file{coerce.[Rch]} from elsewhere. \item The number of methods for generic functions \code{coerce} and \code{as.*} has been reduced substantially, from 306 to 194 (not counting deprecated ones), partly as a result of efforts to do more fine-grained dispatch in C code. \item Files in \file{po/} and \file{inst/po/} have been updated (again), as many more C level messages now use format strings as a result of \code{vsnprintf} usage in \file{src/validity.c}. } } } \section{Changes in version 1.6-0 (2023-06-30 r4125)}{ \subsection{Significant User-Visible Changes}{ \itemize{ \item Class \code{indMatrix} gains a \code{margin} slot with value \code{1L} or \code{2L} (\code{1L} being the prototype and previously implicit value), indicating that the object represents a row or column index matrix, with ones at \code{[i, perm[i]]} or \code{[perm[j], j]}, respectively.\cr \cr Methods with \code{indMatrix} or its subclass \code{pMatrix} in the signature have been adjusted to account for the new slot. Notably, multiplication on the right by an \code{indMatrix} with \code{margin = 2} is now implemented as a column subscript, and the transpose of an \code{indMatrix} is now the same object but with \dQuote{opposite} \code{margin}. \item Virtual class \code{MatrixFactorization} gains a \code{Dimnames} slot. Now all factorizations preserve the \code{Dimnames} of the original, factorized \code{Matrix}, whereas previously classes \code{Schur}, \code{sparseLU}, \code{sparseQR}, \code{dCHMsimpl}, and \code{dCHMsuper} did \emph{not}. Users can get the value of the new \code{Dimnames} slot with \code{dimnames(.)} and set it with \code{dimnames(.) <- value}. \item Classes \code{p?BunchKaufman} and \code{p?Cholesky} no longer extend \code{dtrMatrix} or \code{dtpMatrix} and in turn no longer extend \code{Matrix}. They retain slots \code{Dim}, \code{Dimnames}, \code{uplo}, and \code{x}, but not \code{diag}. This change implies that virtual classes \code{Matrix} and \code{MatrixFactorization} no longer intersect. \item Classes \code{p?Cholesky} gain a \code{perm} slot with prototype \code{integer(0L)} to support representation of pivoted factorizations, as typically computed by LAPACK routine \code{dpstrf}. \code{perm} of length 0 is valid and equivalent to the identity permutation. \item Methods for generic function \code{chol} that previously returned an object of class \code{p?Cholesky} now return an equivalent object of class \code{dtrMatrix} or \code{dtpMatrix}. Existing code that relied (correctly) on \code{chol} to return the upper triangular Cholesky factor as a \code{Matrix} can be expected to work as before. } } \subsection{New Features}{ \itemize{ \item Methods for subscripting \code{Matrix} now use the more systematic code in \file{R/subscript.R} and \file{src/subscript.c}, becoming more efficient for all \code{lsparseMatrix} (no longer coercing to \code{dsparseMatrix} and back), sparse \code{symmetricMatrix} (no longer coercing to \code{generalMatrix} and back when \code{i} in \code{x[i, i]} is monotone), \code{unpackedMatrix} (no longer coercing to \code{matrix} and back), and \code{RsparseMatrix} (no longer coercing to \code{TsparseMatrix}, then to \code{CsparseMatrix}, then back to \code{TsparseMatrix} [!]).\cr \cr \code{x[i, j, drop = FALSE]} preserves the class of \code{x} in more cases where \code{x} is a \code{triangularMatrix}, \code{diagonalMatrix}, or \code{pMatrix}, doing more complete checks on \code{i} and \code{j}.\cr \cr Notably, for \code{x} inheriting from \code{RsparseMatrix}, the result is now always an \code{RsparseMatrix}, rather than always a \code{TsparseMatrix}. \item \code{NULL} subscripts, as in \code{x[NULL]}, \code{x[NULL, j]}, and \code{x[i, NULL]}, are now supported for \code{x} inheriting from \code{Matrix}. They are handled as \code{integer(0)}, consistent with \pkg{base}. \item New nonvirtual class \code{pcorMatrix} extending \code{dppMatrix}. It is the counterpart of \code{corMatrix} using packed storage, supporting more efficient storage of dense correlation matrices. Now \code{pack()} gives a \code{pcorMatrix} preserving the \code{sd} slot, rather than a \code{dppMatrix} without an \code{sd} slot. \item New virtual classes \code{BunchKaufmanFactorization}, \code{SchurFactorization}, and \code{QR}, extended by existing nonvirtual classes \code{p?BunchKaufman}, \code{Schur}, and \code{sparseQR}, respectively. These are parallel to the existing virtual classes \code{CholeskyFactorization} and \code{LU}. Packages defining new factorization classes may extend these. \item Virtual class \code{CHMfactor} and its subclasses gain formal validity methods. \item The validity method for class \code{sparseQR} now checks that the \code{V} slot is lower trapezoidal and that the \code{R} slot has non-negative diagonal elements. \item New generic functions \code{expand1} and \code{expand2}, intended to eventually replace \code{expand} and certain coercions from (subclasses of) \code{MatrixFactorization} to (subclasses of) \code{Matrix}. \code{expand1} is used as \code{expand1(, )} and constructs by name factors appearing in the factorization. \code{expand2} is used as \code{expand2()} and returns a named list of \emph{all} factors appearing in the factorization, in order and with row names on the first factor and column names on the last factor. The result can be used to reconstruct the factorized \code{Matrix} as the product of the elements of the list, namely \code{Reduce(`\%*\%`, expand2(.))}.\cr \cr \code{expand} and its methods are retained for backwards compatibility. They may be formally deprecated in the future, hence new code should use \code{expand1} and \code{expand2}. Notably, \code{expand1} and \code{expand2} have methods for all factorizations in \pkg{Matrix}, whereas \code{expand} continues to have methods only for \code{denseLU}, \code{sparseLU}, and \code{CHMfactor}. See \code{help("expand-methods")} for a list of methods, including useful optional arguments. \item Generic function \code{Cholesky} gains methods for \code{denseMatrix} returning an object of class \code{p?Cholesky}. The method for subclass \code{dsyMatrix} admits an argument \code{perm} indicating if the pivoted factorization should be computed. The corresponding \code{chol} method gains an argument \code{pivot} indicating the same. By default, \code{Cholesky} pivots and \code{chol} does not. \item Many subclasses of \code{MatrixFactorization} can now be coerced to \dQuote{nearby} subclasses of \code{Matrix}. The resulting \code{Matrix} reflects the internal representation of the factorization and not necessarily a particular matrix factor. The new coercions are: \code{as(, "dgeMatrix")}, \code{as(, "dtrMatrix")}, \code{as(, "dtpMatrix")}, \code{as(, "dtrMatrix")}, \code{as(, "dtpMatrix")}, \code{as(, "dtCMatrix")}, and \code{as(, "dgCMatrix")}. See \code{help("denseLU-class")} (and similar) for details. \item \code{determinant(x, \dots)} and \code{solve(a, b, \dots)} now work for \code{x} and \code{a} inheriting from \code{MatrixFactorization}, behaving as if \code{x} and \code{a} were replaced by the factorized \code{Matrix}. The exception is \code{x} inheriting from \code{CHMfactor}, where for backwards compatibility the default behaviour is still to compute the determinant of the Cholesky factor. This exception should be considered \emph{temporary}, hence defensive code will call \code{determinant} with (new) optional argument \code{sqrt} set to \code{TRUE} or \code{FALSE} explicitly, to not rely on the current default value. See \code{help("CHMfactor-class")} for details. \item Generic function \code{diag} gains methods for \code{p?Cholesky} and \code{CHMfactor}. The result is a numeric vector containing the diagonal entries of the diagonal matrix \eqn{D}, as defined in \code{help("Cholesky-class")} and \code{help("CHMfactor-class")}. \item The \code{lu} and \code{qr} methods for class \code{dgCMatrix} now admit an \code{order} argument with value in \code{0:3}, allowing the expert user to choose among all ordering methods made available by the CSparse library. \item \code{solve(, b, sparse = TRUE)} is now handled entirely in C code via \code{cs_spsolve} from the CSparse library. \item New utilities \code{invertPerm}, \code{signPerm}, \code{isPerm}, and \code{asPerm} for computing the inverse and sign of a permutation vector, testing if an integer vector is a permutation vector, and coercing a transposition vector to a permutation vector. \code{invertPerm} is a more general version of the already exported function \code{invPerm}, which is retained as a wrapper around \code{invertPerm} for backwards compatibility. \item The \code{qr.R} method for class \code{sparseQR} gains a \code{backPermute} argument with default \code{FALSE}, for compatibility with \pkg{base}. Function \code{qrR}, which existed primarily to provide a back-permuting option, is retained for backwards compatibility. } } \subsection{Bug Fixes}{ \itemize{ \item \code{x[integer(0), ]} and \code{x[, integer(0)]} now give a \code{generalMatrix} result when \code{x} is a 0-by-0 \code{diagonalMatrix}, for consistency with all other cases of \code{x[seq_len(n), ]} and \code{x[, seq_len(n)]}, where \code{x} is an \code{n}-by-\code{n} triangular, symmetric, or diagonal matrix. \item For \code{x} inheriting from \code{RsparseMatrix}, subassignment of the form \code{x[i, ] <- value} is now correctly distinguished from \code{x[i] <- value}. \item \code{rownames(x[integer(0), , drop = FALSE])} and \code{colnames(x[, integer(0), drop = FALSE])} are now always \code{NULL} and never \code{character(0)}, consistent with the implementation in \pkg{base}. \item Subscript operations on \code{Matrix} now correctly error whenever the formal argument \dots{} is matched, as in \code{x[i, j, drop]}, where \code{x[i, j, drop = drop]} is almost always intended. \item \code{x[i, ]} now correctly drops dimensions when \code{x} is a 1-by-\code{n} \code{Matrix} and \code{i} is \code{TRUE}. \item Methods for \code{solve} now obey the following rules much more strictly: \itemize{ \item \code{solve(a=, b=)} must return a vector. \item \code{solve(a=, b=)} must return a \code{denseMatrix}. \item \code{solve(a=, b=, sparse=FALSE)} must return a \code{denseMatrix}. \item \code{solve(a=, b=, sparse=TRUE)} must return a \code{sparseMatrix}. } resolving some longstanding incompatibilities with \pkg{base}.\cr \cr Note that methods for sparse \code{a} and missing or sparse \code{b} have default \code{sparse = TRUE}, while methods for sparse \code{a} and dense \code{b} have default \code{sparse = FALSE}. \item \code{solve()} now always gives a \code{symmetricMatrix} result. \code{solve()} and \code{solve()} preserve formal positive definiteness, giving a \code{dpoMatrix} and \code{dppMatrix}, respectively. \item The prototype of the \code{Dim} slot of virtual class \code{MatrixFactorization} is now \code{integer(2L)}. Previously it was \code{integer(0L)}, with the result that \code{validObject(new(""))} was always an error. \item The prototype of the \code{L} slot of class \code{sparseLU} is now formally lower triangular, so that \code{validObject(new("sparseLU"))} is not an error. \item The prototypes of the \code{Q} and \code{T} slots of class \code{Schur} are now 0-by-0 \code{dgeMatrix}, so that \code{validObject(new("Schur"))} is not an error. \item \code{BunchKaufman()} now works when argument \code{uplo} (documented to be optional) is missing. \item The validity method for class \code{corMatrix} now tolerates nonfinite elements in the \code{sd} slot. It no longer tolerates nonunit diagonal elements in the \code{x} slot. \item Coercions to \code{corMatrix} now set the diagonal elements of the result to 1, consistent with \code{cov2cor}. \item \code{dimnames(x) <- value} now validates \code{x@Dim} before \code{value} to avoid undefined behaviour in C-level check. \item \code{invPerm(p)} no longer segfaults for \code{p} that are not valid permutation vectors. (\code{invPerm(NA)} was enough to trigger a segfault.) \item \code{chol2inv(x)} now ignores the lower triangular part of \code{x} not inheriting from \code{triangularMatrix}. \item \code{chol2inv(x)} now computes \code{crossprod(solve(x))} instead of \code{tcrossprod(solve(x))} for all formally lower triangular \code{x}. Previously, \code{crossprod} was used only for dense \code{x}. \item \code{rcond(x, norm)} throws a nicer error for \code{x} of length 0. \item Error messages due to invalid \code{norm} in \code{rcond(x, norm)} now refer to the argument as \code{norm} rather than \code{type}. \item \code{rcond(x, norm)} now validates \code{norm} also for \code{x} of class \code{d(sy|sp|po|pp)Matrix}, even if for such \code{x} all valid \code{norm} give the same result. \item \code{which(<[RT]sparseMatrix>, ...)} now gives indices in column-major order in all cases, to be consistent with \code{help("which")}. \item Factorizations inheriting from virtual class \code{LU} are now cached under the name \code{denseLU} or \code{sparseLU}, depending on the nonvirtual class, rather than always under the name \code{LU}. Note that user code should \emph{not} rely on the details of the cache and should instead rely on functions such as \code{lu} to retrieve cached factorizations. \item Errors signaled by \code{as(, "dpoMatrix")} and \code{as(, "dppMatrix")} now clarify that the coercions do not attempt to test for positive semidefiniteness when the matrix is not positive definite. } } \subsection{Misc}{ \itemize{ \item Help pages for matrix factorization classes and methods have been broadly expanded and updated to use consistent notation. \item C code interfacing the CSparse library now checks in more places for failed allocations inside of \code{cs_*()}. \item The length of the \pkg{Matrix} namespace has been reduced by ~15\%. More than 100 unused symbols have been removed. \item The following dependencies, needed only for a small number of \code{Rd} cross references, have been removed: \pkg{MatrixModels}, \pkg{expm}, \pkg{igraph}, \pkg{maptools}, \pkg{sp}, \pkg{spdep}. Links to CRAN and Bioconductor in \file{.Rd} files are preserved throughout. \item \pkg{sfsmisc} has been moved from \code{Enhances} to \code{Suggests}, as \pkg{Matrix} does not formally enhance it by providing methods, etc. \item \pkg{grDevices} and \pkg{datasets} have been added to \code{Imports} and \code{Suggests}, respectively, as \file{NAMESPACE} does import from \pkg{grDevices} and vignettes do load data (albeit \emph{un}conditionally) from \pkg{datasets}. \item Example, test, and vignette code no longer fails when \env{R_DEFAULT_PACKAGES} is set to \code{NULL}, thanks to additional \dQuote{invisible} \code{library} calls in the problematic source files. \item Examples now use \code{requireNamespace} instead of \code{require}, preserving the user search path in more cases. \item Updates to \file{po/*.\{po,pot\}} and \file{inst/po/*} for translators. } } } \section{Changes in version 1.5-4.1 (2023-05-16)}{% hot patch there \subsection{Misc}{ \itemize{ \item Use \code{#ifdef PR18534fixed} to adapt to \R{}'s Lapack header fix for \PR{18534}. } } } \section{Changes in version 1.5-4 (2023-04-02 r3837)}{ \subsection{Deprecated and Defunct}{ \itemize{ \item The following low level coercion utilities, which were previously exported but always \dQuote{hidden} and undocumented, are now deprecated: \code{..2dge}, \code{.C2nC}, \code{.T2Cmat}, \code{.asmatrix}, \code{.dense2sy}, \code{.diag2mat}, \code{.diag2sT}, \code{.diag2tT}, \code{.dsy2dsp}, \code{.dsy2mat}, \code{.dxC2mat}, \code{.m2dgC}, \code{.m2lgC}, \code{.m2ngC}, \code{.m2ngCn}, \code{.m2ngTn}, \code{.n2dgT}, \code{.nC2d}, \code{.nC2l}.\cr \cr The deprecations follow efforts to define more general and more systematic (but still fast) coercion utilities, to allow expert users to bypass S4 dispatch in more cases. The subset of these currently exported is documented under \code{help("fastMisc")}. Deprecation warnings will suggest an appropriate replacement, mostly from that list.\cr \cr It is not always the case that the replacement can be \dQuote{dropped in}, hence users should consult the relevant documentation when changing their code. \item Warnings signaled by coercion methods deprecated in \pkg{Matrix} 1.5-0 now correctly inherit from class \code{deprecatedWarning}. } } \subsection{Bug Fixes}{ \itemize{ \item Defining \code{sequence.default} for \R{} \eqn{<} 4.0.0, so that \code{kronecker(, )}, \code{kronecker(, )}, and \code{ \%*\% } continue to work there. } } \subsection{Misc}{ \itemize{ \item C-level utilities \code{Matrix_memset()} and \code{Matrix_memcpy()}, both new, are now used in many places instead of API macros \code{Memzero()} and \code{Memcpy()} which never check for overflow. C-level macro \code{AZERO()} is no longer defined. \item C-level macro \code{Calloc_or_Alloca_TO()} now zero-initializes also in the \code{alloca}-using case. \item Replace deprecated \code{Rdefines.h} with \code{Rinternals.h} and move inclusion outside of \code{extern "C"} wrapper in API header \file{inst/include/Matrix.h}. \item Replace \code{sprintf} with \code{snprintf} globally to avoid potential buffer overflows. } } } \section{Changes in version 1.5-3 (2022-11-10 r3772)}{ \subsection{Bug Fixes}{ \itemize{ \item \code{dimScale(x)} with argument \code{d1} missing is no longer an error. (The default value had \code{diag(x, FALSE)} instead of \code{diag(x, names = FALSE)}.) \item \code{(dim|row|col)Scale(x)} is no longer an error for traditional matrices \code{x} without a \code{dimnames} attribute. \item Our \code{cov2cor()} methods now again preserve (symmetrized!) \code{dimnames}, fixing \pkg{Matrix} bug #6783 reported by Ben Bolker. \item \code{colSums()} and friends now always give a \emph{named} result when the marginal \code{Dimnames} are non-\code{NULL}. (Names were \dQuote{forgotten} for \code{diagonalMatrix} and \code{indMatrix} arguments.) \item \code{colSums()} and friends now respect \code{na.rm} when handling \code{diagonalMatrix} with \code{NA} diagonal entries. \item \code{expand()} now \dQuote{copies-on-modify}, no longer duplicating the \code{m*n}-length \code{x} slot in the \code{m == n} case, when it can be used directly. \item \code{lu()}, \code{lu(<0-by-n>)}, and \code{BunchKaufman(<0-by-0>)} now give sensible (0-extent) results, rather than a LAPACK error, for \code{denseMatrix}. } } \subsection{New Features}{ \itemize{ \item \code{Diagonal()} gets a new optional \code{names} argument. \item \code{diag(x) <- value} is now done in C also for \code{[CRT]sparseMatrix}. \item \code{.diagU2N()} gets fast counterpart \code{.diagN2U()}. \item \code{colSums()} and friends are now implemented more efficiently for \code{denseMatrix} and \code{[CRT]sparseMatrix}. Notably, methods for triangular and symmetric matrices no longer go via \code{generalMatrix}, and methods for \code{[CRT]sparseMatrix} now handle nonzero pattern and logical matrices directly (no longer coercing to double, a constraint of the earlier implementation using CHOLMOD). \item \code{determinant()} is now computed via the Bunch-Kaufman factorization. Factorizations are cached in the \code{factors} slot for future reuse. } } \subsection{Misc}{ \itemize{ \item Package \pkg{methods} has been moved from \code{Imports} to \code{Depends}, as suggested in the WRE manual. Now \code{as()} and other basic S4 machinery are available whenever \pkg{Matrix} is attached. This change affects \R{} processes started with environment variable \env{R_DEFAULT_PACKAGES} set to \code{NULL} (or some list not containing \pkg{methods}). \item \file{Simple.R} test for sparse \code{"POSIXlt"} example adapted to latest R-devel always having \code{"zone"} which is character. \item C-level wrappers for LAPACK \code{d..trf} routines gain an argument \code{warn} indicating how to handle \code{info > 0}: \code{warn <= 0} is silent, \code{warn = 1} is a warning, and \code{warn > 1} is an error. In the case of \code{dp[op]trf}, for which \code{info > 0} implies an incomplete factorization, \code{info} is now returned as a length-1 integer. } } } \section{Changes in version 1.5-2 (2022-10-21 r3702)}{ \subsection{Bug Fixes}{ \itemize{ \item C-level functions now \code{PROTECT()} the result of \code{R_do_slot()}, \code{getAttrib()}, \code{mkString()}, etc. in many more (but not yet all) places, resolving many new and some old \code{rchk} warnings. \item \code{lu(x)@L@uplo} is now \code{"L"}, not \code{"U"}, for 0-by-0 and 1-by-1 \code{dgCMatrix} \code{x}. \item The validity methods for classes \code{l[ts]CMatrix} now correctly test for structurally nonzero entries on the wrong side of the diagonal, and fail in that case. This test was previously only performed for \code{d[ts]Matrix}. \item The validity and initialization methods for virtual class \code{sparseVector} are more diligent, i.e., catching more edge cases such as \code{NA} in the \code{length} or \code{i} slot. \item The validity method for \code{corMatrix} now throws a better error when the \code{sd} slot is of type \code{"integer"} rather than \code{"double"}. \item \code{.sparseDiagonal()} now agrees with \code{Diagonal()} when called with no arguments, returning a 0-by-0 (rather than 1-by-1) diagonal \code{Matrix}. \item \code{sparseMatrix(i, j)} with 0-length \code{i} and \code{j} now returns a 0-by-0 matrix rather than throwing a perplexing error. \item \code{sparseMatrix(dims = )} and \code{sparseMatrix(x = )} now produce errors. \item \code{diag(x) <- value} now coerces \code{diagonalMatrix} \code{x} if \code{typeof(value)} is \dQuote{higher} than \code{typeof(x@x)} in the usual hierarchy, for consistency with methods for \code{denseMatrix} and with \code{base::`diag<-`}. \item Methods for \code{kronecker()} no longer ignore the \code{make.dimnames} argument. \item Printing a \code{sparseMatrix} with \code{NA} row or column names is no longer an error. \item Products of two \code{pMatrix} objects \code{x} and \code{y} are now computed correctly. Previously, \code{y \%*\% x} was returned instead of \code{x \%*\% y}! \item Products \code{x \%*\% y} with \code{x} a \code{diagonalMatrix} or \code{indMatrix} and \code{y} a traditional matrix or vector, or with \code{x} a traditional matrix or vector and \code{y} a \code{diagonalMatrix} or \code{pMatrix}, now treat the unclassed argument as a \code{.geMatrix} and return a \code{.geMatrix}, for greater consistency with other products involving one \code{Matrix} and one non-\code{Matrix}. \item Similarly, \code{kronecker(x, y)} with one of \code{x} and \code{y} a \code{Matrix} and the other a traditional matrix or vector now treats the unclassed argument as a \code{.geMatrix}. \item \code{dimnames(solve(x))} is now \code{rev(dimnames(x))} for \code{denseMatrix} \code{x}, consistent with the handling of \code{dimnames} by \code{solve.default}. Methods for \code{sparseMatrix} \code{x} have not been addressed (yet). } } \subsection{New Features}{ \itemize{ \item \code{is.nan(x)} is now implemented for all \code{x} inheriting from virtual class \code{Matrix} or \code{sparseVector}. \item New C-level validity methods for \code{n[ts][CRT]Matrix}, \code{p?Cholesky}, \code{p?BunchKaufman}, \code{Schur}, \code{denseLU}, \code{sparseLU}, and \code{sparseQR}. Notably, in the \code{MatrixFactorization} cases, the following properties are now checked: the dimensions of each factor, the orientation of each triangular (or trapezoidal) factor, and the validity of each permutation vector. \item \code{Diagonal(n=, x=)} now recycles \code{x} of any positive length to length \code{n}. Previously, recycling was supported only for \code{x} of length 1. \item Products involving \code{diagonalMatrix} or \code{indMatrix} have been broadly improved as follows: \itemize{ \item \code{dimnames(A \%*\% B)} is now always \code{c(dimnames(A)[1], dimnames(B)[2])}. \item \code{t?crossprod()} methods involving \code{indMatrix} or its subclass \code{pMatrix} gain a \code{boolArith} argument. \item Numeric and boolean products are always returned as \code{dMatrix} and \code{nMatrix}, respectively, except in a few special cases where the product can be represented as an \code{indMatrix}. (Previously, coercions were skipped when one of the operands was unit diagonal.) \item Products of \code{diagonalMatrix} with dense \code{triangularMatrix} now correctly give a \code{triangularMatrix} result (and without unpacking). \item Products of \code{diagonalMatrix} with \code{[RT]sparseMatrix} now preserve storage, no longer coercing to \code{CsparseMatrix}. \item \code{crossprod(x, y)} no longer requires the product of \code{ncol(x)} and \code{ncol(y)} to be less than \code{2^31} when both \code{x} and \code{y} are \code{indMatrix}. (The new implementation now always gives a \code{dgTMatrix} result, whereas previously the result would typically but not always be a \code{dgCMatrix}.) } \item \code{kronecker(, )} now gives the correct \dQuote{shape} (general, [unit] triangular, symmetric, diagonal) in all cases where it can be known without checking. \item \code{kronecker(<[CR]sparseMatrix>, )} now retains the storage of the first argument, no longer coercing to \code{TsparseMatrix}. \item New exported functions \code{dimScale}, \code{rowScale}, and \code{colScale}, for scaling rows and columns of a \code{[mM]atrix} without losing \code{dimnames} and where appropriate without losing symmetry. } } } \section{Changes in version 1.5-1 (2022-09-12 r3642)}{ \subsection{Bug Fixes}{ \itemize{ \item ASAN-detected bugs fixed in C-level functions \code{Tsparse_as_CRsparse()} (triggered by \code{.T2C(<0-by-0>)}) and \code{pMatrix_validate()} (triggered by \code{as(, "pMatrix")}). } } } \section{Changes in version 1.5-0 (2022-09-09 r3636)}{ \subsection{Deprecated and Defunct}{ \itemize{ \item With a few exceptions, direct coercions to non-virtual subclasses of \code{Matrix} (e.g., \code{dsCMatrix}) have been formally deprecated. For now, these will continue to work as before, but with a warning indicating how to accomplish the desired coercion via virtual classes (e.g., \code{symmetricMatrix}) alone. How such warnings are signaled is controlled by the global option \code{Matrix.warnDeprecatedCoerce}. \describe{ \item{\code{0} or less}{is to be silent.} \item{\code{1}}{is to signal a warning with each deprecated coercion.} \item{\code{2} or greater}{is to signal an error with each deprecated coercion.} \item{\code{NA}}{is to signal a message or warning (see below) with the next deprecated coercion and be silent after that.} } If unset or invalid, then the value of the environment variable \env{R_MATRIX_WARN_DEPRECATED_COERCE} (\code{NA} if unset) is used. This is cached when the \pkg{Matrix} namespace is loaded.\cr \cr Option values are coerced to integer before use.\cr \cr To reduce disruption to existing code, the \code{NA} case signals messages rather than warnings with coercions to the most-used non-virtual subclasses of \code{Matrix}, namely \code{dg.Matrix} and \code{d.CMatrix}. This may change in the future. } } \subsection{Bug Fixes}{ \itemize{ \item Symmetrization of \code{@Dimnames} and \code{dimnames()} now goes through C utility \code{symmDN()} in most places, resolving some earlier inconsistencies. \item Many more validity methods now correctly operate under the assumption that methods for superclasses have already been called, eliminating many redundant checks. \item Validation of \code{@Dim} now looks at type \emph{before} length, avoiding a misleading error message. \item Validation of \code{@Dimnames} now avoids \code{isNewList}, which had allowed an error message suggesting that \code{NULL} is a list. \item Setting a factor on a \code{compMatrix} is now to install the factor itself, not a copy, for efficiency and consistency with the semantics of \code{@factors[[name]] <- value}. \item Long vector support in methods for packing and unpacking \code{denseMatrix}, and others. \item \code{diag<-} incorrectly preserved the class of dense matrices, so that, e.g., \code{`diag<-`(x=, value=-1)} was still a \code{dpoMatrix}. Now the result is always one of the more general \code{.(ge|tr|sy|tp|sp)Matrix}. \item \code{t()} no longer clears the \code{sd} slot. \code{t()} now returns one of the more general \code{dt[rp]Matrix}, rather than preserving class and clearing the \code{perm} slot. \item \code{t()} no longer reverses the \code{Dimnames} slot. Symmetrization of \code{dn <- x@Dimnames} and \code{t(x)@Dimnames} had given different results when \code{dn[[1]]} and \code{dn[[2]]} were non-\code{NULL} and asymmetric. \item \code{isTriangular(x, upper)} had incorrectly returned \code{FALSE} for \code{x} of class \code{triangularMatrix} when \code{upper = TRUE} and \code{x@uplo = "L"} or when \code{upper = FALSE} and \code{x@uplo = "U"}. \code{isTriangular} is now equivalent to \code{isDiagonal} in those cases. \item \code{isSymmetric()} was equivalent to \code{isDiagonal()} for triangular matrices, \emph{not} allowing numerical fuzz via an argument \code{tol}. A \code{tol} argument is now implemented for all subclasses of \code{dMatrix} except for those inheriting from \code{symmetricMatrix} or \code{diagonalMatrix}. \item Methods for \code{isSymmetric} now also look at \code{Dimnames} and \code{names(Dimnames)}, following \code{isSymmetric.matrix} from \pkg{base}. See also New Features. \item \code{band(x, -k, k)} for sparse \code{x} used \code{isSymmetric(x)} (which tolerates numerical fuzz) to test for symmetry, resulting in loss of information in some cases. Now it tests that \code{x} inherits from \code{symmetricMatrix}, and so returns \code{symmetricMatrix} in fewer cases. \item \code{triu(x, k)} and \code{tril(x, k)} incorrectly required \code{k <= m} (instead of \code{k <= n}), for \code{m}-by-\code{n} sparse \code{x}. They now accept all \code{k} from \code{-m} to \code{n}, with fewer errors in the \code{m < n} case. \item \code{crossprod(, )} and similar now work again (optional \code{boolArith} was not passed on), fixing Matrix bug #6766 by David Cortes. Ditto for \code{tcrossprod()}, where the old result was even wrong when it had \dQuote{worked}, before \pkg{Matrix} 1.2-0. \item \code{as(, "nMatrix")} can now be sparse \emph{or} dense, going via \code{Matrix()}, for greater consistency with coercions to \code{dMatrix} and \code{lMatrix}. (Previously, the result was always an \code{ngTMatrix}.) \item \code{forceSymmetric(<[RT]sparseMatrix>)} are now more efficient, returning symmetric \code{[RT]sparseMatrix} without intermediate coercions to \code{CsparseMatrix}. \item \code{tcrossprod(a, b)} for unit triangular sparse matrices now works correctly. \item \code{!} is no longer an error in the 0-by-0 unit diagonal case. \item Coercions among \code{[CRT]sparseMatrix} preserve the \code{factors} slot in more cases. \item Coercions of overallocated \code{l.TMatrix} to \code{denseMatrix} or \code{CsparseMatrix} now give \code{TRUE} instead of \code{NA} in the \code{NA || TRUE} case, following conventional logic. \item Methods for unpacking and indexing \code{packedMatrix} and for coercing from \code{[CRT]sparseMatrix} to \code{denseMatrix} now check more consistently for overflow of \code{R_XLEN_T_MAX}. \item \code{solve(, )} is removed from the method list. It had allowed infinite recursion, e.g., with \code{solve(new("dgeMatrix"), NULL)}. \item \code{is.na()} gave \code{TRUE} where the \code{x} slot had \code{NA}. Now the result is always a zero matrix. \item \code{is.na(<.t[rp]Matrix>)} and \code{is.infinite(<.t[rp]Matrix>)} ignored the \code{diag} slot, behaving always as though \code{diag == "N"}. They now give \code{FALSE} on the diagonal in the \code{diag != "N"} case. \item Now only \dQuote{nontrivial} matrix elements determine whether \code{is.na()} is an \code{ndenseMatrix} or an \code{nsparseMatrix}. \item \code{is.na()} coerced to \code{lMatrix}. This unnecessary step is avoided now, saving a potentially nontrivial allocation. \item \code{solve(, b)} coerced the first argument to \code{dgeMatrix} when \code{b} was not a \code{ddenseMatrix} or traditional \code{matrix}. This unnecessary step is avoided now, so that specialized methods for \code{d(tr|sy|po|tp|sp|pp)Matrix} are used where possible (including for \code{b} inheriting from \code{[ln]denseMatrix}, \code{sparseMatrix}, or \code{numLike}). \item \code{`dim<-`(x, -x@Dim)} is now an error, no longer yielding an invalid \code{Matrix} object. \item \code{`dim<-`(x, x@Dim)} is now faster, returning \code{x} without allocation in all cases. \item \code{`dim<-`(x, value)} gives a better error when \code{value} contains \code{NA} or elements exceeding \code{INT_MAX}. \item \code{`dim<-`(, value)} is now an \code{RsparseMatrix}, rather than a \code{TsparseMatrix}. \item For consistency with other methods, \code{symmpart()} now always inherits from both \code{dMatrix} and \code{symmetricMatrix}, and \code{skewpart()} now always has symmetric \code{Dimnames}. \item Zeros on the diagonal of \code{skewpart(<[CRT]sparseMatrix>)} are now \emph{structural}. \item \code{as(, "(vector|matrix|[dl]Matrix)")} and \code{nnzero()} now correctly treat \code{NA} in the \code{x} slot as \code{TRUE}. \item \code{as(<[nl].TMatrix>, "dMatrix")} now correctly handles the overallocated case: data for each unique \code{[i,j]} pair are aggregated logically (\code{x1 || ... || xn}) rather than arithmetically (\code{x1 + ... + xn}), so that elements of the result are restricted to the set \code{c(0, 1, NA)}. This bug had also affected the result of \code{sum(<[nl].TMatrix>)}. \item \code{dimnames(as(x, "matrix"))} is now \code{NULL} for \emph{all} \code{x} inheriting from \code{Matrix}, when \code{x@Dimnames} is the trivial \code{list(NULL, NULL)}. \item \code{.bdiag()} no longer propagates names to the \code{Dim} slot of the result. \item \code{as(, "denseMatrix")} now correctly propagates \code{names} to the result. \item \code{as(, "lMatrix")} no longer drops non-structural zeros, for greater consistency with analogous coercions. \item \code{Matrix(x, doDiag)} now behaves as documented for diagonal matrices \code{x} with asymmetric \code{dimnames}, returning a \code{diagonalMatrix} when \code{doDiag = TRUE}, rather than a \code{triangularMatrix}. \item Matrix() now works for \code{n != 2}. \item \code{Matrix()} now works for vector lengths other than 1, no longer giving an error about length mismatch when neither of \code{nrow} and \code{ncol} are supplied. \item \code{Matrix(, doDiag = FALSE)} is now a \code{symmetricMatrix}, not a \code{diagonalMatrix}, matching the documentation of \code{doDiag}. \item \code{Matrix(<.geMatrix>, sparse = TRUE, forceCheck)} and \code{Matrix(<.g[CRT]Matrix>, sparse = FALSE, forceCheck)} now respect \code{forceCheck = FALSE} by always returning \code{generalMatrix}, i.e., \emph{not} testing for symmetric or triangular structure. \item \code{Matrix(0, nrow, )}, \code{Matrix(0, , ncol)} now throw (correct) errors for \code{nrow}, \code{ncol} in the interval \eqn{[0,1)}, consistent with \code{base::matrix()}. \item \code{sparseDefault()} now counts zeros without coercing to \code{matrix}, making \code{Matrix(, sparse = NULL)} much more efficient. \item Methods for group generic \code{Math} no longer preserve \code{x@diag == "U"} or lose \code{x@Dimnames} when \code{f(0) == 0} and \code{f(1) != 1}. (The former happened for \code{triangularMatrix} \code{x} and the latter for \code{diagonalMatrix} \code{x}.) \item \code{image(Z)} for a completely \dQuote{empty} (all 0) \code{sparseMatrix} works again (?!). \item \code{x[i, ] <- value} and \code{y[, j] <- value} is now an error in more cases for \code{m}-by-0 \code{CsparseMatrix} \code{x} and 0-by-\code{n} \code{CsparseMatrix} \code{y}. In these cases, subassignment gave a (formally) invalid result. \item \code{chol()} now calls the underlying C-level routine exactly once. Previously, it was called an extra time in order to test for positive definiteness, with the result thrown away (!). Hence these methods should become approximately two times faster. \item \code{dimnames(chol(x))} is identical to \code{dimnames(x)} in all cases, now even when \code{chol(x)} is constructed from a cached \code{MatrixFactorization}, for greater consistency with \code{base::chol.default()}. \item \code{chol()} no longer looks at \code{Dimnames} when testing for symmetry. \item \code{lu()} no longer returns an invalid \code{sparseLU} object in the lower triangular case. \item \code{lu(x)} had sometimes incorrectly cached its return value as element \code{"lu"} (rather than \code{"LU"}) of \code{x@factors}. Now it is always \code{"LU"}. \item \code{"Compare"} operators, e.g., \code{a > b}, \code{x != y}, now work correctly in more dense unitriangular and sparse 0-extent cases. \item \code{!} is now always an \code{nMatrix}, never an \code{lMatrix}. \item \code{!} and \code{which()} now correctly handle \code{NA} as \code{TRUE}. \item \code{anyNA()} had incorrectly returned \code{anyNA(.@x)} in many cases, giving false positives for some \code{.(tr|sy)Matrix} and \code{ndenseMatrix}. Now methods respect the \dQuote{rules} of these classes. \item The boolean arithmetic product \code{A \%&\% B} and e.g., \code{crossprod(A, B, boolArith=TRUE)} now should behave as if \code{drop0(A)} and \code{drop0(B)} were used, i.e., for formally sparse matrices, the boolean product results should be stable with respect to non-structural vs structural zeros. \item \code{t()} now retains the \code{factors} slot, avoiding recomputation. \item \code{qr()} no longer segfaults in some cases, but now warns about \dQuote{Out of memory} and stops, fixing Matrix bug #6610 reported by Benjamin Tyner. \item Fixed \code{ \%*\% } possible memory corruption, visible via valgrind, fixing \pkg{Matrix} bug #6726 reported by David Cortes. \item Fixed the (quite \emph{long standing}) \pkg{Matrix} bug #6777, reported by Manuel Koller: \code{tcrossprod(, <[dln]sCMatrix>)} has been wrong in some cases. } } \subsection{New Features}{ \itemize{ \item \code{KhatriRao()} gets new \code{sparseY = TRUE} option and also works for more \code{Matrix} classes. \item Virtual class \code{packedMatrix} gains methods for \code{pack}, \code{unpack}, \code{isSymmetric}, \code{isTriangular}, and \code{isDiagonal} implemented in C, replacing those defined for many subclasses individually. \item New virtual class \code{unpackedMatrix} containing \code{denseMatrix} _without_ \code{packedMatrix}, with methods for \code{pack}, \code{unpack}, \code{isSymmetric}, \code{isTriangular}, \code{isDiagonal}, \code{t}, \code{diag}, and \code{diag<-} implemented in C, replacing those defined for many subclasses individually. \item \code{isTriangular} and \code{isDiagonal} are now implemented in C also for \code{[CRT]sparseMatrix} and standard \code{matrix}. \code{isSymmetric} is now implemented in C for all \code{denseMatrix} and all \code{[CRT]sparseMatrix}, though these C routines are currently only called when testing for \emph{exact} symmetry (always for \code{[ln]Matrix}, only when \code{tol = 0} for \code{dMatrix}). \item Methods for \code{isSymmetric} gain an argument \code{checkDN = TRUE} indicating whether symmetry of \code{Dimnames} should be checked. For backwards compatibility and consistency with \code{isSymmetric.matrix} from \pkg{base}, the actual condition is \code{checkDN && check.attributes}. \item \code{isTriangular(x, upper)} now has a \code{kind} attribute \emph{if and only if} \code{x} is triangular and \code{upper} is \code{NA}. \item \code{diag() <- value} now behaves like \code{diag() <- value}, supporting coercions depending on \code{typeof(value)}, consistent with \code{diag<-} from \pkg{base}. \item \code{pack} and \code{unpack} are now identity functions for \code{packedMatrix} and \code{unpackedMatrix} arguments, respectively (previously an error). \code{pack(<.geMatrix>)} (previously an error) now behaves as \code{pack()}, i.e., by checking for symmetry or triangularity before packing. \code{unpack()} now works and is equivalent to \code{as(, "unpackedMatrix")}, with result inheriting from \code{.(ge|tr|sy)Matrix}, as appropriate. \item Many more validity methods implemented in C, for efficiency, including methods for \code{Matrix}, \code{compMatrix}, \code{diagonalMatrix}, \code{indMatrix}, \code{pMatrix}, \code{corMatrix}, \code{[liz]Matrix}, and \code{ndenseMatrix}. \item The validity method of \code{dppMatrix} now follows the validity method of \code{dpoMatrix}, requiring non-negative diagonal elements. \item Validation of \code{@Dimnames[[i]]} now tolerates vector types other than character, which are coerced to character in C via the new \code{R_DimNames_fixup()}, for greater consistency with base \code{matrix()}. \item \code{band(x, k1, k2)} is optimized further for both dense and sparse \code{x}, returning \code{triangularMatrix}, \code{symmetricMatrix}, and \code{packedMatrix} in more cases. \item \code{band()} is now implemented also for \code{diagonalMatrix} (only \code{tri[ul]()} worked before). \item Coercions \code{.ge<->.g[CRT]}, \code{.t[rp]<->.t[CRT]}, \code{.s[yp]<->.s[CRT]}, and \code{..[CRT]<->matrix} are now fully implemented and optimized, with minimal intermediate allocations. These (and others) no longer rely on CHOLMOD, which had handled integer types as double and required preprocessing in many cases (with \code{diagU2N()}, etc.). \item Fixes in group methods (e.g., \code{>}, \code{&}, \code{|}), notably for matrices inheriting from class \code{symmetricMatrix}, \code{triangularMatrix}, \code{lMatrix}, or \code{nMatrix}. \item \code{as.vector}, \code{as.numeric}, and \code{as.logical} are now implemented for all \code{Matrix}. \item Subassignment to \code{indMatrix} is no longer prohibited, now going via \code{TsparseMatrix}. \item \code{indMatrix} gains methods for \code{isTriangular}, \code{isDiagonal}, \code{diag}, \code{diag<-}, \code{band}, \code{tri[ul]}, and \code{forceSymmetric}. It also gains coercions to more virtual classes (notably \code{denseMatrix}) and a coercion to \code{pMatrix}. \item \code{solve(, )} now works in all cases. \item \code{determinant()} is now much faster in the positive definite case, no longer going via \code{dgeMatrix}. \item \code{diag(<[CRT]sparseMatrix>)} is now done in C and is highly optimized in the \code{.[ts][CR]Matrix} case. \item \code{symmpart} and \code{skewpart} are now done in C for all \code{denseMatrix} and all \code{[CRT]sparseMatrix}. Both now more faithfully preserve the \dQuote{storage} of their argument. (Previously, \code{symmpart()} was an \code{unpackedMatrix}, and \code{(symm|skew)part(<[RT]sparseMatrix>)} was a \code{CsparseMatrix}.) \item \code{as(, "([dln]?dense|[dlnCRT]?sparse)Matrix")} are now fully and more consistently implemented. In the vector case, the result is now always a \code{length}-by-1 \code{generalMatrix}. In the matrix case, structure is now always examined, hence the result is a \code{symmetricMatrix} or \code{triangularMatrix} in more cases. \item \code{Matrix()} now works for classes other than \code{table}. \item \code{lu()} and \code{lu()} now behave more consistently. In the diagonal, upper triangular, and unit lower triangular cases, the result is obtained \dQuote{directly}, i.e., without pivoting. In the non-unit lower triangular case, it is obtained with pivoting. (Previously, pivoting was never done for \code{dtCMatrix} and always done for \code{dt[rpRT]Matrix} and \code{ddiMatrix}.) \item \code{lu(x)} now caches its return value also for all \code{ds.Matrix} \code{x} (by default). \item \code{readMM()} now warns if the number of entries found is less than number reported in the header. \item \code{x[i]} now works for \code{nMatrix} \code{i}, just as for \code{lMatrix} \code{i}. This supports constructions such as \code{x[is.na(x)]}, where the logical operation produces an \code{nMatrix} because it is never \code{NA}. } } \subsection{Misc}{ \itemize{ \item \code{AZERO()} and friends gain an argument specifying a zero constant (0 for \code{int} arrays, 0.0 for \code{double} arrays). \item C-level utilities \code{(R_)?[gs]et_factors()} have been renamed \code{(R_)?[gs]et_factor()}, as they only ever get and set \emph{one} factor. \item The signature of \code{set_factor()} has been changed to match other \code{set*()} functions: to \code{(object,name,value)} from \code{(object,value,name)}. \item For clarity, \code{set_factor()} now returns \code{void} and is used like other \code{set*()} functions (i.e., for its side effect). The \R{} interface is unchanged: \code{R_set_factor()} continues to return the value being set. \item C-level utilities \code{make_[di]_matrix_(triangular|symmetric)()}, \code{packed_to_full_(double|int)()}, \code{full_to_packed_(double|int)()}, and \code{install_diagonal(_int)?()} are replaced by safer, more consistently named ones. Previous versions allowed integer overflow. \item C-level utilities \code{dup_mMatrix_as_d?geMatrix()} are replaced by the more general \code{dense_as_general()}, which takes arguments controlling memory allocation and the \dQuote{kind} of the \code{.geMatrix} result. \item New C-level utility \code{DimNames_is_symmetric()} with \R{} interface \code{isSymmetricDN()}, which should be used consistently to test for symmetry of \code{[dD]imnames}. Note that these are intended to behave consistently with \code{symmetricMatrix_validate()}, by allowing, e.g., \code{list(NULL, nms)}, but not, e.g., \code{list(A = NULL, B = nms)}. \item Coercions to \code{triangularMatrix} and \code{symmetricMatrix} are now almost all inherited from \code{Matrix}, whose methods simply call \code{tri[ul]()} and \code{forceSymmetric()} if \code{isTriangular()} and \code{isSymmetric()}, respectively, return \code{TRUE}. \item Many of the exported \code{.*2*} utilities have been redefined as aliases or wrappers of new, more general functions (see below). These not-yet-deprecated functions have been centralized in \file{R/denseMatrix.R} and \file{R/sparseMatrix.R}. \item New C-level utilities \code{R_(dense|sparse)_as_kind()} for coercion from one \dQuote{kind} to another; \code{R_(dense|sparse)_as_general()} for coercion from triangular and symmetric to general; \code{R_(dense|sparse)_band()} for coercion to triangular (and other banded); \code{R_(unpacked*|packed*|sparse)_force_symmetric()} for coercion to symmetric; \code{R_(dense|sparse)_as_(sparse|dense)()} for coercion between dense and sparse of the same \dQuote{kind} and \dQuote{structure}; \code{R_diagonal_as_sparse()} for coercion from \code{diagonalMatrix} to any \code{[CRT]sparseMatrix}; \code{R_(dense|sparse|geMatrix)_as_(matrix|vector)()} for coercion to base matrix and vector; and \code{tCRsparse_as_RCsparse()} for the idioms \code{as(t(<[CR]sparseMatrix>), "[RC]sparseMatrix")}. These all have not-yet-exported \R{} wrappers. \item \code{indTri()} and \code{indDiag()} now in C, with a new argument \code{packed} for efficiently indexing \code{packedMatrix}. \code{indDiag()} now behaves sensibly in the \code{n = 0} case. \item \code{.M.kind()}, \code{.M.shape()}, and (new) \code{.M.repr()} are now done in C via \code{R_check_class_etc()}, requiring a class definition only in \dQuote{rare} cases. } } } \section{Changes in version 1.4-1 (2022-03-21 r3446)}{ \subsection{Bug Fixes}{ \itemize{ \item \code{diag(x)} methods now mostly also keep \code{names} from \code{dimnames(x)} by default and obey \code{names=*} more generally. } } \subsection{New Features}{ \itemize{ \item New virtual class \code{packedMatrix} containing packed (dense) symmetric and triangular matrices. Methods for subscripting, including \code{diag()}, notably keeping names by default and for \code{t()} which are memory efficient, i.e., do not work via unpacking, thanks to Mikael Jagan. \item New \code{dmperm()} implementing a Dulmage-Mendelsohn decomposition, thanks to the persistency of Mauricio Vargas (@uc.cl). \item Export more low-level conversion utilities: \code{.n2dgT}, \code{.m2ngCn}, \code{.m2ngTn}. \item Provide some matrix multiplication methods for \code{"RsparseMatrix"}. } } \subsection{Misc}{ \itemize{ \item Our C sources now use \code{R_Calloc()}, \code{R_Free()} etc, instead of the shorter versions without 'R_'. Consequently, we get closer to \code{STRICT_R_HEADERS}. Also, include \code{} for \code{DBL_EPSILON}. \item \code{PROTECT()} 3 more; as from \samp{rchk} for \pkg{Matrix} 1.4-0. \item Slightly better patch notably for Windows, for \file{src/SuiteSparse_config/SuiteSparse_config.h} \item Fix to continue working for \R{} 3.5.0 and newer, providing \code{tryInvokeRestart()} for older versions of \R{}, thanking Michael Chirico for the heads up. \item Modified \code{AZERO()} to work with \code{R_xlen_t} and new \code{AZEROs()} for \code{size_t}; other tweaks to evade \code{-Wconversion} warnings. } } } \section{Changes in version 1.4-0 (2021-12-08 r3419)}{ \subsection{Bug Fixes}{ \itemize{ \item Update many \file{src/*.c} preventing integer overflow in \dQuote{pointer} and index computations for large (dense) matrices; prompted by Dario Strbenac's post to R-devel.% June 7, "dgTMatrix Segmentation Fault" \item \code{sparse.model.matrix(.., contrasts.arg = <.. ddiMatrix ..>)} now works correctly, fixing R-Forge \pkg{Matrix} bug #6673 by Davor Josipovic. \item \code{sparse.model.matrix(..)} now also works in cases the contrast matrix has become a \code{"denseMatrix"}; e.g., in a case using \code{poly(.)} in the formula; now works correctly, fixing R-Forge \pkg{Matrix} bug #6657 and useful suggestions by Nick Hanewinckel. \item Fixed the internal \code{attr.all_Mat()} auxiliary for \code{all.equal()}, notably for the case when exactly one of the matrices is a base \code{matrix}. \item Fixed long-standing bug in the \code{rbind2()} method for logical dense matrices, specifically \code{"lgeMatrix"}, thanks to the notice by Aaron Lun. \item fix leak in C-level \code{Csparse_to_dense()} thanks to Bill Dunlap in \R{}'s \PR{18204} and \code{install_lu()} called from \code{solve()} in \PR{18206}. \item fix leak in crossprod(), thanks to report and patch in \PR{18205} by Bill Dunlap. \item \code{band(M, k1, k2)} now also works when \code{k1 * k2} is larger than 2^31-1, the maximal integer, fixing R-Forge \pkg{Matrix} bug #6743 by Ariel Paulson. Further, it works when \code{M} is a sparse \code{"symmetricMatrix"} but the band is not symmetric, \code{k1 != -k2}. \item fix leak in C-level code for \code{cbind(m1,m2)} or \code{rbind(*)} when \code{m1} is \code{"n.Csparse"} and \code{m2} is not, thanks to Bill Dunlap's diagnosis and patch in \R{}'s \PR{18210}. \item \code{sparseVector(i=integer(), length=2^33)} now does show/print, after fixing a bug in the \code{head()} method for \emph{empty} sparseVectors. Reported by David Cortes as \pkg{Matrix} bug #6745. \item inverting or solving \code{dsCMatrix} no longer catches C level warnings too early which would not free, but rather leak memory; thanks to Bill Dunlap's analysis and patch in \R{}'s \PR{18214}. Additionally, such warnings and error are \code{message()}d when \code{getOption("Matrix.verbose")} is \code{>= 1}. \item \file{test-tools-1.R}: \code{Sys.memGB()} can no longer use \code{memory.limit()} on Windows; no returns \code{NA.value = 2.10201} in such cases. \item \code{ss <- [i]} gave an invalid sparseVector \code{ss} as \code{ss@i} was not necessarily sorted; thanks to a report by Quran Wu. \item \code{as(, "generalMatrix")} and similar, sometimes did \emph{not} use (C-level) \code{symmetric_Dimnames()} etc; report (to \R{}'s \PR{18250} by Mikael Jagan); fixed all on C level. As a consequence, you will now see \emph{more} preserved dimnames after matrix transformations or operations which involved symmetric matrices. \item \code{as(, "matrix")} no longer loses dimnames, thanks to Mikael Jagan's report as \pkg{Matrix} bug #6751. } } \subsection{Misc}{ \itemize{ \item No longer include \file{Rdefines.h} as it is somewhat deprecated. } } } \section{Changes in version 1.3-4 (2021-05-24 r3392)}{ \subsection{Misc}{ \itemize{ \item Update \code{matrix(, n,m)} in \file{tests/*} to work with \command{R-devel CMD check --as-cran} } } } \section{Changes in version 1.3-3 (2021-05-01 r3390)}{ \subsection{Deprecated and Defunct}{ \itemize{ \item \code{cBind()} and \code{rBind()} are now defunct: simply use \code{cbind()} and \code{rbind()} instead. } } \subsection{Dependency}{ \itemize{ \item For now revert to \code{Depends: R (>= 3.5.0)} to accomodate users on older R installations. } } \subsection{Bug Fixes}{ \itemize{ \item Fixed a thinko (in 1.3-2): Now direct coercion from \code{"ddiMatrix"} to \code{"dgCMatrix"}, and hence, e.g., \code{as(Matrix(1, sparse=TRUE), "dgCMatrix") now works.} \item Fixed error message in multiplication. \item Fixed long-standing bug in \code{R[,j] <- v} when \code{R} is "Rsparse*", R-Forge \pkg{Matrix} bug #6709 by David Cortes. \item \file{./include/cholmod.h} and \file{./include/Matrix_stubs.h} needed updating from SparseSuite update; R-Forge \pkg{Matrix} bug #6714 by Kasper Kristensen (\CRANpkg{TMB} package). \item \code{as.matrix()} and \code{as.array()} now work for \code{"sparseVector"}s as expected; see \pkg{Matrix} bug #6708. \item \code{M[,]} (and similar) now work as in base \R{}; R-Forge \pkg{Matrix} bug #6720 by David Cortes. \item \code{-S} now works also when \code{S} has no `factors` slot. It signalled an error, e.g., for sparse triangular matrices \code{S}; R-Forge \pkg{Matrix} bug #6656, reported by Chun Fung (Jackson) Kwok. \item \code{M*2} and similar no longer keep cached factorizations (in `factors` slot), but drop them via internal new \code{.empty.factors()}. R-Forge \pkg{Matrix} bug #6606, reported by Tomas Lumley. \item removed the nowhere used (and unexported but still active) class union \code{"Mnumeric"} which actually trickled into many base classes properties. Notably would it break validity of \code{factor} with a proposed change in validity checking, as factors were also \code{"Mnumeric"} but did not fulfill its validity method. Similarly removed (disabled) unused class union \code{"numericVector"}. \item removed a few duplicated \code{.alias{.}} from \file{man/*.Rd}. } } \subsection{Misc}{ \itemize{ \item translation updates (of outlines only); finally added Italian (by Daniele Medri) to svn; updated French (by Philippe Grosjean), forgotten (\R{} part of) Korean. New Lithuanian translations by Gabriele Stupuriene & Rimantas Zakauskas. \item In internal \code{diagOdiag()} method, no longer use \code{matrix(x, n,n)} when \code{x} is longer than n*n. \item Update tests/*.R to future \code{matrix(x, n,k)} warning in more mismatch cases. \item Eliminating the need for \file{ftp://*}, add the very small \code{jgl009} MatrixMarket example to our \file{external/} files. } } } \section{Changes in version 1.3-2 (2021-01-05 r3362)}{ \subsection{Bug Fixes}{ \itemize{ \item \code{rankMatrix()} tweaks for the singular values based methods, notably \code{method = "maybeGrad"}. \item \code{as(new("dtCMatrix", diag="U"), "matrix")} now works, as C-level \code{diagU2N()} now also works for 0-dimensional triangular matrices; this also fixes a subsetting (\dQuote{indexing}) bug of such 0-dimensional matrices, thanks to a report by Aaron Lun. \item logical subsetting of 0-dim. (diagonal/triangular) matrices fixes. \item The new \code{FCONE} macros added for newer Fortran/C compiler combinations are now defined back compatibly with \R{} \eqn{\ge}{>=} 3.6.0. \item \code{chol()} now works. \item \file{rchk}: fix potentially un\code{PROTECT}ed vars in \file{src/dsyMatrix.c} } } } \section{Changes in version 1.3-1 (2020-12-23 r3352)}{ \subsection{Bug Fixes}{ \itemize{ \item \code{rankMatrix(, method="qr.R")} no longer assumes non-negative diagonal entries of the \eqn{R} matrix. } } } \section{Changes in version 1.3-0 (2020-12-15 r3351)}{ \subsection{Significant User-Visible Change}{ \itemize{ \item \code{Matrix(*, doDiag=TRUE)} where \code{doDiag=TRUE} has always been the \emph{default} is now obeyed also in the sparse case, as all \code{"diagonalMatrix"} are also \code{"sparseMatrix"}. \code{Matrix(0, 3,3)} returns a \code{"ddiMatrix"} instead of a \code{"dsCMatrix"} previously. The latter is still returned from \code{Matrix(0, 3,3, doDiag=FALSE)}, and e.g., \code{.symDiagonal(3,pi)}. Also a triangular matrix, e.g., \code{"dtrMatrix"} is detected now in cases with \code{NA}s. This is both a bug fix \emph{and} an API change which breaks code that assumes \code{Matrix(.)} to return a \code{"CsparseMatrix"} in cases where it now returns a \code{"diagonalMatrix"} (which does extend \code{"sparseMatrix"}). } } \subsection{New Features}{ \itemize{ \item Subassignment to \code{"diagonalMatrix"} now returns sparse \code{"triangularMatrix"} more often; also (sparse) \code{"symmetricMatrix"}. \item \code{nearPD()} gets new option: If \code{base.matrix = TRUE}, the resulting \code{mat} component is a \pkg{base} \code{matrix}, as often used desired when \code{nearPD()} is used outside the \pkg{Matrix} package context. \item Factored out new \code{qr2rankMatrix()} utility from \code{rankMatrix()}. \item New \code{BunchKaufman()} method. \item Added \code{wrld_1deg} sparse matrix example to \emph{distributed} version of \pkg{Matrix} (no longer excluding it via \file{.Rbuildignore}). \item New (simple) \code{mat2triplet()} function to be used instead of \code{summary()} in code. \item Internal \code{.diag2tT()} gains new option \code{drop0 = TRUE} and hence now by default drops zero diagonal entries. Consequently, e.g., \code{as(, "CsparseMatrix")} now drops such zeros, too. \item Updated the crucial underlying C libraries from SuiteSparse, from 4.2.1 to 5.7.1 (from 2020-02-20), visible in \code{.SuiteSparse_version()} . \item \code{sparseMatrix()} gets new argument \code{repr = "C"}, superseding the (now deprecated) \code{giveCsparse = TRUE}. Allows to return \code{"RsparseMatrix"} matrices. Similarly, \code{rsparsematrix()}, \code{fac2sparse()} and \code{fac2Sparse()} get the new \code{repr} argument and their \code{giveCsparse} is deprecated, sometimes only informally for now.% no deprecation warning yet \item \code{sparse.model.matrix()} gets option \code{sep = ""}, with, e.g., \code{sep = ":"} allowing to get easier column names; from R-Forge \pkg{Matrix} (non-)bug #6581, by Vitalie Spinu. } } \subsection{Bug Fixes}{ \itemize{ \item \code{rankMatrix(, method="qr")} now returns \code{NA} (or \code{NaN}) instead of signalling an error in the case the sparse \eqn{Q R} decomposition gave \code{NA}s in \code{diag(R)}. \item Coercion (\code{as(., .)}) from e.g., \code{"lsyMatrix"} to \code{"CsparseMatrix"} silently made asymmetric dimnames symmetric, as did the \emph{internal} \code{forceCspSymmetric(*, dimNames)} which may be called from \code{forceSymmetric()}. \item Adapt code to new Fortran requirements of passing length of character arguments, thanks to Brian Ripley. \item (R-Forge \pkg{Matrix} bug #6659, reported by Georg Kindermann): \code{[i] <- val} bug fixed. \item (R-Forge \pkg{Matrix} bug #6666, reported by Ezra Tucker): \code{which(, array.ind=TRUE)} thinko fixed. \item For R-devel Dec 4, 2020: adapt all.equal() check of sparse matrix images (which contain panel functions with environments ..). \item tried fixing warning \emph{'cholmod_factorize_p' accessing 16 bytes in a region of size 8 [-Wstringop-overflow=]} in \file{src/dsCMatrix.c} (in two places); seen by pre-release-gcc11 compilation. } } } % \section{Changes in version 1.2-18 (2019-11-26, manually picked from svn)}{ \subsection{Bug Fixes}{ \itemize{ \item Fix last(?) \code{PROTECT()} warning found by \command{rchk} in \file{src/dense.c}'s \code{ddense_skewpart()}. \item \code{as(m, "dgTMatrix")} does not lose \code{dimnames} anymore when \code{m} is a (traditional) \code{matrix}. \item \code{M[logical(0), ]} now has dimension \eqn{0 x k} for sparse \code{M} as for base matrices. \item \code{log(M, base)} (the 2-argument version of \code{log()}) wrongly gave the result for \code{base = exp(1)}, i.e., the 1-argument default. \item \file{test-tools-Matrix.R}: \code{Qidentical()} no longer assumes \code{class()} to be of length 1. \item \file{test-tools-1.R}: provide bug-fixed \code{canCoerce()} in old \R{} versions. } } } \section{Changes in version 1.2-17 (2019-03-20, svn r3294)}{ \subsection{New Features}{ \itemize{ \item (none) } } \subsection{Bug Fixes}{ \itemize{ \item Fix new \code{PROTECT()} warnings (bugs?) found by \command{rchk}. \item Provide \code{isFALSE()} for \R{} \eqn{<} 3.5.0 as now need it for sparseMatrix printing. } } } \section{Changes in version 1.2-16 (2019-03-04, svn r3291)}{ \subsection{New Features}{ \itemize{ \item regression tests depending on \code{sample()} now are future proof reproducible, via \code{RNGversion(.)}. \item give information about #\{rows\} and #\{columns\} that are suppressed in print()ing if the matrix is larger than \code{max.print}. } } \subsection{Bug Fixes}{ \itemize{ \item \code{data()} no longer attaches \pkg{Matrix} to the search path. \item \code{"Ops"} group methods, i.e., "Arith", "Compare" & "Logic", now should all work with 0-extent matrices as well, thanks to bug reports by Aaron Lun, University of Cambridge. \item when printing and formatting sparse matrices, see \code{formatSpMatrix()}, the \code{maxp} option, e.g., from \code{getOption("max.print")}, is \dQuote{rounded up} to 100, as very small values are very rarely appropriate. } } } \section{Changes in version 1.2-15 (2018-08-20, svn r3283)}{ \subsection{New Features}{ \itemize{ \item \code{image()} gets new optional argument \code{border.color}. } } \subsection{Bug Fixes}{ \itemize{ \item \code{image(Matrix(0, n,m))} now works. } } } \section{Changes in version 1.2-14 (2018-04-08, svn r3278)}{ \subsection{New Features}{ \itemize{ \item German translation updates. } } \subsection{Bug Fixes}{ \itemize{ \item one more \code{PROTECT()}. } } } \section{Changes in version 1.2-13 (2018-03-25, svn r3275)}{ \subsection{New Features}{ \itemize{ \item Faster \code{as(, "sparseMatrix")} and coercion \code{"dgCMatrix"}, \code{"ngCMatrix"}, etc, via new direct C \code{matrix_to_Csparse()} which does \emph{not} go via \code{"dgeMatrix"}. This also works for large matrices \code{m}, i.e., when \code{length(m) >= .Machine$integer.max}. Also provide low-level \R{} functions \code{.m2dgC()}, \code{.m2lgC()}, and \code{.m2ngC()} for these. } } \subsection{Bug Fixes}{ \itemize{ \item \code{cbind(NULL,)} no longer return \code{NULL}; analogously for \code{rbind()}, \code{rbind2()}, \code{cbind2()}, fixing very long standing typo in the corresponsing \code{cbind2()} and \code{rbind2()} methods. \item The deprecation warning (once per session) for \code{cBind()} and \code{rBind()} finally works (fixing a simple thinko). \item \code{cbind()} and \code{rbind()} for largish sparse matrices no longer gives an error because of integer overflow (in the default case where \code{sparse} is not been specified hence is chosen by a \code{nnzero()} based heuristic). \item \code{.symDiagonal(5, 5:1)} and \code{.trDiagonal(x = 4:1)} now work as expected. \item \code{Sp[i]} now is much more efficient for large sparse matrices \code{Sp}, notably when the result is short. \item \code{[ ]} now also gives the correct answer when the result is \dQuote{empty}, i.e., all zero or false. \item large \code{"dspMatrix"} and \code{"dtpMatrix"} objects can now be constructed via \code{new(*, Dim = *, x = *)} also when \code{length(x)} is larger than 2^31 (as the C internal validation method no longer suffers from integer overflow). \item More \samp{PROTECT()}ing to be \dQuote{rather safe than sorry} thanks to Tomas Kalibera's check tools. } } } \section{Changes in version 1.2-12 (2017-11-10, svn r3239)}{ \subsection{New Features}{ \itemize{ \item \code{crossprod(x,y)} and \code{kronecker(x,y)} have become considerably more efficient for large \code{"indMatrix"} objects \code{x, y}, thanks to private nudging by Boris Vaillant. } } \subsection{Bug Fixes}{ \itemize{ \item (R-Forge \pkg{Matrix} bug #6185): \code{c < 0} now also works for derived sparse Matrices (which only \emph{contain} Matrix classes); via improving hidden \code{MatrixClass()}. Part of such derived matrices only work in \R{} \eqn{\ge}{>=} 3.5.0. \item using \code{Authors@R} in \file{../DESCRIPTION} to list all contributors. \item \code{solve(-m)} no longer should use a cached Cholesky factorization (of \code{m}). } } } \section{Changes in version 1.2-11 (2017-08-10, svn r3225)}{ \subsection{New Features}{ \itemize{ \item S4 method dispatch no longer emits ambiguity notes (by default) for everybody, apart from the package maintainer. You can reactivate them by \code{options(Matrix.ambiguityNotes = TRUE)} } } \subsection{Bug Fixes}{ \itemize{ \item \code{rankMatrix()} now gives zero for all methods, as it should be. \item no longer calling \code{length(NULL) <- } which has been deprecated in R-devel since July. \item \code{qr.coef(, y)} now finally has correct (row) names (from pivot back permutation). \item \code{.trDiagonal()} utility is now exported. } } } \section{Changes in version 1.2-10 (2017-04-19, svn r3216)}{ \subsection{Bug Fixes}{ \itemize{ \item quite a collection of new \code{PROTECT(.)}'s thanks to Tomas Kalibera's \sQuote{rprotect} analysis. } } } \section{Changes in version 1.2-9 (2017-03-08, svn r3211)}{ \subsection{New Features}{ \itemize{ \item \code{"Ops"} between "table", "xtabs", and our matrices now work. \item \code{as(matrix(diag(3), 3, dimnames=rep(list(c("A","b","c")),2)), "diagonalMatrix")@x} is no longer named. \item \code{norm(x, "2")} now works as well (and equivalently to \code{base::norm}). \item \code{sparseVector()} now also works without \code{x} argument. \item \code{c.sparseVector()} method for \code{c()} of sparseVectors (and available as regular function on purpose). } } \subsection{Bug Fixes}{ \itemize{ \item \code{as(Diagonal(3), "denseMatrix")} no longer returns a non-dense \code{"ddiMatrix"}. \item \code{S[sel,] <- value} and similar no longer segfault, but give a \code{"not (yet?) supported"} error for sparse matrices \code{S} and logical \code{sel} when \code{sel} contains \code{NA}s. The same error (instead of a low-level one) is signalled for \emph{indexing} (with NA-containing logical \code{sel}), i.e., \code{S[sel,]}. %% from in ../TODO : %% \item \code{S[sel,]}, \code{S[,sel] <- value} and similar now also work for %% sparse matrices \code{S} and logical \code{sel} when \code{sel} contains \code{NA}s. \item \code{which(x, arr.ind=TRUE, *)} (when \code{x} is a \code{"lMatrix"} or \code{"nMatrix"}) now works the same as \code{base::which}, obeying an optional \code{useNames} argument which defaults to \code{TRUE}. Previously, the resulting two-column matrix typically had empty \code{dimnames}. } } } \section{Changes in version 1.2-8 (2017-01-16, svn r3201)}{ \subsection{New Features}{ \itemize{ \item 0-length matrix \code{"Ops"} (binary operations) are now compatible to R-devel (to be \R{} 3.4.0). \item C-API: \code{SuiteSparse_long} is now defined as \code{int64_t} on all platforms, and we now include (C99) \file{inttypes.h} } } \subsection{Bug Fixes}{ \itemize{ \item \code{x[.] <- value} now also works for \code{"sparseVector"}'s, both as \code{x} and as \code{value}. \item \code{x[FALSE] <- value} now also works for \code{"sparseVector"}'s. \item \code{rep(x, *)} now works for \code{"sparseVector"}s and sparse and dense \code{"Matrix"}-classed matrices \code{x}. \item \code{solve()} no gives an error in some cases of singular matrices, where before the C code accessed illegal memory locations. } } } \section{Changes in version 1.2-7.1 (2016-08-29, svn r3187)}{ \itemize{ \item in C code, protect _POSIX_C_SOURCE by #ifdef __GLIBC__ } } \section{Changes in version 1.2-7 (2016-08-27, svn r3185)}{ \subsection{New Features}{ \itemize{ \item \code{cBind()} and \code{rBind()} have been almost silently deprecated in \R{} \eqn{\ge}{>=} 3.2.0 and now give a warning, \dQuote{once per session} only. \item \code{bandSparse(*, k=k, *)} now returns matrices inheriting from \code{"triangularMatrix"} when obvious from the diagonal indices \code{k}. } } \subsection{Bug Fixes}{ \itemize{ \item \code{KhatriRao(X,Y)} now also works when \code{X} or \code{Y} is completely zero. } } } \section{Changes in version 1.2-6 (2016-04-27, svn r3175)}{ \subsection{Bug Fixes}{ \itemize{ \item The 0-dim. Matrix multiplication fix in 1.2-5 did trigger wrong warnings in other diagonal matrix multiplications. } } } \section{Changes in version 1.2-5 (2016-04-14, svn r3170)}{ \subsection{New Features}{ \itemize{ \item \code{isSymmetric(m)} now also works for \code{"indMatrix"} \code{m}. \item \code{isSymmetric(m)} is faster for large dense asymmetric matrices. } } \subsection{Bug Fixes}{ \itemize{ \item Matrix multiplications (\code{A \%*\% B}) now work correctly when one of the matrices is diagonal and the other has a zero dimension. } } } \section{Changes in version 1.2-4 (2016-02-29, svn r3162)}{ \subsection{New Features}{ \itemize{ \item \code{sparseMatrix()} gets new argument \code{triangular} and a smarter default for \code{dims} when \code{symmetric} or \code{triangular} is true. \item \code{as(, "denseMatrix")} now works in more cases when \code{prod(dim(.))} is larger than \eqn{2^{31} - 1}. Hence, e.g., \code{!S} now works for much larger sparse matrices \code{S}. } } \subsection{Bug Fixes}{ \itemize{ \item creating very large dense matrices, e.g., by \code{as(, "matrix")} would segfault (in case it could allocate enough storage). } } } \section{Changes in version 1.2-3 (2015-11-19, svn r3155)}{ \subsection{New Features}{ \itemize{ \item \code{MatrixClass()} is exported now. \item More exports of semi-internal functions (for speed, named \code{"."}, i.e., inofficial API), such as \code{.solve.dgC.lu()}. \item more Korean translations } } \subsection{Bug Fixes}{ \itemize{ \item Packages \emph{linking} to \pkg{Matrix} (\code{LinkingTo:} in \file{DESCRIPTION}) now find \samp{alloca} properly defined in \file{Matrix.h} even for non-GNU compilation environments such as on Solaris or AIX. \item extended "n?CMatrix" classes (e.g., from \code{setClass(., contains="ngCMatrix")}) now can be coerced via \code{as(.)} to \code{"d.CMatrix"}. \item The printing of largish sparse matrices is improved, notably in the case where columns are suppressed, via new \code{fitWidth = TRUE} option in \code{printSpMatrix2()}. %%% FIXME __ EXAMPLES __ \item \code{cbind2()} and \code{rbind2()} no longer fail to determine \code{sparse} when it is unspecified and hence \code{NA}, fixing R-Forge bug #6259. } } } \section{Changes in version 1.2-2 (2015-07-03, svn r3131)}{ \subsection{New Features}{ \itemize{ \item Explicitly import from \dQuote{base} packages such as \pkg{stats}. } } \subsection{Bug Fixes}{ \itemize{ \item Our \code{colSums(x)}, \code{rowMeans(y)}, \dots, methods now \dQuote{keep names}, i.e., if the result is a numeric vector, and the matrix \code{x} has column or row names, these become the \code{names(.)} of the result, fixing R-Forge bug #6018. } } } \section{Changes in version 1.2-1 (2015-05-30, svn r3127)}{ \subsection{New Features}{ \itemize{ \item \code{"Matrix"} now has an \code{initialization()} method coercing 0-length dimnames components to \code{NULL} and other non-\code{NULL} dimnames to \code{character}. Before, e.g., numeric dimnames components partially worked, even though it has always been documented that non-\code{NULL} dimnames should be \code{character}. \item For \code{symmetricMatrix} objects which have symmetrical dimnames by definition, it is allowed to only set one half of the \code{dimnames} to save storage, e.g., \code{list(NULL, nms)} is \emph{semantically} equivalent to \code{list(nms, nms)}. \item \code{as.vector()} etc, now work, too. \item \code{lu()} now keeps \code{dimnames}. \item better \file{NEWS.Rd} (which pleases Kurt and \command{tidy} ;-) } } \subsection{Bug Fixes}{ \itemize{ \item \code{S[] <- T} and \code{S[] <- spV} now work (in more cases) for sparse matrices S, T and sparseVector \code{spV}. \item Huge dense matrix multiplication did lead to segfaults, see R-help, \dQuote{does segfault mean (always) a bug?}, May 5, 2015. Fixed by using C's Alloca() only in smallish cases. \item Optional arguments in \code{image()}, e.g., \code{main= <..>)} now also work for \code{lgCMatrix}, \code{nMatrix} etc; thanks to a 4.5 years old report by Mstislav Elagin. \item \code{dimnames(A) <- val} now resets the \code{factors} slot to empty, as the factorizations now keep dimnames more often. \item \code{crossprod(, Diagonal())} works again (and these are tested more systematically). \item Matrix products (\code{\%*\%}, \code{crossprod}, and \code{tcrossprod}) for \code{"dtrMatrix"} are correct in all cases, including keeping dimnames. \item \code{Matrix(d)} (and other coercions to \code{"Matrix"}) now correctly keeps \code{dimnames} also when \code{d} is a traditional \emph{diagonal} \code{"matrix"}. } } } \section{Changes in version 1.2-0 (2015-04-03, svn r3096)}{ \subsection{New Features}{ \itemize{ \item New \code{\%&\%} for \dQuote{boolean arithmetic} matrix product. \item New argument \code{boolArith = NA} in \code{crossprod()} and \code{tcrossprod()}. \code{boolArith = TRUE} now forces boolean arithmetic, where \code{boolArith = FALSE} forces numeric one. Several of these products are more efficient thanks to new C functionality based on our new \code{chm_transpose_dense()}, and others based on \code{geMatrix_crossprod}, \code{geMatrix_matrix_mm}, etc. \item Most dense matrix products, also for non-\code{dgeMatrix}, including \code{"l..Matrix"} and \code{"n..Matrix"} ones are now directly handled by new \code{.Call()}s. \item \code{"dMatrix"} (numeric) and \code{"lMatrix"} (logical) matrices can now be coerced to \code{"nMatrix"} (non-zero pattern or \dQuote{boolean}) even when they contain \code{NA}s, which then become \code{TRUE}s. \item More thorough checking of \code{cbind2()} and \code{rbind2()} methods, notably as they are called from \code{cbind()} and \code{rbind()} from \R{} \eqn{\ge}{>=} 3.2.0. \code{rbind2(, )} is faster, being based on new C code. \item symmetric Matrices (i.e., inheriting from \code{"symmetricMatrix"}) are allowed to have \code{dimnames} of the form \code{list(NULL, )} \emph{and} now print correctly and get correctly coerced to general matrices. \item \code{indMatrix} object (\dQuote{index matrices}) no longer need to be \dQuote{skinny}. \item \code{rsparseMatrix()} now accepts \code{rand.x = NULL} and then creates a random \emph{patter\bold{n}} matrix (\code{"nsparseMatrix"}). \item \code{anyDuplicatedT()} and \code{uniqTsparse()} low level utilities are exported now. \item Partial Korean translations of messages. } } \subsection{Deprecation}{ \itemize{ \item For \R{} \eqn{\ge}{>=} 3.2.0, \code{cBind()} and \code{rBind()} are deprecated, as they are no longer needed since \code{cbind()} and \code{rbind()} do work automatically. } } \subsection{Bug Fixes}{ \itemize{ \item Fix some \code{rbind2()} methods. \item \code{t()} now transposes the dimnames even for symmetric matrices. \item \code{diag(M) <- val} did not always recycle \code{val} to full length, e.g., when \code{M} was a \code{"dtrMatrix"}. \item \code{crossprod()} was wrong in cases where the matrix had all-zero columns. \item Matrix products (\code{\%*\%}, \code{crossprod}, and \code{tcrossprod}) with one sparse and one dense argument now return \emph{numeric} (a \code{"dMatrix"}) when they should, i.e., unless the new setting \code{boolArith = TRUE} is applied. } } } \section{Changes in version 1.1-5 (2015-01-18, svn r3037)}{ \subsection{New Features}{ \itemize{ \item More use of \code{anyNA()} (for speedup). \item Matrix products (\code{\%*\%}, \code{crossprod}, \code{tcrossprod}) now behave compatibly to \R{} 3.2.0, i.e., more lenient in matching dimensions for matrix - vector products. \item \code{isTriangular()} gets new optional argument \code{upper = NA}. } } \subsection{Bug Fixes}{ \itemize{ \item \code{crossprod()} and \code{tcrossprod()} fixes for several o combinations. \item \code{rowMeans(, na.rm=TRUE)} was wrong sometimes. \item fix and speedup of coercions (\code{as(., .)}) from and to symmetric or triangular matrices. \item \code{invPerm()} coercion to integer \item \code{dimnames( solve(.,.) )} fix [r3036] \item \code{tril()} and \code{triu()} now return correct \code{uplo}. \item \code{names(dimnames(.))} now preserved, e.g. in \code{symmpart()} or subsetting (\code{A[i,j]}). } } } \section{Changes in version 1.1-4 (2014-06-14, svn r2994)}{ \subsection{New Features}{ \itemize{ \item new \code{rsparsematrix()} for random sparse Matrices. \item improved warnings, notably for unused arguments previously swallowed into \code{...}. } } \subsection{Bug Fixes}{ \itemize{ \item \code{crossprod(, )} fixed. \item \code{crossprod()} and \code{kronecker()} fixes for some cases. } } } \section{Changes in version 1.1-3 (2014-03-30, svn r2982)}{ \subsection{New Features}{ \itemize{ \item \code{\%*\%} and \code{crossprod()} now also work with \code{sparseVector}s. \item speedup of \code{crossprod(v, )}, thanks to nudge by Niels Richard Hansen. \item new help page for all such matrix products (\file{../man/matrix-products.Rd}). } } \subsection{Bug Fixes}{ \itemize{ \item \code{image()} now gets correct \code{ylim} again. \item More consistent matrix products. } } } \section{Changes in version 1.1-2-2 (2014-03-04, svn r2966)}{ \subsection{Bug Fixes}{ \itemize{ \item correct adaption to \R{} 3.1.0 \item using \code{tolerance} (and not \sQuote{tol}) in \code{all.equal()} } } } \section{Changes in version 1.1-2 (2014-01-28, svn r2962)}{ \subsection{New Features}{ \itemize{ \item export fast power-user coercion utilities \code{.dsy2mat()}, \code{.dxC2mat()}, \code{.T2Cmat()}, \code{..2dge()}. } } \subsection{Bug Fixes}{ \itemize{ \item matrix products now (mostly) work with \code{sparseVector}s; and correctly in some more cases. } } } \section{Changes in version 1.1-1.1 (2013-12-30, svn r2957)}{ \itemize{ \item Testing code's \code{assertWarning()} adapted for \R{} \eqn{\le}{<=} 3.0.1. \item \code{Depends: R (>= 2.15.2)} eases checking. } } \section{Changes in version 1.1-1 (2013-12-28)}{ \subsection{New Features}{ \itemize{ \item \code{image(.., xlim, ylim)}: nicer defaults %% ../R/dgTMatrix.R for the axis limits, and \code{ylim} is sorted decreasingly; not strictly back-compatible but should never harm. \item \code{rankMatrix(*, method="qr")} now using \code{tol} \item \code{T2graph()} and \code{graph2T()} export old functionality explicitly. Tweaks in conversions between \code{"graph"} and \code{"sparseMatrix"} objects. Notably, \code{as(, )} now more often returns a (0/1 pattern) "n..Matrix". \item \code{sparseMatrix()}: new \code{use.last.ij} argument. } } \subsection{Bug Fixes}{ \itemize{ \item \code{KhatriRao()}: fix rownames (X <-> Y) \item \code{qr.coef()}, \code{qr.fitted}, and \code{qr.resid} now also work with \emph{sparse} RHS \code{y}. \item sparse matrix \dQuote{sub assignments}, e.g., \code{M[ii] <- v}, speedup and fixes. \item bug fixes also in \code{M[negative indices] <- value} and \code{[cbind(i,j)]}. } } } \section{Changes in version 1.1-0 (2013-10-21, svn r2930)}{ \subsection{New Features}{ \itemize{ \item \code{fac2sparse} and \code{fac2Sparse} now exported, with a new \code{giveCsparse} option. \item Update to latest \command{SuiteSparse} C library by Tim Davis, U. Florida. \item ensuing \dQuote{C API changes} \item new \code{.SuiteSparse_version()} function \item Many \sQuote{Imports:} instead of \sQuote{Depends:}. } } \subsection{Bug Fixes}{ \itemize{ \item fixed long lasting undetected \code{solve(, *)} bug. \item Our \code{all.equal()} methods no longer sometimes return \code{c("TRUE", "....difference..")}. \item \code{rankMatrix()}: fix the internal \code{x.dense} definition. } } } \section{Changes in version 1.0-14 (2013-09-12, svn r2907)}{ \subsection{Bug Fixes}{ \itemize{ \item Revert some wrong changes to \code{solve(, *)} from 1.0-13 (\dQuote{stop gap fix} for \R{} 3.0.2). } } } \section{Changes in version 1.0-13 (2013-09-10, svn r2904)}{ \subsection{New Features}{ \itemize{ \item New (efficient) \code{KhatriRao()} function by Michael Cysouw \item New \code{"indMatrix"} class of \dQuote{index matrices}, a generalization of \code{"pMatrix"}, the permutation matrices, many methods generalized from pMatrix to indMatrix. All (initial) functionality contributed by Fabian Scheibl, Univ.\sspace{} Munich. \item Export and document \code{isDiagonal()} and \code{isTriangular()} as they are useful outside of \pkg{Matrix}. \item \code{rankMatrix(M, method="qr")} no longer needs \code{sval} which makes it considerably more useful for large sparse \code{M}. \item Start providing \code{anyNA} methods for \R{} \eqn{\ge}{>=} 3.1.0. \item \code{solve( a, b)}: if \code{a} is symmetric, now compute \emph{sparse} result. \item \code{nearPD()} gets new option \code{conv.norm.type = "I"}. \item \code{determinant()} now uses \code{chol()}, and hence also an existing (\sQuote{cached}) Cholesky factor. \item 3 new \code{C -> R} utilities (including hidden \R{} function \code{.set.factors()} for caching also from \R{}, not just in C). } } \subsection{Bug Fixes}{ \itemize{ \item \code{M[] <- v} for unitriangular \code{M} now correct. \item \code{lu(.)} no longer sometimes returns unsorted columns. } } } %% TODO: fill in from here <<<<<<<<<<<<<<<<<<< %% ---- using ../ChangeLog and notably my ../svn-log-from.all \section{Changes in version 1.0-12 (2013-03-26, svn r2872)}{ \subsection{New Features}{ \itemize{ \item . } } \subsection{Bug Fixes}{ \itemize{ \item . } } } \section{Changes in version 1.0-11 (2013-02-02)}{ \subsection{New Features}{ \itemize{ \item . } } \subsection{Bug Fixes}{ \itemize{ \item \code{as(, "dgCMatrix")} (from package \CRANpkg{SparseM}) now works again. \item . } } } \section{Changes in version 1.0-10 (2012-10-22)}{ \subsection{New Features}{ \itemize{ \item \code{.sparseDiagonal()}: new \code{unitri} argument, and more flexibility; \item new \code{solve(, )} via efficient C code. } } \subsection{Bug Fixes}{ \itemize{ \item . } } } \section{Changes in version 1.0-9 (2012-09-05)}{ \subsection{New Features}{ \itemize{ \item new \code{sparseVector()} constructor function. \item \code{is.finite()} \code{is.infinite()} now work for our matrices and "*sparseVector" objects. \item \code{diag(.) <- V} now preserves symmetricity, triangularity and even uni-triangularity sometimes. } } \subsection{Bug Fixes}{ \itemize{ \item Quite a few fixes for \code{Ops} (arithmetic, logic, etc) group methods. \item Ditto for \code{diagonalMatrix} methods. } } } \section{Changes in version 1.0-6 (2012-03-16, publ. 2012-06-18)}{ \subsection{New Features}{ \itemize{ \item . } } \subsection{Bug Fixes}{ \itemize{ \item . } } } \section{Changes in version 1.0-5 (2012-03-15)}{ \subsection{New Features}{ \itemize{ \item . } } \subsection{Bug Fixes}{ \itemize{ \item . } } } \section{Changes in version 1.0-4 (2012-02-21)}{ \subsection{New Features}{ \itemize{ \item . } } \subsection{Bug Fixes}{ \itemize{ \item . } } } \section{Changes in version 1.0-3 (2012-01-13)}{ \subsection{New Features}{ \itemize{ \item . } } \subsection{Bug Fixes}{ \itemize{ \item . } } } \section{Changes in version 1.0-2 (2011-11-19)}{ \subsection{New Features}{ \itemize{ \item . } } \subsection{Bug Fixes}{ \itemize{ \item . } } } \section{Changes in version 1.0-1 (2011-10-18)}{ \subsection{New Features}{ \itemize{ \item . } } \subsection{Bug Fixes}{ \itemize{ \item . } } } \section{Changes in version 1.0-0 (2011-10-04)}{ \subsection{New Features}{ \itemize{ \item . } } \subsection{Bug Fixes}{ \itemize{ \item . } } } \section{Changes in version 0.9996875-3 (2011-08-13)}{ \subsection{New Features}{ \itemize{ \item . } } \subsection{Bug Fixes}{ \itemize{ \item . } } } \section{Changes in version 0.9996875-2 (2011-08-09)}{ \subsection{New Features}{ \itemize{ \item . } } \subsection{Bug Fixes}{ \itemize{ \item . } } } \section{Changes in version 0.9996875-1 (2011-08-08)}{ \subsection{New Features}{ \itemize{ \item . } } \subsection{Bug Fixes}{ \itemize{ \item . } } } \section{Changes in version 0.999375-50 (2011-04-08)}{ \subsection{New Features}{ \itemize{ \item . } } \subsection{Bug Fixes}{ \itemize{ \item . } } } % How can I add vertical space ? % \preformatted{} is not allowed, nor is \cr %--------------- start of DB+MM history: ------------------------ \section{Changes in version 0.95-1 (2005-02-18, svn r561)}{ \subsection{Authorship}{ \itemize{ \item During Doug Bates' sabbatical in Zurich, Martin Maechler becomes co-author of the \pkg{Matrix} package. } } \subsection{New Features}{ \itemize{ \item Beginning of class reorganization with a more systematic naming scheme. } } \subsection{Bug Fixes}{ \itemize{ \item More (correct) coercions \code{as(, )}. } } } \section{Changes in version 0.9-1 (2005-01-24, svn r451)}{ \subsection{New Features}{ \itemize{ \item lme4 / lmer specific \R{} code moved out to \CRANpkg{lme4} package. } } \subsection{Bug Fixes}{ \itemize{ \item . } } } % How can I add vertical space ? ( \preformatted{} is not allowed, nor is \cr ) %--------------- pre-pre-history: ------------------------ \section{Changes in version 0.8-2 (2004-04-06, svn r51)}{ \subsection{Authorship}{ \itemize{ \item Doug Bates (only) } } \subsection{New Features}{ \itemize{ \item Sparse matrices, classes and methods, partly via \item Interface to LDL, TAUCS, Metis and UMFPACK C libraries } } } % How can I add vertical space ? ................................. \section{Version 0.2-4}{ \subsection{..., 0.3-1, 0.3-n (n=3,5,...,26): 22 more CRAN releases}{ \itemize{ \item ............................................. } }} % How can I add vertical space ? % \preformatted{} is not allowed, nor is \cr \section{Version 0.2-1 (2000-07-15)}{ The first CRAN release of the \pkg{Matrix} package, titled \dQuote{A Matrix library for R} authored by Douglas Bates (maintainer, principal author) and Saikat DebRoy. \subsection{Features}{ \itemize{ \item \code{Matrix()} constructor for \R{} objects of class \code{Matrix}. \item \code{Matrix.class()} returning informal subclasses such as \code{"Hermitian"}, \code{"LowerTriangular"} \item \code{is.Orthonormal()}, \code{is.Hermitian()} , \code{is.UpperTriangular()} functions. \item \code{SVD()}, \code{lu()}, and \code{schur()} decomposition generics with \code{"Matrix"} methods. \item \code{rcond()}, \code{norm()}, \code{det()}; \code{expand()} and \code{facmul()}. \item C++ interface to LAPACK } } } Matrix/inst/po/0000755000175100001440000000000014576343415013143 5ustar hornikusersMatrix/inst/po/ko/0000755000175100001440000000000014576343415013554 5ustar hornikusersMatrix/inst/po/ko/LC_MESSAGES/0000755000175100001440000000000014576343415015341 5ustar hornikusersMatrix/inst/po/ko/LC_MESSAGES/Matrix.mo0000644000175100001440000001161314561104346017134 0ustar hornikusers#4/L +)+U3-!"<('e+0,,2D'w-.&-T&o/+@ <M$$0O@-T> QR J S NC J X ^6 C C I Hg H d '^-.(@ HMAHY!U{^J44Q800ON<# !   " 'data' must be of a vector typeArgument ij must be 2-column integer matrixArgument must be numeric-like atomic vectorMatrix exponential requires square, non-null matrixX must be a numeric (double precision) matrixX must be a real (numeric) matrixdata length exceeds size of matrixdgeMatrix_Schur: argument x must be a non-null square matrixdgeMatrix_Schur: dgees returned code %ddgeMatrix_Schur: first call to dgees faileddgeMatrix_exp: LAPACK routine dgebal returned %ddgeMatrix_exp: dgetrf returned error code %ddgeMatrix_exp: dgetrs returned error code %di and j must be integer vectors of the same lengthincorrect left cyclic shift, j (%d) < 0incorrect left cyclic shift, j (%d) >= k (%d)incorrect left cyclic shift, k (%d) > ldx (%d)invalid '%s' argumentinvalid 'ncol' value (< 0)invalid 'ncol' value (too large or NA)invalid 'nrow' value (< 0)invalid 'nrow' value (too large or NA)invalid class of 'value' in Csparse_subassign()invalid class of 'x' in Csparse_subassign()non-numeric matrix extentnumber of rows in y (%d) does not match number of rows in X (%d)programming error in Csparse_subassign() should never happensubscript 'i' out of bounds in M[ij]subscript 'j' out of bounds in M[ij]tol, given as %g, must be <= 1too many elements specifiedx[] <- val: val is coerced to logical for "%s" xx[] <- val: val should be integer or logical, is coerced to integer, for "%s" xy must be a numeric (double precision) matrixProject-Id-Version: Matrix 1.1-3 Report-Msgid-Bugs-To: PO-Revision-Date: 2015-07-15 17:14-0600 Last-Translator:Chel Hee Lee Language-Team: Chel Hee Lee Language: ko MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; 'data'는 반드시 벡터형(vector type)이어야 합니다.인자 ij는 반드시 2개의 열을 가진 정수형 행렬이어야 합니다.인자는 반드시 수치형과 같은 기본형 벡터이어야합니다행렬의 지수(exponential)은 정방이고 non-null인 행렬이어야 합니다X는 반드시 double precision을 가진 수치형 행렬이어야 합니다.X는 반드시 실수(real)형 숫자를 가진 행렬이어야 합니다.데이터의 길이(data length)가 행렬의 크기(size of matrix)를 초과합니다.dgeMatrix_Schur: 인자 x는 반드시 null이 아닌 정방(square)행렬이어야 합니다.dgeMatrix_Schur: 코드 %d가 dgees로부터 반환되었습니다.dgeMatrix_Schur: dgees로의 첫번째 호출에 실패했습니다dgeMatrix_exp: %d가 LAPACK 루틴 dgebal로부터 반환되었습니다.dgeMatrix_exp: 에러코드 %d가 dgetrf로부터 반환되었습니다.dgeMatrix_exp: 에러코드 %d가 dgetrs로부터 반환되었습니다.i와 j는 반드시 같은 길이를 가지는 정수형 벡터(integer vectors)이어야 합니다.incorrect left cyclic shift, j (%d) < 0incorrect left cyclic shift, j (%d) >= k (%d)incorrect left cyclic shift, k (%d) > ldx (%d)'%s' 인자는 유효하지 않습니다'ncol'의 값이 0보다 작으므로 올바르지 않습니다.'ncol'의 값이 너무 크거나 NA이므로 올바르지 않습니다.'nrow'의 값이 0 보다 작으므로 올바르지 않습니다.'nrow'의 값이 너무 크거나 NA이므로 올바르지 않습니다.Csparse_subassign()에서 사용되는 'value'의 클래스가 올바르지 않습니다.Csparse_subassign()에서 사용되는 'x'의 클래스가 올바르지 않습니다.non-numeric matrix extenty가 가진 행의 개수 (%d)가 X가 가진 행의 개수 (%d)와 일치하지 않습니다.Csparse_subassign()를 사용 중 발생하지 말아야 하는 프로그래밍 에러(programming error)가 발견되었습니다.첨자 'i'가 M[ij]내에 존재하지 않습니다.첨자 'j'가 M[ij]내에 존재하지 않습니다.tol의 값은 1보다 작거나 같아야 하는데 %g를 가지고 있습니다.너무 많은 요소들이 지정되었습니다x[] <- val: val is coerced to logical for "%s" xx[] <- val: val should be integer or logical, is coerced to integer, for "%s" xy는 반드시 double precision을 가진 수치형 행렬이어야 합니다.Matrix/inst/po/ko/LC_MESSAGES/R-Matrix.mo0000644000175100001440000004170614502411615017334 0ustar hornikuserssL 6 3 , 9H  6 1 / ,; *h #  , ; #4 X 4l $ W ( 0G $x 0  8 ''Oo:5#,8.e$D4%F=l-7 -*Nye"""1EwI"@ @a56. =^y"13:-Q@?=9>0x=51O'i&$&7BO(&?""*E;p%)!9>>xA (0A`r5, 76nO>I<c:H,$=Q[_@K O 4 [!?m!`!X"Eg"@"."E#_c#@#-$\2$E$$(%@%4&@I&4&J&C 'N'Hn'A'C'=(=(U(MT)))S) *b*6 +MB+J+N+?*,Cj,\,F -R-<(.<e.X.!./E//0|0o 1wy151.'2GV20202A3fB3f34b4g5[x5=5?6kR6O6U7Ed77K738&D8$k8C8B8;9eS98979O*:?z:S:;6;N;XE<D<_<dC=G=2=?#>5c>0>~>]I?e?R @C`@O@U@JAAfBBI|C -+ _[;CG=,M4QP:NX8T!ld".)Ur?J2qR7SV5*3 ji1n0$Y &IAZW'%bkEHKa9` c6s@\ L^#D]m<peo>(gBhfFO/'%s()' is not yet implemented for representation '%s''%s()' is not yet implemented for element type '%s''A' must be a square matrix'NA' indices are not (yet?) supported for sparse Matrices'by' argument is much too small'diagonals' matrix must have %d columns (= length(k) )'diagonals' must have the same length (%d) as 'k''file' must be a character string or connection'force' must be (coercable to) TRUE or FALSE'lwd' must be NULL or non-negative numeric'ncol' is not a factor of length(x)'ncol' must be >= 0'nearPD()' did not converge in %d iterations'nrow' and 'ncol' must be the same when 'symmetric' is true'nrow' is not a factor of length(x)'nrow' must be >= 0'x' must have length nrow^2 when 'symmetric' is true'x' must inherit from "sparseVector".M.repl.i.2col(): 'i' has no integer column number; should never happen; please report.M.repl.i.2col(): drop 'matrix' case ... --> is not yet implemented[i] is not yet implemented --> is not yet implementedClass %s is not yet implementedCmp.Mat.atomic() should not be called for diagonalMatrixInternal bug: nargs()=%d; please reportInvalid assembled indicator: %sInvalid storage format: %sInvalid storage type: %sLogic.Mat.atomic() should not be called for diagonalMatrixMatrices must have same number of rows for arithmeticMatrix seems negative semi-definiteMust specify 'nrow' when 'symmetric' is trueNAs are not allowed in subscripted assignmentsNot a valid formatOnly numeric sparse matrices allowedRHS 'value' (class %s) matches 'ANY', but must match matrix class %s[ ] indexing not allowed: forgot a "," ?all() is not yet implementedc(,..) of different kinds, coercing all to 'rleDiff'column indices must be <= ncol(.) which is %ddim [product %d] do not match the length of object [%d]dimnames [%d] mismatch in %selement type '%s' not recognizedelement type 'complex' not yet implementedfile is not a MatrixMarket filefor symmetric band matrix, only specify upper or lower triangle hence, all k must have the same signhit a cycle (1) -- stop iterationshit a cycle (2) -- stop iterationsi1[1] == 0 ==> C-level verbosity will not happen!index larger than maximal %dindex must be numeric, logical or sparseVector for indexing sparseVectorsinefficient method used for "- e1"intermediate 'r' is of type %sinternal bug in "Compare" method (Cmp.Mat.atomic); please reportinternal bug in "Logic" method (Logic.Mat.atomic); please reportinternal bug: matrix 'i' in replTmat(): please reportinternal bug: missing 'i' in replTmat(): please reportinvalid 'col.names' string: %sinvalid 'data'invalid (to - from)/by in seq(.)invalid character indexinginvalid nargs()= %dlength must be non-negative numberlength of 1st arg does not match dimension of 2ndlength of 2nd arg does not match dimension of firstlogic programming error in printSpMatrix2(), please reportlogical subscript too long (%d, should be %d)longer object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthm[ ] <- v: inefficiently treating single elementsmust either specify 'A' or the functions 'A.x' and 'At.x'nargs() = %d should never happen; please report.nargs() = %d. Extraneous illegal arguments inside '[ .. ]' ?negative values are not allowed in a matrix subscriptno 'dimnames[[.]]': cannot use character indexingnon-conformable argumentsnon-conformable matrix dimensions in %snot converged in %d iterationsnot enough new vecs -- stop iterationsnot yet implementednot yet implemented .. please reportnot-yet-implemented 'Matrix[<-' methodnothing to replace withnumber of items to replace is not a multiple of replacement lengthnumber of rows are not compatible for %sprod() is not yet implementedrankMatrix(x, method='qr'): computing t(x) as nrow(x) < ncol(x)representation '%s' not recognizedrow indices must be <= nrow(.) which is %dsuch indexing must be by logical or 2-column numeric matrixsum() is not yet implementedsymmetric matrix must be squaresymmetry form '%s' is not yet implementedsymmetry form '%s' not recognizedsymmetry form 'hermitian' not yet implemented for readingsymmetry form 'skew-symmetric' not yet implemented for readingthe %d-th (sub)-diagonal (k = %d) is too short; filling with NA'stoo many argumentstoo many replacement valuestype '%s' not recognizedusing "old code" part in Csparse subassignmentusing"old code" part in Csparse subassignment >>> please report to Matrix-authors@r-project.orgvariable '%s' is absent, its contrast will be ignoredvector too long in Matrix - vector operationwhen 'A' is specified, 'A.x' and 'At.x' are disregardedwrong sign in 'by' argumentx / 0 for an x with sign-change no longer representable as 'rleDiff'x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrixx[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE.x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced; NA |--> TRUE.you cannot mix negative and positive indicesProject-Id-Version: Matrix 1.1-3 PO-Revision-Date: 2015-07-15 17:14-0600 Last-Translator:Chel Hee Lee Language-Team: Chel Hee Lee Language: ko MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; 표현(representation)이 '%2$s'의 경우에 아직 구현되지 않은 '%1$s()'입니다.원소유형(element type)이 '%2$s'의 경우에 아직 구현되지 않은 '%1$s()'입니다.'A'는 반드시 정방행렬(square matrix)이어야 합니다.'NA'는 sparse Matrices에 (아직은?) 사용할 수 없는 인덱스입니다'by' 인자에 사용된 값이 너무 작습니다.'diagonals' 행렬은 반드시 %d (=length(k))개의 열을 가지고 있어야 합니다.'diagnoals'의 길이는 반드시 'k'(=%d)이어야 합니다.'file'은 반드시 문자열(character string) 또는 커넥션(connection)이어야 합니다.'force'는 반드시 (강제변환될 수 있는) TRUE 또는 FALSE 이어야 합니다.'lwd'는 반드시 NULL 또는 음이 아닌 수 이어야 합니다.'ncol'는 길이가 length(x)인 요인(factor)가 아닙니다.'ncol'은 반드시 >= 0 이어야 합니다. 'nearPD()'는 %d 번째 반복에서도 수렴하지 않았습니다.'symmetric'이 참인 경우에는 반드시 'nrow'와 'ncol'을 지정해 주어야 합니다.'nrow'는 길이가 length(x)인 요인(factor)가 아닙니다.'nrow'는 반드시 >= 0 이어야 합니다.'symmetric'이 참인 경우에는 'x'의 길이는 반드시 nrow^2와 같아야 합니다.'x'는 "sparseVector"로부터의 상속(inherit)이어야 합니다..M.repl.i.2col(): 'i'는 정수형 행번호(integer column number)을 가지고 있지 않습니다. 이런 경우는 존재할 수 없으므로 패키지 관리자에게 보고해 주시길 부탁드립니다..M.repl.i.2col(): drop 'matrix' case ... --> 은 아직 구현되지 않았습니다.[i]는 아직 구현되지 않았습니다. --> 은 아직 구현되지 않았습니다.클래스 %s는 아직 구현되지 않았습니다.Cmp.Mat.atomic()은 digonalMatrix에 의하여 호출될 수 없습니다.내부버그 발견: nargs()=%d. 꼭 보고를 부탁드립니다.Invalid assembled indicator: %s%s는 사용할 수 있는 저장형식(storage format)이 아닙니다.%s는 사용할 수 없는 저장형식(storage format)입니다.Logic.Mat.atomic()은 diagonalMatrix에 호출될 수 없습니다.원소단위의 연산을 수행하기 위해서는 입력된 각 행렬이 가지는 열의 개수가 서로 같아야 합니다.음의 반정치(negative semi-definite) 행렬 같습니다.'symmetric'이 참인 경우에는 반드시 'nrow'를 지정해 주어야 합니다.NA는 행렬의 첨자(subscripted assignment)로 사용할 수 없습니다.올바른 형식(format)이 아닙니다.오로지 수치형 희소행렬(sparse matrices)만을 사용할 수 있습니다.클래스 %s를 가지는 우변의 'value'는 'ANY'에 매치되지만, 반드시 행렬의 클래스 %s에 매치되어야 합니다.[ ]와 같은 인덱싱은 사용할 수 없습니다. ","의 사용을 잊었나요?all()는 아직 구현되지 않았습니다.c(,..) of different kinds, 모두 'rleDiff'로 강제변환합니다열에 사용되는 인덱스는 %d 보다 같거나 작아야 합니다. dim [product %d]의 값이 객체 [%d]의 길이와 일치하지 않습니다.%2$s에 입력된 dimnames [%1$d]가 일치하지 않습니다.'%s'는 사용가능한 원소유형(element type)이 아닙니다.원소유형(element type)이 'complex'인 경우에는 아직 구현되지 않았습니다.file에 MatrixMarket 형식의 파일이 입력되지 않았습니다.대칭 띠 행렬(symmetric band matrix)의 경우, 오로지 상삼각(upper triangle) 또는 하삼각(lower)만을 지정합니다. 따라서, 모든 k는 반드시 같은 부호(sign)를 가져야 합니다.cycle (1)에 도달했습니다 -- 반복을 중지합니다cycle (2)에 도달했습니다 -- 반복을 중지합니다i1[1] == 0 ==> C-레벨에서의 진행과정표시는 나타나지 않을 것입니다!인덱스가 %d 보다 큽니다.sparseVectors를 인덱싱하기 위해서는 인덱스는 반드시 수치형, 논리형 또는 sparseVectors이어야 합니다."- e1"를 사용하는데 비효율적인 메소드(method)입니다.intermediate 'r' is of type %s메소드 "Compare" (Cmp.Mat.atomic)내에서 버그(internal bug)가 발생했습니다. 이를 꼭 보고해 주셨으면 합니다.메소드 "Logic" (Logic.Mat.atomic)내에서 버그가 발생되었습니다. 이를 꼭 보고해 주셨으면 합니다.내부버그 발견: replTmat()내에서 'i'는 행렬입니다. 이를 보고해 주시길 부탁드립니다.내부버그 발견: replTmat()내에서 'i'를 찾을 수 없습니다. 이를 보고해 주시길 부탁드립니다.%s은 올바른 'col.names' 문자열이 아닙니다입력된 'data'는 올바르지 않습니다.seq(.)의 사용시 (to - from)/by의 값이 올바르지 않습니다.유효하지 않은 문자형 인덱싱입니다nargs()= %d의 값이 올바르지 않습니다.길이(length)는 반드시 음이 아닌 수이어야 합니다.첫번째 인자(arg)의 길이는 두번째 인자의 차원(dimension)과 일치하지 않습니다.두번째 인자(arg)의 길이가 첫번째 인자의 차원(dimension)과 일치하지 않습니다.printSpMatrix2()를 이용 도중 논리적 프로그래밍 에러(logic programming error)가 발생했습니다. 이를 꼭 보고를 부탁드립니다.길이가 너무 긴 논리형 첨자(subscript)입니다 (%2$d이어야 하는데 %1$d입니다).객체의 길이(긴 것)가 다른 객체가 가지는 길이(짧은 것)의 배수가 아닙니다.객체의 길이(긴 것)이 다른 객체의 길이(짧은 것)의 배수가 아닙니다.m[ ] <- v: inefficiently treating single elements'A' 또는 'A.x'와 'At.x'는 반드시 주어져야 합니다.nargs() = %d 와 같은 경우는 발생할 수 없으므로 꼭 보고해 주시기를 부탁드립니다.nargs() = %d. 필요이상의 인자들이 '[ .. ]' 내에 이용되었나요?음수(negative values)는 행렬의 첨자(subscript)로 사용할 수 없습니다.no 'dimnames[[.]]': 문자형 인덱싱을 사용할 수 없습니다non-conformable arguments%s에 입력된 행렬의 차원이 정합(conformable)하지 않습니다.%d번째 반복에서도 수렴하지 않습니다.not enough new vecs -- stop iterations아직 구현되지 않았습니다.아직 구현되지 않았습니다. 보고를 부탁드립니다.아직 구현되지 않은 'Matrix[<-' 메소드입(method)니다.교체(replace)해야 할 것이 아무것도 없습니다.교체(replace)할 항목의 개수가 입력된 value가 가지는 길이의 배수가 아닙니다.%s의 경우 행의 개수가 올바르지 않습니다.prod()는 아직 구현되지 않았습니다.rankMatrix(x, method='qr'): nrow(x) < ncol(x)이므로 t(x)를 계산합니다.'%s'는 사용가능한 표현(representation)이 아닙니다.행에 사용되는 인덱스는 반드시 %d 보다 같거나 작아야 합니다.이와 같은 유형의 인덱싱(indexing)은 반드시 논리형(logical) 또는 2개의 열로 구성된 수치형(numeric) 행렬에 의해서만 이루어져야 합니다.sum()는 아직 구현되지 않았습니다.대칭행렬(symmetric matrix)는 반드시 정방(square)이어야 합니다.대칭형식(symmetry form)이 '%s'인 경우에는 아직 구현되지 않았습니다.'%s'는 사용가능한 대칭형식(symmetry form)이 아닙니다.대칭형식(symmetry form)이 'hermitian'의 경우에는 아직 구현되지 않았습니다.대칭형식(symmetry form)이 'skew-symmetric'인 경우에는 아직 구현되지 않았습니다.%d-번째 (부분)-대각 (k = %d)이 너무 짧아 NA로 채웁니다.입력된 인자의 개수가 너무 많습니다.교체에 이용될 값이 너무 많이 입력되었습니다.'%s'는 사용가능한 유형(type)이 아닙니다.using "old code" part in Csparse subassignmentusing"old code" part in Csparse subassignment >>> Matrix-authors@r-project.org으로 이를 보고해 주시길 바랍니다.변수 '%s'를 찾을 수 없어 관련 대비(contrast)는 계산되지 않을 것입니다.행렬과 벡터 연산(Matrix - vector operation)에 사용될 벡터의 길이가 너무 깁니다.'A'가 주어진 경우에 입력된 'A.x'와 'At.x'는 사용되지 않습니다.'by' 인자에 사용된 부호(sign)가 올바르지 않습니다.x / 0 for an x with sign-change no longer representable as 'rleDiff'x[.,.] <- val : Tsparse* 에서 CsparseMatrix로 강제변환(coerced)된 x입니다.x[.,.] <- val: x의 클래스는 %s입니다. {TRUE, FALSE}에 해당하지 않는 val의 값은 TRUE로 강제변환(coerced) 되었습니다. x[.,.] <- val: x의 클래스는 %s입니다. {TRUE, FALSE}에 해당하지 않는 val의 값은 강제변환(coerced) 되었습니다. x[.] <- val: x의 클래스는 %s입니다. {TRUE, FALSE}에 해당하지 않는 val의 값은 강제변환(coerced) 되었습니다.x[.] <- val: x의 클래스는 %s입니다. {TRUE, FALSE}에 해당하지 않는 val의 값은 TRUE로 강제변환(coerced) 되었습니다.인덱스에 음수와 양수를 혼용하여 사용할 수 없습니다.Matrix/inst/po/fr/0000755000175100001440000000000014576343415013552 5ustar hornikusersMatrix/inst/po/fr/LC_MESSAGES/0000755000175100001440000000000014576343415015337 5ustar hornikusersMatrix/inst/po/fr/LC_MESSAGES/Matrix.mo0000644000175100001440000001074014561104346017132 0ustar hornikusers$<5\01+Q+}3-! "-<P'+0,,?2l'-.$:&U|&/+@4<u%$$"A0]O-\ !i < V D 7d / 8 G 6M 6 6 5 5( =^ 2 8 9BZ+y+51&"XM{R6 S t%"L|+7 $" ! # 'data' must be of a vector typeArgument ij must be 2-column integer matrixArgument must be numeric-like atomic vectorMatrix exponential requires square, non-null matrixX must be a numeric (double precision) matrixX must be a real (numeric) matrixdata length exceeds size of matrixdgeMatrix_Schur: argument x must be a non-null square matrixdgeMatrix_Schur: dgees returned code %ddgeMatrix_Schur: first call to dgees faileddgeMatrix_exp: LAPACK routine dgebal returned %ddgeMatrix_exp: dgetrf returned error code %ddgeMatrix_exp: dgetrs returned error code %di and j must be integer vectors of the same lengthincorrect left cyclic shift, j (%d) < 0incorrect left cyclic shift, j (%d) >= k (%d)incorrect left cyclic shift, k (%d) > ldx (%d)invalid '%s' argumentinvalid 'ncol' value (< 0)invalid 'ncol' value (too large or NA)invalid 'nrow' value (< 0)invalid 'nrow' value (too large or NA)invalid class of 'value' in Csparse_subassign()invalid class of 'x' in Csparse_subassign()non-numeric matrix extentnumber of rows in y (%d) does not match number of rows in X (%d)programming error in Csparse_subassign() should never happenreplacement diagonal has wrong lengthsubscript 'i' out of bounds in M[ij]subscript 'j' out of bounds in M[ij]tol, given as %g, must be <= 1too many elements specifiedx[] <- val: val is coerced to logical for "%s" xx[] <- val: val should be integer or logical, is coerced to integer, for "%s" xy must be a numeric (double precision) matrixProject-Id-Version: Matrix 1.1-1 Report-Msgid-Bugs-To: PO-Revision-Date: 2021-04-12 18:57+0200 Last-Translator: Philippe Grosjean Language-Team: none Language: fr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n > 1); X-Generator: Poedit 2.4.2 'data' doit être de type vecteurL'argument ij doit être une matrice d'entiers à 2 colonnesL'argument doit être un vecteur atomique de type numérique ou convertible en nombresL'exponentiation de matrice nécessite une matrice carrée non nulleX doit être une matrice numérique (double précision)X doit être une matrice (numérique) de réelsla longueur des données excède la taille de la matricedgeMatrix_Schur : l'argument x doit être une matrice carrée non nulledgeMatrix_Schur : dgees a renvoyé le code d'erreur %ddgeMatrix_Schur : le premier appel à dgees a échouédgeMatrix_exp : la routine LAPACK dgebal a renvoyé %ddgeMatrix_exp : dgetrf a renvoyé le code d'erreur %ddgeMatrix_exp : dgetrs a renvoyé le code d'erreur %di et j doivent être des vecteurs d'entiers de même longueurdécalage cyclique à gauche incorrect, j (%d) < 0décalage cyclique à gauche incorrect, j (%d) >= k (%d)décalage cyclique à gauche incorrect, k (%d) > ldx (%d)argument '%s' incorrectvaleur 'ncol' incorrecte (< 0)valeur 'ncol' incorrecte (trop large ou NA)valeur 'nrow' incorrecte (< 0)valeur 'nrow' incorrecte (trop large ou NA)classe de 'value' incorrecte dans Csparse_subassign()classe de 'x' incorrecte dans Csparse_subassign()étendue de matrice non numériquele nombre de lignes de y (%d) ne correspond pas au nombre de lignes de X (%d)erreur de programmation dans Csparse_subassign() qui ne devrait jamais se produirela diagonale de remplacement a une longueur incorrecteindice 'i' hors plage dans M[ij]indice 'j' hors plage dans M[ij]tol, donné comme %g, doit être <= 1trop d'éléments sont spécifiésx[] <- val: val est converti automatiquement en valeurs logiques pour "%s" xx[] <- val: val devrait être des entiers ou des valeurs booléennes, il est converti automatiquement en entiers pour "%s" xy doit être une matrice numérique (double précision)Matrix/inst/po/fr/LC_MESSAGES/R-Matrix.mo0000644000175100001440000004111614521047060017325 0ustar hornikusers,< 6 3( \ 9x  6 1 /; ,k ? : * #> b ,v ; # 4$LWq(0$#0Hy8'5:N5#,.?$RDw4D%6=\-7 *>ie""15gI"@@Q56(- Vw":91>3p:-@ ?N=2909=j51'*R&q$&B(S&|Bv?]"*;%'M"d)!9>AA 0+4\0`5# ,Y 7  O >*!Ii!<!:!H+",t"E"?#B'$"j$M$'$=%5A%=w%1%?%C'&/k&'&&-&E''N'v'?'#''/v(6(*(6)+?)Ak)3)&)!***CJ*X*,*6+AK++9+}+H^,Q,,,N&-;u-A-#-!.;9.,u..22/2e/N/+/_0)s0$0R0R1Dh1E121&2172$i2.22-2F3EH3B3E3M4/e4b4a4BZ5M575D#6Ch6H6U67K7,7$747 81"8-T88X8%8-9GF99C+:!o:9:i:,5;b;'};;);9;)"<PL<U<V<J=[=*{==?=L=KI>><!?6^?F?$?`@Lb@^@QAO`A^A>Bo],WOc?3j_Cs5}6P{ F<Xl%VfxSU#Hb)+g!zIra|9 1 Z*`/nA$4wmMKh\JB-0t&7DN2"E i;^d[qu'pL:Ry= @vQY(.>eGT~8k'%s()' is not yet implemented for representation '%s''%s()' is not yet implemented for element type '%s''A' must be a square matrix'NA' indices are not (yet?) supported for sparse Matrices'by' argument is much too small'diagonals' matrix must have %d columns (= length(k) )'diagonals' must have the same length (%d) as 'k''file' must be a character string or connection'force' must be (coercable to) TRUE or FALSE'giveCsparse' has been deprecated; setting 'repr = "T"' for you'giveCsparse' has been deprecated; will use 'repr' instead'lwd' must be NULL or non-negative numeric'ncol' is not a factor of length(x)'ncol' must be >= 0'nearPD()' did not converge in %d iterations'nrow' and 'ncol' must be the same when 'symmetric' is true'nrow' is not a factor of length(x)'nrow' must be >= 0'x' must have length nrow^2 when 'symmetric' is true'x' must inherit from "sparseVector".M.repl.i.2col(): 'i' has no integer column number; should never happen; please report.M.repl.i.2col(): drop 'matrix' case ... --> is not yet implemented[i] is not yet implemented --> is not yet implementedClass %s is not yet implementedCmp.Mat.atomic() should not be called for diagonalMatrixInternal bug: nargs()=%d; please reportInvalid assembled indicator: %sInvalid storage format: %sInvalid storage type: %sLogic.Mat.atomic() should not be called for diagonalMatrixMatrices must have same number of rows for arithmeticMatrix seems negative semi-definiteMust specify 'nrow' when 'symmetric' is trueNAs are not allowed in subscripted assignmentsNot a valid formatOnly numeric sparse matrices allowedRHS 'value' (class %s) matches 'ANY', but must match matrix class %s[ ] indexing not allowed: forgot a "," ?a sparseMatrix should rarely be centered: will not be sparse anymoreall() is not yet implementedc(,..) of different kinds, coercing all to 'rleDiff'column indices must be <= ncol(.) which is %ddim [product %d] do not match the length of object [%d]dimnames [%d] mismatch in %selement type '%s' not recognizedelement type 'complex' not yet implementedfile is not a MatrixMarket filefor symmetric band matrix, only specify upper or lower triangle hence, all k must have the same signhit a cycle (1) -- stop iterationshit a cycle (2) -- stop iterationsi1[1] == 0 ==> C-level verbosity will not happen!index larger than maximal %dindex must be numeric, logical or sparseVector for indexing sparseVectorsinefficient method used for "- e1"intermediate 'r' is of type %sinternal bug in "Compare" method (Cmp.Mat.atomic); please reportinternal bug in "Logic" method (Logic.Mat.atomic); please reportinternal bug: matrix 'i' in replTmat(): please reportinternal bug: missing 'i' in replTmat(): please reportinvalid 'col.names' string: %sinvalid 'data'invalid 'repr'; must be "C", "T", or "R"invalid (to - from)/by in seq(.)invalid character indexinginvalid nargs()= %dlength must be non-negative numberlength of 'center' must equal the number of columns of 'x'length of 'scale' must equal the number of columns of 'x'length of 1st arg does not match dimension of 2ndlength of 2nd arg does not match dimension of firstlogic programming error in printSpMatrix2(), please reportlogical subscript too long (%d, should be %d)longer object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthm[ ] <- v: inefficiently treating single elementsmatrix can only be symmetric if square, but n != mmust either specify 'A' or the functions 'A.x' and 'At.x'nargs() = %d should never happen; please report.nargs() = %d. Extraneous illegal arguments inside '[ .. ]' ?negative values are not allowed in a matrix subscriptno 'dimnames[[.]]': cannot use character indexingnon-conformable argumentsnon-conformable matrix dimensions in %snot converged in %d iterationsnot enough new vecs -- stop iterationsnot yet implementednot yet implemented .. please reportnot-yet-implemented 'Matrix[<-' methodnothing to replace withnumber of items to replace is not a multiple of replacement lengthnumber of rows are not compatible for %sprod() is not yet implementedqr2rankMatrix(.): QR with only %d out of %d finite diag(R) entriesrankMatrix(, method = '%s') coerces to dense matrix. Probably should rather use method = 'qr' !?rankMatrix(x, method='qr'): computing t(x) as nrow(x) < ncol(x)representation '%s' not recognizedrow indices must be <= nrow(.) which is %dsuch indexing must be by logical or 2-column numeric matrixsum() is not yet implementedsuppressing %d columnssuppressing %d columns and %d rowssuppressing %d rowssymmetric matrix must be squaresymmetry form '%s' is not yet implementedsymmetry form '%s' not recognizedsymmetry form 'hermitian' not yet implemented for readingsymmetry form 'skew-symmetric' not yet implemented for readingthe %d-th (sub)-diagonal (k = %d) is too short; filling with NA'stoo many argumentstoo many replacement valuestriangular matrix must be squaretype '%s' not recognizeduniDiag=TRUE, but not all diagonal entries are 1uniDiag=TRUE, not all entries in diagonal coded as 1using "old code" part in Csparse subassignmentusing"old code" part in Csparse subassignment >>> please report to Matrix-authors@r-project.orgvariable '%s' is absent, its contrast will be ignoredvector too long in Matrix - vector operationwhen 'A' is specified, 'A.x' and 'At.x' are disregardedwrong sign in 'by' argumentx / 0 for an x with sign-change no longer representable as 'rleDiff'x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrixx[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE.x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced; NA |--> TRUE.you cannot mix negative and positive indicesProject-Id-Version: Matrix 1.1-1 PO-Revision-Date: 2021-02-11 11:04+0100 Last-Translator: Philippe Grosjean Language-Team: none Language: fr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: Poedit 2.4.2 Plural-Forms: nplurals=2; plural=(n > 1); '%s' n'est pas encore implémenté pour la représentation '%s''%s()' n'est pas encore implémenté pour le type d'élément '%s''A' doit être une matrice carréeles indices 'NA' ne sont pas (encore?) supportés pour les Matrices éparsesl'argument 'by' est beaucoup trop petitune matrice 'diagonals' doit avoir %d colonnes (= length(k) )'diagonals' doit avoir la même longueur (%d) que 'k''file' doit être une chaîne de caractères ou une connexion'force' doit être (convertible en) TRUE ou FALSE'giveCsparse' est obsolète ; j’ai mis 'repr = "T"' pour vous‘giveCsparse’ est obsolète ; utilisation de 'repr' à la place'lwd' doit être un nombre non négatif ou NULL'ncol' n'est pas un factor de length(x)'ncol' doit être >= 0'nearPD()' n'a pas converti en %d itérations'now' et 'ncol' doivent être les mêmes lorsque 'symmetric' est vrai'nrow' n'est pas un factor de length(x)'nrow' doit être >= 0'x' doit avoir une longueur nrow^2 lorsque 'symmetric' est vrai'x' doit hériter de "sparseVector".M.repl.i.2col() : 'i' n'a pas un nombre entier de colonnes ; ceci ne devrait pas se produite. Veuillez envoyer un rapport de bogue.M.repl.i.2col() : cas 'matrix' non traité ... --> n'est pas encore implémenté[i] n'est pas encore implémenté --> n'est pas encore implémentéLa classe %s n'est pas encore implémentéeCmp.Mat.atomic() ne devrait pas être appelé pour diagonalMatrixBogue interne : nargs()=%d ; veuillez reporter ceciIndicateur d'assemblage incorrect : %sFormat de stockage incorrect : %sType de stockage incorrect : %sLogic.Mat.atomic() ne devrait pas être appelé pour diagonalMatrixLes matrices doivent avoir le même nombre de lignes pour les opérations arithmétiquesLa matrice semble négative et semi-définieIl faut spécifier 'nrow' lorsque 'symmetric' est vraiLes NAs ne sont pas autorisés dans les assignations avec indicesPas un format acceptableSeules les matrices éparses numériques sont autoriséesLa 'value' du membre gauche de l'équation (classe %s) correspond à 'ANY', mais doit correspondre à la classe de matrice %sindiçage [ ] non permis : n'avez-vous pas oublié une "," ?une sparseMatrix doit rarement être centrée : elle ne sera plus éparse ensuiteall() n'est pas encore implémentéc(,..) de différentes sortes, convertis automatiquement en 'rleDiff"les indices de colonnes doivent être <= ncol(.) qui est %ddim [product %d] ne correspond pas à la longueur de l'objet [%d]dimnames [%d] incohérentes dans %stype d'élément '%s' non reconnule type d'élément 'complex' n'est pas encore implémentéle fichier n'est pas un fichier MatrixMarketpour une matrice de bande symétrique, spécifiez seulement le triangle supérieur ou inférieur donc, tous les k doivent avoir le même signeun cycle est atteint (1) -- arrêt des itérationsun cycle est atteint (2) -- arrêt des itérationsi1[1] == 0 ==> au niveau C, aucune information détaillée ne sera affichée !indice plus grand que la valeur maximale %dles indices doivent être numériques, booléens ou sparseVector pour l'indiçage sparseVectorsméthode inefficace utilisée pour "- e1"le 'r' intermédiaire est de type %sbogue interne dans la méthode "Compare" (Cmp.Mat.atomic) ; veuillez reporter cecibogue interne dans la méthode "Logic" (Logic.Mat.atomic) ; veuillez reporter cecibogue interne : matrice 'i' dans replTmat() : veuillez reporter cecibogue interne : 'i' manquant dans replTmat() : veuillez reporter cecichaîne de caractères 'col.names' incorrecte : %s'data' incorrect'repr' incorrect ; il doit être "C", "T", ou "R"(to - from)/by incorrect dans seq(.)indiçage de chaînes de caractères incorrectnargs()= %d incorrectla longueur doit être un nombre non négatifla longueur de 'center' doit être égale au nombre de colonnes de 'x'la longueur de 'scale' doit être égale au nombre de colonnes de 'x'la longueur du 1er arg ne correspond pas à la dimension du secondla longueur du 2ème arg ne correspond pas à la dimension du premiererreur logique de programmation dans printSpMAtrix2(), veuillez reporter ceciindice logique trop long (%d, devrait être %d)la longueur de l'objet le plus long n'est pas un multiple de la longueur de l'objet le plus courtla longueur de l'objet le plus long n'est pas un multiple de la longueur de l'objet le plus courtm[ ] <- v : traitement inefficace d'éléments uniquesune matrice peut seulement être symétrique si elle est carrée, mais n != mil faut spécifier 'A' ou les fonctions 'A.x' et 'At.x'nargs() = %d ne devrait jamais se produire ; veuillez reporter ceci.nargs() = %d. Arguments supplémentaires dans '[ .. ]' illégaux ?les valeurs négatives ne sont pas permises dans les indices de matricespas de 'dimnames[[.]]' : impossible d'utiliser un indiçage de chaîne de caractèresmatrices de dimensions incompatibles dans les argumentsmatrices de dimensions incompatibles dans %spas de convergence en %d itérationspas assez de nouveaux vecs -- arrêt des itérationspas encore implémentépas encore implémenté .. veuillez reporter ceciméthode 'Matrix[<-' non encore implémentéerien à remplacer avecle nombre d'éléments à remplacer n'est pas un multiple de la longueur de remplacementnombre incompatible de lignes pour %sprod() n'est pas encore implémentéqr2rankMatrix(.): QR avec seulement %d de %d entrées finies de diag(R)rankMatrix(, method = '%s') converti automatiquement en matrice dense. Il faudrait probablement plutôt utiliser une méthode = 'qr' ?rankMatrix(x, method='qr') : calcul de t(x) comme nrow(x) < ncol(x)représentation '%s' non reconnueles indices de lignes doivent être <= nrow(.) qui est %dun tel indiçage doit être réalisé avec un vecteur booléen ou une matrice numérique à deux colonnessum() n'est pas encore implémentésuppression de %d colonnessuppression de %d colonnes et %d lignessuppression de %d lignesla matrice symétrique doit être carréela forme de symétrie '%s' n'est pas encore implémentéela symétrie n'est pas reconnue pour '%s'la forme de symétrie 'hermitian' n'est pas encore implémentée pour la lecturela forme de symétrie 'skew-symmetric' n'est pas encore implémentée pour la lecturela %d-ième (sous)-diagonale (k = %d) est trop courte ; elle est repliée avec des NAstrop d'argumentstrop de valeurs de remplacementla matrice triangulaire doit être carréetype '%s' non reconnuuniDiag=TRUE, mais pas toutes les entrées diagonales sont à 1uniDiag=TRUE, toutes les entrées de la diagonale ne sont pas encodées à 1utilisation d'une partie d'"ancien code" dans une sous-assignation Csparseutilisation d'une partie d'"ancien code" dans une sous-assignation Csparse >>> veuillez envoyer un rapport à Matrix-authors@r-project.orgla variable '%s' est absente, ses contrastes seront ignorésvecteur trop long dans une opération Matrix - vecteurlorsque 'A' est spécifié, 'A.x' et 'At.x' ne sont pas pris en comptesigne incorrect dans l'argument 'by'x / 0 pour un x avec changement de signe il n'est plus représentable comme 'rleDiff'x[.,.] <- val: x est converti automatiquement de Tsparse* vers CsparseMatrixx[.,.] <- val: x vaut %s, val qui ne sont pas dans {TRUE, FALSE} sont convertis NA |--> TRUE.x[.,.] <- val: x vaut %s, val qui ne sont pas dans {TRUE, FALSE} sont convertis.x[.] <- val: x vaut %s, val qui ne sont pas dans {TRUE, FALSE} sont convertis.x[.] <- val: x vaut %s, val qui ne sont pas dans {TRUE, FALSE} sont convertis ; NA |--> TRUE.vous ne pouvez pas mélanger des indices négatifs et positifsMatrix/inst/po/it/0000755000175100001440000000000014576343415013557 5ustar hornikusersMatrix/inst/po/it/LC_MESSAGES/0000755000175100001440000000000014576343415015344 5ustar hornikusersMatrix/inst/po/it/LC_MESSAGES/Matrix.mo0000644000175100001440000001057614561104346017146 0ustar hornikusers$<5\01+Q+}3-! "-<P'+0,,?2l'-.$:&U|&/+@4<u%$$"A0]O-~ ! = 2 D 6c ) 8 H 1F /x 8 : : ?W / 5 6 4N,m,3/%JIpK0"7"Z&}2T5H $" ! # 'data' must be of a vector typeArgument ij must be 2-column integer matrixArgument must be numeric-like atomic vectorMatrix exponential requires square, non-null matrixX must be a numeric (double precision) matrixX must be a real (numeric) matrixdata length exceeds size of matrixdgeMatrix_Schur: argument x must be a non-null square matrixdgeMatrix_Schur: dgees returned code %ddgeMatrix_Schur: first call to dgees faileddgeMatrix_exp: LAPACK routine dgebal returned %ddgeMatrix_exp: dgetrf returned error code %ddgeMatrix_exp: dgetrs returned error code %di and j must be integer vectors of the same lengthincorrect left cyclic shift, j (%d) < 0incorrect left cyclic shift, j (%d) >= k (%d)incorrect left cyclic shift, k (%d) > ldx (%d)invalid '%s' argumentinvalid 'ncol' value (< 0)invalid 'ncol' value (too large or NA)invalid 'nrow' value (< 0)invalid 'nrow' value (too large or NA)invalid class of 'value' in Csparse_subassign()invalid class of 'x' in Csparse_subassign()non-numeric matrix extentnumber of rows in y (%d) does not match number of rows in X (%d)programming error in Csparse_subassign() should never happenreplacement diagonal has wrong lengthsubscript 'i' out of bounds in M[ij]subscript 'j' out of bounds in M[ij]tol, given as %g, must be <= 1too many elements specifiedx[] <- val: val is coerced to logical for "%s" xx[] <- val: val should be integer or logical, is coerced to integer, for "%s" xy must be a numeric (double precision) matrixProject-Id-Version: Matrix 1.3-3 Report-Msgid-Bugs-To: PO-Revision-Date: 2021-04-14 12:18+0200 Last-Translator: Daniele Medri Language-Team: Italian https://github.com/dmedri/R-italian-lang Language: it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); X-Generator: Poedit 2.2.1 'data' dev'essere un tipo vettoreL'argomento ij dev'essere una matrice di interi con 2 colonneL'argomento dev'essere un vettore atomico numericoL'esponenziale della matrice richiede una matrice quadrata non nullaX deve essere una matrice numerica (doppia precisione)X dev'essere una matrice (numerica) realela lunghezza dei dati eccede la dimensione della matricedgeMatrix_Schur: l'argomento x dev'essere una matrice quadrata non nulladgeMatrix_Schur: dgees ha restituito il codice %ddgeMatrix_Schur: prima chiamata a dgees fallitadgeMatrix_exp: la routine LAPACK dgebal ha restituito %ddgeMatrix_exp: dgetrf ha restituito il codice di errore %ddgeMatrix_exp: dgetrs ha restituito il codice di errore %di e j devono essere vettori di interi con la medesima lunghezzaspostamento ciclico sinistro errato, j (%d) < 0spostamento ciclico sinistro errato, j (%d) >= k (%d)spostamento ciclico sinistro errato, k (%d) > ldx (%d)argomento '%s' non validovalore 'ncol' non valido (< 0)valore 'ncol' non valido (troppo larga o NA)valore 'nrow' non valido (< 0)valore 'nrow' non valido (troppo largo o NA)classe di 'value' in Csparse_subassign() non validaclasse of 'x' in Csparse_subassign() non validaestensione della matrice non numericail numero di righe in y (%d) non corrisponde al numero di righe in X (%d)l'errore di programmazione in Csparse_subassign() non dovrebbe mai accaderela diagonale di ricambio ha una lunghezza erratasubscript 'i' fuori banda in M[ij]subscript 'j' fuori banda in M[ij]tol, indicato come %g, dev'essere <= 1specificati troppi elementix[] <- val: val è convertito in logico per x "%s"x[] <- val: val dovrebbe essere intero o logico, è convertito in intero, per x "%s"y dev'essere una matrice numerica (doppia precisione)Matrix/inst/po/it/LC_MESSAGES/R-Matrix.mo0000644000175100001440000004004414521047060017331 0ustar hornikusers,< 6 3( \ 9x  6 1 /; ,k ? : * #> b ,v ; # 4$LWq(0$#0Hy8'5:N5#,.?$RDw4D%6=\-7 *>ie""15gI"@@Q56(- Vw":91>3p:-@ ?N=2909=j51'*R&q$&B(S&|Bv?]"*;%'M"d)!9>AA 0+4\0`5# ,Y 7  O >*!Ii!<!:!H+",t""?4$;t$#$C$"%;;%8w%<%/%>&7\&0&%&&('<+'%h'':'$'o(1u(4(((4)':)@b).)#)')$*BC*D*$*5*+&+R+*k+^+F+K<,),>,8,C*-#n-#-2-#- .).).6. /X@/)//K/K/0?{0>0"01-/1#]1#11.1D1C02Pt2N2M36b3Z3_3DT4C444:5DM535S5"6%=6 c6E6606*7>7VS7.7*7H8wM8B8&92/9Hb9)999 :(:5F:.|:G:L:D@;;;); ;3;>3<Jr<<9M=6=7= =X>Ap>V>H ?FR?T?5?o],WOc?3j_Cs5}6P{ F<Xl%VfxSU#Hb)+g!zIra|9 1 Z*`/nA$4wmMKh\JB-0t&7DN2"E i;^d[qu'pL:Ry= @vQY(.>eGT~8k'%s()' is not yet implemented for representation '%s''%s()' is not yet implemented for element type '%s''A' must be a square matrix'NA' indices are not (yet?) supported for sparse Matrices'by' argument is much too small'diagonals' matrix must have %d columns (= length(k) )'diagonals' must have the same length (%d) as 'k''file' must be a character string or connection'force' must be (coercable to) TRUE or FALSE'giveCsparse' has been deprecated; setting 'repr = "T"' for you'giveCsparse' has been deprecated; will use 'repr' instead'lwd' must be NULL or non-negative numeric'ncol' is not a factor of length(x)'ncol' must be >= 0'nearPD()' did not converge in %d iterations'nrow' and 'ncol' must be the same when 'symmetric' is true'nrow' is not a factor of length(x)'nrow' must be >= 0'x' must have length nrow^2 when 'symmetric' is true'x' must inherit from "sparseVector".M.repl.i.2col(): 'i' has no integer column number; should never happen; please report.M.repl.i.2col(): drop 'matrix' case ... --> is not yet implemented[i] is not yet implemented --> is not yet implementedClass %s is not yet implementedCmp.Mat.atomic() should not be called for diagonalMatrixInternal bug: nargs()=%d; please reportInvalid assembled indicator: %sInvalid storage format: %sInvalid storage type: %sLogic.Mat.atomic() should not be called for diagonalMatrixMatrices must have same number of rows for arithmeticMatrix seems negative semi-definiteMust specify 'nrow' when 'symmetric' is trueNAs are not allowed in subscripted assignmentsNot a valid formatOnly numeric sparse matrices allowedRHS 'value' (class %s) matches 'ANY', but must match matrix class %s[ ] indexing not allowed: forgot a "," ?a sparseMatrix should rarely be centered: will not be sparse anymoreall() is not yet implementedc(,..) of different kinds, coercing all to 'rleDiff'column indices must be <= ncol(.) which is %ddim [product %d] do not match the length of object [%d]dimnames [%d] mismatch in %selement type '%s' not recognizedelement type 'complex' not yet implementedfile is not a MatrixMarket filefor symmetric band matrix, only specify upper or lower triangle hence, all k must have the same signhit a cycle (1) -- stop iterationshit a cycle (2) -- stop iterationsi1[1] == 0 ==> C-level verbosity will not happen!index larger than maximal %dindex must be numeric, logical or sparseVector for indexing sparseVectorsinefficient method used for "- e1"intermediate 'r' is of type %sinternal bug in "Compare" method (Cmp.Mat.atomic); please reportinternal bug in "Logic" method (Logic.Mat.atomic); please reportinternal bug: matrix 'i' in replTmat(): please reportinternal bug: missing 'i' in replTmat(): please reportinvalid 'col.names' string: %sinvalid 'data'invalid 'repr'; must be "C", "T", or "R"invalid (to - from)/by in seq(.)invalid character indexinginvalid nargs()= %dlength must be non-negative numberlength of 'center' must equal the number of columns of 'x'length of 'scale' must equal the number of columns of 'x'length of 1st arg does not match dimension of 2ndlength of 2nd arg does not match dimension of firstlogic programming error in printSpMatrix2(), please reportlogical subscript too long (%d, should be %d)longer object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthm[ ] <- v: inefficiently treating single elementsmatrix can only be symmetric if square, but n != mmust either specify 'A' or the functions 'A.x' and 'At.x'nargs() = %d should never happen; please report.nargs() = %d. Extraneous illegal arguments inside '[ .. ]' ?negative values are not allowed in a matrix subscriptno 'dimnames[[.]]': cannot use character indexingnon-conformable argumentsnon-conformable matrix dimensions in %snot converged in %d iterationsnot enough new vecs -- stop iterationsnot yet implementednot yet implemented .. please reportnot-yet-implemented 'Matrix[<-' methodnothing to replace withnumber of items to replace is not a multiple of replacement lengthnumber of rows are not compatible for %sprod() is not yet implementedqr2rankMatrix(.): QR with only %d out of %d finite diag(R) entriesrankMatrix(, method = '%s') coerces to dense matrix. Probably should rather use method = 'qr' !?rankMatrix(x, method='qr'): computing t(x) as nrow(x) < ncol(x)representation '%s' not recognizedrow indices must be <= nrow(.) which is %dsuch indexing must be by logical or 2-column numeric matrixsum() is not yet implementedsuppressing %d columnssuppressing %d columns and %d rowssuppressing %d rowssymmetric matrix must be squaresymmetry form '%s' is not yet implementedsymmetry form '%s' not recognizedsymmetry form 'hermitian' not yet implemented for readingsymmetry form 'skew-symmetric' not yet implemented for readingthe %d-th (sub)-diagonal (k = %d) is too short; filling with NA'stoo many argumentstoo many replacement valuestriangular matrix must be squaretype '%s' not recognizeduniDiag=TRUE, but not all diagonal entries are 1uniDiag=TRUE, not all entries in diagonal coded as 1using "old code" part in Csparse subassignmentusing"old code" part in Csparse subassignment >>> please report to Matrix-authors@r-project.orgvariable '%s' is absent, its contrast will be ignoredvector too long in Matrix - vector operationwhen 'A' is specified, 'A.x' and 'At.x' are disregardedwrong sign in 'by' argumentx / 0 for an x with sign-change no longer representable as 'rleDiff'x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrixx[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE.x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced; NA |--> TRUE.you cannot mix negative and positive indicesProject-Id-Version: R-Matrix 1.3-3 Report-Msgid-Bugs-To: bugs.r-project.org PO-Revision-Date: 2021-04-14 12:18+0200 Last-Translator: Daniele Medri Language-Team: Italian https://github.com/dmedri/R-italian-lang Language: it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); X-Generator: Poedit 2.2.1 '%s()' non è ancora implementato per la rappresentazione '%s''%s()' non è ancora implementato per il tipo elemento '%s''A' dev'essere una matrice quadratagli indici 'NA' non sono (ancora?) supportati per le matrici sparsel'argomento 'by' è troppo piccolola matrice 'diagonals' deve avere %d colonne (= length(k) )'diagonals' deve avere la medesima lunghezza (%d) di 'k''file' dev'essere una stringa di caratteri o una connessione'force' dev'essere (coercibile in) TRUE o FALSE'giveCsparse' è stato deprecato; viene impostato 'repr = "T"''giveCsparse' è stato deprecato; si utilizzerà 'repr''lwd' dev'essere NULL o un numerico non negativo'ncol' non è un fattore di length(x)'ncol' dev'essere >= 0'nearPD()' non converge in %d iterazioni'nrow' e 'ncol' dev'essere uguali quando 'symmetric' è true'nrow' non è un fattore di length(x)'nrow' dev'essere >= 0'x' deve avere lunghezza nrow^2 quando 'symmetric' è true'x' deve ereditare da "sparseVector".M.repl.i.2col(): 'i' non ha un numero di colonna intero; non dovrebbe mai accadere; per piacere, segnalatelo.M.repl.i.2col(): si elimina il caso 'matrix' ... --> non è ancora implementato[i] non è ancora implementato --> non è ancora implementatoLa classe %s non è ancora implementataCmp.Mat.atomic() non dovrebbe essere chiamata per diagonalMatrixBug interno: nargs()=%d; per piacere riportaloIndicatore assemblato non valido:%sFormato di archiviazione non valido: %sTipo di archiviazione non valido: %sLogic.Mat.atomic() non dovrebbe essere chiamato per diagonalMatrixLe matrici devono avere il medesimo numero di righe per l'aritmeticaMatrix sembra semi-definito negativoBisogna specificare 'nrow' quando 'symmetric' è trueNA non ammessi nelle assegnazioni subscriptNon è un formato validoSono ammesse solo matrici sparse numericheRHS 'value' (classe %s) corrisponde a 'ANY', ma deve corrispondere ad una classe di matrice %s[ ] indicizzazione non ammessa: si è dimenticato un "," ?una sparseMatrix dovrebbe essere raramente centrata: non sarà più sparsa.all() non è ancora implementatoc(,..) di diverso tipo, convertendo tutto a 'rleDiff'gli indici di colonna devono essere <= ncol(.) e sono %ddim [product %d] non corrisponde con la lunghezza dell'oggetto [%d]dimnames [%d] non corrisponde in %stipo elemento '%s' non riconosciutotipo di elemento 'complex' non ancora implementatoil file non è un file MatrixMarketper la matrice di bande simmetriche, specificare solo il triangolo superiore o inferiore poi, tutti i k devono avere lo stesso segnofine ciclo (1) - interrompe le iterazionifine ciclo (2) - interrompe le iterazionii1[1] == 0 ==> la verbosità a livello C non accadrà!indice più largo del massimo %dl'indice dev'essere numerico, logico o sparseVector per l'indicizzazione di sparseVectorutilizzato metodo inefficiente per "- e1"la 'r' intermedia è di tipo %sbug interno nel metodo "Compare" (Cmp.Mat.atomic); per piacere, riportatelobug interno nel metodo "Logic" (Logic.Mat.atomic); per piacere, segnalatelobug interno: matrix 'i' in replTmat(): per piacere, riportatelobug interno: manca 'i' in replTmat(): per piacere, riportatelostringa 'col.names' non valida: %s'data' non valido'repr' non valido; dev'essere "C", "T", o "R"(to - from)/by in seq(.) non validoindicizzazione carattere non validanargs()= %d non validola lunghezza dev'essere un numero non negativola lunghezza di 'center' deve eguagliare il numero di colonne di 'x'la lunghezza di 'scale' deve eguagliare il numero di colonne di 'x'la lunghezza del primo argomento non corrisponde con la dimensione della secondala lunghezza del secondo argomento non corrisponde con la dimensione del primoerrore di programmazione logica in printSpMatrix2(), per piacere, riportatelosubscript logico troppo lungo (%d, dovrebbe essere %d)la lunghezza dell'oggetto più lungo non è un multiplo di lunghezza di quello più cortola lunghezza più lunga dell'oggetto non è un multiplo della lunghezza più corta dell'oggettom[ ] <- v: trattamento inefficiente dei singoli elementila matrice può essere unicamente simmetrica se quadrata, ma n != msi deve specificare 'A' o le funzioni 'A.x' e 'At.x'nargs() = %d non dovrebbe accadere; per piacere riportalo.nargs() = %d. Argomenti illegali estranei all'interno di '[ .. ]' ?valori negativi non ammessi in subscript di matricenessuna 'dimnames[[.]]': non è possibile utilizzare l'indicizzazione dei caratterigli argomenti non sono compatibilidimensioni matrice non conformi in %snon convergente in %d iterazioninon ci sono abbastanza nuovi vettori -- si interrompono le iterazioninon ancora implementatonon ancora implementato .. per piacere riportalometodo 'Matrix[<-' non ancora implementatoniente da sostituireil numero di articoli da sostituire non è un multiplo della lunghezza di sostituzioneil numero di righe non sono compatibili per %sprod() non è ancora implementatoqr2rankMatrix(.): QR con solo %d elementi fuori dai %d finiti di diag(R)rankMatrix(, method = '%s') convertito in matrice densa. Non si dovrebbe provare method = 'qr' !?rankMatrix(x, method='qr'): calcolando t(x) come nrow(x) < ncol(x)rappresentazione '%s' non riconosciutagli indici riga devono essere <= nrow(.) e sono %dtale indicizzazione dev'essere per matrice logica o numerica a 2 colonnesum() non è ancora implementatosoppresse %d colonnesoppresse %d colonne e %d righesoppresse %d righela matrice simmetrica dev'esser quadratala forma di simmetria '%s' non è ancora implementatala forma di simmetria '%s' non è riconosciutala forma di simmetria 'hermitian' non è ancora implementata in letturala forma di simmetria 'skew-symmetric' non è ancora implementata in letturala %d' (sotto)-diagonale (k = %d) è troppo corta; si riempie con NAtroppi argomentitroppi valori di sostituzionela matrice triangolare dev'esser quadratail tipo '%s' non è riconosciutouniDiag=TRUE, ma non tutte le voci diagonali sono 1uniDiag=TRUE, non tutte le voci in diagonale codificate come 1si utilizza una parte di "vecchio codice" nel sotto-assegnamento Csparsesi utilizza una parte di "vecchio codice" nel sotto-assegnamento Csparse >>> per piacere, riportatelo agli autori Matrix-authors@r-project.orgvariabile '%s' assente, i suoi contrasti saranno ignorativettore troppo lungo in Matrix - operazione vettorialequando 'A' è specificato, 'A.x' e 'At.x' sono ignoratisegno errato nell'argomento 'by'x / 0 per un x con cambio di segno non è più rappresentabile come 'rleDiff'x[.,.] <- val : x è stato convertito da Tsparse* a CsparseMatrixx[.,.] <- val: x è %s, il valore esterno a {TRUE, FALSE} è convertito; NA |--> TRUE.x[.,.] <- val: x è %s, il valore esterno a {TRUE, FALSE} è convertito.x[.] <- val: x è %s, il valore esterno a {TRUE, FALSE} è convertito.x[.] <- val: x è %s, il valore esterno a {TRUE, FALSE} è convertito; NA |--> TRUE.non è possibile mischiare indici negativi e positiviMatrix/inst/po/de/0000755000175100001440000000000014576343415013533 5ustar hornikusersMatrix/inst/po/de/LC_MESSAGES/0000755000175100001440000000000014576343415015320 5ustar hornikusersMatrix/inst/po/de/LC_MESSAGES/Matrix.mo0000644000175100001440000001054214561104346017113 0ustar hornikusers$<5\01+Q+}3-! "-<P'+0,,?2l'-.$:&U|&/+@4<u%$$"A0]O-_ l : ' E 94 *n - L 0 7E 3} / / = 0O 6 7  $ 1.$`140"G@7...#Mq:_9( $" ! # 'data' must be of a vector typeArgument ij must be 2-column integer matrixArgument must be numeric-like atomic vectorMatrix exponential requires square, non-null matrixX must be a numeric (double precision) matrixX must be a real (numeric) matrixdata length exceeds size of matrixdgeMatrix_Schur: argument x must be a non-null square matrixdgeMatrix_Schur: dgees returned code %ddgeMatrix_Schur: first call to dgees faileddgeMatrix_exp: LAPACK routine dgebal returned %ddgeMatrix_exp: dgetrf returned error code %ddgeMatrix_exp: dgetrs returned error code %di and j must be integer vectors of the same lengthincorrect left cyclic shift, j (%d) < 0incorrect left cyclic shift, j (%d) >= k (%d)incorrect left cyclic shift, k (%d) > ldx (%d)invalid '%s' argumentinvalid 'ncol' value (< 0)invalid 'ncol' value (too large or NA)invalid 'nrow' value (< 0)invalid 'nrow' value (too large or NA)invalid class of 'value' in Csparse_subassign()invalid class of 'x' in Csparse_subassign()non-numeric matrix extentnumber of rows in y (%d) does not match number of rows in X (%d)programming error in Csparse_subassign() should never happenreplacement diagonal has wrong lengthsubscript 'i' out of bounds in M[ij]subscript 'j' out of bounds in M[ij]tol, given as %g, must be <= 1too many elements specifiedx[] <- val: val is coerced to logical for "%s" xx[] <- val: val should be integer or logical, is coerced to integer, for "%s" xy must be a numeric (double precision) matrixProject-Id-Version: R 4.0.4 / Matrix 1.3-3 Report-Msgid-Bugs-To: PO-Revision-Date: 2021-02-11 13:00+0100 Last-Translator: Detlef Steuer Language-Team: R Core Language: de MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); 'data' muss ein Vektortyp seinArgument ij muss eine zweispaltige ganzzahlige Matrix seinArgument muss zahl-ähnlich atomar seinExponentielle Matrix benötigt eine quadratische Matrix ungleich NullX muss eine numerische (doppelte Genauigkeit) Matrix seinX muss eine echte (numerische) Matrix seinDatenlänge überschreitet Größe der MatrixdgeMatrix_Schur: Argument x muss eine quadratische Matrix ungleich Null seindgeMatrix_Schur: dgees gab Fehlerkode %d zurückdgeMatrix_Schur: Erster Aufruf von dgees fehlgeschlagendgeMatrix_exp: LAPACK-Routine dgebal gab %d zurückdgeMatrix_exp: dgetrf gab Fehlerkode %d zurückdgeMatrix_exp: dgetrs gab Fehlerkode %d zurücki und j müssen Ganzzahlvektoren mit der gleichen Länge seinfalsches zyklisches Linksverschieben, j (%d) < 0falsches zyklisches Linksverschieben, j (%d) >= k (%d)falsches zyklisches Linksverschieben, k (%d) > ldx (%d)ungültiges '%s' Argumentunzulässiger Wert für 'ncol' (< 0)unzulässiger Wert für 'ncol' (zu groß oder NA)unzulässiger Wert für 'nrow' (< 0)unzulässiger Wert für 'nrow' (zu groß oder NA)ungültige Klasse von 'value' in Csparse_subassign()ungültige Klasse von 'x' in Csparse_subassign()nicht-numerische Matrix-AusdehnungAnzahl der Zeilen in y (%d) passt nicht zur Anzahl der Zeilen in X (%d)Fehler in Csparse_subassign(); sollte niemals vorkommenDiagonale zur Ersetzung hat die falsche LängeSubskript 'i' außerhalb des Bereichs in M[ij]Subskript 'j' außerhalb des Bereichs in M[ij]tol, als %g gegeben, muss <= 1 seinzu viele Elemente angegebenx[] <- val: val in booleschen Wert umgewandelt für "%s" xx[] <- val: val sollte ganzzahlig oder logisch sein, wird in ganze Zahl umgewandelt für "%s" xy muss eine numerische (doppelte Genauigkeit) Matrix seinMatrix/inst/po/de/LC_MESSAGES/R-Matrix.mo0000644000175100001440000003664114521047060017315 0ustar hornikusers  6 3 , 9H  6 1 / ,; *h #  , ; #4 X 4l $ W (0G$x08''Oo:5#,8.e$D4DF%=-7U r*e"D"g1I"#F@e@56Ts ":901j3:- @9?z=29+0e=51 <'V~&$&$B<(&Bv?"*;%Sy")!93>mA >0W40`5O,7O >V I < :!HW!,!m!9;#8u#&#K#!$7<$6t$2$4$1%$E%j%0%L%$%#&A9&'{&^&-'30')d'3'"'C'))()S(}((E(@(*?)Cj)1))#)L*;g*d*++R4+2+8+ +,-2,"`,,6-6:-3q--S-(.#B.Jf.K.:.=8/'v//&///) 0<70;t0;0A0@.10o1E1D1>+2Gj2>272B)3;l3C33&4+,45X44)4-44J5.a5,5I5}6@6"616L7+h77,77)7+(8 T8<u8A8M8B9U9$m9969D99%:m_:1:/:G/;$w;[;@;R9<D<D<R=7i=lt*TL`=1g\@ ~p3z4MxC:Ui#Scu|PR!E_')dwFo^y7/ W(]-kZ"2jJHeYG?+.q$5AK0 B f9[aXnr%mI8Ov; >}sNV&,<bDQ{6h'%s()' is not yet implemented for representation '%s''%s()' is not yet implemented for element type '%s''A' must be a square matrix'NA' indices are not (yet?) supported for sparse Matrices'by' argument is much too small'diagonals' matrix must have %d columns (= length(k) )'diagonals' must have the same length (%d) as 'k''file' must be a character string or connection'force' must be (coercable to) TRUE or FALSE'lwd' must be NULL or non-negative numeric'ncol' is not a factor of length(x)'ncol' must be >= 0'nearPD()' did not converge in %d iterations'nrow' and 'ncol' must be the same when 'symmetric' is true'nrow' is not a factor of length(x)'nrow' must be >= 0'x' must have length nrow^2 when 'symmetric' is true'x' must inherit from "sparseVector".M.repl.i.2col(): 'i' has no integer column number; should never happen; please report.M.repl.i.2col(): drop 'matrix' case ... --> is not yet implemented[i] is not yet implemented --> is not yet implementedClass %s is not yet implementedCmp.Mat.atomic() should not be called for diagonalMatrixInternal bug: nargs()=%d; please reportInvalid assembled indicator: %sInvalid storage format: %sInvalid storage type: %sLogic.Mat.atomic() should not be called for diagonalMatrixMatrices must have same number of rows for arithmeticMatrix seems negative semi-definiteMust specify 'nrow' when 'symmetric' is trueNAs are not allowed in subscripted assignmentsNot a valid formatOnly numeric sparse matrices allowedRHS 'value' (class %s) matches 'ANY', but must match matrix class %s[ ] indexing not allowed: forgot a "," ?a sparseMatrix should rarely be centered: will not be sparse anymoreall() is not yet implementedc(,..) of different kinds, coercing all to 'rleDiff'column indices must be <= ncol(.) which is %ddim [product %d] do not match the length of object [%d]dimnames [%d] mismatch in %selement type '%s' not recognizedelement type 'complex' not yet implementedfile is not a MatrixMarket filefor symmetric band matrix, only specify upper or lower triangle hence, all k must have the same signhit a cycle (1) -- stop iterationshit a cycle (2) -- stop iterationsi1[1] == 0 ==> C-level verbosity will not happen!index larger than maximal %dindex must be numeric, logical or sparseVector for indexing sparseVectorsinefficient method used for "- e1"intermediate 'r' is of type %sinternal bug in "Compare" method (Cmp.Mat.atomic); please reportinternal bug in "Logic" method (Logic.Mat.atomic); please reportinternal bug: matrix 'i' in replTmat(): please reportinternal bug: missing 'i' in replTmat(): please reportinvalid 'col.names' string: %sinvalid 'data'invalid (to - from)/by in seq(.)invalid character indexinginvalid nargs()= %dlength must be non-negative numberlength of 'center' must equal the number of columns of 'x'length of 'scale' must equal the number of columns of 'x'length of 1st arg does not match dimension of 2ndlength of 2nd arg does not match dimension of firstlogic programming error in printSpMatrix2(), please reportlogical subscript too long (%d, should be %d)longer object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthm[ ] <- v: inefficiently treating single elementsmatrix can only be symmetric if square, but n != mmust either specify 'A' or the functions 'A.x' and 'At.x'nargs() = %d should never happen; please report.nargs() = %d. Extraneous illegal arguments inside '[ .. ]' ?negative values are not allowed in a matrix subscriptno 'dimnames[[.]]': cannot use character indexingnon-conformable argumentsnon-conformable matrix dimensions in %snot converged in %d iterationsnot enough new vecs -- stop iterationsnot yet implementednot yet implemented .. please reportnot-yet-implemented 'Matrix[<-' methodnothing to replace withnumber of items to replace is not a multiple of replacement lengthnumber of rows are not compatible for %sprod() is not yet implementedqr2rankMatrix(.): QR with only %d out of %d finite diag(R) entriesrankMatrix(, method = '%s') coerces to dense matrix. Probably should rather use method = 'qr' !?rankMatrix(x, method='qr'): computing t(x) as nrow(x) < ncol(x)representation '%s' not recognizedrow indices must be <= nrow(.) which is %dsuch indexing must be by logical or 2-column numeric matrixsum() is not yet implementedsuppressing %d columnssuppressing %d columns and %d rowssuppressing %d rowssymmetric matrix must be squaresymmetry form '%s' is not yet implementedsymmetry form '%s' not recognizedsymmetry form 'hermitian' not yet implemented for readingsymmetry form 'skew-symmetric' not yet implemented for readingthe %d-th (sub)-diagonal (k = %d) is too short; filling with NA'stoo many argumentstoo many replacement valuestriangular matrix must be squaretype '%s' not recognizeduniDiag=TRUE, but not all diagonal entries are 1uniDiag=TRUE, not all entries in diagonal coded as 1using "old code" part in Csparse subassignmentusing"old code" part in Csparse subassignment >>> please report to Matrix-authors@r-project.orgvariable '%s' is absent, its contrast will be ignoredvector too long in Matrix - vector operationwhen 'A' is specified, 'A.x' and 'At.x' are disregardedwrong sign in 'by' argumentx / 0 for an x with sign-change no longer representable as 'rleDiff'x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrixx[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE.x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced; NA |--> TRUE.you cannot mix negative and positive indicesProject-Id-Version: R 4.0.0 / matrix 1.3-0 Report-Msgid-Bugs-To: bugs.r-project.org PO-Revision-Date: 2020-04-01 16:01+0200 Last-Translator: Detlef Steuer Language-Team: R-Core Language: de MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); '%s()' ist noch nicht implementiert für Darstellung '%s''%s()' ist noch nicht für Elementtyp '%s' implementiert'A' muss eine quadratische Matrix sein'NA'-Indizes werden (noch?) nicht für dünn besetzte Matrizen unterstütztArgument 'by' ist zu klein'diagonals'-Matrix muss %d Spalten haben (= length(k) )'diagonals' muss die gleiche Länge (%d) wie 'k' haben'file' muss eine Zeichenkette oder Verbindung sein'force' muss (umwandelbar nach) TRUE oder FALSE sein'lwd' muss NULL oder nicht negativ numerisch sein'ncol' ist kein Faktor von length(x)'ncol' muss >= 0 seinnearPD() ist nicht in %d Iterationen konvergiert'nrow' und 'ncol' müssen gleich sein, wenn 'symmetric' auf true gesetzt ist'nrow' ist kein Faktor von length(x)'nrow' muss >= 0 sein'x' muss die Länge nrow^2, wenn 'symmetric' auf true gesetzt ist'x' muss von "sparseVector" geerbt sein.M.repl.i.2col(): 'i' hat keine ganzzahlige Spaltennummer. Sollte nie passieren. Bitte melden..M.repl.i.2col(): 'matrix'-Fall weglassen ... --> ist noch nicht implementiert[i] ist noch nicht implementiert --> ist noch nicht implementiertKlasse %s noch nicht implementiertCmp.Mat.atomic() sollte nicht für diagonalMatrix aufgerufen werdenInterner Fehler: nargs()=%d; bitte meldenUngültig zusammengesetzter Indikator: %sUngültiges Speicherformat: %sUngültiger Speichertyp: %sLogic.mat.atomic() sollte für diagonalMatrix nicht aufgerufen werdenMatrizen müssen für Arithmetik die gleiche Anzahl Zeilen habenMatrix scheint negativ semidefinit zu sein'nrow' muss angegeben werden, wenn 'symmetric' auf true gesetzt istNAs sind in indexierten Anweisungen nicht erlaubtKein gültiges FormatNur dünn besetzte Matrizen erlaubtRHS 'value' (Klasse %s) passt zu 'ANY', muss aber zur Matrixklasse %s passen[ ] Indexierung nicht erlaubt: Ein ',' vergessen?eine schwach besetze Matrix sollte kaum je zentriert werden: sie ist dann nicht mehr schwach besetztall() ist noch nicht implementiertc(,..) von unterschiedlichen Arten, alle werden in 'rleDiff' umgewandeltSpaltenindizes müssen <= ncol(.) sein, das ist %ddim [produkt %d] passt nicht zur Länge des Objekts [%d]dimnames [%d] passen nicht in %sElementtyp '%s' nicht erkanntElementtyp 'complex' noch nicht implementiertDatei ist keine MatrixMarket-Dateigeben Sie für symmetrische Bandmatrizen nur oberes oder unteres Dreieck an. deshalb müssen alle k dasselbe Vorzeichen haben.auf einen Zyklus getroffen (1) – Iterationen stoppenauf einen Zyklus getroffen (2) – Iterationen stoppeni1[1] == 0 ==> C-Ebene wird nicht detailliert sein!Index größer als maximales %dIndex muss numerisch, logisch oder sparseVector sein, um sparseVector zu indizierenineffiziente Methode für '- e1' benutztZwischenergebnis 'r' ist vom Typ %sinterner Fehler in der "Compare"-Methode (Cmp.Mat.atomic). Bitte berichteninterner Fehler in der "Logic"-Methode (.Logic.Mat.atomic). Bitte berichteninterner Fehler: Matrix 'i' in replTmat(): Bitte berichteninterner Fehler: Fehlendes 'i' in replTmat(): Bitte berichtenungültige 'col.names'-Zeichenkette: %sungültiges 'data'unzulässiges (to - from)/by in seq(.)ungültige Zeichenindexierungungültige nargs()= %dLänge muss eine nicht negative Zahl seinLänge von 'center' muss der Spaltenzahl von 'x' entsprechenLänge von 'scale' muss der Spaltenzahl von 'x' entsprechenLänge des ersten arg passt nicht zur Dimension des zweitenLänge des zweiten Arguments passt nicht zur Dimension des erstenlogischer Programmierfehler in printSpMatrix2(), bitte berichtenlogisches Subskript zu lang (%d, sollte %d sein)längere Objektlänge ist kein Vielfaches der kürzeren Objektlängelängere Objektlänge ist kein Vielfaches der kürzeren Objektlängem[ ] <- v: Einzelne Elemente ineffizient behandeltMatrix kann nur symmetrisch sein, wenn sie quadratisch ist, aber n != mmuss entweder 'A' angeben oder die Funktionen 'A.x' und 'At.x'nargs() = %d sollte niemals vorkommen. Bitte berichten.nargs() = %d. Irrelevante ungültige Argumente innerhalb '[ .. ]'?negative Werte sind in einer Matrix-Subskript nicht erlaubtkeine 'dimnames[[.]]': Zeichenindexierung kann nicht benutzt werdennicht passende Argumentenicht konforme Matrixdimensionen in %snicht konvergiert in %d Iterationsschrittennicht genügend neue Vektoren – Iterationen stoppennoch nicht implementiertnoch nicht implementiert ... bitte meldennoch nicht implementierte 'Matrix[<-'-Methodenichts zu ersetzen mitAnzahl der zu ersetzenden Elemente ist kein Vielfaches der AustauschlängeAnzahl der Zeilen ist nicht kompatibel für %sprod() ist noch nicht implementiertqr2rankMatrix(.): QR Zerlegung mit nur %d von %d endlichen diag(R) WertenrankMatrix(, method = '%s') wird in dicht besetzte Matrix umgewandelt. Evtl. eher method = 'qr' nutzen? rankMatrix(x, method='qr'): t(x) berechnet, da nrow(x) < ncol(x)Repräsentation '%s' nicht erkanntZeilenindizes müssen <= nrow(.) sein, das ist %dsolche Indexierung muss von logischer oder 2-spaltig numerischer Matrix seinsum() ist noch nicht implementiert%d Spalten werden unterdrückt%d Spalten und %d Zeilen werden unterdrückt%d Zeilen werden unterdrücktsymmetrische Matrix muss quadratisch seinSymmetrieform '%s' noch nicht implementiertSymmetrieform '%s' nicht erkanntSymmetrieform 'hermitian' noch nicht zum Lesen implementiertSymmetrieform 'skew-symmetric' noch nicht zum Lesen implementiertdie %d-te (Unter)-Diagonale (k = %d) ist zu kurz und wird mit NA aufgefülltzu viele Argumentezu viele AustauschwerteDreiecksmatrix muss quadratisch seinTyp '%s' nicht erkanntuniDiag=TRUE, aber nicht alle Diagonaleinträge sind 1uniDiag=TRUE, aber nicht alle Einträge der Diagonalen als 1 kodiertbenutzt wird 'alter Kode'-Teil in Csparse-Unterzuweisungbenutzt wird 'alter Kode'-Teil in Csparse-Unterzuweisung >>> bitte an Matrix-authors@r-project.org berichtenVariable '%s' fehlt, ihr Kontrast wird irgnoriertVektor zu lang in der Matrix - Vektor Operationwenn 'A' angegeben wurde, werden 'A.x' und 'At.x' nicht berücksichtigtfalsches Vorzeichen im Argument 'by'x / 0 für einen x mit Vorzeichenwechsel nicht länger als 'rleDiff' darstellbarx[.,.] <- val : x wird von Tsparse* in CsparseMatrix umgewandeltx[.,.] <- val: x ist %s, val nicht in {TRUE, FALSE} wird umgewandelt NA |--> TRUE.x[.,.] <- val: x ist %s, val nicht in {TRUE, FALSE} wird umgewandeltx[.] <- val: x ist %s, val nicht in {TRUE, FALSE}, wird umgewandelt.x[.] <- val: x ist %s, val nicht in {TRUE, FALSE}, wird umgewandelt; NA |--> TRUE.Sie können positive und negative Indizes nicht mischenMatrix/inst/po/pl/0000755000175100001440000000000014576343415013556 5ustar hornikusersMatrix/inst/po/pl/LC_MESSAGES/0000755000175100001440000000000014576343415015343 5ustar hornikusersMatrix/inst/po/pl/LC_MESSAGES/Matrix.mo0000644000175100001440000001105314561104346017134 0ustar hornikusers#4/L +)+U3-!"<('e+0,,2D'w-.&-T&o/+@ <M$$0O@- A . @- 9n 0 - G 4O I 8 ; ;C L 4 :;<x":":9N5FM""p"? Me9# !   " 'data' must be of a vector typeArgument ij must be 2-column integer matrixArgument must be numeric-like atomic vectorMatrix exponential requires square, non-null matrixX must be a numeric (double precision) matrixX must be a real (numeric) matrixdata length exceeds size of matrixdgeMatrix_Schur: argument x must be a non-null square matrixdgeMatrix_Schur: dgees returned code %ddgeMatrix_Schur: first call to dgees faileddgeMatrix_exp: LAPACK routine dgebal returned %ddgeMatrix_exp: dgetrf returned error code %ddgeMatrix_exp: dgetrs returned error code %di and j must be integer vectors of the same lengthincorrect left cyclic shift, j (%d) < 0incorrect left cyclic shift, j (%d) >= k (%d)incorrect left cyclic shift, k (%d) > ldx (%d)invalid '%s' argumentinvalid 'ncol' value (< 0)invalid 'ncol' value (too large or NA)invalid 'nrow' value (< 0)invalid 'nrow' value (too large or NA)invalid class of 'value' in Csparse_subassign()invalid class of 'x' in Csparse_subassign()non-numeric matrix extentnumber of rows in y (%d) does not match number of rows in X (%d)programming error in Csparse_subassign() should never happensubscript 'i' out of bounds in M[ij]subscript 'j' out of bounds in M[ij]tol, given as %g, must be <= 1too many elements specifiedx[] <- val: val is coerced to logical for "%s" xx[] <- val: val should be integer or logical, is coerced to integer, for "%s" xy must be a numeric (double precision) matrixProject-Id-Version: Matrix 1.1-2-2 Report-Msgid-Bugs-To: PO-Revision-Date: 2014-03-24 17:53+0100 Last-Translator: Łukasz Daniel Language-Team: Łukasz Daniel Language: pl_PL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); X-Poedit-SourceCharset: iso-8859-1 X-Generator: Poedit 1.5.4 'data' musi być type wektorArgument 'ij' musi być 2-kolumnową macierzą liczb całkowitychArgument musi być atomowym wektorem liczbowymEksponencjowanie macierzy wymaga kwadratowej, niepustej macierzy'X' musi być macierzą liczbową (o podwójnej precyzji)'X' musi być rzeczywistą (liczbową) macierządługość danych przekracza rozmiar macierzydgeMatrix_Schur: argument 'x' musi być niepustą macierzą kwadratowądgeMatrix_Schur: funkcja 'dgees()' zwróciła kod %ddgeMatrix_Schur: pierwsze wywołanie funkcji 'dgees()' nie powiodło siędgeMatrix_exp: procedura LAPACK 'dgebal()' zwróciła %ddgeMatrix_exp: funkcja 'dgetrf()' zwróciła kod błędu %ddgeMatrix_exp: funkcja 'dgetrs()' zwróciła kod błędu %d'i' oraz 'j' muszą być wektorami liczb całkowitych o tej samej długościniepoprawne lewe cykliczne przesunięcie, j (%d) < 0niepoprawne lewe cykliczne przesunięcie, j (%d) >= k (%d)niepoprawne lewe cykliczne przesunięcie, k (%d) > ldx (%d)niepoprawny argument '%s'niepoprawna wartość 'ncol' (< 0)niepoprawna wartość 'ncol' (zbyt duża lub wartość NA)niepoprawna wartość 'nrow' (< 0)niepoprawna wartość 'nrow' (zbyt duża lub wartość NA)niepoprawna klasa 'value' w funkcji 'Csparse_subassign()'niepoprawna klasa 'x' w funkcji 'Csparse_subassign()'nieliczbowy rozmiar macierzyliczba wierszy w 'y' (%d) nie zgadza się z liczbą wierszy w 'X' (%d)błąd programowy w funkcji 'Csparse_subassign()' nie powinien się wydarzyćindeks 'i' poza zakresem w 'M[ij]'indeks 'j' poza zakresem w 'M[ij]'argument 'tol', podany jako %g, musi być mniejszy lub równy 1określono zbyt dużo elementówx[] <- val: 'val' została przekształcone w wartość logiczną dla "%s" 'x'x[] <- val: 'val' powinno być liczbą całkowitą lub wartością logiczną, została przekształcona na liczbę całkowitą, dla "%s" 'x''y' musi być macierzą liczbową (o podwójnej precyzji)Matrix/inst/po/pl/LC_MESSAGES/R-Matrix.mo0000644000175100001440000003556514502411615017344 0ustar hornikuserssL 6 3 , 9H  6 1 / ,; *h #  , ; #4 X 4l $ W ( 0G $x 0  8 ''Oo:5#,8.e$D4%F=l-7 -*Nye"""1EwI"@ @a56. =^y"13:-Q@?=9>0x=51'Ow&$&B5(x&v??"*;% /)O!y9>AVi0`50,f7O>7Iv<:H8,? ? #!!?E!$!9!7!8"6U";"1""8#UI#1##L#44$zi$/$:%1O%:%*%C%8+&$d&%&"&E&h'+'>'<')(/<(Wl(@(2)O8)8)?)&*((*8Q*)**07+0h+>+,+,%,,R,S -Ht-H-%.,.'?.!g..'.C.C /GP/7/X/W)0G050D0=D171A11$25A2w272.22]3%l3333BU4*494b42`5(585.5S$6Xx6K67$47Y78y7|7>/81n888"8Y8QV9l9_:]u:k:5?; -+ _[;CG=,M4PO:W8S!ld".)Tr?J2qQ7RU5*3 ji1n0$Y &IAZV'%bkEHKa9` c6s@\ L^#D]m<pXeo>(gBhfFN/'%s()' is not yet implemented for representation '%s''%s()' is not yet implemented for element type '%s''A' must be a square matrix'NA' indices are not (yet?) supported for sparse Matrices'by' argument is much too small'diagonals' matrix must have %d columns (= length(k) )'diagonals' must have the same length (%d) as 'k''file' must be a character string or connection'force' must be (coercable to) TRUE or FALSE'lwd' must be NULL or non-negative numeric'ncol' is not a factor of length(x)'ncol' must be >= 0'nearPD()' did not converge in %d iterations'nrow' and 'ncol' must be the same when 'symmetric' is true'nrow' is not a factor of length(x)'nrow' must be >= 0'x' must have length nrow^2 when 'symmetric' is true'x' must inherit from "sparseVector".M.repl.i.2col(): 'i' has no integer column number; should never happen; please report.M.repl.i.2col(): drop 'matrix' case ... --> is not yet implemented[i] is not yet implemented --> is not yet implementedClass %s is not yet implementedCmp.Mat.atomic() should not be called for diagonalMatrixInternal bug: nargs()=%d; please reportInvalid assembled indicator: %sInvalid storage format: %sInvalid storage type: %sLogic.Mat.atomic() should not be called for diagonalMatrixMatrices must have same number of rows for arithmeticMatrix seems negative semi-definiteMust specify 'nrow' when 'symmetric' is trueNAs are not allowed in subscripted assignmentsNot a valid formatOnly numeric sparse matrices allowedRHS 'value' (class %s) matches 'ANY', but must match matrix class %s[ ] indexing not allowed: forgot a "," ?all() is not yet implementedc(,..) of different kinds, coercing all to 'rleDiff'column indices must be <= ncol(.) which is %ddim [product %d] do not match the length of object [%d]dimnames [%d] mismatch in %selement type '%s' not recognizedelement type 'complex' not yet implementedfile is not a MatrixMarket filefor symmetric band matrix, only specify upper or lower triangle hence, all k must have the same signhit a cycle (1) -- stop iterationshit a cycle (2) -- stop iterationsi1[1] == 0 ==> C-level verbosity will not happen!index larger than maximal %dindex must be numeric, logical or sparseVector for indexing sparseVectorsinefficient method used for "- e1"intermediate 'r' is of type %sinternal bug in "Compare" method (Cmp.Mat.atomic); please reportinternal bug in "Logic" method (Logic.Mat.atomic); please reportinternal bug: matrix 'i' in replTmat(): please reportinternal bug: missing 'i' in replTmat(): please reportinvalid 'col.names' string: %sinvalid 'data'invalid (to - from)/by in seq(.)invalid character indexinginvalid nargs()= %dlength must be non-negative numberlength of 1st arg does not match dimension of 2ndlength of 2nd arg does not match dimension of firstlogic programming error in printSpMatrix2(), please reportlogical subscript too long (%d, should be %d)longer object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthm[ ] <- v: inefficiently treating single elementsmust either specify 'A' or the functions 'A.x' and 'At.x'nargs() = %d should never happen; please report.nargs() = %d. Extraneous illegal arguments inside '[ .. ]' ?negative values are not allowed in a matrix subscriptno 'dimnames[[.]]': cannot use character indexingnon-conformable matrix dimensions in %snot converged in %d iterationsnot enough new vecs -- stop iterationsnot yet implementednot yet implemented .. please reportnot-yet-implemented 'Matrix[<-' methodnothing to replace withnumber of items to replace is not a multiple of replacement lengthnumber of rows are not compatible for %sprod() is not yet implementedrankMatrix(, method = '%s') coerces to dense matrix. Probably should rather use method = 'qr' !?rankMatrix(x, method='qr'): computing t(x) as nrow(x) < ncol(x)representation '%s' not recognizedrow indices must be <= nrow(.) which is %dsuch indexing must be by logical or 2-column numeric matrixsum() is not yet implementedsymmetric matrix must be squaresymmetry form '%s' is not yet implementedsymmetry form '%s' not recognizedsymmetry form 'hermitian' not yet implemented for readingsymmetry form 'skew-symmetric' not yet implemented for readingthe %d-th (sub)-diagonal (k = %d) is too short; filling with NA'stoo many argumentstoo many replacement valuestype '%s' not recognizedusing "old code" part in Csparse subassignmentusing"old code" part in Csparse subassignment >>> please report to Matrix-authors@r-project.orgvariable '%s' is absent, its contrast will be ignoredvector too long in Matrix - vector operationwhen 'A' is specified, 'A.x' and 'At.x' are disregardedwrong sign in 'by' argumentx / 0 for an x with sign-change no longer representable as 'rleDiff'x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrixx[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE.x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced; NA |--> TRUE.you cannot mix negative and positive indicesProject-Id-Version: Matrix 1.1-2-2 Report-Msgid-Bugs-To: bugs.r-project.org PO-Revision-Date: 2014-03-27 14:47+0100 Last-Translator: Łukasz Daniel Language-Team: Łukasz Daniel Language: pl_PL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); X-Poedit-SourceCharset: iso-8859-1 X-Generator: Poedit 1.5.4 '%s()' nie jest jeszcze zaimplementowane dla reprezentacji '%s''%s()' nie jest jeszcze zaimplementowany dla typu '%s' elementu'A' musi być macierzą kwadratowąindeksy 'NA' nie są (jeszcze?) wspierane dla rzadkich macierzyargument 'by' jest znacznie za małymacierz 'diagonals' musi mieć %d kolumnę (= length(k) )'diagonals' musi mieć tę samą długość (%d) co 'k''file' musi być łańcuchem tekstowym lub połączeniem'force' musi być (przekształcalne do) TRUE lub FALSE'lwd' musi mieć wartość NULL lub być nieujemną liczbą'ncol' nie jest czynnikiem długości 'length(x)''ncol' musi być >= 0funkcja 'nearPD()' nie uzbieżniła się w %d iteracjach'nrow' oraz 'ncol' muszą mieć tę samą wartość gdy 'symmetric' ma wartość TRUE'nrow' nie jest czynnikiem długości 'length(x)''nrow' musi być >= 0'x' musi mieć długość równą 'nrow'^2 gdy 'symmetric' ma wartość TRUEargument 'x' musi być obiektem klasy "sparseVector".M.repl.i.2col(): 'i' posiada niecałkowitą liczbę kolumn; to nie powinno się nigdy wydarzyć; proszę zgłosić raport.M.repl.i.2col(): zrzuć przypadek 'matrix' ... --> nie jest jeszcze zaimplementowane'[i]' nie jest jeszcze zaimplementowane --> nie jest jeszcze zaimplementowaneKlasa %s nie jest jeszcze zaimplementowana'Cmp.Mat.atomic()' nie powinien być wywołany dla 'diagonalMatrix'Błąd wewnętrzny: nargs()=%d; proszę zgłosić raportNiepoprawnie złożony wskaźnik: %sNiepoprawny format przechowywania: %sNiepoprawny typ przechowywania: %s'Logic.Mat.atomic()' nie powinien być wywołany dla 'diagonalMatrix'Macierze muszą mieć tę samą liczbę wierszy jeśli mają być przeprowadzane działania arytmetyczneMacierz wydaje się być ujemnie określona'nrow' musi być określone, gdy 'symmetric' ma wartość TRUEwartości NA nie są dozwolone w indeksowanych przypisaniachNiepoprawny formatDozwolone są jedynie liczbowe rzadkie macierzeprawa strona 'value' (klasa %s) pasuje do 'ANY', a musi pasować do klasy macierzy '%s'indeksowanie [ ] nie jest dozwolone: zapomniałeś ',' ?'all()' nie jest jeszcze zaimplementowane'c(,..)' różnych rodzajów, przekształcanie wszystkich do 'rleDiff'indeksy kolumn muszą być <= 'ncol(.)' który wynosi %dwymiar [produkt %d] nie zgadza się z długością obiektu [%d]niezgodność nazw wymiarów [%d] w %selement typu '%s' nie został rozpoznanytyp elementu 'complex' nie jest jeszcze zaimplementowanyplik nie jest plikiem typu 'MatrixMarket'dla symetrycznej macierzy wstęgowej, określ jedynie górny oraz dolny trójkąt tak więc, wszystkie k muszą mieć ten sam znaknatrafiona na cykl (1) -- zatrzymywanie iteracjinatrafiona na cykl (2) -- zatrzymywanie iteracjii1[1] == 0 ==> tryb 'verbose' poziomu C nie zostanie wykonany!indeks dłuższy niż maksymalny możliwy %dindeks musi być typem liczbowym, logicznym lub obiektem klasy 'sparseVector' na potrzeby indeksowania obiektów klasy 'sparseVector'nieefektywna metoda użyta dla '- e1'pośrednie 'r' jest typu %sbłąd wewnętrzny w metodzie 'Compare' (Cmp.Mat.atomic); proszę zgłosić raportbłąd wewnętrzny w metodzie 'Logic' (.Logic.Mat.atomic); proszę zgłosić raportwewnętrzny błąd: macierz 'i' w 'replTmat()': proszę zgłosić raportbłąd wewnętrzny: brakuje 'i' w 'replTmat()': proszę zgłosić raportniepoprawny łańcuch 'col.names': %sniepoprawne 'data'niepoprawne '(to - from)/by' w 'seq(.)'niepoprawne tekstowe indeksowanieniepoprawne nargs()=%ddługość musi być nieujemną liczbądługość pierwszego argumentu nie zgadza się z wymiarem drugiegodługość drugiego argumentu nie zgadza się z wymiarem pierwszegobłąd logiczny programu w 'printSpMatrix2()', proszę zgłosić raportindeks logiczny jest zbyt długi (%d, powinien być %d)długość dłuższego obiektu nie jest wielokrotnością długości krótszego obiektudługość dłuższego obiektu nie jest wielokrotnością długości krótszego obiektum[ ] <- v: nieefektywne traktowanie pojedynczych elementówpotrzeba określić 'A' lub funkcje 'A.x' oraz 'At.x''nargs() = %d' nie powinno się wydarzyć; proszę zgłosić raport.nargs() = %d. Obce nielegalne argumenty wewnątrz '[ .. ]' ?ujemne wartości nie są dozwolone w indeksach macierzybrak 'dimnames[[.]]': nie można używać indeksowania tekstowegoniezgodne wymiary macierzy w %snie uzbieżnił się w %d iteracjachzbyt mało nowych wektorów -- zatrzymywanie iteracjijeszcze niezaimplementowanejeszcze niezaimplementowane .. proszę zgłosić raportjeszcze niezaimplementowana metoda 'Matrix[<-'nic do zastąpienialiczba pozycji do zastąpienia nie jest wielokrotnością długości elementu zastępującegoliczba wierszy nie jest zgodna dla %s'prod()' nie jest jeszcze zaimplementowanerankMatrix(, method = '%s') przekształca macierz do gęstej macierzy. Prawdopodobnie należy użyć 'method = "qr"' !?rankMatrix(x, method='qr'): obliczanie t(x) jako nrow(x) < ncol(x)reprezentacja '%s' nie została rozpoznanaindeksy wiersza muszą być <= 'nrow(.)' który wynosi %dtakie indeksowanie musi być wykonane poprzez macierz logiczną lub 2-kolumnową macierz liczbową'sum()' nie jest jeszcze zaimplementowanemacierz symetryczna musi być kwadratowaforma symetryczna '%s' nie jest jeszcze zaimplementowanaforma symetryczna '%s' nie została rozpoznanaforma symetryczna 'hermitian' nie jest jeszcze zaimplementowana na potrzeby odczytuforma symetryczna 'skew-symmetric' nie jest jeszcze zaimplementowana na potrzeby odczytu(pod)-diagonala %d (k = %d) jest zbyt krótkal wypełnianie wartościami NAzbyt wiele argumentówzbyt dużo wartości zamieniającychtyp '%s' nie został rozpoznanyużywanie części 'old code' w przypisaniu w 'Csparse'używanie części 'old code' w przypisaniu w 'Csparse' >>> proszę zgłosić raport na adres 'Matrix-authors@r-project.org'zmienna '%s' jest nieobecna, jej kontrast zostanie zignorowanywektor jest zbyt długi w operacji macierz-wektorgdy 'A' jest określone, 'A.x' oraz 'At.x' są odrzucaneniepoprawny znak w argumencie 'by'x / 0 dla ' x' ze zmianą znaku nie jest dłużej reprezentowalne jako 'rleDiff'x[.,.] <- wartość : 'x' zostaje przekształcone z 'Tsparse*' na 'CsparseMatrix'x[.,.] <- wartość: 'x' to %s, wartość nie w zakresie {TRUE, FALSE} zostaje przekształcona NA |--> TRUE.x[.,.] <- wartość: 'x' to %s, wartość nie w zakresie {TRUE, FALSE} zostaje przekształcona.x[.] <- wartość: 'x' to %s, wartość nie w zakresie {TRUE, FALSE} zostaje przekształcona.x[.] <- wartość: 'x' to %s, wartość nie w zakresie {TRUE, FALSE} zostaje przekształcona; NA |--> TRUE.nie można mieszać ujemnych oraz dodatnich indeksówMatrix/inst/po/lt/0000755000175100001440000000000014576343415013562 5ustar hornikusersMatrix/inst/po/lt/LC_MESSAGES/0000755000175100001440000000000014576343415015347 5ustar hornikusersMatrix/inst/po/lt/LC_MESSAGES/Matrix.mo0000644000175100001440000001066114561104346017144 0ustar hornikusers$<5\01+Q+}3-! "-<P'+0,,?2l'-.$:&U|&/+@4<u%$$"A0]O- ! B 2/ Bb 1 ) & G( +p 8 2 0 09 5j 5 ; <O!j1!140GxTB(,%U%{/r 1 $" ! # 'data' must be of a vector typeArgument ij must be 2-column integer matrixArgument must be numeric-like atomic vectorMatrix exponential requires square, non-null matrixX must be a numeric (double precision) matrixX must be a real (numeric) matrixdata length exceeds size of matrixdgeMatrix_Schur: argument x must be a non-null square matrixdgeMatrix_Schur: dgees returned code %ddgeMatrix_Schur: first call to dgees faileddgeMatrix_exp: LAPACK routine dgebal returned %ddgeMatrix_exp: dgetrf returned error code %ddgeMatrix_exp: dgetrs returned error code %di and j must be integer vectors of the same lengthincorrect left cyclic shift, j (%d) < 0incorrect left cyclic shift, j (%d) >= k (%d)incorrect left cyclic shift, k (%d) > ldx (%d)invalid '%s' argumentinvalid 'ncol' value (< 0)invalid 'ncol' value (too large or NA)invalid 'nrow' value (< 0)invalid 'nrow' value (too large or NA)invalid class of 'value' in Csparse_subassign()invalid class of 'x' in Csparse_subassign()non-numeric matrix extentnumber of rows in y (%d) does not match number of rows in X (%d)programming error in Csparse_subassign() should never happenreplacement diagonal has wrong lengthsubscript 'i' out of bounds in M[ij]subscript 'j' out of bounds in M[ij]tol, given as %g, must be <= 1too many elements specifiedx[] <- val: val is coerced to logical for "%s" xx[] <- val: val should be integer or logical, is coerced to integer, for "%s" xy must be a numeric (double precision) matrixProject-Id-Version: Matrix 1.3-3 Report-Msgid-Bugs-To: PO-Revision-Date: 2021-02-25 14:30+0200 Last-Translator: Gabrielė Stupurienė Language-Team: none Language: lt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=3; plural=(n%10==1 && (n%100<11 || n%100>19) ? 0 : n%10>=2 && n%10<=9 && (n%100<11 || n%100>19) ? 1 : 2); X-Generator: Poedit 2.4.2 'data' turi būti vektoriaus tipoArgumentas ij turi būti 2 stulpelių sveikųjų skaičių matricaArgumentas turi būti skaitinis atominis vektoriusMatricos eksponentė reikalauja kvadratinės, ne nulinės matricosX turi būti skaitinė (dvigubo tikslumo) matricaX turi būti realioji (skaitinė) matricaduomenų ilgis viršija matricos dydįdgeMatrix_Schur: argumentas x turi būti ne nulinė kvadratinė matricadgeMatrix_Schur: dgees grąžintas kodas %ddgeMatrix_Schur: pirmasis iškvietimas į dgees nepavykodgeMatrix_exp: LAPACK programa dgebal grąžino %ddgeMatrix_exp: dgetrf grąžino klaidos kodą %ddgeMatrix_exp: dgetrs grąžino klaidos kodą %di ir j turi būti to paties ilgio sveikieji vektoriaineteisingas kairysis ciklinis pastūmimas, j (%d) < 0neteisingas kairysis ciklinis pastūmimas, j (%d) >= k (%d)neteisingas kairysis ciklinis pastūmimas, k (%d) > ldx (%d)netinkamas argumentas '%s'neleistina 'ncol' reikšmė (< 0)neleistina 'ncol' reikšmė (per didelė arba NA)neleistina 'nrow' reikšmė (< 0)neleistina 'nrow' reikšmė (per didelė arba NA)netinkama 'value' klasė, esanti Csparse_subassign()netinkama 'x' klasė, esanti Csparse_subassign()neskaitinės matricos dydiseilučių skaičius, esantis y (%d) neatitinka eilučių skaičiaus, esančio X (%d)programavimo klaida Csparse_subassign() niekada neturėtų įvyktikeitimo įstrižainės ilgis neteisingasapatinis indeksas 'i' už M[ij] ribųapatinis indeksas 'j' už M[ij] ribųtol, kaip %g, turi būti < = 1nurodyta per daug elementųx[] <- val: val yra paverstas į loginį "%s" xx[] <- val: val turėtų būti sveikasis skaičius arba loginis, yra pakeistas į sveikąjį skaičių dėl "%s" xy turi būti skaitinė (dvigubo tikslumo) matricaMatrix/inst/po/lt/LC_MESSAGES/R-Matrix.mo0000644000175100001440000003673414521047060017347 0ustar hornikusers,< 6 3( \ 9x  6 1 /; ,k ? : * #> b ,v ; # 4$LWq(0$#0Hy8'5:N5#,.?$RDw4D%6=\-7 *>ie""15gI"@@Q56(- Vw":91>3p:-@ ?N=2909=j51'*R&q$&B(S&|Bv?]"*;%'M"d)!9>AA 0+4\0`5# ,Y 7  O >*!Ii!<!:!H+",t"",H$.u$"$2$$=%7S%-%1%:%5&&1\& &&&&A& /'P':g'&'q'/;(*k((+((:).;)&j)"))F)?*+Z*2*/****P)+<z+>+!+B,7[,.,,$,,- 2-~S-,-,-3,.#`.T.&./D/D^/B/;/""0E02X0&0"00'0817M1+1-1@1; 2A\2@2B2:"30]3<3B3>4=M44,44.45(.5&W5~5?5'5#5A"6d6E6#-77Q7H7!77& 828)H8(r8%898@8;<9x99(9979=':<e:p:4;;H;6;#;K;?+<Vk<I<G =UT=1=o],WOc?3j_Cs5}6P{ F<Xl%VfxSU#Hb)+g!zIra|9 1 Z*`/nA$4wmMKh\JB-0t&7DN2"E i;^d[qu'pL:Ry= @vQY(.>eGT~8k'%s()' is not yet implemented for representation '%s''%s()' is not yet implemented for element type '%s''A' must be a square matrix'NA' indices are not (yet?) supported for sparse Matrices'by' argument is much too small'diagonals' matrix must have %d columns (= length(k) )'diagonals' must have the same length (%d) as 'k''file' must be a character string or connection'force' must be (coercable to) TRUE or FALSE'giveCsparse' has been deprecated; setting 'repr = "T"' for you'giveCsparse' has been deprecated; will use 'repr' instead'lwd' must be NULL or non-negative numeric'ncol' is not a factor of length(x)'ncol' must be >= 0'nearPD()' did not converge in %d iterations'nrow' and 'ncol' must be the same when 'symmetric' is true'nrow' is not a factor of length(x)'nrow' must be >= 0'x' must have length nrow^2 when 'symmetric' is true'x' must inherit from "sparseVector".M.repl.i.2col(): 'i' has no integer column number; should never happen; please report.M.repl.i.2col(): drop 'matrix' case ... --> is not yet implemented[i] is not yet implemented --> is not yet implementedClass %s is not yet implementedCmp.Mat.atomic() should not be called for diagonalMatrixInternal bug: nargs()=%d; please reportInvalid assembled indicator: %sInvalid storage format: %sInvalid storage type: %sLogic.Mat.atomic() should not be called for diagonalMatrixMatrices must have same number of rows for arithmeticMatrix seems negative semi-definiteMust specify 'nrow' when 'symmetric' is trueNAs are not allowed in subscripted assignmentsNot a valid formatOnly numeric sparse matrices allowedRHS 'value' (class %s) matches 'ANY', but must match matrix class %s[ ] indexing not allowed: forgot a "," ?a sparseMatrix should rarely be centered: will not be sparse anymoreall() is not yet implementedc(,..) of different kinds, coercing all to 'rleDiff'column indices must be <= ncol(.) which is %ddim [product %d] do not match the length of object [%d]dimnames [%d] mismatch in %selement type '%s' not recognizedelement type 'complex' not yet implementedfile is not a MatrixMarket filefor symmetric band matrix, only specify upper or lower triangle hence, all k must have the same signhit a cycle (1) -- stop iterationshit a cycle (2) -- stop iterationsi1[1] == 0 ==> C-level verbosity will not happen!index larger than maximal %dindex must be numeric, logical or sparseVector for indexing sparseVectorsinefficient method used for "- e1"intermediate 'r' is of type %sinternal bug in "Compare" method (Cmp.Mat.atomic); please reportinternal bug in "Logic" method (Logic.Mat.atomic); please reportinternal bug: matrix 'i' in replTmat(): please reportinternal bug: missing 'i' in replTmat(): please reportinvalid 'col.names' string: %sinvalid 'data'invalid 'repr'; must be "C", "T", or "R"invalid (to - from)/by in seq(.)invalid character indexinginvalid nargs()= %dlength must be non-negative numberlength of 'center' must equal the number of columns of 'x'length of 'scale' must equal the number of columns of 'x'length of 1st arg does not match dimension of 2ndlength of 2nd arg does not match dimension of firstlogic programming error in printSpMatrix2(), please reportlogical subscript too long (%d, should be %d)longer object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthm[ ] <- v: inefficiently treating single elementsmatrix can only be symmetric if square, but n != mmust either specify 'A' or the functions 'A.x' and 'At.x'nargs() = %d should never happen; please report.nargs() = %d. Extraneous illegal arguments inside '[ .. ]' ?negative values are not allowed in a matrix subscriptno 'dimnames[[.]]': cannot use character indexingnon-conformable argumentsnon-conformable matrix dimensions in %snot converged in %d iterationsnot enough new vecs -- stop iterationsnot yet implementednot yet implemented .. please reportnot-yet-implemented 'Matrix[<-' methodnothing to replace withnumber of items to replace is not a multiple of replacement lengthnumber of rows are not compatible for %sprod() is not yet implementedqr2rankMatrix(.): QR with only %d out of %d finite diag(R) entriesrankMatrix(, method = '%s') coerces to dense matrix. Probably should rather use method = 'qr' !?rankMatrix(x, method='qr'): computing t(x) as nrow(x) < ncol(x)representation '%s' not recognizedrow indices must be <= nrow(.) which is %dsuch indexing must be by logical or 2-column numeric matrixsum() is not yet implementedsuppressing %d columnssuppressing %d columns and %d rowssuppressing %d rowssymmetric matrix must be squaresymmetry form '%s' is not yet implementedsymmetry form '%s' not recognizedsymmetry form 'hermitian' not yet implemented for readingsymmetry form 'skew-symmetric' not yet implemented for readingthe %d-th (sub)-diagonal (k = %d) is too short; filling with NA'stoo many argumentstoo many replacement valuestriangular matrix must be squaretype '%s' not recognizeduniDiag=TRUE, but not all diagonal entries are 1uniDiag=TRUE, not all entries in diagonal coded as 1using "old code" part in Csparse subassignmentusing"old code" part in Csparse subassignment >>> please report to Matrix-authors@r-project.orgvariable '%s' is absent, its contrast will be ignoredvector too long in Matrix - vector operationwhen 'A' is specified, 'A.x' and 'At.x' are disregardedwrong sign in 'by' argumentx / 0 for an x with sign-change no longer representable as 'rleDiff'x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrixx[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE.x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced; NA |--> TRUE.you cannot mix negative and positive indicesProject-Id-Version: Matrix 1.3-3 PO-Revision-Date: 2021-03-01 20:55+0200 Last-Translator: Gabrielė Stupurienė Language-Team: none Language: lt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: Poedit 2.4.2 Plural-Forms: nplurals=3; plural=(n%10==1 && (n%100<11 || n%100>19) ? 0 : n%10>=2 && n%10<=9 && (n%100<11 || n%100>19) ? 1 : 2); '%s()' dar neįgyvendinta '%s' atvaizdavimui'%s()' dar neįgyvendinta elementų tipui '%s''A' turi būti kvadratinė matrica'NA' indeksai nėra (dar?) remiami sparse Matrices'by' argumentas per mažas'diagonals' matricoje turi būti %d stulpeliai (= length(k) )'diagonals' turi būti tokio pat ilgio (%d) kaip ir 'k''file' turi būti simbolių eilutė ar ryšys'force' turi būti (verčiama į) TRUE arba FALSE'giveCsparse' nebenaudojamas; nustatymas 'repr = "T"' jums'giveCsparse' nebenaudojamas; vietoj to naudos 'repr''lwd' turi būti NULL arba ne neigiamas skaitinis'ncol' nėra length(x) faktorius'ncol' turi būti >= 0'nearPD()' nekonvergavo %d iteracijose'nrow' ir 'ncol' turi būti vienodi, kai 'symmetric' yra teisinga"nrow" nėra length(x) faktorius'nrow' turi būti >= 0'x' turi būti ilgio nrow^2, kai 'symmetric' yra teisingas'x' turi paveldėti iš "sparseVector".M.repl.i.2col(): 'i' neturi sveiko skaičiaus stulpelio numerio; niekada neturėtų įvykti; prašome pranešti.M.repl.i.2col(): išmetė 'matrix' atveją ... --> dar neįgyvendinta[i] dar neįgyvendinta --> dar neįgyvendintasKlasės %s dar neįgyvendintaCmp.Mat.atomic() negalima būti iškviestas diagonalMatrixVidinė klaida: nargs()=%d; prašome praneštiNeleistinas surinktas indikatorius: %sNeleistinas saugyklos formatas: %sNetinkamas saugyklos tipas: %sLogic.Mat.atomic() neturėtų būti iškviečiamas dėl diagonalMatrixMatricos turi turėti tą patį eilučių skaičių aritmetikaiMatrica atrodo pusiau neigiamai apibrėžtaTuri nurodyti 'nrow', kai 'symmetric' yra teisingaNA neleidžiamos apatinio indekso priskyrimuoseNeleistinas formatasLeidžiamos tik skaitinės sparse matricosRHS 'value' (%s klasė) atitinka 'ANY', tačiau turi atitikti matricos klasę %s[ ] indeksavimas neleidžiamas: pamiršote "," ?sparseMatrix retai turėtų būti centre: daugiau nebus sparseall() dar neįgyvendintic(,..) įvairių rūšių, paverčiant visus į 'rleDiff'stulpelių indeksai turi būti <= ncol(.), kuris yra %ddim [product %d] neatitinka objekto ilgio [%d]dimnames [%d] neatitikimas %selemento tipas '%s' neatpažįstamaselemento tipas 'complex' dar neįgyvendintasfailas nėra MatrixMarket failassimetrinės juostos matricai nurodykite tik viršutinį arba apatinį trikampį taigi, visi k turi turėti tą patį ženkląpasiekti ciklą (1) -- sustabdyti iteracijaspasiekti ciklą (2) -- sustabdyti iteracijasi1[1] == 0 ==> C lygio daugiakalbiškumas neįvyks!indeksas didesnis nei maksimalus %dindeksas turi būti skaitinis, loginis arba sparseVector, sparseVectors indeksavimuineefektyvus metodas, naudojamas "- e1"tarpinis 'r' yra %s tipovidinė klaida "Compare" metode (Cmp.Mat.atomic); prašome praneštividinė klaida "Logic" metode (Logic.Mat.atomic); prašome praneštividinė klaida: matrica 'i', esanti replTmat(): prašome praneštividinė klaida: trūksta 'i' replTmat(): prašome praneštineleistina 'col.names' eilutė: %sneleistinas 'data'negaliojantis 'repr'; turi būti "C", "T" arba "R"negaliojantis (iki - nuo)/pagal seq(.)neleistinas simbolių indeksavimasneleistini nargs()= %dilgis turi būti ne neigiamas skaičius'center' ilgis turi būti lygus stulpelių skaičiui 'x''scale' ilgis turi būti lygus stulpelių skaičiui 'x'1-mo arg ilgis nesutampa su 2-ojo dimensija2-ojo arg ilgis neatitinka pirmojo dimensijosloginio programavimo klaida printSpMatrix2(), prašome praneštiloginis apatinis indeksas per ilgas (%d, turėtų būti %d)ilgesnis objekto ilgis nėra trumpesnio objekto ilgio kartotinisilgesnis objekto ilgis nėra trumpesnio objekto ilgio kartotinism[ ] <- v: neefektyviai apdorojant pavienius elementusmatrica gali būti simetriška tik kvadratinė, bet n != mturi nurodyti 'A' arba funkcijas 'A.x' ir 'At.x'nargs() = %d niekada neturėtų įvykti; prašome pranešti.nargs() = %d. Pašaliniai neteisėti argumentai viduje '[ .. ]' ?matricos apatiniame indekse neigiamos reikšmės neleidžiamosnėra 'dimnames[[.]]': negalima naudoti simbolių indeksavimoneatitinkantys argumentaineatitinkantys matricos matmenys, esantys %snekonverguoja %d iteracijosenepakanka naujų vecs -- sustabdyti iteracijasdar neįvykdytadar neįgyvendinta .. prašome praneštidar neįgyvendintas 'Matrix[<-' methodnėra nieko pakeisti sukeičiamų elementų skaičius nėra keičiamo ilgio kartotiniseilučių skaičius nesuderinamas su %sprod() dar neįgyvendintasqr2rankMatrix(.): QR tik su %d iš %d baigtinių diag(R) įrašųrankMatrix(, method = '%s') paverčiamas į tankio matricą. Tikriausiai reikėtų naudoti metodą = 'qr' !?rankMatrix(x, method='qr'): skaičiavimas t(x) kaip nrow(x) < ncol(x)neatpažįstamas atvaizdavimas '%s'eilučių indeksai turi būti < = nrow(.), kuris yra %dtoks indeksavimas turi būti loginis arba 2 stulpelių skaitinė matricasum() dar neįgyvendintanerodyti %d stulpeliųnerodyti %d stulpelių ir %d eilučiųnerodyti %d eilučiųsimetrinė matrica turi būti kvadratinėsimetrinė forma '%s' dar neįgyvendintasimetrinė forma '%s' neatpažįstamasimetrinė forma 'hermitian' dar neįgyvendinta skaitymuisimetriška forma 'skew-symmetric', dar neįgyvendinta skaitymui%d įstrižainė (k = %d) yra per trumpa; užpildymas su NAper daug argumentųper daug pakeitimo reikšmiųtrikampė matrica turi būti kvadratinėtipas '%s' neatpažįstamasuniDiag=TRUE, bet ne visi įstrižainės įrašai yra 1uniDiag=TRUE, ne visi įstrižainės įrašai, koduoti kaip 1naudojant "senojo kodo" dalį Csparse antriniame priskyrimenaudojant "senojo kodo" dalį Csparse antriniame priskyrime >>> prašome pranešti Matrix-authors@r-project.orgkintamojo '%s' nėra, jo kontrastas bus ignoruojamasvektorius, esantis Matrix, per ilgas - vektoriaus operacijakai nurodyta 'A', į 'A.x' and 'At.x' neatsižvelgiamaneteisingas ženklas 'by' argumentex / 0 dėl x su ženklo pakeitimu nebeatitinkamas kaip 'rleDiff'x[.,.] <- val: x yra paverčiamas iš Tsparse* į CsparseMatrixx[...] <- val: x yra %s, val, kurio nėra {TRUE, FALSE} yra paverčiamas NA |--> TRUE.x[.,.] <- val: x yra %s, val, kurio nėra {TRUE, FALSE} yra paverčiamas.x[.] <- val: x yra %s, val, kurio nėra {TRUE, FALSE} yra paverčiamas.x[.] <- val: x yra %s, val, kurio nėra {TRUE, FALSE} yra paverčiamas; NA |--> TRUE.negalite maišyti neigiamų ir teigiamų indeksųMatrix/inst/po/en@quot/0000755000175100001440000000000014576343415014556 5ustar hornikusersMatrix/inst/po/en@quot/LC_MESSAGES/0000755000175100001440000000000014576343415016343 5ustar hornikusersMatrix/inst/po/en@quot/LC_MESSAGES/Matrix.mo0000644000175100001440000005355314574652341020156 0ustar hornikusersL  7 :GYy<'//):Y$000-Lz%# <4]1,& 5AUm "0J`v$ :9&`v"!!.I"^@' $ +0!\!~( ')(Q(z7)+Ic{9A*8>'w-% )0RZFF;Y+y+(*.% #T $x # $ = -$!3R!=!,!-!-"!M"3o"A"/"#!1#1S#:#9#"#&$7D$2|$!$$!$-%)6%>`%+%R%O&"n&-&<&'&+$'0P',','','1$($V(?{(A(((#&)7J)2)")')-*..*]*u***&**&*$+/B++r++X+ ,#(,-L,3z,+,5,!-%2-$X-A}----).(:.>c.@.%.; /<E///%/9/0;*0$f0$0000 1<&1Fc111141 420?2Op2-2/2424 N47o4 4444<5+>53j535:5$ 64260g606-667%7A7Z7%z77 787984M8 8*8888 9;9J9i99&9999:5:O:,o::(:B:A#;e;!;&;";%;%<27<j<&<D<+<$=(@=3i=%=%=#=, >#:>'^>+>,>,>? ?L?-`??!???@=$@Eb@.@<@+A1@A"rA!A)A-AVBJfBJB!B#C+BC+nC0C2C.C#-D$QD#vD$D=D-D3+EA_E,E-E-E!*F7LFEF3FF%G1DG:vG9G"G&H75H2mH!HH!H1H)+I>UI/IRIOJ"gJ-J<J'J+K0IK,zK,KK4K9%L$_LGLEL,M'?M?gM2M.M' N-1N._NNNNN*N'O*FOqO3O/OOXP`P'}P-P3P+Q53Q!iQ%Q$QAQR5ROR)iR(R>R@R%|sE%* SK$7f_9?h~N A[80qvLz'5eHwQ]tM%s cannot exceed %s%s has elements not in {%s}%s has elements not in {%s}\{%s}%s is %d but columns are not stored in increasing order%s is not %d%s is not in {%s}%s is not representable as "%s"%s length cannot exceed %s%s too dense for %s; would have more than %s nonzero entries%s(%s) is undefined: '%s' is not square%s(%s, %s) requires m-by-n '%s' with m >= n > 0%s(%s, %s) requires m-by-n '%s' with n >= m > 0%s(<%s>) does not support structurally rank deficient case%s(<%s>, <%s>) failed: out of memory%s-by-%s %s invalid for positive '%s' when %s=%d%s="%s" but there are entries above the diagonal%s="%s" but there are entries below the diagonal%s="%s" but there are entries on the diagonal%s[%d] (%s) is negative%s[%d] (%s) is not %d%s[%d] (%s) is not %d or %d%s[%d] (%s) is not in %s%s[%d] (%s) is not less than %s%s[1] != %s[2] (matrix is not square)%s[1] differs from %s[2]%s[[%d]] is not NULL or a vector'%s' (%d) must be an integer from %s (%d) to %s (%d)'%s' (%d) must be less than or equal to '%s' (%d)'%s' and '%s' slots do not have equal length'%s' does not have length %d'%s' does not support complex matrices'%s' failed'%s' failed in '%s''%s' failed in '%s': %s'%s' has length exceeding %s'%s' is NA'%s' is NA or less than %s'%s' is empty or not square'%s' is not a number'%s' is not a number or not finite'%s' is not of type "%s"'%s' is not square'%s' must be "%s" or "%s"'%s' must be %d or %d'%s' must be %s or %s'%s' must be %s or %s or %s'%s' or '%s' does not have length %d'%s' or '%s' is NA'%s' or '%s' is not of type "%s"'%s' slot allocates fewer than %s elements for column '%s''%s' slot allocates more than %s elements for column '%s''%s' slot contains NA'%s' slot contains duplicates'%s' slot does not have %s columns'%s' slot does not have %s row'%s' slot does not have length %d'%s' slot does not have length %s'%s' slot does not have length %s or length %s'%s' slot exceeds %s'%s' slot has elements not in {%s}'%s' slot has elements not in {%s} after truncation towards zero'%s' slot has elements not in {%s}\{%s}'%s' slot has fewer than %s rows'%s' slot has length greater than %s'%s' slot has length greater than '%s' slot'%s' slot has length less than %d'%s' slot has length less than %s'%s' slot has more than %s rows'%s' slot has negative diagonal elements'%s' slot has negative elements'%s' slot has no '%s' attribute'%s' slot has nonunit diagonal elements'%s' slot has nonzero length but %s is 0'%s' slot has unpaired negative elements'%s' slot is "%s" but '%s' slot does not have length %s'%s' slot is NA'%s' slot is lower (not upper) triangular'%s' slot is negative'%s' slot is not "%s" or "%s"'%s' slot is not %d or %d'%s' slot is not a list'%s' slot is not increasing'%s' slot is not increasing after truncation towards zero'%s' slot is not increasing when traversed in stored column order'%s' slot is not increasing within columns'%s' slot is not increasing within columns after sorting'%s' slot is not increasing within rows'%s' slot is not increasing within supernodes'%s' slot is not nondecreasing'%s' slot is not of type "%s"'%s' slot is not of type "%s" or "%s"'%s' slot is upper (not lower) triangular'%s' slot is wrong within diagonal blocks (row and column indices do not coincide)'%s' slot must be lower trapezoidal but has entries above the diagonal'%s' slot must be upper trapezoidal but has entries below the diagonal'%s' would overflow type "%s"'data' must be of a vector typeArgument ij must be 2-column integer matrixArgument must be numeric-like atomic vectorCHOLMOD error '%s' at file '%s', line %dCHOLMOD warning '%s' at file '%s', line %dCholesky factor has negative diagonal elementsLAPACK dgels returned error code %dLAPACK dgeqrf returned error code %dLAPACK dposv returned error code %dLAPACK dtrcon returned error code %dLU factorization of %s failed: out of memory or near-singularLU factorization of m-by-n %s requires m == nMatrix exponential requires square, non-null matrixNA subscripts in %s not supported for '%s' inheriting from %sQR factorization of %s failed: out of memoryQR factorization of m-by-n %s requires m >= nX must be a numeric (double precision) matrixX must be a real (numeric) matrixargument '%s' ("%s") does not have string length %dargument '%s' ("%s") is not "%s", "%s", "%s", "%s", "%s", or "%s"argument '%s' ("%s") is not "%s", "%s", or "%s"argument '%s' has length %dargument '%s' is not of type "%s"attempt to allocate vector of length exceeding %sattempt to construct %s with more than %s nonzero elementsattempt to construct %s with more than %s nonzero entriesattempt to construct non-square %sattempt to get sign of non-permutationattempt to get skew-symmetric part of non-square matrixattempt to get symmetric part of non-square matrixattempt to invert non-permutationattempt to pack a %sattempt to pack non-square matrixattempt to set factor on %s without '%s' slotattempt to symmetrize a non-square matrixcoercing n-by-n %s to %s is not supported for n*n exceeding %scolumn '%s' is stored first but %s is not 0data length [%lld] is not a sub-multiple or multiple of the number of columns [%d]data length [%lld] is not a sub-multiple or multiple of the number of rows [%d]data length exceeds size of matrixdeterminant of non-square matrix is undefineddgeMatrix_Schur: argument x must be a non-null square matrixdgeMatrix_Schur: dgees returned code %ddgeMatrix_Schur: first call to dgees faileddgeMatrix_exp: LAPACK routine dgebal returned %ddgeMatrix_exp: dgetrf returned error code %ddgeMatrix_exp: dgetrs returned error code %ddimensions cannot exceed %sdimensions of '%s' and '%s' are inconsistentdimensions of '%s' slot are not identical to '%s'failed to open file "%s" for writingfirst differences of '%s' slot are less than those of '%s' slotfirst differences of '%s' slot are not equal to supernode lengthsfirst differences of '%s' slot exceed %sfirst element of '%s' slot is not 0first entry in column '%s' does not have row index '%s'i and j must be integer vectors of the same lengthincompatible '%s' and '%s' in '%s'incorrect left cyclic shift, j (%d) < 0incorrect left cyclic shift, j (%d) >= k (%d)incorrect left cyclic shift, k (%d) > ldx (%d)indices would exceed %sinvalid '%s' argumentinvalid '%s' to '%s'invalid 'ncol' value (< 0)invalid 'ncol' value (too large or NA)invalid 'nrow' value (< 0)invalid 'nrow' value (too large or NA)invalid class "%s" object: %sinvalid class of 'value' in Csparse_subassign()invalid class of 'x' in Csparse_subassign()invalid factor nameinvalid simplicial Cholesky factorization: structural zero on main diagonal in column %dinvalid transposition vectorlast element of '%s' slot is not %sleading dimension not equal to number of rowsleading principal minor of order %d is not positiveleading principal minor of order %d is zerolength of %s[[%d]] (%lld) is not equal to %s[%d] (%d)matrix has more columns than rowsmatrix has negative diagonal elementsmatrix has nonunit diagonal elementsmatrix length (%d * %d) is not a multiple of vector length (%lld)n+1 would overflow type "%s"non-conformable argumentsnon-numeric matrix extentnonempty vector supplied for empty matrixnumber of columns of matrices must matchnumber of columns of result is not a multiple of vector lengthnumber of rows in y (%d) does not match number of rows in X (%d)number of rows of matrices must matchnumber of rows of result is not a multiple of vector lengthprogramming error in Csparse_subassign() should never happenreplacement diagonal has incompatible type "%s"replacement diagonal has wrong lengthsecond argument of '%s' does not specify a subclass of %sshould never happen ...sparse->dense coercion: allocating vector of size %0.1f GiBsubscript 'i' out of bounds in M[ij]subscript 'j' out of bounds in M[ij]supernode lengths exceed %stol, given as %g, must be <= 1tol, given as %g, must be >= 0too many elements specifiedtraversal of '%s' slot does not complete in exactly %s stepsunable to aggregate %s with '%s' and '%s' slots of length exceeding %sunexpected kind "%c" in '%s'unexpected type "%s" in '%s'unknown error in getGivensvector length (%lld) exceeds matrix length (%d * %d)wrong '%s'x[] <- val: val is coerced to logical for "%s" xx[] <- val: val should be integer or logical, is coerced to integer, for "%s" xy must be a numeric (double precision) matrixProject-Id-Version: Matrix 1.7-0 Report-Msgid-Bugs-To: PO-Revision-Date: 2024-03-14 15:49-0400 Last-Translator: Automatically generated Language-Team: none Language: en MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); %s cannot exceed %s%s has elements not in {%s}%s has elements not in {%s}\{%s}%s is %d but columns are not stored in increasing order%s is not %d%s is not in {%s}%s is not representable as "%s"%s length cannot exceed %s%s too dense for %s; would have more than %s nonzero entries%s(%s) is undefined: ‘%s’ is not square%s(%s, %s) requires m-by-n ‘%s’ with m >= n > 0%s(%s, %s) requires m-by-n ‘%s’ with n >= m > 0%s(<%s>) does not support structurally rank deficient case%s(<%s>, <%s>) failed: out of memory%s-by-%s %s invalid for positive ‘%s’ when %s=%d%s="%s" but there are entries above the diagonal%s="%s" but there are entries below the diagonal%s="%s" but there are entries on the diagonal%s[%d] (%s) is negative%s[%d] (%s) is not %d%s[%d] (%s) is not %d or %d%s[%d] (%s) is not in %s%s[%d] (%s) is not less than %s%s[1] != %s[2] (matrix is not square)%s[1] differs from %s[2]%s[[%d]] is not NULL or a vector‘%s’ (%d) must be an integer from %s (%d) to %s (%d)‘%s’ (%d) must be less than or equal to ‘%s’ (%d)‘%s’ and ‘%s’ slots do not have equal length‘%s’ does not have length %d‘%s’ does not support complex matrices‘%s’ failed‘%s’ failed in ‘%s’‘%s’ failed in ‘%s’: %s‘%s’ has length exceeding %s‘%s’ is NA‘%s’ is NA or less than %s‘%s’ is empty or not square‘%s’ is not a number‘%s’ is not a number or not finite‘%s’ is not of type "%s"‘%s’ is not square‘%s’ must be "%s" or "%s"‘%s’ must be %d or %d‘%s’ must be %s or %s‘%s’ must be %s or %s or %s‘%s’ or ‘%s’ does not have length %d‘%s’ or ‘%s’ is NA‘%s’ or ‘%s’ is not of type "%s"‘%s’ slot allocates fewer than %s elements for column ‘%s’‘%s’ slot allocates more than %s elements for column ‘%s’‘%s’ slot contains NA‘%s’ slot contains duplicates‘%s’ slot does not have %s columns‘%s’ slot does not have %s row‘%s’ slot does not have length %d‘%s’ slot does not have length %s‘%s’ slot does not have length %s or length %s‘%s’ slot exceeds %s‘%s’ slot has elements not in {%s}‘%s’ slot has elements not in {%s} after truncation towards zero‘%s’ slot has elements not in {%s}\{%s}‘%s’ slot has fewer than %s rows‘%s’ slot has length greater than %s‘%s’ slot has length greater than ‘%s’ slot‘%s’ slot has length less than %d‘%s’ slot has length less than %s‘%s’ slot has more than %s rows‘%s’ slot has negative diagonal elements‘%s’ slot has negative elements‘%s’ slot has no ‘%s’ attribute‘%s’ slot has nonunit diagonal elements‘%s’ slot has nonzero length but %s is 0‘%s’ slot has unpaired negative elements‘%s’ slot is "%s" but ‘%s’ slot does not have length %s‘%s’ slot is NA‘%s’ slot is lower (not upper) triangular‘%s’ slot is negative‘%s’ slot is not "%s" or "%s"‘%s’ slot is not %d or %d‘%s’ slot is not a list‘%s’ slot is not increasing‘%s’ slot is not increasing after truncation towards zero‘%s’ slot is not increasing when traversed in stored column order‘%s’ slot is not increasing within columns‘%s’ slot is not increasing within columns after sorting‘%s’ slot is not increasing within rows‘%s’ slot is not increasing within supernodes‘%s’ slot is not nondecreasing‘%s’ slot is not of type "%s"‘%s’ slot is not of type "%s" or "%s"‘%s’ slot is upper (not lower) triangular‘%s’ slot is wrong within diagonal blocks (row and column indices do not coincide)‘%s’ slot must be lower trapezoidal but has entries above the diagonal‘%s’ slot must be upper trapezoidal but has entries below the diagonal‘%s’ would overflow type "%s"‘data’ must be of a vector typeArgument ij must be 2-column integer matrixArgument must be numeric-like atomic vectorCHOLMOD error ‘%s’ at file ‘%s’, line %dCHOLMOD warning ‘%s’ at file ‘%s’, line %dCholesky factor has negative diagonal elementsLAPACK dgels returned error code %dLAPACK dgeqrf returned error code %dLAPACK dposv returned error code %dLAPACK dtrcon returned error code %dLU factorization of %s failed: out of memory or near-singularLU factorization of m-by-n %s requires m == nMatrix exponential requires square, non-null matrixNA subscripts in %s not supported for ‘%s’ inheriting from %sQR factorization of %s failed: out of memoryQR factorization of m-by-n %s requires m >= nX must be a numeric (double precision) matrixX must be a real (numeric) matrixargument ‘%s’ ("%s") does not have string length %dargument ‘%s’ ("%s") is not "%s", "%s", "%s", "%s", "%s", or "%s"argument ‘%s’ ("%s") is not "%s", "%s", or "%s"argument ‘%s’ has length %dargument ‘%s’ is not of type "%s"attempt to allocate vector of length exceeding %sattempt to construct %s with more than %s nonzero elementsattempt to construct %s with more than %s nonzero entriesattempt to construct non-square %sattempt to get sign of non-permutationattempt to get skew-symmetric part of non-square matrixattempt to get symmetric part of non-square matrixattempt to invert non-permutationattempt to pack a %sattempt to pack non-square matrixattempt to set factor on %s without ‘%s’ slotattempt to symmetrize a non-square matrixcoercing n-by-n %s to %s is not supported for n*n exceeding %scolumn ‘%s’ is stored first but %s is not 0data length [%lld] is not a sub-multiple or multiple of the number of columns [%d]data length [%lld] is not a sub-multiple or multiple of the number of rows [%d]data length exceeds size of matrixdeterminant of non-square matrix is undefineddgeMatrix_Schur: argument x must be a non-null square matrixdgeMatrix_Schur: dgees returned code %ddgeMatrix_Schur: first call to dgees faileddgeMatrix_exp: LAPACK routine dgebal returned %ddgeMatrix_exp: dgetrf returned error code %ddgeMatrix_exp: dgetrs returned error code %ddimensions cannot exceed %sdimensions of ‘%s’ and ‘%s’ are inconsistentdimensions of ‘%s’ slot are not identical to ‘%s’failed to open file "%s" for writingfirst differences of ‘%s’ slot are less than those of ‘%s’ slotfirst differences of ‘%s’ slot are not equal to supernode lengthsfirst differences of ‘%s’ slot exceed %sfirst element of ‘%s’ slot is not 0first entry in column ‘%s’ does not have row index ‘%s’i and j must be integer vectors of the same lengthincompatible ‘%s’ and ‘%s’ in ‘%s’incorrect left cyclic shift, j (%d) < 0incorrect left cyclic shift, j (%d) >= k (%d)incorrect left cyclic shift, k (%d) > ldx (%d)indices would exceed %sinvalid ‘%s’ argumentinvalid ‘%s’ to ‘%s’invalid ‘ncol’ value (< 0)invalid ‘ncol’ value (too large or NA)invalid ‘nrow’ value (< 0)invalid ‘nrow’ value (too large or NA)invalid class "%s" object: %sinvalid class of ‘value’ in Csparse_subassign()invalid class of ‘x’ in Csparse_subassign()invalid factor nameinvalid simplicial Cholesky factorization: structural zero on main diagonal in column %dinvalid transposition vectorlast element of ‘%s’ slot is not %sleading dimension not equal to number of rowsleading principal minor of order %d is not positiveleading principal minor of order %d is zerolength of %s[[%d]] (%lld) is not equal to %s[%d] (%d)matrix has more columns than rowsmatrix has negative diagonal elementsmatrix has nonunit diagonal elementsmatrix length (%d * %d) is not a multiple of vector length (%lld)n+1 would overflow type "%s"non-conformable argumentsnon-numeric matrix extentnonempty vector supplied for empty matrixnumber of columns of matrices must matchnumber of columns of result is not a multiple of vector lengthnumber of rows in y (%d) does not match number of rows in X (%d)number of rows of matrices must matchnumber of rows of result is not a multiple of vector lengthprogramming error in Csparse_subassign() should never happenreplacement diagonal has incompatible type "%s"replacement diagonal has wrong lengthsecond argument of ‘%s’ does not specify a subclass of %sshould never happen ...sparse->dense coercion: allocating vector of size %0.1f GiBsubscript ‘i’ out of bounds in M[ij]subscript ‘j’ out of bounds in M[ij]supernode lengths exceed %stol, given as %g, must be <= 1tol, given as %g, must be >= 0too many elements specifiedtraversal of ‘%s’ slot does not complete in exactly %s stepsunable to aggregate %s with ‘%s’ and ‘%s’ slots of length exceeding %sunexpected kind "%c" in ‘%s’unexpected type "%s" in ‘%s’unknown error in getGivensvector length (%lld) exceeds matrix length (%d * %d)wrong ‘%s’x[] <- val: val is coerced to logical for "%s" xx[] <- val: val should be integer or logical, is coerced to integer, for "%s" xy must be a numeric (double precision) matrixMatrix/inst/po/en@quot/LC_MESSAGES/R-Matrix.mo0000644000175100001440000007177314575137654020367 0ustar hornikusers tgh<i[ =4^(WENZ2>'C+T #B#\&'!(#/ St$!6399U1&6>1u#/,?(:h51 #?c*x"#,;+ #g  8 , $!*!D!c!4!$!W!(3"0\"$"0""8#<#O#'h####:#5$#U$,y$.$$$$D %4R%)%D%%%D&a& |&0&)&&&')='8g'=''''-"(P(o(-(J(7(1)M),m)) )*):*>*#^*e*"*" +1.+3`+++I+",=,@\,@,5,6-K-[-s------(-(. D.e..!.(...& /%3/Y/v// /'/"/:09S01030 00:1R1-m1@1?1=22Z2&2*2)24 3>3S3%k3B3353`#49484>4659R59505=5&565\6166'6#7 *7)77a7Mf77&77$8&38Z8Br8*8(8< 90F9 w99&9B9v9?n:3:/:0;1C;/u;%;;";* <5<M<(e<;<%<<"=*=>=)^=!=9=>=A#>e>>? ,?.M?|?!?0?4?N@0l@`@5@,4A7aAAOA>BIDB<B:BHC,OC|C@DDD[ E hE8E,E[EIKFRF6FBG/bGG/G(G"H+#HOHnHFH'H.H+*IVI%oI,I'I$IJ(&J%OJ>uJ;JJ=K#NK"rK5KK*K:L9LL'L3L0LGMB[M9M9MN'.N'VN~N.N&N'NO0-OG^O'OOHO0/P(`PP"P!P<P()Q[RQ,Q0Q$ R01RbR8RRR'RS/SJS:cS5S#S4S.-T\T$oTLT4T)UD@U%UDUU V0,V)]VV&V)V@VA7WyW'W-WW X-XJIX7XXX4Y=Y$ZY.YFYY'Ze=Z"Z"Z1Z3[O[n[I["["[@\@\\9\:\]"]>]X]w]"]]],],^ /^P^k^%^,^^^&_%*_P_m__$_'_"_B`AZ`1`3` a a:&aaa-|a@a?a=+b2ib&b*b)b4cMcbc%zcBcc5c`2d9d8d>eEe9aeEe0eAf*Tf5f5ff'g#-g Qg)^ggMgg&g!h$5h*ZhhBh*h( i<4i0qi ii&iBi~"jCj7j/k4Mk1k/k%k l&&l*Mlxll(l;l% m3m"Jmmmm-m%m=mB3nAvnn\ooo o.oo%o0p4OpNp0p`q9eq,qCqrS0r>rIr< s:JsHs,s<m@%qu4~|{13iAoQ EP8=9fGI#&cR2!'zr ,Y]n7db^S+gMX:`*yjtwk0)pe/H x. B};"CUF(Wv- s>65l[ NDV aKT_ ?$\Z hOJL%1$s(%2$s) is undefined: '%2$s' is not positive semidefinite%s length cannot exceed %s%s(<%s>) is not yet implemented%s(<%s>, <%s>) is not yet implemented; ask maintainer("%s") to implement the missing method%s="%s" invalid for %s@uplo="%s"'%1$s' is computationally singular, rcond(%1$s)=%2$g'%1$s' is not "%2$s", "%3$s", or "%2$s."'%1$s' is not "%2$s1", "%2$s1.", "%2$s2", "%2$s2.", "%3$s", "%3$s1", "%4$s", or "%4$s1"'%1$s' is not "%2$s1", "%2$s1.", "%2$s2", "%2$s2.", "%3$s", or "%4$s"'%1$s' is not "%2$s1", "%2$s1.", "%3$s", "%3$s.", "%3$s1", "%3$s1.", or "%4$s"'%1$s' is not "%2$s1", "%2$s1.", "%3$s", or "%4$s"'%1$s' is not formally symmetric; factorizing tcrossprod(%1$s)'%s' and '%s' must be positive integers'%s' contains NA'%s' does not inherit from virtual class %s'%s' has elements exceeding '%s''%s' has elements less than %d'%s' has length 0 but '%s' does not'%s' has non-finite values'%s' has the wrong length'%s' is computationally singular, min(d)/max(d)=%g, d=abs(diag(U))'%s' is deprecated; setting %s="%s"'%s' is deprecated; using '%s' instead'%s' is not "%1$s", "D%1$s", or "%1$s."'%s' is not %d or %d'%s' is not a non-negative number'%s' is not a permutation of seq_len(%s)'%s' is not a square numeric matrix'%s' is not of type "%s" or "%s"'%s' is not square'%s' method must use default %s="%s"'%s' via sparse -> dense coercion'%s()' is not yet implemented for representation '%s''%s()' is not yet implemented for element type '%s''A' must be a square matrix'NA' indices are not (yet?) supported for sparse Matrices'by' argument is much too small'cl' is not a character string'cols' has elements not in seq(0, length.out = n)'cols' must be numeric'contrasts.arg' argument must be named'diagonals' matrix must have %d columns (= length(k) )'diagonals' must have the same length (%d) as 'k''dims' must contain all (i,j) pairs'file' must be a character string or connection'force' must be (coercable to) TRUE or FALSE'giveCsparse' has been deprecated; setting 'repr = "T"' for you'giveCsparse' has been deprecated; will use 'repr' instead'giveCsparse' is deprecated; setting repr="T" for you'giveCsparse' is deprecated; using 'repr' instead'i' and 'j' must be'i' and 'j' must not contain NA'kind' must be one of "d", "l", "n"'lst' must be a list'lwd' must be NULL or non-negative numeric'n' must be a non-negative integer'ncol' is not a factor of length(x)'ncol' must be >= 0'nearPD()' did not converge in %d iterations'nrow' and 'ncol' must be the same when 'symmetric' is true'nrow' is not a factor of length(x)'nrow' must be >= 0'nrow', 'ncol', 'byrow' disregarded for [mM]atrix 'data''p' must be a nondecreasing vector c(0, ...)'shape' must be one of "g", "t", "s"'uplo' must be "U" or "L"'x' has unsupported class "%s"'x' has unsupported type "%s"'x' must have length nrow^2 when 'symmetric' is true'x' must inherit from "sparseVector".M.repl.i.2col(): 'i' has no integer column number; should never happen; please report.M.repl.i.2col(): drop 'matrix' case ... --> is not yet implemented[i] is not yet implemented --> is not yet implementedClass %s is not yet implementedCmp.Mat.atomic() should not be called for diagonalMatrixD[i,i] is NA, i=%dD[i,i] is negative, i=%dInternal bug: nargs()=%d; please reportInvalid assembled indicator: %sInvalid storage format: %sInvalid storage type: %sLogic.Mat.atomic() should not be called for diagonalMatrixMatrices must have same number of rows for arithmeticMatrix seems negative semi-definiteMust specify 'nrow' when 'symmetric' is trueNAs are not allowed in subscripted assignmentsNot a valid formatOnly numeric sparse matrices allowedRHS 'value' (class %s) matches 'ANY', but must match matrix class %s[ ] indexing not allowed: forgot a "," ?[[ suppressing %d column name%s %s ... ]]a sparseMatrix should rarely be centered: will not be sparse anymoreall() is not yet implementedassigned dimensions [product %.0f] do not match object length [%.0f]assigned dimensions are NAassigned dimensions are negativeassigned dimensions are not of type "%s" or "%s"assigned dimensions do not have length %dassigned dimensions exceed %sattempt to coerce matrix with NA to %sattempt to coerce non-square matrix to %sattempt to recycle 'x' of length 0 to length 'n' (n > 0)c(,..) of different kinds, coercing all to 'rleDiff'cannot coerce from %s to %scannot coerce matrix of type "%s" to %scolumn indices must be <= ncol(.) which is %dcomplex %s not yet implementeddata is too longdeterminant of non-square matrix is undefineddiag(%s) has non-positive or non-finite entries; finite result is doubtfuldim [product %d] do not match the length of object [%d]dimensions cannot exceed %sdimensions cannot exceed 2^31-1dimensions of '%s' and '%s' are inconsistentdimnames [%d] mismatch in %selement type '%s' not recognizedelement type 'complex' not yet implementedexactly one of 'i', 'j', and 'p' must be missing from callfile is not a MatrixMarket filefirst element used of '%s' argumentfor symmetric band matrix, only specify upper or lower triangle hence, all k must have the same signhit a cycle (1) -- stop iterationshit a cycle (2) -- stop iterationsi1[1] == 0 ==> C-level verbosity will not happen!in show(); maybe adjust options(max.print=, width=)incorrect number of dimensionsindex larger than maximal %dindex must be numeric, logical or sparseVector for indexing sparseVectorsinefficient method used for "- e1"intermediate 'r' is of type %sinternal bug in "Compare" method (Cmp.Mat.atomic); please reportinternal bug in "Logic" method (Logic.Mat.atomic); please reportinternal bug: matrix 'i' in replTmat(): please reportinternal bug: missing 'i' in replTmat(): please reportinvalid %s="%s"invalid %s="%s" to '%s'invalid '%s' argumentinvalid '%s': not in %d:%dinvalid 'Class2'invalid 'col.names' string: %sinvalid 'data'invalid 'dims'invalid 'repr'; must be "C", "R", or "T"invalid 'repr'; must be "C", "T", or "R"invalid (to - from)/by in seq(.)invalid character indexinginvalid class "%s" in '%s'invalid class "%s" in '%s' methodinvalid class "%s" object in '%s' methodinvalid mode "%s"invalid nargs()= %dinvalid subassignment value class "%s"invalid subassignment value type "%s"invalid subscript class "%s"invalid subscript type "%s"invalid type "%s" in '%s'invalid type "%s" in '%s' methodis not an integer multiple of length(x)length must be non-negative numberlength of 'center' must equal the number of columns of 'x'length of 'scale' must equal the number of columns of 'x'length of 1st arg does not match dimension of 2ndlength of 2nd arg does not match dimension of firstlength(i)length(x) must not exceedlogic programming error in printSpMatrix2(), please reportlogical subscript too longlogical subscript too long (%d, should be %d)longer object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthm[ ] <- v: inefficiently treating single elementsmatrix can only be symmetric if square, but n != mmatrix exactly singular, J[i,]=0, i=%dmatrix is exactly singular, D[i,i]=0, i=%dmatrix is exactly singular, J[,j]=0, j=%dmatrix is not diagonal; consider Diagonal(x=diag(.))matrix is not squarematrix is not symmetricmatrix is not symmetric or triangularmatrix is not symmetric; consider forceSymmetric(.) or symmpart(.)matrix is not triangularmatrix is not triangular; consider triu(.) or tril(.)matrix is structurally rank deficient; using augmented matrix with additional %d row(s) of zerosmatrix must have exactly one entry in each row and columnmatrix must have exactly one entry in each row or columnmismatch between typeof(x)="%s" and kind="%s"; using kind="%s"missing subassignment valuemodel frame and formula mismatch in sparse.model.matrix()must either specify 'A' or the functions 'A.x' and 'At.x'nargs() = %d should never happen; please report.nargs() = %d. Extraneous illegal arguments inside '[ .. ]' ?need greater '%s' as pivoting occurrednegative values are not allowed in a matrix subscriptno 'dimnames[[.]]': cannot use character indexingnon-conformable argumentsnon-conformable matrix dimensions in %snon-list contrasts argument ignorednon-negativenon0.i() not yet implemented for class %snormnot a positive definite matrix (and positive semidefiniteness is not checked)not converged in %d iterationsnot enough new vecs -- stop iterationsnot yet implementednot yet implemented .. please reportnot-yet-implemented 'Matrix[<-' methodnothing to replace withnumber of items to replace is not a multiple of replacement lengthnumber of nonzero entries cannot exceed %snumber of rows are not compatible for %sonly square matrices can be used as graph incidence matricesonly zeros may be mixed with negative subscriptsp[length(p)]positiveprod() is not yet implementedqr2rankMatrix(.): QR with only %d out of %d finite diag(R) entriesrankMatrix(, method = '%s') coerces to dense matrix. Probably should rather use method = 'qr' !?rankMatrix(x, method='qr'): computing t(x) as nrow(x) < ncol(x)readMM(): column indices 'j' are not in 1:ncol[=%d]readMM(): expected %d entries but found only %dreadMM(): row indices 'i' are not in 1:nrow[=%d]recycled %s would have maximal index exceeding %sreplacement diagonal has incompatible type "%s"replacement diagonal has wrong lengthreplacement has length zerorepresentation '%s' not recognizedrow indices must be <= nrow(.) which is %dshould never happen ...subscript out of boundssubscripts exceeding %s replaced with NAsuch indexing must be by logical or 2-column numeric matrixsum() is not yet implementedsuppressing %d columnssuppressing %d columns and %d rowssuppressing %d rowssymmetric matrix must be squaresymmetry form '%s' is not yet implementedsymmetry form '%s' not recognizedsymmetry form 'hermitian' not yet implemented for readingsymmetry form 'skew-symmetric' not yet implemented for readingthe %d-th (sub)-diagonal (k = %d) is too short; filling with NA'sthe default value of argument '%s' of method '%s(<%s>, <%s>)' may change from %s to %s as soon as the next release of Matrix; set '%s' when programmingtoo many argumentstoo many replacement valuestriangular matrix must be squaretrimmed means are not defined for complex datatype '%s' not recognizedunexpected %s="%s" in '%s' methoduniDiag=TRUE, but not all diagonal entries are 1uniDiag=TRUE, not all entries in diagonal coded as 1use Diagonal() to construct diagonal (symmetric && triangular) sparse matricesusing "old code" part in Csparse subassignmentusing"old code" part in Csparse subassignment >>> please report to Matrix-authors@r-project.orgvariable '%s' is absent, its contrast will be ignoredvector too long in Matrix - vector operationwhen 'A' is specified, 'A.x' and 'At.x' are disregardedwrong sign in 'by' argumentx / 0 for an x with sign-change no longer representable as 'rleDiff'x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrixx[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE.x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced; NA |--> TRUE.you cannot mix negative and positive indicesProject-Id-Version: Matrix 1.7-0 PO-Revision-Date: 2024-03-12 11:27 Last-Translator: Automatically generated Language-Team: none Language: en MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); %1$s(%2$s) is undefined: ‘%2$s’ is not positive semidefinite%s length cannot exceed %s%s(<%s>) is not yet implemented%s(<%s>, <%s>) is not yet implemented; ask maintainer("%s") to implement the missing method%s="%s" invalid for %s@uplo="%s"‘%1$s’ is computationally singular, rcond(%1$s)=%2$g‘%1$s’ is not "%2$s", "%3$s", or "%2$s."‘%1$s’ is not "%2$s1", "%2$s1.", "%2$s2", "%2$s2.", "%3$s", "%3$s1", "%4$s", or "%4$s1"‘%1$s’ is not "%2$s1", "%2$s1.", "%2$s2", "%2$s2.", "%3$s", or "%4$s"‘%1$s’ is not "%2$s1", "%2$s1.", "%3$s", "%3$s.", "%3$s1", "%3$s1.", or "%4$s"‘%1$s’ is not "%2$s1", "%2$s1.", "%3$s", or "%4$s"‘%1$s’ is not formally symmetric; factorizing tcrossprod(%1$s)‘%s’ and ‘%s’ must be positive integers‘%s’ contains NA‘%s’ does not inherit from virtual class %s‘%s’ has elements exceeding ‘%s’‘%s’ has elements less than %d‘%s’ has length 0 but ‘%s’ does not‘%s’ has non-finite values‘%s’ has the wrong length‘%s’ is computationally singular, min(d)/max(d)=%g, d=abs(diag(U))‘%s’ is deprecated; setting %s="%s"‘%s’ is deprecated; using ‘%s’ instead‘%s’ is not "%1$s", "D%1$s", or "%1$s."‘%s’ is not %d or %d‘%s’ is not a non-negative number‘%s’ is not a permutation of seq_len(%s)‘%s’ is not a square numeric matrix‘%s’ is not of type "%s" or "%s"‘%s’ is not square‘%s’ method must use default %s="%s"‘%s’ via sparse -> dense coercion‘%s()’ is not yet implemented for representation ‘%s’‘%s()’ is not yet implemented for element type ‘%s’‘A’ must be a square matrix‘NA’ indices are not (yet?) supported for sparse Matrices‘by’ argument is much too small‘cl’ is not a character string‘cols’ has elements not in seq(0, length.out = n)‘cols’ must be numeric‘contrasts.arg’ argument must be named‘diagonals’ matrix must have %d columns (= length(k) )‘diagonals’ must have the same length (%d) as ‘k’‘dims’ must contain all (i,j) pairs‘file’ must be a character string or connection‘force’ must be (coercable to) TRUE or FALSE‘giveCsparse’ has been deprecated; setting ‘repr = "T"’ for you‘giveCsparse’ has been deprecated; will use ‘repr’ instead‘giveCsparse’ is deprecated; setting repr="T" for you‘giveCsparse’ is deprecated; using ‘repr’ instead‘i’ and ‘j’ must be‘i’ and ‘j’ must not contain NA‘kind’ must be one of "d", "l", "n"‘lst’ must be a list‘lwd’ must be NULL or non-negative numeric‘n’ must be a non-negative integer‘ncol’ is not a factor of length(x)‘ncol’ must be >= 0‘nearPD()’ did not converge in %d iterations‘nrow’ and ‘ncol’ must be the same when ‘symmetric’ is true‘nrow’ is not a factor of length(x)‘nrow’ must be >= 0‘nrow’, ‘ncol’, ‘byrow’ disregarded for [mM]atrix ‘data’‘p’ must be a nondecreasing vector c(0, ...)‘shape’ must be one of "g", "t", "s"‘uplo’ must be "U" or "L"‘x’ has unsupported class "%s"‘x’ has unsupported type "%s"‘x’ must have length nrow^2 when ‘symmetric’ is true‘x’ must inherit from "sparseVector".M.repl.i.2col(): ‘i’ has no integer column number; should never happen; please report.M.repl.i.2col(): drop ‘matrix’ case ... --> is not yet implemented[i] is not yet implemented --> is not yet implementedClass %s is not yet implementedCmp.Mat.atomic() should not be called for diagonalMatrixD[i,i] is NA, i=%dD[i,i] is negative, i=%dInternal bug: nargs()=%d; please reportInvalid assembled indicator: %sInvalid storage format: %sInvalid storage type: %sLogic.Mat.atomic() should not be called for diagonalMatrixMatrices must have same number of rows for arithmeticMatrix seems negative semi-definiteMust specify ‘nrow’ when ‘symmetric’ is trueNAs are not allowed in subscripted assignmentsNot a valid formatOnly numeric sparse matrices allowedRHS ‘value’ (class %s) matches ‘ANY’, but must match matrix class %s[ ] indexing not allowed: forgot a "," ?[[ suppressing %d column name%s %s ... ]]a sparseMatrix should rarely be centered: will not be sparse anymoreall() is not yet implementedassigned dimensions [product %.0f] do not match object length [%.0f]assigned dimensions are NAassigned dimensions are negativeassigned dimensions are not of type "%s" or "%s"assigned dimensions do not have length %dassigned dimensions exceed %sattempt to coerce matrix with NA to %sattempt to coerce non-square matrix to %sattempt to recycle ‘x’ of length 0 to length ‘n’ (n > 0)c(,..) of different kinds, coercing all to ‘rleDiff’cannot coerce from %s to %scannot coerce matrix of type "%s" to %scolumn indices must be <= ncol(.) which is %dcomplex %s not yet implementeddata is too longdeterminant of non-square matrix is undefineddiag(%s) has non-positive or non-finite entries; finite result is doubtfuldim [product %d] do not match the length of object [%d]dimensions cannot exceed %sdimensions cannot exceed 2^31-1dimensions of ‘%s’ and ‘%s’ are inconsistentdimnames [%d] mismatch in %selement type ‘%s’ not recognizedelement type ‘complex’ not yet implementedexactly one of ‘i’, ‘j’, and ‘p’ must be missing from callfile is not a MatrixMarket filefirst element used of ‘%s’ argumentfor symmetric band matrix, only specify upper or lower triangle hence, all k must have the same signhit a cycle (1) -- stop iterationshit a cycle (2) -- stop iterationsi1[1] == 0 ==> C-level verbosity will not happen!in show(); maybe adjust options(max.print=, width=)incorrect number of dimensionsindex larger than maximal %dindex must be numeric, logical or sparseVector for indexing sparseVectorsinefficient method used for "- e1"intermediate ‘r’ is of type %sinternal bug in "Compare" method (Cmp.Mat.atomic); please reportinternal bug in "Logic" method (Logic.Mat.atomic); please reportinternal bug: matrix ‘i’ in replTmat(): please reportinternal bug: missing ‘i’ in replTmat(): please reportinvalid %s="%s"invalid %s="%s" to ‘%s’invalid ‘%s’ argumentinvalid ‘%s’: not in %d:%dinvalid ‘Class2’invalid ‘col.names’ string: %sinvalid ‘data’invalid ‘dims’invalid ‘repr’; must be "C", "R", or "T"invalid ‘repr’; must be "C", "T", or "R"invalid (to - from)/by in seq(.)invalid character indexinginvalid class "%s" in ‘%s’invalid class "%s" in ‘%s’ methodinvalid class "%s" object in ‘%s’ methodinvalid mode "%s"invalid nargs()= %dinvalid subassignment value class "%s"invalid subassignment value type "%s"invalid subscript class "%s"invalid subscript type "%s"invalid type "%s" in ‘%s’invalid type "%s" in ‘%s’ methodis not an integer multiple of length(x)length must be non-negative numberlength of ‘center’ must equal the number of columns of ‘x’length of ‘scale’ must equal the number of columns of ‘x’length of 1st arg does not match dimension of 2ndlength of 2nd arg does not match dimension of firstlength(i)length(x) must not exceedlogic programming error in printSpMatrix2(), please reportlogical subscript too longlogical subscript too long (%d, should be %d)longer object length is not a multiple of shorter object lengthlonger object length is not a multiple of shorter object lengthm[ ] <- v: inefficiently treating single elementsmatrix can only be symmetric if square, but n != mmatrix exactly singular, J[i,]=0, i=%dmatrix is exactly singular, D[i,i]=0, i=%dmatrix is exactly singular, J[,j]=0, j=%dmatrix is not diagonal; consider Diagonal(x=diag(.))matrix is not squarematrix is not symmetricmatrix is not symmetric or triangularmatrix is not symmetric; consider forceSymmetric(.) or symmpart(.)matrix is not triangularmatrix is not triangular; consider triu(.) or tril(.)matrix is structurally rank deficient; using augmented matrix with additional %d row(s) of zerosmatrix must have exactly one entry in each row and columnmatrix must have exactly one entry in each row or columnmismatch between typeof(x)="%s" and kind="%s"; using kind="%s"missing subassignment valuemodel frame and formula mismatch in sparse.model.matrix()must either specify ‘A’ or the functions ‘A.x’ and ‘At.x’nargs() = %d should never happen; please report.nargs() = %d. Extraneous illegal arguments inside ‘[ .. ]’ ?need greater ‘%s’ as pivoting occurrednegative values are not allowed in a matrix subscriptno ‘dimnames[[.]]’: cannot use character indexingnon-conformable argumentsnon-conformable matrix dimensions in %snon-list contrasts argument ignorednon-negativenon0.i() not yet implemented for class %snormnot a positive definite matrix (and positive semidefiniteness is not checked)not converged in %d iterationsnot enough new vecs -- stop iterationsnot yet implementednot yet implemented .. please reportnot-yet-implemented ‘Matrix[<-’ methodnothing to replace withnumber of items to replace is not a multiple of replacement lengthnumber of nonzero entries cannot exceed %snumber of rows are not compatible for %sonly square matrices can be used as graph incidence matricesonly zeros may be mixed with negative subscriptsp[length(p)]positiveprod() is not yet implementedqr2rankMatrix(.): QR with only %d out of %d finite diag(R) entriesrankMatrix(, method = ‘%s’) coerces to dense matrix. Probably should rather use method = ‘qr’ !?rankMatrix(x, method=‘qr’): computing t(x) as nrow(x) < ncol(x)readMM(): column indices ‘j’ are not in 1:ncol[=%d]readMM(): expected %d entries but found only %dreadMM(): row indices ‘i’ are not in 1:nrow[=%d]recycled %s would have maximal index exceeding %sreplacement diagonal has incompatible type "%s"replacement diagonal has wrong lengthreplacement has length zerorepresentation ‘%s’ not recognizedrow indices must be <= nrow(.) which is %dshould never happen ...subscript out of boundssubscripts exceeding %s replaced with NAsuch indexing must be by logical or 2-column numeric matrixsum() is not yet implementedsuppressing %d columnssuppressing %d columns and %d rowssuppressing %d rowssymmetric matrix must be squaresymmetry form ‘%s’ is not yet implementedsymmetry form ‘%s’ not recognizedsymmetry form ‘hermitian’ not yet implemented for readingsymmetry form ‘skew-symmetric’ not yet implemented for readingthe %d-th (sub)-diagonal (k = %d) is too short; filling with NA'sthe default value of argument ‘%s’ of method ‘%s(<%s>, <%s>)’ may change from %s to %s as soon as the next release of Matrix; set ‘%s’ when programmingtoo many argumentstoo many replacement valuestriangular matrix must be squaretrimmed means are not defined for complex datatype ‘%s’ not recognizedunexpected %s="%s" in ‘%s’ methoduniDiag=TRUE, but not all diagonal entries are 1uniDiag=TRUE, not all entries in diagonal coded as 1use Diagonal() to construct diagonal (symmetric && triangular) sparse matricesusing "old code" part in Csparse subassignmentusing"old code" part in Csparse subassignment >>> please report to Matrix-authors@r-project.orgvariable ‘%s’ is absent, its contrast will be ignoredvector too long in Matrix - vector operationwhen ‘A’ is specified, ‘A.x’ and ‘At.x’ are disregardedwrong sign in ‘by’ argumentx / 0 for an x with sign-change no longer representable as ‘rleDiff’x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrixx[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE.x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced; NA |--> TRUE.you cannot mix negative and positive indicesMatrix/inst/scripts/0000755000175100001440000000000014576343415014214 5ustar hornikusersMatrix/inst/scripts/CXSparse.patch0000644000175100001440000002415514552026002016714 0ustar hornikusersdiff -ruN src/SuiteSparse/CXSparse/Makefile src/SuiteSparse-patched/CXSparse/Makefile --- src/SuiteSparse/CXSparse/Makefile 1969-12-31 19:00:00 +++ src/SuiteSparse-patched/CXSparse/Makefile 2024-01-12 11:54:13 @@ -0,0 +1,71 @@ +sources = \ + Source/cs_add.c Source/cs_dl_add.c Source/cs_ci_add.c Source/cs_cl_add.c \ + Source/cs_amd.c Source/cs_dl_amd.c Source/cs_ci_amd.c Source/cs_cl_amd.c \ + Source/cs_chol.c Source/cs_dl_chol.c Source/cs_ci_chol.c Source/cs_cl_chol.c \ + Source/cs_cholsol.c Source/cs_dl_cholsol.c Source/cs_ci_cholsol.c Source/cs_cl_cholsol.c \ + Source/cs_compress.c Source/cs_dl_compress.c Source/cs_ci_compress.c Source/cs_cl_compress.c \ + Source/cs_convert.c \ + Source/cs_counts.c Source/cs_dl_counts.c Source/cs_ci_counts.c Source/cs_cl_counts.c \ + Source/cs_cumsum.c Source/cs_dl_cumsum.c Source/cs_ci_cumsum.c Source/cs_cl_cumsum.c \ + Source/cs_dfs.c Source/cs_dl_dfs.c Source/cs_ci_dfs.c Source/cs_cl_dfs.c \ + Source/cs_dmperm.c Source/cs_dl_dmperm.c Source/cs_ci_dmperm.c Source/cs_cl_dmperm.c \ + Source/cs_droptol.c Source/cs_dl_droptol.c Source/cs_ci_droptol.c Source/cs_cl_droptol.c \ + Source/cs_dropzeros.c Source/cs_dl_dropzeros.c Source/cs_ci_dropzeros.c Source/cs_cl_dropzeros.c \ + Source/cs_dupl.c Source/cs_dl_dupl.c Source/cs_ci_dupl.c Source/cs_cl_dupl.c \ + Source/cs_entry.c Source/cs_dl_entry.c Source/cs_ci_entry.c Source/cs_cl_entry.c \ + Source/cs_ereach.c Source/cs_dl_ereach.c Source/cs_ci_ereach.c Source/cs_cl_ereach.c \ + Source/cs_etree.c Source/cs_dl_etree.c Source/cs_ci_etree.c Source/cs_cl_etree.c \ + Source/cs_fkeep.c Source/cs_dl_fkeep.c Source/cs_ci_fkeep.c Source/cs_cl_fkeep.c \ + Source/cs_gaxpy.c Source/cs_dl_gaxpy.c Source/cs_ci_gaxpy.c Source/cs_cl_gaxpy.c \ + Source/cs_happly.c Source/cs_dl_happly.c Source/cs_ci_happly.c Source/cs_cl_happly.c \ + Source/cs_house.c Source/cs_dl_house.c Source/cs_ci_house.c Source/cs_cl_house.c \ + Source/cs_ipvec.c Source/cs_dl_ipvec.c Source/cs_ci_ipvec.c Source/cs_cl_ipvec.c \ + Source/cs_leaf.c Source/cs_dl_leaf.c Source/cs_ci_leaf.c Source/cs_cl_leaf.c \ + Source/cs_load.c Source/cs_dl_load.c Source/cs_ci_load.c Source/cs_cl_load.c \ + Source/cs_lsolve.c Source/cs_dl_lsolve.c Source/cs_ci_lsolve.c Source/cs_cl_lsolve.c \ + Source/cs_ltsolve.c Source/cs_dl_ltsolve.c Source/cs_ci_ltsolve.c Source/cs_cl_ltsolve.c \ + Source/cs_lu.c Source/cs_dl_lu.c Source/cs_ci_lu.c Source/cs_cl_lu.c \ + Source/cs_lusol.c Source/cs_dl_lusol.c Source/cs_ci_lusol.c Source/cs_cl_lusol.c \ + Source/cs_malloc.c Source/cs_dl_malloc.c Source/cs_ci_malloc.c Source/cs_cl_malloc.c \ + Source/cs_maxtrans.c Source/cs_dl_maxtrans.c Source/cs_ci_maxtrans.c Source/cs_cl_maxtrans.c \ + Source/cs_multiply.c Source/cs_dl_multiply.c Source/cs_ci_multiply.c Source/cs_cl_multiply.c \ + Source/cs_norm.c Source/cs_dl_norm.c Source/cs_ci_norm.c Source/cs_cl_norm.c \ + Source/cs_permute.c Source/cs_dl_permute.c Source/cs_ci_permute.c Source/cs_cl_permute.c \ + Source/cs_pinv.c Source/cs_dl_pinv.c Source/cs_ci_pinv.c Source/cs_cl_pinv.c \ + Source/cs_post.c Source/cs_dl_post.c Source/cs_ci_post.c Source/cs_cl_post.c \ + Source/cs_print.c Source/cs_dl_print.c Source/cs_ci_print.c Source/cs_cl_print.c \ + Source/cs_pvec.c Source/cs_dl_pvec.c Source/cs_ci_pvec.c Source/cs_cl_pvec.c \ + Source/cs_qr.c Source/cs_dl_qr.c Source/cs_ci_qr.c Source/cs_cl_qr.c \ + Source/cs_qrsol.c Source/cs_dl_qrsol.c Source/cs_ci_qrsol.c Source/cs_cl_qrsol.c \ + Source/cs_randperm.c Source/cs_dl_randperm.c Source/cs_ci_randperm.c Source/cs_cl_randperm.c \ + Source/cs_reach.c Source/cs_dl_reach.c Source/cs_ci_reach.c Source/cs_cl_reach.c \ + Source/cs_scatter.c Source/cs_dl_scatter.c Source/cs_ci_scatter.c Source/cs_cl_scatter.c \ + Source/cs_scc.c Source/cs_dl_scc.c Source/cs_ci_scc.c Source/cs_cl_scc.c \ + Source/cs_schol.c Source/cs_dl_schol.c Source/cs_ci_schol.c Source/cs_cl_schol.c \ + Source/cs_spsolve.c Source/cs_dl_spsolve.c Source/cs_ci_spsolve.c Source/cs_cl_spsolve.c \ + Source/cs_sqr.c Source/cs_dl_sqr.c Source/cs_ci_sqr.c Source/cs_cl_sqr.c \ + Source/cs_symperm.c Source/cs_dl_symperm.c Source/cs_ci_symperm.c Source/cs_cl_symperm.c \ + Source/cs_tdfs.c Source/cs_dl_tdfs.c Source/cs_ci_tdfs.c Source/cs_cl_tdfs.c \ + Source/cs_transpose.c Source/cs_dl_transpose.c Source/cs_ci_transpose.c Source/cs_cl_transpose.c \ + Source/cs_updown.c Source/cs_dl_updown.c Source/cs_ci_updown.c Source/cs_cl_updown.c \ + Source/cs_usolve.c Source/cs_dl_usolve.c Source/cs_ci_usolve.c Source/cs_cl_usolve.c \ + Source/cs_util.c Source/cs_dl_util.c Source/cs_ci_util.c Source/cs_cl_util.c \ + Source/cs_utsolve.c Source/cs_dl_utsolve.c Source/cs_ci_utsolve.c Source/cs_cl_utsolve.c \ + Source/cxsparse_version.c +objects = $(sources:.c=.o) +archive = CXSparse.a + +PKG_CPPFLAGS = -I./Include -I../SuiteSparse_config + +all : $(archive) + +$(archive) : $(objects) + rm -f $@ + $(AR) -cr $@ $(objects) + $(RANLIB) $@ + +.c.o : + $(CC) $(PKG_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) -c $< -o $*.o + +clean : + @rm -f $(objects) $(archive) diff -ruN src/SuiteSparse/CXSparse/Source/cs_multiply.c src/SuiteSparse-patched/CXSparse/Source/cs_multiply.c --- src/SuiteSparse/CXSparse/Source/cs_multiply.c 2024-01-10 19:08:51 +++ src/SuiteSparse-patched/CXSparse/Source/cs_multiply.c 2024-01-12 11:54:13 @@ -20,7 +20,8 @@ Cp = C->p ; for (j = 0 ; j < n ; j++) { - if (nz + m > C->nzmax && !cs_sprealloc (C, 2*(C->nzmax)+m)) + if (C->nzmax > (CS_INT_MAX - m) / 2 || /* 2*(C->nzmax)+m overflows */ + (nz + m > C->nzmax && !cs_sprealloc (C, 2*(C->nzmax)+m))) { return (cs_done (C, w, x, 0)) ; /* out of memory */ } diff -ruN src/SuiteSparse/CXSparse/Source/cs_print.c src/SuiteSparse-patched/CXSparse/Source/cs_print.c --- src/SuiteSparse/CXSparse/Source/cs_print.c 2024-01-10 19:08:51 +++ src/SuiteSparse-patched/CXSparse/Source/cs_print.c 2024-01-12 11:54:13 @@ -2,52 +2,54 @@ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" +#include + /* print a sparse matrix; use %g for integers to avoid differences with CS_INT */ CS_INT cs_print (const cs *A, CS_INT brief) { CS_INT p, j, m, n, nzmax, nz, *Ap, *Ai ; CS_ENTRY *Ax ; - if (!A) { printf ("(null)\n") ; return (0) ; } + if (!A) { Rprintf ("(null)\n") ; return (0) ; } m = A->m ; n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; nzmax = A->nzmax ; nz = A->nz ; - printf ("CXSparse Version %d.%d.%d, %s. %s\n", CS_VER, CS_SUBVER, + Rprintf ("CXSparse Version %d.%d.%d, %s. %s\n", CS_VER, CS_SUBVER, CS_SUBSUB, CS_DATE, CS_COPYRIGHT) ; if (nz < 0) { - printf ("%g-by-%g, nzmax: %g nnz: %g, 1-norm: %g\n", (double) m, + Rprintf ("%g-by-%g, nzmax: %g nnz: %g, 1-norm: %g\n", (double) m, (double) n, (double) nzmax, (double) (Ap [n]), cs_norm (A)) ; for (j = 0 ; j < n ; j++) { - printf (" col %g : locations %g to %g\n", (double) j, + Rprintf (" col %g : locations %g to %g\n", (double) j, (double) (Ap [j]), (double) (Ap [j+1]-1)) ; for (p = Ap [j] ; p < Ap [j+1] ; p++) { - printf (" %g : ", (double) (Ai [p])) ; + Rprintf (" %g : ", (double) (Ai [p])) ; #ifdef CS_COMPLEX - printf ("(%g, %g)\n", + Rprintf ("(%g, %g)\n", Ax ? CS_REAL (Ax [p]) : 1, Ax ? CS_IMAG (Ax [p]) : 0) ; #else - printf ("%g\n", Ax ? Ax [p] : 1) ; + Rprintf ("%g\n", Ax ? Ax [p] : 1) ; #endif - if (brief && p > 20) { printf (" ...\n") ; return (1) ; } + if (brief && p > 20) { Rprintf (" ...\n") ; return (1) ; } } } } else { - printf ("triplet: %g-by-%g, nzmax: %g nnz: %g\n", (double) m, + Rprintf ("triplet: %g-by-%g, nzmax: %g nnz: %g\n", (double) m, (double) n, (double) nzmax, (double) nz) ; for (p = 0 ; p < nz ; p++) { - printf (" %g %g : ", (double) (Ai [p]), (double) (Ap [p])) ; + Rprintf (" %g %g : ", (double) (Ai [p]), (double) (Ap [p])) ; #ifdef CS_COMPLEX - printf ("(%g, %g)\n", + Rprintf ("(%g, %g)\n", Ax ? CS_REAL (Ax [p]) : 1, Ax ? CS_IMAG (Ax [p]) : 0) ; #else - printf ("%g\n", Ax ? Ax [p] : 1) ; + Rprintf ("%g\n", Ax ? Ax [p] : 1) ; #endif - if (brief && p > 20) { printf (" ...\n") ; return (1) ; } + if (brief && p > 20) { Rprintf (" ...\n") ; return (1) ; } } } return (1) ; diff -ruN src/SuiteSparse/CXSparse/Source/cs_randperm.c src/SuiteSparse-patched/CXSparse/Source/cs_randperm.c --- src/SuiteSparse/CXSparse/Source/cs_randperm.c 2024-01-10 19:08:51 +++ src/SuiteSparse-patched/CXSparse/Source/cs_randperm.c 2024-01-12 11:54:13 @@ -2,6 +2,8 @@ // CXSparse, Copyright (c) 2006-2022, Timothy A. Davis. All Rights Reserved. // SPDX-License-Identifier: LGPL-2.1+ #include "cs.h" +#include + /* return a random permutation vector, the identity perm, or p = n-1:-1:0. * seed = -1 means p = n-1:-1:0. seed = 0 means p = identity. otherwise * p = random permutation. */ @@ -13,6 +15,7 @@ if (!p) return (NULL) ; /* out of memory */ for (k = 0 ; k < n ; k++) p [k] = n-k-1 ; if (seed == -1) return (p) ; /* return reverse permutation */ + GetRNGstate(); srand (seed) ; /* get new random number seed */ for (k = 0 ; k < n ; k++) { @@ -21,5 +24,6 @@ p [j] = p [k] ; p [k] = t ; } + PutRNGstate(); return (p) ; } Matrix/inst/scripts/CCOLAMD.patch0000644000175100001440000000114114552026002016254 0ustar hornikusersdiff -ruN src/SuiteSparse/CCOLAMD/Makefile src/SuiteSparse-patched/CCOLAMD/Makefile --- src/SuiteSparse/CCOLAMD/Makefile 1969-12-31 19:00:00 +++ src/SuiteSparse-patched/CCOLAMD/Makefile 2024-01-12 11:54:13 @@ -0,0 +1,18 @@ +sources = Source/ccolamd.c Source/ccolamd_l.c Source/ccolamd_version.c +objects = $(sources:.c=.o) +archive = CCOLAMD.a + +PKG_CPPFLAGS = -I./Include -I../SuiteSparse_config + +all : $(archive) + +$(archive) : $(objects) + rm -f $@ + $(AR) -cr $@ $(objects) + $(RANLIB) $@ + +.c.o : + $(CC) $(PKG_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) -c $< -o $*.o + +clean : + @rm -f $(objects) $(archive) Matrix/inst/scripts/api.patch0000644000175100001440000004677114552026002016005 0ustar hornikusers--- inst/include/Matrix/cholmod.h 2024-01-17 13:47:18 +++ inst/include/Matrix/cholmod.h-patched.h 2024-01-17 02:18:32 @@ -46,8 +46,8 @@ // CHOLMOD's Partition Module. // ----------------------------------------------------------------------------- -#ifndef CHOLMOD_H -#define CHOLMOD_H +#ifndef R_MATRIX_CHOLMOD_H +#define R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // CHOLMOD conventions @@ -259,6 +259,8 @@ extern "C" { #endif +#ifndef R_MATRIX_CHOLMOD_H + int cholmod_version // returns CHOLMOD_VERSION, defined above ( // if version is not NULL, then cholmod_version returns its contents as: @@ -268,6 +270,8 @@ int version [3] ) ; int cholmod_l_version (int version [3]) ; + +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ #ifdef __cplusplus } @@ -287,6 +291,8 @@ // particular, you must use -DNLARGEFILE for MATLAB 6.5 or earlier (which does // not have the io64.h include file). +#ifndef R_MATRIX_CHOLMOD_H + // skip all of this if NLARGEFILE is defined at the compiler command line #ifndef NLARGEFILE #if defined(MATLAB_MEX_FILE) || defined(MATHWORKS) @@ -301,10 +307,14 @@ #endif #endif +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ + //------------------------------------------------------------------------------ // SuiteSparse_config: definitions for all SuiteSparse packages //------------------------------------------------------------------------------ +#ifndef R_MATRIX_CHOLMOD_H + #include "SuiteSparse_config.h" #define CHOLMOD__VERSION SUITESPARSE__VERCODE(5,1,1) @@ -313,6 +323,13 @@ #error "CHOLMOD 5.1.1 requires SuiteSparse_config 7.5.0 or later" #endif +#else + +#include +#include + +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ + //------------------------------------------------------------------------------ // CHOLMOD configuration //------------------------------------------------------------------------------ @@ -353,6 +370,8 @@ // existence of this #define here, and its use in these 3 modules, does not // affect the license itself; see CHOLMOD/Doc/License.txt for your actual // license. + +#ifndef R_MATRIX_CHOLMOD_H #ifdef NGPL #undef NMATRIXOPS @@ -363,6 +382,8 @@ #define NSUPERNODAL #endif +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ + //============================================================================== // CHOLMOD:Utility Module //============================================================================== @@ -923,6 +944,8 @@ #define CHOLMOD_GPU_POTRF_TIME cholmod_gpu_potrf_time #define CHOLMOD_ASSEMBLE_TIME cholmod_assemble_time #define CHOLMOD_ASSEMBLE_TIME2 cholmod_assemble_time2 + +#ifndef R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // cholmod_start: first call to CHOLMOD @@ -1065,6 +1088,8 @@ ) ; int cholmod_l_divcomplex (double, double, double, double, double *, double *) ; +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ + //============================================================================== // cholmod_sparse: a sparse matrix in compressed-column (CSC) form //============================================================================== @@ -1109,6 +1134,8 @@ } cholmod_sparse ; +#ifndef R_MATRIX_CHOLMOD_H + //------------------------------------------------------------------------------ // cholmod_allocate_sparse: allocate a sparse matrix //------------------------------------------------------------------------------ @@ -1436,6 +1463,8 @@ ) ; int cholmod_l_sparse_xtype (int, cholmod_sparse *, cholmod_common *) ; +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ + //============================================================================== // cholmod_factor: symbolic or numeric factorization (simplicial or supernodal) //============================================================================== @@ -1556,6 +1585,8 @@ } cholmod_factor ; +#ifndef R_MATRIX_CHOLMOD_H + //------------------------------------------------------------------------------ // cholmod_allocate_factor: allocate a numerical factor //------------------------------------------------------------------------------ @@ -1698,6 +1729,8 @@ cholmod_common *Common ) ; int cholmod_l_factor_xtype (int, cholmod_factor *, cholmod_common *) ; + +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ //============================================================================== // cholmod_dense: a dense matrix, held by column @@ -1716,6 +1749,8 @@ } cholmod_dense ; +#ifndef R_MATRIX_CHOLMOD_H + //------------------------------------------------------------------------------ // cholmod_allocate_dense: allocate a dense matrix (contents not initialized) //------------------------------------------------------------------------------ @@ -1893,6 +1928,8 @@ ) ; int cholmod_l_dense_xtype (int, cholmod_dense *, cholmod_common *) ; +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ + //============================================================================= // cholmod_triplet: a sparse matrix in triplet form //============================================================================= @@ -1934,6 +1971,8 @@ int dtype ; // x and z are double or single } cholmod_triplet ; + +#ifndef R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // cholmod_allocate_triplet: allocate a triplet matrix @@ -2033,6 +2072,8 @@ ) ; int cholmod_l_triplet_xtype (int, cholmod_triplet *, cholmod_common *) ; +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ + //------------------------------------------------------------------------------ // memory allocation: malloc/calloc/realloc/free //------------------------------------------------------------------------------ @@ -2046,6 +2087,8 @@ // statistics. cholmod_realloc does not return NULL if it fails; instead, it // returns the pointer to the unmodified block of memory. +#ifndef R_MATRIX_CHOLMOD_H + void *cholmod_malloc // return pointer to newly allocated memory ( // input: @@ -2108,6 +2151,8 @@ int cholmod_l_realloc_multiple (size_t, int, int, void **, void **, void **, void **, size_t *, cholmod_common *) ; +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ + //------------------------------------------------------------------------------ // numerical comparisons //------------------------------------------------------------------------------ @@ -2115,6 +2160,8 @@ // These macros were different on Windows for older versions of CHOLMOD. // They are no longer needed but are kept for backward compatibility. +#ifndef R_MATRIX_CHOLMOD_H + #define CHOLMOD_IS_NAN(x) isnan (x) #define CHOLMOD_IS_ZERO(x) ((x) == 0.) #define CHOLMOD_IS_NONZERO(x) ((x) != 0.) @@ -2122,14 +2169,14 @@ #define CHOLMOD_IS_GT_ZERO(x) ((x) > 0.) #define CHOLMOD_IS_LE_ZERO(x) ((x) <= 0.) +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ + #endif //============================================================================== // CHOLMOD:Check Module //============================================================================== -#ifndef NCHECK - // Routines that check and print the 5 basic data types in CHOLMOD, and 3 kinds // of integer vectors (subset, perm, and parent), and read in matrices from a // file: @@ -2180,6 +2227,8 @@ // See cholmod_read.c for a description of the file formats supported by the // cholmod_read_* routines. +#ifndef R_MATRIX_CHOLMOD_H + //------------------------------------------------------------------------------ // cholmod_check_common: check the Common object //------------------------------------------------------------------------------ @@ -2518,6 +2567,8 @@ // cholmod_write_sparse: write a sparse matrix to a file //------------------------------------------------------------------------------ +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ + // return values of cholmod_symmetry and cholmod_write: #define CHOLMOD_MM_RECTANGULAR 1 #define CHOLMOD_MM_UNSYMMETRIC 2 @@ -2527,6 +2578,8 @@ #define CHOLMOD_MM_SYMMETRIC_POSDIAG 6 #define CHOLMOD_MM_HERMITIAN_POSDIAG 7 +#ifndef R_MATRIX_CHOLMOD_H + int cholmod_write_sparse // see above, or -1 on error ( // input: @@ -2554,14 +2607,12 @@ int cholmod_l_write_dense (FILE *, cholmod_dense *, const char *, cholmod_common *) ; -#endif +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ //============================================================================== // CHOLMOD:Cholesky Module //============================================================================== -#ifndef NCHOLESKY - // Sparse Cholesky routines: analysis, factorization, and solve. // // The primary routines are all that a user requires to order, analyze, and @@ -2602,6 +2653,8 @@ // Optionally uses the Supernodal and Partition modules. // Required by the Partition module. +#ifndef R_MATRIX_CHOLMOD_H + //------------------------------------------------------------------------------ // cholmod_analyze: order and analyze (simplicial or supernodal) //------------------------------------------------------------------------------ @@ -2706,6 +2759,8 @@ // factorization from cholmod_factorize (or as modified by any other CHOLMOD // routine). D is identity for LL' factorizations. +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ + #define CHOLMOD_A 0 /* solve Ax=b */ #define CHOLMOD_LDLt 1 /* solve LDL'x=b */ #define CHOLMOD_LD 2 /* solve LDx=b */ @@ -2715,6 +2770,8 @@ #define CHOLMOD_D 6 /* solve Dx=b */ #define CHOLMOD_P 7 /* permute x=Px */ #define CHOLMOD_Pt 8 /* permute x=P'x */ + +#ifndef R_MATRIX_CHOLMOD_H cholmod_dense *cholmod_solve // returns the solution X ( @@ -3076,14 +3133,12 @@ int64_t cholmod_l_postorder (int64_t *, size_t, int64_t *, int64_t *, cholmod_common *) ; -#endif +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ //============================================================================== // CHOLMOD:MatrixOps Module //============================================================================== -#ifndef NMATRIXOPS - // Basic operations on sparse and dense matrices. // // cholmod_drop A = entries in A with abs. value >= tol @@ -3102,6 +3157,8 @@ // // Requires the Utility module. Not required by any other CHOLMOD module. +#ifndef R_MATRIX_CHOLMOD_H + //------------------------------------------------------------------------------ // cholmod_drop: drop entries with small absolute value //------------------------------------------------------------------------------ @@ -3167,12 +3224,16 @@ // cholmod_scale: A = diag(s)*A, A*diag(s), s*A or diag(s)*A*diag(s) //------------------------------------------------------------------------------ +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ + // scaling modes, selected by the scale input parameter: #define CHOLMOD_SCALAR 0 /* A = s*A */ #define CHOLMOD_ROW 1 /* A = diag(s)*A */ #define CHOLMOD_COL 2 /* A = A*diag(s) */ #define CHOLMOD_SYM 3 /* A = diag(s)*A*diag(s) */ +#ifndef R_MATRIX_CHOLMOD_H + int cholmod_scale ( // input: @@ -3308,13 +3369,11 @@ int cholmod_l_symmetry (cholmod_sparse *, int, int64_t *, int64_t *, int64_t *, int64_t *, cholmod_common *) ; -#endif +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ //============================================================================== // CHOLMOD:Modify Module //============================================================================== - -#ifndef NMODIFY //------------------------------------------------------------------------------ // CHOLMOD:Modify Module. Copyright (C) 2005-2023, Timothy A. Davis and William @@ -3349,6 +3408,8 @@ // // Requires the Utility module. Not required by any other CHOLMOD module. +#ifndef R_MATRIX_CHOLMOD_H + //------------------------------------------------------------------------------ // cholmod_updown: multiple rank update/downdate //------------------------------------------------------------------------------ @@ -3600,7 +3661,7 @@ int cholmod_l_rowdel_mark (size_t, cholmod_sparse *, double [2], int64_t *, cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; -#endif +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ //============================================================================== // CHOLMOD:Partition Module (CAMD, CCOLAMD, and CSYMAMD) @@ -3632,7 +3693,7 @@ // Requires the Utility and Cholesky modules, and three packages: METIS, CAMD, // and CCOLAMD. Optionally used by the Cholesky module. -#ifndef NCAMD +#ifndef R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // cholmod_ccolamd @@ -3694,7 +3755,7 @@ int cholmod_l_camd (cholmod_sparse *, int64_t *, size_t, int64_t *, int64_t *, cholmod_common *) ; -#endif +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ //------------------------------------------------------------------------------ // CHOLMOD:Partition Module (graph partition methods) @@ -3703,7 +3764,7 @@ // These routines still exist if CHOLMOD is compiled with -DNPARTITION, // but they return Common->status = CHOLMOD_NOT_INSTALLED in that case. -#if 1 +#ifndef R_MATRIX_CHOLMOD_H //------------------------------------------------------------------------------ // cholmod_nested_dissection @@ -3820,13 +3881,11 @@ int64_t cholmod_l_collapse_septree (size_t, size_t, double, size_t, int64_t *, int64_t *, cholmod_common *) ; -#endif +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ //============================================================================== // CHOLMOD:Supernodal Module //============================================================================== - -#ifndef NSUPERNODAL // Supernodal analysis, factorization, and solve. The simplest way to use // these routines is via the Cholesky module. It does not provide any @@ -3860,6 +3919,8 @@ // Requires the Utility module, and two external packages: LAPACK and the BLAS. // Optionally used by the Cholesky module. +#ifndef R_MATRIX_CHOLMOD_H + //------------------------------------------------------------------------------ // cholmod_super_symbolic //------------------------------------------------------------------------------ @@ -3888,10 +3949,14 @@ // Analyze for supernodal Cholesky or multifrontal QR +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ + #define CHOLMOD_ANALYZE_FOR_SPQR 0 #define CHOLMOD_ANALYZE_FOR_CHOLESKY 1 #define CHOLMOD_ANALYZE_FOR_SPQRGPU 2 +#ifndef R_MATRIX_CHOLMOD_H + int cholmod_super_symbolic2 ( // input: @@ -3972,7 +4037,7 @@ int cholmod_l_super_ltsolve (cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; -#endif +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ #ifdef __cplusplus } @@ -3997,11 +4062,15 @@ } descendantScore ; +#ifndef R_MATRIX_CHOLMOD_H + int cholmod_score_comp (struct cholmod_descendant_score_t *i, struct cholmod_descendant_score_t *j) ; int cholmod_l_score_comp (struct cholmod_descendant_score_t *i, struct cholmod_descendant_score_t *j) ; +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ + #ifdef __cplusplus } #endif @@ -4048,6 +4117,8 @@ void *d_RelativeMap ; } cholmod_gpu_pointers ; + +#ifndef R_MATRIX_CHOLMOD_H int cholmod_gpu_memorysize // GPU memory size available, 1 if no GPU ( @@ -4078,11 +4149,124 @@ int cholmod_gpu_allocate ( cholmod_common *Common ) ; int cholmod_l_gpu_allocate ( cholmod_common *Common ) ; +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ + #ifdef __cplusplus } #endif #endif +/* <<<< Matrix <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ + +/* We declare a minimal subset of the above as "API" : */ + +#ifndef R_MATRIX_CHOLMOD +# define R_MATRIX_CHOLMOD(_NAME_) M_cholmod_ ## _NAME_ #endif +#ifndef R_MATRIX_INLINE +# define R_MATRIX_INLINE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef cholmod_common * CHM_CM; +typedef cholmod_factor * CHM_FR; +typedef cholmod_sparse * CHM_SP; +typedef cholmod_triplet * CHM_TR; +typedef cholmod_dense * CHM_DN; + +R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(aat)( + CHM_SP, int *, size_t, int, CHM_CM); +R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(add)( + CHM_SP, CHM_SP, double[2], double[2], int, int, CHM_CM); +R_MATRIX_INLINE CHM_DN R_MATRIX_CHOLMOD(allocate_dense)( + size_t, size_t, size_t, int, CHM_CM); +R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(allocate_sparse)( + size_t, size_t, size_t, int, int, int, int, CHM_CM); +R_MATRIX_INLINE CHM_TR R_MATRIX_CHOLMOD(allocate_triplet)( + size_t, size_t, size_t, int, int, CHM_CM); +R_MATRIX_INLINE CHM_FR R_MATRIX_CHOLMOD(analyze)( + CHM_SP, CHM_CM); +R_MATRIX_INLINE CHM_FR R_MATRIX_CHOLMOD(analyze_p)( + CHM_SP, int *, int *, size_t, CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(band_inplace)( + int, int, int, CHM_SP, CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(change_factor)( + int, int, int, int, int, CHM_FR, CHM_CM); +R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(copy)( + CHM_SP, int, int, CHM_CM); +R_MATRIX_INLINE CHM_DN R_MATRIX_CHOLMOD(copy_dense)( + CHM_DN, CHM_CM); +R_MATRIX_INLINE CHM_FR R_MATRIX_CHOLMOD(copy_factor)( + CHM_FR, CHM_CM); +R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(copy_sparse)( + CHM_SP, CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(defaults)( + CHM_CM); +R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(dense_to_sparse)( + CHM_DN, int, CHM_CM); +R_MATRIX_INLINE void R_MATRIX_CHOLMOD(error_handler)( + int, const char *, int, const char *); +R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(factor_to_sparse )( + CHM_FR, CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(factorize)( + CHM_SP, CHM_FR, CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(factorize_p)( + CHM_SP, double[2], int *, size_t, CHM_FR, CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(finish)( + CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(free_dense)( + CHM_DN *, CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(free_factor)( + CHM_FR *, CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(free_sparse)( + CHM_SP *, CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(free_triplet)( + CHM_TR *, CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(nnz)( + CHM_SP, CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(scale)( + CHM_DN, int, CHM_SP, CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(sdmult)( + CHM_SP, int, double[2], double[2], CHM_DN, CHM_DN, CHM_CM); +R_MATRIX_INLINE CHM_DN R_MATRIX_CHOLMOD(solve)( + int, CHM_FR, CHM_DN, CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(solve2)( + int, CHM_FR, CHM_DN, CHM_DN *, CHM_DN *, CHM_DN *, CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(sort)( + CHM_SP, CHM_CM); +R_MATRIX_INLINE CHM_DN R_MATRIX_CHOLMOD(sparse_to_dense)( + CHM_SP, CHM_CM); +R_MATRIX_INLINE CHM_TR R_MATRIX_CHOLMOD(sparse_to_triplet)( + CHM_SP, CHM_CM); +R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(speye)( + size_t, size_t, int, CHM_CM); +R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(spsolve)( + int, CHM_FR, CHM_SP, CHM_CM); +R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(ssmult)( + CHM_SP, CHM_SP, int, int, int, CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(start)( + CHM_CM); +R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(submatrix)( + CHM_SP, int *, int, int *, int, int, int, CHM_CM); +R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(transpose)( + CHM_SP, int, CHM_CM); +R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(triplet_to_sparse)( + CHM_TR, int, CHM_CM); +R_MATRIX_INLINE int R_MATRIX_CHOLMOD(updown)( + int, CHM_SP, CHM_FR, CHM_CM); +R_MATRIX_INLINE CHM_SP R_MATRIX_CHOLMOD(vertcat)( + CHM_SP, CHM_SP, int, CHM_CM); + +#ifdef __cplusplus +} +#endif + +/* >>>> Matrix >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */ + +#endif /* !defined(R_MATRIX_CHOLMOD_H) */ + Matrix/inst/scripts/CAMD.patch0000644000175100001440000000214014552026002015716 0ustar hornikusersdiff -ruN src/SuiteSparse/CAMD/Makefile src/SuiteSparse-patched/CAMD/Makefile --- src/SuiteSparse/CAMD/Makefile 1969-12-31 19:00:00 +++ src/SuiteSparse-patched/CAMD/Makefile 2024-01-12 11:54:13 @@ -0,0 +1,30 @@ +sources = \ + Source/camd_1.c Source/camd_l1.c \ + Source/camd_2.c Source/camd_l2.c \ + Source/camd_aat.c Source/camd_l_aat.c \ + Source/camd_control.c Source/camd_l_control.c \ + Source/camd_defaults.c Source/camd_l_defaults.c \ + Source/camd_dump.c Source/camd_l_dump.c \ + Source/camd_info.c Source/camd_l_info.c \ + Source/camd_order.c Source/camd_l_order.c \ + Source/camd_postorder.c Source/camd_l_postorder.c \ + Source/camd_preprocess.c Source/camd_l_preprocess.c \ + Source/camd_valid.c Source/camd_l_valid.c \ + Source/camd_version.c +objects = $(sources:.c=.o) +archive = CAMD.a + +PKG_CPPFLAGS = -I./Include -I../SuiteSparse_config + +all : $(archive) + +$(archive) : $(objects) + rm -f $@ + $(AR) -cr $@ $(objects) + $(RANLIB) $@ + +.c.o : + $(CC) $(PKG_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) -c $< -o $*.o + +clean : + @rm -f $(objects) $(archive) Matrix/inst/scripts/rules.mk0000644000175100001440000000646114575137654015713 0ustar hornikusers## Generated by ./rules.sh : Csparse.o: Csparse.c Mdefines.h version.h \ Msymbols.h utils.h cs-etc.h \ SuiteSparse/CXSparse/Include/cs.h \ SuiteSparse/SuiteSparse_config/SuiteSparse_config.h cholmod-etc.h \ SuiteSparse/CHOLMOD/Include/cholmod.h Csparse.h attrib.o: attrib.c Mdefines.h version.h \ Msymbols.h utils.h attrib.h bind.o: bind.c Mdefines.h version.h \ Msymbols.h utils.h coerce.h bind.h cholmod-common.o: cholmod-common.c Mdefines.h version.h \ Msymbols.h utils.h cholmod-common.h \ cholmod-etc.h SuiteSparse/SuiteSparse_config/SuiteSparse_config.h \ SuiteSparse/CHOLMOD/Include/cholmod.h cholmod-etc.o: cholmod-etc.c Mdefines.h version.h \ Msymbols.h utils.h idz.h \ cholmod-etc.h SuiteSparse/SuiteSparse_config/SuiteSparse_config.h \ SuiteSparse/CHOLMOD/Include/cholmod.h coerce.o: coerce.c Mdefines.h version.h \ Msymbols.h utils.h idz.h coerce.h cs-etc.o: cs-etc.c Mdefines.h version.h \ Msymbols.h utils.h cs-etc.h \ SuiteSparse/CXSparse/Include/cs.h \ SuiteSparse/SuiteSparse_config/SuiteSparse_config.h dense.o: dense.c Mdefines.h version.h \ Msymbols.h utils.h idz.h dense.h determinant.o: determinant.c \ Mdefines.h version.h \ Msymbols.h utils.h cholmod-etc.h \ SuiteSparse/SuiteSparse_config/SuiteSparse_config.h \ SuiteSparse/CHOLMOD/Include/cholmod.h determinant.h expm.o: expm.c Lapack-etc.h \ Mdefines.h version.h \ Msymbols.h utils.h expm.h factor.o: factor.c Lapack-etc.h \ cs-etc.h \ SuiteSparse/CXSparse/Include/cs.h \ SuiteSparse/SuiteSparse_config/SuiteSparse_config.h cholmod-etc.h \ SuiteSparse/CHOLMOD/Include/cholmod.h Mdefines.h version.h \ Msymbols.h utils.h factor.h idz.o: idz.c Mdefines.h version.h \ Msymbols.h utils.h idz.h init.o: init.c Mdefines.h version.h \ Msymbols.h utils.h Csparse.h \ attrib.h bind.h cholmod-common.h cholmod-etc.h \ SuiteSparse/SuiteSparse_config/SuiteSparse_config.h \ SuiteSparse/CHOLMOD/Include/cholmod.h coerce.h dense.h determinant.h \ expm.h factor.h kappa.h matmult.h objects.h perm.h solve.h sparse.h \ subassign.h subscript.h utils-R.h validity.h vector.h \ kappa.o: kappa.c Lapack-etc.h \ Mdefines.h version.h \ Msymbols.h utils.h kappa.h matmult.o: matmult.c Lapack-etc.h \ cholmod-etc.h \ SuiteSparse/SuiteSparse_config/SuiteSparse_config.h \ SuiteSparse/CHOLMOD/Include/cholmod.h Mdefines.h version.h \ Msymbols.h utils.h idz.h coerce.h \ dense.h sparse.h matmult.h objects.o: objects.c Mdefines.h version.h \ Msymbols.h utils.h objects.h perm.o: perm.c Mdefines.h version.h \ Msymbols.h utils.h perm.h solve.o: solve.c Lapack-etc.h \ cs-etc.h \ SuiteSparse/CXSparse/Include/cs.h \ SuiteSparse/SuiteSparse_config/SuiteSparse_config.h cholmod-etc.h \ SuiteSparse/CHOLMOD/Include/cholmod.h Mdefines.h version.h \ Msymbols.h utils.h idz.h solve.h sparse.o: sparse.c Mdefines.h version.h \ Msymbols.h utils.h sparse.h subassign.o: subassign.c Mdefines.h version.h \ Msymbols.h utils.h subassign.h \ t_subassign.c subscript.o: subscript.c Mdefines.h version.h \ Msymbols.h utils.h subscript.h utils-R.o: utils-R.c Mdefines.h version.h \ Msymbols.h utils.h utils-R.h \ t_rle.c utils.o: utils.c Mdefines.h version.h \ Msymbols.h utils.h validity.o: validity.c Mdefines.h version.h \ Msymbols.h utils.h validity.h vector.o: vector.c Mdefines.h version.h \ Msymbols.h utils.h vector.h Matrix/inst/scripts/AMD.patch0000644000175100001440000000217114552026002015617 0ustar hornikusersdiff -ruN src/SuiteSparse/AMD/Makefile src/SuiteSparse-patched/AMD/Makefile --- src/SuiteSparse/AMD/Makefile 1969-12-31 19:00:00 +++ src/SuiteSparse-patched/AMD/Makefile 2024-01-12 11:54:13 @@ -0,0 +1,31 @@ +sources = \ + Source/amd_1.c Source/amd_l1.c \ + Source/amd_2.c Source/amd_l2.c \ + Source/amd_aat.c Source/amd_l_aat.c \ + Source/amd_control.c Source/amd_l_control.c \ + Source/amd_defaults.c Source/amd_l_defaults.c \ + Source/amd_dump.c Source/amd_l_dump.c \ + Source/amd_info.c Source/amd_l_info.c \ + Source/amd_order.c Source/amd_l_order.c \ + Source/amd_post_tree.c Source/amd_l_post_tree.c \ + Source/amd_postorder.c Source/amd_l_postorder.c \ + Source/amd_preprocess.c Source/amd_l_preprocess.c \ + Source/amd_valid.c Source/amd_l_valid.c \ + Source/amd_version.c +objects = $(sources:.c=.o) +archive = AMD.a + +PKG_CPPFLAGS = -I./Include -I../SuiteSparse_config + +all : $(archive) + +$(archive) : $(objects) + rm -f $@ + $(AR) -cr $@ $(objects) + $(RANLIB) $@ + +.c.o : + $(CC) $(PKG_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) -c $< -o $*.o + +clean : + @rm -f $(objects) $(archive) Matrix/inst/scripts/ssget.sh0000644000175100001440000000773214561103552015674 0ustar hornikusers#!/bin/sh pkg=Matrix if [ ! -f DESCRIPTION -o -z "$(grep "^Package: ${pkg}$" DESCRIPTION)" ]; then echo "script must be run in package [${pkg}] root directory" exit 1 fi ssdir=SuiteSparse ssver=7.6.0 sspfx=${ssdir}-${ssver} sstgz=${sspfx}.tar.gz ssurl=https://github.com/DrTimothyAldenDavis/SuiteSparse/archive/refs/tags/v${ssver}.tar.gz if [ -f ${sstgz} ]; then echo "Using existing ${sstgz}" else echo "Downloading ${sstgz} from GitHub ..." wget ${ssurl} -O ${sstgz} || exit 1 echo "done" fi echo "Extracting files under inst/doc and src ..." for d in inst/doc/${ssdir} src/${ssdir}; do if [ -d ${d} ]; then echo "Moving existing ${d} to ${d}.bak ..." rm -rf ${d}.bak mv ${d} ${d}.bak echo "done" fi done ## {root} tar -zxvf ${sstgz} -C inst/doc \ ${sspfx}/README.md \ ${sspfx}/ChangeLog \ ${sspfx}/LICENSE.txt ## SuiteSparse_config sslib=SuiteSparse_config tar -zxvf ${sstgz} -C inst/doc \ ${sspfx}/${sslib}/README.txt tar -zxvf ${sstgz} -C src \ ${sspfx}/${sslib}/SuiteSparse_config.c \ ${sspfx}/${sslib}/SuiteSparse_config.h ## CXsparse sslib=CXSparse tar -zxvf ${sstgz} -C inst/doc \ ${sspfx}/${sslib}/README.txt \ ${sspfx}/${sslib}/Doc/ChangeLog \ ${sspfx}/${sslib}/Doc/License.txt tar -zxvf ${sstgz} -C src \ ${sspfx}/${sslib}/Include/*.h \ ${sspfx}/${sslib}/Source/*.[ch] ## AMD sslib=AMD tar -zxvf ${sstgz} -C inst/doc \ ${sspfx}/${sslib}/README.txt \ ${sspfx}/${sslib}/Doc/ChangeLog \ ${sspfx}/${sslib}/Doc/License.txt tar -zxvf ${sstgz} -C src \ ${sspfx}/${sslib}/Include/*.h \ ${sspfx}/${sslib}/Source/*.[ch] ## COLAMD sslib=COLAMD tar -zxvf ${sstgz} -C inst/doc \ ${sspfx}/${sslib}/README.txt \ ${sspfx}/${sslib}/Doc/ChangeLog \ ${sspfx}/${sslib}/Doc/License.txt tar -zxvf ${sstgz} -C src \ ${sspfx}/${sslib}/Include/*.h \ ${sspfx}/${sslib}/Source/*.[ch] ## CAMD sslib=CAMD tar -zxvf ${sstgz} -C inst/doc \ ${sspfx}/${sslib}/README.txt \ ${sspfx}/${sslib}/Doc/ChangeLog \ ${sspfx}/${sslib}/Doc/License.txt tar -zxvf ${sstgz} -C src \ ${sspfx}/${sslib}/Include/*.h \ ${sspfx}/${sslib}/Source/*.[ch] ## CCOLAMD sslib=CCOLAMD tar -zxvf ${sstgz} -C inst/doc \ ${sspfx}/${sslib}/README.txt \ ${sspfx}/${sslib}/Doc/ChangeLog \ ${sspfx}/${sslib}/Doc/License.txt tar -zxvf ${sstgz} -C src \ ${sspfx}/${sslib}/Include/*.h \ ${sspfx}/${sslib}/Source/*.[ch] ## CHOLMOD sslib=CHOLMOD tar -zxvf ${sstgz} -C inst/doc \ ${sspfx}/${sslib}/README.txt \ ${sspfx}/${sslib}/Doc/ChangeLog \ ${sspfx}/${sslib}/Doc/License.txt \ ${sspfx}/${sslib}/SuiteSparse_metis/Changelog \ ${sspfx}/${sslib}/SuiteSparse_metis/LICENSE.txt \ ${sspfx}/${sslib}/SuiteSparse_metis/README.txt tar -zxvf ${sstgz} -C src \ ${sspfx}/${sslib}/Include/*.h \ ${sspfx}/${sslib}/Check/*.[ch] \ ${sspfx}/${sslib}/Cholesky/*.[ch] \ ${sspfx}/${sslib}/Utility/*.[ch] \ ${sspfx}/${sslib}/MatrixOps/*.[ch] \ ${sspfx}/${sslib}/Modify/*.[ch] \ ${sspfx}/${sslib}/Partition/*.[ch] \ ${sspfx}/${sslib}/Supernodal/*.[ch] \ ${sspfx}/${sslib}/SuiteSparse_metis/include/*.h \ ${sspfx}/${sslib}/SuiteSparse_metis/GKlib/*.[ch] \ ${sspfx}/${sslib}/SuiteSparse_metis/libmetis/*.[ch] echo "done" echo "Changing prefix ${sspfx} to ${ssdir} ..." mv inst/doc/${sspfx} inst/doc/${ssdir} mv src/${sspfx} src/${ssdir} echo "done" echo "Applying our patches ..." for sslib in SuiteSparse_config CXSparse AMD COLAMD CAMD CCOLAMD CHOLMOD; do if [ -f inst/scripts/${sslib}.patch ]; then patch -p0 < inst/scripts/${sslib}.patch fi done patch -p0 < inst/scripts/wall.patch echo "done" metis=src/${ssdir}/CHOLMOD/SuiteSparse_metis echo "Adding disclaimer to comply with Apache-2.0 ..." for f in $(find ${metis} \( ! -path "${metis}/*/*" -o -prune \) -type f); do mv ${f} ${f}.bak cat inst/scripts/disclaimer.txt ${f}.bak > ${f} rm ${f}.bak done echo "done" inc=inst/include/Matrix h=cholmod.h echo "Copying ${h} into ${inc} ..." if [ -f ${inc}/${h} ]; then echo "Moving existing ${inc}/${h} to ${inc}/${h}.bak ..." mv ${inc}/${h} ${inc}/${h}.bak echo "done" fi cp src/${ssdir}/CHOLMOD/Include/${h} ${inc} patch -p0 < inst/scripts/api.patch echo "done" Matrix/inst/scripts/rules.sh0000644000175100001440000000175714565445420015711 0ustar hornikusers#!/bin/sh pkg=Matrix if [ ! -f DESCRIPTION -o -z "$(grep "^Package: ${pkg}$" DESCRIPTION)" ]; then echo "script must be run in package [${pkg}] root directory" exit 1 fi root=$(pwd) smk=inst/scripts/sources.mk rmk=inst/scripts/rules.mk echo "Getting source file names from ${smk} ..." lst=$(cat ${smk}| sed -E "1d;s/^[\t ]*([^ ]*[.]c).*$/\1/") for file in ${lst}; do echo " ${file}" done echo "done" if [ -f ${out} ]; then echo "Moving existing ${rmk} to ${rmk}.bak ..." mv ${rmk} ${rmk}.bak echo "done" fi R=R include1="$(${R} RHOME)/include" include2="SuiteSparse/SuiteSparse_config" echo "Writing gcc -MM output to ${rmk} for inclusion in src/Makevars ..." echo "====" echo "## Generated by ./rules.sh :" | tee ${rmk} cd src for file in ${lst}; do if [ -f ${file} ]; then gcc -I${include1} -I${include2} -MM ${file} | sed -E "s~${include1}/[^ ]*[.]h( |$)~~g;\~^[\t ]*\\\\$~d" | tee -a ../${rmk} else echo "## missing ${file}" | tee -a ../${rmk} fi done cd .. echo "====" echo "done" Matrix/inst/scripts/sources.mk0000644000175100001440000000050514575137654016235 0ustar hornikuserssources = \ Csparse.c \ attrib.c \ bind.c \ cholmod-common.c \ cholmod-etc.c \ coerce.c \ cs-etc.c \ dense.c \ determinant.c \ expm.c \ factor.c \ idz.c \ init.c \ kappa.c \ matmult.c \ objects.c \ perm.c \ solve.c \ sparse.c \ subassign.c \ subscript.c \ utils-R.c \ utils.c \ validity.c \ vector.c Matrix/inst/scripts/SuiteSparse_config.patch0000644000175100001440000007352714575233601021041 0ustar hornikusersdiff -ruN src/SuiteSparse/SuiteSparse_config/Makefile src/SuiteSparse-patched/SuiteSparse_config/Makefile --- src/SuiteSparse/SuiteSparse_config/Makefile 1969-12-31 19:00:00 +++ src/SuiteSparse-patched/SuiteSparse_config/Makefile 2024-03-16 01:09:07 @@ -0,0 +1,16 @@ +sources = SuiteSparse_config.c +objects = $(sources:.c=.o) +archive = SuiteSparse_config.a + +all : $(archive) + +$(archive) : $(objects) + rm -f $@ + $(AR) -cr $@ $(objects) + $(RANLIB) $@ + +.c.o : + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $*.o + +clean : + @rm -f $(objects) $(archive) diff -ruN src/SuiteSparse/SuiteSparse_config/SuiteSparse_config.c src/SuiteSparse-patched/SuiteSparse_config/SuiteSparse_config.c --- src/SuiteSparse/SuiteSparse_config/SuiteSparse_config.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/SuiteSparse_config/SuiteSparse_config.c 2024-03-16 01:09:07 @@ -72,8 +72,8 @@ /* MATLAB mexFunction: */ mexPrintf, #else - /* standard ANSI C: */ - printf, +#include + Rprintf, #endif #else /* printf is disabled */ diff -ruN src/SuiteSparse/SuiteSparse_config/SuiteSparse_config.h src/SuiteSparse-patched/SuiteSparse_config/SuiteSparse_config.h --- src/SuiteSparse/SuiteSparse_config/SuiteSparse_config.h 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/SuiteSparse_config/SuiteSparse_config.h 2024-03-16 01:12:06 @@ -41,6 +41,33 @@ #include #include +#ifndef INT32_MAX +# define int32_t long +# define INT32_MIN LONG_MIN +# define INT32_MAX LONG_MAX +# define PRId32 "ld" +# define SCNd32 "ld" +#endif +#ifndef INT64_MAX +# define int64_t long long +# define INT64_MIN LLONG_MIN +# define INT64_MAX LLONG_MAX +# define PRId64 "lld" +# define SCNd64 "lld" +#endif +#ifndef UINT32_MAX +# define uint32_t unsigned long +# define UINT32_MAX ULONG_MAX +# define PRIu32 "lu" +# define SCNu32 "lu" +#endif +#ifndef UINT64_MAX +# define uint64_t unsigned long long +# define UINT64_MAX ULLONG_MAX +# define PRIu64 "llu" +# define SCNu64 "llu" +#endif + //------------------------------------------------------------------------------ // SuiteSparse_long is now int64_t in SuiteSparse v6.0.0 and later //------------------------------------------------------------------------------ @@ -677,6 +704,19 @@ #if defined ( SUITESPARSE_BLAS_DEFINITIONS ) +#ifndef USE_FC_LEN_T +# define USE_FC_LEN_T +#endif +#include + +#ifdef FC_LEN_T +# define FCLEN , FC_LEN_T +# define FCONE , (FC_LEN_T) 1 +#else +# define FCLEN +# define FCONE +#endif + //------------------------------------------------------------------------------ // gemv: Y = alpha*A*x + beta*Y //------------------------------------------------------------------------------ @@ -696,7 +736,7 @@ // input/output: double *Y, // input: - const SUITESPARSE_BLAS_INT *incy + const SUITESPARSE_BLAS_INT *incy FCLEN ) ; #define SUITESPARSE_BLAS_dgemv(trans,m,n,alpha,A,lda,X,incx,beta,Y,incy,ok) \ @@ -709,7 +749,7 @@ if (ok) \ { \ SUITESPARSE_BLAS_DGEMV (trans, &M_blas_int, &N_blas_int, alpha, A, \ - &LDA_blas_int, X, &INCX_blas_int, beta, Y, &INCY_blas_int) ; \ + &LDA_blas_int, X, &INCX_blas_int, beta, Y, &INCY_blas_int FCONE) ; \ } \ } @@ -728,7 +768,7 @@ // input/output: float *Y, // input: - const SUITESPARSE_BLAS_INT *incy + const SUITESPARSE_BLAS_INT *incy FCLEN ) ; #define SUITESPARSE_BLAS_sgemv(trans,m,n,alpha,A,lda,X,incx,beta,Y,incy,ok) \ @@ -741,7 +781,7 @@ if (ok) \ { \ SUITESPARSE_BLAS_SGEMV (trans, &M_blas_int, &N_blas_int, alpha, A, \ - &LDA_blas_int, X, &INCX_blas_int, beta, Y, &INCY_blas_int) ; \ + &LDA_blas_int, X, &INCX_blas_int, beta, Y, &INCY_blas_int FCONE) ; \ } \ } @@ -760,7 +800,7 @@ // input/output: void *Y, // input: - const SUITESPARSE_BLAS_INT *incy + const SUITESPARSE_BLAS_INT *incy FCLEN ) ; #define SUITESPARSE_BLAS_zgemv(trans,m,n,alpha,A,lda,X,incx,beta,Y,incy,ok) \ @@ -773,7 +813,7 @@ if (ok) \ { \ SUITESPARSE_BLAS_ZGEMV (trans, &M_blas_int, &N_blas_int, alpha, A, \ - &LDA_blas_int, X, &INCX_blas_int, beta, Y, &INCY_blas_int) ; \ + &LDA_blas_int, X, &INCX_blas_int, beta, Y, &INCY_blas_int FCONE) ; \ } \ } @@ -792,7 +832,7 @@ // input/output: void *Y, // input: - const SUITESPARSE_BLAS_INT *incy + const SUITESPARSE_BLAS_INT *incy FCLEN ) ; #define SUITESPARSE_BLAS_cgemv(trans,m,n,alpha,A,lda,X,incx,beta,Y,incy,ok) \ @@ -805,7 +845,7 @@ if (ok) \ { \ SUITESPARSE_BLAS_CGEMV (trans, &M_blas_int, &N_blas_int, alpha, A, \ - &LDA_blas_int, X, &INCX_blas_int, beta, Y, &INCY_blas_int) ; \ + &LDA_blas_int, X, &INCX_blas_int, beta, Y, &INCY_blas_int FCONE) ; \ } \ } @@ -825,7 +865,7 @@ // input/output: double *X, // input: - const SUITESPARSE_BLAS_INT *incx + const SUITESPARSE_BLAS_INT *incx FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_dtrsv(uplo,trans,diag,n,A,lda,X,incx,ok) \ @@ -836,7 +876,7 @@ if (ok) \ { \ SUITESPARSE_BLAS_DTRSV (uplo, trans, diag, &N_blas_int, A, \ - &LDA_blas_int, X, &INCX_blas_int) ; \ + &LDA_blas_int, X, &INCX_blas_int FCONE FCONE FCONE) ; \ } \ } @@ -852,7 +892,7 @@ // input/output: float *X, // input: - const SUITESPARSE_BLAS_INT *incx + const SUITESPARSE_BLAS_INT *incx FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_strsv(uplo,trans,diag,n,A,lda,X,incx,ok) \ @@ -863,7 +903,7 @@ if (ok) \ { \ SUITESPARSE_BLAS_STRSV (uplo, trans, diag, &N_blas_int, A, \ - &LDA_blas_int, X, &INCX_blas_int) ; \ + &LDA_blas_int, X, &INCX_blas_int FCONE FCONE FCONE) ; \ } \ } @@ -879,7 +919,7 @@ // input/output: void *X, // input: - const SUITESPARSE_BLAS_INT *incx + const SUITESPARSE_BLAS_INT *incx FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_ztrsv(uplo,trans,diag,n,A,lda,X,incx,ok) \ @@ -890,7 +930,7 @@ if (ok) \ { \ SUITESPARSE_BLAS_ZTRSV (uplo, trans, diag, &N_blas_int, A, \ - &LDA_blas_int, X, &INCX_blas_int) ; \ + &LDA_blas_int, X, &INCX_blas_int FCONE FCONE FCONE) ; \ } \ } @@ -906,7 +946,7 @@ // input/output: void *X, // input: - const SUITESPARSE_BLAS_INT *incx + const SUITESPARSE_BLAS_INT *incx FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_ctrsv(uplo,trans,diag,n,A,lda,X,incx,ok) \ @@ -917,7 +957,7 @@ if (ok) \ { \ SUITESPARSE_BLAS_CTRSV (uplo, trans, diag, &N_blas_int, A, \ - &LDA_blas_int, X, &INCX_blas_int) ; \ + &LDA_blas_int, X, &INCX_blas_int FCONE FCONE FCONE) ; \ } \ } @@ -940,7 +980,7 @@ // input/output: double *B, // input: - const SUITESPARSE_BLAS_INT *ldb + const SUITESPARSE_BLAS_INT *ldb FCLEN FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_dtrsm(side,uplo,transa,diag,m,n,alpha,A,lda,B,ldb,ok)\ @@ -952,7 +992,7 @@ if (ok) \ { \ SUITESPARSE_BLAS_DTRSM (side, uplo, transa, diag, &M_blas_int, \ - &N_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int) ; \ + &N_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int FCONE FCONE FCONE FCONE) ; \ } \ } @@ -971,7 +1011,7 @@ // input/output: float *B, // input: - const SUITESPARSE_BLAS_INT *ldb + const SUITESPARSE_BLAS_INT *ldb FCLEN FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_strsm(side,uplo,transa,diag,m,n,alpha,A,lda,B,ldb,ok)\ @@ -983,7 +1023,7 @@ if (ok) \ { \ SUITESPARSE_BLAS_STRSM (side, uplo, transa, diag, &M_blas_int, \ - &N_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int) ; \ + &N_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int FCONE FCONE FCONE FCONE) ; \ } \ } @@ -1002,7 +1042,7 @@ // input/output: void *B, // input: - const SUITESPARSE_BLAS_INT *ldb + const SUITESPARSE_BLAS_INT *ldb FCLEN FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_ztrsm(side,uplo,transa,diag,m,n,alpha,A,lda,B,ldb,ok)\ @@ -1014,7 +1054,7 @@ if (ok) \ { \ SUITESPARSE_BLAS_ZTRSM (side, uplo, transa, diag, &M_blas_int, \ - &N_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int) ; \ + &N_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int FCONE FCONE FCONE FCONE) ; \ } \ } @@ -1033,7 +1073,7 @@ // input/output: void *B, // input: - const SUITESPARSE_BLAS_INT *ldb + const SUITESPARSE_BLAS_INT *ldb FCLEN FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_ctrsm(side,uplo,transa,diag,m,n,alpha,A,lda,B,ldb,ok)\ @@ -1045,7 +1085,7 @@ if (ok) \ { \ SUITESPARSE_BLAS_CTRSM (side, uplo, transa, diag, &M_blas_int, \ - &N_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int) ; \ + &N_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int FCONE FCONE FCONE FCONE) ; \ } \ } @@ -1070,7 +1110,7 @@ // input/output: double *C, // input: - const SUITESPARSE_BLAS_INT *ldc + const SUITESPARSE_BLAS_INT *ldc FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_dgemm(transa,transb,m,n,k,alpha,A,lda,B,ldb,beta, \ @@ -1086,7 +1126,7 @@ { \ SUITESPARSE_BLAS_DGEMM (transa, transb, &M_blas_int, &N_blas_int, \ &K_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int, beta, C, \ - &LDC_blas_int) ; \ + &LDC_blas_int FCONE FCONE) ; \ } \ } @@ -1107,7 +1147,7 @@ // input/output: float *C, // input: - const SUITESPARSE_BLAS_INT *ldc + const SUITESPARSE_BLAS_INT *ldc FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_sgemm(transa,transb,m,n,k,alpha,A,lda,B,ldb,beta, \ @@ -1123,7 +1163,7 @@ { \ SUITESPARSE_BLAS_SGEMM (transa, transb, &M_blas_int, &N_blas_int, \ &K_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int, beta, C, \ - &LDC_blas_int) ; \ + &LDC_blas_int FCONE FCONE) ; \ } \ } @@ -1144,7 +1184,7 @@ // input/output: void *C, // input: - const SUITESPARSE_BLAS_INT *ldc + const SUITESPARSE_BLAS_INT *ldc FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_zgemm(transa,transb,m,n,k,alpha,A,lda,B,ldb,beta, \ @@ -1160,7 +1200,7 @@ { \ SUITESPARSE_BLAS_ZGEMM (transa, transb, &M_blas_int, &N_blas_int, \ &K_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int, beta, C, \ - &LDC_blas_int) ; \ + &LDC_blas_int FCONE FCONE) ; \ } \ } @@ -1181,7 +1221,7 @@ // input/output: void *C, // input: - const SUITESPARSE_BLAS_INT *ldc + const SUITESPARSE_BLAS_INT *ldc FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_cgemm(transa,transb,m,n,k,alpha,A,lda,B,ldb,beta, \ @@ -1197,7 +1237,7 @@ { \ SUITESPARSE_BLAS_CGEMM (transa, transb, &M_blas_int, &N_blas_int, \ &K_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int, beta, C, \ - &LDC_blas_int) ; \ + &LDC_blas_int FCONE FCONE) ; \ } \ } @@ -1219,7 +1259,7 @@ // input/output: double *C, // input: - const SUITESPARSE_BLAS_INT *ldc + const SUITESPARSE_BLAS_INT *ldc FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_dsyrk(uplo,trans,n,k,alpha,A,lda,beta,C,ldc,ok) \ @@ -1231,7 +1271,7 @@ if (ok) \ { \ SUITESPARSE_BLAS_DSYRK (uplo, trans, &N_blas_int, &K_blas_int, alpha, \ - A, &LDA_blas_int, beta, C, &LDC_blas_int) ; \ + A, &LDA_blas_int, beta, C, &LDC_blas_int FCONE FCONE) ; \ } \ } @@ -1249,7 +1289,7 @@ // input/output: float *C, // input: - const SUITESPARSE_BLAS_INT *ldc + const SUITESPARSE_BLAS_INT *ldc FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_ssyrk(uplo,trans,n,k,alpha,A,lda,beta,C,ldc,ok) \ @@ -1261,7 +1301,7 @@ if (ok) \ { \ SUITESPARSE_BLAS_SSYRK (uplo, trans, &N_blas_int, &K_blas_int, alpha, \ - A, &LDA_blas_int, beta, C, &LDC_blas_int) ; \ + A, &LDA_blas_int, beta, C, &LDC_blas_int FCONE FCONE) ; \ } \ } @@ -1279,7 +1319,7 @@ // input/output: void *C, // input: - const SUITESPARSE_BLAS_INT *ldc + const SUITESPARSE_BLAS_INT *ldc FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_zherk(uplo,trans,n,k,alpha,A,lda,beta,C,ldc,ok) \ @@ -1291,7 +1331,7 @@ if (ok) \ { \ SUITESPARSE_BLAS_ZHERK (uplo, trans, &N_blas_int, &K_blas_int, alpha, \ - A, &LDA_blas_int, beta, C, &LDC_blas_int) ; \ + A, &LDA_blas_int, beta, C, &LDC_blas_int FCONE FCONE) ; \ } \ } @@ -1309,7 +1349,7 @@ // input/output: void *C, // input: - const SUITESPARSE_BLAS_INT *ldc + const SUITESPARSE_BLAS_INT *ldc FCLEN FCLEN ) ; #define SUITESPARSE_BLAS_cherk(uplo,trans,n,k,alpha,A,lda,beta,C,ldc,ok) \ @@ -1321,7 +1361,7 @@ if (ok) \ { \ SUITESPARSE_BLAS_CHERK (uplo, trans, &N_blas_int, &K_blas_int, alpha, \ - A, &LDA_blas_int, beta, C, &LDC_blas_int) ; \ + A, &LDA_blas_int, beta, C, &LDC_blas_int FCONE FCONE) ; \ } \ } @@ -1339,7 +1379,7 @@ // input: const SUITESPARSE_BLAS_INT *lda, // output: - SUITESPARSE_BLAS_INT *info + SUITESPARSE_BLAS_INT *info FCLEN ) ; #define SUITESPARSE_LAPACK_dpotrf(uplo,n,A,lda,info,ok) \ @@ -1351,7 +1391,7 @@ { \ SUITESPARSE_BLAS_INT LAPACK_Info = -999 ; \ SUITESPARSE_LAPACK_DPOTRF (uplo, &N_blas_int, A, &LDA_blas_int, \ - &LAPACK_Info) ; \ + &LAPACK_Info FCONE) ; \ info = (Int) LAPACK_Info ; \ } \ } @@ -1366,7 +1406,7 @@ // input: const SUITESPARSE_BLAS_INT *lda, // output: - SUITESPARSE_BLAS_INT *info + SUITESPARSE_BLAS_INT *info FCLEN ) ; #define SUITESPARSE_LAPACK_spotrf(uplo,n,A,lda,info,ok) \ @@ -1378,7 +1418,7 @@ { \ SUITESPARSE_BLAS_INT LAPACK_Info = -999 ; \ SUITESPARSE_LAPACK_SPOTRF (uplo, &N_blas_int, A, &LDA_blas_int, \ - &LAPACK_Info) ; \ + &LAPACK_Info FCONE) ; \ info = (Int) LAPACK_Info ; \ } \ } @@ -1393,7 +1433,7 @@ // input: const SUITESPARSE_BLAS_INT *lda, // output: - SUITESPARSE_BLAS_INT *info + SUITESPARSE_BLAS_INT *info FCLEN ) ; #define SUITESPARSE_LAPACK_zpotrf(uplo,n,A,lda,info,ok) \ @@ -1405,7 +1445,7 @@ { \ SUITESPARSE_BLAS_INT LAPACK_Info = -999 ; \ SUITESPARSE_LAPACK_ZPOTRF (uplo, &N_blas_int, A, &LDA_blas_int, \ - &LAPACK_Info) ; \ + &LAPACK_Info FCONE) ; \ info = LAPACK_Info ; \ } \ } @@ -1420,7 +1460,7 @@ // input: const SUITESPARSE_BLAS_INT *lda, // output: - SUITESPARSE_BLAS_INT *info + SUITESPARSE_BLAS_INT *info FCLEN ) ; #define SUITESPARSE_LAPACK_cpotrf(uplo,n,A,lda,info,ok) \ @@ -1432,7 +1472,7 @@ { \ SUITESPARSE_BLAS_INT LAPACK_Info = -999 ; \ SUITESPARSE_LAPACK_CPOTRF (uplo, &N_blas_int, A, &LDA_blas_int, \ - &LAPACK_Info) ; \ + &LAPACK_Info FCONE) ; \ info = LAPACK_Info ; \ } \ } @@ -1666,7 +1706,7 @@ // output: double *T, // input: - const SUITESPARSE_BLAS_INT *ldt + const SUITESPARSE_BLAS_INT *ldt FCLEN FCLEN ) ; #define SUITESPARSE_LAPACK_dlarft(direct,storev,n,k,V,ldv,Tau,T,ldt,ok) \ @@ -1678,7 +1718,7 @@ if (ok) \ { \ SUITESPARSE_LAPACK_DLARFT (direct, storev, &N_blas_int, &K_blas_int, \ - V, &LDV_blas_int, Tau, T, &LDT_blas_int) ; \ + V, &LDV_blas_int, Tau, T, &LDT_blas_int FCONE FCONE) ; \ } \ } @@ -1695,7 +1735,7 @@ // output: float *T, // input: - const SUITESPARSE_BLAS_INT *ldt + const SUITESPARSE_BLAS_INT *ldt FCLEN FCLEN ) ; #define SUITESPARSE_LAPACK_slarft(direct,storev,n,k,V,ldv,Tau,T,ldt,ok) \ @@ -1707,7 +1747,7 @@ if (ok) \ { \ SUITESPARSE_LAPACK_SLARFT (direct, storev, &N_blas_int, &K_blas_int, \ - V, &LDV_blas_int, Tau, T, &LDT_blas_int) ; \ + V, &LDV_blas_int, Tau, T, &LDT_blas_int FCONE FCONE) ; \ } \ } @@ -1724,7 +1764,7 @@ // output: void *T, // input: - const SUITESPARSE_BLAS_INT *ldt + const SUITESPARSE_BLAS_INT *ldt FCLEN FCLEN ) ; #define SUITESPARSE_LAPACK_zlarft(direct,storev,n,k,V,ldv,Tau,T,ldt,ok) \ @@ -1736,7 +1776,7 @@ if (ok) \ { \ SUITESPARSE_LAPACK_ZLARFT (direct, storev, &N_blas_int, &K_blas_int, \ - V, &LDV_blas_int, Tau, T, &LDT_blas_int) ; \ + V, &LDV_blas_int, Tau, T, &LDT_blas_int FCONE FCONE) ; \ } \ } @@ -1753,7 +1793,7 @@ // output: void *T, // input: - const SUITESPARSE_BLAS_INT *ldt + const SUITESPARSE_BLAS_INT *ldt FCLEN FCLEN ) ; #define SUITESPARSE_LAPACK_clarft(direct,storev,n,k,V,ldv,Tau,T,ldt,ok) \ @@ -1765,7 +1805,7 @@ if (ok) \ { \ SUITESPARSE_LAPACK_CLARFT (direct, storev, &N_blas_int, &K_blas_int, \ - V, &LDV_blas_int, Tau, T, &LDT_blas_int) ; \ + V, &LDV_blas_int, Tau, T, &LDT_blas_int FCONE FCONE) ; \ } \ } @@ -1794,7 +1834,7 @@ // workspace: double *Work, // input: - const SUITESPARSE_BLAS_INT *ldwork + const SUITESPARSE_BLAS_INT *ldwork FCLEN FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_LAPACK_dlarfb(side,trans,direct,storev,m,n,k,V,ldv,T,ldt, \ @@ -1811,7 +1851,7 @@ { \ SUITESPARSE_LAPACK_DLARFB (side, trans, direct, storev, &M_blas_int, \ &N_blas_int, &K_blas_int, V, &LDV_blas_int, T, &LDT_blas_int, C, \ - &LDC_blas_int, Work, &LDWORK_blas_int) ; \ + &LDC_blas_int, Work, &LDWORK_blas_int FCONE FCONE FCONE FCONE) ; \ } \ } @@ -1836,7 +1876,7 @@ // workspace: float *Work, // input: - const SUITESPARSE_BLAS_INT *ldwork + const SUITESPARSE_BLAS_INT *ldwork FCLEN FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_LAPACK_slarfb(side,trans,direct,storev,m,n,k,V,ldv,T,ldt, \ @@ -1853,7 +1893,7 @@ { \ SUITESPARSE_LAPACK_SLARFB (side, trans, direct, storev, &M_blas_int, \ &N_blas_int, &K_blas_int, V, &LDV_blas_int, T, &LDT_blas_int, C, \ - &LDC_blas_int, Work, &LDWORK_blas_int) ; \ + &LDC_blas_int, Work, &LDWORK_blas_int FCONE FCONE FCONE FCONE) ; \ } \ } @@ -1878,7 +1918,7 @@ // workspace: void *Work, // input: - const SUITESPARSE_BLAS_INT *ldwork + const SUITESPARSE_BLAS_INT *ldwork FCLEN FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_LAPACK_zlarfb(side,trans,direct,storev,m,n,k,V,ldv,T,ldt, \ @@ -1895,7 +1935,7 @@ { \ SUITESPARSE_LAPACK_ZLARFB (side, trans, direct, storev, &M_blas_int, \ &N_blas_int, &K_blas_int, V, &LDV_blas_int, T, &LDT_blas_int, C, \ - &LDC_blas_int, Work, &LDWORK_blas_int) ; \ + &LDC_blas_int, Work, &LDWORK_blas_int FCONE FCONE FCONE FCONE) ; \ } \ } @@ -1920,7 +1960,7 @@ // workspace: void *Work, // input: - const SUITESPARSE_BLAS_INT *ldwork + const SUITESPARSE_BLAS_INT *ldwork FCLEN FCLEN FCLEN FCLEN ) ; #define SUITESPARSE_LAPACK_clarfb(side,trans,direct,storev,m,n,k,V,ldv,T,ldt, \ @@ -1937,7 +1977,7 @@ { \ SUITESPARSE_LAPACK_CLARFB (side, trans, direct, storev, &M_blas_int, \ &N_blas_int, &K_blas_int, V, &LDV_blas_int, T, &LDT_blas_int, C, \ - &LDC_blas_int, Work, &LDWORK_blas_int) ; \ + &LDC_blas_int, Work, &LDWORK_blas_int FCONE FCONE FCONE FCONE) ; \ } \ } @@ -2139,7 +2179,7 @@ // input: const SUITESPARSE_BLAS_INT *ldc, // workspace: - double *Work + double *Work FCLEN ) ; #define SUITESPARSE_LAPACK_dlarf(side,m,n,V,incv,tau,C,ldc,Work,ok) \ @@ -2151,7 +2191,7 @@ if (ok) \ { \ SUITESPARSE_LAPACK_DLARF (side, &M_blas_int, &N_blas_int, V, \ - &INCV_blas_int, tau, C, &LDC_blas_int, Work) ; \ + &INCV_blas_int, tau, C, &LDC_blas_int, Work FCONE) ; \ } \ } @@ -2169,7 +2209,7 @@ // input: const SUITESPARSE_BLAS_INT *ldc, // workspace: - float *Work + float *Work FCLEN ) ; #define SUITESPARSE_LAPACK_slarf(side,m,n,V,incv,tau,C,ldc,Work,ok) \ @@ -2181,7 +2221,7 @@ if (ok) \ { \ SUITESPARSE_LAPACK_SLARF (side, &M_blas_int, &N_blas_int, V, \ - &INCV_blas_int, tau, C, &LDC_blas_int, Work) ; \ + &INCV_blas_int, tau, C, &LDC_blas_int, Work FCONE) ; \ } \ } @@ -2199,7 +2239,7 @@ // input: const SUITESPARSE_BLAS_INT *ldc, // workspace: - void *Work + void *Work FCLEN ) ; #define SUITESPARSE_LAPACK_zlarf(side,m,n,V,incv,tau,C,ldc,Work,ok) \ @@ -2211,7 +2251,7 @@ if (ok) \ { \ SUITESPARSE_LAPACK_ZLARF (side, &M_blas_int, &N_blas_int, V, \ - &INCV_blas_int, tau, C, &LDC_blas_int, Work) ; \ + &INCV_blas_int, tau, C, &LDC_blas_int, Work FCONE) ; \ } \ } @@ -2229,7 +2269,7 @@ // input: const SUITESPARSE_BLAS_INT *ldc, // workspace: - void *Work + void *Work FCLEN ) ; #define SUITESPARSE_LAPACK_clarf(side,m,n,V,incv,tau,C,ldc,Work,ok) \ @@ -2241,7 +2281,7 @@ if (ok) \ { \ SUITESPARSE_LAPACK_CLARF (side, &M_blas_int, &N_blas_int, V, \ - &INCV_blas_int, tau, C, &LDC_blas_int, Work) ; \ + &INCV_blas_int, tau, C, &LDC_blas_int, Work FCONE) ; \ } \ } Matrix/inst/scripts/COLAMD.patch0000644000175100001440000000113114552026002016150 0ustar hornikusersdiff -ruN src/SuiteSparse/COLAMD/Makefile src/SuiteSparse-patched/COLAMD/Makefile --- src/SuiteSparse/COLAMD/Makefile 1969-12-31 19:00:00 +++ src/SuiteSparse-patched/COLAMD/Makefile 2024-01-12 11:54:13 @@ -0,0 +1,18 @@ +sources = Source/colamd.c Source/colamd_l.c Source/colamd_version.c +objects = $(sources:.c=.o) +archive = COLAMD.a + +PKG_CPPFLAGS = -I./Include -I../SuiteSparse_config + +all : $(archive) + +$(archive) : $(objects) + rm -f $@ + $(AR) -cr $@ $(objects) + $(RANLIB) $@ + +.c.o : + $(CC) $(PKG_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) -c $< -o $*.o + +clean : + @rm -f $(objects) $(archive) Matrix/inst/scripts/CHOLMOD.patch0000644000175100001440000005636214552026002016316 0ustar hornikusersdiff -ruN src/SuiteSparse/CHOLMOD/Include/cholmod.h src/SuiteSparse-patched/CHOLMOD/Include/cholmod.h --- src/SuiteSparse/CHOLMOD/Include/cholmod.h 2024-01-10 19:08:51 +++ src/SuiteSparse-patched/CHOLMOD/Include/cholmod.h 2024-01-12 11:54:13 @@ -1419,8 +1419,8 @@ int sorted, // ignored; C is now always returned as sorted cholmod_common *Common ) ; -cholmod_sparse *cholmod_l_add (cholmod_sparse *, cholmod_sparse *, double *, - double *, int, int, cholmod_common *) ; +cholmod_sparse *cholmod_l_add (cholmod_sparse *, cholmod_sparse *, double [2], + double [2], int, int, cholmod_common *) ; //------------------------------------------------------------------------------ // cholmod_sparse_xtype: change the xtype and/or dtype of a sparse matrix @@ -2695,7 +2695,7 @@ cholmod_factor *L, // resulting factorization cholmod_common *Common ) ; -int cholmod_l_factorize_p (cholmod_sparse *, double *, int64_t *, size_t, +int cholmod_l_factorize_p (cholmod_sparse *, double [2], int64_t *, size_t, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ @@ -2893,7 +2893,7 @@ cholmod_factor *L, cholmod_common *Common ) ; -int cholmod_l_rowfac (cholmod_sparse *, cholmod_sparse *, double *, size_t, +int cholmod_l_rowfac (cholmod_sparse *, cholmod_sparse *, double [2], size_t, size_t, cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ @@ -2918,7 +2918,7 @@ cholmod_factor *L, cholmod_common *Common ) ; -int cholmod_l_rowfac_mask (cholmod_sparse *, cholmod_sparse *, double *, +int cholmod_l_rowfac_mask (cholmod_sparse *, cholmod_sparse *, double [2], size_t, size_t, int64_t *, int64_t *, cholmod_factor *, cholmod_common *) ; int cholmod_rowfac_mask2 @@ -2937,7 +2937,7 @@ cholmod_factor *L, cholmod_common *Common ) ; -int cholmod_l_rowfac_mask2 (cholmod_sparse *, cholmod_sparse *, double *, +int cholmod_l_rowfac_mask2 (cholmod_sparse *, cholmod_sparse *, double [2], size_t, size_t, int64_t *, int64_t, int64_t *, cholmod_factor *, cholmod_common *) ; @@ -3202,7 +3202,7 @@ cholmod_dense *Y, // resulting dense matrix cholmod_common *Common ) ; -int cholmod_l_sdmult (cholmod_sparse *, int, double *, double *, +int cholmod_l_sdmult (cholmod_sparse *, int, double [2], double [2], cholmod_dense *, cholmod_dense *Y, cholmod_common *) ; //------------------------------------------------------------------------------ @@ -3502,7 +3502,7 @@ cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; -int cholmod_l_rowadd_solve (size_t, cholmod_sparse *, double *, +int cholmod_l_rowadd_solve (size_t, cholmod_sparse *, double [2], cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ @@ -3526,7 +3526,7 @@ cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; -int cholmod_l_rowadd_mark (size_t, cholmod_sparse *, double *, int64_t *, +int cholmod_l_rowadd_mark (size_t, cholmod_sparse *, double [2], int64_t *, cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ @@ -3573,7 +3573,7 @@ cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; -int cholmod_l_rowdel_solve (size_t, cholmod_sparse *, double *, +int cholmod_l_rowdel_solve (size_t, cholmod_sparse *, double [2], cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; //------------------------------------------------------------------------------ @@ -3597,7 +3597,7 @@ cholmod_dense *DeltaB, // change in b, zero on output cholmod_common *Common ) ; -int cholmod_l_rowdel_mark (size_t, cholmod_sparse *, double *, int64_t *, +int cholmod_l_rowdel_mark (size_t, cholmod_sparse *, double [2], int64_t *, cholmod_factor *, cholmod_dense *, cholmod_dense *, cholmod_common *) ; #endif @@ -3927,7 +3927,7 @@ cholmod_factor *L, // factorization cholmod_common *Common ) ; -int cholmod_l_super_numeric (cholmod_sparse *, cholmod_sparse *, double *, +int cholmod_l_super_numeric (cholmod_sparse *, cholmod_sparse *, double [2], cholmod_factor *, cholmod_common *) ; //------------------------------------------------------------------------------ diff -ruN src/SuiteSparse/CHOLMOD/Makefile src/SuiteSparse-patched/CHOLMOD/Makefile --- src/SuiteSparse/CHOLMOD/Makefile 1969-12-31 19:00:00 +++ src/SuiteSparse-patched/CHOLMOD/Makefile 2024-01-12 11:54:13 @@ -0,0 +1,128 @@ +sources = \ + Check/cholmod_check.c Check/cholmod_l_check.c \ + Check/cholmod_read.c Check/cholmod_l_read.c \ + Check/cholmod_write.c Check/cholmod_l_write.c \ + Cholesky/cholmod_amd.c Cholesky/cholmod_l_amd.c \ + Cholesky/cholmod_analyze.c Cholesky/cholmod_l_analyze.c \ + Cholesky/cholmod_colamd.c Cholesky/cholmod_l_colamd.c \ + Cholesky/cholmod_etree.c Cholesky/cholmod_l_etree.c \ + Cholesky/cholmod_factorize.c Cholesky/cholmod_l_factorize.c \ + Cholesky/cholmod_postorder.c Cholesky/cholmod_l_postorder.c \ + Cholesky/cholmod_rcond.c Cholesky/cholmod_l_rcond.c \ + Cholesky/cholmod_resymbol.c Cholesky/cholmod_l_resymbol.c \ + Cholesky/cholmod_rowcolcounts.c Cholesky/cholmod_l_rowcolcounts.c \ + Cholesky/cholmod_rowfac.c Cholesky/cholmod_l_rowfac.c \ + Cholesky/cholmod_solve.c Cholesky/cholmod_l_solve.c \ + Cholesky/cholmod_spsolve.c Cholesky/cholmod_l_spsolve.c \ + Utility/cholmod_aat.c Utility/cholmod_l_aat.c \ + Utility/cholmod_add.c Utility/cholmod_l_add.c \ + Utility/cholmod_add_size_t.c Utility/cholmod_l_add_size_t.c \ + Utility/cholmod_alloc_factor.c Utility/cholmod_l_alloc_factor.c \ + Utility/cholmod_alloc_work.c Utility/cholmod_l_alloc_work.c \ + Utility/cholmod_allocate_dense.c Utility/cholmod_l_allocate_dense.c \ + Utility/cholmod_allocate_factor.c Utility/cholmod_l_allocate_factor.c \ + Utility/cholmod_allocate_sparse.c Utility/cholmod_l_allocate_sparse.c \ + Utility/cholmod_allocate_triplet.c Utility/cholmod_l_allocate_triplet.c \ + Utility/cholmod_allocate_work.c Utility/cholmod_l_allocate_work.c \ + Utility/cholmod_band.c Utility/cholmod_l_band.c \ + Utility/cholmod_band_nnz.c Utility/cholmod_l_band_nnz.c \ + Utility/cholmod_calloc.c Utility/cholmod_l_calloc.c \ + Utility/cholmod_change_factor.c Utility/cholmod_l_change_factor.c \ + Utility/cholmod_clear_flag.c Utility/cholmod_l_clear_flag.c \ + Utility/cholmod_copy.c Utility/cholmod_l_copy.c \ + Utility/cholmod_copy_dense.c Utility/cholmod_l_copy_dense.c \ + Utility/cholmod_copy_dense2.c Utility/cholmod_l_copy_dense2.c \ + Utility/cholmod_copy_factor.c Utility/cholmod_l_copy_factor.c \ + Utility/cholmod_copy_sparse.c Utility/cholmod_l_copy_sparse.c \ + Utility/cholmod_copy_triplet.c Utility/cholmod_l_copy_triplet.c \ + Utility/cholmod_cumsum.c Utility/cholmod_l_cumsum.c \ + Utility/cholmod_dbound.c Utility/cholmod_l_dbound.c \ + Utility/cholmod_defaults.c Utility/cholmod_l_defaults.c \ + Utility/cholmod_dense_nnz.c Utility/cholmod_l_dense_nnz.c \ + Utility/cholmod_dense_to_sparse.c Utility/cholmod_l_dense_to_sparse.c \ + Utility/cholmod_divcomplex.c Utility/cholmod_l_divcomplex.c \ + Utility/cholmod_ensure_dense.c Utility/cholmod_l_ensure_dense.c \ + Utility/cholmod_error.c Utility/cholmod_l_error.c \ + Utility/cholmod_eye.c Utility/cholmod_l_eye.c \ + Utility/cholmod_factor_to_sparse.c Utility/cholmod_l_factor_to_sparse.c \ + Utility/cholmod_finish.c Utility/cholmod_l_finish.c \ + Utility/cholmod_free.c Utility/cholmod_l_free.c \ + Utility/cholmod_free_dense.c Utility/cholmod_l_free_dense.c \ + Utility/cholmod_free_factor.c Utility/cholmod_l_free_factor.c \ + Utility/cholmod_free_sparse.c Utility/cholmod_l_free_sparse.c \ + Utility/cholmod_free_triplet.c Utility/cholmod_l_free_triplet.c \ + Utility/cholmod_free_work.c Utility/cholmod_l_free_work.c \ + Utility/cholmod_hypot.c Utility/cholmod_l_hypot.c \ + Utility/cholmod_malloc.c Utility/cholmod_l_malloc.c \ + Utility/cholmod_maxrank.c Utility/cholmod_l_maxrank.c \ + Utility/cholmod_memdebug.c \ + Utility/cholmod_mult_size_t.c Utility/cholmod_l_mult_size_t.c \ + Utility/cholmod_mult_uint64_t.c \ + Utility/cholmod_nnz.c Utility/cholmod_l_nnz.c \ + Utility/cholmod_ones.c Utility/cholmod_l_ones.c \ + Utility/cholmod_pack_factor.c Utility/cholmod_l_pack_factor.c \ + Utility/cholmod_ptranspose.c Utility/cholmod_l_ptranspose.c \ + Utility/cholmod_realloc.c Utility/cholmod_l_realloc.c \ + Utility/cholmod_realloc_multiple.c Utility/cholmod_l_realloc_multiple.c \ + Utility/cholmod_reallocate_column.c Utility/cholmod_l_reallocate_column.c \ + Utility/cholmod_reallocate_factor.c Utility/cholmod_l_reallocate_factor.c \ + Utility/cholmod_reallocate_sparse.c Utility/cholmod_l_reallocate_sparse.c \ + Utility/cholmod_reallocate_triplet.c Utility/cholmod_l_reallocate_triplet.c \ + Utility/cholmod_sbound.c Utility/cholmod_l_sbound.c \ + Utility/cholmod_score_comp.c Utility/cholmod_l_score_comp.c \ + Utility/cholmod_set_empty.c Utility/cholmod_l_set_empty.c \ + Utility/cholmod_sort.c Utility/cholmod_l_sort.c \ + Utility/cholmod_sparse_to_dense.c Utility/cholmod_l_sparse_to_dense.c \ + Utility/cholmod_sparse_to_triplet.c Utility/cholmod_l_sparse_to_triplet.c \ + Utility/cholmod_speye.c Utility/cholmod_l_speye.c \ + Utility/cholmod_spzeros.c Utility/cholmod_l_spzeros.c \ + Utility/cholmod_start.c Utility/cholmod_l_start.c \ + Utility/cholmod_transpose.c Utility/cholmod_l_transpose.c \ + Utility/cholmod_transpose_sym.c Utility/cholmod_l_transpose_sym.c \ + Utility/cholmod_transpose_unsym.c Utility/cholmod_l_transpose_unsym.c \ + Utility/cholmod_triplet_to_sparse.c Utility/cholmod_l_triplet_to_sparse.c \ + Utility/cholmod_version.c Utility/cholmod_l_version.c \ + Utility/cholmod_xtype.c Utility/cholmod_l_xtype.c \ + Utility/cholmod_zeros.c Utility/cholmod_l_zeros.c \ + MatrixOps/cholmod_drop.c MatrixOps/cholmod_l_drop.c \ + MatrixOps/cholmod_horzcat.c MatrixOps/cholmod_l_horzcat.c \ + MatrixOps/cholmod_norm.c MatrixOps/cholmod_l_norm.c \ + MatrixOps/cholmod_scale.c MatrixOps/cholmod_l_scale.c \ + MatrixOps/cholmod_sdmult.c MatrixOps/cholmod_l_sdmult.c \ + MatrixOps/cholmod_ssmult.c MatrixOps/cholmod_l_ssmult.c \ + MatrixOps/cholmod_submatrix.c MatrixOps/cholmod_l_submatrix.c \ + MatrixOps/cholmod_symmetry.c MatrixOps/cholmod_l_symmetry.c \ + MatrixOps/cholmod_vertcat.c MatrixOps/cholmod_l_vertcat.c \ + Modify/cholmod_rowadd.c Modify/cholmod_l_rowadd.c \ + Modify/cholmod_rowdel.c Modify/cholmod_l_rowdel.c \ + Modify/cholmod_updown.c Modify/cholmod_l_updown.c \ + Partition/cholmod_camd.c Partition/cholmod_l_camd.c \ + Partition/cholmod_ccolamd.c Partition/cholmod_l_ccolamd.c \ + Partition/cholmod_csymamd.c Partition/cholmod_l_csymamd.c \ + Partition/cholmod_metis.c Partition/cholmod_l_metis.c \ + Partition/cholmod_metis_wrapper.c \ + Partition/cholmod_nesdis.c Partition/cholmod_l_nesdis.c \ + Supernodal/cholmod_super_numeric.c Supernodal/cholmod_l_super_numeric.c \ + Supernodal/cholmod_super_solve.c Supernodal/cholmod_l_super_solve.c \ + Supernodal/cholmod_super_symbolic.c Supernodal/cholmod_l_super_symbolic.c +objects = $(sources:.c=.o) +archive = CHOLMOD.a + +PKG_CPPFLAGS = -I./Include -I../SuiteSparse_config \ + -I../AMD/Include -I../COLAMD/Include \ + -I../CAMD/Include -I../CCOLAMD/Include \ + -I. -I./SuiteSparse_metis/include \ + -I./SuiteSparse_metis/GKlib -I./SuiteSparse_metis/libmetis + +all : $(archive) + +$(archive) : $(objects) + rm -f $@ + $(AR) -cr $@ $(objects) + $(RANLIB) $@ + +.c.o : + $(CC) $(PKG_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) -c $< -o $*.o + +clean : + @rm -f $(objects) $(archive) diff -ruN src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_sdmult_worker.c src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_sdmult_worker.c --- src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_sdmult_worker.c 2024-01-10 19:08:51 +++ src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_sdmult_worker.c 2024-01-12 11:54:13 @@ -76,7 +76,7 @@ size_t dy = Y->d ; size_t dx = X->d ; Real *w = W ; - Real *Wz = W + 4*nx ; + Real *Wz = (W) ? W + 4*nx : W ; //-------------------------------------------------------------------------- // Y = beta * Y diff -ruN src/SuiteSparse/CHOLMOD/Partition/cholmod_metis_wrapper.h src/SuiteSparse-patched/CHOLMOD/Partition/cholmod_metis_wrapper.h --- src/SuiteSparse/CHOLMOD/Partition/cholmod_metis_wrapper.h 2024-01-10 19:08:51 +++ src/SuiteSparse-patched/CHOLMOD/Partition/cholmod_metis_wrapper.h 2024-01-12 11:54:13 @@ -16,15 +16,6 @@ #define USE_GKRAND #endif -#if defined ( __GNUC__ ) && !defined ( __clang__ ) - // disable memcpy warnings: - #pragma GCC diagnostic ignored "-Wstringop-overflow=" - // csr.c has misleading indentation: - #pragma GCC diagnostic ignored "-Wmisleading-indentation" - // GKlib/error.c: - #pragma GCC diagnostic ignored "-Wunused-result" -#endif - #if SUITESPARSE_COMPILER_MSC #undef __thread #define __thread __declspec(thread) diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/csr.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/csr.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/csr.c 2024-01-10 19:08:51 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/csr.c 2024-01-12 11:54:13 @@ -16,7 +16,7 @@ \returns the allocated matrix. The various fields are set to NULL. */ /**************************************************************************/ -gk_csr_t *gk_csr_Create() +gk_csr_t *gk_csr_Create(void) { gk_csr_t *mat; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/error.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/error.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/error.c 2024-01-10 19:08:51 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/error.c 2024-01-12 11:54:13 @@ -95,7 +95,7 @@ of a longjmp */ /***************************************************************************/ -int gk_sigtrap() +int gk_sigtrap(void) { if (gk_cur_jbufs+1 >= MAX_JBUFS) return 0; @@ -113,7 +113,7 @@ /*! This function sets the handlers for the signals to their default handlers */ /***************************************************************************/ -int gk_siguntrap() +int gk_siguntrap(void) { if (gk_cur_jbufs == -1) return 0; @@ -142,7 +142,7 @@ * This function sets a number of signal handlers and sets the return point * of a longjmp ****************************************************************************/ -void gk_SetSignalHandlers() +void gk_SetSignalHandlers(void) { old_SIGMEM_handler = signal(SIGMEM, gk_NonLocalExit_Handler); old_SIGERR_handler = signal(SIGERR, gk_NonLocalExit_Handler); @@ -152,7 +152,7 @@ /*************************************************************************** * This function sets the handlers for the signals to their default handlers ****************************************************************************/ -void gk_UnsetSignalHandlers() +void gk_UnsetSignalHandlers(void) { signal(SIGMEM, old_SIGMEM_handler); signal(SIGERR, old_SIGERR_handler); @@ -198,7 +198,7 @@ /************************************************************************* * This function prints a backtrace of calling functions **************************************************************************/ -void PrintBackTrace() +void PrintBackTrace(void) { #ifdef HAVE_EXECINFO_H void *array[10]; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_getopt.h src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/gk_getopt.h --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_getopt.h 2024-01-10 19:08:51 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/gk_getopt.h 2024-01-12 11:54:13 @@ -52,11 +52,9 @@ /* Function prototypes */ -extern int gk_getopt(int __argc, char **__argv, char *__shortopts); -extern int gk_getopt_long(int __argc, char **__argv, char *__shortopts, - struct gk_option *__longopts, int *__longind); -extern int gk_getopt_long_only (int __argc, char **__argv, - char *__shortopts, struct gk_option *__longopts, int *__longind); +int gk_getopt(int, char **, char *); +int gk_getopt_long(int, char **, char *, struct gk_option *, int *); +int gk_getopt_long_only (int, char **, char *, struct gk_option *, int *); diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_mkrandom.h src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/gk_mkrandom.h --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_mkrandom.h 2024-01-10 19:08:51 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/gk_mkrandom.h 2024-01-12 11:54:13 @@ -33,7 +33,7 @@ /*************************************************************************/\ /*! Returns a random number */ \ /**************************************************************************/\ -RNGT FPRFX ## rand() \ +RNGT FPRFX ## rand(void) \ {\ if (sizeof(RNGT) <= sizeof(int32_t)) \ return (RNGT)gk_randint32(); \ diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gkregex.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/gkregex.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gkregex.c 2024-01-10 19:08:51 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/gkregex.c 2024-01-12 11:54:13 @@ -19,7 +19,7 @@ 02111-1307 USA. */ /* this is for removing a compiler warning */ -void gkfooo() { return; } +void gkfooo(void) { return; } #ifdef USE_GKREGEX diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/graph.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/graph.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/graph.c 2024-01-10 19:08:51 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/graph.c 2024-01-12 11:54:13 @@ -16,7 +16,7 @@ \returns the allocated graph. The various fields are set to NULL. */ /**************************************************************************/ -gk_graph_t *gk_graph_Create() +gk_graph_t *gk_graph_Create(void) { gk_graph_t *graph; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/mcore.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/mcore.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/mcore.c 2024-01-10 19:08:51 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/mcore.c 2024-01-12 11:54:13 @@ -40,7 +40,7 @@ /*! This function creates an mcore. This version is used for gkmcore. */ /*************************************************************************/ -gk_mcore_t *gk_gkmcoreCreate() +gk_mcore_t *gk_gkmcoreCreate(void) { gk_mcore_t *mcore; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/memory.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/memory.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/memory.c 2024-01-10 19:08:51 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/memory.c 2024-01-12 11:54:13 @@ -96,7 +96,7 @@ /*! This function initializes tracking of heap allocations. */ /*************************************************************************/ -int gk_malloc_init() +int gk_malloc_init(void) { #if 1 // Revised for SuiteSparse: do not create gkmcore: @@ -235,7 +235,7 @@ * This function returns the current ammount of dynamically allocated * memory that is used by the system **************************************************************************/ -size_t gk_GetCurMemoryUsed() +size_t gk_GetCurMemoryUsed(void) { if (gkmcore == NULL) return 0; @@ -248,7 +248,7 @@ * This function returns the maximum ammount of dynamically allocated * memory that was used by the system **************************************************************************/ -size_t gk_GetMaxMemoryUsed() +size_t gk_GetMaxMemoryUsed(void) { if (gkmcore == NULL) return 0; diff -ruN src/SuiteSparse/CHOLMOD/Supernodal/cholmod_super_numeric.c src/SuiteSparse-patched/CHOLMOD/Supernodal/cholmod_super_numeric.c --- src/SuiteSparse/CHOLMOD/Supernodal/cholmod_super_numeric.c 2024-01-10 19:08:51 +++ src/SuiteSparse-patched/CHOLMOD/Supernodal/cholmod_super_numeric.c 2024-01-12 11:54:13 @@ -82,15 +82,6 @@ #define ZOMPLEX #include "t_cholmod_super_numeric_worker.c" -#undef DOUBLE -#define SINGLE -#define REAL -#include "t_cholmod_super_numeric_worker.c" -#define COMPLEX -#include "t_cholmod_super_numeric_worker.c" -#define ZOMPLEX -#include "t_cholmod_super_numeric_worker.c" - //------------------------------------------------------------------------------ // cholmod_super_numeric //------------------------------------------------------------------------------ @@ -297,16 +288,16 @@ switch ((A->xtype + A->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: - ok = rs_cholmod_super_numeric_worker (A, F, s_beta, L, C, Common) ; + ok = FALSE ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: - ok = cs_cholmod_super_numeric_worker (A, F, s_beta, L, C, Common) ; + ok = FALSE ; break ; case CHOLMOD_ZOMPLEX + CHOLMOD_SINGLE: // A is zomplex, but L is complex - ok = zs_cholmod_super_numeric_worker (A, F, s_beta, L, C, Common) ; + ok = FALSE ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: diff -ruN src/SuiteSparse/CHOLMOD/Supernodal/cholmod_super_solve.c src/SuiteSparse-patched/CHOLMOD/Supernodal/cholmod_super_solve.c --- src/SuiteSparse/CHOLMOD/Supernodal/cholmod_super_solve.c 2024-01-10 19:08:51 +++ src/SuiteSparse-patched/CHOLMOD/Supernodal/cholmod_super_solve.c 2024-01-12 11:54:13 @@ -30,13 +30,6 @@ #define COMPLEX #include "t_cholmod_super_solve_worker.c" -#undef DOUBLE -#define SINGLE -#define REAL -#include "t_cholmod_super_solve_worker.c" -#define COMPLEX -#include "t_cholmod_super_solve_worker.c" - //------------------------------------------------------------------------------ // cholmod_super_lsolve: solve x=L\b //------------------------------------------------------------------------------ @@ -114,11 +107,11 @@ switch ((L->xtype + L->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: - rs_cholmod_super_lsolve_worker (L, X, E, Common) ; + return FALSE ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: - cs_cholmod_super_lsolve_worker (L, X, E, Common) ; + return FALSE ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: @@ -215,11 +208,11 @@ switch ((L->xtype + L->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: - rs_cholmod_super_ltsolve_worker (L, X, E, Common) ; + return FALSE ; break ; case CHOLMOD_COMPLEX + CHOLMOD_SINGLE: - cs_cholmod_super_ltsolve_worker (L, X, E, Common) ; + return FALSE ; break ; case CHOLMOD_REAL + CHOLMOD_DOUBLE: Matrix/inst/scripts/wall.patch0000644000175100001440000030673014575233601016177 0ustar hornikusersdiff -ruN src/SuiteSparse/CCOLAMD/Source/ccolamd.c src/SuiteSparse-patched/CCOLAMD/Source/ccolamd.c --- src/SuiteSparse/CCOLAMD/Source/ccolamd.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CCOLAMD/Source/ccolamd.c 2024-03-16 01:25:07 @@ -1545,7 +1545,9 @@ Int *dead_cols ; Int set1 ; Int set2 ; +#ifndef NDEBUG Int cs ; +#endif int ok ; @@ -1894,7 +1896,9 @@ p [k] = col ; ASSERT (A [col] == EMPTY) ; +#ifndef NDEBUG cs = CMEMBER (col) ; +#endif ASSERT (k >= cset_start [cs] && k < cset_start [cs+1]) ; A [col] = k ; @@ -1911,8 +1915,8 @@ if (A [col] == EMPTY) { k = Col [col].shared2.order ; - cs = CMEMBER (col) ; #ifndef NDEBUG + cs = CMEMBER (col) ; dead_cols [cs]-- ; #endif ASSERT (k >= cset_start [cs] && k < cset_start [cs+1]) ; diff -ruN src/SuiteSparse/CHOLMOD/Check/cholmod_check.c src/SuiteSparse-patched/CHOLMOD/Check/cholmod_check.c --- src/SuiteSparse/CHOLMOD/Check/cholmod_check.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Check/cholmod_check.c 2024-03-16 01:25:07 @@ -216,7 +216,6 @@ //-------------------------------------------------------------------------- RETURN_IF_NULL_COMMON (FALSE) ; - int init_print = print ; P2 ("%s", "\n") ; @@ -965,7 +964,7 @@ ) { void *Xx, *Xz ; - Int i, j, d, nrow, ncol, nzmax, nz, init_print, count ; + Int i, j, d, nrow, ncol, nzmax, init_print, count ; const char *type = "dense" ; //-------------------------------------------------------------------------- @@ -1034,7 +1033,6 @@ { init_print = print ; ETC_START (count, 9) ; - nz = nrow * ncol ; for (j = 0 ; j < ncol ; j++) { ETC (j == ncol-1, count, 5) ; @@ -1487,10 +1485,10 @@ void *Lx, *Lz ; Int *Lp, *Li, *Lnz, *Lnext, *Lprev, *Perm, *ColCount, *Lpi, *Lpx, *Super, *Ls ; - Int n, nzmax, j, p, pend, i, nz, ordering, space, is_monotonic, minor, - count, precise, init_print, ilast, lnz, head, tail, jprev, plast, - jnext, examine_super, nsuper, s, k1, k2, psi, psend, psx, nsrow, nscol, - ps2, psxend, ssize, xsize, maxcsize, maxesize, nsrow2, jj, ii ; + Int n, nzmax, j, p, pend, i, nz, space, is_monotonic, minor, + count, init_print, ilast, lnz, head, tail, jprev, plast, + jnext, examine_super, nsuper, s, k1, k2, psi, psend, psx = 0, nsrow, nscol, + psxend, ssize, xsize, maxcsize, maxesize, nsrow2, jj, ii ; Int check_Lpx ; const char *type = "factor" ; @@ -1512,7 +1510,6 @@ n = L->n ; minor = L->minor ; - ordering = L->ordering ; int xtype = L->xtype ; int dtype = L->dtype ; @@ -1520,8 +1517,6 @@ ColCount = L->ColCount ; lnz = 0 ; - precise = Common->precise ; - P3 (" "ID"", n) ; P3 ("-by-"ID"", n) ; @@ -1896,7 +1891,6 @@ nsrow = psend - psi ; nscol = k2 - k1 ; nsrow2 = nsrow - nscol ; - ps2 = psi + nscol ; if (check_Lpx) { diff -ruN src/SuiteSparse/CHOLMOD/Check/cholmod_write.c src/SuiteSparse-patched/CHOLMOD/Check/cholmod_write.c --- src/SuiteSparse/CHOLMOD/Check/cholmod_write.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Check/cholmod_write.c 2024-03-16 01:25:07 @@ -354,7 +354,7 @@ double x = 0, z = 0 ; void *Ax, *Az ; Int *Ap, *Ai, *Anz, *Zp, *Zi, *Znz ; - Int nrow, ncol, is_complex, symmetry, i, j, q, iz, p, nz, is_binary, stype, + Int nrow, ncol, is_complex, i, j, q, iz, p, nz, is_binary, stype, is_integer, asym, is_sym, apacked, zpacked, pend, qend, zsym ; int ok, xtype, dtype ; @@ -527,7 +527,6 @@ // A is rectangular or unsymmetric ok = ok && (fprintf (f, " general\n") > 0) ; is_sym = FALSE ; - symmetry = CHOLMOD_MM_UNSYMMETRIC ; break ; case CHOLMOD_MM_SYMMETRIC: @@ -535,7 +534,6 @@ // A is symmetric ok = ok && (fprintf (f, " symmetric\n") > 0) ; is_sym = TRUE ; - symmetry = CHOLMOD_MM_SYMMETRIC ; break ; case CHOLMOD_MM_HERMITIAN: @@ -543,14 +541,12 @@ // A is Hermitian ok = ok && (fprintf (f, " Hermitian\n") > 0) ; is_sym = TRUE ; - symmetry = CHOLMOD_MM_HERMITIAN ; break ; case CHOLMOD_MM_SKEW_SYMMETRIC: // A is skew symmetric ok = ok && (fprintf (f, " skew-symmetric\n") > 0) ; is_sym = TRUE ; - symmetry = CHOLMOD_MM_SKEW_SYMMETRIC ; break ; } diff -ruN src/SuiteSparse/CHOLMOD/Cholesky/cholmod_analyze.c src/SuiteSparse-patched/CHOLMOD/Cholesky/cholmod_analyze.c --- src/SuiteSparse/CHOLMOD/Cholesky/cholmod_analyze.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Cholesky/cholmod_analyze.c 2024-03-16 01:25:07 @@ -399,7 +399,7 @@ Int *First, *Level, *Work4n, *Cmember, *CParent, *ColCount, *Lperm, *Parent, *Post, *Perm, *Lparent, *Lcolcount ; cholmod_factor *L ; - Int k, n, method, nmethods, status, default_strategy, ncol, + Int k, n, method, nmethods, status, default_strategy, skip_analysis, skip_best ; Int amd_backup ; int ok = TRUE ; @@ -421,7 +421,6 @@ //-------------------------------------------------------------------------- n = A->nrow ; - ncol = A->ncol ; //-------------------------------------------------------------------------- // set the default strategy diff -ruN src/SuiteSparse/CHOLMOD/Cholesky/cholmod_factorize.c src/SuiteSparse-patched/CHOLMOD/Cholesky/cholmod_factorize.c --- src/SuiteSparse/CHOLMOD/Cholesky/cholmod_factorize.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Cholesky/cholmod_factorize.c 2024-03-16 01:25:07 @@ -104,7 +104,7 @@ { cholmod_sparse *S, *F, *A1, *A2 ; - Int nrow, ncol, stype, convert, n, grow2, status ; + Int nrow, ncol, stype, convert, grow2, status ; int ok = TRUE ; //-------------------------------------------------------------------------- @@ -118,7 +118,6 @@ RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; nrow = A->nrow ; ncol = A->ncol ; - n = L->n ; stype = A->stype ; if (L->n != A->nrow) { diff -ruN src/SuiteSparse/CHOLMOD/Cholesky/cholmod_resymbol.c src/SuiteSparse-patched/CHOLMOD/Cholesky/cholmod_resymbol.c --- src/SuiteSparse/CHOLMOD/Cholesky/cholmod_resymbol.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Cholesky/cholmod_resymbol.c 2024-03-16 01:25:07 @@ -102,8 +102,6 @@ //-------------------------------------------------------------------------- Int stype = A->stype ; - Int nrow = A->nrow ; - Int ncol = A->ncol ; // s = 2*nrow + (stype ? 0 : ncol) int ok = TRUE ; diff -ruN src/SuiteSparse/CHOLMOD/Cholesky/cholmod_solve.c src/SuiteSparse-patched/CHOLMOD/Cholesky/cholmod_solve.c --- src/SuiteSparse/CHOLMOD/Cholesky/cholmod_solve.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Cholesky/cholmod_solve.c 2024-03-16 01:25:07 @@ -203,8 +203,8 @@ cholmod_dense *Y = NULL, *X = NULL ; cholmod_sparse *C, *Yset, C_header, Yset_header, *Xset ; Int *Perm = NULL, *IPerm = NULL ; - Int n, nrhs, ncols, k1, nr, ytype, k, blen, p, i, d, nrow ; - Int Cp [2], Ysetp [2], *Ci, *Yseti, ysetlen ; + Int n, nrhs, ncols, k1, nr, ytype, k, blen, p, d, nrow ; + Int Cp [2], Ysetp [2], *Ci, *Yseti ; RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (L, FALSE) ; diff -ruN src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_psolve_worker.c src/SuiteSparse-patched/CHOLMOD/Cholesky/t_cholmod_psolve_worker.c --- src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_psolve_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Cholesky/t_cholmod_psolve_worker.c 2024-03-16 01:25:07 @@ -265,12 +265,17 @@ //-------------------------------------------------------------------------- Real *Yx, *Yz, *Xx, *Xz ; - Int k2, nk, p, k, j, nrow, ncol, d, dj, j2 ; + Int k2, p, k, j, nrow, ncol, d, dj, j2 ; +#ifndef NDEBUG + Int nk ; +#endif ncol = X->ncol ; nrow = X->nrow ; k2 = MIN (k1+ncols, ncol) ; +#ifndef NDEBUG nk = MAX (k2 - k1, 0) ; +#endif d = X->d ; Xx = X->x ; Xz = X->z ; diff -ruN src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_resymbol_worker.c src/SuiteSparse-patched/CHOLMOD/Cholesky/t_cholmod_resymbol_worker.c --- src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_resymbol_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Cholesky/t_cholmod_resymbol_worker.c 2024-03-16 01:25:07 @@ -29,12 +29,13 @@ Int *Ap = A->p ; Int *Anz = A->nz ; bool apacked = A->packed ; - bool sorted = A->sorted ; int stype = A->stype ; Int *Li = L->i ; Real *Lx = L->x ; +#ifdef ZOMPLEX Real *Lz = L->z ; +#endif Int *Lp = L->p ; Int *Lnz = L->nz ; diff -ruN src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_rowfac_worker.c src/SuiteSparse-patched/CHOLMOD/Cholesky/t_cholmod_rowfac_worker.c --- src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_rowfac_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Cholesky/t_cholmod_rowfac_worker.c 2024-03-16 01:25:07 @@ -49,11 +49,14 @@ #ifdef ZOMPLEX Real yz [1], lz [1], fz [1] ; #endif - Real *Ax, *Az, *Lx, *Lz, *Wx, *Wz, *Fx, *Fz ; + Real *Ax, *Lx, *Wx, *Fx ; +#ifdef ZOMPLEX + Real *Az, *Lz, *Wz, *Fz ; +#endif Int *Ap, *Anz, *Ai, *Lp, *Lnz, *Li, *Lnext, *Flag, *Stack, *Fp, *Fi, *Fnz, *Iwork ; Int i, p, k, t, pf, pfend, top, s, mark, pend, n, lnz, is_ll, multadds, - use_bound, packed, stype, Fpacked, sorted, nzmax, len, parent ; + use_bound, packed, stype, Fpacked, sorted, len, parent ; #ifndef REAL Int dk_imaginary ; #endif @@ -71,7 +74,9 @@ Fp = NULL ; Fi = NULL ; Fx = NULL ; +#ifdef ZOMPLEX Fz = NULL ; +#endif Fnz = NULL ; Fpacked = TRUE ; } @@ -81,7 +86,9 @@ Fp = F->p ; Fi = F->i ; Fx = F->x ; +#ifdef ZOMPLEX Fz = F->z ; +#endif Fnz = F->nz ; Fpacked = F->packed ; } @@ -89,7 +96,9 @@ Ap = A->p ; // size A->ncol+1, column pointers of A Ai = A->i ; // size nz = Ap [A->ncol], row indices of A Ax = A->x ; // size nz, numeric values of A +#ifdef ZOMPLEX Az = A->z ; +#endif Anz = A->nz ; packed = A->packed ; sorted = A->sorted ; @@ -153,8 +162,9 @@ Lnext = L->next ; // size n+2 Li = L->i ; // size L->nzmax, can change in size Lx = L->x ; // size L->nzmax or 2*L->nzmax, can change in size +#ifdef ZOMPLEX Lz = L->z ; // size L->nzmax for zomplex case, can change in size - nzmax = L->nzmax ; +#endif ASSERT (Lnz != NULL && Li != NULL && Lx != NULL) ; //-------------------------------------------------------------------------- @@ -166,9 +176,13 @@ Flag = Common->Flag ; // size n, Flag [i] < mark must hold Wx = Common->Xwork ; // size n if real, 2*n if complex or // zomplex. Xwork [i] == 0 must hold. +#ifdef ZOMPLEX Wz = Wx + n ; // size n for zomplex case only +#endif mark = Common->mark ; +#ifndef NDEBUG size_t wsize = (L->xtype == CHOLMOD_REAL ? 1:2) * ((size_t) n) ; +#endif ASSERT (Common->xworkbytes >= wsize * sizeof (Real)) ; //-------------------------------------------------------------------------- @@ -388,7 +402,9 @@ } Li = L->i ; // L->i, L->x, L->z may have moved Lx = L->x ; +#ifdef ZOMPLEX Lz = L->z ; +#endif p = Lp [i] + lnz ; // contents of L->p changed ASSERT (p < Lp [Lnext [i]]) ; } diff -ruN src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_solve_worker.c src/SuiteSparse-patched/CHOLMOD/Cholesky/t_cholmod_solve_worker.c --- src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_solve_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Cholesky/t_cholmod_solve_worker.c 2024-03-16 01:25:07 @@ -70,7 +70,9 @@ Int *Lp = L->p ; Real *Lx = L->x ; Real *Yx = Y->x ; +#ifdef ZOMPLEX Real *Yz = Y->z ; +#endif if (Yset) { @@ -209,7 +211,9 @@ //-------------------------------------------------------------------------- Real *Yx = Y->x ; +#ifdef ZOMPLEX Real *Yz = Y->z ; +#endif Int *Ysetp = Yset->p ; Int *Yseti = Yset->i ; Int ysetlen = Ysetp [1] ; @@ -227,7 +231,9 @@ // Y (C) = B (Bset) Real *Bx = B->x ; +#ifdef ZOMPLEX Real *Bz = B->z ; +#endif Int *Bsetp = Bset->p ; Int *Bseti = Bset->i ; Int *Bsetnz = Bset->nz ; @@ -262,12 +268,16 @@ { Real *Xx = X->x ; +#ifdef ZOMPLEX Real *Xz = X->z ; +#endif Int *Xseti = Xset->i ; Int *Xsetp = Xset->p ; Real *Yx = Y->x ; +#ifdef ZOMPLEX Real *Yz = Y->z ; +#endif Int *Ysetp = Yset->p ; Int *Yseti = Yset->i ; diff -ruN src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_spsolve_worker.c src/SuiteSparse-patched/CHOLMOD/Cholesky/t_cholmod_spsolve_worker.c --- src/SuiteSparse/CHOLMOD/Cholesky/t_cholmod_spsolve_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Cholesky/t_cholmod_spsolve_worker.c 2024-03-16 01:25:07 @@ -30,12 +30,16 @@ Int *Bp = B->p ; Int *Bi = B->i ; Real *Bx = B->x ; +#ifdef ZOMPLEX Real *Bz = B->z ; +#endif Int *Bnz = B->nz ; bool packed = B->packed ; Real *B4x = B4->x ; +#ifdef ZOMPLEX Real *B4z = B4->z ; +#endif Int n = B4->nrow ; @@ -78,13 +82,17 @@ Int *Xp = X->p ; Int *Xi = X->i ; Real *Xx = X->x ; +#ifdef ZOMPLEX Real *Xz = X->z ; +#endif size_t px = (*xnz) ; size_t nzmax = X->nzmax ; Real *X4x = X4->x ; +#ifdef ZOMPLEX Real *X4z = X4->z ; +#endif Int n = X4->nrow ; //-------------------------------------------------------------------------- @@ -139,7 +147,9 @@ } Xi = X->i ; Xx = X->x ; +#ifdef ZOMPLEX Xz = X->z ; +#endif } Xi [px] = i ; ASSIGN (Xx, Xz, px, X4x, X4z, p) ; @@ -180,7 +190,9 @@ bool packed = B->packed ; Real *B4x = B4->x ; +#ifdef ZOMPLEX Real *B4z = B4->z ; +#endif Int n = B4->nrow ; diff -ruN src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_ssmult.c src/SuiteSparse-patched/CHOLMOD/MatrixOps/cholmod_ssmult.c --- src/SuiteSparse/CHOLMOD/MatrixOps/cholmod_ssmult.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/MatrixOps/cholmod_ssmult.c 2024-03-16 01:25:07 @@ -84,7 +84,7 @@ // check inputs //-------------------------------------------------------------------------- - cholmod_sparse *C = NULL, *A2 = NULL, *B2 = NULL, *C2 = NULL ; + cholmod_sparse *C = NULL, *A2 = NULL, *B2 = NULL ; RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_NULL (A, NULL) ; @@ -196,7 +196,6 @@ Int ncol = B->ncol ; // get workspace - void *W = Common->Xwork ; // size nrow, unused if values is false Int *Flag = Common->Flag ; // size nrow, Flag [0..nrow-1] < mark on input //-------------------------------------------------------------------------- diff -ruN src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_drop_worker.c src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_drop_worker.c --- src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_drop_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_drop_worker.c 2024-03-16 01:25:07 @@ -59,7 +59,9 @@ Int *Ap = A->p ; Int *Ai = A->i ; Real *Ax = A->x ; +#ifdef ZOMPLEX Real *Az = A->z ; +#endif Int *Anz = A->nz ; bool packed = A->packed ; Int ncol = A->ncol ; diff -ruN src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_horzcat_worker.c src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_horzcat_worker.c --- src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_horzcat_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_horzcat_worker.c 2024-03-16 01:25:07 @@ -25,23 +25,35 @@ Int *Ap = A->p ; Int *Anz = A->nz ; Int *Ai = A->i ; +#ifndef PATTERN Real *Ax = A->x ; +#ifdef ZOMPLEX Real *Az = A->z ; +#endif +#endif bool apacked = A->packed ; Int ancol = A->ncol ; Int *Bp = B->p ; Int *Bnz = B->nz ; Int *Bi = B->i ; +#ifndef PATTERN Real *Bx = B->x ; +#ifdef ZOMPLEX Real *Bz = B->z ; +#endif +#endif bool bpacked = B->packed ; Int bncol = B->ncol ; Int *Cp = C->p ; Int *Ci = C->i ; +#ifndef PATTERN Real *Cx = C->x ; +#ifdef ZOMPLEX Real *Cz = C->z ; +#endif +#endif Int ncol = C->ncol ; //-------------------------------------------------------------------------- diff -ruN src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_norm_worker.c src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_norm_worker.c --- src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_norm_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_norm_worker.c 2024-03-16 01:25:07 @@ -36,7 +36,9 @@ Int nrow = X->nrow ; Int d = X->d ; Real *Xx = X->x ; +#ifdef ZOMPLEX Real *Xz = X->z ; +#endif double xnorm = 0 ; @@ -158,8 +160,12 @@ Int *Ap = A->p ; Int *Ai = A->i ; Int *Anz = A->nz ; +#ifndef PATTERN Real *Ax = A->x ; +#ifdef ZOMPLEX Real *Az = A->z ; +#endif +#endif Int ncol = A->ncol ; Int nrow = A->nrow ; bool packed = A->packed ; diff -ruN src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_scale_worker.c src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_scale_worker.c --- src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_scale_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_scale_worker.c 2024-03-16 01:25:07 @@ -28,12 +28,16 @@ Int *Anz = A->nz ; Int *Ai = A->i ; Real *Ax = A->x ; +#ifdef ZOMPLEX Real *Az = A->z ; +#endif bool packed = A->packed ; Int ncol = A->ncol ; Real *Sx = S->x ; +#ifdef ZOMPLEX Real *Sz = S->z ; +#endif //-------------------------------------------------------------------------- // scale the matrix @@ -55,7 +59,9 @@ Int i = Ai [p] ; // t = S (i) * A (i,j) Real tx [2] ; +#ifdef ZOMPLEX Real tz [1] ; +#endif MULT (tx, tz, 0, Sx, Sz, i, Ax, Az, p) ; // A (i,j) = t ASSIGN (Ax, Az, p, tx, tz, 0) ; @@ -74,7 +80,9 @@ { // s = S (j) Real sx [2] ; +#ifdef ZOMPLEX Real sz [1] ; +#endif ASSIGN (sx, sz, 0, Sx, Sz, j) ; Int p = Ap [j] ; @@ -83,7 +91,9 @@ { // t = A (i,j) * s Real tx [2] ; +#ifdef ZOMPLEX Real tz [1] ; +#endif MULT (tx, tz, 0, Ax, Az, p, sx, sz, 0) ; // A (i,j) = t ASSIGN (Ax, Az, p, tx, tz, 0) ; @@ -102,7 +112,9 @@ { // s = S (j) Real sx [2] ; +#ifdef ZOMPLEX Real sz [1] ; +#endif ASSIGN (sx, sz, 0, Sx, Sz, j) ; Int p = Ap [j] ; @@ -112,7 +124,9 @@ Int i = Ai [p] ; // t = A (i,j) * S (i) Real tx [2] ; +#ifdef ZOMPLEX Real tz [1] ; +#endif MULT (tx, tz, 0, Ax, Az, p, Sx, Sz, i) ; // A (i,j) = s * t MULT (Ax, Az, p, sx, sz, 0, tx, tz, 0) ; @@ -129,7 +143,9 @@ // s = S (0) Real sx [2] ; +#ifdef ZOMPLEX Real sz [1] ; +#endif ASSIGN (sx, sz, 0, Sx, Sz, 0) ; for (Int j = 0 ; j < ncol ; j++) @@ -140,7 +156,9 @@ { // t = s * A (i,j) Real tx [2] ; +#ifdef ZOMPLEX Real tz [1] ; +#endif MULT (tx, tz, 0, sx, sz, 0, Ax, Az, p) ; // A (i,j) = t ASSIGN (Ax, Az, p, tx, tz, 0) ; diff -ruN src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_sdmult_worker.c src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_sdmult_worker.c --- src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_sdmult_worker.c 2024-03-16 01:30:04 +++ src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_sdmult_worker.c 2024-03-16 01:25:07 @@ -55,28 +55,37 @@ #endif size_t ny = transpose ? A->ncol : A->nrow ; // required length of Y +#ifdef ZOMPLEX size_t nx = transpose ? A->nrow : A->ncol ; // required length of X +#endif - Int nrow = A->nrow ; Int ncol = A->ncol ; Int *Ap = A->p ; Int *Anz = A->nz ; Int *Ai = A->i ; Real *Ax = A->x ; +#ifdef ZOMPLEX Real *Az = A->z ; +#endif bool packed = A->packed ; Real *Xx = X->x ; +#ifdef ZOMPLEX Real *Xz = X->z ; +#endif Real *Yx = Y->x ; +#ifdef ZOMPLEX Real *Yz = Y->z ; +#endif Int kcol = X->ncol ; size_t dy = Y->d ; size_t dx = X->d ; Real *w = W ; +#ifdef ZOMPLEX Real *Wz = (W) ? W + 4*nx : W ; +#endif //-------------------------------------------------------------------------- // Y = beta * Y @@ -120,7 +129,9 @@ //-------------------------------------------------------------------------- Yx = Y->x ; +#ifdef ZOMPLEX Yz = Y->z ; +#endif Int k = 0 ; if (A->stype == 0) diff -ruN src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_ssmult_worker.c src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_ssmult_worker.c --- src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_ssmult_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_ssmult_worker.c 2024-03-16 01:25:07 @@ -23,35 +23,51 @@ // get inputs //-------------------------------------------------------------------------- - Real *W = Common->Xwork ; - Int *Ap = A->p ; Int *Anz = A->nz ; Int *Ai = A->i ; +#ifndef PATTERN Real *Ax = A->x ; +#ifdef ZOMPLEX Real *Az = A->z ; +#endif +#endif bool apacked = A->packed ; Int *Bp = B->p ; Int *Bnz = B->nz ; Int *Bi = B->i ; +#ifndef PATTERN Real *Bx = B->x ; +#ifdef ZOMPLEX Real *Bz = B->z ; +#endif +#endif bool bpacked = B->packed ; // get the size of C +#ifdef ZOMPLEX Int nrow = A->nrow ; +#endif Int ncol = B->ncol ; // get workspace +#ifndef PATTERN Real *Wx = Common->Xwork ; // size nrow, unused if C is pattern +#ifdef ZOMPLEX Real *Wz = Wx + nrow ; // only used for the zomplex case +#endif +#endif Int *Flag = Common->Flag ; // size nrow, Flag [0..nrow-1] < mark on input Int *Cp = C->p ; Int *Ci = C->i ; +#ifndef PATTERN Real *Cx = C->x ; +#ifdef ZOMPLEX Real *Cz = C->z ; +#endif +#endif //-------------------------------------------------------------------------- // C = A*B @@ -77,8 +93,12 @@ Int k = Bi [pb] ; // b = Bx [pb] ; +#ifndef PATTERN Real bx [2] ; +#ifdef ZOMPLEX Real bz [1] ; +#endif +#endif ASSIGN (bx, bz, 0, Bx, Bz, pb) ; // add the nonzero pattern of A(:,k) to the pattern of C(:,j) diff -ruN src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_submatrix_worker.c src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_submatrix_worker.c --- src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_submatrix_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_submatrix_worker.c 2024-03-16 01:25:07 @@ -29,14 +29,22 @@ Int *Ap = A->p ; Int *Ai = A->i ; Int *Anz = A->nz ; +#ifndef PATTERN Real *Ax = A->x ; +#ifdef ZOMPLEX Real *Az = A->z ; +#endif +#endif bool packed = A->packed ; Int *Cp = C->p ; Int *Ci = C->i ; +#ifndef PATTERN Real *Cx = C->x ; +#ifdef ZOMPLEX Real *Cz = C->z ; +#endif +#endif Int cncol = C->ncol ; //-------------------------------------------------------------------------- diff -ruN src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_vertcat_worker.c src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_vertcat_worker.c --- src/SuiteSparse/CHOLMOD/MatrixOps/t_cholmod_vertcat_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/MatrixOps/t_cholmod_vertcat_worker.c 2024-03-16 01:25:07 @@ -25,22 +25,34 @@ Int *Ap = A->p ; Int *Anz = A->nz ; Int *Ai = A->i ; +#ifndef PATTERN Real *Ax = A->x ; +#ifdef ZOMPLEX Real *Az = A->z ; +#endif +#endif bool apacked = A->packed ; Int anrow = A->nrow ; Int *Bp = B->p ; Int *Bnz = B->nz ; Int *Bi = B->i ; +#ifndef PATTERN Real *Bx = B->x ; +#ifdef ZOMPLEX Real *Bz = B->z ; +#endif +#endif bool bpacked = B->packed ; Int *Cp = C->p ; Int *Ci = C->i ; +#ifndef PATTERN Real *Cx = C->x ; +#ifdef ZOMPLEX Real *Cz = C->z ; +#endif +#endif Int ncol = C->ncol ; //-------------------------------------------------------------------------- diff -ruN src/SuiteSparse/CHOLMOD/Modify/cholmod_rowadd.c src/SuiteSparse-patched/CHOLMOD/Modify/cholmod_rowadd.c --- src/SuiteSparse/CHOLMOD/Modify/cholmod_rowadd.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Modify/cholmod_rowadd.c 2024-03-16 01:25:07 @@ -136,7 +136,6 @@ RETURN_IF_NULL (R, FALSE) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_REAL, FALSE) ; RETURN_IF_XTYPE_INVALID (R, CHOLMOD_REAL, CHOLMOD_REAL, FALSE) ; - Int n = L->n ; Int k = kadd ; if (kadd >= L->n || k < 0) { diff -ruN src/SuiteSparse/CHOLMOD/Modify/cholmod_rowdel.c src/SuiteSparse-patched/CHOLMOD/Modify/cholmod_rowdel.c --- src/SuiteSparse/CHOLMOD/Modify/cholmod_rowdel.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Modify/cholmod_rowdel.c 2024-03-16 01:25:07 @@ -122,7 +122,6 @@ RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (L, FALSE) ; RETURN_IF_XTYPE_INVALID (L, CHOLMOD_PATTERN, CHOLMOD_REAL, FALSE) ; - Int n = L->n ; Int k = kdel ; if (kdel >= L->n || k < 0) { diff -ruN src/SuiteSparse/CHOLMOD/Modify/t_cholmod_updown_worker.c src/SuiteSparse-patched/CHOLMOD/Modify/t_cholmod_updown_worker.c --- src/SuiteSparse/CHOLMOD/Modify/t_cholmod_updown_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Modify/t_cholmod_updown_worker.c 2024-03-16 01:25:07 @@ -148,7 +148,9 @@ double fl = 0 ; bool use_colmark = (colmark != NULL) ; +#ifndef NDEBUG Int *ps1 = NULL ; +#endif Int *ps2 = NULL ; //-------------------------------------------------------------------------- @@ -699,7 +701,9 @@ if (nsets > 0) { +#ifndef NDEBUG ps1 = Set_ps1 [0] ; +#endif ps2 = Set_ps2 [0] ; } diff -ruN src/SuiteSparse/CHOLMOD/Partition/cholmod_metis.c src/SuiteSparse-patched/CHOLMOD/Partition/cholmod_metis.c --- src/SuiteSparse/CHOLMOD/Partition/cholmod_metis.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Partition/cholmod_metis.c 2024-03-16 01:25:07 @@ -578,7 +578,7 @@ idx_t *Mp, *Mi, *Mperm, *Miperm ; cholmod_sparse *B ; Int i, j, n, nz, p, identity ; - idx_t nn, zero = 0 ; + idx_t nn ; RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; diff -ruN src/SuiteSparse/CHOLMOD/Partition/cholmod_nesdis.c src/SuiteSparse-patched/CHOLMOD/Partition/cholmod_nesdis.c --- src/SuiteSparse/CHOLMOD/Partition/cholmod_nesdis.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Partition/cholmod_nesdis.c 2024-03-16 01:25:07 @@ -681,8 +681,11 @@ ) { - Int n, mark, cj, j, sj, sn, p, i, snode, pstart, pdest, pend, nd_components, + Int mark, cj, j, sj, sn, p, i, snode, pstart, pdest, pend, nd_components, part, first, save_mark ; +#ifndef NDEBUG + Int n ; +#endif Int *Bp, *Bi, *Flag ; //-------------------------------------------------------------------------- @@ -702,7 +705,9 @@ Bp = B->p ; Bi = B->i ; +#ifndef NDEBUG n = B->nrow ; +#endif ASSERT (cnode >= EMPTY && cnode < n) ; ASSERT (IMPLIES (cnode >= 0, Flag [cnode] < EMPTY)) ; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_mkpqueue.h src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/gk_mkpqueue.h --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/gk_mkpqueue.h 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/gk_mkpqueue.h 2024-03-16 01:25:07 @@ -11,6 +11,38 @@ #ifndef _GK_MKPQUEUE_H #define _GK_MKPQUEUE_H +#ifndef NDEBUG +#define DO_CHECKHEAP\ +do {\ + gk_idx_t i, j;\ + size_t nnodes;\ + gk_idx_t *locator;\ + KVT *heap;\ +\ + heap = queue->heap;\ + locator = queue->locator;\ + nnodes = queue->nnodes;\ +\ + if (nnodes == 0)\ + return 1;\ +\ + ASSERT(locator[heap[0].val] == 0);\ + for (i=1; imaxnodes; i++) {\ + if (locator[i] != -1)\ + j++;\ + }\ + ASSERTP(j == nnodes, ("%jd %jd\n", (intmax_t)j, (intmax_t)nnodes));\ +} while (0) +#else +#define DO_CHECKHEAP +#endif #define GK_MKPQUEUE(FPRFX, PQT, KVT, KT, VT, KVMALLOC, KMAX, KEY_LT)\ /*************************************************************************/\ @@ -380,32 +412,7 @@ /**************************************************************************/\ int FPRFX ## CheckHeap(PQT *queue)\ {\ - gk_idx_t i, j;\ - size_t nnodes;\ - gk_idx_t *locator;\ - KVT *heap;\ -\ - heap = queue->heap;\ - locator = queue->locator;\ - nnodes = queue->nnodes;\ -\ - if (nnodes == 0)\ - return 1;\ -\ - ASSERT(locator[heap[0].val] == 0);\ - for (i=1; imaxnodes; i++) {\ - if (locator[i] != -1)\ - j++;\ - }\ - ASSERTP(j == nnodes, ("%jd %jd\n", (intmax_t)j, (intmax_t)nnodes));\ -\ + DO_CHECKHEAP;\ return 1;\ }\ diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/mcore.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/mcore.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/mcore.c 2024-03-16 01:30:04 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/mcore.c 2024-03-16 01:28:20 @@ -71,6 +71,7 @@ if (mcore == NULL) return; +#ifndef NDEBUG if (showstats) printf("\n gk_mcore statistics\n" " coresize: %12zu nmops: %12zu cmop: %6zu\n" @@ -89,6 +90,7 @@ " cur_callocs: %6zu cur_hallocs: %6zu cmop: %6zu\n", mcore->cur_callocs, mcore->cur_hallocs, mcore->cmop); } +#endif gk_free((void **)&mcore->core, &mcore->mops, &mcore, LTERM); @@ -107,6 +109,7 @@ if (mcore == NULL) return; +#ifndef NDEBUG if (showstats) printf("\n gk_mcore statistics\n" " nmops: %12zu cmop: %6zu\n" @@ -125,6 +128,7 @@ " cur_hallocs: %6zu cmop: %6zu\n", mcore->cur_hallocs, mcore->cmop); } +#endif free(mcore->mops); free(mcore); diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/memory.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/memory.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/GKlib/memory.c 2024-03-16 01:30:04 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/GKlib/memory.c 2024-03-16 01:28:20 @@ -152,8 +152,10 @@ ptr = (void *)malloc(nbytes); if (ptr == NULL) { +#ifndef NDEBUG fprintf(stderr, " Current memory used: %10zu bytes\n", gk_GetCurMemoryUsed()); fprintf(stderr, " Maximum memory used: %10zu bytes\n", gk_GetMaxMemoryUsed()); +#endif gk_errexit(SIGMEM, "***Memory allocation failed for %s. Requested size: %zu bytes", msg, nbytes); return NULL; @@ -187,8 +189,10 @@ ptr = (void *)realloc(oldptr, nbytes); if (ptr == NULL) { +#ifndef NDEBUG fprintf(stderr, " Maximum memory used: %10zu bytes\n", gk_GetMaxMemoryUsed()); fprintf(stderr, " Current memory used: %10zu bytes\n", gk_GetCurMemoryUsed()); +#endif gk_errexit(SIGMEM, "***Memory realloc failed for %s. " "Requested size: %zu bytes", msg, nbytes); return NULL; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/balance.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/balance.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/balance.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/balance.c 2024-03-16 01:25:07 @@ -40,7 +40,7 @@ **************************************************************************/ void Bnd2WayBalance(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts) { - idx_t i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, pass, me, tmp; + idx_t i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, tmp; idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *id, *ed, *bndptr, *bndind, *pwgts; idx_t *moved, *perm; rpq_t *queue; @@ -168,7 +168,7 @@ **************************************************************************/ void General2WayBalance(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts) { - idx_t i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, pass, me, tmp; + idx_t i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, tmp; idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *id, *ed, *bndptr, *bndind, *pwgts; idx_t *moved, *perm; rpq_t *queue; @@ -280,8 +280,8 @@ **************************************************************************/ void McGeneral2WayBalance(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts) { - idx_t i, ii, j, k, l, kwgt, nvtxs, ncon, nbnd, nswaps, from, to, pass, - me, limit, tmp, cnum; + idx_t i, ii, j, k, l, kwgt, nvtxs, ncon, nbnd, nswaps, from, to, + limit, tmp, cnum; idx_t *xadj, *adjncy, *vwgt, *adjwgt, *where, *pwgts, *id, *ed, *bndptr, *bndind; idx_t *moved, *swaps, *perm, *qnum, *qsizes; idx_t higain, mincut, newcut, mincutorder; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/coarsen.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/coarsen.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/coarsen.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/coarsen.c 2024-03-16 01:25:07 @@ -21,7 +21,7 @@ /*************************************************************************/ graph_t *CoarsenGraph(ctrl_t *ctrl, graph_t *graph) { - idx_t i, eqewgts, level=0; + idx_t i, eqewgts; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->CoarsenTmr)); @@ -62,7 +62,6 @@ graph = graph->coarser; eqewgts = 0; - level++; ASSERT(CheckGraph(graph, 0, 1)); @@ -148,8 +147,8 @@ /**************************************************************************/ idx_t Match_RM(ctrl_t *ctrl, graph_t *graph) { - idx_t i, pi, ii, j, jj, jjinc, k, nvtxs, ncon, cnvtxs, maxidx, last_unmatched; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *maxvwgt; + idx_t i, pi, j, k, nvtxs, ncon, cnvtxs, maxidx, last_unmatched; + idx_t *xadj, *vwgt, *adjncy, *maxvwgt; idx_t *match, *cmap, *perm; size_t nunmatched=0; @@ -162,7 +161,6 @@ xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; - adjwgt = graph->adjwgt; cmap = graph->cmap; maxvwgt = ctrl->maxvwgt; @@ -275,7 +273,7 @@ /**************************************************************************/ idx_t Match_SHEM(ctrl_t *ctrl, graph_t *graph) { - idx_t i, pi, ii, j, jj, jjinc, k, nvtxs, ncon, cnvtxs, maxidx, maxwgt, + idx_t i, pi, j, k, nvtxs, ncon, cnvtxs, maxidx, maxwgt, last_unmatched, avgdegree; idx_t *xadj, *vwgt, *adjncy, *adjwgt, *maxvwgt; idx_t *match, *cmap, *degrees, *perm, *tperm; @@ -437,7 +435,7 @@ idx_t Match_2HopAny(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match, idx_t cnvtxs, size_t *r_nunmatched, size_t maxdegree) { - idx_t i, pi, ii, j, jj, k, nvtxs; + idx_t i, pi, j, jj, nvtxs; idx_t *xadj, *adjncy, *colptr, *rowind; idx_t *cmap; size_t nunmatched; @@ -516,7 +514,7 @@ idx_t Match_2HopAll(ctrl_t *ctrl, graph_t *graph, idx_t *perm, idx_t *match, idx_t cnvtxs, size_t *r_nunmatched, size_t maxdegree) { - idx_t i, pi, pk, ii, j, jj, k, nvtxs, mask, idegree; + idx_t i, pi, pk, j, jj, k, nvtxs, mask, idegree; idx_t *xadj, *adjncy; idx_t *cmap, *mark; ikv_t *keys; @@ -621,7 +619,7 @@ void CreateCoarseGraph(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs, idx_t *match) { - idx_t j, jj, k, kk, l, m, istart, iend, nvtxs, nedges, ncon, cnedges, + idx_t j, jj, k, kk, m, istart, iend, nvtxs, nedges, ncon, cnedges, v, u, mask, dovsize; idx_t *xadj, *vwgt, *vsize, *adjncy, *adjwgt; idx_t *cmap, *htable; @@ -932,7 +930,7 @@ void CreateCoarseGraphPerm(ctrl_t *ctrl, graph_t *graph, idx_t cnvtxs, idx_t *match, idx_t *perm) { - idx_t i, j, jj, k, kk, l, m, istart, iend, nvtxs, nedges, ncon, cnedges, + idx_t i, j, jj, k, kk, m, istart, iend, nvtxs, nedges, ncon, cnedges, v, u, mask, dovsize; idx_t *xadj, *vwgt, *vsize, *adjncy, *adjwgt; idx_t *cmap, *htable; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/compress.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/compress.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/compress.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/compress.c 2024-03-16 01:25:07 @@ -151,7 +151,7 @@ idx_t *vwgt, idx_t *iperm, real_t factor) { idx_t i, j, k, l, nlarge, pnvtxs, pnedges; - idx_t *pxadj, *padjncy, *padjwgt, *pvwgt; + idx_t *pxadj, *padjncy, *pvwgt; idx_t *perm; graph_t *graph=NULL; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/contig.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/contig.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/contig.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/contig.c 2024-03-16 01:25:07 @@ -32,7 +32,7 @@ idx_t FindPartitionInducedComponents(graph_t *graph, idx_t *where, idx_t *cptr, idx_t *cind) { - idx_t i, ii, j, jj, k, me=0, nvtxs, first, last, nleft, ncmps; + idx_t i, j, k, me=0, nvtxs, first, last, nleft, ncmps; idx_t *xadj, *adjncy; idx_t *touched, *perm, *todo; idx_t mustfree_ccsr=0, mustfree_where=0; @@ -267,7 +267,7 @@ idx_t FindSepInducedComponents(ctrl_t *ctrl, graph_t *graph, idx_t *cptr, idx_t *cind) { - idx_t i, j, k, nvtxs, first, last, nleft, ncmps, wgt; + idx_t i, j, k, nvtxs, first, last, nleft, ncmps; idx_t *xadj, *adjncy, *where, *touched, *queue; nvtxs = graph->nvtxs; @@ -335,14 +335,13 @@ /*************************************************************************/ void EliminateComponents(ctrl_t *ctrl, graph_t *graph) { - idx_t i, ii, j, jj, k, me, nparts, nvtxs, ncon, ncmps, other, + idx_t i, ii, j, jj, me, nparts, nvtxs, ncon, ncmps, ncand, target; idx_t *xadj, *adjncy, *vwgt, *adjwgt, *where, *pwgts; idx_t *cptr, *cind, *cpvec, *pcptr, *pcind, *cwhere; idx_t cid, bestcid, *cwgt, *bestcwgt; idx_t ntodo, oldntodo, *todo; rkv_t *cand; - real_t *tpwgts; idx_t *vmarker=NULL, *pmarker=NULL, *modind=NULL; /* volume specific work arrays */ WCOREPUSH; @@ -358,7 +357,6 @@ pwgts = graph->pwgts; nparts = ctrl->nparts; - tpwgts = ctrl->tpwgts; cptr = iwspacemalloc(ctrl, nvtxs+1); cind = iwspacemalloc(ctrl, nvtxs); @@ -531,12 +529,11 @@ void MoveGroupContigForCut(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t gid, idx_t *ptr, idx_t *ind) { - idx_t i, ii, iii, j, jj, k, l, nvtxs, nbnd, from, me; + idx_t i, ii, iii, j, k, nbnd, from, me; idx_t *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind; ckrinfo_t *myrinfo; cnbr_t *mynbrs; - nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; @@ -602,12 +599,11 @@ idx_t *ptr, idx_t *ind, idx_t *vmarker, idx_t *pmarker, idx_t *modind) { - idx_t i, ii, iii, j, jj, k, l, nvtxs, from, me, other, xgain; + idx_t i, ii, iii, j, k, l, from, other, xgain; idx_t *xadj, *vsize, *adjncy, *where; vkrinfo_t *myrinfo, *orinfo; vnbr_t *mynbrs, *onbrs; - nvtxs = graph->nvtxs; xadj = graph->xadj; vsize = graph->vsize; adjncy = graph->adjncy; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/debug.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/debug.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/debug.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/debug.c 2024-03-16 01:28:20 @@ -47,7 +47,7 @@ /*************************************************************************/ idx_t ComputeVolume(graph_t *graph, idx_t *where) { - idx_t i, j, k, me, nvtxs, nparts, totalv; + idx_t i, j, k, nvtxs, nparts, totalv; idx_t *xadj, *adjncy, *vsize, *marker; @@ -106,7 +106,9 @@ maxcut = cuts[iargmax(nparts, cuts)]; +#ifndef NDEBUG printf("%zu => %"PRIDX"\n", iargmax(nparts, cuts), maxcut); +#endif gk_free((void **)&cuts, LTERM); @@ -120,6 +122,7 @@ /*************************************************************************/ idx_t CheckBnd(graph_t *graph) { +#ifndef NDEBUG idx_t i, j, nvtxs, nbnd; idx_t *xadj, *adjncy, *where, *bndptr, *bndind; @@ -145,6 +148,7 @@ } ASSERTP(nbnd == graph->nbnd, ("%"PRIDX" %"PRIDX"\n", nbnd, graph->nbnd)); +#endif return 1; } @@ -157,6 +161,7 @@ /*************************************************************************/ idx_t CheckBnd2(graph_t *graph) { +#ifndef NDEBUG idx_t i, j, nvtxs, nbnd, id, ed; idx_t *xadj, *adjncy, *where, *bndptr, *bndind; @@ -183,6 +188,7 @@ } ASSERTP(nbnd == graph->nbnd, ("%"PRIDX" %"PRIDX"\n", nbnd, graph->nbnd)); +#endif return 1; } @@ -194,6 +200,7 @@ /*************************************************************************/ idx_t CheckNodeBnd(graph_t *graph, idx_t onbnd) { +#ifndef NDEBUG idx_t i, j, nvtxs, nbnd; idx_t *xadj, *adjncy, *where, *bndptr, *bndind; @@ -219,6 +226,7 @@ ASSERTP(bndptr[i] != -1, ("%"PRIDX" %"PRIDX"\n", i, bndptr[i])); } } +#endif return 1; } @@ -231,6 +239,7 @@ /*************************************************************************/ idx_t CheckRInfo(ctrl_t *ctrl, ckrinfo_t *rinfo) { +#ifndef NDEBUG idx_t i, j; cnbr_t *nbrs; @@ -242,6 +251,7 @@ ("%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"\n", i, j, nbrs[i].pid, nbrs[j].pid)); } +#endif return 1; } @@ -254,15 +264,14 @@ /*************************************************************************/ idx_t CheckNodePartitionParams(graph_t *graph) { - idx_t i, j, k, l, nvtxs, me, other; - idx_t *xadj, *adjncy, *adjwgt, *vwgt, *where; + idx_t i, j, nvtxs, me, other; + idx_t *xadj, *adjncy, *vwgt, *where; idx_t edegrees[2], pwgts[3]; nvtxs = graph->nvtxs; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; - adjwgt = graph->adjwgt; where = graph->where; /*------------------------------------------------------------ @@ -308,6 +317,7 @@ /*************************************************************************/ idx_t IsSeparable(graph_t *graph) { +#ifndef NDEBUG idx_t i, j, nvtxs, other; idx_t *xadj, *adjncy, *where; @@ -327,6 +337,7 @@ xadj[adjncy[j]+1]-xadj[adjncy[j]])); } } +#endif return 1; } @@ -338,8 +349,8 @@ /*************************************************************************/ void CheckKWayVolPartitionParams(ctrl_t *ctrl, graph_t *graph) { - idx_t i, ii, j, k, kk, l, nvtxs, nbnd, mincut, minvol, me, other, pid; - idx_t *xadj, *vsize, *adjncy, *pwgts, *where, *bndind, *bndptr; + idx_t i, ii, j, k, kk, nvtxs, me, other, pid; + idx_t *xadj, *vsize, *adjncy, *where; vkrinfo_t *rinfo, *myrinfo, *orinfo, tmprinfo; vnbr_t *mynbrs, *onbrs, *tmpnbrs; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/fm.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/fm.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/fm.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/fm.c 2024-03-16 01:25:07 @@ -28,7 +28,7 @@ /*************************************************************************/ void FM_2WayCutRefine(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niter) { - idx_t i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, pass, me, limit, tmp; + idx_t i, ii, j, k, kwgt, nvtxs, nbnd, nswaps, from, to, pass, limit, tmp; idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *id, *ed, *bndptr, *bndind, *pwgts; idx_t *moved, *swaps, *perm; rpq_t *queues[2]; @@ -207,7 +207,7 @@ void FM_Mc2WayCutRefine(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niter) { idx_t i, ii, j, k, l, kwgt, nvtxs, ncon, nbnd, nswaps, from, to, pass, - me, limit, tmp, cnum; + limit, tmp, cnum; idx_t *xadj, *adjncy, *vwgt, *adjwgt, *pwgts, *where, *id, *ed, *bndptr, *bndind; idx_t *moved, *swaps, *perm, *qnum; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/graph.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/graph.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/graph.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/graph.c 2024-03-16 01:25:07 @@ -17,8 +17,7 @@ graph_t *SetupGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t ncon, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt) { - idx_t i, j, k, sum; - real_t *nvwgt; + idx_t i, j; graph_t *graph; /* allocate the graph and fill in the fields */ diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/initpart.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/initpart.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/initpart.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/initpart.c 2024-03-16 01:25:07 @@ -114,18 +114,15 @@ void RandomBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { - idx_t i, ii, j, k, nvtxs, pwgts[2], zeromaxpwgt, from, me, - bestcut=0, icut, mincut, inbfs; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where; + idx_t i, ii, nvtxs, pwgts[2], zeromaxpwgt, + bestcut=0, inbfs; + idx_t *vwgt, *where; idx_t *perm, *bestwhere; WCOREPUSH; nvtxs = graph->nvtxs; - xadj = graph->xadj; vwgt = graph->vwgt; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; Allocate2WayPartitionMemory(ctrl, graph); where = graph->where; @@ -191,9 +188,9 @@ { idx_t i, j, k, nvtxs, drain, nleft, first, last, pwgts[2], oneminpwgt, onemaxpwgt, - from, me, bestcut=0, icut, mincut, inbfs; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where; - idx_t *queue, *touched, *gain, *bestwhere; + bestcut=0, inbfs; + idx_t *xadj, *vwgt, *adjncy, *where; + idx_t *queue, *touched, *bestwhere; WCOREPUSH; @@ -201,7 +198,6 @@ xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; - adjwgt = graph->adjwgt; Allocate2WayPartitionMemory(ctrl, graph); where = graph->where; @@ -325,7 +321,7 @@ void McRandomBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { - idx_t i, ii, j, k, nvtxs, ncon, from, bestcut=0, mincut, inbfs, qnum; + idx_t i, ii, nvtxs, ncon, bestcut=0, inbfs, qnum; idx_t *bestwhere, *where, *perm, *counts; idx_t *vwgt; @@ -385,7 +381,7 @@ void McGrowBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { - idx_t i, j, k, nvtxs, ncon, from, bestcut=0, mincut, inbfs; + idx_t nvtxs, bestcut=0, inbfs; idx_t *bestwhere, *where; WCOREPUSH; @@ -434,9 +430,9 @@ idx_t niparts) { idx_t i, j, k, nvtxs, drain, nleft, first, last, pwgts[2], oneminpwgt, - onemaxpwgt, from, me, bestcut=0, icut, mincut, inbfs; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *bndind; - idx_t *queue, *touched, *gain, *bestwhere; + onemaxpwgt, bestcut=0, inbfs; + idx_t *xadj, *vwgt, *adjncy, *where, *bndind; + idx_t *queue, *touched, *bestwhere; WCOREPUSH; @@ -444,7 +440,6 @@ xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; - adjwgt = graph->adjwgt; bestwhere = iwspacemalloc(ctrl, nvtxs); queue = iwspacemalloc(ctrl, nvtxs); @@ -570,7 +565,7 @@ void GrowBisectionNode2(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts, idx_t niparts) { - idx_t i, j, k, nvtxs, bestcut=0, mincut, inbfs; + idx_t i, j, nvtxs, bestcut=0, inbfs; idx_t *xadj, *where, *bndind, *bestwhere; WCOREPUSH; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/kmetis.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/kmetis.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/kmetis.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/kmetis.c 2024-03-16 01:25:07 @@ -102,10 +102,9 @@ /*************************************************************************/ idx_t MlevelKWayPartitioning(ctrl_t *ctrl, graph_t *graph, idx_t *part) { - idx_t i, j, objval=0, curobj=0, bestobj=0; + idx_t i, objval=0, curobj=0, bestobj=0; real_t curbal=0.0, bestbal=0.0; graph_t *cgraph; - int status; for (i=0; incuts; i++) { @@ -171,7 +170,10 @@ /*************************************************************************/ void InitKWayPartitioning(ctrl_t *ctrl, graph_t *graph) { - idx_t i, ntrials, options[METIS_NOPTIONS], curobj=0, bestobj=0; + idx_t i, options[METIS_NOPTIONS], curobj=0; +#ifdef XXX + idx_t ntrials, bestobj=0; +#endif idx_t *bestwhere=NULL; real_t *ubvec=NULL; int status; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/kwayfm.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/kwayfm.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/kwayfm.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/kwayfm.c 2024-03-16 01:25:07 @@ -61,12 +61,12 @@ real_t ffactor, idx_t omode) { /* Common variables to all types of kway-refinement/balancing routines */ - idx_t i, ii, iii, j, k, l, pass, nvtxs, nparts, gain; + idx_t i, ii, iii, j, k, pass, nvtxs, nparts, gain; idx_t from, me, to, oldcut, vwgt; idx_t *xadj, *adjncy, *adjwgt; idx_t *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt, *itpwgts; idx_t nmoved, nupd, *vstatus, *updptr, *updind; - idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL, **adwgts=NULL; + idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL; idx_t *bfslvl=NULL, *bfsind=NULL, *bfsmrk=NULL; idx_t bndtype = (omode == OMODE_REFINE ? BNDTYPE_REFINE : BNDTYPE_BALANCE); @@ -118,7 +118,6 @@ nads = ctrl->nads; adids = ctrl->adids; - adwgts = ctrl->adwgts; doms = iset(nparts, 0, ctrl->pvec1); } @@ -371,12 +370,12 @@ real_t ffactor, idx_t omode) { /* Common variables to all types of kway-refinement/balancing routines */ - idx_t i, ii, iii, j, k, l, pass, nvtxs, nparts, gain; + idx_t i, ii, iii, j, k, pass, nvtxs, nparts, gain; idx_t from, me, to, oldcut, vwgt; idx_t *xadj, *adjncy; - idx_t *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt, *itpwgts; + idx_t *where, *pwgts, *perm, *bndind, *minwgt, *maxwgt, *itpwgts; idx_t nmoved, nupd, *vstatus, *updptr, *updind; - idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL, **adwgts=NULL; + idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL; idx_t *bfslvl=NULL, *bfsind=NULL, *bfsmrk=NULL; idx_t bndtype = (omode == OMODE_REFINE ? BNDTYPE_REFINE : BNDTYPE_BALANCE); @@ -393,7 +392,6 @@ nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; - bndptr = graph->bndptr; bndind = graph->bndind; where = graph->where; pwgts = graph->pwgts; @@ -425,7 +423,6 @@ nads = ctrl->nads; adids = ctrl->adids; - adwgts = ctrl->adwgts; doms = iset(nparts, 0, ctrl->pvec1); } @@ -685,12 +682,12 @@ real_t ffactor, idx_t omode) { /* Common variables to all types of kway-refinement/balancing routines */ - idx_t i, ii, iii, j, k, l, pass, nvtxs, ncon, nparts, gain; + idx_t i, ii, iii, j, k, pass, nvtxs, ncon, nparts, gain; idx_t from, me, to, cto, oldcut; idx_t *xadj, *vwgt, *adjncy, *adjwgt; idx_t *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt; idx_t nmoved, nupd, *vstatus, *updptr, *updind; - idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL, **adwgts=NULL; + idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL; idx_t *bfslvl=NULL, *bfsind=NULL, *bfsmrk=NULL; idx_t bndtype = (omode == OMODE_REFINE ? BNDTYPE_REFINE : BNDTYPE_BALANCE); real_t *ubfactors, *pijbm; @@ -765,7 +762,6 @@ nads = ctrl->nads; adids = ctrl->adids; - adwgts = ctrl->adwgts; doms = iset(nparts, 0, ctrl->pvec1); } @@ -1027,12 +1023,12 @@ real_t ffactor, idx_t omode) { /* Common variables to all types of kway-refinement/balancing routines */ - idx_t i, ii, iii, j, k, l, pass, nvtxs, ncon, nparts, gain; + idx_t i, ii, iii, j, k, pass, nvtxs, ncon, nparts, gain; idx_t from, me, to, cto, oldcut; idx_t *xadj, *vwgt, *adjncy; - idx_t *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt; + idx_t *where, *pwgts, *perm, *bndind, *minwgt, *maxwgt; idx_t nmoved, nupd, *vstatus, *updptr, *updind; - idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL, **adwgts=NULL; + idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL; idx_t *bfslvl=NULL, *bfsind=NULL, *bfsmrk=NULL; idx_t bndtype = (omode == OMODE_REFINE ? BNDTYPE_REFINE : BNDTYPE_BALANCE); real_t *ubfactors, *pijbm; @@ -1053,7 +1049,6 @@ xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; - bndptr = graph->bndptr; bndind = graph->bndind; where = graph->where; pwgts = graph->pwgts; @@ -1104,7 +1099,6 @@ nads = ctrl->nads; adids = ctrl->adids; - adwgts = ctrl->adwgts; doms = iset(nparts, 0, ctrl->pvec1); } @@ -1462,7 +1456,7 @@ idx_t *updind, idx_t bndtype, idx_t *vmarker, idx_t *pmarker, idx_t *modind) { - idx_t i, ii, iii, j, jj, k, kk, l, u, nmod, other, me, myidx; + idx_t i, ii, iii, j, jj, k, kk, u, nmod, other, me, myidx; idx_t *xadj, *vsize, *adjncy, *where; vkrinfo_t *myrinfo, *orinfo; vnbr_t *mynbrs, *onbrs; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/kwayrefine.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/kwayrefine.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/kwayrefine.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/kwayrefine.c 2024-03-16 01:25:07 @@ -148,7 +148,7 @@ /**************************************************************************/ void ComputeKWayPartitionParams(ctrl_t *ctrl, graph_t *graph) { - idx_t i, j, k, l, nvtxs, ncon, nparts, nbnd, mincut, me, other; + idx_t i, j, k, nvtxs, ncon, nparts, nbnd, mincut, me, other; idx_t *xadj, *vwgt, *adjncy, *adjwgt, *pwgts, *where, *bndind, *bndptr; nparts = ctrl->nparts; @@ -561,8 +561,8 @@ /*************************************************************************/ void ComputeKWayVolGains(ctrl_t *ctrl, graph_t *graph) { - idx_t i, ii, j, k, l, nvtxs, nparts, me, other, pid; - idx_t *xadj, *vsize, *adjncy, *adjwgt, *where, + idx_t i, ii, j, k, nvtxs, nparts, me, other; + idx_t *xadj, *vsize, *adjncy, *where, *bndind, *bndptr, *ophtable; vkrinfo_t *myrinfo, *orinfo; vnbr_t *mynbrs, *onbrs; @@ -575,7 +575,6 @@ xadj = graph->xadj; vsize = graph->vsize; adjncy = graph->adjncy; - adjwgt = graph->adjwgt; where = graph->where; bndind = graph->bndind; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/minconn.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/minconn.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/minconn.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/minconn.c 2024-03-16 01:28:20 @@ -18,16 +18,13 @@ void ComputeSubDomainGraph(ctrl_t *ctrl, graph_t *graph) { idx_t i, ii, j, pid, other, nparts, nvtxs, nnbrs; - idx_t *xadj, *adjncy, *adjwgt, *where; + idx_t *where; idx_t *pptr, *pind; idx_t nads=0, *vadids, *vadwgts; WCOREPUSH; nvtxs = graph->nvtxs; - xadj = graph->xadj; - adjncy = graph->adjncy; - adjwgt = graph->adjwgt; where = graph->where; nparts = ctrl->nparts; @@ -264,10 +261,12 @@ avg = total/nparts; max = nads[iargmax(nparts, nads)]; +#ifndef NDEBUG IFSET(ctrl->dbglvl, METIS_DBG_CONNINFO, printf("Adjacent Subdomain Stats: Total: %3"PRIDX", " "Max: %3"PRIDX"[%zu], Avg: %3"PRIDX"\n", total, max, iargmax(nparts, nads), avg)); +#endif if (max < badfactor*avg) break; @@ -477,12 +476,11 @@ void MoveGroupMinConnForCut(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t nind, idx_t *ind) { - idx_t i, ii, j, jj, k, l, nvtxs, nbnd, from, me; + idx_t i, ii, j, k, nbnd, from, me; idx_t *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind; ckrinfo_t *myrinfo; cnbr_t *mynbrs; - nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; @@ -561,12 +559,11 @@ void MoveGroupMinConnForVol(ctrl_t *ctrl, graph_t *graph, idx_t to, idx_t nind, idx_t *ind, idx_t *vmarker, idx_t *pmarker, idx_t *modind) { - idx_t i, ii, j, jj, k, l, nvtxs, from, me, other, xgain, ewgt; + idx_t i, ii, j, k, l, from, me, other, xgain, ewgt; idx_t *xadj, *vsize, *adjncy, *where; vkrinfo_t *myrinfo, *orinfo; vnbr_t *mynbrs, *onbrs; - nvtxs = graph->nvtxs; xadj = graph->xadj; vsize = graph->vsize; adjncy = graph->adjncy; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/ometis.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/ometis.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/ometis.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/ometis.c 2024-03-16 01:25:07 @@ -48,7 +48,6 @@ graph_t *graph=NULL; ctrl_t *ctrl; idx_t *cptr, *cind, *piperm; - int numflag = 0; /* set up malloc cleaning code and signal catchers */ if (!gk_malloc_init()) @@ -183,12 +182,10 @@ void MlevelNestedDissection(ctrl_t *ctrl, graph_t *graph, idx_t *order, idx_t lastvtx) { - idx_t i, j, nvtxs, nbnd; + idx_t i, nbnd; idx_t *label, *bndind; graph_t *lgraph, *rgraph; - nvtxs = graph->nvtxs; - MlevelNodeBisectionMultiple(ctrl, graph); IFSET(ctrl->dbglvl, METIS_DBG_SEPINFO, @@ -236,7 +233,7 @@ void MlevelNestedDissectionCC(ctrl_t *ctrl, graph_t *graph, idx_t *order, idx_t lastvtx) { - idx_t i, j, nvtxs, nbnd, ncmps, rnvtxs, snvtxs; + idx_t i, nvtxs, nbnd, ncmps, rnvtxs, snvtxs; idx_t *label, *bndind; idx_t *cptr, *cind; graph_t **sgraphs; @@ -423,7 +420,7 @@ graph_t **r_rgraph) { idx_t i, ii, j, k, l, istart, iend, mypart, nvtxs, snvtxs[3], snedges[3]; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *label, *where, *bndptr, *bndind; + idx_t *xadj, *vwgt, *adjncy, *label, *where, *bndptr, *bndind; idx_t *sxadj[2], *svwgt[2], *sadjncy[2], *sadjwgt[2], *slabel[2]; idx_t *rename; idx_t *auxadjncy; @@ -437,7 +434,6 @@ xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; - adjwgt = graph->adjwgt; label = graph->label; where = graph->where; bndptr = graph->bndptr; @@ -552,8 +548,8 @@ graph_t **SplitGraphOrderCC(ctrl_t *ctrl, graph_t *graph, idx_t ncmps, idx_t *cptr, idx_t *cind) { - idx_t i, ii, iii, j, k, l, istart, iend, mypart, nvtxs, snvtxs, snedges; - idx_t *xadj, *vwgt, *adjncy, *adjwgt, *label, *where, *bndptr, *bndind; + idx_t i, ii, iii, j, k, l, istart, iend, nvtxs, snvtxs, snedges; + idx_t *xadj, *vwgt, *adjncy, *label, *where, *bndptr, *bndind; idx_t *sxadj, *svwgt, *sadjncy, *sadjwgt, *slabel; idx_t *rename; idx_t *auxadjncy; @@ -567,7 +563,6 @@ xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; - adjwgt = graph->adjwgt; label = graph->label; where = graph->where; bndptr = graph->bndptr; @@ -654,7 +649,7 @@ /*************************************************************************/ void MMDOrder(ctrl_t *ctrl, graph_t *graph, idx_t *order, idx_t lastvtx) { - idx_t i, j, k, nvtxs, nofsub, firstvtx; + idx_t i, k, nvtxs, nofsub, firstvtx; idx_t *xadj, *adjncy, *label; idx_t *perm, *iperm, *head, *qsize, *list, *marker; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/parmetis.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/parmetis.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/parmetis.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/parmetis.c 2024-03-16 01:25:07 @@ -105,7 +105,7 @@ void MlevelNestedDissectionP(ctrl_t *ctrl, graph_t *graph, idx_t *order, idx_t lastvtx, idx_t npes, idx_t cpos, idx_t *sizes) { - idx_t i, j, nvtxs, nbnd; + idx_t i, nvtxs, nbnd; idx_t *label, *bndind; graph_t *lgraph, *rgraph; @@ -161,7 +161,6 @@ int METIS_ComputeVertexSeparator(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *options, idx_t *r_sepsize, idx_t *part) { - idx_t i, j; graph_t *graph; ctrl_t *ctrl; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/pmetis.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/pmetis.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/pmetis.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/pmetis.c 2024-03-16 01:25:07 @@ -157,7 +157,7 @@ idx_t MlevelRecursiveBisection(ctrl_t *ctrl, graph_t *graph, idx_t nparts, idx_t *part, real_t *tpwgts, idx_t fpart) { - idx_t i, j, nvtxs, ncon, objval; + idx_t i, nvtxs, ncon, objval; idx_t *label, *where; graph_t *lgraph, *rgraph; real_t wsum, *tpwgts2; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/separator.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/separator.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/separator.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/separator.c 2024-03-16 01:25:07 @@ -20,7 +20,7 @@ **************************************************************************/ void ConstructSeparator(ctrl_t *ctrl, graph_t *graph) { - idx_t i, j, k, nvtxs, nbnd; + idx_t i, j, nvtxs, nbnd; idx_t *xadj, *where, *bndind; WCOREPUSH; @@ -70,7 +70,10 @@ { idx_t i, ii, j, jj, k, l, nvtxs, nbnd, bnvtxs[3], bnedges[2], csize; idx_t *xadj, *adjncy, *bxadj, *badjncy; - idx_t *where, *bndind, *bndptr, *vmap, *ivmap, *cover; + idx_t *where, *bndind, *vmap, *ivmap, *cover; +#ifndef NDEBUG + idx_t *bndptr; +#endif WCOREPUSH; @@ -80,7 +83,9 @@ nbnd = graph->nbnd; bndind = graph->bndind; +#ifndef NDEBUG bndptr = graph->bndptr; +#endif where = graph->where; vmap = iwspacemalloc(ctrl, nvtxs); diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/sfm.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/sfm.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/sfm.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/sfm.c 2024-03-16 01:25:07 @@ -476,7 +476,7 @@ void FM_2WayNodeBalance(ctrl_t *ctrl, graph_t *graph) { idx_t i, ii, j, k, jj, kk, nvtxs, nbnd, nswaps, gain; - idx_t badmaxpwgt, higain, oldgain, pass, to, other; + idx_t badmaxpwgt, higain, oldgain, to, other; idx_t *xadj, *vwgt, *adjncy, *where, *pwgts, *edegrees, *bndind, *bndptr; idx_t *perm, *moved; rpq_t *queue; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/srefine.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/srefine.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/srefine.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/srefine.c 2024-03-16 01:25:07 @@ -136,7 +136,7 @@ /*************************************************************************/ void Project2WayNodePartition(ctrl_t *ctrl, graph_t *graph) { - idx_t i, j, nvtxs; + idx_t i, nvtxs; idx_t *cmap, *where, *cwhere; graph_t *cgraph; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/stat.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/stat.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/stat.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/stat.c 2024-03-16 01:25:07 @@ -20,8 +20,8 @@ **************************************************************************/ void ComputePartitionInfoBipartite(graph_t *graph, idx_t nparts, idx_t *where) { - idx_t i, j, k, nvtxs, ncon, mustfree=0; - idx_t *xadj, *adjncy, *vwgt, *vsize, *adjwgt, *kpwgts, *tmpptr; + idx_t i, j, nvtxs, ncon, mustfree=0; + idx_t *xadj, *adjncy, *vwgt, *vsize, *adjwgt, *kpwgts; idx_t *padjncy, *padjwgt, *padjcut; nvtxs = graph->nvtxs; @@ -126,7 +126,6 @@ { idx_t i, j, nvtxs, ncon; idx_t *kpwgts, *vwgt; - real_t balance; nvtxs = graph->nvtxs; ncon = graph->ncon; diff -ruN src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/wspace.c src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/wspace.c --- src/SuiteSparse/CHOLMOD/SuiteSparse_metis/libmetis/wspace.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/SuiteSparse_metis/libmetis/wspace.c 2024-03-16 01:28:20 @@ -81,12 +81,14 @@ { gk_mcoreDestroy(&ctrl->mcore, ctrl->dbglvl&METIS_DBG_INFO); +#ifndef NDEBUG IFSET(ctrl->dbglvl, METIS_DBG_INFO, printf(" nbrpool statistics\n" " nbrpoolsize: %12zu nbrpoolcpos: %12zu\n" " nbrpoolreallocs: %12zu\n\n", ctrl->nbrpoolsize, ctrl->nbrpoolcpos, ctrl->nbrpoolreallocs)); +#endif gk_free((void **)&ctrl->cnbrpool, &ctrl->vnbrpool, LTERM); ctrl->nbrpoolsize = 0; diff -ruN src/SuiteSparse/CHOLMOD/Supernodal/cholmod_super_numeric.c src/SuiteSparse-patched/CHOLMOD/Supernodal/cholmod_super_numeric.c --- src/SuiteSparse/CHOLMOD/Supernodal/cholmod_super_numeric.c 2024-03-16 01:30:04 +++ src/SuiteSparse-patched/CHOLMOD/Supernodal/cholmod_super_numeric.c 2024-03-16 01:25:07 @@ -281,10 +281,6 @@ // supernodal numerical factorization, using template routine //-------------------------------------------------------------------------- - float s_beta [2] ; - s_beta [0] = (float) beta [0] ; - s_beta [1] = (float) beta [1] ; - switch ((A->xtype + A->dtype) % 8) { case CHOLMOD_REAL + CHOLMOD_SINGLE: diff -ruN src/SuiteSparse/CHOLMOD/Supernodal/cholmod_super_symbolic.c src/SuiteSparse-patched/CHOLMOD/Supernodal/cholmod_super_symbolic.c --- src/SuiteSparse/CHOLMOD/Supernodal/cholmod_super_symbolic.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Supernodal/cholmod_super_symbolic.c 2024-03-16 01:25:07 @@ -173,11 +173,13 @@ csize, maxcsize, ss, nscol0, nscol1, ns, nfsuper, newzeros, totzeros, merge, snext, esize, maxesize, nrelax0, nrelax1, nrelax2, Asorted ; int find_xsize ; +#if (defined(CHOLMOD_HAS_CUDA) && defined(CHOLMOD_INT64)) const char* env_use_gpu; const char* env_max_bytes; size_t max_bytes; const char* env_max_fraction; double max_fraction ; +#endif RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; @@ -243,10 +245,11 @@ // real/complex/zomples only), and only when the GPU is requested and // available. + #ifdef CHOLMOD_INT64 + max_bytes = 0; max_fraction = 0; - #ifdef CHOLMOD_INT64 if ( Common->useGPU == EMPTY ) { // useGPU not explicitly requested by the user, but not explicitly @@ -552,9 +555,6 @@ double xns = (double) ns ; double xtotsize = (xns * (xns+1) / 2) + xns * (lnz1 - nscol1) ; double z = xtotzeros / xtotsize ; - - Int totsize ; - totsize = (ns * (ns+1) / 2) + ns * (Snz [s+1] - nscol1) ; PRINT2 (("oldzeros "ID" newzeros "ID" xtotsize %g z %g\n", Zeros [s+1], newzeros, xtotsize, z)) ; diff -ruN src/SuiteSparse/CHOLMOD/Supernodal/t_cholmod_super_numeric_worker.c src/SuiteSparse-patched/CHOLMOD/Supernodal/t_cholmod_super_numeric_worker.c --- src/SuiteSparse/CHOLMOD/Supernodal/t_cholmod_super_numeric_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Supernodal/t_cholmod_super_numeric_worker.c 2024-03-16 01:25:07 @@ -152,15 +152,21 @@ #ifdef BLAS_TIMER double tstart, blas_time ; #endif - Real *Lx, *Ax, *Fx, *Az, *Fz, *C ; + Real *Lx, *Ax, *Fx, *C ; +#ifdef ZOMPLEX + Real *Az, *Fz ; +#endif Int *Super, *Head, *Ls, *Lpi, *Lpx, *Map, *SuperMap, *RelativeMap, *Next, - *Lpos, *Fp, *Fi, *Fnz, *Ap, *Ai, *Anz, *Iwork, *Next_save, *Lpos_save, - *Previous; + *Lpos, *Fp, *Fi, *Fnz, *Ap, *Ai, *Anz, *Iwork, *Next_save, *Lpos_save; Int nsuper, n, s, k1, k2, nscol, psi, psx, psend, nsrow, - pj, d, kd1, kd2, info, ndcol, ndrow, pdi, pdx, pdend, pdi1, pdi2, + d, kd1, kd2, info, ndcol, ndrow, pdi, pdx, pdend, pdi2, ndrow1, ndrow2, dancestor, sparent, dnext, nsrow2, ndrow3, stype, Apacked, Fpacked, repeat_supernode, nscol2, ss, - tail, nscol_new = 0; + nscol_new = 0; +#if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) + Int *Previous ; + Int tail ; +#endif info = 0 ; ASSERT (L->dtype == A->dtype) ; @@ -215,7 +221,9 @@ Lpos = Iwork + 2*((size_t) n) + nsuper ; // size nsuper Next_save = Iwork + 2*((size_t) n) + 2*((size_t) nsuper) ;// size nsuper Lpos_save = Iwork + 2*((size_t) n) + 3*((size_t) nsuper) ;// size nsuper +#if (defined (CHOLMOD_HAS_CUDA) && defined (DOUBLE)) Previous = Iwork + 2*((size_t) n) + 4*((size_t) nsuper) ;// size nsuper +#endif Map = Common->Flag ; // size n, use Flag as workspace for Map array Head = Common->Head ; // size n+1, only Head [0..nsuper-1] used @@ -273,7 +281,9 @@ Fp = NULL ; Fi = NULL ; Fx = NULL ; +#ifdef ZOMPLEX Fz = NULL ; +#endif Fnz = NULL ; Fpacked = TRUE ; } @@ -284,7 +294,9 @@ Fp = F->p ; Fi = F->i ; Fx = F->x ; +#ifdef ZOMPLEX Fz = F->z ; +#endif Fnz = F->nz ; Fpacked = F->packed ; } @@ -292,7 +304,9 @@ Ap = A->p ; Ai = A->i ; Ax = A->x ; +#ifdef ZOMPLEX Az = A->z ; +#endif Anz = A->nz ; Apacked = A->packed ; @@ -303,8 +317,10 @@ #endif Int ii ; +#ifdef _OPENMP #pragma omp parallel for num_threads(nthreads) \ if ( n > 128 ) schedule (static) +#endif for (ii = 0 ; ii < n ; ii++) { Map [ii] = EMPTY ; @@ -370,8 +386,10 @@ #endif Int p ; +#ifdef _OPENMP #pragma omp parallel for num_threads(nthreads) \ schedule (static) if ( pend - psx > 1024 ) +#endif for (p = psx ; p < pend ; p++) { L_CLEAR (Lx,p) ; @@ -390,8 +408,10 @@ #endif Int k ; +#ifdef _OPENMP #pragma omp parallel for num_threads(nthreads) \ if ( nsrow > 128 ) +#endif for (k = 0 ; k < nsrow ; k++) { PRINT1 ((" "ID" map "ID"\n", Ls [psi+k], k)) ; @@ -416,8 +436,6 @@ // copy matrix into supernode s (lower triangular part only) //---------------------------------------------------------------------- - Int pk = psx ; - #ifdef _OPENMP double work ; if (stype != 0) @@ -435,8 +453,10 @@ nthreads = cholmod_nthreads (work, Common) ; #endif +#ifdef _OPENMP #pragma omp parallel for num_threads(nthreads) \ if ( k2-k1 > 64 ) +#endif for (k = k1 ; k < k2 ; k++) { if (stype != 0) @@ -894,8 +914,10 @@ #endif Int i ; +#ifdef _OPENMP #pragma omp parallel for num_threads(nthreads) \ if ( ndrow2 > 64 ) +#endif for (i = 0 ; i < ndrow2 ; i++) { RelativeMap [i] = Map [Ls [pdi1 + i]] ; @@ -912,8 +934,10 @@ #endif Int j ; +#ifdef _OPENMP #pragma omp parallel for num_threads(nthreads) \ if (ndrow1 > 64 ) +#endif for (j = 0 ; j < ndrow1 ; j++) // cols k1:k2-1 { ASSERT (RelativeMap [j] == Map [Ls [pdi1 + j]]) ; diff -ruN src/SuiteSparse/CHOLMOD/Supernodal/t_cholmod_super_solve_worker.c src/SuiteSparse-patched/CHOLMOD/Supernodal/t_cholmod_super_solve_worker.c --- src/SuiteSparse/CHOLMOD/Supernodal/t_cholmod_super_solve_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Supernodal/t_cholmod_super_solve_worker.c 2024-03-16 01:25:07 @@ -37,12 +37,11 @@ Real minus_one [2], one [2] ; Int *Lpi, *Lpx, *Ls, *Super ; Int nsuper, k1, k2, psi, psend, psx, nsrow, nscol, ii, s, - nsrow2, n, ps2, j, i, d, nrhs ; + nsrow2, ps2, j, i, d, nrhs ; nrhs = X->ncol ; Ex = E->x ; Xx = X->x ; - n = L->n ; d = X->d ; nsuper = L->nsuper ; @@ -326,12 +325,11 @@ Real minus_one [2], one [2] ; Int *Lpi, *Lpx, *Ls, *Super ; Int nsuper, k1, k2, psi, psend, psx, nsrow, nscol, ii, s, - nsrow2, n, ps2, j, i, d, nrhs ; + nsrow2, ps2, j, i, d, nrhs ; nrhs = X->ncol ; Ex = E->x ; Xx = X->x ; - n = L->n ; d = X->d ; nsuper = L->nsuper ; diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_aat.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_aat.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_aat.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_aat.c 2024-03-16 01:25:07 @@ -106,7 +106,6 @@ bool ignore_diag = (mode < 0) ; bool values = (mode > 0) && (A->xtype != CHOLMOD_PATTERN) ; int axtype = (values) ? A->xtype : CHOLMOD_PATTERN ; - bool conj = (mode >= 2) ; Int nrow = A->nrow ; Int ncol = A->ncol ; @@ -121,12 +120,8 @@ // get the sizes of the entries of C and A //-------------------------------------------------------------------------- - size_t ei = sizeof (Int) ; - size_t e = (A->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ew = ((axtype == CHOLMOD_PATTERN) ? 0 : ((axtype == CHOLMOD_COMPLEX) ? 2 : 1)) ; - size_t ex = e * ew ; - size_t ez = e * ((axtype == CHOLMOD_ZOMPLEX) ? 1 : 0) ; //-------------------------------------------------------------------------- // allocate workspace diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_aat_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_aat_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_aat_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_aat_worker.c 2024-03-16 01:25:07 @@ -35,20 +35,32 @@ Int *Ap = (Int *) A->p ; Int *Anz = (Int *) A->nz ; Int *Ai = (Int *) A->i ; +#ifndef PATTERN Real *Ax = (Real *) A->x ; +#ifdef ZOMPLEX Real *Az = (Real *) A->z ; +#endif +#endif bool packed = A->packed ; Int *Fp = (Int *) F->p ; Int *Fi = (Int *) F->i ; +#ifndef PATTERN Real *Fx = (Real *) F->x ; +#ifdef ZOMPLEX Real *Fz = (Real *) F->z ; +#endif +#endif ASSERT (F->packed) ; Int *Cp = (Int *) C->p ; Int *Ci = (Int *) C->i ; +#ifndef PATTERN Real *Cx = (Real *) C->x ; +#ifdef ZOMPLEX Real *Cz = (Real *) C->z ; +#endif +#endif ASSERT (C->packed) ; //-------------------------------------------------------------------------- @@ -93,8 +105,12 @@ //------------------------------------------------------------------ Int t = Fi [pf] ; +#ifndef PATTERN Real fx [2] = {0,0} ; +#ifdef ZOMPLEX Real fz [1] = {0} ; +#endif +#endif ASSIGN (fx, fz, 0, Fx, Fz, pf) ; //------------------------------------------------------------------ diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_add.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_add.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_add.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_add.c 2024-03-16 01:25:07 @@ -118,12 +118,6 @@ // get the sizes of the entries of C, A, and B //-------------------------------------------------------------------------- - size_t ei = sizeof (Int) ; - size_t e = (dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; - size_t ex = e * ((xtype == CHOLMOD_PATTERN) ? 0 : - ((xtype == CHOLMOD_COMPLEX) ? 2 : 1)) ; - size_t ez = e * ((xtype == CHOLMOD_ZOMPLEX) ? 1 : 0) ; - //-------------------------------------------------------------------------- // convert/sort A and/or B, if needed //-------------------------------------------------------------------------- diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_band_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_band_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_band_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_band_worker.c 2024-03-16 01:25:07 @@ -30,14 +30,22 @@ Int *Ap = (Int *) A->p ; Int *Anz = (Int *) A->nz ; Int *Ai = (Int *) A->i ; +#ifndef PATTERN Real *Ax = (Real *) A->x ; +#ifdef ZOMPLEX Real *Az = (Real *) A->z ; +#endif +#endif bool packed = A->packed ; Int *Cp = (Int *) C->p ; Int *Ci = (Int *) C->i ; +#ifndef PATTERN Real *Cx = (Real *) C->x ; +#ifdef ZOMPLEX Real *Cz = (Real *) C->z ; +#endif +#endif // columns outside of j1:j2 have no entries in diagonals k1:k2 Int j1 = MAX (k1, 0) ; diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_change_factor.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_change_factor.c 2024-03-16 01:25:07 @@ -698,8 +698,6 @@ bool make_ldl = (!to_ll && L->is_ll) ; Int n = L->n ; - Int *Lp = (Int *) L->p ; - Int *Li = (Int *) L->i ; Int *Lnz = (Int *) L->nz ; bool grow = false ; @@ -900,11 +898,8 @@ // get inputs //-------------------------------------------------------------------------- - Int n = L->n ; Int nsuper = L->nsuper ; Int *Lpi = (Int *) L->pi ; - Int *Lpx = (Int *) L->px ; - Int *Ls = (Int *) L->s ; Int *Super = (Int *) L->super ; size_t ei = sizeof (Int) ; @@ -1088,7 +1083,6 @@ // get the sizes of the entries //-------------------------------------------------------------------------- - size_t ei = sizeof (Int) ; size_t e = (L->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * ((to_xtype == CHOLMOD_COMPLEX) ? 2 : 1) ; size_t xs = L->xsize ; diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_1_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_change_factor_1_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_1_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_change_factor_1_worker.c 2024-03-16 01:25:07 @@ -36,7 +36,9 @@ Int *Lp = (Int *) L->p ; Int *Li = (Int *) L->i ; Real *Lx = (Real *) L->x ; +#ifdef ZOMPLEX Real *Lz = (Real *) L->z ; +#endif Int n = L->n ; //-------------------------------------------------------------------------- @@ -44,7 +46,9 @@ //-------------------------------------------------------------------------- Real onex [2] = {1,0} ; +#ifdef ZOMPLEX Real onez [1] = {0} ; +#endif for (Int j = 0 ; j < n ; j++) { diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_2_template.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_change_factor_2_template.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_2_template.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_change_factor_2_template.c 2024-03-16 01:25:07 @@ -34,7 +34,9 @@ //------------------------------------------------------------------------------ { +#ifndef IN_PLACE Int pnew = 0 ; +#endif if (make_ll) { diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_2_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_change_factor_2_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_2_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_change_factor_2_worker.c 2024-03-16 01:25:07 @@ -50,7 +50,9 @@ Int *Lp = (Int *) L->p ; Int *Li = (Int *) L->i ; Real *Lx = (Real *) L->x ; +#ifdef ZOMPLEX Real *Lz = (Real *) L->z ; +#endif Int *Lnz = (Int *) L->nz ; //-------------------------------------------------------------------------- diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_3_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_change_factor_3_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_factor_3_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_change_factor_3_worker.c 2024-03-16 01:25:07 @@ -100,7 +100,6 @@ Int *Lp = (Int *) L->p ; // simplicial col pointers Int *Li = (Int *) L->i ; // simplicial row indices Int *Lnz = (Int *) L->nz ; // simplicial column counts - Int lnz = L->nzmax ; // size of Li, Lp, and Lx //---------------------------------------------------------------------- // convert supernodal LL' to simplicial LL' or LDL' (packed/unpacked) diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_xdtype.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_change_xdtype.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_change_xdtype.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_change_xdtype.c 2024-03-16 01:25:07 @@ -214,7 +214,7 @@ int output_dtype = to_xdtype & 4 ; // double or single if (output_xtype <= CHOLMOD_PATTERN || - L->is_super && output_xtype == CHOLMOD_ZOMPLEX) + (L->is_super && output_xtype == CHOLMOD_ZOMPLEX)) { // output_xtype not supported ERROR (CHOLMOD_INVALID, "invalid xtype") ; diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_dense2_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_copy_dense2_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_dense2_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_copy_dense2_worker.c 2024-03-16 01:25:07 @@ -36,9 +36,13 @@ //-------------------------------------------------------------------------- Real *Xx = (Real *) X->x ; +#ifdef ZOMPLEX Real *Xz = (Real *) X->z ; +#endif Real *Yx = (Real *) Y->x ; +#ifdef ZOMPLEX Real *Yz = (Real *) Y->z ; +#endif size_t nrow = X->nrow ; size_t ncol = X->ncol ; size_t xd = X->d ; @@ -50,9 +54,13 @@ size_t e = (X->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t fx = ((X->xtype == CHOLMOD_COMPLEX) ? 2 : 1) ; +#ifdef ZOMPLEX size_t fz = ((X->xtype == CHOLMOD_ZOMPLEX) ? 1 : 0) ; +#endif size_t e_fx_nrow = e * fx * nrow ; +#ifdef ZOMPLEX size_t e_fz_nrow = e * fz * nrow ; +#endif //-------------------------------------------------------------------------- // copy X = Y diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_factor.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_copy_factor.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_factor.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_copy_factor.c 2024-03-16 01:25:07 @@ -69,7 +69,6 @@ size_t e = (L->dtype == CHOLMOD_SINGLE) ? sizeof (float) : sizeof (double) ; size_t ex = e * ((L->xtype == CHOLMOD_PATTERN) ? 0 : ((L->xtype == CHOLMOD_COMPLEX) ? 2 : 1)) ; - size_t ez = e * ((L->xtype == CHOLMOD_ZOMPLEX) ? 1 : 0) ; //-------------------------------------------------------------------------- // allocate the new factor H, H->Perm, and H->ColCount diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_factor_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_copy_factor_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_factor_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_copy_factor_worker.c 2024-03-16 01:25:07 @@ -29,11 +29,15 @@ Int *Li = (Int *) L->i ; Int *Lnz = (Int *) L->nz ; Real *Lx = (Real *) L->x ; +#ifdef ZOMPLEX Real *Lz = (Real *) L->z ; +#endif Int *Hi = (Int *) H->i ; Real *Hx = (Real *) H->x ; +#ifdef ZOMPLEX Real *Hz = (Real *) H->z ; +#endif //-------------------------------------------------------------------------- // copy each column diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_sparse_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_copy_sparse_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_sparse_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_copy_sparse_worker.c 2024-03-16 01:25:07 @@ -31,13 +31,21 @@ Int *Ap = (Int *) A->p ; Int *Anz = (Int *) A->nz ; Int *Ai = (Int *) A->i ; +#ifndef PATTERN Real *Ax = (Real *) A->x ; +#ifdef ZOMPLEX Real *Az = (Real *) A->z ; +#endif +#endif size_t ncol = A->ncol ; Int *Ci = (Int *) C->i ; +#ifndef PATTERN Real *Cx = (Real *) C->x ; +#ifdef ZOMPLEX Real *Cz = (Real *) C->z ; +#endif +#endif //-------------------------------------------------------------------------- // copy the contents from A to C diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_copy_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_copy_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_copy_worker.c 2024-03-16 01:25:07 @@ -45,14 +45,21 @@ Int *Ap = (Int *) A->p ; Int *Anz = (Int *) A->nz ; Int *Ai = (Int *) A->i ; +#ifndef PATTERN Real *Ax = (Real *) A->x ; +#ifdef ZOMPLEX Real *Az = (Real *) A->z ; +#endif +#endif bool packed = A->packed ; - Int *Cp = (Int *) C->p ; Int *Ci = (Int *) C->i ; +#ifndef PATTERN Real *Cx = (Real *) C->x ; +#ifdef ZOMPLEX Real *Cz = (Real *) C->z ; +#endif +#endif bool keep_diag = !ignore_diag ; //-------------------------------------------------------------------------- diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_dense_nnz_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_dense_nnz_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_dense_nnz_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_dense_nnz_worker.c 2024-03-16 01:25:07 @@ -21,7 +21,9 @@ //-------------------------------------------------------------------------- Real *Xx = (Real *) X->x ; +#ifdef ZOMPLEX Real *Xz = (Real *) X->z ; +#endif Int nrow = (Int) X->nrow ; Int ncol = (Int) X->ncol ; diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_dense_to_sparse_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_dense_to_sparse_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_dense_to_sparse_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_dense_to_sparse_worker.c 2024-03-16 01:25:07 @@ -34,7 +34,9 @@ //-------------------------------------------------------------------------- Real *Xx = (Real *) X->x ; +#ifdef ZOMPLEX Real *Xz = (Real *) X->z ; +#endif Int nrow = X->nrow ; Int ncol = X->ncol ; Int d = X->d ; @@ -42,7 +44,9 @@ Int *Cp = (Int *) C->p ; Int *Ci = (Int *) C->i ; Real *Cx = (Real *) C->x ; +#ifdef ZOMPLEX Real *Cz = (Real *) C->z ; +#endif bool pattern = (C->xtype == CHOLMOD_PATTERN) ; //-------------------------------------------------------------------------- diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_eye_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_eye_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_eye_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_eye_worker.c 2024-03-16 01:25:07 @@ -21,14 +21,18 @@ //-------------------------------------------------------------------------- Real *Xx = (Real *) X->x ; +#ifdef ZOMPLEX Real *Xz = (Real *) X->z ; +#endif Int nrow = (Int) X->nrow ; Int ncol = (Int) X->ncol ; Int n = MIN (nrow, ncol) ; Real onex [2] = {1,0} ; +#ifdef ZOMPLEX Real onez [1] = {0} ; +#endif for (Int k = 0 ; k < n ; k++) { diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_ones_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_ones_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_ones_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_ones_worker.c 2024-03-16 01:25:07 @@ -21,11 +21,15 @@ //-------------------------------------------------------------------------- Real *Xx = (Real *) X->x ; +#ifdef ZOMPLEX Real *Xz = (Real *) X->z ; +#endif size_t nzmax = X->nzmax ; Real onex [2] = {1,0} ; +#ifdef ZOMPLEX Real onez [1] = {0} ; +#endif for (Int k = 0 ; k < nzmax ; k++) { diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_pack_factor_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_pack_factor_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_pack_factor_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_pack_factor_worker.c 2024-03-16 01:25:07 @@ -29,7 +29,9 @@ Int *Lp = (Int *) L->p ; Int *Li = (Int *) L->i ; Real *Lx = (Real *) L->x ; +#ifdef ZOMPLEX Real *Lz = (Real *) L->z ; +#endif Int *Lnz = (Int *) L->nz ; Int *Lnext = (Int *) L->next ; diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_realloc.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_realloc.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_realloc.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_realloc.c 2024-03-16 01:25:07 @@ -34,7 +34,9 @@ int ok ; bool newly_allocated = (p == NULL) ; +#ifndef NDEBUG void *pold = p ; +#endif size_t nold = (*n) ; p = SuiteSparse_realloc (nnew, *n, size, p, &ok) ; diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_reallocate_column.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_reallocate_column.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_reallocate_column.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_reallocate_column.c 2024-03-16 01:25:07 @@ -84,7 +84,6 @@ need = MAX (need, 1) ; double slack = MAX (Common->grow1, 1.0) * ((double) need) + Common->grow2 ; slack = MIN (slack, (double) (n-j)) ; - size_t nslack = (size_t) floor (slack) ; need = MAX (need, slack) ; need = MAX (need, 1) ; need = MIN (need, n-j) ; diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_reallocate_column_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_reallocate_column_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_reallocate_column_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_reallocate_column_worker.c 2024-03-16 01:25:07 @@ -26,7 +26,9 @@ Int *Lnz = (Int *) L->nz ; Int *Li = (Int *) L->i ; Real *Lx = (Real *) L->x ; +#ifdef ZOMPLEX Real *Lz = (Real *) L->z ; +#endif Int len = Lnz [j] ; //-------------------------------------------------------------------------- diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sort_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_sort_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sort_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_sort_worker.c 2024-03-16 01:25:07 @@ -185,8 +185,12 @@ Int *Ap = (Int *) A->p ; Int *Ai = (Int *) A->i ; Int *Anz = (Int *) A->nz ; +#ifndef PATTERN Real *Ax = (Real *) A->x ; +#ifdef ZOMPLEX Real *Az = (Real *) A->z ; +#endif +#endif Int ncol = A->ncol ; bool packed = A->packed ; uint64_t seed = 42 ; @@ -207,7 +211,6 @@ if (i < ilast) { // sort Ai, Ax, Ax [pa:pend-1] according to row index Ai - Int jnz = pend - pa ; CM_QSRT (Ai, Ax, Az, pa, pend - pa, &seed) ; break ; } diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sparse_to_dense_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_sparse_to_dense_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sparse_to_dense_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_sparse_to_dense_worker.c 2024-03-16 01:25:07 @@ -30,13 +30,19 @@ //-------------------------------------------------------------------------- Real *Xx = (Real *) X->x ; +#ifdef ZOMPLEX Real *Xz = (Real *) X->z ; +#endif Int *Ap = (Int *) A->p ; Int *Ai = (Int *) A->i ; Int *Anz = (Int *) A->nz ; +#ifndef PATTERN Real *Ax = (Real *) A->x ; +#ifdef ZOMPLEX Real *Az = (Real *) A->z ; +#endif +#endif Int nrow = (Int) A->nrow ; Int ncol = (Int) A->ncol ; diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sparse_to_triplet_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_sparse_to_triplet_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_sparse_to_triplet_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_sparse_to_triplet_worker.c 2024-03-16 01:25:07 @@ -21,19 +21,26 @@ // get inputs //-------------------------------------------------------------------------- - Int nrow = A->nrow ; Int ncol = A->ncol ; bool packed = (bool) A->packed ; Int *Ap = (Int *) A->p ; Int *Ai = (Int *) A->i ; +#ifndef PATTERN Real *Ax = (Real *) A->x ; +#ifdef ZOMPLEX Real *Az = (Real *) A->z ; +#endif +#endif Int *Anz = (Int *) A->nz ; Int *Ti = (Int *) T->i ; Int *Tj = (Int *) T->j ; +#ifndef PATTERN Real *Tx = (Real *) T->x ; +#ifdef ZOMPLEX Real *Tz = (Real *) T->z ; +#endif +#endif Int k = 0 ; diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_speye_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_speye_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_speye_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_speye_worker.c 2024-03-16 01:25:07 @@ -22,15 +22,23 @@ Int *Ap = (Int *) A->p ; Int *Ai = (Int *) A->i ; +#ifndef PATTERN Real *Ax = (Real *) A->x ; +#ifdef ZOMPLEX Real *Az = (Real *) A->z ; +#endif +#endif Int ncol = (Int) A->ncol ; Int nrow = (Int) A->nrow ; Int n = MIN (nrow, ncol) ; +#ifndef PATTERN Real onex [2] = {1,0} ; +#ifdef ZOMPLEX Real onez [1] = {0} ; +#endif +#endif for (Int k = 0 ; k < n ; k++) { diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_sym_permuted.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_transpose_sym_permuted.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_sym_permuted.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_transpose_sym_permuted.c 2024-03-16 01:25:07 @@ -44,7 +44,10 @@ #endif { // C(jnew,inew) = conj (A(iold,jold)) - Int pc = Wi [inew]++ ; +#ifdef NUMERIC + Int pc = +#endif + Wi [inew]++ ; #ifdef NUMERIC ASSIGN_CONJ_OR_NCONJ (Cx, Cz, pc, Ax, Az, pa) ; Ci [pc] = jnew ; @@ -53,7 +56,10 @@ else { // C(inew,jnew) = A(iold,jold) - Int pc = Wi [jnew]++ ; +#ifdef NUMERIC + Int pc = +#endif + Wi [jnew]++ ; #ifdef NUMERIC ASSIGN (Cx, Cz, pc, Ax, Az, pa) ; Ci [pc] = inew ; diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_sym_unpermuted.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_transpose_sym_unpermuted.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_sym_unpermuted.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_transpose_sym_unpermuted.c 2024-03-16 01:25:07 @@ -40,7 +40,10 @@ if (i > j) continue ; #endif // C(j,i) = conj (A(i,j)) - Int pc = Wi [i]++ ; +#ifdef NUMERIC + Int pc = +#endif + Wi [i]++ ; #ifdef NUMERIC ASSIGN_CONJ_OR_NCONJ (Cx, Cz, pc, Ax, Az, pa) ; Ci [pc] = j ; diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_sym_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_transpose_sym_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_sym_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_transpose_sym_worker.c 2024-03-16 01:25:07 @@ -28,13 +28,20 @@ Int *Ap = (Int *) A->p ; Int *Ai = (Int *) A->i ; Int *Anz = (Int *) A->nz ; +#ifndef PATTERN Real *Ax = (Real *) A->x ; +#ifdef ZOMPLEX Real *Az = (Real *) A->z ; +#endif +#endif - Int *Cp = (Int *) C->p ; Int *Ci = (Int *) C->i ; +#ifndef PATTERN Real *Cx = (Real *) C->x ; +#ifdef ZOMPLEX Real *Cz = (Real *) C->z ; +#endif +#endif //-------------------------------------------------------------------------- // compute pattern and values of C diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_unsym_template.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_transpose_unsym_template.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_unsym_template.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_transpose_unsym_template.c 2024-03-16 01:25:07 @@ -59,7 +59,10 @@ for ( ; p < pend ; p++) { // get A(i,j) and count it or get its place in C - Int pc = Wi [Ai [p]]++ ; +#ifdef NUMERIC + Int pc = +#endif + Wi [Ai [p]]++ ; #ifdef NUMERIC // C(j,i) = conj (A(i,j)) ASSIGN_CONJ_OR_NCONJ (Cx, Cz, pc, Ax, Az, p) ; diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_unsym_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_transpose_unsym_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_transpose_unsym_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_transpose_unsym_worker.c 2024-03-16 01:25:07 @@ -27,14 +27,21 @@ Int *Ap = (Int *) A->p ; Int *Ai = (Int *) A->i ; Int *Anz = (Int *) A->nz ; +#ifndef PATTERN Real *Ax = (Real *) A->x ; +#ifdef ZOMPLEX Real *Az = (Real *) A->z ; +#endif +#endif Int ncol = A->ncol ; - Int *Cp = (Int *) C->p ; Int *Ci = (Int *) C->i ; +#ifndef PATTERN Real *Cx = (Real *) C->x ; +#ifdef ZOMPLEX Real *Cz = (Real *) C->z ; +#endif +#endif //-------------------------------------------------------------------------- // compute the pattern and values of C diff -ruN src/SuiteSparse/CHOLMOD/Utility/t_cholmod_triplet_to_sparse_worker.c src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_triplet_to_sparse_worker.c --- src/SuiteSparse/CHOLMOD/Utility/t_cholmod_triplet_to_sparse_worker.c 2024-01-24 19:45:24 +++ src/SuiteSparse-patched/CHOLMOD/Utility/t_cholmod_triplet_to_sparse_worker.c 2024-03-16 01:25:07 @@ -25,13 +25,21 @@ Int *Rp = (Int *) R->p ; Int *Ri = (Int *) R->i ; Int *Rnz = (Int *) R->nz ; +#ifndef PATTERN Real *Rx = (Real *) R->x ; +#ifdef ZOMPLEX Real *Rz = (Real *) R->z ; +#endif +#endif Int *Ti = (Int *) T->i ; Int *Tj = (Int *) T->j ; +#ifndef PATTERN Real *Tx = (Real *) T->x ; +#ifdef ZOMPLEX Real *Tz = (Real *) T->z ; +#endif +#endif size_t nrow = T->nrow ; size_t ncol = T->ncol ; Int nz = T->nnz ; Matrix/inst/scripts/disclaimer.txt0000644000175100001440000000106114552244506017062 0ustar hornikusers/* Subsequent to changes made for SuiteSparse by Timothy A. Davis, */ /* which are documented in the file */ /* ../../../../../inst/doc/SuiteSparse/CHOLMOD/SuiteSparse_metis/README.txt, */ /* the METIS library sources, which include this file, have been patched */ /* for R package Matrix by its authors to resolve warnings issued by GCC */ /* and Clang with options -Wall and -Wextra. See the files ssget.sh and */ /* *.patch below ../../../../../inst/scripts for details. */ Matrix/po/0000755000175100001440000000000014576344041012162 5ustar hornikusersMatrix/po/lt.po0000644000175100001440000015131414575137654013157 0ustar hornikusers# Lithuanian translations for Matrix package. # Copyright (C) 2020 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the Matrix package. # Gabrielė Stupurienė , 2020. # msgid "" msgstr "" "Project-Id-Version: Matrix 1.3-3\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-14 15:49-0400\n" "PO-Revision-Date: 2021-02-25 14:30+0200\n" "Last-Translator: Gabrielė Stupurienė \n" "Language-Team: none\n" "Language: lt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && (n%100<11 || n%100>19) ? 0 : " "n%10>=2 && n%10<=9 && (n%100<11 || n%100>19) ? 1 : 2);\n" "X-Generator: Poedit 2.4.2\n" #: Csparse.c:26 Csparse.c:61 Csparse.c:86 Csparse.c:113 Csparse.c:127 #: Csparse.c:132 Csparse.c:137 Csparse.c:411 #, fuzzy, c-format msgid "'%s' failed" msgstr "cs_qr nepavyko" #: Csparse.c:35 cholmod-common.c:54 #, fuzzy, c-format msgid "'%s' slot is not increasing within columns after sorting" msgstr "laukas j nedidėja stulpelio viduje" #: Csparse.c:57 #, fuzzy, c-format msgid "'%s' is empty or not square" msgstr "Matrica nėra kvadratinė" #: Csparse.c:59 Csparse.c:81 Csparse.c:104 solve.c:43 solve.c:988 #, fuzzy, c-format msgid "dimensions of '%s' and '%s' are inconsistent" msgstr "Sistemos, kurią reikia išspręsti, matmenys yra nenuoseklūs" #: Csparse.c:83 #, c-format msgid "%s(%s, %s) requires m-by-n '%s' with m >= n > 0" msgstr "" #: Csparse.c:106 #, c-format msgid "%s(%s, %s) requires m-by-n '%s' with n >= m > 0" msgstr "" #: Csparse.c:194 coerce.c:220 coerce.c:240 coerce.c:250 coerce.c:905 #: coerce.c:911 coerce.c:1015 coerce.c:1501 coerce.c:1521 coerce.c:1531 #: coerce.c:2061 coerce.c:2256 coerce.c:2262 coerce.c:2268 coerce.c:2397 #: coerce.c:2404 coerce.c:2494 coerce.c:2629 coerce.c:2707 coerce.c:2729 #: coerce.c:4327 coerce.c:4396 dense.c:696 matmult.c:939 matmult.c:1291 #: solve.c:719 solve.c:972 solve.c:1104 sparse.c:1234 sparse.c:1626 #, fuzzy, c-format msgid "invalid '%s' to '%s'" msgstr "netinkamas argumentas '%s'" #: Csparse.c:409 #, fuzzy, c-format msgid "failed to open file \"%s\" for writing" msgstr "nepavyko atidaryti failo \"%s\" rašymui" #: attrib.c:229 #, fuzzy msgid "invalid factor name" msgstr "netinkamas argumentas '%s'" #: attrib.c:233 #, c-format msgid "attempt to set factor on %s without '%s' slot" msgstr "" #: bind.c:46 bind.c:153 msgid "number of rows of matrices must match" msgstr "" #: bind.c:48 bind.c:155 msgid "number of columns of matrices must match" msgstr "" #: bind.c:51 bind.c:158 bind.c:182 bind.c:206 cholmod-common.c:608 #: cholmod-common.c:759 cholmod-common.c:874 cholmod-common.c:975 #: cholmod-etc.c:183 cholmod-etc.c:283 cholmod-etc.c:330 coerce.c:215 #: coerce.c:235 coerce.c:260 coerce.c:268 coerce.c:276 coerce.c:341 #: coerce.c:1496 coerce.c:1516 coerce.c:1543 coerce.c:1551 coerce.c:1559 #: matmult.c:28 matmult.c:50 matmult.c:56 #, c-format msgid "dimensions cannot exceed %s" msgstr "" #: bind.c:210 msgid "number of rows of result is not a multiple of vector length" msgstr "" #: bind.c:212 msgid "number of columns of result is not a multiple of vector length" msgstr "" #: bind.c:626 bind.c:691 sparse.c:913 sparse.c:994 #, c-format msgid "%s cannot exceed %s" msgstr "" #: bind.c:756 bind.c:853 cholmod-common.c:978 cholmod-etc.c:333 coerce.c:29 #: coerce.c:518 coerce.c:811 coerce.c:945 coerce.c:2772 coerce.c:3041 #: coerce.c:3146 dense.c:919 matmult.c:151 matmult.c:212 matmult.c:291 #: matmult.c:379 matmult.c:456 matmult.c:550 matmult.c:868 subscript.c:1232 #: subscript.c:1417 utils-R.c:32 #, c-format msgid "attempt to allocate vector of length exceeding %s" msgstr "" #: bind.c:858 matmult.c:1357 msgid "should never happen ..." msgstr "" #: cholmod-common.c:11 cholmod-common.c:34 validity.c:29 validity.c:150 #: validity.c:229 validity.c:248 validity.c:257 validity.c:299 validity.c:316 #: validity.c:350 validity.c:367 validity.c:401 validity.c:403 validity.c:439 #: validity.c:465 validity.c:485 validity.c:926 validity.c:959 validity.c:1041 #: validity.c:1061 validity.c:1127 validity.c:1129 validity.c:1177 #: validity.c:1240 validity.c:1242 validity.c:1288 validity.c:1335 #: validity.c:1384 validity.c:1417 validity.c:1427 validity.c:1440 #: validity.c:1494 validity.c:1496 validity.c:1528 validity.c:1540 #: validity.c:1563 validity.c:1626 validity.c:1645 validity.c:1647 #: validity.c:1679 validity.c:1714 validity.c:1742 #, fuzzy, c-format msgid "'%s' slot is not of type \"%s\"" msgstr "Dim laukas nėra sveikasis skaičius" #: cholmod-common.c:14 validity.c:274 validity.c:285 validity.c:301 #: validity.c:352 validity.c:487 validity.c:928 validity.c:961 validity.c:1063 #: validity.c:1131 validity.c:1179 validity.c:1244 validity.c:1290 #: validity.c:1429 validity.c:1446 validity.c:1498 validity.c:1500 #: validity.c:1530 validity.c:1542 validity.c:1565 validity.c:1681 #: validity.c:1718 validity.c:1746 validity.c:1796 #, fuzzy, c-format msgid "'%s' slot does not have length %s" msgstr "Dim laukas turi būti 2 ilgio" #: cholmod-common.c:18 validity.c:304 validity.c:355 validity.c:1634 #: validity.c:1654 validity.c:1656 #, fuzzy, c-format msgid "first element of '%s' slot is not 0" msgstr "pirmasis lauko p elementas turi būti lygus nuliui" #: cholmod-common.c:23 cholmod-common.c:46 validity.c:34 validity.c:308 #: validity.c:326 validity.c:359 validity.c:377 validity.c:413 validity.c:415 #: validity.c:491 validity.c:1008 validity.c:1020 validity.c:1067 #: validity.c:1140 validity.c:1152 validity.c:1253 validity.c:1265 #: validity.c:1294 validity.c:1345 validity.c:1394 validity.c:1433 #: validity.c:1453 validity.c:1534 validity.c:1550 validity.c:1575 #: validity.c:1639 validity.c:1659 validity.c:1661 validity.c:1688 #, c-format msgid "'%s' slot contains NA" msgstr "" #: cholmod-common.c:26 validity.c:310 validity.c:361 #, fuzzy, c-format msgid "'%s' slot is not nondecreasing" msgstr "laukas p turi būti nemažėjantis" #: cholmod-common.c:29 validity.c:312 validity.c:363 #, c-format msgid "first differences of '%s' slot exceed %s" msgstr "" #: cholmod-common.c:37 validity.c:318 validity.c:369 #, fuzzy, c-format msgid "'%s' slot has length less than %s" msgstr "'Dim' lauko ilgis yra mažesnis nei du" #: cholmod-common.c:49 validity.c:328 validity.c:379 validity.c:417 #: validity.c:420 validity.c:493 validity.c:1010 validity.c:1069 #: validity.c:1142 validity.c:1154 validity.c:1255 validity.c:1267 #: validity.c:1347 validity.c:1396 validity.c:1455 validity.c:1577 #: validity.c:1690 #, fuzzy, c-format msgid "'%s' slot has elements not in {%s}" msgstr "'Dim' lauko ilgis yra mažesnis nei du" #: cholmod-common.c:165 cholmod-common.c:296 cholmod-common.c:1072 #: cholmod-common.c:1075 cholmod-common.c:1108 cholmod-common.c:1126 #, fuzzy, c-format msgid "'%s' failed in '%s'" msgstr "cs_qr nepavyko" #: cholmod-common.c:212 #, fuzzy, c-format msgid "'%s' failed in '%s': %s" msgstr "cs_qr nepavyko" #: cholmod-common.c:601 cholmod-common.c:604 cholmod-common.c:606 #: cholmod-common.c:752 cholmod-common.c:755 cholmod-common.c:757 #: cholmod-common.c:867 cholmod-common.c:870 cholmod-common.c:872 #: cholmod-common.c:969 cholmod-common.c:971 cholmod-etc.c:177 #: cholmod-etc.c:179 cholmod-etc.c:181 cholmod-etc.c:277 cholmod-etc.c:279 #: cholmod-etc.c:281 cholmod-etc.c:324 cholmod-etc.c:326 cs-etc.c:43 #, c-format msgid "wrong '%s'" msgstr "" #: cholmod-common.c:611 cholmod-etc.c:186 #, fuzzy, c-format msgid "'%s' would overflow type \"%s\"" msgstr "Dim laukas nėra sveikasis skaičius" #: cholmod-common.c:615 cholmod-etc.c:190 #, c-format msgid "n+1 would overflow type \"%s\"" msgstr "" #: cholmod-common.c:620 cholmod-etc.c:195 #, fuzzy, c-format msgid "leading principal minor of order %d is not positive" msgstr "vadovaujantis minoras, kurio eilė yra %d, nėra teigiamai apibrėžtas" #: cholmod-common.c:623 cholmod-etc.c:198 #, fuzzy, c-format msgid "leading principal minor of order %d is zero" msgstr "vadovaujantis minoras, kurio eilė yra %d, nėra teigiamai apibrėžtas" #: cholmod-common.c:973 cholmod-etc.c:328 msgid "leading dimension not equal to number of rows" msgstr "" #: cholmod-common.c:1037 #, c-format msgid "" "invalid simplicial Cholesky factorization: structural zero on main diagonal " "in column %d" msgstr "" #: cholmod-common.c:1097 #, fuzzy, c-format msgid "CHOLMOD error '%s' at file '%s', line %d" msgstr "Cholmod klaida '%s' faile %s, eilutė %d" #: cholmod-common.c:1100 #, fuzzy, c-format msgid "CHOLMOD warning '%s' at file '%s', line %d" msgstr "Cholmod įspėjimas '%s' faile %s, eilutė %d" #: coerce.c:24 coerce.c:364 coerce.c:1050 #, fuzzy, c-format msgid "attempt to construct non-square %s" msgstr "Determinantui reikia kvadratinės matricos" #: coerce.c:186 coerce.c:476 coerce.c:1467 coerce.c:1622 #, c-format msgid "second argument of '%s' does not specify a subclass of %s" msgstr "" #: coerce.c:194 coerce.c:200 coerce.c:484 coerce.c:490 coerce.c:925 #: coerce.c:1475 coerce.c:1481 coerce.c:1630 coerce.c:1636 coerce.c:2275 #: coerce.c:3344 coerce.c:3349 #, fuzzy, c-format msgid "'%s' must be \"%s\" or \"%s\"" msgstr "'%s' turi būti '%s'" #: coerce.c:246 coerce.c:496 coerce.c:793 coerce.c:917 coerce.c:1527 #: coerce.c:1642 dense.c:322 dense.c:1102 dense.c:1678 dense.c:1683 #: dense.c:1929 dense.c:2124 sparse.c:784 sparse.c:2449 sparse.c:3141 #: sparse.c:3146 sparse.c:3151 sparse.c:3427 sparse.c:3664 #, fuzzy, c-format msgid "'%s' must be %s or %s" msgstr "'%s' turi būti '%s'" #: coerce.c:266 coerce.c:274 coerce.c:285 coerce.c:1549 coerce.c:1557 #: coerce.c:1568 msgid "nonempty vector supplied for empty matrix" msgstr "" #: coerce.c:287 coerce.c:1570 #, c-format msgid "vector length (%lld) exceeds matrix length (%d * %d)" msgstr "" #: coerce.c:290 coerce.c:1573 #, c-format msgid "matrix length (%d * %d) is not a multiple of vector length (%lld)" msgstr "" #: coerce.c:521 #, c-format msgid "coercing n-by-n %s to %s is not supported for n*n exceeding %s" msgstr "" #: coerce.c:525 coerce.c:815 coerce.c:949 #, c-format msgid "sparse->dense coercion: allocating vector of size %0.1f GiB" msgstr "" #: coerce.c:1196 coerce.c:1941 coerce.c:2948 coerce.c:2954 #, c-format msgid "attempt to construct %s with more than %s nonzero entries" msgstr "" #: coerce.c:3246 #, fuzzy msgid "attempt to pack non-square matrix" msgstr "Determinantui reikia kvadratinės matricos" #: coerce.c:3420 coerce.c:3590 #, c-format msgid "unable to aggregate %s with '%s' and '%s' slots of length exceeding %s" msgstr "" #: coerce.c:4211 #, fuzzy, c-format msgid "attempt to pack a %s" msgstr "Determinantui reikia kvadratinės matricos" #: coerce.c:4330 dense.c:1232 sparse.c:2580 #, fuzzy, c-format msgid "'%s' must be %s or %s or %s" msgstr "'%s' turi būti '%s'" #: dense.c:210 dense.c:215 sparse.c:590 sparse.c:595 #, fuzzy, c-format msgid "'%s' (%d) must be an integer from %s (%d) to %s (%d)" msgstr "'%s' turi būti '%s'" #: dense.c:218 sparse.c:598 #, fuzzy, c-format msgid "'%s' (%d) must be less than or equal to '%s' (%d)" msgstr "'%s' turi būti '%s'" #: dense.c:428 sparse.c:1070 #, fuzzy, c-format msgid "replacement diagonal has incompatible type \"%s\"" msgstr "keitimo įstrižainės ilgis neteisingas" #: dense.c:437 sparse.c:1079 msgid "replacement diagonal has wrong length" msgstr "keitimo įstrižainės ilgis neteisingas" #: dense.c:622 sparse.c:1275 #, fuzzy msgid "attempt to symmetrize a non-square matrix" msgstr "Determinantui reikia kvadratinės matricos" #: dense.c:721 sparse.c:1653 msgid "attempt to get symmetric part of non-square matrix" msgstr "" #: dense.c:873 sparse.c:2083 msgid "attempt to get skew-symmetric part of non-square matrix" msgstr "" #: dense.c:1673 sparse.c:3136 #, fuzzy, c-format msgid "'%s' must be %d or %d" msgstr "'%s' turi būti '%s'" #: dense.c:2156 #, c-format msgid "incorrect left cyclic shift, j (%d) < 0" msgstr "neteisingas kairysis ciklinis pastūmimas, j (%d) < 0" #: dense.c:2159 #, c-format msgid "incorrect left cyclic shift, j (%d) >= k (%d)" msgstr "neteisingas kairysis ciklinis pastūmimas, j (%d) >= k (%d)" #: dense.c:2162 #, c-format msgid "incorrect left cyclic shift, k (%d) > ldx (%d)" msgstr "neteisingas kairysis ciklinis pastūmimas, k (%d) > ldx (%d)" #: dense.c:2215 #, fuzzy msgid "unknown error in getGivens" msgstr "Nežinoma getGivens klaida" #: dense.c:2224 dense.c:2238 dense.c:2268 msgid "X must be a numeric (double precision) matrix" msgstr "X turi būti skaitinė (dvigubo tikslumo) matrica" #: dense.c:2240 dense.c:2270 msgid "y must be a numeric (double precision) matrix" msgstr "y turi būti skaitinė (dvigubo tikslumo) matrica" #: dense.c:2244 dense.c:2274 #, c-format msgid "number of rows in y (%d) does not match number of rows in X (%d)" msgstr "" "eilučių skaičius, esantis y (%d) neatitinka eilučių skaičiaus, esančio X (%d)" #: dense.c:2260 #, fuzzy, c-format msgid "LAPACK dposv returned error code %d" msgstr "Lapack programa dposv grąžino klaidos kodą %d" #: dense.c:2288 dense.c:2294 #, fuzzy, c-format msgid "LAPACK dgels returned error code %d" msgstr "Lapack programa %s grąžino klaidos kodą %d" #: dense.c:2313 msgid "X must be a real (numeric) matrix" msgstr "X turi būti realioji (skaitinė) matrica" #: dense.c:2316 #, fuzzy, c-format msgid "tol, given as %g, must be >= 0" msgstr "tol, kaip %g, turi būti < = 1" #: dense.c:2318 #, c-format msgid "tol, given as %g, must be <= 1" msgstr "tol, kaip %g, turi būti < = 1" #: dense.c:2347 dense.c:2355 #, fuzzy, c-format msgid "LAPACK dgeqrf returned error code %d" msgstr "Pirmasis iškvietimas į dgeqrf grąžino klaidos kodą %d" #: dense.c:2360 dense.c:2383 #, fuzzy, c-format msgid "LAPACK dtrcon returned error code %d" msgstr "Lapack programa dtrcon grąžino klaidos kodą %d" #: determinant.c:33 #, fuzzy msgid "determinant of non-square matrix is undefined" msgstr "Determinantui reikia kvadratinės matricos" #: determinant.c:276 #, fuzzy, c-format msgid "%s(<%s>) does not support structurally rank deficient case" msgstr "%s(): struktūrinio rango deficito atvejis: galbūt WRONG nuliai" #: expm.c:39 msgid "Matrix exponential requires square, non-null matrix" msgstr "Matricos eksponentė reikalauja kvadratinės, ne nulinės matricos" #: expm.c:56 expm.c:58 #, c-format msgid "dgeMatrix_exp: LAPACK routine dgebal returned %d" msgstr "dgeMatrix_exp: LAPACK programa dgebal grąžino %d" #: expm.c:96 #, c-format msgid "dgeMatrix_exp: dgetrf returned error code %d" msgstr "dgeMatrix_exp: dgetrf grąžino klaidos kodą %d" #: expm.c:98 #, c-format msgid "dgeMatrix_exp: dgetrs returned error code %d" msgstr "dgeMatrix_exp: dgetrs grąžino klaidos kodą %d" #: factor.c:330 msgid "dgeMatrix_Schur: argument x must be a non-null square matrix" msgstr "dgeMatrix_Schur: argumentas x turi būti ne nulinė kvadratinė matrica" #: factor.c:343 msgid "dgeMatrix_Schur: first call to dgees failed" msgstr "dgeMatrix_Schur: pirmasis iškvietimas į dgees nepavyko" #: factor.c:352 #, c-format msgid "dgeMatrix_Schur: dgees returned code %d" msgstr "dgeMatrix_Schur: dgees grąžintas kodas %d" #: factor.c:403 sparse.c:196 #, fuzzy, c-format msgid "'%s' is not a number" msgstr "%s nėra sąrašas" #: factor.c:424 #, c-format msgid "LU factorization of m-by-n %s requires m == n" msgstr "" #: factor.c:433 #, c-format msgid "LU factorization of %s failed: out of memory or near-singular" msgstr "" #: factor.c:510 #, c-format msgid "QR factorization of m-by-n %s requires m >= n" msgstr "" #: factor.c:519 #, c-format msgid "QR factorization of %s failed: out of memory" msgstr "" #: factor.c:619 factor.c:897 #, c-format msgid "'%s' is not a number or not finite" msgstr "" #: idz.c:467 idz.c:528 #, c-format msgid "incompatible '%s' and '%s' in '%s'" msgstr "" #: kappa.c:10 kappa.c:54 #, fuzzy, c-format msgid "argument '%s' is not of type \"%s\"" msgstr "argumentas type[1]='%s' turi būti vienos raidės simbolio eilutė" #: kappa.c:13 kappa.c:57 #, fuzzy, c-format msgid "argument '%s' has length %d" msgstr "'%s' eilutės ilgis turi būti 1" #: kappa.c:17 kappa.c:61 #, fuzzy, c-format msgid "argument '%s' (\"%s\") does not have string length %d" msgstr "'%s' eilutės ilgis turi būti 1" #: kappa.c:41 #, c-format msgid "" "argument '%s' (\"%s\") is not \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", or " "\"%s\"" msgstr "" #: kappa.c:75 #, fuzzy, c-format msgid "argument '%s' (\"%s\") is not \"%s\", \"%s\", or \"%s\"" msgstr "'%s' eilutės ilgis turi būti 1" #: kappa.c:238 #, c-format msgid "%s(%s) is undefined: '%s' is not square" msgstr "" #: matmult.c:107 matmult.c:210 matmult.c:289 matmult.c:377 matmult.c:454 #: matmult.c:548 matmult.c:812 matmult.c:862 msgid "non-conformable arguments" msgstr "" #: matmult.c:782 matmult.c:810 #, c-format msgid "'%s' does not support complex matrices" msgstr "" #: objects.c:23 #, c-format msgid "unexpected type \"%s\" in '%s'" msgstr "" #: objects.c:41 objects.c:58 #, c-format msgid "unexpected kind \"%c\" in '%s'" msgstr "" #: perm.c:26 perm.c:106 msgid "attempt to get sign of non-permutation" msgstr "" #: perm.c:51 perm.c:123 msgid "attempt to invert non-permutation" msgstr "" #: perm.c:66 #, fuzzy msgid "invalid transposition vector" msgstr "neleistinas eilutės indeksas padėtyje %d" #: perm.c:79 perm.c:81 perm.c:96 perm.c:98 perm.c:113 perm.c:133 perm.c:145 #, fuzzy, c-format msgid "'%s' is not of type \"%s\"" msgstr "Dim laukas nėra sveikasis skaičius" #: perm.c:83 perm.c:100 perm.c:147 #, fuzzy, c-format msgid "'%s' does not have length %d" msgstr "'%s' lauko ilgis turi būti 1" #: perm.c:86 perm.c:103 #, c-format msgid "'%s' is NA" msgstr "" #: perm.c:115 perm.c:138 #, fuzzy, c-format msgid "'%s' or '%s' is not of type \"%s\"" msgstr "Dim laukas nėra sveikasis skaičius" #: perm.c:117 perm.c:140 #, fuzzy, c-format msgid "'%s' or '%s' does not have length %d" msgstr "'%s' lauko ilgis turi būti 1" #: perm.c:120 perm.c:143 #, c-format msgid "'%s' or '%s' is NA" msgstr "" #: perm.c:136 #, c-format msgid "'%s' has length exceeding %s" msgstr "" #: perm.c:150 #, c-format msgid "'%s' is NA or less than %s" msgstr "" #: solve.c:38 #, fuzzy, c-format msgid "'%s' is not square" msgstr "Matrica nėra kvadratinė" #: solve.c:497 #, c-format msgid "%s(<%s>, <%s>) failed: out of memory" msgstr "" #: solve.c:618 #, fuzzy, c-format msgid "attempt to construct %s with more than %s nonzero elements" msgstr "Determinantui reikia kvadratinės matricos" #: subscript.c:1542 subscript.c:1695 subscript.c:1938 subscript.c:2122 #, c-format msgid "%s too dense for %s; would have more than %s nonzero entries" msgstr "" #: subscript.c:2209 #, c-format msgid "NA subscripts in %s not supported for '%s' inheriting from %s" msgstr "" #: t_subassign.c:141 msgid "invalid class of 'x' in Csparse_subassign()" msgstr "netinkama 'x' klasė, esanti Csparse_subassign()" #: t_subassign.c:143 msgid "invalid class of 'value' in Csparse_subassign()" msgstr "netinkama 'value' klasė, esanti Csparse_subassign()" #: t_subassign.c:186 #, c-format msgid "x[] <- val: val is coerced to logical for \"%s\" x" msgstr "x[] <- val: val yra paverstas į loginį \"%s\" x" #: t_subassign.c:191 #, c-format msgid "" "x[] <- val: val should be integer or logical, is coerced to integer, for " "\"%s\" x" msgstr "" "x[] <- val: val turėtų būti sveikasis skaičius arba loginis, yra pakeistas į " "sveikąjį skaičių dėl \"%s\" x" #: t_subassign.c:198 msgid "programming error in Csparse_subassign() should never happen" msgstr "programavimo klaida Csparse_subassign() niekada neturėtų įvykti" #: utils-R.c:30 utils-R.c:116 #, c-format msgid "indices would exceed %s" msgstr "" #: utils-R.c:235 utils-R.c:270 utils-R.c:281 utils-R.c:312 msgid "Argument must be numeric-like atomic vector" msgstr "Argumentas turi būti skaitinis atominis vektorius" #: utils-R.c:345 msgid "'data' must be of a vector type" msgstr "'data' turi būti vektoriaus tipo" #: utils-R.c:352 #, c-format msgid "invalid '%s' argument" msgstr "netinkamas argumentas '%s'" #: utils-R.c:359 utils-R.c:367 msgid "non-numeric matrix extent" msgstr "neskaitinės matricos dydis" #: utils-R.c:362 msgid "invalid 'nrow' value (too large or NA)" msgstr "neleistina 'nrow' reikšmė (per didelė arba NA)" #: utils-R.c:364 msgid "invalid 'nrow' value (< 0)" msgstr "neleistina 'nrow' reikšmė (< 0)" #: utils-R.c:370 msgid "invalid 'ncol' value (too large or NA)" msgstr "neleistina 'ncol' reikšmė (per didelė arba NA)" #: utils-R.c:372 msgid "invalid 'ncol' value (< 0)" msgstr "neleistina 'ncol' reikšmė (< 0)" #: utils-R.c:390 #, fuzzy, c-format msgid "" "data length [%lld] is not a sub-multiple or multiple of the number of rows " "[%d]" msgstr "duomenų ilgis [%d] nėra eilučių skaičiaus pogrupis ar kartotinis [%d]" #: utils-R.c:395 #, fuzzy, c-format msgid "" "data length [%lld] is not a sub-multiple or multiple of the number of " "columns [%d]" msgstr "" "duomenų ilgis [%d] nėra stulpelių skaičiaus pogrupis ar kartotinis [%d]" #: utils-R.c:399 msgid "data length exceeds size of matrix" msgstr "duomenų ilgis viršija matricos dydį" #: utils-R.c:404 msgid "too many elements specified" msgstr "nurodyta per daug elementų" #: utils-R.c:545 msgid "Argument ij must be 2-column integer matrix" msgstr "Argumentas ij turi būti 2 stulpelių sveikųjų skaičių matrica" #: utils-R.c:570 msgid "subscript 'i' out of bounds in M[ij]" msgstr "apatinis indeksas 'i' už M[ij] ribų" #: utils-R.c:572 msgid "subscript 'j' out of bounds in M[ij]" msgstr "apatinis indeksas 'j' už M[ij] ribų" #: utils-R.c:626 msgid "i and j must be integer vectors of the same length" msgstr "i ir j turi būti to paties ilgio sveikieji vektoriai" #: validity.c:31 validity.c:52 validity.c:231 validity.c:250 validity.c:259 #: validity.c:441 validity.c:467 validity.c:977 validity.c:1419 validity.c:1443 #, fuzzy, c-format msgid "'%s' slot does not have length %d" msgstr "Dim laukas turi būti 2 ilgio" #: validity.c:36 validity.c:932 validity.c:965 #, fuzzy, c-format msgid "'%s' slot has negative elements" msgstr "'Dim' lauko ilgis yra mažesnis nei du" #: validity.c:50 validity.c:164 #, fuzzy, c-format msgid "'%s' slot is not a list" msgstr "Dim laukas nėra sveikasis skaičius" #: validity.c:68 #, fuzzy, c-format msgid "%s[[%d]] is not NULL or a vector" msgstr "Dimnames[%d] nėra simbolių vektorius" #: validity.c:71 #, fuzzy, c-format msgid "length of %s[[%d]] (%lld) is not equal to %s[%d] (%d)" msgstr "length(Dimnames[%d]) skiriasi nuo Dim[%d], kuris yra %d" #: validity.c:170 #, c-format msgid "'%s' slot has no '%s' attribute" msgstr "" #: validity.c:181 validity.c:244 validity.c:435 validity.c:506 validity.c:1082 #: validity.c:1413 validity.c:1774 #, c-format msgid "%s[1] != %s[2] (matrix is not square)" msgstr "" #: validity.c:206 validity.c:219 #, c-format msgid "%s[1] differs from %s[2]" msgstr "" #: validity.c:234 validity.c:253 validity.c:262 validity.c:444 #, fuzzy, c-format msgid "'%s' slot is not \"%s\" or \"%s\"" msgstr "x laukas nėra \"double\"" #: validity.c:331 validity.c:1580 #, fuzzy, c-format msgid "'%s' slot is not increasing within columns" msgstr "laukas j nedidėja stulpelio viduje" #: validity.c:382 #, fuzzy, c-format msgid "'%s' slot is not increasing within rows" msgstr "laukas j nedidėja stulpelio viduje" #: validity.c:406 validity.c:790 validity.c:816 validity.c:842 validity.c:1043 #: validity.c:1649 validity.c:1651 #, fuzzy, c-format msgid "'%s' and '%s' slots do not have equal length" msgstr "Dim laukas turi būti 2 ilgio" #: validity.c:409 #, c-format msgid "'%s' slot has nonzero length but %s is 0" msgstr "" #: validity.c:450 validity.c:454 #, fuzzy, c-format msgid "'%s' slot is \"%s\" but '%s' slot does not have length %s" msgstr "Dim laukas turi būti 2 ilgio" #: validity.c:470 #, fuzzy, c-format msgid "'%s' slot is not %d or %d" msgstr "x laukas nėra \"double\"" #: validity.c:476 validity.c:479 #, c-format msgid "%s-by-%s %s invalid for positive '%s' when %s=%d" msgstr "" #: validity.c:516 validity.c:1145 validity.c:1157 validity.c:1258 #: validity.c:1270 validity.c:1350 validity.c:1399 validity.c:1458 #, c-format msgid "'%s' slot contains duplicates" msgstr "" #: validity.c:544 validity.c:589 validity.c:635 validity.c:680 validity.c:724 #: validity.c:759 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries below the diagonal" msgstr "uplo='U' neturi turėti sparse įrašų po įstrižainės" #: validity.c:554 validity.c:602 validity.c:645 validity.c:693 validity.c:729 #: validity.c:770 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries above the diagonal" msgstr "uplo='L' neturi turėti sparse įrašų virš įstrižainės" #: validity.c:592 validity.c:605 validity.c:683 validity.c:696 validity.c:762 #: validity.c:773 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries on the diagonal" msgstr "uplo='U' neturi turėti sparse įrašų po įstrižainės" #: validity.c:878 validity.c:902 validity.c:906 msgid "matrix has negative diagonal elements" msgstr "" #: validity.c:922 validity.c:950 validity.c:954 msgid "matrix has nonunit diagonal elements" msgstr "" #: validity.c:974 validity.c:999 validity.c:1793 #, fuzzy, c-format msgid "'%s' slot is not of type \"%s\" or \"%s\"" msgstr "Dim laukas nėra sveikasis skaičius" #: validity.c:982 validity.c:989 #, fuzzy, c-format msgid "'%s' slot is NA" msgstr "Dim laukas nėra sveikasis skaičius" #: validity.c:984 validity.c:991 #, fuzzy, c-format msgid "'%s' slot is negative" msgstr "'Dim' lauko ilgis yra mažesnis nei du" #: validity.c:993 #, fuzzy, c-format msgid "'%s' slot exceeds %s" msgstr "'%s' turi būti '%s'" #: validity.c:1003 #, fuzzy, c-format msgid "'%s' slot has length greater than '%s' slot" msgstr "'Dim' lauko ilgis yra mažesnis nei du" #: validity.c:1013 validity.c:1641 validity.c:1663 validity.c:1665 #, fuzzy, c-format msgid "'%s' slot is not increasing" msgstr "laukas j nedidėja stulpelio viduje" #: validity.c:1023 #, fuzzy, c-format msgid "'%s' slot has elements not in {%s} after truncation towards zero" msgstr "'Dim' lauko ilgis yra mažesnis nei du" #: validity.c:1026 #, fuzzy, c-format msgid "'%s' slot is not increasing after truncation towards zero" msgstr "laukas j nedidėja stulpelio viduje" #: validity.c:1092 validity.c:1119 validity.c:1781 validity.c:1788 #, fuzzy, c-format msgid "dimensions of '%s' slot are not identical to '%s'" msgstr "X ir y matmenys nesuderinami su %s" #: validity.c:1094 #, c-format msgid "'%s' slot is upper (not lower) triangular" msgstr "" #: validity.c:1107 #, c-format msgid "'%s' slot has nonunit diagonal elements" msgstr "" #: validity.c:1121 #, c-format msgid "'%s' slot is lower (not upper) triangular" msgstr "" #: validity.c:1133 validity.c:1246 validity.c:1337 validity.c:1386 #, fuzzy, c-format msgid "'%s' slot does not have length %s or length %s" msgstr "Dim laukas turi būti 2 ilgio" #: validity.c:1173 msgid "matrix has more columns than rows" msgstr "" #: validity.c:1193 #, fuzzy, c-format msgid "'%s' slot has fewer than %s rows" msgstr "'Dim' lauko ilgis yra mažesnis nei du" #: validity.c:1195 #, fuzzy, c-format msgid "'%s' slot has more than %s rows" msgstr "'Dim' lauko ilgis yra mažesnis nei du" #: validity.c:1197 validity.c:1219 #, fuzzy, c-format msgid "'%s' slot does not have %s columns" msgstr "Dim laukas turi būti 2 ilgio" #: validity.c:1204 #, fuzzy, c-format msgid "'%s' slot must be lower trapezoidal but has entries above the diagonal" msgstr "uplo='L' neturi turėti sparse įrašų virš įstrižainės" #: validity.c:1217 #, fuzzy, c-format msgid "'%s' slot does not have %s row" msgstr "Dim laukas turi būti 2 ilgio" #: validity.c:1226 #, fuzzy, c-format msgid "'%s' slot must be upper trapezoidal but has entries below the diagonal" msgstr "uplo='U' neturi turėti sparse įrašų po įstrižainės" #: validity.c:1230 #, c-format msgid "'%s' slot has negative diagonal elements" msgstr "" #: validity.c:1296 #, c-format msgid "'%s' slot has elements not in {%s}\\{%s}" msgstr "" #: validity.c:1305 #, c-format msgid "'%s' slot has unpaired negative elements" msgstr "" #: validity.c:1331 validity.c:1375 validity.c:1379 validity.c:1727 #: validity.c:1759 msgid "Cholesky factor has negative diagonal elements" msgstr "" #: validity.c:1422 #, fuzzy, c-format msgid "%s[%d] (%s) is not in %s" msgstr "%s nėra sąrašas" #: validity.c:1435 validity.c:1536 #, fuzzy, c-format msgid "%s is not in {%s}" msgstr "%s nėra sąrašas" #: validity.c:1472 #, c-format msgid "%s is not representable as \"%s\"" msgstr "" #: validity.c:1477 validity.c:1483 #, c-format msgid "%s[%d] (%s) is not %d or %d" msgstr "" #: validity.c:1480 validity.c:1596 validity.c:1599 validity.c:1602 #, c-format msgid "%s[%d] (%s) is not %d" msgstr "" #: validity.c:1505 #, c-format msgid "%s has elements not in {%s}" msgstr "" #: validity.c:1508 #, c-format msgid "%s has elements not in {%s}\\{%s}" msgstr "" #: validity.c:1511 #, c-format msgid "%s is %d but columns are not stored in increasing order" msgstr "" #: validity.c:1514 validity.c:1517 #, c-format msgid "traversal of '%s' slot does not complete in exactly %s steps" msgstr "" #: validity.c:1523 validity.c:1525 #, fuzzy, c-format msgid "%s is not %d" msgstr "%s nėra sąrašas" #: validity.c:1546 #, c-format msgid "column '%s' is stored first but %s is not 0" msgstr "" #: validity.c:1552 #, fuzzy, c-format msgid "'%s' slot is not increasing when traversed in stored column order" msgstr "laukas j nedidėja stulpelio viduje" #: validity.c:1554 #, c-format msgid "'%s' slot allocates fewer than %s elements for column '%s'" msgstr "" #: validity.c:1557 #, c-format msgid "'%s' slot allocates more than %s elements for column '%s'" msgstr "" #: validity.c:1571 #, c-format msgid "first entry in column '%s' does not have row index '%s'" msgstr "" #: validity.c:1605 validity.c:1608 #, c-format msgid "%s[%d] (%s) is negative" msgstr "" #: validity.c:1611 #, c-format msgid "%s[%d] (%s) is not less than %s" msgstr "" #: validity.c:1629 #, fuzzy, c-format msgid "'%s' slot has length less than %d" msgstr "'Dim' lauko ilgis yra mažesnis nei du" #: validity.c:1631 #, fuzzy, c-format msgid "'%s' slot has length greater than %s" msgstr "'Dim' lauko ilgis yra mažesnis nei du" #: validity.c:1636 #, fuzzy, c-format msgid "last element of '%s' slot is not %s" msgstr "pirmasis lauko p elementas turi būti lygus nuliui" #: validity.c:1669 #, c-format msgid "first differences of '%s' slot are less than those of '%s' slot" msgstr "" #: validity.c:1672 #, c-format msgid "supernode lengths exceed %s" msgstr "" #: validity.c:1674 #, c-format msgid "first differences of '%s' slot are not equal to supernode lengths" msgstr "" #: validity.c:1694 #, c-format msgid "" "'%s' slot is wrong within diagonal blocks (row and column indices do not " "coincide)" msgstr "" #: validity.c:1697 #, fuzzy, c-format msgid "'%s' slot is not increasing within supernodes" msgstr "laukas j nedidėja stulpelio viduje" #: validity.c:1812 #, fuzzy, c-format msgid "invalid class \"%s\" object: %s" msgstr "netinkama objekto klasė į %s" #: vector.c:90 #, c-format msgid "%s length cannot exceed %s" msgstr "" #, fuzzy, c-format #~ msgid "dgeMatrix_svd(x,*): dim(x)[j] = %d is too large" #~ msgstr "Matricos matmenys %d x %d (= %g) yra per dideli" #, c-format #~ msgid "diagonal element %d of Cholesky factor is missing" #~ msgstr "trūksta Choleskio faktoriaus įstrižainės elemento %d" #, c-format #~ msgid "cholmod_factorize_p failed: status %d, minor %d of ncol %d" #~ msgstr "cholmod_factorize_p nepavyko: būsena %d, nedideli %d iš ncol %d" #~ msgid "cholmod_change_factor failed" #~ msgstr "cholmod_change_factor nepavyko" #~ msgid "cholmod_write_sparse returned error code" #~ msgstr "cholmod_write_sparse grąžintas klaidos kodas" #, c-format #~ msgid "%s = '%s' (back-permuted) is experimental" #~ msgstr "%s = '%s' (atgalinis) yra eksperimentinis" #~ msgid "diag_tC(): invalid 'resultKind'" #~ msgstr "diag_tC(): netinkamas 'resultKind'" #, fuzzy #~ msgid "complex matrices are not yet supported" #~ msgstr "sudėtinis sparse matricos kodas dar neįrašytas" #~ msgid "Argument rho must be an environment" #~ msgstr "Argumentas rho turi būti aplinka" #~ msgid "invalid class of object to as_cholmod_sparse" #~ msgstr "netinkama objekto klasė į as_cholmod_sparse" #~ msgid "invalid object passed to as_cholmod_sparse" #~ msgstr "neleistinas objektas perduotas į as_cholmod_sparse" #~ msgid "in_place cholmod_sort returned an error code" #~ msgstr "in_place cholmod_sort grąžino klaidos kodą" #~ msgid "cholmod_sort returned an error code" #~ msgstr "cholmod_sort grąžino klaidos kodą" #~ msgid "chm_sparse_to_SEXP(, *): invalid 'Rkind' (real kind code)" #~ msgstr "" #~ "chm_sparse_to_SEXP (, *): neteisingas 'Rkind' (tikrasis rūšies " #~ "kodas)" #~ msgid "unknown xtype in cholmod_sparse object" #~ msgstr "nežinomas xtype cholmod_sparse objekte" #~ msgid "complex sparse matrix code not yet written" #~ msgstr "sudėtinis sparse matricos kodas dar neįrašytas" #~ msgid "Symmetric and triangular both set" #~ msgstr "Simetriškas ir trikampis abiejų rinkinys" #~ msgid "invalid class of object to as_cholmod_triplet" #~ msgstr "netinkama objekto klasė į as_cholmod_triplet" #~ msgid "as_cholmod_triplet(): could not reallocate for internal diagU2N()" #~ msgstr "as_cholmod_triplet(): nepavyko perskirstyti vidiniam diagU2N()" #~ msgid "unknown xtype in cholmod_triplet object" #~ msgstr "nežinomas xtype cholmod_triplet objekte" #~ msgid "invalid class of object to as_cholmod_dense" #~ msgstr "netinkama objekto klasė į as_cholmod_dense" #, c-format #~ msgid "" #~ "chm_transpose_dense(ans, x) not yet implemented for %s different from %s" #~ msgstr "" #~ "chm_transpose_dense(ans, x) dar neįgyvendintas dėl %s skiriasi nuo %s" #, c-format #~ msgid "Unable to initialize cholmod: error code %d" #~ msgstr "Neįmanoma inicijuoti cholmod: klaidos kodas %d" #~ msgid "unknown 'Rkind'" #~ msgstr "nežinomas 'Rkind'" #~ msgid "unknown xtype" #~ msgstr "nežinomas xtype" #~ msgid "code for cholmod_dense with holes not yet written" #~ msgstr "cholmod_dense kodas su dar neįrašytais tarpais" #~ msgid "don't know if a dense pattern matrix makes sense" #~ msgstr "nežinau, ar tankio modelio matrica turi prasmę" #, fuzzy #~ msgid "object of invalid class to 'as_cholmod_factor()'" #~ msgstr "netinkama objekto klasė į as_cholmod_factor" #~ msgid "failure in as_cholmod_factor" #~ msgstr "klaida, esanti as_cholmod_factor" #~ msgid "CHOLMOD factorization was unsuccessful" #~ msgstr "CHOLMOD faktoringas buvo nesėkmingas" #, c-format #~ msgid "f->xtype of %d not recognized" #~ msgstr "neatpažintas %d f->xtype" #, c-format #~ msgid "chm_diagN2U(): nrow=%d, ncol=%d" #~ msgstr "chm_diagN2U(): nrow=%d, ncol=%d" #, c-format #~ msgid "chm_diagN2U(x, uploT = %d): uploT should be +- 1" #~ msgstr "chm_diagN2U(x, uploT = %d): uploT turi būti +- 1" #~ msgid "dgCMatrix_lusol requires a square, non-empty matrix" #~ msgstr "dgCMatrix_lusol reikia kvadratinės, netuščios matricos" #~ msgid "Dimensions of system to be solved are inconsistent" #~ msgstr "Sistemos, kurią reikia išspręsti, matmenys yra nenuoseklūs" #~ msgid "cs_lusol failed" #~ msgstr "cs_lusol nepavyko" #~ msgid "dgCMatrix_qrsol(., order) needs order in {0,..,3}" #~ msgstr "dgCMatrix_qrsol(., tvarka) reikia tvarkos {0,..,3}" #, c-format #~ msgid "" #~ "dgCMatrix_qrsol(<%d x %d>-matrix) requires a 'tall' rectangular matrix" #~ msgstr "" #~ "dgCMatrix_qrsol(<%d x %d>-matrix) reikalauja 'tall' stačiakampės matricos" #~ msgid "cs_qrsol() failed inside dgCMatrix_qrsol()" #~ msgstr "cs_qrsol() nepavyko viduje dgCMatrix_qrsol ()" #~ msgid "dgCMatrix_cholsol requires a 'short, wide' rectangular matrix" #~ msgstr "dgCMatrix_cholsol reikia 'short, wide' stačiakampės matricos" #~ msgid "cholmod_sdmult error (rhs)" #~ msgstr "cholmod_sdmult klaida (rhs)" #, c-format #~ msgid "cholmod_factorize failed: status %d, minor %d from ncol %d" #~ msgstr "cholmod_factorize nepavyko: būsena %d, nedideli %d iš ncol %d" #, c-format #~ msgid "cholmod_solve (CHOLMOD_A) failed: status %d, minor %d from ncol %d" #~ msgstr "" #~ "cholmod_solve (CHOLMOD_A) nepavyko: būsena %d, nedideli %d iš ncol %d" #~ msgid "cholmod_sdmult error (resid)" #~ msgstr "cholmod_sdmult klaida (resid)" #~ msgid "SuiteSparseQR_C_QR returned an error code" #~ msgstr "SuiteSparseQR_C_QR grąžino klaidos kodą" #, fuzzy, c-format #~ msgid "LAPACK routine '%s': matrix is exactly singular, %s[i,i]=0, i=%d" #~ msgstr "Lapack programa dgetrs: sistema yra tiksliai singuliari" #, fuzzy, c-format #~ msgid "" #~ "LAPACK routine '%s': leading principal minor of order %d is not positive" #~ msgstr "vadovaujantis minoras, kurio eilė yra %d, nėra teigiamai apibrėžtas" #, fuzzy #~ msgid "missing 'Matrix' namespace; should never happen" #~ msgstr "trūksta 'Matrix' vardų srities: niekada neturėtų įvykti" #, fuzzy #~ msgid "'Matrix' namespace not determined correctly" #~ msgstr "Matricos vardų sritis nustatyta neteisingai" #~ msgid "Csparse_sort(x): x is not a valid (apart from sorting) CsparseMatrix" #~ msgstr "" #~ "Csparse_sort(x): x nėra galiojantis (išskyrus rūšiavimą) CsparseMatrix" #, c-format #~ msgid "Impossible Rk_x/Rk_y in Csparse_%s(), please report" #~ msgstr "Neįmanoma Rk_x/Rk_y, esanti Csparse_%s(), prašome pranešti" #, c-format #~ msgid "chm_MOD_xtype() was not successful in Csparse_%s(), please report" #~ msgstr "chm_MOD_xtype() nebuvo sėkmingas Csparse_%s(), prašome pranešti" #, c-format #~ msgid "the number of columns differ in R_rbind2_vector: %d != %d" #~ msgstr "stulpelių skaičius skiriasi R_rbind2_vector: %d != %d" #~ msgid "csp_eye argument n must be positive" #~ msgstr "csp_eye argumentas n turi būti teigiamas" #~ msgid "invalid class of 'x' in Matrix_as_cs(a, x)" #~ msgstr "netinkama 'x' klasė, esanti Matrix_as_cs(a, x)" #, c-format #~ msgid "invalid class of object to %s" #~ msgstr "netinkama objekto klasė į %s" #, c-format #~ msgid "cs matrix not compatible with class '%s'" #~ msgstr "cs matrica nesuderinama su klase '%s'" #, c-format #~ msgid "Inappropriate class cl='%s' in Matrix_css_to_SEXP(S, cl, ..)" #~ msgstr "Netinkama klasė cl ='%s', esanti Matrix_css_to_SEXP(S, cl, ..)" #, c-format #~ msgid "Inappropriate class cl='%s' in Matrix_csn_to_SEXP(S, cl, ..)" #~ msgstr "Netinkama klasė cl ='%s', esanti Matrix_csn_to_SEXP(S, cl, ..)" #, c-format #~ msgid "Dimensions of x and y are not compatible for %s" #~ msgstr "X ir y matmenys nesuderinami su %s" #~ msgid "Argument y must be numeric, integer or logical" #~ msgstr "Argumentas y turi būti skaitinis, sveikasis skaičius arba loginis" #~ msgid "Matrices are not conformable for multiplication" #~ msgstr "Matricos nėra tinkamos daugybai" #~ msgid "dtrMatrix must be square" #~ msgstr "dtrMatrix turi būti kvadratinė" #, c-format #~ msgid "Dimensions of a (%d,%d) and b (%d,%d) do not conform" #~ msgstr "Matmenys a (%d,%d) ir b (%d,%d) neatitinka" #~ msgid "right=TRUE is not yet implemented __ FIXME" #~ msgstr "right=TRUE dar neįgyvendinta __ FIXME" #, c-format #~ msgid "cholmod_change_factor failed with status %d" #~ msgstr "cholmod_change_factor nepavyko su būsena %d" #~ msgid "system argument is not valid" #~ msgstr "sistemos argumentas neleistinas" #, c-format #~ msgid "cholmod_updown() returned %d" #~ msgstr "cholmod_updown() grąžintas %d" #~ msgid "cholmod_drop() failed" #~ msgstr "cholmod_drop() nepavyko" #, fuzzy #~ msgid "'off' does not have length 1" #~ msgstr "'%s' lauko ilgis turi būti 1" #, fuzzy #~ msgid "invalid 'code' to 'R_matrix_as_dense()'" #~ msgstr "netinkama klasė '%s' į dup_mMatrix_as_dgeMatrix" #, fuzzy #~ msgid "invalid 'uplo' to 'R_matrix_as_dense()'" #~ msgstr "netinkama klasė '%s' į dup_mMatrix_as_dgeMatrix" #, fuzzy #~ msgid "invalid 'diag' to 'R_matrix_as_dense()'" #~ msgstr "netinkama klasė '%s' į dup_mMatrix_as_dgeMatrix" #, fuzzy #~ msgid "invalid argument 'system'" #~ msgstr "netinkamas argumentas '%s'" #, fuzzy #~ msgid "dimensions of 'qr' and 'y' are inconsistent" #~ msgstr "Sistemos, kurią reikia išspręsti, matmenys yra nenuoseklūs" #, fuzzy #~ msgid "invalid 'op'" #~ msgstr "netinkamas argumentas '%s'" #, fuzzy #~ msgid "'names' must be TRUE or FALSE" #~ msgstr "'uplo' turi būti UPP arba LOW" #~ msgid "Csparse_crossprod(): error return from cholmod_aat()" #~ msgstr "Csparse_crossprod(): klaida grąžinima iš cholmod_aat()" #, fuzzy #~ msgid "invalid 'kind' to 'R_sparse_as_kind()'" #~ msgstr "netinkama 'x' klasė, esanti Csparse_subassign()" #~ msgid "slot p must have length = nrow(.) + 1" #~ msgstr "lauko p ilgis turi būti = nrow(.) + 1" #~ msgid "last element of slot p must match length of slots j and x" #~ msgstr "paskutinis lauko p elementas turi atitikti laukų j ir x ilgį" #~ msgid "all column indices must be between 0 and ncol-1" #~ msgstr "visi stulpelių indeksai turi būti nuo 0 iki ncol-1" #~ msgid "slot j is not *strictly* increasing inside a column" #~ msgstr "laukas j nėra *griežtai* didėjantis stulpelio viduje" #~ msgid "Csparse_to_nz_pattern(x, tri = NA): 'tri' is taken as TRUE" #~ msgstr "Csparse_to_nz_pattern(x, tri = NA): 'tri' laikoma TRUE" #~ msgid "not a 'n.CMatrix'" #~ msgstr "ne 'n.CMatrix'" #, c-format #~ msgid "nz2Csparse(): invalid/non-implemented r_kind = %d" #~ msgstr "nz2Csparse(): netinkamas/neįgyvendintas r_kind = %d" #~ msgid "Nonsymmetric matrix in Csparse_symmetric_to_general" #~ msgstr "Nesimetrinė matrica, esanti Csparse_symmetric_to_general" #~ msgid "Csparse_general_to_symmetric(): matrix is not square!" #~ msgstr "Csparse_general_to_symmetric (): matrica nėra kvadratinė!" #~ msgid "Index i must be NULL or integer" #~ msgstr "Rodyklė i turi būti NULL arba sveikasis skaičius" #~ msgid "Index j must be NULL or integer" #~ msgstr "Rodyklė j turi būti NULL arba sveikasis skaičius" #, c-format #~ msgid "negative vector lengths not allowed: np = %d, nnz = %d" #~ msgstr "neigiami vektoriaus ilgiai neleidžiami: np = %d, nnz = %d" #~ msgid "exactly 1 of 'i', 'j' or 'p' must be NULL" #~ msgstr "tiksliai 1 iš 'i', 'j' arba 'p' turi būti NULL" #, c-format #~ msgid "np = %d, must be zero when p is NULL" #~ msgstr "np = %d, turi būti nulis, kai p yra NULL" #, c-format #~ msgid "p[0] = %d, should be zero" #~ msgstr "p[0] = %d, turėtų būti nulis" #~ msgid "p must be non-decreasing" #~ msgstr "p turi būti nemažėjantis" #, c-format #~ msgid "Inconsistent dimensions: np = 0 and nnz = %d" #~ msgstr "Nenuoseklūs matmenys: np = 0 ir nnz = %d" #, c-format #~ msgid "invalid column index at position %d" #~ msgstr "neleistinas stulpelio indeksas padėtyje %d" #, c-format #~ msgid "strlen of cls argument = %d, should be 8" #~ msgstr "cls argumento strlen = %d, turėtų būti 8" #, c-format #~ msgid "cls = \"%s\" does not end in \"CMatrix\"" #~ msgstr "cls = \"%s\" nesibaigia \"CMatrix\"" #, c-format #~ msgid "cls = \"%s\" must begin with 'd', 'l' or 'n'" #~ msgstr "cls = \"%s\" turi prasidėti 'd', 'l' arba 'n'" #~ msgid "Only 'g'eneral sparse matrix types allowed" #~ msgstr "Leidžiami tik 'g'eneral sparse matricų tipai" #~ msgid "code not yet written for cls = \"lgCMatrix\"" #~ msgstr "kodas dar neparašytas dėl cls = \"lgCMatrix\"" #, c-format #~ msgid "%s must be (traditional R) matrix" #~ msgstr "%s turi būti (tradicinė R) matrica" #, c-format #~ msgid "%s must be character string" #~ msgstr "%s turi būti simbolių eilutė" #, c-format #~ msgid "nrow * ncol = %d * %d must equal length(x) = %ld" #~ msgstr "nrow * ncol = %d * %d turi būti lygus length(x) = %ld" #, c-format #~ msgid "strlen of cls argument = %d, should be 9" #~ msgstr "cls argumento strlen = %d, turėtų būti 9" #, c-format #~ msgid "cls = \"%s\" must begin with 'd', 'l' or 'n' for now" #~ msgstr "cls = \"%s\" turi prasidėti 'd', 'l' arba 'n'" #, c-format #~ msgid "%s must be a logical or double vector" #~ msgstr "%s turi būti loginis arba dvigubas vektorius" #, c-format #~ msgid "argument type[1]='%s' must be one of 'M','1','O','I','F' or 'E'" #~ msgstr "" #~ "argumentas type[1]='%s' turi būti vienas iš 'M','1','O','I','F' arba 'E'" #, c-format #~ msgid "argument type[1]='%s' must be one of '1','O', or 'I'" #~ msgstr "argumentas type[1]='%s' turi būti vienas iš '1','O' arba 'I'" #~ msgid "object must be a named, numeric vector" #~ msgstr "objektas turi būti įvardytas, skaitinis vektorius" #~ msgid "'factors' slot must be a named list" #~ msgstr "'factors' laukas turi būti įvardytas sąrašas" #~ msgid "Matrix object has no 'factors' slot" #~ msgstr "Matricos objektas neturi 'factors' lauko" #~ msgid "'s1' and 's2' must be \"character\" vectors" #~ msgstr "'s1' ir 's2' turi būti \"character\" vektoriai" #~ msgid "length of x slot != prod(Dim)" #~ msgstr "x lauko ilgis != prod(Dim)" #~ msgid "Negative value in Dim" #~ msgid_plural "Negative values in Dim" #~ msgstr[0] "Neigiama dim reikšmė" #~ msgstr[1] "Neigiamos dim reikšmės" #~ msgstr[2] "Neigiamų dim reikšmių" #, c-format #~ msgid "%s is a list, but not of length 2" #~ msgstr "%s yra sąrašas, bet ne ilgio 2" #, c-format #~ msgid "invalid class '%s' to dup_mMatrix_as_geMatrix" #~ msgstr "netinkama klasė '%s' į dup_mMatrix_as_geMatrix" #, c-format #~ msgid "unexpected ctype = %d in dup_mMatrix_as_geMatrix" #~ msgstr "netikėtas ctype = %d, esantis dup_mMatrix_as_geMatrix" #~ msgid "lengths of slots i and j must match" #~ msgstr "laukų i ir j ilgiai turi atitikti" #~ msgid "slot Dim must have length 2" #~ msgstr "laukas Dim turi būti 2 ilgio" #~ msgid "" #~ "all row indices (slot 'i') must be between 0 and nrow-1 in a TsparseMatrix" #~ msgstr "" #~ "visi eilučių indeksai (laukas 'i') turi būti nuo 0 iki nrow-1, esančio " #~ "TsparseMatrix" #~ msgid "" #~ "all column indices (slot 'j') must be between 0 and ncol-1 in a " #~ "TsparseMatrix" #~ msgstr "" #~ "visi stulpelių indeksai (laukas 'j') turi būti nuo 0 iki ncol-1, esančio " #~ "TsparseMatrix" #~ msgid "Supernodal LDL' decomposition not available" #~ msgstr "Supernodal LDL' skilimas negalimas" #~ msgid "Supernodal/simplicial class inconsistent with type flags" #~ msgstr "Supernodal/simplicial klasė nesuderinama su tipo vėliavėlėmis" #~ msgid "Number of supernodes must be positive when is_super is TRUE" #~ msgstr "Super mazgų skaičius turi būti teigiamas, kai is_super yra TRUE" #~ msgid "Lengths of super and pi must be equal" #~ msgstr "Super ir pi ilgiai turi būti lygūs" #~ msgid "Lengths of super and px must be equal" #~ msgstr "Super ir px ilgiai turi būti lygūs" #, c-format #~ msgid "First call to Lapack routine dgels returned error code %d" #~ msgstr "" #~ "Pirmasis iškvietimas į Lapack programą dgels grąžino klaidos kodą %d" #, c-format #~ msgid "Second call to Lapack routine dgels returned error code %d" #~ msgstr "Antrasis skambutis į Lapack programą dgels grąžino klaidos kodą %d" #, c-format #~ msgid "tol, given as %g, must be non-negative" #~ msgstr "tol, kaip %g, turi būti ne neigiamas" #, c-format #~ msgid "Second call to dgeqrf returned error code %d" #~ msgstr "Antrasis iškvietimas į dgeqrf grąžino klaidos kodą %d" #, c-format #~ msgid "" #~ "dense_to_Csparse(): cholmod_l_dense_to_sparse failure status=%d" #~ msgstr "" #~ "dense_to_Csparse(): cholmod_l_dense_to_sparse klaida status=%d" #, c-format #~ msgid "" #~ "Matrix dimension %d x %d (= %g) too large [FIXME calling " #~ "cholmod_l_dense_to_sparse]" #~ msgstr "" #~ "Matricos dimensija %d x %d (= %g) per didelė [FIXME iškvietė " #~ "cholmod_l_dense_to_sparse]" #, c-format #~ msgid "Lower band %d > upper band %d" #~ msgstr "Apatinė juosta %d > viršutinė juosta %d" #~ msgid "ddense_to_symmetric(): matrix is not square!" #~ msgstr "ddense_to_symmetric (): matrica nėra kvadratinė!" #, c-format #~ msgid "matrix is not symmetric [%d,%d]" #~ msgstr "matrica nėra simetrinė [%d,%d]" #~ msgid "matrix is not square! (symmetric part)" #~ msgstr "matrica nėra kvadratinė! (simetrinė dalis)" #~ msgid "matrix is not square! (skew-symmetric part)" #~ msgstr "matrica nėra kvadratinė! (Iškreipta simetriška dalis)" #~ msgid "lengths of slots 'i' and 'x' must match" #~ msgstr "laukų 'i' ir 'x' ilgiai turi atitikti" #~ msgid "lengths of slots 'j' and 'x' must match" #~ msgstr "laukų 'j' ir 'x' ilgiai turi atitikti" #, c-format #~ msgid "invalid class(x) '%s' in compressed_to_TMatrix(x)" #~ msgstr "netinkama class(x) '%s', esanti compressed_to_TMatrix(x)" #, c-format #~ msgid "invalid class(x) '%s' in R_to_CMatrix(x)" #~ msgstr "netinkama class(x) '%s', esanti R_to_CMatrix(x)" #~ msgid "A must have #{rows} >= #{columns}" #~ msgstr "Turi būti #{rows} >= #{columns}" #~ msgid "cs_sqr failed" #~ msgstr "cs_sqr nepavyko" #~ msgid "dgcMatrix_QR(*, keep_dimnames = NA): NA taken as TRUE" #~ msgstr "dgcMatrix_QR(*, keep_dimnames = NA): NA laikoma TRUE" #~ msgid "LU decomposition applies only to square matrices" #~ msgstr "LU dekompozicija taikoma tik kvadratinėms matricoms" #~ msgid "cs_lu(A) failed: near-singular A (or out of memory)" #~ msgstr "cs_lu (A) nepavyko: beveik singuliari A (arba trūksta atminties)" #~ msgid "dgcMatrix_LU(*, keep_dimnames = NA): NA taken as TRUE" #~ msgstr "dgcMatrix_LU(*, keep_dimnames = NA): NA laikoma TRUE" #~ msgid "dgCMatrix_matrix_solve(.., sparse=TRUE) not yet implemented" #~ msgstr "dgCMatrix_matrix_solve(.., sparse=TRUE) dar neįgyvendinta" #~ msgid "lengths of slots i and x must match" #~ msgstr "laukų i ir x ilgiai turi atitikti" #, c-format #~ msgid "too large matrix: %.0f" #~ msgstr "per didelė matrica: %.0f" #, c-format #~ msgid "Cannot coerce to too large *geMatrix with %.0f entries" #~ msgstr "Negalima pakeisti į per didelį *geMatrix su %.0f įrašais" #~ msgid "x slot must be numeric \"double\"" #~ msgstr "x laukas turi būti skaitinis \"double\"" #~ msgid "factors slot must be named list" #~ msgstr "faktorių laukas turi būti įvardytas sąrašas" #~ msgid "rcond requires a square, non-empty matrix" #~ msgstr "rcond reikia kvadratinės, netuščios matricos" #~ msgid "diagonal to be added has wrong length" #~ msgstr "pridedamos įstrižainės ilgis neteisingas" #~ msgid "Cannot factor a matrix with zero extents" #~ msgstr "Negalima faktorizuoti matricos su nuliniais dydžiais" #, c-format #~ msgid "Exact singularity detected during LU decomposition: %s, i=%d." #~ msgstr "Tikslus singuliarumas, aptiktas LU dekomponavimo metu: %s, i=%d." #~ msgid "Solve requires a square matrix" #~ msgstr "Norint išspręsti reikia kvadratinės matricos" #, c-format #~ msgid "error [%d] from Lapack 'dgecon()'" #~ msgstr "klaida [%d] iš Lapack 'dgecon()'" #, c-format #~ msgid "" #~ "Lapack dgecon(): system computationally singular, reciprocal condition " #~ "number = %g" #~ msgstr "" #~ "Lapack dgecon(): singuliariai apskaičiuota sistema, abipusės sąlygos " #~ "skaičius = %g" #~ msgid "Lapack routine dgetri: system is exactly singular" #~ msgstr "Lapack programa dgetri: sistema yra tiksliai singuliari" #~ msgid "dpoMatrix is not positive definite" #~ msgstr "dpoMatrix nėra teigiamai apibrėžta" #~ msgid "Cannot solve() for matrices with zero extents" #~ msgstr "Negalima solve() matricoms su nuliniais dydžiais" #~ msgid "Argument b must be a numeric matrix" #~ msgstr "Argumentas b turi būti skaitinė matrica" #~ msgid "chm_factor_name(): did not get string of length 11" #~ msgstr "chm_factor_name(): negavo 11 ilgio eilutės" #~ msgid "" #~ "Cholesky factorization failed; unusually, please report to Matrix-authors" #~ msgstr "" #~ "Cholesky faktoringas nepavyko; neįprastai, prašome pranešti Matrix " #~ "autoriams" #~ msgid "internal_chm_factor: Cholesky factorization failed" #~ msgstr "internal_chm_factor: Cholesky faktoringas nepavyko" #~ msgid "Non-symmetric matrix passed to dsCMatrix_to_dgTMatrix" #~ msgstr "Ne simetrinė matrica perduota į dsCMatrix_to_dgTMatrix" #~ msgid "Incorrect length of 'x' slot" #~ msgstr "Neteisingas 'x' lauko ilgis" #, c-format #~ msgid "Lapack routine dsytrf returned error code %d" #~ msgstr "Lapack programa dsytrf grąžino klaidos kodą %d" #~ msgid "x must be a \"double\" (numeric) matrix" #~ msgstr "x turi būti \"double\" (skaitinė) matrica" #~ msgid "matrix_trf(x, *): matrix is not square" #~ msgstr "matrix_trf(x, *): matrica nėra kvadratinė" #~ msgid "matrix_trf(*, uplo): uplo must be string" #~ msgstr "matrix_trf(*, uplo): uplo turi būti eilutė" #~ msgid "cannot set diag() as long as 'diag = \"U\"'" #~ msgstr "negali nustatyti diag() tol, kol 'diag = \"U\"'" #~ msgid "cannot add diag() as long as 'diag = \"U\"'" #~ msgstr "negali pridėti diag() tol, kol 'diag = \"U\"'" #~ msgid "x slot is not of correct length" #~ msgstr "x laukas nėra tinkamo ilgio" #~ msgid "A must be a logical matrix" #~ msgstr "A turi būti loginė matrica" #~ msgid "length(p) must match nrow(V)" #~ msgstr "length(p) turi atitikti nrow(V)" #~ msgid "length(beta) must match ncol(V)" #~ msgstr "length(beta) turi atitikti ncol(V)" #~ msgid "length(q) must be zero or ncol(R)" #~ msgstr "length(q) turi būti lygus nuliui arba ncol(R)" #, c-format #~ msgid "sparseQR_Qmult(): nrow(y) = %d != %d = nrow(V)" #~ msgstr "sparseQR_Qmult(): nrow(y) = %d != %d = nrow(V)" #~ msgid "\"dtrMatrix\" objects in '%*%' must have matching (square) dimension" #~ msgstr "" #~ "\"dtrMatrix\" objektai, esantys '%*%', turi turėti sutampantį " #~ "(kvadratinį) matmenį" Matrix/po/R-lt.po0000644000175100001440000011767414575137654013371 0ustar hornikusersmsgid "" msgstr "" "Project-Id-Version: Matrix 1.3-3\n" "POT-Creation-Date: 2024-03-15 17:22\n" "PO-Revision-Date: 2021-03-01 20:55+0200\n" "Last-Translator: Gabrielė Stupurienė \n" "Language-Team: none\n" "Language: lt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.4.2\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && (n%100<11 || n%100>19) ? 0 : " "n%10>=2 && n%10<=9 && (n%100<11 || n%100>19) ? 1 : 2);\n" #, fuzzy msgid "invalid mode \"%s\"" msgstr "negaliojantis 'mod': %s" msgid "" "%s(<%s>, <%s>) is not yet implemented; ask maintainer(\"%s\") to implement " "the missing method" msgstr "" #, fuzzy msgid "complex %s not yet implemented" msgstr "Klasės %s dar neįgyvendinta" #, fuzzy msgid "cannot coerce matrix of type \"%s\" to %s" msgstr "negalima paversti 'NA' į \"nsparseMatrix\"" #, fuzzy msgid "non0.i() not yet implemented for class %s" msgstr "dar neįgyvendinta klasei %s" msgid "%s=\"%s\" invalid for %s@uplo=\"%s\"" msgstr "" msgid "'%s' is not \"%1$s\", \"D%1$s\", or \"%1$s.\"" msgstr "" #, fuzzy msgid "%1$s(%2$s) is undefined: '%2$s' is not positive semidefinite" msgstr "chol() neapibrėžtas įstrižainei matricai su neigiamais įrašais" #, fuzzy msgid "matrix is not square" msgstr "matrica nėra įstrižainė" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", \"%3$s.\", \"%3$s1\", \"%3$s1." "\", or \"%4$s\"" msgstr "" #, fuzzy msgid "'%s' does not inherit from virtual class %s" msgstr "'x' turi paveldėti iš \"sparseVector\"" msgid "D[i,i] is NA, i=%d" msgstr "" msgid "D[i,i] is negative, i=%d" msgstr "" msgid "'%1$s' is not formally symmetric; factorizing tcrossprod(%1$s)" msgstr "" msgid "unexpected %s=\"%s\" in '%s' method" msgstr "" msgid "Not a valid format" msgstr "Neleistinas formatas" msgid "'file' must be a character string or connection" msgstr "'file' turi būti simbolių eilutė ar ryšys" msgid "Invalid storage type: %s" msgstr "Netinkamas saugyklos tipas: %s" msgid "Only numeric sparse matrices allowed" msgstr "Leidžiamos tik skaitinės sparse matricos" msgid "Invalid storage format: %s" msgstr "Neleistinas saugyklos formatas: %s" msgid "Invalid assembled indicator: %s" msgstr "Neleistinas surinktas indikatorius: %s" msgid "file is not a MatrixMarket file" msgstr "failas nėra MatrixMarket failas" msgid "type '%s' not recognized" msgstr "tipas '%s' neatpažįstamas" msgid "representation '%s' not recognized" msgstr "neatpažįstamas atvaizdavimas '%s'" msgid "element type '%s' not recognized" msgstr "elemento tipas '%s' neatpažįstamas" msgid "symmetry form '%s' not recognized" msgstr "simetrinė forma '%s' neatpažįstama" msgid "readMM(): expected %d entries but found only %d" msgstr "" #, fuzzy msgid "readMM(): row indices 'i' are not in 1:nrow[=%d]" msgstr "readMM(): eilučių\t reikšmės 'i' nėra 1:nr" #, fuzzy msgid "readMM(): column indices 'j' are not in 1:ncol[=%d]" msgstr "readMM(): stulpelių reikšmės 'j' nėra 1:nc" msgid "symmetry form 'skew-symmetric' not yet implemented for reading" msgstr "simetriška forma 'skew-symmetric', dar neįgyvendinta skaitymui" msgid "symmetry form 'hermitian' not yet implemented for reading" msgstr "simetrinė forma 'hermitian' dar neįgyvendinta skaitymui" msgid "symmetry form '%s' is not yet implemented" msgstr "simetrinė forma '%s' dar neįgyvendinta" msgid "element type 'complex' not yet implemented" msgstr "elemento tipas 'complex' dar neįgyvendintas" msgid "'%s()' is not yet implemented for element type '%s'" msgstr "'%s()' dar neįgyvendinta elementų tipui '%s'" msgid "'%s()' is not yet implemented for representation '%s'" msgstr "'%s()' dar neįgyvendinta '%s' atvaizdavimui" msgid "longer object length is not a multiple of shorter object length" msgstr "ilgesnis objekto ilgis nėra trumpesnio objekto ilgio kartotinis" #, fuzzy msgid "invalid class \"%s\" in '%s' method" msgstr "neleistina 'col.names' eilutė: %s" msgid "invalid type \"%s\" in '%s' method" msgstr "" msgid "non-conformable matrix dimensions in %s" msgstr "neatitinkantys matricos matmenys, esantys %s" msgid "dimnames [%d] mismatch in %s" msgstr "dimnames [%d] neatitikimas %s" msgid "inefficient method used for \"- e1\"" msgstr "neefektyvus metodas, naudojamas \"- e1\"" msgid "dim [product %d] do not match the length of object [%d]" msgstr "dim [product %d] neatitinka objekto ilgio [%d]" msgid "internal bug in \"Compare\" method (Cmp.Mat.atomic); please report" msgstr "vidinė klaida \"Compare\" metode (Cmp.Mat.atomic); prašome pranešti" msgid "Cmp.Mat.atomic() should not be called for diagonalMatrix" msgstr "Cmp.Mat.atomic() negalima būti iškviestas diagonalMatrix" msgid "Matrices must have same number of rows for arithmetic" msgstr "Matricos turi turėti tą patį eilučių skaičių aritmetikai" msgid "number of rows are not compatible for %s" msgstr "eilučių skaičius nesuderinamas su %s" msgid "length of 2nd arg does not match dimension of first" msgstr "2-ojo arg ilgis neatitinka pirmojo dimensijos" msgid "length of 1st arg does not match dimension of 2nd" msgstr "1-mo arg ilgis nesutampa su 2-ojo dimensija" msgid "internal bug in \"Logic\" method (Logic.Mat.atomic); please report" msgstr "vidinė klaida \"Logic\" metode (Logic.Mat.atomic); prašome pranešti" msgid "Logic.Mat.atomic() should not be called for diagonalMatrix" msgstr "Logic.Mat.atomic() neturėtų būti iškviečiamas dėl diagonalMatrix" msgid "vector too long in Matrix - vector operation" msgstr "vektorius, esantis Matrix, per ilgas - vektoriaus operacija" msgid "" "longer object length\n" "\tis not a multiple of shorter object length" msgstr "" "ilgesnis objekto ilgis\n" "\tnėra trumpesnio objekto ilgio kartotinis" #, fuzzy msgid "invalid class \"%s\" object in '%s' method" msgstr "neleistina 'col.names' eilutė: %s" msgid "intermediate 'r' is of type %s" msgstr "tarpinis 'r' yra %s tipo" msgid "not yet implemented .. please report" msgstr "dar neįgyvendinta .. prašome pranešti" msgid "'%s' has non-finite values" msgstr "" msgid "'%1$s' is not \"%2$s\", \"%3$s\", or \"%2$s.\"" msgstr "" msgid "'force' must be (coercable to) TRUE or FALSE" msgstr "'force' turi būti (verčiama į) TRUE arba FALSE" msgid "invalid (to - from)/by in seq(.)" msgstr "negaliojantis (iki - nuo)/pagal seq(.)" msgid "wrong sign in 'by' argument" msgstr "neteisingas ženklas 'by' argumente" msgid "'by' argument is much too small" msgstr "'by' argumentas per mažas" msgid "length must be non-negative number" msgstr "ilgis turi būti ne neigiamas skaičius" msgid "too many arguments" msgstr "per daug argumentų" msgid "c(,..) of different kinds, coercing all to 'rleDiff'" msgstr "c(,..) įvairių rūšių, paverčiant visus į 'rleDiff'" msgid "[i] is not yet implemented" msgstr "[i] dar neįgyvendinta" msgid "all() is not yet implemented" msgstr "all() dar neįgyvendinti" msgid "sum() is not yet implemented" msgstr "sum() dar neįgyvendinta" msgid "prod() is not yet implemented" msgstr "prod() dar neįgyvendintas" msgid "not yet implemented" msgstr "dar neįvykdyta" msgid "" "x / 0 for an x with sign-change\n" " no longer representable as 'rleDiff'" msgstr "" "x / 0 dėl x su ženklo pakeitimu\n" " nebeatitinkamas kaip 'rleDiff'" msgid " --> is not yet implemented" msgstr " --> dar neįgyvendinta" msgid " --> is not yet implemented" msgstr " --> dar neįgyvendintas" #, fuzzy msgid "only square matrices can be used as graph incidence matrices" msgstr "" "tik kvadratinės matricos gali būti naudojamos kaip paplitimo matricos " "grafikams" #, fuzzy msgid "matrix is not symmetric; consider forceSymmetric(.) or symmpart(.)" msgstr "ne simetriška matrica; apsvarstykite forceSymmetric() arba symmpart()" #, fuzzy msgid "matrix is not triangular; consider triu(.) or tril(.)" msgstr "matrica nėra trikampė" msgid "matrix is not diagonal; consider Diagonal(x=diag(.))" msgstr "" #, fuzzy msgid "invalid type \"%s\" in '%s'" msgstr "neleistinas 'type'" #, fuzzy msgid "invalid %s=\"%s\" to '%s'" msgstr "Netinkamas saugyklos tipas: %s" msgid "dimensions cannot exceed %s" msgstr "" #, fuzzy msgid "invalid class \"%s\" in '%s'" msgstr "neleistina 'col.names' eilutė: %s" msgid "%s length cannot exceed %s" msgstr "" msgid "'A' must be a square matrix" msgstr "'A' turi būti kvadratinė matrica" msgid "must either specify 'A' or the functions 'A.x' and 'At.x'" msgstr "turi nurodyti 'A' arba funkcijas 'A.x' ir 'At.x'" msgid "when 'A' is specified, 'A.x' and 'At.x' are disregarded" msgstr "kai nurodyta 'A', į 'A.x' and 'At.x' neatsižvelgiama" msgid "not converged in %d iterations" msgstr "nekonverguoja %d iteracijose" msgid "hit a cycle (1) -- stop iterations" msgstr "pasiekti ciklą (1) -- sustabdyti iteracijas" msgid "hit a cycle (2) -- stop iterations" msgstr "pasiekti ciklą (2) -- sustabdyti iteracijas" msgid "not enough new vecs -- stop iterations" msgstr "nepakanka naujų vecs -- sustabdyti iteracijas" msgid "invalid 'data'" msgstr "neleistinas 'data'" #, fuzzy msgid "'nrow', 'ncol', 'byrow' disregarded for [mM]atrix 'data'" msgstr "matricos 'data' atveju neatsižvelgiama į 'nrow', 'ncol' ir t. t." msgid "data is too long" msgstr "" #, fuzzy msgid "exactly one of 'i', 'j', and 'p' must be missing from call" msgstr "iškvietimo metu turi trūkti tiksliai vieno iš 'i', 'j' arba 'p'" msgid "" "use Diagonal() to construct diagonal (symmetric && triangular) sparse " "matrices" msgstr "" #, fuzzy msgid "'giveCsparse' is deprecated; using 'repr' instead" msgstr "'giveCsparse' nebenaudojamas; vietoj to naudos 'repr'" #, fuzzy msgid "'giveCsparse' is deprecated; setting repr=\"T\" for you" msgstr "'giveCsparse' nebenaudojamas; nustatymas 'repr = \"T\"' jums" #, fuzzy msgid "'p' must be a nondecreasing vector c(0, ...)" msgstr "'p' turi būti nemažėjantis vektorius (0, ...)" msgid "dimensions cannot exceed 2^31-1" msgstr "" msgid "'i' and 'j' must not contain NA" msgstr "" msgid "'i' and 'j' must be" msgstr "" msgid "positive" msgstr "" msgid "non-negative" msgstr "" #, fuzzy msgid "invalid 'dims'" msgstr "neleistinas 'data'" msgid "'dims' must contain all (i,j) pairs" msgstr "" msgid "symmetric matrix must be square" msgstr "simetrinė matrica turi būti kvadratinė" msgid "triangular matrix must be square" msgstr "trikampė matrica turi būti kvadratinė" msgid "p[length(p)]" msgstr "" msgid "length(i)" msgstr "" #, fuzzy msgid "is not an integer multiple of length(x)" msgstr "length(i) nėra length(x) kartotinis" msgid "length(x) must not exceed" msgstr "" #, fuzzy msgid "invalid 'repr'; must be \"C\", \"R\", or \"T\"" msgstr "negaliojantis 'repr'; turi būti \"C\", \"T\" arba \"R\"" #, fuzzy msgid "'n' must be a non-negative integer" msgstr "ilgis turi būti ne neigiamas skaičius" msgid "'x' has unsupported class \"%s\"" msgstr "" msgid "'x' has unsupported type \"%s\"" msgstr "" msgid "attempt to recycle 'x' of length 0 to length 'n' (n > 0)" msgstr "" msgid "'shape' must be one of \"g\", \"t\", \"s\"" msgstr "" #, fuzzy msgid "'kind' must be one of \"d\", \"l\", \"n\"" msgstr "negaliojantis 'repr'; turi būti \"C\", \"T\" arba \"R\"" msgid "mismatch between typeof(x)=\"%s\" and kind=\"%s\"; using kind=\"%s\"" msgstr "" #, fuzzy msgid "'cols' must be numeric" msgstr "'ncol' turi būti >= 0" msgid "'cols' has elements not in seq(0, length.out = n)" msgstr "" #, fuzzy msgid "'uplo' must be \"U\" or \"L\"" msgstr "negaliojantis 'repr'; turi būti \"C\", \"T\" arba \"R\"" #, fuzzy msgid "'lst' must be a list" msgstr "'ncol' turi būti >= 0" msgid "'giveCsparse' has been deprecated; setting 'repr = \"T\"' for you" msgstr "'giveCsparse' nebenaudojamas; nustatymas 'repr = \"T\"' jums" msgid "'giveCsparse' has been deprecated; will use 'repr' instead" msgstr "'giveCsparse' nebenaudojamas; vietoj to naudos 'repr'" msgid "'diagonals' matrix must have %d columns (= length(k) )" msgstr "'diagonals' matricoje turi būti %d stulpeliai (= length(k) )" msgid "'diagonals' must have the same length (%d) as 'k'" msgstr "'diagonals' turi būti tokio pat ilgio (%d) kaip ir 'k'" msgid "matrix can only be symmetric if square, but n != m" msgstr "matrica gali būti simetriška tik kvadratinė, bet n != m" msgid "" "for symmetric band matrix, only specify upper or lower triangle\n" " hence, all k must have the same sign" msgstr "" "simetrinės juostos matricai nurodykite tik viršutinį arba apatinį trikampį\n" " taigi, visi k turi turėti tą patį ženklą" msgid "the %d-th (sub)-diagonal (k = %d) is too short; filling with NA's" msgstr "%d įstrižainė (k = %d) yra per trumpa; užpildymas su NA" msgid "invalid 'repr'; must be \"C\", \"T\", or \"R\"" msgstr "negaliojantis 'repr'; turi būti \"C\", \"T\" arba \"R\"" msgid "'x' must inherit from \"sparseVector\"" msgstr "'x' turi paveldėti iš \"sparseVector\"" msgid "'ncol' must be >= 0" msgstr "'ncol' turi būti >= 0" msgid "'nrow' must be >= 0" msgstr "'nrow' turi būti >= 0" msgid "Must specify 'nrow' when 'symmetric' is true" msgstr "Turi nurodyti 'nrow', kai 'symmetric' yra teisinga" msgid "'nrow' and 'ncol' must be the same when 'symmetric' is true" msgstr "'nrow' ir 'ncol' turi būti vienodi, kai 'symmetric' yra teisinga" msgid "'x' must have length nrow^2 when 'symmetric' is true" msgstr "'x' turi būti ilgio nrow^2, kai 'symmetric' yra teisingas" msgid "'ncol' is not a factor of length(x)" msgstr "'ncol' nėra length(x) faktorius" msgid "'nrow' is not a factor of length(x)" msgstr "\"nrow\" nėra length(x) faktorius" msgid "Class %s is not yet implemented" msgstr "Klasės %s dar neįgyvendinta" #, fuzzy msgid "'%s' and '%s' must be positive integers" msgstr "ilgis turi būti ne neigiamas skaičius" #, fuzzy msgid "matrix is not symmetric or triangular" msgstr "'x' nėra nei simetriškas, nei trikampis" #, fuzzy msgid "matrix is not symmetric" msgstr "matrica nėra trikampė" #, fuzzy msgid "matrix is not triangular" msgstr "'x' nėra nei simetriškas, nei trikampis" msgid "" "the default value of argument '%s' of method '%s(<%s>, <%s>)' may change " "from %s to %s as soon as the next release of Matrix; set '%s' when " "programming" msgstr "" msgid "determinant of non-square matrix is undefined" msgstr "" msgid "replacement diagonal has wrong length" msgstr "" msgid "replacement diagonal has incompatible type \"%s\"" msgstr "" msgid "assigned dimensions are not of type \"%s\" or \"%s\"" msgstr "" msgid "assigned dimensions do not have length %d" msgstr "" msgid "assigned dimensions are NA" msgstr "" msgid "assigned dimensions are negative" msgstr "" msgid "assigned dimensions exceed %s" msgstr "" #, fuzzy msgid "assigned dimensions [product %.0f] do not match object length [%.0f]" msgstr "dim [product %d] neatitinka objekto ilgio [%d]" msgid "'lwd' must be NULL or non-negative numeric" msgstr "'lwd' turi būti NULL arba ne neigiamas skaitinis" #, fuzzy msgid "%s(<%s>) is not yet implemented" msgstr "Klasės %s dar neįgyvendinta" msgid "'%s' is not of type \"%s\" or \"%s\"" msgstr "" msgid "'%s' contains NA" msgstr "" msgid "'%s' has elements less than %d" msgstr "" #, fuzzy msgid "'%s' is not a non-negative number" msgstr "ilgis turi būti ne neigiamas skaičius" msgid "'%s' has elements exceeding '%s'" msgstr "" msgid "'%s' is not %d or %d" msgstr "" #, fuzzy msgid "'%s' is not a permutation of seq_len(%s)" msgstr "'ncol' nėra length(x) faktorius" #, fuzzy msgid "matrix must have exactly one entry in each row or column" msgstr "eilutėje turi būti lygiai vienas ne nulinis įrašas" #, fuzzy msgid "attempt to coerce non-square matrix to %s" msgstr "negalima paversti nesimetrinio \"dgTMatrix\" į \"dsCMatrix\" klasę" #, fuzzy msgid "matrix must have exactly one entry in each row and column" msgstr "eilutėje turi būti lygiai vienas ne nulinis įrašas" #, fuzzy msgid "'%s' via sparse -> dense coercion" msgstr "rcond(.) per sparse -> dense pavertimą" #, fuzzy msgid "invalid %s=\"%s\"" msgstr "neleistini nargs()= %d" msgid "norm" msgstr "" #, fuzzy msgid "'%s' method must use default %s=\"%s\"" msgstr "kronecker metodas turi naudoti numatytąjį 'FUN'" #, fuzzy msgid "number of nonzero entries cannot exceed %s" msgstr "eilučių skaičius nesuderinamas su %s" msgid "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", or \"%4$s\"" msgstr "" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%2$s2\", \"%2$s2.\", \"%3$s\", or " "\"%4$s\"" msgstr "" msgid "non-conformable arguments" msgstr "neatitinkantys argumentai" #, fuzzy msgid "model frame and formula mismatch in sparse.model.matrix()" msgstr "modelio sistemos ir formulės neatitikimas model.matrix()" #, fuzzy msgid "non-list contrasts argument ignored" msgstr "neleistinas argumentas 'contrasts.arg'" #, fuzzy msgid "'contrasts.arg' argument must be named" msgstr "neleistinas argumentas 'contrasts.arg'" msgid "variable '%s' is absent, its contrast will be ignored" msgstr "kintamojo '%s' nėra, jo kontrastas bus ignoruojamas" msgid "Matrix seems negative semi-definite" msgstr "Matrica atrodo pusiau neigiamai apibrėžta" msgid "'nearPD()' did not converge in %d iterations" msgstr "'nearPD()' nekonvergavo %d iteracijose" #, fuzzy msgid "'cl' is not a character string" msgstr "'V' nėra *kvadratinė* matrica" msgid "" "not a positive definite matrix (and positive semidefiniteness is not checked)" msgstr "" #, fuzzy msgid "'%s' is not a square numeric matrix" msgstr "'V' nėra *kvadratinė* matrica" #, fuzzy msgid "" "diag(%s) has non-positive or non-finite entries; finite result is doubtful" msgstr "diag(.) turėjo 0 arba NA įrašus; abejotinas ne baigtinis rezultatas" msgid "" "matrix is structurally rank deficient; using augmented matrix with " "additional %d row(s) of zeros" msgstr "" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%2$s2\", \"%2$s2.\", \"%3$s\", " "\"%3$s1\", \"%4$s\", or \"%4$s1\"" msgstr "" #, fuzzy msgid "'%s' has the wrong length" msgstr "RHS 'b' ilgis neteisingas" #, fuzzy msgid "invalid '%s': not in %d:%d" msgstr "neleistina 'col.names' eilutė: %s" msgid "need greater '%s' as pivoting occurred" msgstr "" msgid "qr2rankMatrix(.): QR with only %d out of %d finite diag(R) entries" msgstr "qr2rankMatrix(.): QR tik su %d iš %d baigtinių diag(R) įrašų" msgid "" "rankMatrix(, method = '%s') coerces to dense matrix.\n" " Probably should rather use method = 'qr' !?" msgstr "" "rankMatrix(, method = '%s') paverčiamas į tankio " "matricą.\n" " Tikriausiai reikėtų naudoti metodą = 'qr' !?" msgid "rankMatrix(x, method='qr'): computing t(x) as nrow(x) < ncol(x)" msgstr "rankMatrix(x, method='qr'): skaičiavimas t(x) kaip nrow(x) < ncol(x)" #, fuzzy msgid "[[ suppressing %d column name%s %s ... ]]" msgstr "[[ nerodyti %d stulpelių pavadinimų %s ... ]]" msgid "invalid 'col.names' string: %s" msgstr "neleistina 'col.names' eilutė: %s" msgid "uniDiag=TRUE, but not all diagonal entries are 1" msgstr "uniDiag=TRUE, bet ne visi įstrižainės įrašai yra 1" msgid "uniDiag=TRUE, not all entries in diagonal coded as 1" msgstr "uniDiag=TRUE, ne visi įstrižainės įrašai, koduoti kaip 1" #, fuzzy msgid "in show(); maybe adjust options(max.print=, width=)" msgstr "show(); galbūt pritaikyti 'options(max.print= *, width = *)'" msgid "suppressing %d columns and %d rows" msgstr "nerodyti %d stulpelių ir %d eilučių" msgid "suppressing %d rows" msgstr "nerodyti %d eilučių" msgid "suppressing %d columns" msgstr "nerodyti %d stulpelių" msgid "logic programming error in printSpMatrix2(), please report" msgstr "loginio programavimo klaida printSpMatrix2(), prašome pranešti" #, fuzzy msgid "'%s' is not square" msgstr "'V' nėra kvadratinė matrica" msgid "dimensions of '%s' and '%s' are inconsistent" msgstr "" msgid "'%1$s' is computationally singular, rcond(%1$s)=%2$g" msgstr "" msgid "'%s' is computationally singular, min(d)/max(d)=%g, d=abs(diag(U))" msgstr "" msgid "matrix is exactly singular, D[i,i]=0, i=%d" msgstr "" msgid "matrix is exactly singular, J[,j]=0, j=%d" msgstr "" msgid "matrix exactly singular, J[i,]=0, i=%d" msgstr "" msgid "cannot coerce from %s to %s" msgstr "" msgid "a sparseMatrix should rarely be centered: will not be sparse anymore" msgstr "sparseMatrix retai turėtų būti centre: daugiau nebus sparse" msgid "length of 'center' must equal the number of columns of 'x'" msgstr "'center' ilgis turi būti lygus stulpelių skaičiui 'x'" msgid "length of 'scale' must equal the number of columns of 'x'" msgstr "'scale' ilgis turi būti lygus stulpelių skaičiui 'x'" #, fuzzy msgid "invalid subassignment value class \"%s\"" msgstr "netinkama klasė: %s" #, fuzzy msgid "invalid subassignment value type \"%s\"" msgstr "Netinkamas saugyklos tipas: %s" msgid "missing subassignment value" msgstr "" #, fuzzy msgid "incorrect number of dimensions" msgstr "nesuderinamos matricos dimensijos" msgid "replacement has length zero" msgstr "" msgid "number of items to replace is not a multiple of replacement length" msgstr "keičiamų elementų skaičius nėra keičiamo ilgio kartotinis" msgid "" ".M.repl.i.2col(): 'i' has no integer column number;\n" " should never happen; please report" msgstr "" ".M.repl.i.2col(): 'i' neturi sveiko skaičiaus stulpelio numerio;\n" " niekada neturėtų įvykti; prašome pranešti" msgid "such indexing must be by logical or 2-column numeric matrix" msgstr "toks indeksavimas turi būti loginis arba 2 stulpelių skaitinė matrica" msgid ".M.repl.i.2col(): drop 'matrix' case ..." msgstr ".M.repl.i.2col(): išmetė 'matrix' atveją ..." msgid "negative values are not allowed in a matrix subscript" msgstr "matricos apatiniame indekse neigiamos reikšmės neleidžiamos" msgid "NAs are not allowed in subscripted assignments" msgstr "NA neleidžiamos apatinio indekso priskyrimuose" msgid "m[ ] <- v: inefficiently treating single elements" msgstr "m[ ] <- v: neefektyviai apdorojant pavienius elementus" msgid "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' ?" msgstr "nargs() = %d. Pašaliniai neteisėti argumentai viduje '[ .. ]' ?" msgid "RHS 'value' (class %s) matches 'ANY', but must match matrix class %s" msgstr "" "RHS 'value' (%s klasė) atitinka 'ANY', tačiau turi atitikti matricos klasę %s" msgid "not-yet-implemented 'Matrix[<-' method" msgstr "dar neįgyvendintas 'Matrix[<-' method" msgid "invalid nargs()= %d" msgstr "neleistini nargs()= %d" msgid "nothing to replace with" msgstr "nėra nieko pakeisti su" msgid "too many replacement values" msgstr "per daug pakeitimo reikšmių" msgid "i1[1] == 0 ==> C-level verbosity will not happen!" msgstr "i1[1] == 0 ==> C lygio daugiakalbiškumas neįvyks!" msgid "using\t \"old code\" part in Csparse subassignment" msgstr "naudojant\t \"senojo kodo\" dalį Csparse antriniame priskyrime" msgid "" "using\"old code\" part in Csparse subassignment\n" " >>> please report to Matrix-authors@r-project.org" msgstr "" "naudojant \"senojo kodo\" dalį Csparse antriniame priskyrime\n" " >>> prašome pranešti Matrix-authors@r-project.org" msgid "you cannot mix negative and positive indices" msgstr "negalite maišyti neigiamų ir teigiamų indeksų" msgid "index larger than maximal %d" msgstr "indeksas didesnis nei maksimalus %d" msgid "'NA' indices are not (yet?) supported for sparse Matrices" msgstr "'NA' indeksai nėra (dar?) remiami sparse Matrices" msgid "logical subscript too long (%d, should be %d)" msgstr "loginis apatinis indeksas per ilgas (%d, turėtų būti %d)" msgid "no 'dimnames[[.]]': cannot use character indexing" msgstr "nėra 'dimnames[[.]]': negalima naudoti simbolių indeksavimo" msgid "invalid character indexing" msgstr "neleistinas simbolių indeksavimas" msgid "internal bug: missing 'i' in replTmat(): please report" msgstr "vidinė klaida: trūksta 'i' replTmat(): prašome pranešti" msgid "[ ] indexing not allowed: forgot a \",\" ?" msgstr "[ ] indeksavimas neleidžiamas: pamiršote \",\" ?" msgid "internal bug: matrix 'i' in replTmat(): please report" msgstr "vidinė klaida: matrica 'i', esanti replTmat(): prašome pranešti" msgid "" "x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced; NA |--> TRUE." msgstr "" "x[.] <- val: x yra %s, val, kurio nėra {TRUE, FALSE} yra paverčiamas; NA |--" "> TRUE." msgid "x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced." msgstr "x[.] <- val: x yra %s, val, kurio nėra {TRUE, FALSE} yra paverčiamas." msgid "" "x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE." msgstr "" "x[...] <- val: x yra %s, val, kurio nėra {TRUE, FALSE} yra paverčiamas NA |--" "> TRUE." msgid "x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced." msgstr "" "x[.,.] <- val: x yra %s, val, kurio nėra {TRUE, FALSE} yra paverčiamas." msgid "x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrix" msgstr "x[.,.] <- val: x yra paverčiamas iš Tsparse* į CsparseMatrix" msgid "nargs() = %d should never happen; please report." msgstr "nargs() = %d niekada neturėtų įvykti; prašome pranešti." msgid "row indices must be <= nrow(.) which is %d" msgstr "eilučių indeksai turi būti < = nrow(.), kuris yra %d" msgid "column indices must be <= ncol(.) which is %d" msgstr "stulpelių indeksai turi būti <= ncol(.), kuris yra %d" msgid "Internal bug: nargs()=%d; please report" msgstr "Vidinė klaida: nargs()=%d; prašome pranešti" msgid "" "index must be numeric, logical or sparseVector for indexing sparseVectors" msgstr "" "indeksas turi būti skaitinis, loginis arba sparseVector, sparseVectors " "indeksavimui" #, fuzzy msgid "invalid subscript class \"%s\"" msgstr "netinkama klasė: %s" #, fuzzy msgid "invalid subscript type \"%s\"" msgstr "Netinkamas saugyklos tipas: %s" msgid "recycled %s would have maximal index exceeding %s" msgstr "" msgid "subscripts exceeding %s replaced with NA" msgstr "" msgid "subscript out of bounds" msgstr "" #, fuzzy msgid "logical subscript too long" msgstr "loginis apatinis indeksas per ilgas (%d, turėtų būti %d)" msgid "only zeros may be mixed with negative subscripts" msgstr "" msgid "trimmed means are not defined for complex data" msgstr "" msgid "first element used of '%s' argument" msgstr "" #, fuzzy msgid "invalid '%s' argument" msgstr "neleistinas 'data'" msgid "should never happen ..." msgstr "" #, fuzzy msgid "'%s' is deprecated; using '%s' instead" msgstr "'giveCsparse' nebenaudojamas; vietoj to naudos 'repr'" #, fuzzy msgid "'%s' is deprecated; setting %s=\"%s\"" msgstr "'giveCsparse' nebenaudojamas; nustatymas 'repr = \"T\"' jums" msgid "'%s' has length 0 but '%s' does not" msgstr "" #, fuzzy msgid "attempt to coerce matrix with NA to %s" msgstr "negalima paversti nesimetrinio \"dgTMatrix\" į \"dsCMatrix\" klasę" #, fuzzy msgid "invalid 'Class2'" msgstr "neleistinas 'data'" #~ msgid "qr2rankMatrix(.): QR has negative diag(R) entries" #~ msgstr "qr2rankMatrix(.): QR turi neigiamų diag(R) įrašų" #, fuzzy #~ msgid "invalid 'each' argument" #~ msgstr "neteisingas ženklas 'by' argumente" #, fuzzy #~ msgid "invalid 'times' argument" #~ msgstr "neleistinas 'data'" #~ msgid "" #~ "not-yet-implemented method for %s(<%s>).\n" #~ " ->> Ask the package authors to implement the missing feature." #~ msgstr "" #~ "dar neįgyvendintas metodas dėl %s (<%s>).\n" #~ " ->> Paprašykite paketo autorių įgyvendinti trūkstamą funkciją." #~ msgid "" #~ "not-yet-implemented method for %s(<%s>, <%s>).\n" #~ " ->> Ask the package authors to implement the missing feature." #~ msgstr "" #~ "dar neįgyvendintas metodas dėl %s (<%s>, <%s>).\n" #~ " ->> Paprašykite paketo autorių įgyvendinti trūkstamą funkciją." #, fuzzy #~ msgid "complex \"diagonalMatrix\" not yet implemented" #~ msgstr "bendroji Matrix klasė dar neįgyvendinta %s" #, fuzzy #~ msgid "not yet implemented for class \"%s\"" #~ msgstr "dar neįgyvendinta klasei %s" #, fuzzy #~ msgid "invalid 'uplo'" #~ msgstr "neleistinas 'type'" #~ msgid "'lag' and 'differences' must be integers >= 1" #~ msgstr "'lag' ir 'differences' turi būti sveikieji skaičiai >= 1" #~ msgid "" #~ "programming error: min() should have dispatched w/ 1st arg much earlier" #~ msgstr "programavimo klaida: min() turėjo išsiųsti w/ 1st arg daug anksčiau" #~ msgid "in Summary(, .): %s(<%s>, <%s>,...)" #~ msgstr "esantis Summary(, .): %s(<%s>, <%s>,...)" #~ msgid "in Summary(, .): %s(<%s>, <%s>)" #~ msgstr "esantis Summary(, .): %s(<%s>, <%s>)" #, fuzzy #~ msgid "number of rows of matrices must match" #~ msgstr "eilučių skaičius nesuderinamas su %s" #, fuzzy #~ msgid "number of columns of matrices must match" #~ msgstr "eilučių skaičius nesuderinamas su %s" #~ msgid "resulting x-slot has different type than x's or y's" #~ msgstr "gautas x-slot turi skirtingą tipą nei x arba y" #, fuzzy #~ msgid "dimensions must be numeric of length 2" #~ msgstr "dim(.) reikšmė turi būti skaitinio ilgio 2" #, fuzzy #~ msgid "'perm' must be numeric" #~ msgstr "'A' turi būti kvadratinė matrica" #, fuzzy #~ msgid "'margin' must be 1 or 2" #~ msgstr "'ncol' turi būti >= 0" #~ msgid "not-yet-implemented method for <%s> %%*%% <%s>" #~ msgstr "dar neįgyvendintas metodas <%s> %%*%% <%s>" #~ msgid "'boolArith = %d' not yet implemented" #~ msgstr "'boolArith = %d' dar neįgyvendintas" #, fuzzy #~ msgid "'rcond' via sparse -> dense coercion" #~ msgstr "rcond(.) per sparse -> dense pavertimą" #, fuzzy #~ msgid "invalid 'norm'" #~ msgstr "neleistinas 'data'" #, fuzzy #~ msgid "cannot coerce zsparseVector to dgCMatrix" #~ msgstr "negalima paversti NA reikšmes į modelį \"ngCMatrix\"" #, fuzzy #~ msgid "cannot coerce zsparseVector to dgeMatrix" #~ msgstr "negalima paversti 'NA' į \"nsparseVector\"" #~ msgid "" #~ "number of non zeros is smaller than 'nnz' because of duplicated (i,j)s" #~ msgstr "ne nulių skaičius yra mažesnis už 'nnz' dėl dubliuotų (i,j)s" #~ msgid "'times >= 0' is required" #~ msgstr "'times >= 0' yra būtinas" #~ msgid "'giveCsparse' has been deprecated; setting 'repr = \"%s\"' for you" #~ msgstr "'giveCsparse' nebenaudojamas; nustatymas 'repr = \"%s\"' jums" #~ msgid "Matrices must have same number of rows in %s" #~ msgstr "Matricos turi turėti tą patį eilučių skaičių %s" #~ msgid "Matrices must have same number of columns in %s" #~ msgstr "Matricos turi turėti tą patį stulpelių skaičių %s" #, fuzzy #~ msgid "only 2-dimensional tables can be coerced to sparseMatrix" #~ msgstr "" #~ "tik 2 matmenų lentelės gali būti tiesiogiai paverstos į sparse matricas" #, fuzzy #~ msgid "matrix is not symmetric or" #~ msgstr "'x' nėra nei simetriškas, nei trikampis" #, fuzzy #~ msgid "triangular" #~ msgstr "ne trikampė matrica" #, fuzzy #~ msgid "matrix is not" #~ msgstr "matrica nėra įstrižainė" #~ msgid "'x' is not positive definite -- chol() undefined." #~ msgstr "'x' nėra teigiamai apibrėžtas -- chol() neapibrėžtas." #~ msgid "Matrices must have same dimensions in %s" #~ msgstr "Matricos turi turėti tuos pačius matmenis %s" #~ msgid "names(dimnames()) must be NULL or of length two" #~ msgstr "names(dimnames()) turi būti NULL arba dviejų ilgių" #~ msgid "[[ suppressing %d column names %s ]]" #~ msgstr "[[ nerodyti %d stulpelių pavadinimų %s ]]" #~ msgid "'x' must be \"sparseMatrix\"" #~ msgstr "'x' turi būti \"sparseMatrix\"" #~ msgid "not yet implemented for matrix with typeof %s" #~ msgstr "dar neįgyvendinta matricai su typeof %s" #~ msgid "not yet implemented for %s" #~ msgstr "dar neįgyvendinta %s" #~ msgid "" #~ "Quadratic matrix '%s' (=: A) is not formally\n" #~ "\tsymmetric. Will be treated as\tA A'" #~ msgstr "" #~ "Kvadratinė matrica '%s' (=: A) formaliai nėra\n" #~ "\tsimetrinis. Bus traktuojama kaip as\tA A'" #~ msgid "" #~ "'update' must be logical or '+' or '-'; 'C' a matrix, and 'L' a " #~ "\"CHMfactor\"" #~ msgstr "" #~ "'update' turi būti loginis arba '+' arba '-'; 'C' matrica, o 'L' – " #~ "\"CHMfactor\"" #~ msgid "update must be TRUE/FALSE or '+' or '-'" #~ msgstr "atnaujinimas turi būti TRUE/FALSE arba '+' arba '-'" #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "Matricos vidinė klaida, esanti [i,,d]; prašome pranešti" #~ msgid "" #~ "Cholesky() -> *symbolic* factorization -- not yet implemented" #~ msgstr "" #~ "Cholesky() -> *symbolic* faktoringas -- dar neįgyvendintas" #~ msgid "" #~ "as.matrix() is deprecated (to become a no-op in the future).\n" #~ "Use as(x, \"matrix\") or .asmatrix(x) instead." #~ msgstr "" #~ "as.matrix() yra nebenaudojamas (ateityje taps no-op).\n" #~ "Vietoj to naudokite as(x, \"matrix\") arba .asmatrix(x)." #~ msgid "" #~ "as.array() is deprecated. Use as(x, \"matrix\") or .asmatrix(x) " #~ "instead." #~ msgstr "" #~ "as.array() nebenaudojamas. Vietoj to naudokite as(x, \"matrix\") " #~ "arba .asmatrix(x)." #~ msgid "trimmed mean of 'sparseVector' -- suboptimally using as.numeric(.)" #~ msgstr "" #~ "apdorotas 'sparseVector' vidurkis -- suboptimally naudojant as.numeric(.)" #~ msgid "invalid dimnames given for %s object" #~ msgstr "neleistinas dimnames %s objektui" #~ msgid "" #~ "dimnames(.) <- NULL: translated to \n" #~ "dimnames(.) <- list(NULL,NULL) <==> unname(.)" #~ msgstr "" #~ "dimnames(.) <- NULL: išverstas į \n" #~ "dimnames(.) <- list(NULL,NULL) <==> unname(.)" #~ msgid "" #~ "'nrow', 'ncol', etc, are disregarded when 'data' is \"Matrix\" already" #~ msgstr "" #~ "Į 'nrow', 'ncol' ir t. t. neatsižvelgiama, kai 'data' jau yra \"Matrix\"" #~ msgid "complex matrices not yet implemented in Matrix package" #~ msgstr "kompleksinės matricos dar neįgyvendintos Matrix pakete" #~ msgid "using slow kronecker() method" #~ msgstr "naudojant lėtą kronecker() metodą" #~ msgid "" #~ "Cholesky(A) called for 'A' of class \"%s\";\n" #~ "\t it is currently defined for sparseMatrix only; consider using chol() " #~ "instead" #~ msgstr "" #~ "Cholesky(A) iškvietė dėl 'A' klasės \"%s\";\n" #~ "\t šiuo metu jis nustatytas tik rsparseMatrix; apsvarstyti galimybę " #~ "vietoj to naudoti chol ()" #~ msgid "invalid or not-yet-implemented 'Matrix' subsetting" #~ msgstr "neleistinas arba dar neįgyvendintas 'Matrix' pogrupis" #~ msgid "[ ] : .M.sub.i.logical() maybe inefficient" #~ msgstr "[ ] : . M.sub.i.logical() gal neefektyvus" #~ msgid "" #~ "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' (i.logical)?" #~ msgstr "" #~ "nargs() = %d. Pašaliniai neteisėti argumentai viduje '[ .. ]' (i." #~ "logical)?" #~ msgid "" #~ "m[]: inefficiently indexing single elements - should not " #~ "happen, please report!" #~ msgstr "" #~ "m[]: neefektyviai indeksuojant pavienius elementus - neturėtų " #~ "įvykti, prašome pranešti!" #~ msgid "" #~ "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' (i.2col)?" #~ msgstr "" #~ "nargs() = %d. Pašaliniai neteisėti argumentai viduje '[ .. ]' (i.2col)?" #~ msgid "" #~ ".M.sub.i.2col(): 'i' has no integer column number;\n" #~ " should never happen; please report" #~ msgstr "" #~ ".M.sub.i.2col(): 'i' neturi sveiko skaičiaus stulpelio numerio;\n" #~ " niekada neturėtų įvykti; prašome pranešti" #~ msgid "not-yet-implemented coercion to \"TsparseMatrix\"" #~ msgstr "dar neįgyvendinta paverstas į \"TsparseMatrix\"" #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "Matricos vidinė klaida, esanti [i,,d]; prašome pranešti" #~ msgid "FIXME: NOT YET FINISHED IMPLEMENTATION" #~ msgstr "FIXME: DAR NEBAIGTAS ĮGYVENDINIMAS" #~ msgid "diagonalMatrix in .dense2C() -- should never happen, please report!" #~ msgstr "" #~ "diagonalMatrix, esanti .dense2C() -- niekada neturėtų atsitikti, prašome " #~ "pranešti!" #~ msgid "undefined method for class %s" #~ msgstr "neapibrėžtas metodas klasei %s" #~ msgid "dimensions don't match the number of cells" #~ msgstr "matmenys neatitinka langelių skaičiaus" #~ msgid "" #~ "LU computationally singular: ratio of extreme entries in |diag(U)| = %9.4g" #~ msgstr "" #~ "LU skaičiavimo singuliarumas: ekstremalių įrašų santykis |diag(U)| = %9.4g" #~ msgid "RHS 'b' has wrong number of rows:" #~ msgstr "RHS 'b' turi neteisingą eilučių skaičių:" #~ msgid "'x' has invalid data type" #~ msgstr "'x' turi neleistiną duomenų tipą" #~ msgid "length(x) must be either 1 or #{cols}" #~ msgstr "length(x) turi būti 1 arba #{cols}" #~ msgid "some arguments are not matrices" #~ msgstr "kai kurie argumentai nėra matricos" #~ msgid "%s kind not yet implemented" #~ msgstr "%s rūšis dar neįgyvendinta" #~ msgid "non-square matrix" #~ msgstr "nekvadratinė matrica" #~ msgid "" #~ "matrix with non-zero off-diagonals cannot be coerced to \"diagonalMatrix\"" #~ msgstr "" #~ "matricos su ne nulinėmis įstrižainėmis negalima paversti į " #~ "\"diagonalMatrix\"" #~ msgid "non-matching dimensions" #~ msgstr "nesutampančios dimensijos" #~ msgid "not a positive definite matrix" #~ msgstr "ne teigiamai abiprėžta matrica" #~ msgid "" #~ "as(.,\"dsCMatrix\") is deprecated (since 2008); do use as(., " #~ "\"symmetricMatrix\")" #~ msgstr "" #~ "as(.,\"dsCMatrix\") nebenaudojamas (nuo 2008 m.); naudoti as(., " #~ "\"symmetricMatrix\")" #~ msgid "inefficient coercion (lost triangularity); please report" #~ msgstr "neefektyvi pavertimas (prarastas trianguliarumas); prašome pranešti" #~ msgid "coercion to \"indMatrix\" only works from integer numeric" #~ msgstr "pavertimas į \"indMatrix\" veikia tik iš sveikųjų skaitinių" #~ msgid "" #~ "coercion from list(i1,...,ik, d) to \"indMatrix\" failed.\n" #~ " All entries must be integer valued and the number of columns, d, not " #~ "smaller\n" #~ " than the maximal index i*." #~ msgstr "" #~ "pavertimas iš list(i1,...,ik, d) į \"indMatrix\" nepavyko.\n" #~ " Visi įrašai turi būti vertinami kaip sveikieji ir stulpelių skaičius d " #~ "ne mažesnis\n" #~ " nei maksimalus indeksas i*." #~ msgid "the number of non-zero entries differs from nrow(.)" #~ msgstr "ne nulinių įrašų skaičius skiriasi nuo nrow(.)" #~ msgid "resulting matrix dimension would be too large" #~ msgstr "gautas matricos matmuo būtų per didelis" #~ msgid "replacing \"indMatrix\" entries is not allowed, as rarely sensible" #~ msgstr "pakeisti \"indMatrix\" įrašų neleidžiama, kaip retai praktiškų" #~ msgid "temporarily disabled" #~ msgstr "laikinai išjungtas" #~ msgid "cannot coerce NA values to pattern \"ntCMatrix\"" #~ msgstr "negalima paversti NA reikšmes į modelį \"ntCMatrix\"" #~ msgid "coercion to \"pMatrix\" only works from integer numeric" #~ msgstr "pavertimas į \"pMatrix\" veikia tik iš sveikųjų skaitinių" #~ msgid "not a square matrix" #~ msgstr "ne kvadratinė matrica" #~ msgid "NA's in (i,j) are not allowed" #~ msgstr "NA esantys (i,j) yra neleidžiami" #~ msgid "" #~ "Both 'symmetric' and 'triangular', i.e. asking for diagonal matrix. Use " #~ "'Diagonal()' instead" #~ msgstr "" #~ "Ir 'symmetric', ir 'triangular', t. y. prašant įstrižinės matricos. " #~ "Vietoj to naudokite 'Diagonal()'" #~ msgid "triangular matrix must have all i >= j or i <= j" #~ msgstr "trikampė matrica turi turėti visus i >= j arba i <= j" #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "Matricos vidinė klaida, esanti [i,,d]; prašome pranešti" #~ msgid "" #~ "qr.R() may differ from qr.R() because of permutations. " #~ "Possibly use our qrR() instead" #~ msgstr "" #~ "qr.R() gali skirtis nuo qr.R() dėl perstatų. Galbūt " #~ "vietoj to naudokite mūsų qrR()" #~ msgid "(un)packing only applies to dense matrices, class(x)='%s'" #~ msgstr "(iš)pakavimas taikomas tik tankio matricoms, class(x)='%s'" #~ msgid "'x' is not symmetric -- chol() undefined." #~ msgstr "'x' nėra simetriškas -- chol() neapibrėžtas." #~ msgid "" #~ "extra argument %s will be disregarded in\n" #~ " %s" #~ msgid_plural "" #~ "extra arguments %s will be disregarded in\n" #~ " %s" #~ msgstr[0] "" #~ "papildomas argumentas %s, į kurį bus neatsižvelgiama\n" #~ " %s" #~ msgstr[1] "" #~ "papildomi argumentai %s, į kuriuos bus neatsižvelgiama\n" #~ " %s" #~ msgstr[2] "" #~ "papildomų argumentų %s, į kuriuos bus neatsižvelgiama\n" #~ " %s" Matrix/po/R-Matrix.pot0000644000175100001440000004133114575137654014364 0ustar hornikusersmsgid "" msgstr "" "Project-Id-Version: Matrix 1.7-0\n" "POT-Creation-Date: 2024-03-12 11:27\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" msgid "invalid mode \"%s\"" msgstr "" msgid "%s(<%s>, <%s>) is not yet implemented; ask maintainer(\"%s\") to implement the missing method" msgstr "" msgid "complex %s not yet implemented" msgstr "" msgid "cannot coerce matrix of type \"%s\" to %s" msgstr "" msgid "non0.i() not yet implemented for class %s" msgstr "" msgid "%s=\"%s\" invalid for %s@uplo=\"%s\"" msgstr "" msgid "'%s' is not \"%1$s\", \"D%1$s\", or \"%1$s.\"" msgstr "" msgid "%1$s(%2$s) is undefined: '%2$s' is not positive semidefinite" msgstr "" msgid "matrix is not square" msgstr "" msgid "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", \"%3$s.\", \"%3$s1\", \"%3$s1.\", or \"%4$s\"" msgstr "" msgid "'%s' does not inherit from virtual class %s" msgstr "" msgid "D[i,i] is NA, i=%d" msgstr "" msgid "D[i,i] is negative, i=%d" msgstr "" msgid "'%1$s' is not formally symmetric; factorizing tcrossprod(%1$s)" msgstr "" msgid "unexpected %s=\"%s\" in '%s' method" msgstr "" msgid "Not a valid format" msgstr "" msgid "'file' must be a character string or connection" msgstr "" msgid "Invalid storage type: %s" msgstr "" msgid "Only numeric sparse matrices allowed" msgstr "" msgid "Invalid storage format: %s" msgstr "" msgid "Invalid assembled indicator: %s" msgstr "" msgid "file is not a MatrixMarket file" msgstr "" msgid "type '%s' not recognized" msgstr "" msgid "representation '%s' not recognized" msgstr "" msgid "element type '%s' not recognized" msgstr "" msgid "symmetry form '%s' not recognized" msgstr "" msgid "readMM(): expected %d entries but found only %d" msgstr "" msgid "readMM(): row indices 'i' are not in 1:nrow[=%d]" msgstr "" msgid "readMM(): column indices 'j' are not in 1:ncol[=%d]" msgstr "" msgid "symmetry form 'skew-symmetric' not yet implemented for reading" msgstr "" msgid "symmetry form 'hermitian' not yet implemented for reading" msgstr "" msgid "symmetry form '%s' is not yet implemented" msgstr "" msgid "element type 'complex' not yet implemented" msgstr "" msgid "'%s()' is not yet implemented for element type '%s'" msgstr "" msgid "'%s()' is not yet implemented for representation '%s'" msgstr "" msgid "longer object length is not a multiple of shorter object length" msgstr "" msgid "invalid class \"%s\" in '%s' method" msgstr "" msgid "invalid type \"%s\" in '%s' method" msgstr "" msgid "non-conformable matrix dimensions in %s" msgstr "" msgid "dimnames [%d] mismatch in %s" msgstr "" msgid "inefficient method used for \"- e1\"" msgstr "" msgid "dim [product %d] do not match the length of object [%d]" msgstr "" msgid "internal bug in \"Compare\" method (Cmp.Mat.atomic); please report" msgstr "" msgid "Cmp.Mat.atomic() should not be called for diagonalMatrix" msgstr "" msgid "Matrices must have same number of rows for arithmetic" msgstr "" msgid "number of rows are not compatible for %s" msgstr "" msgid "length of 2nd arg does not match dimension of first" msgstr "" msgid "length of 1st arg does not match dimension of 2nd" msgstr "" msgid "internal bug in \"Logic\" method (Logic.Mat.atomic); please report" msgstr "" msgid "Logic.Mat.atomic() should not be called for diagonalMatrix" msgstr "" msgid "vector too long in Matrix - vector operation" msgstr "" msgid "longer object length\n\tis not a multiple of shorter object length" msgstr "" msgid "invalid class \"%s\" object in '%s' method" msgstr "" msgid "intermediate 'r' is of type %s" msgstr "" msgid "not yet implemented .. please report" msgstr "" msgid "'%s' has non-finite values" msgstr "" msgid "'%1$s' is not \"%2$s\", \"%3$s\", or \"%2$s.\"" msgstr "" msgid "'force' must be (coercable to) TRUE or FALSE" msgstr "" msgid "invalid (to - from)/by in seq(.)" msgstr "" msgid "wrong sign in 'by' argument" msgstr "" msgid "'by' argument is much too small" msgstr "" msgid "length must be non-negative number" msgstr "" msgid "too many arguments" msgstr "" msgid "c(,..) of different kinds, coercing all to 'rleDiff'" msgstr "" msgid "[i] is not yet implemented" msgstr "" msgid "all() is not yet implemented" msgstr "" msgid "sum() is not yet implemented" msgstr "" msgid "prod() is not yet implemented" msgstr "" msgid "not yet implemented" msgstr "" msgid "x / 0 for an x with sign-change\n no longer representable as 'rleDiff'" msgstr "" msgid " --> is not yet implemented" msgstr "" msgid " --> is not yet implemented" msgstr "" msgid "only square matrices can be used as graph incidence matrices" msgstr "" msgid "matrix is not symmetric; consider forceSymmetric(.) or symmpart(.)" msgstr "" msgid "matrix is not triangular; consider triu(.) or tril(.)" msgstr "" msgid "matrix is not diagonal; consider Diagonal(x=diag(.))" msgstr "" msgid "invalid type \"%s\" in '%s'" msgstr "" msgid "invalid %s=\"%s\" to '%s'" msgstr "" msgid "dimensions cannot exceed %s" msgstr "" msgid "invalid class \"%s\" in '%s'" msgstr "" msgid "%s length cannot exceed %s" msgstr "" msgid "'A' must be a square matrix" msgstr "" msgid "must either specify 'A' or the functions 'A.x' and 'At.x'" msgstr "" msgid "when 'A' is specified, 'A.x' and 'At.x' are disregarded" msgstr "" msgid "not converged in %d iterations" msgstr "" msgid "hit a cycle (1) -- stop iterations" msgstr "" msgid "hit a cycle (2) -- stop iterations" msgstr "" msgid "not enough new vecs -- stop iterations" msgstr "" msgid "invalid 'data'" msgstr "" msgid "'nrow', 'ncol', 'byrow' disregarded for [mM]atrix 'data'" msgstr "" msgid "data is too long" msgstr "" msgid "exactly one of 'i', 'j', and 'p' must be missing from call" msgstr "" msgid "use Diagonal() to construct diagonal (symmetric && triangular) sparse matrices" msgstr "" msgid "'giveCsparse' is deprecated; using 'repr' instead" msgstr "" msgid "'giveCsparse' is deprecated; setting repr=\"T\" for you" msgstr "" msgid "'p' must be a nondecreasing vector c(0, ...)" msgstr "" msgid "dimensions cannot exceed 2^31-1" msgstr "" msgid "'i' and 'j' must not contain NA" msgstr "" msgid "'i' and 'j' must be" msgstr "" msgid "positive" msgstr "" msgid "non-negative" msgstr "" msgid "invalid 'dims'" msgstr "" msgid "'dims' must contain all (i,j) pairs" msgstr "" msgid "symmetric matrix must be square" msgstr "" msgid "triangular matrix must be square" msgstr "" msgid "p[length(p)]" msgstr "" msgid "length(i)" msgstr "" msgid "is not an integer multiple of length(x)" msgstr "" msgid "length(x) must not exceed" msgstr "" msgid "invalid 'repr'; must be \"C\", \"R\", or \"T\"" msgstr "" msgid "'n' must be a non-negative integer" msgstr "" msgid "'x' has unsupported class \"%s\"" msgstr "" msgid "'x' has unsupported type \"%s\"" msgstr "" msgid "attempt to recycle 'x' of length 0 to length 'n' (n > 0)" msgstr "" msgid "'shape' must be one of \"g\", \"t\", \"s\"" msgstr "" msgid "'kind' must be one of \"d\", \"l\", \"n\"" msgstr "" msgid "mismatch between typeof(x)=\"%s\" and kind=\"%s\"; using kind=\"%s\"" msgstr "" msgid "'cols' must be numeric" msgstr "" msgid "'cols' has elements not in seq(0, length.out = n)" msgstr "" msgid "'uplo' must be \"U\" or \"L\"" msgstr "" msgid "'lst' must be a list" msgstr "" msgid "'giveCsparse' has been deprecated; setting 'repr = \"T\"' for you" msgstr "" msgid "'giveCsparse' has been deprecated; will use 'repr' instead" msgstr "" msgid "'diagonals' matrix must have %d columns (= length(k) )" msgstr "" msgid "'diagonals' must have the same length (%d) as 'k'" msgstr "" msgid "matrix can only be symmetric if square, but n != m" msgstr "" msgid "for symmetric band matrix, only specify upper or lower triangle\n hence, all k must have the same sign" msgstr "" msgid "the %d-th (sub)-diagonal (k = %d) is too short; filling with NA's" msgstr "" msgid "invalid 'repr'; must be \"C\", \"T\", or \"R\"" msgstr "" msgid "'x' must inherit from \"sparseVector\"" msgstr "" msgid "'ncol' must be >= 0" msgstr "" msgid "'nrow' must be >= 0" msgstr "" msgid "Must specify 'nrow' when 'symmetric' is true" msgstr "" msgid "'nrow' and 'ncol' must be the same when 'symmetric' is true" msgstr "" msgid "'x' must have length nrow^2 when 'symmetric' is true" msgstr "" msgid "'ncol' is not a factor of length(x)" msgstr "" msgid "'nrow' is not a factor of length(x)" msgstr "" msgid "Class %s is not yet implemented" msgstr "" msgid "'%s' and '%s' must be positive integers" msgstr "" msgid "matrix is not symmetric or triangular" msgstr "" msgid "matrix is not symmetric" msgstr "" msgid "matrix is not triangular" msgstr "" msgid "the default value of argument '%s' of method '%s(<%s>, <%s>)' may change from %s to %s as soon as the next release of Matrix; set '%s' when programming" msgstr "" msgid "determinant of non-square matrix is undefined" msgstr "" msgid "replacement diagonal has wrong length" msgstr "" msgid "replacement diagonal has incompatible type \"%s\"" msgstr "" msgid "assigned dimensions are not of type \"%s\" or \"%s\"" msgstr "" msgid "assigned dimensions do not have length %d" msgstr "" msgid "assigned dimensions are NA" msgstr "" msgid "assigned dimensions are negative" msgstr "" msgid "assigned dimensions exceed %s" msgstr "" msgid "assigned dimensions [product %.0f] do not match object length [%.0f]" msgstr "" msgid "'lwd' must be NULL or non-negative numeric" msgstr "" msgid "%s(<%s>) is not yet implemented" msgstr "" msgid "'%s' is not of type \"%s\" or \"%s\"" msgstr "" msgid "'%s' contains NA" msgstr "" msgid "'%s' has elements less than %d" msgstr "" msgid "'%s' is not a non-negative number" msgstr "" msgid "'%s' has elements exceeding '%s'" msgstr "" msgid "'%s' is not %d or %d" msgstr "" msgid "'%s' is not a permutation of seq_len(%s)" msgstr "" msgid "matrix must have exactly one entry in each row or column" msgstr "" msgid "attempt to coerce non-square matrix to %s" msgstr "" msgid "matrix must have exactly one entry in each row and column" msgstr "" msgid "'%s' via sparse -> dense coercion" msgstr "" msgid "invalid %s=\"%s\"" msgstr "" msgid "norm" msgstr "" msgid "'%s' method must use default %s=\"%s\"" msgstr "" msgid "number of nonzero entries cannot exceed %s" msgstr "" msgid "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", or \"%4$s\"" msgstr "" msgid "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%2$s2\", \"%2$s2.\", \"%3$s\", or \"%4$s\"" msgstr "" msgid "non-conformable arguments" msgstr "" msgid "model frame and formula mismatch in sparse.model.matrix()" msgstr "" msgid "non-list contrasts argument ignored" msgstr "" msgid "'contrasts.arg' argument must be named" msgstr "" msgid "variable '%s' is absent, its contrast will be ignored" msgstr "" msgid "Matrix seems negative semi-definite" msgstr "" msgid "'nearPD()' did not converge in %d iterations" msgstr "" msgid "'cl' is not a character string" msgstr "" msgid "not a positive definite matrix (and positive semidefiniteness is not checked)" msgstr "" msgid "'%s' is not a square numeric matrix" msgstr "" msgid "diag(%s) has non-positive or non-finite entries; finite result is doubtful" msgstr "" msgid "matrix is structurally rank deficient; using augmented matrix with additional %d row(s) of zeros" msgstr "" msgid "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%2$s2\", \"%2$s2.\", \"%3$s\", \"%3$s1\", \"%4$s\", or \"%4$s1\"" msgstr "" msgid "'%s' has the wrong length" msgstr "" msgid "invalid '%s': not in %d:%d" msgstr "" msgid "need greater '%s' as pivoting occurred" msgstr "" msgid "qr2rankMatrix(.): QR with only %d out of %d finite diag(R) entries" msgstr "" msgid "rankMatrix(, method = '%s') coerces to dense matrix.\n Probably should rather use method = 'qr' !?" msgstr "" msgid "rankMatrix(x, method='qr'): computing t(x) as nrow(x) < ncol(x)" msgstr "" msgid "[[ suppressing %d column name%s %s ... ]]" msgstr "" msgid "invalid 'col.names' string: %s" msgstr "" msgid "uniDiag=TRUE, but not all diagonal entries are 1" msgstr "" msgid "uniDiag=TRUE, not all entries in diagonal coded as 1" msgstr "" msgid "in show(); maybe adjust options(max.print=, width=)" msgstr "" msgid "suppressing %d columns and %d rows" msgstr "" msgid "suppressing %d rows" msgstr "" msgid "suppressing %d columns" msgstr "" msgid "logic programming error in printSpMatrix2(), please report" msgstr "" msgid "'%s' is not square" msgstr "" msgid "dimensions of '%s' and '%s' are inconsistent" msgstr "" msgid "'%1$s' is computationally singular, rcond(%1$s)=%2$g" msgstr "" msgid "'%s' is computationally singular, min(d)/max(d)=%g, d=abs(diag(U))" msgstr "" msgid "matrix is exactly singular, D[i,i]=0, i=%d" msgstr "" msgid "matrix is exactly singular, J[,j]=0, j=%d" msgstr "" msgid "matrix exactly singular, J[i,]=0, i=%d" msgstr "" msgid "cannot coerce from %s to %s" msgstr "" msgid "a sparseMatrix should rarely be centered: will not be sparse anymore" msgstr "" msgid "length of 'center' must equal the number of columns of 'x'" msgstr "" msgid "length of 'scale' must equal the number of columns of 'x'" msgstr "" msgid "invalid subassignment value class \"%s\"" msgstr "" msgid "invalid subassignment value type \"%s\"" msgstr "" msgid "missing subassignment value" msgstr "" msgid "incorrect number of dimensions" msgstr "" msgid "replacement has length zero" msgstr "" msgid "number of items to replace is not a multiple of replacement length" msgstr "" msgid ".M.repl.i.2col(): 'i' has no integer column number;\n should never happen; please report" msgstr "" msgid "such indexing must be by logical or 2-column numeric matrix" msgstr "" msgid ".M.repl.i.2col(): drop 'matrix' case ..." msgstr "" msgid "negative values are not allowed in a matrix subscript" msgstr "" msgid "NAs are not allowed in subscripted assignments" msgstr "" msgid "m[ ] <- v: inefficiently treating single elements" msgstr "" msgid "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' ?" msgstr "" msgid "RHS 'value' (class %s) matches 'ANY', but must match matrix class %s" msgstr "" msgid "not-yet-implemented 'Matrix[<-' method" msgstr "" msgid "invalid nargs()= %d" msgstr "" msgid "nothing to replace with" msgstr "" msgid "too many replacement values" msgstr "" msgid "i1[1] == 0 ==> C-level verbosity will not happen!" msgstr "" msgid "using\t \"old code\" part in Csparse subassignment" msgstr "" msgid "using\"old code\" part in Csparse subassignment\n >>> please report to Matrix-authors@r-project.org" msgstr "" msgid "you cannot mix negative and positive indices" msgstr "" msgid "index larger than maximal %d" msgstr "" msgid "'NA' indices are not (yet?) supported for sparse Matrices" msgstr "" msgid "logical subscript too long (%d, should be %d)" msgstr "" msgid "no 'dimnames[[.]]': cannot use character indexing" msgstr "" msgid "invalid character indexing" msgstr "" msgid "internal bug: missing 'i' in replTmat(): please report" msgstr "" msgid "[ ] indexing not allowed: forgot a \",\" ?" msgstr "" msgid "internal bug: matrix 'i' in replTmat(): please report" msgstr "" msgid "x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced; NA |--> TRUE." msgstr "" msgid "x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced." msgstr "" msgid "x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE." msgstr "" msgid "x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced." msgstr "" msgid "x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrix" msgstr "" msgid "nargs() = %d should never happen; please report." msgstr "" msgid "row indices must be <= nrow(.) which is %d" msgstr "" msgid "column indices must be <= ncol(.) which is %d" msgstr "" msgid "Internal bug: nargs()=%d; please report" msgstr "" msgid "index must be numeric, logical or sparseVector for indexing sparseVectors" msgstr "" msgid "invalid subscript class \"%s\"" msgstr "" msgid "invalid subscript type \"%s\"" msgstr "" msgid "recycled %s would have maximal index exceeding %s" msgstr "" msgid "subscripts exceeding %s replaced with NA" msgstr "" msgid "subscript out of bounds" msgstr "" msgid "logical subscript too long" msgstr "" msgid "only zeros may be mixed with negative subscripts" msgstr "" msgid "trimmed means are not defined for complex data" msgstr "" msgid "first element used of '%s' argument" msgstr "" msgid "invalid '%s' argument" msgstr "" msgid "should never happen ..." msgstr "" msgid "'%s' is deprecated; using '%s' instead" msgstr "" msgid "'%s' is deprecated; setting %s=\"%s\"" msgstr "" msgid "'%s' has length 0 but '%s' does not" msgstr "" msgid "attempt to coerce matrix with NA to %s" msgstr "" msgid "invalid 'Class2'" msgstr "" Matrix/po/Matrix.pot0000644000175100001440000006146514575137654014177 0ustar hornikusers# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the Matrix package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: Matrix 1.7-0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-14 15:49-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: Csparse.c:26 Csparse.c:61 Csparse.c:86 Csparse.c:113 Csparse.c:127 #: Csparse.c:132 Csparse.c:137 Csparse.c:411 #, c-format msgid "'%s' failed" msgstr "" #: Csparse.c:35 cholmod-common.c:54 #, c-format msgid "'%s' slot is not increasing within columns after sorting" msgstr "" #: Csparse.c:57 #, c-format msgid "'%s' is empty or not square" msgstr "" #: Csparse.c:59 Csparse.c:81 Csparse.c:104 solve.c:43 solve.c:988 #, c-format msgid "dimensions of '%s' and '%s' are inconsistent" msgstr "" #: Csparse.c:83 #, c-format msgid "%s(%s, %s) requires m-by-n '%s' with m >= n > 0" msgstr "" #: Csparse.c:106 #, c-format msgid "%s(%s, %s) requires m-by-n '%s' with n >= m > 0" msgstr "" #: Csparse.c:194 coerce.c:220 coerce.c:240 coerce.c:250 coerce.c:905 #: coerce.c:911 coerce.c:1015 coerce.c:1501 coerce.c:1521 coerce.c:1531 #: coerce.c:2061 coerce.c:2256 coerce.c:2262 coerce.c:2268 coerce.c:2397 #: coerce.c:2404 coerce.c:2494 coerce.c:2629 coerce.c:2707 coerce.c:2729 #: coerce.c:4327 coerce.c:4396 dense.c:696 matmult.c:939 matmult.c:1291 #: solve.c:719 solve.c:972 solve.c:1104 sparse.c:1234 sparse.c:1626 #, c-format msgid "invalid '%s' to '%s'" msgstr "" #: Csparse.c:409 #, c-format msgid "failed to open file \"%s\" for writing" msgstr "" #: attrib.c:229 msgid "invalid factor name" msgstr "" #: attrib.c:233 #, c-format msgid "attempt to set factor on %s without '%s' slot" msgstr "" #: bind.c:46 bind.c:153 msgid "number of rows of matrices must match" msgstr "" #: bind.c:48 bind.c:155 msgid "number of columns of matrices must match" msgstr "" #: bind.c:51 bind.c:158 bind.c:182 bind.c:206 cholmod-common.c:608 #: cholmod-common.c:759 cholmod-common.c:874 cholmod-common.c:975 #: cholmod-etc.c:183 cholmod-etc.c:283 cholmod-etc.c:330 coerce.c:215 #: coerce.c:235 coerce.c:260 coerce.c:268 coerce.c:276 coerce.c:341 #: coerce.c:1496 coerce.c:1516 coerce.c:1543 coerce.c:1551 coerce.c:1559 #: matmult.c:28 matmult.c:50 matmult.c:56 #, c-format msgid "dimensions cannot exceed %s" msgstr "" #: bind.c:210 msgid "number of rows of result is not a multiple of vector length" msgstr "" #: bind.c:212 msgid "number of columns of result is not a multiple of vector length" msgstr "" #: bind.c:626 bind.c:691 sparse.c:913 sparse.c:994 #, c-format msgid "%s cannot exceed %s" msgstr "" #: bind.c:756 bind.c:853 cholmod-common.c:978 cholmod-etc.c:333 coerce.c:29 #: coerce.c:518 coerce.c:811 coerce.c:945 coerce.c:2772 coerce.c:3041 #: coerce.c:3146 dense.c:919 matmult.c:151 matmult.c:212 matmult.c:291 #: matmult.c:379 matmult.c:456 matmult.c:550 matmult.c:868 subscript.c:1232 #: subscript.c:1417 utils-R.c:32 #, c-format msgid "attempt to allocate vector of length exceeding %s" msgstr "" #: bind.c:858 matmult.c:1357 msgid "should never happen ..." msgstr "" #: cholmod-common.c:11 cholmod-common.c:34 validity.c:29 validity.c:150 #: validity.c:229 validity.c:248 validity.c:257 validity.c:299 validity.c:316 #: validity.c:350 validity.c:367 validity.c:401 validity.c:403 validity.c:439 #: validity.c:465 validity.c:485 validity.c:926 validity.c:959 validity.c:1041 #: validity.c:1061 validity.c:1127 validity.c:1129 validity.c:1177 #: validity.c:1240 validity.c:1242 validity.c:1288 validity.c:1335 #: validity.c:1384 validity.c:1417 validity.c:1427 validity.c:1440 #: validity.c:1494 validity.c:1496 validity.c:1528 validity.c:1540 #: validity.c:1563 validity.c:1626 validity.c:1645 validity.c:1647 #: validity.c:1679 validity.c:1714 validity.c:1742 #, c-format msgid "'%s' slot is not of type \"%s\"" msgstr "" #: cholmod-common.c:14 validity.c:274 validity.c:285 validity.c:301 #: validity.c:352 validity.c:487 validity.c:928 validity.c:961 validity.c:1063 #: validity.c:1131 validity.c:1179 validity.c:1244 validity.c:1290 #: validity.c:1429 validity.c:1446 validity.c:1498 validity.c:1500 #: validity.c:1530 validity.c:1542 validity.c:1565 validity.c:1681 #: validity.c:1718 validity.c:1746 validity.c:1796 #, c-format msgid "'%s' slot does not have length %s" msgstr "" #: cholmod-common.c:18 validity.c:304 validity.c:355 validity.c:1634 #: validity.c:1654 validity.c:1656 #, c-format msgid "first element of '%s' slot is not 0" msgstr "" #: cholmod-common.c:23 cholmod-common.c:46 validity.c:34 validity.c:308 #: validity.c:326 validity.c:359 validity.c:377 validity.c:413 validity.c:415 #: validity.c:491 validity.c:1008 validity.c:1020 validity.c:1067 #: validity.c:1140 validity.c:1152 validity.c:1253 validity.c:1265 #: validity.c:1294 validity.c:1345 validity.c:1394 validity.c:1433 #: validity.c:1453 validity.c:1534 validity.c:1550 validity.c:1575 #: validity.c:1639 validity.c:1659 validity.c:1661 validity.c:1688 #, c-format msgid "'%s' slot contains NA" msgstr "" #: cholmod-common.c:26 validity.c:310 validity.c:361 #, c-format msgid "'%s' slot is not nondecreasing" msgstr "" #: cholmod-common.c:29 validity.c:312 validity.c:363 #, c-format msgid "first differences of '%s' slot exceed %s" msgstr "" #: cholmod-common.c:37 validity.c:318 validity.c:369 #, c-format msgid "'%s' slot has length less than %s" msgstr "" #: cholmod-common.c:49 validity.c:328 validity.c:379 validity.c:417 #: validity.c:420 validity.c:493 validity.c:1010 validity.c:1069 #: validity.c:1142 validity.c:1154 validity.c:1255 validity.c:1267 #: validity.c:1347 validity.c:1396 validity.c:1455 validity.c:1577 #: validity.c:1690 #, c-format msgid "'%s' slot has elements not in {%s}" msgstr "" #: cholmod-common.c:165 cholmod-common.c:296 cholmod-common.c:1072 #: cholmod-common.c:1075 cholmod-common.c:1108 cholmod-common.c:1126 #, c-format msgid "'%s' failed in '%s'" msgstr "" #: cholmod-common.c:212 #, c-format msgid "'%s' failed in '%s': %s" msgstr "" #: cholmod-common.c:601 cholmod-common.c:604 cholmod-common.c:606 #: cholmod-common.c:752 cholmod-common.c:755 cholmod-common.c:757 #: cholmod-common.c:867 cholmod-common.c:870 cholmod-common.c:872 #: cholmod-common.c:969 cholmod-common.c:971 cholmod-etc.c:177 #: cholmod-etc.c:179 cholmod-etc.c:181 cholmod-etc.c:277 cholmod-etc.c:279 #: cholmod-etc.c:281 cholmod-etc.c:324 cholmod-etc.c:326 cs-etc.c:43 #, c-format msgid "wrong '%s'" msgstr "" #: cholmod-common.c:611 cholmod-etc.c:186 #, c-format msgid "'%s' would overflow type \"%s\"" msgstr "" #: cholmod-common.c:615 cholmod-etc.c:190 #, c-format msgid "n+1 would overflow type \"%s\"" msgstr "" #: cholmod-common.c:620 cholmod-etc.c:195 #, c-format msgid "leading principal minor of order %d is not positive" msgstr "" #: cholmod-common.c:623 cholmod-etc.c:198 #, c-format msgid "leading principal minor of order %d is zero" msgstr "" #: cholmod-common.c:973 cholmod-etc.c:328 msgid "leading dimension not equal to number of rows" msgstr "" #: cholmod-common.c:1037 #, c-format msgid "" "invalid simplicial Cholesky factorization: structural zero on main diagonal " "in column %d" msgstr "" #: cholmod-common.c:1097 #, c-format msgid "CHOLMOD error '%s' at file '%s', line %d" msgstr "" #: cholmod-common.c:1100 #, c-format msgid "CHOLMOD warning '%s' at file '%s', line %d" msgstr "" #: coerce.c:24 coerce.c:364 coerce.c:1050 #, c-format msgid "attempt to construct non-square %s" msgstr "" #: coerce.c:186 coerce.c:476 coerce.c:1467 coerce.c:1622 #, c-format msgid "second argument of '%s' does not specify a subclass of %s" msgstr "" #: coerce.c:194 coerce.c:200 coerce.c:484 coerce.c:490 coerce.c:925 #: coerce.c:1475 coerce.c:1481 coerce.c:1630 coerce.c:1636 coerce.c:2275 #: coerce.c:3344 coerce.c:3349 #, c-format msgid "'%s' must be \"%s\" or \"%s\"" msgstr "" #: coerce.c:246 coerce.c:496 coerce.c:793 coerce.c:917 coerce.c:1527 #: coerce.c:1642 dense.c:322 dense.c:1102 dense.c:1678 dense.c:1683 #: dense.c:1929 dense.c:2124 sparse.c:784 sparse.c:2449 sparse.c:3141 #: sparse.c:3146 sparse.c:3151 sparse.c:3427 sparse.c:3664 #, c-format msgid "'%s' must be %s or %s" msgstr "" #: coerce.c:266 coerce.c:274 coerce.c:285 coerce.c:1549 coerce.c:1557 #: coerce.c:1568 msgid "nonempty vector supplied for empty matrix" msgstr "" #: coerce.c:287 coerce.c:1570 #, c-format msgid "vector length (%lld) exceeds matrix length (%d * %d)" msgstr "" #: coerce.c:290 coerce.c:1573 #, c-format msgid "matrix length (%d * %d) is not a multiple of vector length (%lld)" msgstr "" #: coerce.c:521 #, c-format msgid "coercing n-by-n %s to %s is not supported for n*n exceeding %s" msgstr "" #: coerce.c:525 coerce.c:815 coerce.c:949 #, c-format msgid "sparse->dense coercion: allocating vector of size %0.1f GiB" msgstr "" #: coerce.c:1196 coerce.c:1941 coerce.c:2948 coerce.c:2954 #, c-format msgid "attempt to construct %s with more than %s nonzero entries" msgstr "" #: coerce.c:3246 msgid "attempt to pack non-square matrix" msgstr "" #: coerce.c:3420 coerce.c:3590 #, c-format msgid "unable to aggregate %s with '%s' and '%s' slots of length exceeding %s" msgstr "" #: coerce.c:4211 #, c-format msgid "attempt to pack a %s" msgstr "" #: coerce.c:4330 dense.c:1232 sparse.c:2580 #, c-format msgid "'%s' must be %s or %s or %s" msgstr "" #: dense.c:210 dense.c:215 sparse.c:590 sparse.c:595 #, c-format msgid "'%s' (%d) must be an integer from %s (%d) to %s (%d)" msgstr "" #: dense.c:218 sparse.c:598 #, c-format msgid "'%s' (%d) must be less than or equal to '%s' (%d)" msgstr "" #: dense.c:428 sparse.c:1070 #, c-format msgid "replacement diagonal has incompatible type \"%s\"" msgstr "" #: dense.c:437 sparse.c:1079 msgid "replacement diagonal has wrong length" msgstr "" #: dense.c:622 sparse.c:1275 msgid "attempt to symmetrize a non-square matrix" msgstr "" #: dense.c:721 sparse.c:1653 msgid "attempt to get symmetric part of non-square matrix" msgstr "" #: dense.c:873 sparse.c:2083 msgid "attempt to get skew-symmetric part of non-square matrix" msgstr "" #: dense.c:1673 sparse.c:3136 #, c-format msgid "'%s' must be %d or %d" msgstr "" #: dense.c:2156 #, c-format msgid "incorrect left cyclic shift, j (%d) < 0" msgstr "" #: dense.c:2159 #, c-format msgid "incorrect left cyclic shift, j (%d) >= k (%d)" msgstr "" #: dense.c:2162 #, c-format msgid "incorrect left cyclic shift, k (%d) > ldx (%d)" msgstr "" #: dense.c:2215 msgid "unknown error in getGivens" msgstr "" #: dense.c:2224 dense.c:2238 dense.c:2268 msgid "X must be a numeric (double precision) matrix" msgstr "" #: dense.c:2240 dense.c:2270 msgid "y must be a numeric (double precision) matrix" msgstr "" #: dense.c:2244 dense.c:2274 #, c-format msgid "number of rows in y (%d) does not match number of rows in X (%d)" msgstr "" #: dense.c:2260 #, c-format msgid "LAPACK dposv returned error code %d" msgstr "" #: dense.c:2288 dense.c:2294 #, c-format msgid "LAPACK dgels returned error code %d" msgstr "" #: dense.c:2313 msgid "X must be a real (numeric) matrix" msgstr "" #: dense.c:2316 #, c-format msgid "tol, given as %g, must be >= 0" msgstr "" #: dense.c:2318 #, c-format msgid "tol, given as %g, must be <= 1" msgstr "" #: dense.c:2347 dense.c:2355 #, c-format msgid "LAPACK dgeqrf returned error code %d" msgstr "" #: dense.c:2360 dense.c:2383 #, c-format msgid "LAPACK dtrcon returned error code %d" msgstr "" #: determinant.c:33 msgid "determinant of non-square matrix is undefined" msgstr "" #: determinant.c:276 #, c-format msgid "%s(<%s>) does not support structurally rank deficient case" msgstr "" #: expm.c:39 msgid "Matrix exponential requires square, non-null matrix" msgstr "" #: expm.c:56 expm.c:58 #, c-format msgid "dgeMatrix_exp: LAPACK routine dgebal returned %d" msgstr "" #: expm.c:96 #, c-format msgid "dgeMatrix_exp: dgetrf returned error code %d" msgstr "" #: expm.c:98 #, c-format msgid "dgeMatrix_exp: dgetrs returned error code %d" msgstr "" #: factor.c:330 msgid "dgeMatrix_Schur: argument x must be a non-null square matrix" msgstr "" #: factor.c:343 msgid "dgeMatrix_Schur: first call to dgees failed" msgstr "" #: factor.c:352 #, c-format msgid "dgeMatrix_Schur: dgees returned code %d" msgstr "" #: factor.c:403 sparse.c:196 #, c-format msgid "'%s' is not a number" msgstr "" #: factor.c:424 #, c-format msgid "LU factorization of m-by-n %s requires m == n" msgstr "" #: factor.c:433 #, c-format msgid "LU factorization of %s failed: out of memory or near-singular" msgstr "" #: factor.c:510 #, c-format msgid "QR factorization of m-by-n %s requires m >= n" msgstr "" #: factor.c:519 #, c-format msgid "QR factorization of %s failed: out of memory" msgstr "" #: factor.c:619 factor.c:897 #, c-format msgid "'%s' is not a number or not finite" msgstr "" #: idz.c:467 idz.c:528 #, c-format msgid "incompatible '%s' and '%s' in '%s'" msgstr "" #: kappa.c:10 kappa.c:54 #, c-format msgid "argument '%s' is not of type \"%s\"" msgstr "" #: kappa.c:13 kappa.c:57 #, c-format msgid "argument '%s' has length %d" msgstr "" #: kappa.c:17 kappa.c:61 #, c-format msgid "argument '%s' (\"%s\") does not have string length %d" msgstr "" #: kappa.c:41 #, c-format msgid "" "argument '%s' (\"%s\") is not \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", or " "\"%s\"" msgstr "" #: kappa.c:75 #, c-format msgid "argument '%s' (\"%s\") is not \"%s\", \"%s\", or \"%s\"" msgstr "" #: kappa.c:238 #, c-format msgid "%s(%s) is undefined: '%s' is not square" msgstr "" #: matmult.c:107 matmult.c:210 matmult.c:289 matmult.c:377 matmult.c:454 #: matmult.c:548 matmult.c:812 matmult.c:862 msgid "non-conformable arguments" msgstr "" #: matmult.c:782 matmult.c:810 #, c-format msgid "'%s' does not support complex matrices" msgstr "" #: objects.c:23 #, c-format msgid "unexpected type \"%s\" in '%s'" msgstr "" #: objects.c:41 objects.c:58 #, c-format msgid "unexpected kind \"%c\" in '%s'" msgstr "" #: perm.c:26 perm.c:106 msgid "attempt to get sign of non-permutation" msgstr "" #: perm.c:51 perm.c:123 msgid "attempt to invert non-permutation" msgstr "" #: perm.c:66 msgid "invalid transposition vector" msgstr "" #: perm.c:79 perm.c:81 perm.c:96 perm.c:98 perm.c:113 perm.c:133 perm.c:145 #, c-format msgid "'%s' is not of type \"%s\"" msgstr "" #: perm.c:83 perm.c:100 perm.c:147 #, c-format msgid "'%s' does not have length %d" msgstr "" #: perm.c:86 perm.c:103 #, c-format msgid "'%s' is NA" msgstr "" #: perm.c:115 perm.c:138 #, c-format msgid "'%s' or '%s' is not of type \"%s\"" msgstr "" #: perm.c:117 perm.c:140 #, c-format msgid "'%s' or '%s' does not have length %d" msgstr "" #: perm.c:120 perm.c:143 #, c-format msgid "'%s' or '%s' is NA" msgstr "" #: perm.c:136 #, c-format msgid "'%s' has length exceeding %s" msgstr "" #: perm.c:150 #, c-format msgid "'%s' is NA or less than %s" msgstr "" #: solve.c:38 #, c-format msgid "'%s' is not square" msgstr "" #: solve.c:497 #, c-format msgid "%s(<%s>, <%s>) failed: out of memory" msgstr "" #: solve.c:618 #, c-format msgid "attempt to construct %s with more than %s nonzero elements" msgstr "" #: subscript.c:1542 subscript.c:1695 subscript.c:1938 subscript.c:2122 #, c-format msgid "%s too dense for %s; would have more than %s nonzero entries" msgstr "" #: subscript.c:2209 #, c-format msgid "NA subscripts in %s not supported for '%s' inheriting from %s" msgstr "" #: t_subassign.c:141 msgid "invalid class of 'x' in Csparse_subassign()" msgstr "" #: t_subassign.c:143 msgid "invalid class of 'value' in Csparse_subassign()" msgstr "" #: t_subassign.c:186 #, c-format msgid "x[] <- val: val is coerced to logical for \"%s\" x" msgstr "" #: t_subassign.c:191 #, c-format msgid "" "x[] <- val: val should be integer or logical, is coerced to integer, for " "\"%s\" x" msgstr "" #: t_subassign.c:198 msgid "programming error in Csparse_subassign() should never happen" msgstr "" #: utils-R.c:30 utils-R.c:116 #, c-format msgid "indices would exceed %s" msgstr "" #: utils-R.c:235 utils-R.c:270 utils-R.c:281 utils-R.c:312 msgid "Argument must be numeric-like atomic vector" msgstr "" #: utils-R.c:345 msgid "'data' must be of a vector type" msgstr "" #: utils-R.c:352 #, c-format msgid "invalid '%s' argument" msgstr "" #: utils-R.c:359 utils-R.c:367 msgid "non-numeric matrix extent" msgstr "" #: utils-R.c:362 msgid "invalid 'nrow' value (too large or NA)" msgstr "" #: utils-R.c:364 msgid "invalid 'nrow' value (< 0)" msgstr "" #: utils-R.c:370 msgid "invalid 'ncol' value (too large or NA)" msgstr "" #: utils-R.c:372 msgid "invalid 'ncol' value (< 0)" msgstr "" #: utils-R.c:390 #, c-format msgid "" "data length [%lld] is not a sub-multiple or multiple of the number of rows " "[%d]" msgstr "" #: utils-R.c:395 #, c-format msgid "" "data length [%lld] is not a sub-multiple or multiple of the number of " "columns [%d]" msgstr "" #: utils-R.c:399 msgid "data length exceeds size of matrix" msgstr "" #: utils-R.c:404 msgid "too many elements specified" msgstr "" #: utils-R.c:545 msgid "Argument ij must be 2-column integer matrix" msgstr "" #: utils-R.c:570 msgid "subscript 'i' out of bounds in M[ij]" msgstr "" #: utils-R.c:572 msgid "subscript 'j' out of bounds in M[ij]" msgstr "" #: utils-R.c:626 msgid "i and j must be integer vectors of the same length" msgstr "" #: validity.c:31 validity.c:52 validity.c:231 validity.c:250 validity.c:259 #: validity.c:441 validity.c:467 validity.c:977 validity.c:1419 validity.c:1443 #, c-format msgid "'%s' slot does not have length %d" msgstr "" #: validity.c:36 validity.c:932 validity.c:965 #, c-format msgid "'%s' slot has negative elements" msgstr "" #: validity.c:50 validity.c:164 #, c-format msgid "'%s' slot is not a list" msgstr "" #: validity.c:68 #, c-format msgid "%s[[%d]] is not NULL or a vector" msgstr "" #: validity.c:71 #, c-format msgid "length of %s[[%d]] (%lld) is not equal to %s[%d] (%d)" msgstr "" #: validity.c:170 #, c-format msgid "'%s' slot has no '%s' attribute" msgstr "" #: validity.c:181 validity.c:244 validity.c:435 validity.c:506 validity.c:1082 #: validity.c:1413 validity.c:1774 #, c-format msgid "%s[1] != %s[2] (matrix is not square)" msgstr "" #: validity.c:206 validity.c:219 #, c-format msgid "%s[1] differs from %s[2]" msgstr "" #: validity.c:234 validity.c:253 validity.c:262 validity.c:444 #, c-format msgid "'%s' slot is not \"%s\" or \"%s\"" msgstr "" #: validity.c:331 validity.c:1580 #, c-format msgid "'%s' slot is not increasing within columns" msgstr "" #: validity.c:382 #, c-format msgid "'%s' slot is not increasing within rows" msgstr "" #: validity.c:406 validity.c:790 validity.c:816 validity.c:842 validity.c:1043 #: validity.c:1649 validity.c:1651 #, c-format msgid "'%s' and '%s' slots do not have equal length" msgstr "" #: validity.c:409 #, c-format msgid "'%s' slot has nonzero length but %s is 0" msgstr "" #: validity.c:450 validity.c:454 #, c-format msgid "'%s' slot is \"%s\" but '%s' slot does not have length %s" msgstr "" #: validity.c:470 #, c-format msgid "'%s' slot is not %d or %d" msgstr "" #: validity.c:476 validity.c:479 #, c-format msgid "%s-by-%s %s invalid for positive '%s' when %s=%d" msgstr "" #: validity.c:516 validity.c:1145 validity.c:1157 validity.c:1258 #: validity.c:1270 validity.c:1350 validity.c:1399 validity.c:1458 #, c-format msgid "'%s' slot contains duplicates" msgstr "" #: validity.c:544 validity.c:589 validity.c:635 validity.c:680 validity.c:724 #: validity.c:759 #, c-format msgid "%s=\"%s\" but there are entries below the diagonal" msgstr "" #: validity.c:554 validity.c:602 validity.c:645 validity.c:693 validity.c:729 #: validity.c:770 #, c-format msgid "%s=\"%s\" but there are entries above the diagonal" msgstr "" #: validity.c:592 validity.c:605 validity.c:683 validity.c:696 validity.c:762 #: validity.c:773 #, c-format msgid "%s=\"%s\" but there are entries on the diagonal" msgstr "" #: validity.c:878 validity.c:902 validity.c:906 msgid "matrix has negative diagonal elements" msgstr "" #: validity.c:922 validity.c:950 validity.c:954 msgid "matrix has nonunit diagonal elements" msgstr "" #: validity.c:974 validity.c:999 validity.c:1793 #, c-format msgid "'%s' slot is not of type \"%s\" or \"%s\"" msgstr "" #: validity.c:982 validity.c:989 #, c-format msgid "'%s' slot is NA" msgstr "" #: validity.c:984 validity.c:991 #, c-format msgid "'%s' slot is negative" msgstr "" #: validity.c:993 #, c-format msgid "'%s' slot exceeds %s" msgstr "" #: validity.c:1003 #, c-format msgid "'%s' slot has length greater than '%s' slot" msgstr "" #: validity.c:1013 validity.c:1641 validity.c:1663 validity.c:1665 #, c-format msgid "'%s' slot is not increasing" msgstr "" #: validity.c:1023 #, c-format msgid "'%s' slot has elements not in {%s} after truncation towards zero" msgstr "" #: validity.c:1026 #, c-format msgid "'%s' slot is not increasing after truncation towards zero" msgstr "" #: validity.c:1092 validity.c:1119 validity.c:1781 validity.c:1788 #, c-format msgid "dimensions of '%s' slot are not identical to '%s'" msgstr "" #: validity.c:1094 #, c-format msgid "'%s' slot is upper (not lower) triangular" msgstr "" #: validity.c:1107 #, c-format msgid "'%s' slot has nonunit diagonal elements" msgstr "" #: validity.c:1121 #, c-format msgid "'%s' slot is lower (not upper) triangular" msgstr "" #: validity.c:1133 validity.c:1246 validity.c:1337 validity.c:1386 #, c-format msgid "'%s' slot does not have length %s or length %s" msgstr "" #: validity.c:1173 msgid "matrix has more columns than rows" msgstr "" #: validity.c:1193 #, c-format msgid "'%s' slot has fewer than %s rows" msgstr "" #: validity.c:1195 #, c-format msgid "'%s' slot has more than %s rows" msgstr "" #: validity.c:1197 validity.c:1219 #, c-format msgid "'%s' slot does not have %s columns" msgstr "" #: validity.c:1204 #, c-format msgid "'%s' slot must be lower trapezoidal but has entries above the diagonal" msgstr "" #: validity.c:1217 #, c-format msgid "'%s' slot does not have %s row" msgstr "" #: validity.c:1226 #, c-format msgid "'%s' slot must be upper trapezoidal but has entries below the diagonal" msgstr "" #: validity.c:1230 #, c-format msgid "'%s' slot has negative diagonal elements" msgstr "" #: validity.c:1296 #, c-format msgid "'%s' slot has elements not in {%s}\\{%s}" msgstr "" #: validity.c:1305 #, c-format msgid "'%s' slot has unpaired negative elements" msgstr "" #: validity.c:1331 validity.c:1375 validity.c:1379 validity.c:1727 #: validity.c:1759 msgid "Cholesky factor has negative diagonal elements" msgstr "" #: validity.c:1422 #, c-format msgid "%s[%d] (%s) is not in %s" msgstr "" #: validity.c:1435 validity.c:1536 #, c-format msgid "%s is not in {%s}" msgstr "" #: validity.c:1472 #, c-format msgid "%s is not representable as \"%s\"" msgstr "" #: validity.c:1477 validity.c:1483 #, c-format msgid "%s[%d] (%s) is not %d or %d" msgstr "" #: validity.c:1480 validity.c:1596 validity.c:1599 validity.c:1602 #, c-format msgid "%s[%d] (%s) is not %d" msgstr "" #: validity.c:1505 #, c-format msgid "%s has elements not in {%s}" msgstr "" #: validity.c:1508 #, c-format msgid "%s has elements not in {%s}\\{%s}" msgstr "" #: validity.c:1511 #, c-format msgid "%s is %d but columns are not stored in increasing order" msgstr "" #: validity.c:1514 validity.c:1517 #, c-format msgid "traversal of '%s' slot does not complete in exactly %s steps" msgstr "" #: validity.c:1523 validity.c:1525 #, c-format msgid "%s is not %d" msgstr "" #: validity.c:1546 #, c-format msgid "column '%s' is stored first but %s is not 0" msgstr "" #: validity.c:1552 #, c-format msgid "'%s' slot is not increasing when traversed in stored column order" msgstr "" #: validity.c:1554 #, c-format msgid "'%s' slot allocates fewer than %s elements for column '%s'" msgstr "" #: validity.c:1557 #, c-format msgid "'%s' slot allocates more than %s elements for column '%s'" msgstr "" #: validity.c:1571 #, c-format msgid "first entry in column '%s' does not have row index '%s'" msgstr "" #: validity.c:1605 validity.c:1608 #, c-format msgid "%s[%d] (%s) is negative" msgstr "" #: validity.c:1611 #, c-format msgid "%s[%d] (%s) is not less than %s" msgstr "" #: validity.c:1629 #, c-format msgid "'%s' slot has length less than %d" msgstr "" #: validity.c:1631 #, c-format msgid "'%s' slot has length greater than %s" msgstr "" #: validity.c:1636 #, c-format msgid "last element of '%s' slot is not %s" msgstr "" #: validity.c:1669 #, c-format msgid "first differences of '%s' slot are less than those of '%s' slot" msgstr "" #: validity.c:1672 #, c-format msgid "supernode lengths exceed %s" msgstr "" #: validity.c:1674 #, c-format msgid "first differences of '%s' slot are not equal to supernode lengths" msgstr "" #: validity.c:1694 #, c-format msgid "" "'%s' slot is wrong within diagonal blocks (row and column indices do not " "coincide)" msgstr "" #: validity.c:1697 #, c-format msgid "'%s' slot is not increasing within supernodes" msgstr "" #: validity.c:1812 #, c-format msgid "invalid class \"%s\" object: %s" msgstr "" #: vector.c:90 #, c-format msgid "%s length cannot exceed %s" msgstr "" Matrix/po/R-ko.po0000644000175100001440000013474714575137654013363 0ustar hornikusers# Korean translations for Matrix package. # Recommended/Matrix/po/R-ko.po # # Thanks to Martin Maechler # # This file is distributed under the same license as the R Matrix package. # Maintained by Chel Hee Lee , 2013-2015. # # Notes: # Freezing on 15-JUL-2015 for R-3.3.0, QC: PASS # Freezing on 30-MAR-2015 for R-3.2.0, QC: PASS # Freezing on 28-FEB-2015 for R-3.1.3, QC: PASS # msgid "" msgstr "" "Project-Id-Version: Matrix 1.1-3\n" "POT-Creation-Date: 2024-03-15 17:22\n" "PO-Revision-Date: 2015-07-15 17:14-0600\n" "Last-Translator:Chel Hee Lee \n" "Language-Team: Chel Hee Lee \n" "Language: ko\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #, fuzzy msgid "invalid mode \"%s\"" msgstr "사용할 수 있는 'mod'(%s)가 아닙니다." msgid "" "%s(<%s>, <%s>) is not yet implemented; ask maintainer(\"%s\") to implement " "the missing method" msgstr "" #, fuzzy msgid "complex %s not yet implemented" msgstr "클래스 %s는 아직 구현되지 않았습니다." #, fuzzy msgid "cannot coerce matrix of type \"%s\" to %s" msgstr "'NA'를 \"nsparseMatrix\"으로 강제변환(coerce)할 수 없습니다." #, fuzzy msgid "non0.i() not yet implemented for class %s" msgstr "클래스 %s의 경우에 아직 구현되지 않았습니다." msgid "%s=\"%s\" invalid for %s@uplo=\"%s\"" msgstr "" msgid "'%s' is not \"%1$s\", \"D%1$s\", or \"%1$s.\"" msgstr "" #, fuzzy msgid "%1$s(%2$s) is undefined: '%2$s' is not positive semidefinite" msgstr "chol()은 음의 값을 가진 대각행렬에 대하여 정의되지 않았습니다." #, fuzzy msgid "matrix is not square" msgstr "대각행렬이 아닙니다." msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", \"%3$s.\", \"%3$s1\", \"%3$s1." "\", or \"%4$s\"" msgstr "" #, fuzzy msgid "'%s' does not inherit from virtual class %s" msgstr "'x'는 \"sparseVector\"로부터의 상속(inherit)이어야 합니다." msgid "D[i,i] is NA, i=%d" msgstr "" msgid "D[i,i] is negative, i=%d" msgstr "" msgid "'%1$s' is not formally symmetric; factorizing tcrossprod(%1$s)" msgstr "" msgid "unexpected %s=\"%s\" in '%s' method" msgstr "" msgid "Not a valid format" msgstr "올바른 형식(format)이 아닙니다." msgid "'file' must be a character string or connection" msgstr "" "'file'은 반드시 문자열(character string) 또는 커넥션(connection)이어야 합니" "다." msgid "Invalid storage type: %s" msgstr "%s는 사용할 수 없는 저장형식(storage format)입니다." msgid "Only numeric sparse matrices allowed" msgstr "오로지 수치형 희소행렬(sparse matrices)만을 사용할 수 있습니다." msgid "Invalid storage format: %s" msgstr "%s는 사용할 수 있는 저장형식(storage format)이 아닙니다." msgid "Invalid assembled indicator: %s" msgstr "Invalid assembled indicator: %s" msgid "file is not a MatrixMarket file" msgstr "file에 MatrixMarket 형식의 파일이 입력되지 않았습니다." msgid "type '%s' not recognized" msgstr "'%s'는 사용가능한 유형(type)이 아닙니다." msgid "representation '%s' not recognized" msgstr "'%s'는 사용가능한 표현(representation)이 아닙니다." msgid "element type '%s' not recognized" msgstr "'%s'는 사용가능한 원소유형(element type)이 아닙니다." msgid "symmetry form '%s' not recognized" msgstr "'%s'는 사용가능한 대칭형식(symmetry form)이 아닙니다." msgid "readMM(): expected %d entries but found only %d" msgstr "" #, fuzzy msgid "readMM(): row indices 'i' are not in 1:nrow[=%d]" msgstr "readMM(): 행(row) 'i'는 1:nr 내에 존재하지 않습니다." #, fuzzy msgid "readMM(): column indices 'j' are not in 1:ncol[=%d]" msgstr "readMM(): 열(column) 'j'는 1:nc 내에 존재하지 않습니다." msgid "symmetry form 'skew-symmetric' not yet implemented for reading" msgstr "" "대칭형식(symmetry form)이 'skew-symmetric'인 경우에는 아직 구현되지 않았습니" "다." msgid "symmetry form 'hermitian' not yet implemented for reading" msgstr "" "대칭형식(symmetry form)이 'hermitian'의 경우에는 아직 구현되지 않았습니다." msgid "symmetry form '%s' is not yet implemented" msgstr "대칭형식(symmetry form)이 '%s'인 경우에는 아직 구현되지 않았습니다." msgid "element type 'complex' not yet implemented" msgstr "" "원소유형(element type)이 'complex'인 경우에는 아직 구현되지 않았습니다." msgid "'%s()' is not yet implemented for element type '%s'" msgstr "" "원소유형(element type)이 '%2$s'의 경우에 아직 구현되지 않은 '%1$s()'입니다." msgid "'%s()' is not yet implemented for representation '%s'" msgstr "" "표현(representation)이 '%2$s'의 경우에 아직 구현되지 않은 '%1$s()'입니다." msgid "longer object length is not a multiple of shorter object length" msgstr "객체의 길이(긴 것)이 다른 객체의 길이(짧은 것)의 배수가 아닙니다." #, fuzzy msgid "invalid class \"%s\" in '%s' method" msgstr "%s은 올바른 'col.names' 문자열이 아닙니다" msgid "invalid type \"%s\" in '%s' method" msgstr "" msgid "non-conformable matrix dimensions in %s" msgstr "%s에 입력된 행렬의 차원이 정합(conformable)하지 않습니다." msgid "dimnames [%d] mismatch in %s" msgstr "%2$s에 입력된 dimnames [%1$d]가 일치하지 않습니다." msgid "inefficient method used for \"- e1\"" msgstr "\"- e1\"를 사용하는데 비효율적인 메소드(method)입니다." msgid "dim [product %d] do not match the length of object [%d]" msgstr "dim [product %d]의 값이 객체 [%d]의 길이와 일치하지 않습니다." msgid "internal bug in \"Compare\" method (Cmp.Mat.atomic); please report" msgstr "" "메소드 \"Compare\" (Cmp.Mat.atomic)내에서 버그(internal bug)가 발생했습니다. " "이를 꼭 보고해 주셨으면 합니다." msgid "Cmp.Mat.atomic() should not be called for diagonalMatrix" msgstr "Cmp.Mat.atomic()은 digonalMatrix에 의하여 호출될 수 없습니다." msgid "Matrices must have same number of rows for arithmetic" msgstr "" "원소단위의 연산을 수행하기 위해서는 입력된 각 행렬이 가지는 열의 개수가 서로 " "같아야 합니다." msgid "number of rows are not compatible for %s" msgstr "%s의 경우 행의 개수가 올바르지 않습니다." msgid "length of 2nd arg does not match dimension of first" msgstr "" "두번째 인자(arg)의 길이가 첫번째 인자의 차원(dimension)과 일치하지 않습니다." msgid "length of 1st arg does not match dimension of 2nd" msgstr "" "첫번째 인자(arg)의 길이는 두번째 인자의 차원(dimension)과 일치하지 않습니다." msgid "internal bug in \"Logic\" method (Logic.Mat.atomic); please report" msgstr "" "메소드 \"Logic\" (Logic.Mat.atomic)내에서 버그가 발생되었습니다. 이를 꼭 보" "고해 주셨으면 합니다." msgid "Logic.Mat.atomic() should not be called for diagonalMatrix" msgstr "Logic.Mat.atomic()은 diagonalMatrix에 호출될 수 없습니다." msgid "vector too long in Matrix - vector operation" msgstr "" "행렬과 벡터 연산(Matrix - vector operation)에 사용될 벡터의 길이가 너무 깁니" "다." msgid "" "longer object length\n" "\tis not a multiple of shorter object length" msgstr "" "객체의 길이(긴 것)가\n" "\t 다른 객체가 가지는 길이(짧은 것)의 배수가 아닙니다." #, fuzzy msgid "invalid class \"%s\" object in '%s' method" msgstr "%s은 올바른 'col.names' 문자열이 아닙니다" msgid "intermediate 'r' is of type %s" msgstr "intermediate 'r' is of type %s" msgid "not yet implemented .. please report" msgstr "아직 구현되지 않았습니다. 보고를 부탁드립니다." msgid "'%s' has non-finite values" msgstr "" msgid "'%1$s' is not \"%2$s\", \"%3$s\", or \"%2$s.\"" msgstr "" msgid "'force' must be (coercable to) TRUE or FALSE" msgstr "'force'는 반드시 (강제변환될 수 있는) TRUE 또는 FALSE 이어야 합니다." msgid "invalid (to - from)/by in seq(.)" msgstr "seq(.)의 사용시 (to - from)/by의 값이 올바르지 않습니다." msgid "wrong sign in 'by' argument" msgstr "'by' 인자에 사용된 부호(sign)가 올바르지 않습니다." msgid "'by' argument is much too small" msgstr "'by' 인자에 사용된 값이 너무 작습니다." msgid "length must be non-negative number" msgstr "길이(length)는 반드시 음이 아닌 수이어야 합니다." msgid "too many arguments" msgstr "입력된 인자의 개수가 너무 많습니다." msgid "c(,..) of different kinds, coercing all to 'rleDiff'" msgstr "c(,..) of different kinds, 모두 'rleDiff'로 강제변환합니다" msgid "[i] is not yet implemented" msgstr "[i]는 아직 구현되지 않았습니다." msgid "all() is not yet implemented" msgstr "all()는 아직 구현되지 않았습니다." msgid "sum() is not yet implemented" msgstr "sum()는 아직 구현되지 않았습니다." msgid "prod() is not yet implemented" msgstr "prod()는 아직 구현되지 않았습니다." msgid "not yet implemented" msgstr "아직 구현되지 않았습니다." msgid "" "x / 0 for an x with sign-change\n" " no longer representable as 'rleDiff'" msgstr "" "x / 0 for an x with sign-change\n" " no longer representable as 'rleDiff'" msgid " --> is not yet implemented" msgstr " --> 은 아직 구현되지 않았습니다." msgid " --> is not yet implemented" msgstr " --> 은 아직 구현되지 않았습니다." #, fuzzy msgid "only square matrices can be used as graph incidence matrices" msgstr "" "오로지 정방(square) 행렬만이 그래프를 위한 접속행렬(incidence matrices)로서 " "사용할 수 있습니다." #, fuzzy msgid "matrix is not symmetric; consider forceSymmetric(.) or symmpart(.)" msgstr "" "대칭행렬(symmetric matrix)가 아닙니다. forceSymmtric() 또는 symmpart() 함수" "의 사용을 고려해 보시길 바랍니다." #, fuzzy msgid "matrix is not triangular; consider triu(.) or tril(.)" msgstr "삼각행렬이 아닙니다." msgid "matrix is not diagonal; consider Diagonal(x=diag(.))" msgstr "" #, fuzzy msgid "invalid type \"%s\" in '%s'" msgstr "올바르지 않은 'type'입니다." #, fuzzy msgid "invalid %s=\"%s\" to '%s'" msgstr "%s는 사용할 수 없는 저장형식(storage format)입니다." msgid "dimensions cannot exceed %s" msgstr "" #, fuzzy msgid "invalid class \"%s\" in '%s'" msgstr "%s은 올바른 'col.names' 문자열이 아닙니다" msgid "%s length cannot exceed %s" msgstr "" msgid "'A' must be a square matrix" msgstr "'A'는 반드시 정방행렬(square matrix)이어야 합니다." msgid "must either specify 'A' or the functions 'A.x' and 'At.x'" msgstr "'A' 또는 'A.x'와 'At.x'는 반드시 주어져야 합니다." msgid "when 'A' is specified, 'A.x' and 'At.x' are disregarded" msgstr "'A'가 주어진 경우에 입력된 'A.x'와 'At.x'는 사용되지 않습니다." msgid "not converged in %d iterations" msgstr "%d번째 반복에서도 수렴하지 않습니다." msgid "hit a cycle (1) -- stop iterations" msgstr "cycle (1)에 도달했습니다 -- 반복을 중지합니다" msgid "hit a cycle (2) -- stop iterations" msgstr "cycle (2)에 도달했습니다 -- 반복을 중지합니다" msgid "not enough new vecs -- stop iterations" msgstr "not enough new vecs -- stop iterations" msgid "invalid 'data'" msgstr "입력된 'data'는 올바르지 않습니다." #, fuzzy msgid "'nrow', 'ncol', 'byrow' disregarded for [mM]atrix 'data'" msgstr "행렬 'data'인 경우에 입력된 'nrow', 'ncol' 등은 사용되지 않습니다." msgid "data is too long" msgstr "" #, fuzzy msgid "exactly one of 'i', 'j', and 'p' must be missing from call" msgstr "'i', 'j', 또는 'p' 중 하나가 호출(call)로부터 누락된 것 같습니다. " msgid "" "use Diagonal() to construct diagonal (symmetric && triangular) sparse " "matrices" msgstr "" msgid "'giveCsparse' is deprecated; using 'repr' instead" msgstr "" msgid "'giveCsparse' is deprecated; setting repr=\"T\" for you" msgstr "" #, fuzzy msgid "'p' must be a nondecreasing vector c(0, ...)" msgstr "'p'는 반드시 감소하지 않는(non-decreasing) 벡터 (0, ...)이어야 합니다." msgid "dimensions cannot exceed 2^31-1" msgstr "" msgid "'i' and 'j' must not contain NA" msgstr "" msgid "'i' and 'j' must be" msgstr "" msgid "positive" msgstr "" msgid "non-negative" msgstr "" #, fuzzy msgid "invalid 'dims'" msgstr "입력된 'data'는 올바르지 않습니다." msgid "'dims' must contain all (i,j) pairs" msgstr "" msgid "symmetric matrix must be square" msgstr "대칭행렬(symmetric matrix)는 반드시 정방(square)이어야 합니다." #, fuzzy msgid "triangular matrix must be square" msgstr "대칭행렬(symmetric matrix)는 반드시 정방(square)이어야 합니다." msgid "p[length(p)]" msgstr "" msgid "length(i)" msgstr "" #, fuzzy msgid "is not an integer multiple of length(x)" msgstr "length(i)는 length(x)의 배수가 아닙니다." msgid "length(x) must not exceed" msgstr "" msgid "invalid 'repr'; must be \"C\", \"R\", or \"T\"" msgstr "" #, fuzzy msgid "'n' must be a non-negative integer" msgstr "길이(length)는 반드시 음이 아닌 수이어야 합니다." msgid "'x' has unsupported class \"%s\"" msgstr "" msgid "'x' has unsupported type \"%s\"" msgstr "" msgid "attempt to recycle 'x' of length 0 to length 'n' (n > 0)" msgstr "" msgid "'shape' must be one of \"g\", \"t\", \"s\"" msgstr "" msgid "'kind' must be one of \"d\", \"l\", \"n\"" msgstr "" msgid "mismatch between typeof(x)=\"%s\" and kind=\"%s\"; using kind=\"%s\"" msgstr "" #, fuzzy msgid "'cols' must be numeric" msgstr "'ncol'은 반드시 >= 0 이어야 합니다. " msgid "'cols' has elements not in seq(0, length.out = n)" msgstr "" msgid "'uplo' must be \"U\" or \"L\"" msgstr "" #, fuzzy msgid "'lst' must be a list" msgstr "'ncol'은 반드시 >= 0 이어야 합니다. " msgid "'giveCsparse' has been deprecated; setting 'repr = \"T\"' for you" msgstr "" msgid "'giveCsparse' has been deprecated; will use 'repr' instead" msgstr "" msgid "'diagonals' matrix must have %d columns (= length(k) )" msgstr "" "'diagonals' 행렬은 반드시 %d (=length(k))개의 열을 가지고 있어야 합니다." msgid "'diagonals' must have the same length (%d) as 'k'" msgstr "'diagnoals'의 길이는 반드시 'k'(=%d)이어야 합니다." msgid "matrix can only be symmetric if square, but n != m" msgstr "" msgid "" "for symmetric band matrix, only specify upper or lower triangle\n" " hence, all k must have the same sign" msgstr "" "대칭 띠 행렬(symmetric band matrix)의 경우, 오로지 상삼각(upper triangle) 또" "는 하삼각(lower)만을 지정합니다. \n" " 따라서, 모든 k는 반드시 같은 부호(sign)를 가져야 합니다." msgid "the %d-th (sub)-diagonal (k = %d) is too short; filling with NA's" msgstr "%d-번째 (부분)-대각 (k = %d)이 너무 짧아 NA로 채웁니다." msgid "invalid 'repr'; must be \"C\", \"T\", or \"R\"" msgstr "" msgid "'x' must inherit from \"sparseVector\"" msgstr "'x'는 \"sparseVector\"로부터의 상속(inherit)이어야 합니다." msgid "'ncol' must be >= 0" msgstr "'ncol'은 반드시 >= 0 이어야 합니다. " msgid "'nrow' must be >= 0" msgstr "'nrow'는 반드시 >= 0 이어야 합니다." msgid "Must specify 'nrow' when 'symmetric' is true" msgstr "'symmetric'이 참인 경우에는 반드시 'nrow'를 지정해 주어야 합니다." msgid "'nrow' and 'ncol' must be the same when 'symmetric' is true" msgstr "" "'symmetric'이 참인 경우에는 반드시 'nrow'와 'ncol'을 지정해 주어야 합니다." msgid "'x' must have length nrow^2 when 'symmetric' is true" msgstr "" "'symmetric'이 참인 경우에는 'x'의 길이는 반드시 nrow^2와 같아야 합니다." msgid "'ncol' is not a factor of length(x)" msgstr "'ncol'는 길이가 length(x)인 요인(factor)가 아닙니다." msgid "'nrow' is not a factor of length(x)" msgstr "'nrow'는 길이가 length(x)인 요인(factor)가 아닙니다." msgid "Class %s is not yet implemented" msgstr "클래스 %s는 아직 구현되지 않았습니다." #, fuzzy msgid "'%s' and '%s' must be positive integers" msgstr "길이(length)는 반드시 음이 아닌 수이어야 합니다." #, fuzzy msgid "matrix is not symmetric or triangular" msgstr "'x'는 대칭(symmetric)도 아니고 삼각(triangular)도 아닙니다." #, fuzzy msgid "matrix is not symmetric" msgstr "삼각행렬이 아닙니다." #, fuzzy msgid "matrix is not triangular" msgstr "'x'는 대칭(symmetric)도 아니고 삼각(triangular)도 아닙니다." msgid "" "the default value of argument '%s' of method '%s(<%s>, <%s>)' may change " "from %s to %s as soon as the next release of Matrix; set '%s' when " "programming" msgstr "" msgid "determinant of non-square matrix is undefined" msgstr "" msgid "replacement diagonal has wrong length" msgstr "" msgid "replacement diagonal has incompatible type \"%s\"" msgstr "" msgid "assigned dimensions are not of type \"%s\" or \"%s\"" msgstr "" msgid "assigned dimensions do not have length %d" msgstr "" msgid "assigned dimensions are NA" msgstr "" msgid "assigned dimensions are negative" msgstr "" msgid "assigned dimensions exceed %s" msgstr "" #, fuzzy msgid "assigned dimensions [product %.0f] do not match object length [%.0f]" msgstr "dim [product %d]의 값이 객체 [%d]의 길이와 일치하지 않습니다." msgid "'lwd' must be NULL or non-negative numeric" msgstr "'lwd'는 반드시 NULL 또는 음이 아닌 수 이어야 합니다." #, fuzzy msgid "%s(<%s>) is not yet implemented" msgstr "클래스 %s는 아직 구현되지 않았습니다." msgid "'%s' is not of type \"%s\" or \"%s\"" msgstr "" msgid "'%s' contains NA" msgstr "" msgid "'%s' has elements less than %d" msgstr "" #, fuzzy msgid "'%s' is not a non-negative number" msgstr "길이(length)는 반드시 음이 아닌 수이어야 합니다." msgid "'%s' has elements exceeding '%s'" msgstr "" msgid "'%s' is not %d or %d" msgstr "" #, fuzzy msgid "'%s' is not a permutation of seq_len(%s)" msgstr "'ncol'는 길이가 length(x)인 요인(factor)가 아닙니다." #, fuzzy msgid "matrix must have exactly one entry in each row or column" msgstr "각 행마다 반드시 정확히 하나의 영이 아닌 항목을 가지고 있어야 합니다." #, fuzzy msgid "attempt to coerce non-square matrix to %s" msgstr "" "비대칭(non-symmetric) \"dgTMatrix\"는 \"dsCMatrix\" 클래스로 강제변환" "(coerce) 할 수 없습니다. " #, fuzzy msgid "matrix must have exactly one entry in each row and column" msgstr "각 행마다 반드시 정확히 하나의 영이 아닌 항목을 가지고 있어야 합니다." #, fuzzy msgid "'%s' via sparse -> dense coercion" msgstr "rcond(.) via sparse -> dense coercion" #, fuzzy msgid "invalid %s=\"%s\"" msgstr "nargs()= %d의 값이 올바르지 않습니다." msgid "norm" msgstr "" #, fuzzy msgid "'%s' method must use default %s=\"%s\"" msgstr "" "크로넥커 메소드(kronecker method)는 반드시 기본 'FUN'을 사용해야 합니다." #, fuzzy msgid "number of nonzero entries cannot exceed %s" msgstr "%s의 경우 행의 개수가 올바르지 않습니다." msgid "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", or \"%4$s\"" msgstr "" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%2$s2\", \"%2$s2.\", \"%3$s\", or " "\"%4$s\"" msgstr "" msgid "non-conformable arguments" msgstr "non-conformable arguments" #, fuzzy msgid "model frame and formula mismatch in sparse.model.matrix()" msgstr "" "model.matrix()를 사용할 때 모델프레임(model frame)과 모델식(formula)가 일치하" "지 않습니다." #, fuzzy msgid "non-list contrasts argument ignored" msgstr "'contrasts.arg' 인자가 올바르지 않습니다." #, fuzzy msgid "'contrasts.arg' argument must be named" msgstr "'contrasts.arg' 인자가 올바르지 않습니다." msgid "variable '%s' is absent, its contrast will be ignored" msgstr "변수 '%s'를 찾을 수 없어 관련 대비(contrast)는 계산되지 않을 것입니다." msgid "Matrix seems negative semi-definite" msgstr "음의 반정치(negative semi-definite) 행렬 같습니다." msgid "'nearPD()' did not converge in %d iterations" msgstr "'nearPD()'는 %d 번째 반복에서도 수렴하지 않았습니다." #, fuzzy msgid "'cl' is not a character string" msgstr "'V'는 정방행렬(square matrix)이 아닙니다." msgid "" "not a positive definite matrix (and positive semidefiniteness is not checked)" msgstr "" #, fuzzy msgid "'%s' is not a square numeric matrix" msgstr "'V'는 정방행렬(square matrix)이 아닙니다." #, fuzzy msgid "" "diag(%s) has non-positive or non-finite entries; finite result is doubtful" msgstr "" "diag(.)에 0 또는 NA가 존재하므로 유한하지 않은 결과(non-finite result)를 얻" "을 것으로 생각됩니다." msgid "" "matrix is structurally rank deficient; using augmented matrix with " "additional %d row(s) of zeros" msgstr "" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%2$s2\", \"%2$s2.\", \"%3$s\", " "\"%3$s1\", \"%4$s\", or \"%4$s1\"" msgstr "" #, fuzzy msgid "'%s' has the wrong length" msgstr "우변의 'b'가 올바르지 않은 길이(length)를 가지고 있습니다." #, fuzzy msgid "invalid '%s': not in %d:%d" msgstr "%s은 올바른 'col.names' 문자열이 아닙니다" msgid "need greater '%s' as pivoting occurred" msgstr "" msgid "qr2rankMatrix(.): QR with only %d out of %d finite diag(R) entries" msgstr "" msgid "" "rankMatrix(, method = '%s') coerces to dense matrix.\n" " Probably should rather use method = 'qr' !?" msgstr "" msgid "rankMatrix(x, method='qr'): computing t(x) as nrow(x) < ncol(x)" msgstr "rankMatrix(x, method='qr'): nrow(x) < ncol(x)이므로 t(x)를 계산합니다." #, fuzzy msgid "[[ suppressing %d column name%s %s ... ]]" msgstr "[[ %d개의 열이름 %s ...를 제거합니다 ]]" msgid "invalid 'col.names' string: %s" msgstr "%s은 올바른 'col.names' 문자열이 아닙니다" msgid "uniDiag=TRUE, but not all diagonal entries are 1" msgstr "" msgid "uniDiag=TRUE, not all entries in diagonal coded as 1" msgstr "" msgid "in show(); maybe adjust options(max.print=, width=)" msgstr "" #, fuzzy msgid "suppressing %d columns and %d rows" msgstr "[[ %d개의 열이름 %s를 제거합니다 ]]" #, fuzzy msgid "suppressing %d rows" msgstr "[[ %d개의 열이름 %s를 제거합니다 ]]" #, fuzzy msgid "suppressing %d columns" msgstr "[[ %d개의 열이름 %s를 제거합니다 ]]" msgid "logic programming error in printSpMatrix2(), please report" msgstr "" "printSpMatrix2()를 이용 도중 논리적 프로그래밍 에러(logic programming error)" "가 발생했습니다. 이를 꼭 보고를 부탁드립니다." #, fuzzy msgid "'%s' is not square" msgstr "'V'는 정방행렬(square matrix)이 아닙니다." msgid "dimensions of '%s' and '%s' are inconsistent" msgstr "" msgid "'%1$s' is computationally singular, rcond(%1$s)=%2$g" msgstr "" msgid "'%s' is computationally singular, min(d)/max(d)=%g, d=abs(diag(U))" msgstr "" msgid "matrix is exactly singular, D[i,i]=0, i=%d" msgstr "" msgid "matrix is exactly singular, J[,j]=0, j=%d" msgstr "" msgid "matrix exactly singular, J[i,]=0, i=%d" msgstr "" msgid "cannot coerce from %s to %s" msgstr "" msgid "a sparseMatrix should rarely be centered: will not be sparse anymore" msgstr "" #, fuzzy msgid "length of 'center' must equal the number of columns of 'x'" msgstr "%s에 사용된 각 행렬이 가지는 열의 개수는 서로 같아야 합니다." #, fuzzy msgid "length of 'scale' must equal the number of columns of 'x'" msgstr "%s에 사용된 각 행렬이 가지는 열의 개수는 서로 같아야 합니다." #, fuzzy msgid "invalid subassignment value class \"%s\"" msgstr "%s는 사용가능한 클래스(class)가 아닙니다." #, fuzzy msgid "invalid subassignment value type \"%s\"" msgstr "%s는 사용할 수 없는 저장형식(storage format)입니다." msgid "missing subassignment value" msgstr "" #, fuzzy msgid "incorrect number of dimensions" msgstr "차원(dimensions) 정보가 일치하지 않습니다." msgid "replacement has length zero" msgstr "" msgid "number of items to replace is not a multiple of replacement length" msgstr "" "교체(replace)할 항목의 개수가 입력된 value가 가지는 길이의 배수가 아닙니다." msgid "" ".M.repl.i.2col(): 'i' has no integer column number;\n" " should never happen; please report" msgstr "" ".M.repl.i.2col(): 'i'는 정수형 행번호(integer column number)을 가지고 있지 않" "습니다.\n" " 이런 경우는 존재할 수 없으므로 패키지 관리자에게 보고해 주시길 부탁드립니다." msgid "such indexing must be by logical or 2-column numeric matrix" msgstr "" "이와 같은 유형의 인덱싱(indexing)은 반드시 논리형(logical) 또는 2개의 열로 구" "성된 수치형(numeric) 행렬에 의해서만 이루어져야 합니다." msgid ".M.repl.i.2col(): drop 'matrix' case ..." msgstr ".M.repl.i.2col(): drop 'matrix' case ..." msgid "negative values are not allowed in a matrix subscript" msgstr "음수(negative values)는 행렬의 첨자(subscript)로 사용할 수 없습니다." msgid "NAs are not allowed in subscripted assignments" msgstr "NA는 행렬의 첨자(subscripted assignment)로 사용할 수 없습니다." msgid "m[ ] <- v: inefficiently treating single elements" msgstr "m[ ] <- v: inefficiently treating single elements" msgid "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' ?" msgstr "nargs() = %d. 필요이상의 인자들이 '[ .. ]' 내에 이용되었나요?" msgid "RHS 'value' (class %s) matches 'ANY', but must match matrix class %s" msgstr "" "클래스 %s를 가지는 우변의 'value'는 'ANY'에 매치되지만, 반드시 행렬의 클래스 " "%s에 매치되어야 합니다." msgid "not-yet-implemented 'Matrix[<-' method" msgstr "아직 구현되지 않은 'Matrix[<-' 메소드입(method)니다." msgid "invalid nargs()= %d" msgstr "nargs()= %d의 값이 올바르지 않습니다." msgid "nothing to replace with" msgstr "교체(replace)해야 할 것이 아무것도 없습니다." msgid "too many replacement values" msgstr "교체에 이용될 값이 너무 많이 입력되었습니다." msgid "i1[1] == 0 ==> C-level verbosity will not happen!" msgstr "i1[1] == 0 ==> C-레벨에서의 진행과정표시는 나타나지 않을 것입니다!" msgid "using\t \"old code\" part in Csparse subassignment" msgstr "using\t \"old code\" part in Csparse subassignment" msgid "" "using\"old code\" part in Csparse subassignment\n" " >>> please report to Matrix-authors@r-project.org" msgstr "" "using\"old code\" part in Csparse subassignment\n" " >>> Matrix-authors@r-project.org으로 이를 보고해 주시길 바랍니다." msgid "you cannot mix negative and positive indices" msgstr "인덱스에 음수와 양수를 혼용하여 사용할 수 없습니다." msgid "index larger than maximal %d" msgstr "인덱스가 %d 보다 큽니다." msgid "'NA' indices are not (yet?) supported for sparse Matrices" msgstr "'NA'는 sparse Matrices에 (아직은?) 사용할 수 없는 인덱스입니다" msgid "logical subscript too long (%d, should be %d)" msgstr "" "길이가 너무 긴 논리형 첨자(subscript)입니다 (%2$d이어야 하는데 %1$d입니다)." msgid "no 'dimnames[[.]]': cannot use character indexing" msgstr "no 'dimnames[[.]]': 문자형 인덱싱을 사용할 수 없습니다" msgid "invalid character indexing" msgstr "유효하지 않은 문자형 인덱싱입니다" msgid "internal bug: missing 'i' in replTmat(): please report" msgstr "" "내부버그 발견: replTmat()내에서 'i'를 찾을 수 없습니다. 이를 보고해 주시길 부" "탁드립니다." msgid "[ ] indexing not allowed: forgot a \",\" ?" msgstr "" "[ ]와 같은 인덱싱은 사용할 수 없습니다. \",\"의 사용을 잊었나요?" msgid "internal bug: matrix 'i' in replTmat(): please report" msgstr "" "내부버그 발견: replTmat()내에서 'i'는 행렬입니다. 이를 보고해 주시길 부탁드립" "니다." msgid "" "x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced; NA |--> TRUE." msgstr "" "x[.] <- val: x의 클래스는 %s입니다. {TRUE, FALSE}에 해당하지 않는 val의 값" "은 TRUE로 강제변환(coerced) 되었습니다." msgid "x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced." msgstr "" "x[.] <- val: x의 클래스는 %s입니다. {TRUE, FALSE}에 해당하지 않는 val의 값" "은 강제변환(coerced) 되었습니다." msgid "" "x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE." msgstr "" "x[.,.] <- val: x의 클래스는 %s입니다. {TRUE, FALSE}에 해당하지 않는 val의 값" "은 TRUE로 강제변환(coerced) 되었습니다. " msgid "x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced." msgstr "" "x[.,.] <- val: x의 클래스는 %s입니다. {TRUE, FALSE}에 해당하지 않는 val의 값" "은 강제변환(coerced) 되었습니다. " msgid "x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrix" msgstr "" "x[.,.] <- val : Tsparse* 에서 CsparseMatrix로 강제변환(coerced)된 x입니다." msgid "nargs() = %d should never happen; please report." msgstr "" "nargs() = %d 와 같은 경우는 발생할 수 없으므로 꼭 보고해 주시기를 부탁드립니" "다." msgid "row indices must be <= nrow(.) which is %d" msgstr "행에 사용되는 인덱스는 반드시 %d 보다 같거나 작아야 합니다." msgid "column indices must be <= ncol(.) which is %d" msgstr "열에 사용되는 인덱스는 %d 보다 같거나 작아야 합니다. " msgid "Internal bug: nargs()=%d; please report" msgstr "내부버그 발견: nargs()=%d. 꼭 보고를 부탁드립니다." msgid "" "index must be numeric, logical or sparseVector for indexing sparseVectors" msgstr "" "sparseVectors를 인덱싱하기 위해서는 인덱스는 반드시 수치형, 논리형 또는 " "sparseVectors이어야 합니다." #, fuzzy msgid "invalid subscript class \"%s\"" msgstr "%s는 사용가능한 클래스(class)가 아닙니다." #, fuzzy msgid "invalid subscript type \"%s\"" msgstr "%s는 사용할 수 없는 저장형식(storage format)입니다." msgid "recycled %s would have maximal index exceeding %s" msgstr "" msgid "subscripts exceeding %s replaced with NA" msgstr "" msgid "subscript out of bounds" msgstr "" #, fuzzy msgid "logical subscript too long" msgstr "" "길이가 너무 긴 논리형 첨자(subscript)입니다 (%2$d이어야 하는데 %1$d입니다)." msgid "only zeros may be mixed with negative subscripts" msgstr "" msgid "trimmed means are not defined for complex data" msgstr "" msgid "first element used of '%s' argument" msgstr "" #, fuzzy msgid "invalid '%s' argument" msgstr "입력된 'data'는 올바르지 않습니다." msgid "should never happen ..." msgstr "" msgid "'%s' is deprecated; using '%s' instead" msgstr "" msgid "'%s' is deprecated; setting %s=\"%s\"" msgstr "" msgid "'%s' has length 0 but '%s' does not" msgstr "" #, fuzzy msgid "attempt to coerce matrix with NA to %s" msgstr "" "비대칭(non-symmetric) \"dgTMatrix\"는 \"dsCMatrix\" 클래스로 강제변환" "(coerce) 할 수 없습니다. " #, fuzzy msgid "invalid 'Class2'" msgstr "입력된 'data'는 올바르지 않습니다." #, fuzzy #~ msgid "invalid 'each' argument" #~ msgstr "'by' 인자에 사용된 부호(sign)가 올바르지 않습니다." #, fuzzy #~ msgid "invalid 'times' argument" #~ msgstr "입력된 'data'는 올바르지 않습니다." #~ msgid "" #~ "not-yet-implemented method for %s(<%s>).\n" #~ " ->> Ask the package authors to implement the missing feature." #~ msgstr "" #~ "%s(<%s>)의 경우에 대하여 아직 구현되지 않은 메소드(method)입니다.\n" #~ " ->> 이 기능에 대한 구현을 패키지 관리자에게 문의해 주셨으면 합니다." #~ msgid "" #~ "not-yet-implemented method for %s(<%s>, <%s>).\n" #~ " ->> Ask the package authors to implement the missing feature." #~ msgstr "" #~ "%s(<%s>, <%s>)의 경우에 대하여 아직 구현되지 않은 메소드(method)입니다.\n" #~ " ->> 이 기능에 대한 구현을 패키지 관리자에게 문의해 주시길 바랍니다." #, fuzzy #~ msgid "complex \"diagonalMatrix\" not yet implemented" #~ msgstr "%s의 경우에는 아직 구현되지 않은 일반적인 Matrix 클래스입니다." #, fuzzy #~ msgid "not yet implemented for class \"%s\"" #~ msgstr "클래스 %s의 경우에 아직 구현되지 않았습니다." #, fuzzy #~ msgid "invalid 'uplo'" #~ msgstr "올바르지 않은 'type'입니다." #~ msgid "'lag' and 'differences' must be integers >= 1" #~ msgstr "'lag'과 'differences'는 반드시 1보다 크거나 같은 정수이어야 합니다." #~ msgid "" #~ "programming error: min() should have dispatched w/ 1st arg much earlier" #~ msgstr "" #~ "programming error: min() should have dispatched w/ 1st arg much earlier" #~ msgid "in Summary(, .): %s(<%s>, <%s>,...)" #~ msgstr "in Summary(, .): %s(<%s>, <%s>,...)" #~ msgid "in Summary(, .): %s(<%s>, <%s>)" #~ msgstr "in Summary(, .): %s(<%s>, <%s>)" #, fuzzy #~ msgid "number of rows of matrices must match" #~ msgstr "%s의 경우 행의 개수가 올바르지 않습니다." #, fuzzy #~ msgid "number of columns of matrices must match" #~ msgstr "%s의 경우 행의 개수가 올바르지 않습니다." #, fuzzy #~ msgid "dimensions must be numeric of length 2" #~ msgstr "dim(.)의 값은 반드시 길이가 2인 수치형 벡터이어야 합니다." #, fuzzy #~ msgid "'perm' must be numeric" #~ msgstr "'A'는 반드시 정방행렬(square matrix)이어야 합니다." #, fuzzy #~ msgid "'margin' must be 1 or 2" #~ msgstr "'ncol'은 반드시 >= 0 이어야 합니다. " #~ msgid "not-yet-implemented method for <%s> %%*%% <%s>" #~ msgstr "<%s> %%*%% <%s>에 사용할 수 있는 메소드가 아직 구현되지 않았습니다." #, fuzzy #~ msgid "'boolArith = %d' not yet implemented" #~ msgstr "아직 구현되지 않은 종류 %s입니다." #, fuzzy #~ msgid "'rcond' via sparse -> dense coercion" #~ msgstr "rcond(.) via sparse -> dense coercion" #, fuzzy #~ msgid "invalid 'norm'" #~ msgstr "입력된 'data'는 올바르지 않습니다." #, fuzzy #~ msgid "cannot coerce zsparseVector to dgCMatrix" #~ msgstr "'NA'를 \"nsparseMatrix\"으로 강제변환(coerce)할 수 없습니다." #, fuzzy #~ msgid "cannot coerce zsparseVector to dgeMatrix" #~ msgstr "'NA'를 \"nsparseVector\"로 강제변환(coerce) 할 수 없습니다." #~ msgid "" #~ "number of non zeros is smaller than 'nnz' because of duplicated (i,j)s" #~ msgstr "" #~ "중복된 (i,j)에 위치한 값들 때문에 영이 아닌 요소의 개수가 'nnz' 보다 작습" #~ "니다." #~ msgid "'times >= 0' is required" #~ msgstr "'times >= 0'이 요구되어집니다." #~ msgid "Matrices must have same number of rows in %s" #~ msgstr "%s에 사용된 각 행렬이 가지는 행의 개수는 서로 같아야 합니다." #~ msgid "Matrices must have same number of columns in %s" #~ msgstr "%s에 사용된 각 행렬이 가지는 열의 개수는 서로 같아야 합니다." #, fuzzy #~ msgid "only lists of length 2 can be coerced to indMatrix" #~ msgstr "" #~ "NA를 가진 \"lMatrix\" 객체는 \"nMatrix\"로 강제변환(coerced) 될 수 없습니" #~ "다." #, fuzzy #~ msgid "only 2-dimensional tables can be coerced to sparseMatrix" #~ msgstr "" #~ "오로지 2차원 테이블만이 희소행렬(sparse matrice)로 강제변환(coerced)될 수 " #~ "있습니다." #, fuzzy #~ msgid "matrix is not symmetric or" #~ msgstr "'x'는 대칭(symmetric)도 아니고 삼각(triangular)도 아닙니다." #, fuzzy #~ msgid "triangular" #~ msgstr "삼각행렬(triangular matrix)가 아닙니다." #, fuzzy #~ msgid "matrix is not" #~ msgstr "대각행렬이 아닙니다." #~ msgid "'x' is not positive definite -- chol() undefined." #~ msgstr "" #~ "'x'는 양정치(positive definite) 행렬이 아니므로 chol()가 정의되어지지 않습" #~ "니다." #~ msgid "Matrices must have same dimensions in %s" #~ msgstr "" #~ "%s에 입력된 행렬들은 반드시 같은 차원(dimensions)을 가지고 있어야 합니다." #~ msgid "names(dimnames()) must be NULL or of length two" #~ msgstr "names(dimnames())의 길이는 2이거나 NULL이어야 합니다." #~ msgid "[[ suppressing %d column names %s ]]" #~ msgstr "[[ %d개의 열이름 %s를 제거합니다 ]]" #~ msgid "'x' must be \"sparseMatrix\"" #~ msgstr "'x'는 반드시 \"sparseMatrix\"이어야 합니다." #~ msgid "not yet implemented for matrix with typeof %s" #~ msgstr "" #~ "저장방식(typeof) %s를 가지는 행렬의 경우에는 아직 구현되지 않았습니다." #~ msgid "not yet implemented for %s" #~ msgstr "%s의 경우에는 아직 구현되지 않았습니다." #~ msgid "" #~ "Quadratic matrix '%s' (=: A) is not formally\n" #~ "\tsymmetric. Will be treated as\tA A'" #~ msgstr "" #~ "이차행렬(quadratic matrix) '%s' (=: A)는 형식적으로\n" #~ "\t대칭(symmetric)이 아닙니다. \tA A'와 같이 다루겠나요?" #~ msgid "" #~ "'update' must be logical or '+' or '-'; 'C' a matrix, and 'L' a " #~ "\"CHMfactor\"" #~ msgstr "" #~ "'update'는 반드시 논리형(logical) 또는 '+' 또는 '-'이어야 하며, 'C'는 행렬" #~ "이어야 하고 'L'은 \"CHMfactor\"이어야 합니다." #~ msgid "update must be TRUE/FALSE or '+' or '-'" #~ msgstr "update는 반드시 TRUE/FALSE 또는 '+' 또는 '-'이어야 합니다." #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "" #~ "[i,,d]에서 Matrix-내부오류(internal error)가 발생한 경우입니다. " #~ "이를 보고해 주시길 부탁드립니다." #~ msgid "" #~ "Cholesky() -> *symbolic* factorization -- not yet implemented" #~ msgstr "" #~ "Cholesky() -> *symbolic* factorization -- 아직 구현되지 않았습" #~ "니다." #~ msgid "trimmed mean of 'sparseVector' -- suboptimally using as.numeric(.)" #~ msgstr "trimmed mean of 'sparseVector' -- suboptimally using as.numeric(.)" #~ msgid "invalid dimnames given for %s object" #~ msgstr "객체 %s에 주어진 dimnames가 올바르지 않습니다." #~ msgid "" #~ "dimnames(.) <- NULL: translated to \n" #~ "dimnames(.) <- list(NULL,NULL) <==> unname(.)" #~ msgstr "" #~ "dimnames(.) <- NULL:은 다음과 같이 변경되었습니다. \n" #~ "dimnames(.) <- list(NULL,NULL) <==> unname(.)" #~ msgid "" #~ "'nrow', 'ncol', etc, are disregarded when 'data' is \"Matrix\" already" #~ msgstr "" #~ "'data'가 이미 \"Matrix\"인 경우에는 입력된 'nrow', 'ncol' 등은 사용되지 않" #~ "습니다." #~ msgid "complex matrices not yet implemented in Matrix package" #~ msgstr "" #~ "복소수형(complex) 행렬을 다루는 경우는 아직 Matrix 패키지내에서는 아직 구" #~ "현되지 않았습니다." #~ msgid "using slow kronecker() method" #~ msgstr "느린 크로넥커 방법(slow kronecker method)를 사용합니다." #~ msgid "" #~ "Cholesky(A) called for 'A' of class \"%s\";\n" #~ "\t it is currently defined for sparseMatrix only; consider using chol() " #~ "instead" #~ msgstr "" #~ "Cholesky(A)는 클래스 \"%s\"를 가지는 'A'를 호출합니다.\n" #~ "\t 이것은 현재 sparseMatrix 만을 위하여 정의되었으므로 chol()을 사용하시" #~ "길 바랍니다." #~ msgid "invalid or not-yet-implemented 'Matrix' subsetting" #~ msgstr "" #~ "올바르지 않거나 아직 구현되지 않은 'Matrix' 부분추출(subsetting)입니다." #~ msgid "[ ] : .M.sub.i.logical() maybe inefficient" #~ msgstr "" #~ "[ ] : .M.sub.i.logical()의 사용은 비효율적(inefficient) " #~ "일 수 있습니다." #~ msgid "" #~ "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' (i.logical)?" #~ msgstr "" #~ "nargs() = %d. 필요이상의 인자들이 '[ .. ]' (i.logical)에 이용되었나요?" #, fuzzy #~ msgid "" #~ "m[]: inefficiently indexing single elements - should not " #~ "happen, please report!" #~ msgstr "m[ ]: inefficiently indexing single elements" #~ msgid "" #~ "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' (i.2col)?" #~ msgstr "" #~ "nargs() = %d. 필요이상의 인자들이 '[ .. ]' (i.2col)에 이용되었나요?" #~ msgid "" #~ ".M.sub.i.2col(): 'i' has no integer column number;\n" #~ " should never happen; please report" #~ msgstr "" #~ ".M.sub.i.2col(): 'i'는 정수형 행번호(integer column number)를 가지고 있지 " #~ "않습니다.\n" #~ " 이런 경우는 존재할 수 없으므로 패키지 관리자에게 보고해 주시길 부탁드립니" #~ "다." #~ msgid "not-yet-implemented coercion to \"TsparseMatrix\"" #~ msgstr "" #~ "\"TsparseMatrix\"으로의 강제변환(coercion)은 아직 구현되지 않았습니다." #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "" #~ "[i,,d] 내에서 행렬과 관련한 내부에러가 발생했습니다; 꼭 보고를 " #~ "부탁드립니다" #~ msgid "FIXME: NOT YET FINISHED IMPLEMENTATION" #~ msgstr "FIXME: 완전한 구현이 아직 이루어지지 않았습니다." #~ msgid "diagonalMatrix in .dense2C() -- should never happen, please report!" #~ msgstr "" #~ "diagonalMatrix in .dense2C() -- 발생해서는 안되는 경우이므로 꼭 보고를 부" #~ "탁드립니다!" #~ msgid "undefined method for class %s" #~ msgstr "클래스 %s에 정의된 메소드가 아닙니다." #~ msgid "dimensions don't match the number of cells" #~ msgstr "차원정보가 cell의 개수와 일치하지 않습니다" #~ msgid "" #~ "LU computationally singular: ratio of extreme entries in |diag(U)| = %9.4g" #~ msgstr "" #~ "LU computationally singular: ratio of extreme entries in |diag(U)| = %9.4g" #~ msgid "RHS 'b' has wrong number of rows:" #~ msgstr "우변의 'b'는 다음과 같은 올바르지 않은 행의 수를 가지고 있습니다: " #~ msgid "'x' has invalid data type" #~ msgstr "'x'의 데이터형(data type)은 사용가능하지 않습니다." #~ msgid "length(x) must be either 1 or #{cols}" #~ msgstr "length(x)는 반드시 1 또는 #{cols} 이어야 합니다. " #~ msgid "some arguments are not matrices" #~ msgstr "일부 인자가 행렬이 아닙니다." #~ msgid "%s kind not yet implemented" #~ msgstr "아직 구현되지 않은 종류 %s입니다." #~ msgid "non-square matrix" #~ msgstr "비정방(non-square) 행렬입니다." #~ msgid "" #~ "matrix with non-zero off-diagonals cannot be coerced to \"diagonalMatrix\"" #~ msgstr "" #~ "비대각원소의 값이 영이 아닌 행렬은 \"diagonalMatrix\"로 강제변환(coerced) " #~ "할 수 없습니다." #~ msgid "non-matching dimensions" #~ msgstr "차원(dimensions) 정보가 일치하지 않습니다." #~ msgid "not a positive definite matrix" #~ msgstr "양정치(positive definite) 행렬이 아닙니다." #~ msgid "" #~ "as(.,\"dsCMatrix\") is deprecated (since 2008); do use as(., " #~ "\"symmetricMatrix\")" #~ msgstr "" #~ "as(.,\"dsCMatrix\")은 2008년 이후로 지원되지 않으므로 as(., " #~ "\"symmetricMatrix\")를 이용해 주시길 바랍니다." #~ msgid "inefficient coercion (lost triangularity); please report" #~ msgstr "" #~ "비효율적인 강제변환입니다 (triangularity를 소실하였기 때문입니다). 꼭 보" #~ "고를 부탁드립니다." #~ msgid "coercion to \"indMatrix\" only works from integer numeric" #~ msgstr "" #~ "\"indMatrix\"로의 강제변환(coercion)은 오로지 정수를 가지는 숫자(integer " #~ "numeric)인 경우만 가능합니다." #~ msgid "" #~ "coercion from list(i1,...,ik, d) to \"indMatrix\" failed.\n" #~ " All entries must be integer valued and the number of columns, d, not " #~ "smaller\n" #~ " than the maximal index i*." #~ msgstr "" #~ "list(i1,...,ik, d)으로부터 \"indMatrix\"로의 강제변환(coercion)은 이루어지" #~ "지 않았습니다.\n" #~ " 모든 원소들은 반드시 정수이어야 하며 행의 개수 d는 인덱스 i* 중 \n" #~ " 가장 큰 수보다 보다 작지 않아야 합니다." #~ msgid "the number of non-zero entries differs from nrow(.)" #~ msgstr "영이 아닌 항목들의 개수가 nrow(.)와 다릅니다." #~ msgid "replacing \"indMatrix\" entries is not allowed, as rarely sensible" #~ msgstr "" #~ "\"indMatrix\" 요소를 변경하는 것은 허용되지 않습니다, as rarely sensible" #~ msgid "temporarily disabled" #~ msgstr "일시적으로 사용할 수 없습니다." #, fuzzy #~ msgid "cannot coerce NA values to pattern \"ntCMatrix\"" #~ msgstr "'NA'를 \"nsparseMatrix\"으로 강제변환(coerce)할 수 없습니다." #~ msgid "coercion to \"pMatrix\" only works from integer numeric" #~ msgstr "" #~ "\"pMatrix\"로의 강제변환(coercion)은 오로지 정수값을 가진 숫자(integer " #~ "numeric)인 경우로부터만 가능합니다." #~ msgid "not a square matrix" #~ msgstr "정방행렬(square matrix)이 아닙니다." #~ msgid "NA's in (i,j) are not allowed" #~ msgstr "(i,j) 위치에 NA는 사용될 수 없습니다." #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "" #~ "[i,,d]를 사용중 행렬-내부 오류(matrix-internal error)가 발생했습" #~ "니다. 이를 꼭 보고 부탁드립니다." #~ msgid "" #~ "qr.R() may differ from qr.R() because of permutations. " #~ "Possibly use our qrR() instead" #~ msgstr "" #~ "qr.R()은 아마도 순열(permutations) 때문에 qr.R()와 다를 수 " #~ "있습니다. 따라서, qrR()을 사용하시길 바랍니다." #~ msgid "(un)packing only applies to dense matrices, class(x)='%s'" #~ msgstr "(un)packing only applies to dense matrices, class(x)='%s'" #, fuzzy #~ msgid "'x' is not symmetric -- chol() undefined." #~ msgstr "" #~ "'x'는 양정치(positive definite) 행렬이 아니므로 chol()가 정의되어지지 않습" #~ "니다." #~ msgid "" #~ "extra argument %s will be disregarded in\n" #~ " %s" #~ msgid_plural "" #~ "extra arguments %s will be disregarded in\n" #~ " %s" #~ msgstr[0] "추가 인자들(extra arguments) %s는 %s에서 사용되지 않을 것입니다." #~ msgid " %s %s is undefined" #~ msgstr " %1$s %2$s는 정의되지 않았습니다." #~ msgid "%s %s is undefined" #~ msgstr "%s %s 은 정의되지 않았습니다." #~ msgid "variable '%s' converted to a factor" #~ msgstr "변수 '%s'가 요인(factor)로 변환되었습니다." #~ msgid "\"dMatrix\" object with NAs cannot be coerced to \"nMatrix\"" #~ msgstr "" #~ "NA를 가진 \"dMatrix\" 객체는 \"nMatrix\"로 강제변환(coerced) 할 수 없습니" #~ "다." #~ msgid "not a skinny matrix" #~ msgstr "not a skinny matrix" Matrix/po/pl.po0000644000175100001440000025653614575137654013167 0ustar hornikusersmsgid "" msgstr "" "Project-Id-Version: Matrix 1.1-2-2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-14 15:49-0400\n" "PO-Revision-Date: 2014-03-24 17:53+0100\n" "Last-Translator: Łukasz Daniel \n" "Language-Team: Łukasz Daniel \n" "Language: pl_PL\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" "X-Poedit-SourceCharset: iso-8859-1\n" "X-Generator: Poedit 1.5.4\n" # Matrix/src/dgCMatrix.c: 160 # error(_("cs_lusol failed")) #: Csparse.c:26 Csparse.c:61 Csparse.c:86 Csparse.c:113 Csparse.c:127 #: Csparse.c:132 Csparse.c:137 Csparse.c:411 #, fuzzy, c-format msgid "'%s' failed" msgstr "funkcja 'cs_qr' nie powiodła się " # Matrix/src/Csparse.c: 97 # (_("slot j is not increasing inside a column")) #: Csparse.c:35 cholmod-common.c:54 #, fuzzy, c-format msgid "'%s' slot is not increasing within columns after sorting" msgstr "gniazdo 'j' nie jest rosnące wewnątrz kolumny" # Matrix/src/dsyMatrix.c: 9 # (_("Matrix is not square")) # Matrix/src/dtrMatrix.c: 13 # (_("Matrix is not square")) #: Csparse.c:57 #, fuzzy, c-format msgid "'%s' is empty or not square" msgstr "Macierz nie jest kwadratowa" # Matrix/src/dppMatrix.c: 81 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dpoMatrix.c: 92 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dpoMatrix.c: 117 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dsyMatrix.c: 85 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dtCMatrix.c: 90 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dtCMatrix.c: 106 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dgCMatrix.c: 158 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dgCMatrix.c: 184 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dgCMatrix.c: 438 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dgCMatrix.c: 471 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dtrMatrix.c: 99 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dgeMatrix.c: 423 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dspMatrix.c: 79 # error(_("Dimensions of system to be solved are inconsistent")) #: Csparse.c:59 Csparse.c:81 Csparse.c:104 solve.c:43 solve.c:988 #, fuzzy, c-format msgid "dimensions of '%s' and '%s' are inconsistent" msgstr "Wymiary systemu, który ma być rozwiązany, są niespójne" #: Csparse.c:83 #, c-format msgid "%s(%s, %s) requires m-by-n '%s' with m >= n > 0" msgstr "" #: Csparse.c:106 #, c-format msgid "%s(%s, %s) requires m-by-n '%s' with n >= m > 0" msgstr "" # Matrix/src/Mutils.c: 990 # error(_("invalid '%s' argument"), "byrow") #: Csparse.c:194 coerce.c:220 coerce.c:240 coerce.c:250 coerce.c:905 #: coerce.c:911 coerce.c:1015 coerce.c:1501 coerce.c:1521 coerce.c:1531 #: coerce.c:2061 coerce.c:2256 coerce.c:2262 coerce.c:2268 coerce.c:2397 #: coerce.c:2404 coerce.c:2494 coerce.c:2629 coerce.c:2707 coerce.c:2729 #: coerce.c:4327 coerce.c:4396 dense.c:696 matmult.c:939 matmult.c:1291 #: solve.c:719 solve.c:972 solve.c:1104 sparse.c:1234 sparse.c:1626 #, fuzzy, c-format msgid "invalid '%s' to '%s'" msgstr "niepoprawny argument '%s'" # Matrix/src/Csparse.c: 612 # error(_("failure to open file \"%s\" for writing"), # CHAR(asChar(fname))) #: Csparse.c:409 #, fuzzy, c-format msgid "failed to open file \"%s\" for writing" msgstr "nie udało się otworzyć pliku '%s' do zapisu" # Matrix/src/Mutils.c: 990 # error(_("invalid '%s' argument"), "byrow") #: attrib.c:229 #, fuzzy msgid "invalid factor name" msgstr "niepoprawny argument '%s'" #: attrib.c:233 #, c-format msgid "attempt to set factor on %s without '%s' slot" msgstr "" #: bind.c:46 bind.c:153 msgid "number of rows of matrices must match" msgstr "" #: bind.c:48 bind.c:155 msgid "number of columns of matrices must match" msgstr "" #: bind.c:51 bind.c:158 bind.c:182 bind.c:206 cholmod-common.c:608 #: cholmod-common.c:759 cholmod-common.c:874 cholmod-common.c:975 #: cholmod-etc.c:183 cholmod-etc.c:283 cholmod-etc.c:330 coerce.c:215 #: coerce.c:235 coerce.c:260 coerce.c:268 coerce.c:276 coerce.c:341 #: coerce.c:1496 coerce.c:1516 coerce.c:1543 coerce.c:1551 coerce.c:1559 #: matmult.c:28 matmult.c:50 matmult.c:56 #, c-format msgid "dimensions cannot exceed %s" msgstr "" #: bind.c:210 msgid "number of rows of result is not a multiple of vector length" msgstr "" #: bind.c:212 msgid "number of columns of result is not a multiple of vector length" msgstr "" #: bind.c:626 bind.c:691 sparse.c:913 sparse.c:994 #, c-format msgid "%s cannot exceed %s" msgstr "" #: bind.c:756 bind.c:853 cholmod-common.c:978 cholmod-etc.c:333 coerce.c:29 #: coerce.c:518 coerce.c:811 coerce.c:945 coerce.c:2772 coerce.c:3041 #: coerce.c:3146 dense.c:919 matmult.c:151 matmult.c:212 matmult.c:291 #: matmult.c:379 matmult.c:456 matmult.c:550 matmult.c:868 subscript.c:1232 #: subscript.c:1417 utils-R.c:32 #, c-format msgid "attempt to allocate vector of length exceeding %s" msgstr "" #: bind.c:858 matmult.c:1357 msgid "should never happen ..." msgstr "" # Matrix/src/dgeMatrix.c: 19 # (_("'x' slot must be numeric \"double\"")) #: cholmod-common.c:11 cholmod-common.c:34 validity.c:29 validity.c:150 #: validity.c:229 validity.c:248 validity.c:257 validity.c:299 validity.c:316 #: validity.c:350 validity.c:367 validity.c:401 validity.c:403 validity.c:439 #: validity.c:465 validity.c:485 validity.c:926 validity.c:959 validity.c:1041 #: validity.c:1061 validity.c:1127 validity.c:1129 validity.c:1177 #: validity.c:1240 validity.c:1242 validity.c:1288 validity.c:1335 #: validity.c:1384 validity.c:1417 validity.c:1427 validity.c:1440 #: validity.c:1494 validity.c:1496 validity.c:1528 validity.c:1540 #: validity.c:1563 validity.c:1626 validity.c:1645 validity.c:1647 #: validity.c:1679 validity.c:1714 validity.c:1742 #, fuzzy, c-format msgid "'%s' slot is not of type \"%s\"" msgstr "gniazdo 'x' musi być liczbą typu \"double\"" # Matrix/src/dgeMatrix.c: 11 # (_("'Dim' slot must have length 2")) #: cholmod-common.c:14 validity.c:274 validity.c:285 validity.c:301 #: validity.c:352 validity.c:487 validity.c:928 validity.c:961 validity.c:1063 #: validity.c:1131 validity.c:1179 validity.c:1244 validity.c:1290 #: validity.c:1429 validity.c:1446 validity.c:1498 validity.c:1500 #: validity.c:1530 validity.c:1542 validity.c:1565 validity.c:1681 #: validity.c:1718 validity.c:1746 validity.c:1796 #, fuzzy, c-format msgid "'%s' slot does not have length %s" msgstr "gniazdo 'Dim' musi mieć długość 2" # Matrix/src/Csparse.c: 75 # (_("first element of slot p must be zero")) #: cholmod-common.c:18 validity.c:304 validity.c:355 validity.c:1634 #: validity.c:1654 validity.c:1656 #, fuzzy, c-format msgid "first element of '%s' slot is not 0" msgstr "pierwszy element gniazda 'p' musi być zerem" #: cholmod-common.c:23 cholmod-common.c:46 validity.c:34 validity.c:308 #: validity.c:326 validity.c:359 validity.c:377 validity.c:413 validity.c:415 #: validity.c:491 validity.c:1008 validity.c:1020 validity.c:1067 #: validity.c:1140 validity.c:1152 validity.c:1253 validity.c:1265 #: validity.c:1294 validity.c:1345 validity.c:1394 validity.c:1433 #: validity.c:1453 validity.c:1534 validity.c:1550 validity.c:1575 #: validity.c:1639 validity.c:1659 validity.c:1661 validity.c:1688 #, c-format msgid "'%s' slot contains NA" msgstr "" # Matrix/src/Csparse.c: 86 # (_("slot p must be non-decreasing")) #: cholmod-common.c:26 validity.c:310 validity.c:361 #, fuzzy, c-format msgid "'%s' slot is not nondecreasing" msgstr "gniazdo 'p' musi być niemalejące" #: cholmod-common.c:29 validity.c:312 validity.c:363 #, c-format msgid "first differences of '%s' slot exceed %s" msgstr "" # Matrix/src/dsyMatrix.c: 7 # (_("'dim' slot has length less than two")) # Matrix/src/dtrMatrix.c: 11 # (_("'dim' slot has length less than two")) #: cholmod-common.c:37 validity.c:318 validity.c:369 #, fuzzy, c-format msgid "'%s' slot has length less than %s" msgstr "gniazdo 'dim' ma długość mniejszą niż dwa" # Matrix/src/dsyMatrix.c: 7 # (_("'dim' slot has length less than two")) # Matrix/src/dtrMatrix.c: 11 # (_("'dim' slot has length less than two")) #: cholmod-common.c:49 validity.c:328 validity.c:379 validity.c:417 #: validity.c:420 validity.c:493 validity.c:1010 validity.c:1069 #: validity.c:1142 validity.c:1154 validity.c:1255 validity.c:1267 #: validity.c:1347 validity.c:1396 validity.c:1455 validity.c:1577 #: validity.c:1690 #, fuzzy, c-format msgid "'%s' slot has elements not in {%s}" msgstr "gniazdo 'dim' ma długość mniejszą niż dwa" # Matrix/src/dgCMatrix.c: 160 # error(_("cs_lusol failed")) #: cholmod-common.c:165 cholmod-common.c:296 cholmod-common.c:1072 #: cholmod-common.c:1075 cholmod-common.c:1108 cholmod-common.c:1126 #, fuzzy, c-format msgid "'%s' failed in '%s'" msgstr "funkcja 'cs_qr' nie powiodła się " # Matrix/src/dgCMatrix.c: 160 # error(_("cs_lusol failed")) #: cholmod-common.c:212 #, fuzzy, c-format msgid "'%s' failed in '%s': %s" msgstr "funkcja 'cs_qr' nie powiodła się " #: cholmod-common.c:601 cholmod-common.c:604 cholmod-common.c:606 #: cholmod-common.c:752 cholmod-common.c:755 cholmod-common.c:757 #: cholmod-common.c:867 cholmod-common.c:870 cholmod-common.c:872 #: cholmod-common.c:969 cholmod-common.c:971 cholmod-etc.c:177 #: cholmod-etc.c:179 cholmod-etc.c:181 cholmod-etc.c:277 cholmod-etc.c:279 #: cholmod-etc.c:281 cholmod-etc.c:324 cholmod-etc.c:326 cs-etc.c:43 #, c-format msgid "wrong '%s'" msgstr "" # Matrix/src/dgeMatrix.c: 19 # (_("'x' slot must be numeric \"double\"")) #: cholmod-common.c:611 cholmod-etc.c:186 #, fuzzy, c-format msgid "'%s' would overflow type \"%s\"" msgstr "gniazdo 'x' musi być liczbą typu \"double\"" #: cholmod-common.c:615 cholmod-etc.c:190 #, c-format msgid "n+1 would overflow type \"%s\"" msgstr "" # Matrix/src/dppMatrix.c: 34 # error(_("the leading minor of order %d is not positive definite"), # info) # Matrix/src/dpoMatrix.c: 40 # error(_("the leading minor of order %d is not positive definite"), # info) #: cholmod-common.c:620 cholmod-etc.c:195 #, fuzzy, c-format msgid "leading principal minor of order %d is not positive" msgstr "wiodący minor rzędu %d nie jest dodatnio określony" # Matrix/src/dppMatrix.c: 34 # error(_("the leading minor of order %d is not positive definite"), # info) # Matrix/src/dpoMatrix.c: 40 # error(_("the leading minor of order %d is not positive definite"), # info) #: cholmod-common.c:623 cholmod-etc.c:198 #, fuzzy, c-format msgid "leading principal minor of order %d is zero" msgstr "wiodący minor rzędu %d nie jest dodatnio określony" #: cholmod-common.c:973 cholmod-etc.c:328 msgid "leading dimension not equal to number of rows" msgstr "" #: cholmod-common.c:1037 #, c-format msgid "" "invalid simplicial Cholesky factorization: structural zero on main diagonal " "in column %d" msgstr "" # Matrix/src/chm_common.c: 698 # error(_("Cholmod error '%s' at file %s, line %d"), message, file, line) #: cholmod-common.c:1097 #, fuzzy, c-format msgid "CHOLMOD error '%s' at file '%s', line %d" msgstr "Błąd 'cholmod' '%s' w pliku %s, linia %d" # Matrix/src/chm_common.c: 702 # warning(_("Cholmod warning '%s' at file %s, line %d"), # message, file, line) #: cholmod-common.c:1100 #, fuzzy, c-format msgid "CHOLMOD warning '%s' at file '%s', line %d" msgstr "Ostrzeżenie 'cholmod' '%s' w pliku %s, linia %d" # Matrix/src/dgeMatrix.c: 341 # error(_("Determinant requires a square matrix")) #: coerce.c:24 coerce.c:364 coerce.c:1050 #, fuzzy, c-format msgid "attempt to construct non-square %s" msgstr "Wyznacznik wymaga aby macierz była kwadratowa" #: coerce.c:186 coerce.c:476 coerce.c:1467 coerce.c:1622 #, c-format msgid "second argument of '%s' does not specify a subclass of %s" msgstr "" # Matrix/src/Mutils.c: 268 # _("'%s' must be in '%s'") #: coerce.c:194 coerce.c:200 coerce.c:484 coerce.c:490 coerce.c:925 #: coerce.c:1475 coerce.c:1481 coerce.c:1630 coerce.c:1636 coerce.c:2275 #: coerce.c:3344 coerce.c:3349 #, fuzzy, c-format msgid "'%s' must be \"%s\" or \"%s\"" msgstr "'%s' musi być w '%s'" # Matrix/src/Mutils.c: 268 # _("'%s' must be in '%s'") #: coerce.c:246 coerce.c:496 coerce.c:793 coerce.c:917 coerce.c:1527 #: coerce.c:1642 dense.c:322 dense.c:1102 dense.c:1678 dense.c:1683 #: dense.c:1929 dense.c:2124 sparse.c:784 sparse.c:2449 sparse.c:3141 #: sparse.c:3146 sparse.c:3151 sparse.c:3427 sparse.c:3664 #, fuzzy, c-format msgid "'%s' must be %s or %s" msgstr "'%s' musi być w '%s'" #: coerce.c:266 coerce.c:274 coerce.c:285 coerce.c:1549 coerce.c:1557 #: coerce.c:1568 msgid "nonempty vector supplied for empty matrix" msgstr "" #: coerce.c:287 coerce.c:1570 #, c-format msgid "vector length (%lld) exceeds matrix length (%d * %d)" msgstr "" #: coerce.c:290 coerce.c:1573 #, c-format msgid "matrix length (%d * %d) is not a multiple of vector length (%lld)" msgstr "" #: coerce.c:521 #, c-format msgid "coercing n-by-n %s to %s is not supported for n*n exceeding %s" msgstr "" #: coerce.c:525 coerce.c:815 coerce.c:949 #, c-format msgid "sparse->dense coercion: allocating vector of size %0.1f GiB" msgstr "" #: coerce.c:1196 coerce.c:1941 coerce.c:2948 coerce.c:2954 #, c-format msgid "attempt to construct %s with more than %s nonzero entries" msgstr "" # Matrix/src/dgeMatrix.c: 341 # error(_("Determinant requires a square matrix")) #: coerce.c:3246 #, fuzzy msgid "attempt to pack non-square matrix" msgstr "Wyznacznik wymaga aby macierz była kwadratowa" #: coerce.c:3420 coerce.c:3590 #, c-format msgid "unable to aggregate %s with '%s' and '%s' slots of length exceeding %s" msgstr "" # Matrix/src/dgeMatrix.c: 341 # error(_("Determinant requires a square matrix")) #: coerce.c:4211 #, fuzzy, c-format msgid "attempt to pack a %s" msgstr "Wyznacznik wymaga aby macierz była kwadratowa" # Matrix/src/Mutils.c: 268 # _("'%s' must be in '%s'") #: coerce.c:4330 dense.c:1232 sparse.c:2580 #, fuzzy, c-format msgid "'%s' must be %s or %s or %s" msgstr "'%s' musi być w '%s'" # Matrix/src/Mutils.c: 268 # _("'%s' must be in '%s'") #: dense.c:210 dense.c:215 sparse.c:590 sparse.c:595 #, fuzzy, c-format msgid "'%s' (%d) must be an integer from %s (%d) to %s (%d)" msgstr "'%s' musi być w '%s'" # Matrix/src/Mutils.c: 268 # _("'%s' must be in '%s'") #: dense.c:218 sparse.c:598 #, fuzzy, c-format msgid "'%s' (%d) must be less than or equal to '%s' (%d)" msgstr "'%s' musi być w '%s'" #: dense.c:428 sparse.c:1070 #, c-format msgid "replacement diagonal has incompatible type \"%s\"" msgstr "" #: dense.c:437 sparse.c:1079 msgid "replacement diagonal has wrong length" msgstr "" # Matrix/src/dgeMatrix.c: 341 # error(_("Determinant requires a square matrix")) #: dense.c:622 sparse.c:1275 #, fuzzy msgid "attempt to symmetrize a non-square matrix" msgstr "Wyznacznik wymaga aby macierz była kwadratowa" #: dense.c:721 sparse.c:1653 msgid "attempt to get symmetric part of non-square matrix" msgstr "" #: dense.c:873 sparse.c:2083 msgid "attempt to get skew-symmetric part of non-square matrix" msgstr "" # Matrix/src/Mutils.c: 268 # _("'%s' must be in '%s'") #: dense.c:1673 sparse.c:3136 #, fuzzy, c-format msgid "'%s' must be %d or %d" msgstr "'%s' musi być w '%s'" # Matrix/src/dense.c: 31 # error(_("incorrect left cyclic shift, j (%d) < 0"), j, k) #: dense.c:2156 #, c-format msgid "incorrect left cyclic shift, j (%d) < 0" msgstr "niepoprawne lewe cykliczne przesunięcie, j (%d) < 0" # Matrix/src/dense.c: 29 # error(_("incorrect left cyclic shift, j (%d) >= k (%d)"), j, k) #: dense.c:2159 #, c-format msgid "incorrect left cyclic shift, j (%d) >= k (%d)" msgstr "niepoprawne lewe cykliczne przesunięcie, j (%d) >= k (%d)" # Matrix/src/dense.c: 33 # error(_("incorrect left cyclic shift, k (%d) > ldx (%d)"), k, ldx) #: dense.c:2162 #, c-format msgid "incorrect left cyclic shift, k (%d) > ldx (%d)" msgstr "niepoprawne lewe cykliczne przesunięcie, k (%d) > ldx (%d)" # Matrix/src/dense.c: 78 # error(_("Unknown error in 'getGivens' function")) #: dense.c:2215 #, fuzzy msgid "unknown error in getGivens" msgstr "Nieznany błąd w funkcji 'getGivens()'" # Matrix/src/dense.c: 90 # error(_("'X' argument must be a numeric (double precision) matrix")) # Matrix/src/dense.c: 106 # error(_("'X' argument must be a numeric (double precision) matrix")) # Matrix/src/dense.c: 137 # error(_("'X' argument must be a numeric (double precision) matrix")) #: dense.c:2224 dense.c:2238 dense.c:2268 msgid "X must be a numeric (double precision) matrix" msgstr "'X' musi być macierzą liczbową (o podwójnej precyzji)" # Matrix/src/dense.c: 111 # error(_("'y' argument must be a numeric (double precision) matrix")) # Matrix/src/dense.c: 142 # error(_("'y' argument must be a numeric (double precision) matrix")) #: dense.c:2240 dense.c:2270 msgid "y must be a numeric (double precision) matrix" msgstr "'y' musi być macierzą liczbową (o podwójnej precyzji)" # Matrix/src/dense.c: 114 # error(_("number of rows in 'y' (%d) does not match number of rows in 'X' (%d)"), ydims[0], n) # Matrix/src/dense.c: 145 # error(_("number of rows in 'y' (%d) does not match number of rows in 'X' (%d)"), ydims[0], n) #: dense.c:2244 dense.c:2274 #, c-format msgid "number of rows in y (%d) does not match number of rows in X (%d)" msgstr "liczba wierszy w 'y' (%d) nie zgadza się z liczbą wierszy w 'X' (%d)" # Matrix/src/dense.c: 124 # error(_("Lapack routine 'dposv' returned error code %d"), info) #: dense.c:2260 #, fuzzy, c-format msgid "LAPACK dposv returned error code %d" msgstr "procedura Lapack 'dposv' zwróciła kod błędu %d" # Matrix/src/dppMatrix.c: 37 # error(_("Lapack routine '%s' returned error code %d"), "dpptrf", info) # Matrix/src/dpoMatrix.c: 43 # error(_("Lapack routine '%s' returned error code %d"), "dpotrf", info) # Matrix/src/dgeMatrix.c: 317 # error(_("Lapack routine '%s' returned error code %d"), "dgetrf()", info) # Matrix/src/dspMatrix.c: 182 # error(_("Lapack routine '%s' returned error code %d"), "dsptrf", info) #: dense.c:2288 dense.c:2294 #, fuzzy, c-format msgid "LAPACK dgels returned error code %d" msgstr "Procedura Lapack '%s' zwróciła kod błędu %d" # Matrix/src/dense.c: 173 # error(_("'X' must be a real (numeric) matrix")) #: dense.c:2313 msgid "X must be a real (numeric) matrix" msgstr "'X' musi być rzeczywistą (liczbową) macierzą" # Matrix/src/dense.c: 175 # error(_("'tol' argument, given as %g, must be less or equal to 1"), tol) #: dense.c:2316 #, fuzzy, c-format msgid "tol, given as %g, must be >= 0" msgstr "argument 'tol', podany jako %g, musi być mniejszy lub równy 1" # Matrix/src/dense.c: 175 # error(_("'tol' argument, given as %g, must be less or equal to 1"), tol) #: dense.c:2318 #, c-format msgid "tol, given as %g, must be <= 1" msgstr "argument 'tol', podany jako %g, musi być mniejszy lub równy 1" # Matrix/src/dense.c: 199 # error(_("First call to 'dgeqrf' returned error code %d"), info) #: dense.c:2347 dense.c:2355 #, fuzzy, c-format msgid "LAPACK dgeqrf returned error code %d" msgstr "Pierwsze wywołanie 'dgeqrf()' zwróciło kod błędu %d" # Matrix/src/dense.c: 210 # error(_("Lapack routine 'dtrcon' returned error code %d"), info) # Matrix/src/dense.c: 230 # error(_("Lapack routine 'dtrcon' returned error code %d"), info) #: dense.c:2360 dense.c:2383 #, fuzzy, c-format msgid "LAPACK dtrcon returned error code %d" msgstr "Procedura Lapack 'dtrcon()' zwróciła kod błędu %d" # Matrix/src/dgeMatrix.c: 341 # error(_("Determinant requires a square matrix")) #: determinant.c:33 #, fuzzy msgid "determinant of non-square matrix is undefined" msgstr "Wyznacznik wymaga aby macierz była kwadratowa" # Matrix/src/sparseQR.c: 121 # warning(_("%s(): structurally rank deficient case: possibly WRONG zeros"), # "sparseQR_qty") # Matrix/src/sparseQR.c: 159 # warning(_("%s(): structurally rank deficient case: possibly WRONG zeros"), # "sparseQR_coef") # Matrix/src/sparseQR.c: 195 # warning(_("%s(): structurally rank deficient case: possibly WRONG zeros"), # "sparseQR_resid_fitted") #: determinant.c:276 #, fuzzy, c-format msgid "%s(<%s>) does not support structurally rank deficient case" msgstr "" "%s(): przypadek strukturalnie z niedoborem rang: prawdopodobnie BŁĘDNE zera" # Matrix/src/dgeMatrix.c: 570 # error(_("Matrix exponential requires square, non-null matrix")) #: expm.c:39 msgid "Matrix exponential requires square, non-null matrix" msgstr "Eksponencjowanie macierzy wymaga kwadratowej, niepustej macierzy" # Matrix/src/dgeMatrix.c: 587 # error(_("dgeMatrix_exp: LAPACK routine 'dgebal()' returned %d"), j) # Matrix/src/dgeMatrix.c: 589 # error(_("dgeMatrix_exp: LAPACK routine 'dgebal()' returned %d"), j) #: expm.c:56 expm.c:58 #, c-format msgid "dgeMatrix_exp: LAPACK routine dgebal returned %d" msgstr "dgeMatrix_exp: procedura LAPACK 'dgebal()' zwróciła %d" # Matrix/src/dgeMatrix.c: 627 # error(_("dgeMatrix_exp: 'dgetrf()' returned error code %d"), j) #: expm.c:96 #, c-format msgid "dgeMatrix_exp: dgetrf returned error code %d" msgstr "dgeMatrix_exp: funkcja 'dgetrf()' zwróciła kod błędu %d" # Matrix/src/dgeMatrix.c: 629 # error(_("dgeMatrix_exp: 'dgetrs()' returned error code %d"), j) #: expm.c:98 #, c-format msgid "dgeMatrix_exp: dgetrs returned error code %d" msgstr "dgeMatrix_exp: funkcja 'dgetrs()' zwróciła kod błędu %d" # Matrix/src/dgeMatrix.c: 702 # error(_("dgeMatrix_Schur: 'x' argument must be a non-null square matrix")) #: factor.c:330 msgid "dgeMatrix_Schur: argument x must be a non-null square matrix" msgstr "dgeMatrix_Schur: argument 'x' musi być niepustą macierzą kwadratową" # Matrix/src/dgeMatrix.c: 713 # error(_("dgeMatrix_Schur: first call to 'dgees()' function failed")) #: factor.c:343 msgid "dgeMatrix_Schur: first call to dgees failed" msgstr "dgeMatrix_Schur: pierwsze wywołanie funkcji 'dgees()' nie powiodło się" # Matrix/src/dgeMatrix.c: 721 # error(_("dgeMatrix_Schur: 'dgees()' function returned code %d"), info) #: factor.c:352 #, c-format msgid "dgeMatrix_Schur: dgees returned code %d" msgstr "dgeMatrix_Schur: funkcja 'dgees()' zwróciła kod %d" # Matrix/src/dsyMatrix.c: 9 # (_("Matrix is not square")) # Matrix/src/dtrMatrix.c: 13 # (_("Matrix is not square")) #: factor.c:403 sparse.c:196 #, fuzzy, c-format msgid "'%s' is not a number" msgstr "Macierz nie jest kwadratowa" #: factor.c:424 #, c-format msgid "LU factorization of m-by-n %s requires m == n" msgstr "" #: factor.c:433 #, c-format msgid "LU factorization of %s failed: out of memory or near-singular" msgstr "" #: factor.c:510 #, c-format msgid "QR factorization of m-by-n %s requires m >= n" msgstr "" #: factor.c:519 #, c-format msgid "QR factorization of %s failed: out of memory" msgstr "" #: factor.c:619 factor.c:897 #, c-format msgid "'%s' is not a number or not finite" msgstr "" #: idz.c:467 idz.c:528 #, c-format msgid "incompatible '%s' and '%s' in '%s'" msgstr "" # Matrix/src/Mutils.c: 13 # error( # _("argument type[1]='%s' must be a one-letter character string"), # typstr) # Matrix/src/Mutils.c: 32 # error( # _("argument type[1]='%s' must be a one-letter character string"), # typstr) #: kappa.c:10 kappa.c:54 #, fuzzy, c-format msgid "argument '%s' is not of type \"%s\"" msgstr "argument type[1]='%s' musi być jednoliterowym łańcuchem tekstowym" # Matrix/src/Mutils.c: 261 # _("'%s' must have string length 1") #: kappa.c:13 kappa.c:57 #, fuzzy, c-format msgid "argument '%s' has length %d" msgstr "'%s' musi mieć łańcuch długości 1" # Matrix/src/Mutils.c: 261 # _("'%s' must have string length 1") #: kappa.c:17 kappa.c:61 #, fuzzy, c-format msgid "argument '%s' (\"%s\") does not have string length %d" msgstr "'%s' musi mieć łańcuch długości 1" #: kappa.c:41 #, c-format msgid "" "argument '%s' (\"%s\") is not \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", or " "\"%s\"" msgstr "" # Matrix/src/Mutils.c: 261 # _("'%s' must have string length 1") #: kappa.c:75 #, fuzzy, c-format msgid "argument '%s' (\"%s\") is not \"%s\", \"%s\", or \"%s\"" msgstr "'%s' musi mieć łańcuch długości 1" #: kappa.c:238 #, c-format msgid "%s(%s) is undefined: '%s' is not square" msgstr "" #: matmult.c:107 matmult.c:210 matmult.c:289 matmult.c:377 matmult.c:454 #: matmult.c:548 matmult.c:812 matmult.c:862 msgid "non-conformable arguments" msgstr "" #: matmult.c:782 matmult.c:810 #, c-format msgid "'%s' does not support complex matrices" msgstr "" #: objects.c:23 #, c-format msgid "unexpected type \"%s\" in '%s'" msgstr "" #: objects.c:41 objects.c:58 #, c-format msgid "unexpected kind \"%c\" in '%s'" msgstr "" #: perm.c:26 perm.c:106 msgid "attempt to get sign of non-permutation" msgstr "" #: perm.c:51 perm.c:123 msgid "attempt to invert non-permutation" msgstr "" # Matrix/src/Csparse.c: 797 # error(_("invalid row index at position %d"), ii) #: perm.c:66 #, fuzzy msgid "invalid transposition vector" msgstr "niepoprawny indeks wiersza na pozycji %d" # Matrix/src/dgeMatrix.c: 19 # (_("'x' slot must be numeric \"double\"")) #: perm.c:79 perm.c:81 perm.c:96 perm.c:98 perm.c:113 perm.c:133 perm.c:145 #, fuzzy, c-format msgid "'%s' is not of type \"%s\"" msgstr "gniazdo 'x' musi być liczbą typu \"double\"" # Matrix/src/Mutils.c: 257 # _("'%s' slot must have length 1") #: perm.c:83 perm.c:100 perm.c:147 #, fuzzy, c-format msgid "'%s' does not have length %d" msgstr "gniazdo '%s' musi mieć długość 1" #: perm.c:86 perm.c:103 #, c-format msgid "'%s' is NA" msgstr "" # Matrix/src/dgeMatrix.c: 19 # (_("'x' slot must be numeric \"double\"")) #: perm.c:115 perm.c:138 #, fuzzy, c-format msgid "'%s' or '%s' is not of type \"%s\"" msgstr "gniazdo 'x' musi być liczbą typu \"double\"" # Matrix/src/Mutils.c: 257 # _("'%s' slot must have length 1") #: perm.c:117 perm.c:140 #, fuzzy, c-format msgid "'%s' or '%s' does not have length %d" msgstr "gniazdo '%s' musi mieć długość 1" #: perm.c:120 perm.c:143 #, c-format msgid "'%s' or '%s' is NA" msgstr "" #: perm.c:136 #, c-format msgid "'%s' has length exceeding %s" msgstr "" #: perm.c:150 #, c-format msgid "'%s' is NA or less than %s" msgstr "" # Matrix/src/dsyMatrix.c: 9 # (_("Matrix is not square")) # Matrix/src/dtrMatrix.c: 13 # (_("Matrix is not square")) #: solve.c:38 #, fuzzy, c-format msgid "'%s' is not square" msgstr "Macierz nie jest kwadratowa" #: solve.c:497 #, c-format msgid "%s(<%s>, <%s>) failed: out of memory" msgstr "" # Matrix/src/dgeMatrix.c: 341 # error(_("Determinant requires a square matrix")) #: solve.c:618 #, fuzzy, c-format msgid "attempt to construct %s with more than %s nonzero elements" msgstr "Wyznacznik wymaga aby macierz była kwadratowa" #: subscript.c:1542 subscript.c:1695 subscript.c:1938 subscript.c:2122 #, c-format msgid "%s too dense for %s; would have more than %s nonzero entries" msgstr "" #: subscript.c:2209 #, c-format msgid "NA subscripts in %s not supported for '%s' inheriting from %s" msgstr "" # Matrix/src/t_Csparse_subassign.c: 144 # error(_("invalid class of 'x' in 'Csparse_subassign()' function")) #: t_subassign.c:141 msgid "invalid class of 'x' in Csparse_subassign()" msgstr "niepoprawna klasa 'x' w funkcji 'Csparse_subassign()'" # Matrix/src/t_Csparse_subassign.c: 146 # error(_("invalid class of 'value' in 'Csparse_subassign()' function")) #: t_subassign.c:143 msgid "invalid class of 'value' in Csparse_subassign()" msgstr "niepoprawna klasa 'value' w funkcji 'Csparse_subassign()'" # Matrix/src/t_Csparse_subassign.c: 189 # warning(_("x[] <- val: 'val' must be logical for \"%s\" x"), # valid_cM[ctype_x]) #: t_subassign.c:186 #, c-format msgid "x[] <- val: val is coerced to logical for \"%s\" x" msgstr "" "x[] <- val: 'val' została przekształcone w wartość logiczną dla \"%s\" 'x'" # Matrix/src/t_Csparse_subassign.c: 194 # error(_("x[] <- val: 'val' must be integer or logical for \"%s\" x"), # valid_cM[ctype_x]) #: t_subassign.c:191 #, c-format msgid "" "x[] <- val: val should be integer or logical, is coerced to integer, for " "\"%s\" x" msgstr "" "x[] <- val: 'val' powinno być liczbą całkowitą lub wartością logiczną, " "została przekształcona na liczbę całkowitą, dla \"%s\" 'x'" # Matrix/src/t_Csparse_subassign.c: 201 # error(_("programming error in 'Csparse_subassign()' function should never happen")) #: t_subassign.c:198 msgid "programming error in Csparse_subassign() should never happen" msgstr "" "błąd programowy w funkcji 'Csparse_subassign()' nie powinien się wydarzyć" #: utils-R.c:30 utils-R.c:116 #, c-format msgid "indices would exceed %s" msgstr "" # Matrix/src/dpoMatrix.c: 115 # error(_("Argument 'b' must be a numeric matrix")) #: utils-R.c:235 utils-R.c:270 utils-R.c:281 utils-R.c:312 msgid "Argument must be numeric-like atomic vector" msgstr "Argument musi być atomowym wektorem liczbowym" # Matrix/src/Mutils.c: 983 # error(_("'data' must be of a vector type")) #: utils-R.c:345 msgid "'data' must be of a vector type" msgstr "'data' musi być type wektor" # Matrix/src/Mutils.c: 990 # error(_("invalid '%s' argument"), "byrow") #: utils-R.c:352 #, c-format msgid "invalid '%s' argument" msgstr "niepoprawny argument '%s'" # Matrix/src/Mutils.c: 997 # error(_("non-numeric matrix extent")) # Matrix/src/Mutils.c: 1005 # error(_("non-numeric matrix extent")) #: utils-R.c:359 utils-R.c:367 msgid "non-numeric matrix extent" msgstr "nieliczbowy rozmiar macierzy" # Matrix/src/Mutils.c: 1000 # error(_("invalid 'nrow' value (too large or NA)")) #: utils-R.c:362 msgid "invalid 'nrow' value (too large or NA)" msgstr "niepoprawna wartość 'nrow' (zbyt duża lub wartość NA)" # Matrix/src/Mutils.c: 1002 # error(_("invalid 'nrow' value (< 0)")) #: utils-R.c:364 msgid "invalid 'nrow' value (< 0)" msgstr "niepoprawna wartość 'nrow' (< 0)" # Matrix/src/Mutils.c: 1008 # error(_("invalid 'ncol' value (too large or NA)")) #: utils-R.c:370 msgid "invalid 'ncol' value (too large or NA)" msgstr "niepoprawna wartość 'ncol' (zbyt duża lub wartość NA)" # Matrix/src/Mutils.c: 1010 # error(_("invalid 'ncol' value (< 0)")) #: utils-R.c:372 msgid "invalid 'ncol' value (< 0)" msgstr "niepoprawna wartość 'ncol' (< 0)" # Matrix/src/Mutils.c: 1028 # warning(_("data length [%d] is not a sub-multiple or multiple of the number of rows [%d]"), lendat, nr) #: utils-R.c:390 #, fuzzy, c-format msgid "" "data length [%lld] is not a sub-multiple or multiple of the number of rows " "[%d]" msgstr "" "długość danych [%d] nie jest podwielokrotnością lub wielokrotnością liczby " "wierszy [%d]" # Matrix/src/Mutils.c: 1031 # warning(_("data length [%d] is not a sub-multiple or multiple of the number of columns [%d]"), lendat, nc) #: utils-R.c:395 #, fuzzy, c-format msgid "" "data length [%lld] is not a sub-multiple or multiple of the number of " "columns [%d]" msgstr "" "długość danych [%d] nie jest podwielokrotnością lub wielokrotnością liczby " "kolumn [%d]" # Matrix/src/Mutils.c: 1034 # warning(_("data length exceeds size of matrix")) #: utils-R.c:399 msgid "data length exceeds size of matrix" msgstr "długość danych przekracza rozmiar macierzy" # Matrix/src/Mutils.c: 1040 # error(_("too many elements specified")) #: utils-R.c:404 msgid "too many elements specified" msgstr "określono zbyt dużo elementów" # Matrix/src/Mutils.c: 840 # error(_("Argument 'ij' must be 2-column integer matrix")) #: utils-R.c:545 msgid "Argument ij must be 2-column integer matrix" msgstr "Argument 'ij' musi być 2-kolumnową macierzą liczb całkowitych" # Matrix/src/Mutils.c: 856 # error(_("subscript 'i' out of bounds in M[ij]")) #: utils-R.c:570 msgid "subscript 'i' out of bounds in M[ij]" msgstr "indeks 'i' poza zakresem w 'M[ij]'" # Matrix/src/Mutils.c: 858 # error(_("subscript 'j' out of bounds in M[ij]")) #: utils-R.c:572 msgid "subscript 'j' out of bounds in M[ij]" msgstr "indeks 'j' poza zakresem w 'M[ij]'" # Matrix/src/Mutils.c: 897 # error(_("'i' and 'j' arguments must be integer vectors of the same length")) #: utils-R.c:626 msgid "i and j must be integer vectors of the same length" msgstr "" "'i' oraz 'j' muszą być wektorami liczb całkowitych o tej samej długości" # Matrix/src/dgeMatrix.c: 11 # (_("'Dim' slot must have length 2")) #: validity.c:31 validity.c:52 validity.c:231 validity.c:250 validity.c:259 #: validity.c:441 validity.c:467 validity.c:977 validity.c:1419 validity.c:1443 #, fuzzy, c-format msgid "'%s' slot does not have length %d" msgstr "gniazdo 'Dim' musi mieć długość 2" # Matrix/src/dsyMatrix.c: 7 # (_("'dim' slot has length less than two")) # Matrix/src/dtrMatrix.c: 11 # (_("'dim' slot has length less than two")) #: validity.c:36 validity.c:932 validity.c:965 #, fuzzy, c-format msgid "'%s' slot has negative elements" msgstr "gniazdo 'dim' ma długość mniejszą niż dwa" # Matrix/src/dgeMatrix.c: 19 # (_("'x' slot must be numeric \"double\"")) #: validity.c:50 validity.c:164 #, fuzzy, c-format msgid "'%s' slot is not a list" msgstr "gniazdo 'x' musi być liczbą typu \"double\"" # Matrix/src/Mutils.c: 287 # error(_("'s1' and 's2' must be \"character\" vectors")) #: validity.c:68 #, fuzzy, c-format msgid "%s[[%d]] is not NULL or a vector" msgstr "'s1' oraz 's2' muszą być wektorami tekstowymi" #: validity.c:71 #, c-format msgid "length of %s[[%d]] (%lld) is not equal to %s[%d] (%d)" msgstr "" #: validity.c:170 #, c-format msgid "'%s' slot has no '%s' attribute" msgstr "" #: validity.c:181 validity.c:244 validity.c:435 validity.c:506 validity.c:1082 #: validity.c:1413 validity.c:1774 #, c-format msgid "%s[1] != %s[2] (matrix is not square)" msgstr "" #: validity.c:206 validity.c:219 #, c-format msgid "%s[1] differs from %s[2]" msgstr "" # Matrix/src/dgeMatrix.c: 19 # (_("'x' slot must be numeric \"double\"")) #: validity.c:234 validity.c:253 validity.c:262 validity.c:444 #, fuzzy, c-format msgid "'%s' slot is not \"%s\" or \"%s\"" msgstr "gniazdo 'x' musi być liczbą typu \"double\"" # Matrix/src/Csparse.c: 97 # (_("slot j is not increasing inside a column")) #: validity.c:331 validity.c:1580 #, fuzzy, c-format msgid "'%s' slot is not increasing within columns" msgstr "gniazdo 'j' nie jest rosnące wewnątrz kolumny" # Matrix/src/Csparse.c: 97 # (_("slot j is not increasing inside a column")) #: validity.c:382 #, fuzzy, c-format msgid "'%s' slot is not increasing within rows" msgstr "gniazdo 'j' nie jest rosnące wewnątrz kolumny" # Matrix/src/dgeMatrix.c: 11 # (_("'Dim' slot must have length 2")) #: validity.c:406 validity.c:790 validity.c:816 validity.c:842 validity.c:1043 #: validity.c:1649 validity.c:1651 #, fuzzy, c-format msgid "'%s' and '%s' slots do not have equal length" msgstr "gniazdo 'Dim' musi mieć długość 2" #: validity.c:409 #, c-format msgid "'%s' slot has nonzero length but %s is 0" msgstr "" # Matrix/src/dgeMatrix.c: 11 # (_("'Dim' slot must have length 2")) #: validity.c:450 validity.c:454 #, fuzzy, c-format msgid "'%s' slot is \"%s\" but '%s' slot does not have length %s" msgstr "gniazdo 'Dim' musi mieć długość 2" # Matrix/src/dgeMatrix.c: 19 # (_("'x' slot must be numeric \"double\"")) #: validity.c:470 #, fuzzy, c-format msgid "'%s' slot is not %d or %d" msgstr "gniazdo 'x' musi być liczbą typu \"double\"" #: validity.c:476 validity.c:479 #, c-format msgid "%s-by-%s %s invalid for positive '%s' when %s=%d" msgstr "" #: validity.c:516 validity.c:1145 validity.c:1157 validity.c:1258 #: validity.c:1270 validity.c:1350 validity.c:1399 validity.c:1458 #, c-format msgid "'%s' slot contains duplicates" msgstr "" # Matrix/src/dtTMatrix.c: 24 # (_("uplo='U' must not have sparse entries below the diagonal")) # Matrix/src/dtCMatrix.c: 28 # (_("uplo='U' must not have sparse entries below the diagonal")) # Matrix/src/dtCMatrix.c: 63 # (_("uplo='U' must not have sparse entries below the diagonal")) #: validity.c:544 validity.c:589 validity.c:635 validity.c:680 validity.c:724 #: validity.c:759 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries below the diagonal" msgstr "uplo='U' nie może mieć rzadkich wpisów poniżej diagonali" # Matrix/src/dtTMatrix.c: 29 # (_("uplo='L' must not have sparse entries above the diagonal")) # Matrix/src/dtCMatrix.c: 34 # (_("uplo='L' must not have sparse entries above the diagonal")) # Matrix/src/dtCMatrix.c: 69 # (_("uplo='L' must not have sparse entries above the diagonal")) #: validity.c:554 validity.c:602 validity.c:645 validity.c:693 validity.c:729 #: validity.c:770 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries above the diagonal" msgstr "uplo='L' nie może mieć rzadkich wpisów powyżej diagonali" # Matrix/src/dtTMatrix.c: 24 # (_("uplo='U' must not have sparse entries below the diagonal")) # Matrix/src/dtCMatrix.c: 28 # (_("uplo='U' must not have sparse entries below the diagonal")) # Matrix/src/dtCMatrix.c: 63 # (_("uplo='U' must not have sparse entries below the diagonal")) #: validity.c:592 validity.c:605 validity.c:683 validity.c:696 validity.c:762 #: validity.c:773 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries on the diagonal" msgstr "uplo='U' nie może mieć rzadkich wpisów poniżej diagonali" #: validity.c:878 validity.c:902 validity.c:906 msgid "matrix has negative diagonal elements" msgstr "" #: validity.c:922 validity.c:950 validity.c:954 msgid "matrix has nonunit diagonal elements" msgstr "" # Matrix/src/dgeMatrix.c: 19 # (_("'x' slot must be numeric \"double\"")) #: validity.c:974 validity.c:999 validity.c:1793 #, fuzzy, c-format msgid "'%s' slot is not of type \"%s\" or \"%s\"" msgstr "gniazdo 'x' musi być liczbą typu \"double\"" # Matrix/src/dgeMatrix.c: 19 # (_("'x' slot must be numeric \"double\"")) #: validity.c:982 validity.c:989 #, fuzzy, c-format msgid "'%s' slot is NA" msgstr "gniazdo 'x' musi być liczbą typu \"double\"" # Matrix/src/dsyMatrix.c: 7 # (_("'dim' slot has length less than two")) # Matrix/src/dtrMatrix.c: 11 # (_("'dim' slot has length less than two")) #: validity.c:984 validity.c:991 #, fuzzy, c-format msgid "'%s' slot is negative" msgstr "gniazdo 'dim' ma długość mniejszą niż dwa" # Matrix/src/Mutils.c: 268 # _("'%s' must be in '%s'") #: validity.c:993 #, fuzzy, c-format msgid "'%s' slot exceeds %s" msgstr "'%s' musi być w '%s'" # Matrix/src/dsyMatrix.c: 7 # (_("'dim' slot has length less than two")) # Matrix/src/dtrMatrix.c: 11 # (_("'dim' slot has length less than two")) #: validity.c:1003 #, fuzzy, c-format msgid "'%s' slot has length greater than '%s' slot" msgstr "gniazdo 'dim' ma długość mniejszą niż dwa" # Matrix/src/Csparse.c: 97 # (_("slot j is not increasing inside a column")) #: validity.c:1013 validity.c:1641 validity.c:1663 validity.c:1665 #, fuzzy, c-format msgid "'%s' slot is not increasing" msgstr "gniazdo 'j' nie jest rosnące wewnątrz kolumny" # Matrix/src/dsyMatrix.c: 7 # (_("'dim' slot has length less than two")) # Matrix/src/dtrMatrix.c: 11 # (_("'dim' slot has length less than two")) #: validity.c:1023 #, fuzzy, c-format msgid "'%s' slot has elements not in {%s} after truncation towards zero" msgstr "gniazdo 'dim' ma długość mniejszą niż dwa" # Matrix/src/Csparse.c: 97 # (_("slot j is not increasing inside a column")) #: validity.c:1026 #, fuzzy, c-format msgid "'%s' slot is not increasing after truncation towards zero" msgstr "gniazdo 'j' nie jest rosnące wewnątrz kolumny" # Matrix/src/dgeMatrix.c: 127 # error(_("Dimensions of 'x' and 'y' are not compatible for '%s'"), # tr ? "tcrossprod" : "crossprod") # Matrix/src/dgeMatrix.c: 184 # error(_("Dimensions of 'x' and 'y' are not compatible for '%s'"), # tr ? "tcrossprod" : "crossprod") #: validity.c:1092 validity.c:1119 validity.c:1781 validity.c:1788 #, fuzzy, c-format msgid "dimensions of '%s' slot are not identical to '%s'" msgstr "Wymiary 'x' oraz 'y' nie są zgodne dla '%s'" #: validity.c:1094 #, c-format msgid "'%s' slot is upper (not lower) triangular" msgstr "" #: validity.c:1107 #, c-format msgid "'%s' slot has nonunit diagonal elements" msgstr "" #: validity.c:1121 #, c-format msgid "'%s' slot is lower (not upper) triangular" msgstr "" # Matrix/src/dgeMatrix.c: 11 # (_("'Dim' slot must have length 2")) #: validity.c:1133 validity.c:1246 validity.c:1337 validity.c:1386 #, fuzzy, c-format msgid "'%s' slot does not have length %s or length %s" msgstr "gniazdo 'Dim' musi mieć długość 2" #: validity.c:1173 msgid "matrix has more columns than rows" msgstr "" # Matrix/src/dsyMatrix.c: 7 # (_("'dim' slot has length less than two")) # Matrix/src/dtrMatrix.c: 11 # (_("'dim' slot has length less than two")) #: validity.c:1193 #, fuzzy, c-format msgid "'%s' slot has fewer than %s rows" msgstr "gniazdo 'dim' ma długość mniejszą niż dwa" # Matrix/src/dsyMatrix.c: 7 # (_("'dim' slot has length less than two")) # Matrix/src/dtrMatrix.c: 11 # (_("'dim' slot has length less than two")) #: validity.c:1195 #, fuzzy, c-format msgid "'%s' slot has more than %s rows" msgstr "gniazdo 'dim' ma długość mniejszą niż dwa" # Matrix/src/dgeMatrix.c: 11 # (_("'Dim' slot must have length 2")) #: validity.c:1197 validity.c:1219 #, fuzzy, c-format msgid "'%s' slot does not have %s columns" msgstr "gniazdo 'Dim' musi mieć długość 2" # Matrix/src/dtTMatrix.c: 29 # (_("uplo='L' must not have sparse entries above the diagonal")) # Matrix/src/dtCMatrix.c: 34 # (_("uplo='L' must not have sparse entries above the diagonal")) # Matrix/src/dtCMatrix.c: 69 # (_("uplo='L' must not have sparse entries above the diagonal")) #: validity.c:1204 #, fuzzy, c-format msgid "'%s' slot must be lower trapezoidal but has entries above the diagonal" msgstr "uplo='L' nie może mieć rzadkich wpisów powyżej diagonali" # Matrix/src/dgeMatrix.c: 11 # (_("'Dim' slot must have length 2")) #: validity.c:1217 #, fuzzy, c-format msgid "'%s' slot does not have %s row" msgstr "gniazdo 'Dim' musi mieć długość 2" # Matrix/src/dtTMatrix.c: 24 # (_("uplo='U' must not have sparse entries below the diagonal")) # Matrix/src/dtCMatrix.c: 28 # (_("uplo='U' must not have sparse entries below the diagonal")) # Matrix/src/dtCMatrix.c: 63 # (_("uplo='U' must not have sparse entries below the diagonal")) #: validity.c:1226 #, fuzzy, c-format msgid "'%s' slot must be upper trapezoidal but has entries below the diagonal" msgstr "uplo='U' nie może mieć rzadkich wpisów poniżej diagonali" #: validity.c:1230 #, c-format msgid "'%s' slot has negative diagonal elements" msgstr "" #: validity.c:1296 #, c-format msgid "'%s' slot has elements not in {%s}\\{%s}" msgstr "" #: validity.c:1305 #, c-format msgid "'%s' slot has unpaired negative elements" msgstr "" #: validity.c:1331 validity.c:1375 validity.c:1379 validity.c:1727 #: validity.c:1759 msgid "Cholesky factor has negative diagonal elements" msgstr "" #: validity.c:1422 #, c-format msgid "%s[%d] (%s) is not in %s" msgstr "" #: validity.c:1435 validity.c:1536 #, c-format msgid "%s is not in {%s}" msgstr "" #: validity.c:1472 #, c-format msgid "%s is not representable as \"%s\"" msgstr "" #: validity.c:1477 validity.c:1483 #, c-format msgid "%s[%d] (%s) is not %d or %d" msgstr "" #: validity.c:1480 validity.c:1596 validity.c:1599 validity.c:1602 #, c-format msgid "%s[%d] (%s) is not %d" msgstr "" #: validity.c:1505 #, c-format msgid "%s has elements not in {%s}" msgstr "" #: validity.c:1508 #, c-format msgid "%s has elements not in {%s}\\{%s}" msgstr "" #: validity.c:1511 #, c-format msgid "%s is %d but columns are not stored in increasing order" msgstr "" #: validity.c:1514 validity.c:1517 #, c-format msgid "traversal of '%s' slot does not complete in exactly %s steps" msgstr "" #: validity.c:1523 validity.c:1525 #, c-format msgid "%s is not %d" msgstr "" #: validity.c:1546 #, c-format msgid "column '%s' is stored first but %s is not 0" msgstr "" # Matrix/src/Csparse.c: 97 # (_("slot j is not increasing inside a column")) #: validity.c:1552 #, fuzzy, c-format msgid "'%s' slot is not increasing when traversed in stored column order" msgstr "gniazdo 'j' nie jest rosnące wewnątrz kolumny" #: validity.c:1554 #, c-format msgid "'%s' slot allocates fewer than %s elements for column '%s'" msgstr "" #: validity.c:1557 #, c-format msgid "'%s' slot allocates more than %s elements for column '%s'" msgstr "" #: validity.c:1571 #, c-format msgid "first entry in column '%s' does not have row index '%s'" msgstr "" #: validity.c:1605 validity.c:1608 #, c-format msgid "%s[%d] (%s) is negative" msgstr "" #: validity.c:1611 #, c-format msgid "%s[%d] (%s) is not less than %s" msgstr "" # Matrix/src/dsyMatrix.c: 7 # (_("'dim' slot has length less than two")) # Matrix/src/dtrMatrix.c: 11 # (_("'dim' slot has length less than two")) #: validity.c:1629 #, fuzzy, c-format msgid "'%s' slot has length less than %d" msgstr "gniazdo 'dim' ma długość mniejszą niż dwa" # Matrix/src/dsyMatrix.c: 7 # (_("'dim' slot has length less than two")) # Matrix/src/dtrMatrix.c: 11 # (_("'dim' slot has length less than two")) #: validity.c:1631 #, fuzzy, c-format msgid "'%s' slot has length greater than %s" msgstr "gniazdo 'dim' ma długość mniejszą niż dwa" # Matrix/src/Csparse.c: 75 # (_("first element of slot p must be zero")) #: validity.c:1636 #, fuzzy, c-format msgid "last element of '%s' slot is not %s" msgstr "pierwszy element gniazda 'p' musi być zerem" #: validity.c:1669 #, c-format msgid "first differences of '%s' slot are less than those of '%s' slot" msgstr "" #: validity.c:1672 #, c-format msgid "supernode lengths exceed %s" msgstr "" #: validity.c:1674 #, c-format msgid "first differences of '%s' slot are not equal to supernode lengths" msgstr "" #: validity.c:1694 #, c-format msgid "" "'%s' slot is wrong within diagonal blocks (row and column indices do not " "coincide)" msgstr "" # Matrix/src/Csparse.c: 97 # (_("slot j is not increasing inside a column")) #: validity.c:1697 #, fuzzy, c-format msgid "'%s' slot is not increasing within supernodes" msgstr "gniazdo 'j' nie jest rosnące wewnątrz kolumny" # Matrix/src/cs_utils.c: 170 # error(_("invalid class of object to %s"), "Matrix_as_css") # Matrix/src/cs_utils.c: 185 # error(_("invalid class of object to %s"), "Matrix_as_css") # Matrix/src/cs_utils.c: 205 # error(_("invalid class of object to %s"), "Matrix_as_csn") # Matrix/src/cs_utils.c: 218 # error(_("invalid class of object to %s"), "Matrix_as_csn") #: validity.c:1812 #, fuzzy, c-format msgid "invalid class \"%s\" object: %s" msgstr "niepoprawna klasa obiektu przekazanego do '%s'" #: vector.c:90 #, c-format msgid "%s length cannot exceed %s" msgstr "" # Matrix/src/CHMfactor.c: 97 # error(_("diagonal element %d of Cholesky factor is missing"), j) #, c-format #~ msgid "diagonal element %d of Cholesky factor is missing" #~ msgstr "brakuje elementu diagonalnego %d czynnika Cholesky'ego" # Matrix/src/CHMfactor.c: 135 # error(_("cholmod_factorize_p failed: status %d, minor %d of ncol %d"), # c.status, f->minor, f->n) #, c-format #~ msgid "cholmod_factorize_p failed: status %d, minor %d of ncol %d" #~ msgstr "" #~ "'cholmod_factorize_p' nie powiódł się: status %d, minor %d liczba kolumn " #~ "%d" # Matrix/src/CHMfactor.c: 140 # error(_("cholmod_change_factor failed")) #~ msgid "cholmod_change_factor failed" #~ msgstr "'cholmod_change_factor' nie powiódł się" # Matrix/src/Csparse.c: 616 # error(_("cholmod_write_sparse returned error code")) #~ msgid "cholmod_write_sparse returned error code" #~ msgstr "'cholmod_write_sparse' zwrócił kod błędu" # Matrix/src/Csparse.c: 689 # warning(_("%s = '%s' (back-permuted) is experimental"), # "resultKind", "diagBack") #, c-format #~ msgid "%s = '%s' (back-permuted) is experimental" #~ msgstr "%s = '%s' (wstecznie permutowany) jest eksperymentalny" # Matrix/src/Csparse.c: 699 # error(_("diag_tC(): invalid 'resultKind'")) #~ msgid "diag_tC(): invalid 'resultKind'" #~ msgstr "diag_tC(): niepoprawny 'resultKind'" # Matrix/src/chm_common.c: 383 # error(_("complex sparse matrix code not yet written")) # Matrix/src/chm_common.c: 577 # error(_("complex sparse matrix code not yet written")) # Matrix/src/chm_common.c: 812 # error(_("complex sparse matrix code not yet written")) # Matrix/src/chm_common.c: 862 # error(_("complex sparse matrix code not yet written")) #, fuzzy #~ msgid "complex matrices are not yet supported" #~ msgstr "kod dla zespolonych rzadkich macierzy nie został jeszcze napisany" # Matrix/src/chm_common.c: 67 # error(_("Argument 'rho' must be an environment")) #~ msgid "Argument rho must be an environment" #~ msgstr "Argument 'rho' musi być środowiskiem" # Matrix/src/chm_common.c: 230 # error(_("invalid class of object passed to 'as_cholmod_sparse' function")) #~ msgid "invalid class of object to as_cholmod_sparse" #~ msgstr "" #~ "niepoprawna klasa obiektu przekazanego do funkcji 'as_cholmod_sparse()'" # Matrix/src/chm_common.c: 232 # error(_("invalid object passed to 'as_cholmod_sparse' function")) #~ msgid "invalid object passed to as_cholmod_sparse" #~ msgstr "niepoprawny obiekt przekazany do funkcji 'as_cholmod_sparse()'" # Matrix/src/chm_common.c: 259 # error(_("'in_place' 'cholmod_sort' returned an error code")) #~ msgid "in_place cholmod_sort returned an error code" #~ msgstr "'in_place' funkcji 'cholmod_sort()' zwróciło kod błędu" # Matrix/src/chm_common.c: 265 # error(_("'cholmod_sort' function returned an error code")) #~ msgid "cholmod_sort returned an error code" #~ msgstr "funkcja 'cholmod_sort' zwróciła kod błędu" # Matrix/src/chm_common.c: 346 # error(_("chm_sparse_to_SEXP(, *): invalid 'Rkind' (real kind code)")) #~ msgid "chm_sparse_to_SEXP(, *): invalid 'Rkind' (real kind code)" #~ msgstr "" #~ "chm_sparse_to_SEXP(, *): niepoprawny 'Rkind' (kod 'real kind')" # Matrix/src/chm_common.c: 354 # error(_("unknown 'xtype' in \"cholmod_sparse\" object")) #~ msgid "unknown xtype in cholmod_sparse object" #~ msgstr "nieznany 'xtype' w obiekcie klasy \"cholmod_sparse\"" # Matrix/src/chm_common.c: 383 # error(_("complex sparse matrix code not yet written")) # Matrix/src/chm_common.c: 577 # error(_("complex sparse matrix code not yet written")) # Matrix/src/chm_common.c: 812 # error(_("complex sparse matrix code not yet written")) # Matrix/src/chm_common.c: 862 # error(_("complex sparse matrix code not yet written")) #~ msgid "complex sparse matrix code not yet written" #~ msgstr "kod dla zespolonych rzadkich macierzy nie został jeszcze napisany" # Matrix/src/chm_common.c: 388 # error(_("'symmetric' and 'triangular' both set")) # Matrix/src/chm_common.c: 582 # error(_("'symmetric' and 'triangular' both set")) #~ msgid "Symmetric and triangular both set" #~ msgstr "Ustawiono jednocześnie 'symmetric' oraz 'triangular'" # Matrix/src/chm_common.c: 428 # error(_("invalid class of object passed to 'as_cholmod_triplet' function")) #~ msgid "invalid class of object to as_cholmod_triplet" #~ msgstr "" #~ "niepoprawna klasa obiektu przekazanego do funkcji 'as_cholmod_triplet()'" # Matrix/src/chm_common.c: 452 # error(_("as_cholmod_triplet(): could not reallocate for internal 'diagU2N()' function")) #~ msgid "as_cholmod_triplet(): could not reallocate for internal diagU2N()" #~ msgstr "" #~ "as_cholmod_triplet(): nie można ponownie przydzielić dla wewnętrznej " #~ "funkcji 'diagU2N()'" # Matrix/src/chm_common.c: 549 # error(_("unknown 'xtype' in \"cholmod_triplet\" object")) #~ msgid "unknown xtype in cholmod_triplet object" #~ msgstr "nieznany 'xtype' w obiekcie klasy \"cholmod_triplet\"" # Matrix/src/chm_common.c: 628 # error(_("invalid class of object passed to 'as_cholmod_dense()' function")) #~ msgid "invalid class of object to as_cholmod_dense" #~ msgstr "" #~ "niepoprawna klasa obiektu przekazanego do funkcji 'as_cholmod_dense()'" # Matrix/src/chm_common.c: 731 # error(_("Unable to initialize 'cholmod' function: error code %d"), res) #, c-format #~ msgid "Unable to initialize cholmod: error code %d" #~ msgstr "Nie można zainicjować funkcji 'cholmod()': kod błędu %d" # Matrix/src/chm_common.c: 778 # error(_("unknown 'Rkind'")) #~ msgid "unknown 'Rkind'" #~ msgstr "nieznany 'Rkind'" # Matrix/src/chm_common.c: 785 # error(_("unknown 'xtype'")) # Matrix/src/chm_common.c: 848 # error(_("unknown 'xtype'")) #~ msgid "unknown xtype" #~ msgstr "nieznany 'xtype'" # Matrix/src/chm_common.c: 818 # error(_("code for 'cholmod_dense()' function with holes not yet written")) # Matrix/src/chm_common.c: 871 # error(_("code for 'cholmod_dense()' functionwith holes not yet written")) #~ msgid "code for cholmod_dense with holes not yet written" #~ msgstr "" #~ "kod dla funkcji 'cholmod_dense()' z dziurami nie jest jeszcze napisany" # Matrix/src/chm_common.c: 867 # error(_("don't know if a dense pattern matrix makes sense")) #~ msgid "don't know if a dense pattern matrix makes sense" #~ msgstr "nie wiadomo, czy gęsty wzrór macierzy ma sens" # Matrix/src/chm_common.c: 934 # error(_("invalid class of object passed to 'as_cholmod_factor' function")) #, fuzzy #~ msgid "object of invalid class to 'as_cholmod_factor()'" #~ msgstr "" #~ "niepoprawna klasa obiektu przekazanego do funkcji 'as_cholmod_factor()'" # Matrix/src/chm_common.c: 988 # error(_("failure in 'as_cholmod_factor' function")) #~ msgid "failure in as_cholmod_factor" #~ msgstr "niepowodzenie w funkcji 'as_cholmod_factor()'" # Matrix/src/chm_common.c: 1016 # error(_("CHOLMOD factorization was unsuccessful")) #~ msgid "CHOLMOD factorization was unsuccessful" #~ msgstr "Faktoryzacja 'CHOLMOD' nie powiodła się" # Matrix/src/chm_common.c: 1029 # error(_("f->xtype of %d not recognized"), f->xtype) #, c-format #~ msgid "f->xtype of %d not recognized" #~ msgstr "'f->xtype' dla %d nie został rozpoznany" # Matrix/src/chm_common.c: 1094 # error(_("chm_diagN2U(): nrow=%d, ncol=%d"), # n, chx->ncol) #, c-format #~ msgid "chm_diagN2U(): nrow=%d, ncol=%d" #~ msgstr "chm_diagN2U(): nrow=%d, ncol=%d" # Matrix/src/chm_common.c: 1137 # error(_("chm_diagN2U(x, uploT = %d): uploT should be +- 1"), uploT) #, c-format #~ msgid "chm_diagN2U(x, uploT = %d): uploT should be +- 1" #~ msgstr "chm_diagN2U(x, uploT = %d): 'uploT' powinien wynosić +/- 1" # Matrix/src/dgCMatrix.c: 156 # error(_("dgCMatrix_lusol requires a square, non-empty matrix")) #~ msgid "dgCMatrix_lusol requires a square, non-empty matrix" #~ msgstr "'dgCMatrix_lusol' wymaga kwadratowej, niepustej macierzy" # Matrix/src/dppMatrix.c: 81 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dpoMatrix.c: 92 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dpoMatrix.c: 117 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dsyMatrix.c: 85 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dtCMatrix.c: 90 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dtCMatrix.c: 106 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dgCMatrix.c: 158 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dgCMatrix.c: 184 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dgCMatrix.c: 438 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dgCMatrix.c: 471 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dtrMatrix.c: 99 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dgeMatrix.c: 423 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dspMatrix.c: 79 # error(_("Dimensions of system to be solved are inconsistent")) #~ msgid "Dimensions of system to be solved are inconsistent" #~ msgstr "Wymiary systemu, który ma być rozwiązany, są niespójne" # Matrix/src/dgCMatrix.c: 160 # error(_("cs_lusol failed")) #~ msgid "cs_lusol failed" #~ msgstr "'cs_lusol' nie powiódł się" # Matrix/src/dgCMatrix.c: 181 # error(_("'dgCMatrix_qrsol(., order)' function needs order in {0,..,3}")) #~ msgid "dgCMatrix_qrsol(., order) needs order in {0,..,3}" #~ msgstr "" #~ "funkcja 'dgCMatrix_qrsol(., order)' potrzebuje zmiennej 'order' ze zbioru " #~ "{0,..,3}" # Matrix/src/dgCMatrix.c: 190 # error(_("'dgCMatrix_qrsol(<%d x %d>-matrix)' function requires a 'tall' rectangular matrix"), # xc->m, xc->n) #, c-format #~ msgid "" #~ "dgCMatrix_qrsol(<%d x %d>-matrix) requires a 'tall' rectangular matrix" #~ msgstr "" #~ "funkcja 'dgCMatrix_qrsol(macierz <%d x %d>)' wymaga długiej prostokątnej " #~ "macierzy" # Matrix/src/dgCMatrix.c: 201 # error(_("'cs_qrsol()' function failed inside 'dgCMatrix_qrsol()' function")) #~ msgid "cs_qrsol() failed inside dgCMatrix_qrsol()" #~ msgstr "" #~ "funkcja 'cs_qrsol()' nie powiodła się wewnątrz funkcji 'dgCMatrix_qrsol()'" # Matrix/src/dgCMatrix.c: 469 # error(_("'dgCMatrix_cholsol' function requires a 'short, wide' rectangular matrix")) #~ msgid "dgCMatrix_cholsol requires a 'short, wide' rectangular matrix" #~ msgstr "" #~ "funkcja 'dgCMatrix_cholsol()' wymaga krótkiej lub szerokiej macierzy " #~ "prostokątnej" # Matrix/src/dgCMatrix.c: 477 # error(_("'cholmod_sdmult' function error (rhs)")) #~ msgid "cholmod_sdmult error (rhs)" #~ msgstr "błąd funkcji 'cholmod_sdmult' (prawa strona)" # Matrix/src/CHMfactor.c: 135 # error(_("cholmod_factorize_p failed: status %d, minor %d of ncol %d"), # c.status, f->minor, f->n) #, c-format #~ msgid "cholmod_factorize failed: status %d, minor %d from ncol %d" #~ msgstr "" #~ "'cholmod_factorize_p' nie powiódł się: status %d, minor %d liczba kolumn " #~ "%d" # Matrix/src/dgCMatrix.c: 484 # error(_("'cholmod_solve' function (CHOLMOD_A) failed: status %d, minor %d from ncol %d"), # c.status, L->minor, L->n) #, c-format #~ msgid "cholmod_solve (CHOLMOD_A) failed: status %d, minor %d from ncol %d" #~ msgstr "" #~ "funkcja 'cholmod_solve' (CHOLMOD_A) nie powiodła się: status %d, minor %d " #~ "z liczbą kolumn %d" # Matrix/src/dgCMatrix.c: 501 # error(_("'cholmod_sdmult' function error (resid)")) #~ msgid "cholmod_sdmult error (resid)" #~ msgstr "błąd funkcji 'cholmod_sdmult' (reszta)" # Matrix/src/dgCMatrix.c: 293 # error(_("'SuiteSparseQR_C_QR' function returned an error code")) #~ msgid "SuiteSparseQR_C_QR returned an error code" #~ msgstr "funkcja 'SuiteSparseQR_C_QR()' zwróciła kod błędu" # Matrix/src/dgeMatrix.c: 428 # error(_("Lapack routine 'dgetrs()': system is exactly singular")) #, fuzzy, c-format #~ msgid "LAPACK routine '%s': matrix is exactly singular, %s[i,i]=0, i=%d" #~ msgstr "procedura Lapack 'dgetrs()': system jest ściśle osobliwy" # Matrix/src/dppMatrix.c: 34 # error(_("the leading minor of order %d is not positive definite"), # info) # Matrix/src/dpoMatrix.c: 40 # error(_("the leading minor of order %d is not positive definite"), # info) #, fuzzy, c-format #~ msgid "" #~ "LAPACK routine '%s': leading principal minor of order %d is not positive" #~ msgstr "wiodący minor rzędu %d nie jest dodatnio określony" # Matrix/src/init.c: 356 # error(_("missing 'Matrix' namespace: should never happen")) #, fuzzy #~ msgid "missing 'Matrix' namespace; should never happen" #~ msgstr "brakuje przestrzeni nazw 'Matrix': nie powinno się wydarzyć" # Matrix/src/init.c: 367 # error(_("Matrix namespace not determined correctly")) #, fuzzy #~ msgid "'Matrix' namespace not determined correctly" #~ msgstr "przestrzeń nazw macierzy nie została poprawnie określona" # Matrix/src/Csparse.c: 55 # warning(_("Csparse_sort(x): x is not a valid (apart from sorting) CsparseMatrix")) #~ msgid "Csparse_sort(x): x is not a valid (apart from sorting) CsparseMatrix" #~ msgstr "" #~ "Csparse_sort(x): 'x' nie jest poprawnym (niezależnie od sortowania) " #~ "obiektem klasy \"CsparseMatrix\"" # Matrix/src/cs_utils.c: 37 # error(_("'csp_eye' function's argument 'n' must be positive")) #~ msgid "csp_eye argument n must be positive" #~ msgstr "argument 'n' w funkcji 'csp_eye()' musi być dodatni" # Matrix/src/cs_utils.c: 68 # error(_("invalid class of 'x' argument in 'Matrix_as_cs(a, x)' function")) #~ msgid "invalid class of 'x' in Matrix_as_cs(a, x)" #~ msgstr "niepoprawna klasa argumentu 'x' w funkcji 'Matrix_as_cs(a, x)'" # Matrix/src/cs_utils.c: 170 # error(_("invalid class of object to %s"), "Matrix_as_css") # Matrix/src/cs_utils.c: 185 # error(_("invalid class of object to %s"), "Matrix_as_css") # Matrix/src/cs_utils.c: 205 # error(_("invalid class of object to %s"), "Matrix_as_csn") # Matrix/src/cs_utils.c: 218 # error(_("invalid class of object to %s"), "Matrix_as_csn") #, c-format #~ msgid "invalid class of object to %s" #~ msgstr "niepoprawna klasa obiektu przekazanego do '%s'" # Matrix/src/cs_utils.c: 139 # error(_("cs matrix not compatible with class '%s'"), valid[ctype]) #, c-format #~ msgid "cs matrix not compatible with class '%s'" #~ msgstr "'cs matrix' nie jest zgodne z klasą '%s'" # Matrix/src/cs_utils.c: 242 # error(_("Inappropriate class cl='%s' in Matrix_css_to_SEXP(S, cl, ..)"), # cl) # Matrix/src/cs_utils.c: 261 # error(_("Inappropriate class cl='%s' in Matrix_css_to_SEXP(S, cl, ..)"), # cl) #, c-format #~ msgid "Inappropriate class cl='%s' in Matrix_css_to_SEXP(S, cl, ..)" #~ msgstr "Niepoprawna klasa cl='%s' w 'Matrix_css_to_SEXP(S, cl, ..)'" # Matrix/src/cs_utils.c: 287 # error(_("Inappropriate class cl='%s' in Matrix_csn_to_SEXP(S, cl, ..)"), # cl) # Matrix/src/cs_utils.c: 306 # error(_("Inappropriate class cl='%s' in Matrix_csn_to_SEXP(S, cl, ..)"), # cl) #, c-format #~ msgid "Inappropriate class cl='%s' in Matrix_csn_to_SEXP(S, cl, ..)" #~ msgstr "Niepoprawna klasa cl='%s' w 'Matrix_csn_to_SEXP(S, cl, ..)'" # Matrix/src/dgeMatrix.c: 127 # error(_("Dimensions of 'x' and 'y' are not compatible for '%s'"), # tr ? "tcrossprod" : "crossprod") # Matrix/src/dgeMatrix.c: 184 # error(_("Dimensions of 'x' and 'y' are not compatible for '%s'"), # tr ? "tcrossprod" : "crossprod") #, c-format #~ msgid "Dimensions of x and y are not compatible for %s" #~ msgstr "Wymiary 'x' oraz 'y' nie są zgodne dla '%s'" # Matrix/src/dgeMatrix.c: 166 # error(_("'y' argument must be numeric or integer")) #, fuzzy #~ msgid "Argument y must be numeric, integer or logical" #~ msgstr "Argument 'y' musi być liczbą lub rzeczywistą lub całkowitą" # Matrix/src/dsyMatrix.c: 122 # error(_("Matrices are not conformable for multiplication")) # Matrix/src/dtrMatrix.c: 123 # error(_("Matrices are not conformable for multiplication")) # Matrix/src/dgeMatrix.c: 447 # error(_("Matrices are not conformable for multiplication")) # Matrix/src/dgeMatrix.c: 469 # error(_("Matrices are not conformable for multiplication")) # Matrix/src/dspMatrix.c: 153 # error(_("Matrices are not conformable for multiplication")) #~ msgid "Matrices are not conformable for multiplication" #~ msgstr "Macierze nie są dostosowane do przemnożenia" # Matrix/src/dtrMatrix.c: 121 # error(_("object of class \"dtrMatrix\" must be square")) #~ msgid "dtrMatrix must be square" #~ msgstr "obiekt klasy \"dtrMatrix\" musi być kwadratowy" # Matrix/src/dtpMatrix.c: 125 # error(_("Dimensions of 'a' (%d,%d) and 'b' (%d,%d) do not conform"), # xDim[0], xDim[1], yDim[0], yDim[1]) # Matrix/src/dtpMatrix.c: 153 # error(_("Dimensions of 'a' (%d,%d) and 'b' (%d,%d) do not conform"), # aDim[0], aDim[1], bDim[0], bDim[1]) # Matrix/src/dtpMatrix.c: 184 # error(_("Dimensions of 'a' (%d,%d) and 'b' (%d,%d) do not conform"), # xDim[0], xDim[1], yDim[0], yDim[1]) #, c-format #~ msgid "Dimensions of a (%d,%d) and b (%d,%d) do not conform" #~ msgstr "Wymiary 'a' (%d,%d) oraz 'b' (%d,%d) nie pokrywają się" # Matrix/src/dtpMatrix.c: 132 # error(_("right=TRUE is not yet implemented __ FIXME")) #~ msgid "right=TRUE is not yet implemented __ FIXME" #~ msgstr "'right = TRUE' nie jest jeszcze zaimplementowane __ NAPRAW_MNIE" # Matrix/src/CHMfactor.c: 14 # error(_("cholmod_change_factor failed with status %d"), c.status) #, c-format #~ msgid "cholmod_change_factor failed with status %d" #~ msgstr "'cholmod_change_factor' nie powiódł się zwracając status %d" # Matrix/src/CHMfactor.c: 30 # error(_("system argument is not valid")) # Matrix/src/CHMfactor.c: 60 # error(_("system argument is not valid")) #~ msgid "system argument is not valid" #~ msgstr "argument systemowy nie jest poprawny" # Matrix/src/CHMfactor.c: 47 # error(_("cholmod_updown() returned %d"), r) #, c-format #~ msgid "cholmod_updown() returned %d" #~ msgstr "cholmod_updown() zwróciło %d" # Matrix/src/Csparse.c: 455 # error(_("cholmod_drop() failed")) #~ msgid "cholmod_drop() failed" #~ msgstr "'cholmod_drop()' nie powiódł się" # Matrix/src/Mutils.c: 257 # _("'%s' slot must have length 1") #, fuzzy #~ msgid "'off' does not have length 1" #~ msgstr "gniazdo '%s' musi mieć długość 1" # Matrix/src/Mutils.c: 794 # error(_("invalid class \"%s\" passed to 'dup_mMatrix_as_dgeMatrix' function"), # class_P(A)) #, fuzzy #~ msgid "invalid 'code' to 'R_matrix_as_dense()'" #~ msgstr "" #~ "niepoprawna klasa \"%s\" przekazana do funkcji " #~ "'dup_mMatrix_as_dgeMatrix()'" # Matrix/src/Mutils.c: 794 # error(_("invalid class \"%s\" passed to 'dup_mMatrix_as_dgeMatrix' function"), # class_P(A)) #, fuzzy #~ msgid "invalid 'uplo' to 'R_matrix_as_dense()'" #~ msgstr "" #~ "niepoprawna klasa \"%s\" przekazana do funkcji " #~ "'dup_mMatrix_as_dgeMatrix()'" # Matrix/src/Mutils.c: 794 # error(_("invalid class \"%s\" passed to 'dup_mMatrix_as_dgeMatrix' function"), # class_P(A)) #, fuzzy #~ msgid "invalid 'diag' to 'R_matrix_as_dense()'" #~ msgstr "" #~ "niepoprawna klasa \"%s\" przekazana do funkcji " #~ "'dup_mMatrix_as_dgeMatrix()'" # Matrix/src/Mutils.c: 990 # error(_("invalid '%s' argument"), "byrow") #, fuzzy #~ msgid "invalid argument 'system'" #~ msgstr "niepoprawny argument '%s'" # Matrix/src/dppMatrix.c: 81 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dpoMatrix.c: 92 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dpoMatrix.c: 117 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dsyMatrix.c: 85 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dtCMatrix.c: 90 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dtCMatrix.c: 106 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dgCMatrix.c: 158 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dgCMatrix.c: 184 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dgCMatrix.c: 438 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dgCMatrix.c: 471 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dtrMatrix.c: 99 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dgeMatrix.c: 423 # error(_("Dimensions of system to be solved are inconsistent")) # Matrix/src/dspMatrix.c: 79 # error(_("Dimensions of system to be solved are inconsistent")) #, fuzzy #~ msgid "dimensions of 'qr' and 'y' are inconsistent" #~ msgstr "Wymiary systemu, który ma być rozwiązany, są niespójne" # Matrix/src/Mutils.c: 990 # error(_("invalid '%s' argument"), "byrow") #, fuzzy #~ msgid "invalid 'op'" #~ msgstr "niepoprawny argument '%s'" # Matrix/src/Mutils.c: 330 # error(_("'uplo' must be UPP or LOW")) # Matrix/src/Mutils.c: 356 # error(_("'uplo' must be UPP or LOW")) #, fuzzy #~ msgid "'names' must be TRUE or FALSE" #~ msgstr "'uplo' musi być UPP lub LOW" # Matrix/src/Csparse.c: 423 # error(_("Csparse_crossprod(): error return from cholmod_aat()")) #~ msgid "Csparse_crossprod(): error return from cholmod_aat()" #~ msgstr "Csparse_crossprod(): błąd zwrócony z 'cholmod_aat()'" # Matrix/src/t_Csparse_subassign.c: 144 # error(_("invalid class of 'x' in 'Csparse_subassign()' function")) #, fuzzy #~ msgid "invalid 'kind' to 'R_sparse_as_kind()'" #~ msgstr "niepoprawna klasa 'x' w funkcji 'Csparse_subassign()'" # Matrix/src/Csparse.c: 73 # (_("slot p must have length = nrow(.) + 1")) #~ msgid "slot p must have length = nrow(.) + 1" #~ msgstr "gniazdo 'p' musi mieć długość = nrow(.) + 1" # Matrix/src/Csparse.c: 78 # (_("last element of slot p must match length of slots j and x")) #~ msgid "last element of slot p must match length of slots j and x" #~ msgstr "" #~ "ostatni element gniazda 'p' musi zgadzać się długością z gniazdem 'j' " #~ "oraz 'x'" # Matrix/src/Csparse.c: 81 # (_("all column indices must be between 0 and ncol-1")) #~ msgid "all column indices must be between 0 and ncol-1" #~ msgstr "wszystkie indeksy kolumn muszą być pomiędzy 0 a 'ncol-1'" # Matrix/src/Csparse.c: 99 # (_("slot j is not *strictly* increasing inside a column")) #~ msgid "slot j is not *strictly* increasing inside a column" #~ msgstr "gniazdo 'j' nie jest *ściśle* rosnące wewnątrz kolumny" #~ msgid "not a 'n.CMatrix'" #~ msgstr "to nie jest 'n.Cmatrix'" # Matrix/src/Csparse.c: 172 # error(_("nz2Csparse(): invalid/non-implemented r_kind = %d"), # r_kind) #, c-format #~ msgid "nz2Csparse(): invalid/non-implemented r_kind = %d" #~ msgstr "nz2Csparse(): niepoprawny/niezaimplementowany 'r_kind = %d'" # Matrix/src/Csparse.c: 221 # error(_("Nonsymmetric matrix in Csparse_symmetric_to_general")) #~ msgid "Nonsymmetric matrix in Csparse_symmetric_to_general" #~ msgstr "Niesymetryczna macierz w 'Csparse_symmetric_to_general'" # Matrix/src/Csparse.c: 232 # error(_("Csparse_general_to_symmetric(): matrix is not square!")) #~ msgid "Csparse_general_to_symmetric(): matrix is not square!" #~ msgstr "Csparse_general_to_symmetric(): macierz nie jest kwadratowa!" # Matrix/src/Csparse.c: 568 # error(_("Index i must be NULL or integer")) #~ msgid "Index i must be NULL or integer" #~ msgstr "Indeks 'i' musi być wartością NULL lub być liczbą całkowitą" # Matrix/src/Csparse.c: 570 # error(_("Index j must be NULL or integer")) #~ msgid "Index j must be NULL or integer" #~ msgstr "Indeks 'j' musi być wartością NULL lub być liczbą całkowitą" # Matrix/src/Csparse.c: 760 # error(_("negative vector lengths not allowed: np = %d, nnz = %d"), # np, nnz) #, c-format #~ msgid "negative vector lengths not allowed: np = %d, nnz = %d" #~ msgstr "ujemne długości wektora nie są dozwolone: np = %d, nnz = %d" # Matrix/src/Csparse.c: 765 # error(_("exactly 1 of 'i', 'j' or 'p' must be NULL")) #~ msgid "exactly 1 of 'i', 'j' or 'p' must be NULL" #~ msgstr "dokładnie jeden z 'i', 'j' lub 'p' musi być wartością NULL" # Matrix/src/Csparse.c: 767 # error(_("np = %d, must be zero when p is NULL"), np) #, c-format #~ msgid "np = %d, must be zero when p is NULL" #~ msgstr "np = %d, musi wynosić zero gdy 'p' ma wartość NULL" # Matrix/src/Csparse.c: 770 # error(_("p[0] = %d, should be zero"), p[0]) #, c-format #~ msgid "p[0] = %d, should be zero" #~ msgstr "'p[0] = %d', powinno być zero" # Matrix/src/Csparse.c: 773 # error(_("p must be non-decreasing")) #~ msgid "p must be non-decreasing" #~ msgstr "'p' musi być niemalejące" # Matrix/src/Csparse.c: 789 # error(_("Inconsistent dimensions: np = 0 and nnz = %d"), # nnz) #, c-format #~ msgid "Inconsistent dimensions: np = 0 and nnz = %d" #~ msgstr "Niespójne wymiary: 'np = 0' oraz 'nnz = %d'" # Matrix/src/Csparse.c: 804 # error(_("invalid column index at position %d"), jj) #, c-format #~ msgid "invalid column index at position %d" #~ msgstr "niepoprawny indeks kolumny na pozycji %d" # Matrix/src/Csparse.c: 814 # error(_("strlen of cls argument = %d, should be 8"), strlen(cls)) #, c-format #~ msgid "strlen of cls argument = %d, should be 8" #~ msgstr "długość argumentu 'cls = %d', powinna wynosić 8" # Matrix/src/Csparse.c: 816 # error(_("cls = \"%s\" does not end in \"CMatrix\""), cls) #, c-format #~ msgid "cls = \"%s\" does not end in \"CMatrix\"" #~ msgstr "'cls = \"%s\"' nie kończy się w 'CMatrix'" # Matrix/src/Csparse.c: 826 # error(_("cls = \"%s\" must begin with 'd', 'l' or 'n'"), cls) #, c-format #~ msgid "cls = \"%s\" must begin with 'd', 'l' or 'n'" #~ msgstr "'cls = \"%s\"' musi rozpoczynać się od 'd', 'l' lub 'n'" # Matrix/src/Csparse.c: 829 # error(_("Only 'g'eneral sparse matrix types allowed")) #~ msgid "Only 'g'eneral sparse matrix types allowed" #~ msgstr "Tylko ogólne ('g') typy rzadkich macierzy są dozwolone" # Matrix/src/Csparse.c: 857 # error(_("code not yet written for cls = \"lgCMatrix\"")) #~ msgid "code not yet written for cls = \"lgCMatrix\"" #~ msgstr "kod dla 'cls = \"lgCMatrix\"' nie został jeszcze napisany" # Matrix/src/lgCMatrix.c: 58 # error(_("'A' must be a logical matrix")) #, fuzzy, c-format #~ msgid "%s must be (traditional R) matrix" #~ msgstr "'A' musi być macierzą logiczną" # Matrix/src/Mutils.c: 287 # error(_("'s1' and 's2' must be \"character\" vectors")) #, fuzzy, c-format #~ msgid "%s must be character string" #~ msgstr "'s1' oraz 's2' muszą być wektorami tekstowymi" # Matrix/src/Csparse.c: 814 # error(_("strlen of cls argument = %d, should be 8"), strlen(cls)) #, fuzzy, c-format #~ msgid "strlen of cls argument = %d, should be 9" #~ msgstr "długość argumentu 'cls = %d', powinna wynosić 8" # Matrix/src/Csparse.c: 826 # error(_("cls = \"%s\" must begin with 'd', 'l' or 'n'"), cls) #, fuzzy, c-format #~ msgid "cls = \"%s\" must begin with 'd', 'l' or 'n' for now" #~ msgstr "'cls = \"%s\"' musi rozpoczynać się od 'd', 'l' lub 'n'" # Matrix/src/lgCMatrix.c: 58 # error(_("'A' must be a logical matrix")) #, fuzzy, c-format #~ msgid "%s must be a logical or double vector" #~ msgstr "'A' musi być macierzą logiczną" # Matrix/src/Mutils.c: 22 # error(_("argument type[1]='%s' must be one of 'M','1','O','I','F' or 'E'"), # typstr) #, c-format #~ msgid "argument type[1]='%s' must be one of 'M','1','O','I','F' or 'E'" #~ msgstr "argument type[1]='%s' musi być jednym z 'M','1','O','I','F' lub 'E'" # Matrix/src/Mutils.c: 39 # error(_("argument type[1]='%s' must be one of '1','O', or 'I'"), # typstr) #, c-format #~ msgid "argument type[1]='%s' must be one of '1','O', or 'I'" #~ msgstr "argument type[1]='%s' musi być jednym z '1','O', lub 'I'" # Matrix/src/Mutils.c: 50 # error(_("object must be a named, numeric vector")) # Matrix/src/Mutils.c: 66 # error(_("object must be a named, numeric vector")) #~ msgid "object must be a named, numeric vector" #~ msgstr "obiekt musi być nazwanym wektorem liczbowym" # Matrix/src/Mutils.c: 113 # error(_("'factors' slot must be a named list")) # Matrix/src/Mutils.c: 137 # error(_("'factors' slot must be a named list")) #~ msgid "'factors' slot must be a named list" #~ msgstr "gniazdo 'factors' musi być nazwaną listą" # Matrix/src/Mutils.c: 287 # error(_("'s1' and 's2' must be \"character\" vectors")) #~ msgid "'s1' and 's2' must be \"character\" vectors" #~ msgstr "'s1' oraz 's2' muszą być wektorami tekstowymi" # Matrix/src/Mutils.c: 309 # (_("length of 'x' slot is not equal to 'prod(Dim)'")) #~ msgid "length of x slot != prod(Dim)" #~ msgstr "długość gniazda 'x' nie równa się 'prod(Dim)'" # Matrix/src/dgeMatrix.c: 14 # ngettext("Matrix", # "Negative value in 'Dim' slot", # "Negative values in 'Dim' slot", # (m*n > 0) ? 2 : 1) #~ msgid "Negative value in Dim" #~ msgid_plural "Negative values in Dim" #~ msgstr[0] "Ujemna wartość w gnieździe 'Dim'" #~ msgstr[1] "Ujemne wartości w gnieździe 'Dim'" #~ msgstr[2] "Ujemne wartości w gnieździe 'Dim'" # Matrix/src/Mutils.c: 643 # error(_("invalid class \"%s\" passed to 'dup_mMatrix_as_geMatrix' function"), # class_P(A)) #, c-format #~ msgid "invalid class '%s' to dup_mMatrix_as_geMatrix" #~ msgstr "" #~ "niepoprawna klasa \"%s\" przekazana do funkcji 'dup_mMatrix_as_geMatrix()'" # Matrix/src/Mutils.c: 763 # error(_("unexpected ctype = %d in 'dup_mMatrix_as_geMatrix' function"), ctype) #, c-format #~ msgid "unexpected ctype = %d in dup_mMatrix_as_geMatrix" #~ msgstr "nieoczekiwany 'ctype = %d' w funkcji 'dup_mMatrix_as_geMatrix()'" # Matrix/src/Tsparse.c: 20 # (_("lengths of slots i and j must match")) #~ msgid "lengths of slots i and j must match" #~ msgstr "długość gniazd 'i' oraz 'j' musi się zgadzać" # Matrix/src/Tsparse.c: 23 # (_("slot 'dim' must have length 2")) #~ msgid "slot Dim must have length 2" #~ msgstr "gniazdo 'dim' musi mieć długość 2" # Matrix/src/Tsparse.c: 27 # (_("all row indices (slot 'i') must be between 0 and nrow-1 in a object of class \"TsparseMatrix\"")) #~ msgid "" #~ "all row indices (slot 'i') must be between 0 and nrow-1 in a TsparseMatrix" #~ msgstr "" #~ "wszystkie indeksy wierszy (gniazdo 'i') muszą być pomiędzy 0 a 'nrow-1' w " #~ "obiekcie klasy \"TsparseMatrix\"" # Matrix/src/Tsparse.c: 29 # (_("all column indices (slot 'j') must be between 0 and ncol-1 in a object of class \"TsparseMatrix\"")) #~ msgid "" #~ "all column indices (slot 'j') must be between 0 and ncol-1 in a " #~ "TsparseMatrix" #~ msgstr "" #~ "wszystkie indeksy kolumn (gniazdo 'j') muszą być pomiędzy 0 a 'ncol-1' w " #~ "obiekcie klasy \"TsparseMatrix\"" # Matrix/src/chm_common.c: 948 # error(_("Supernodal LDL decomposition not available")) #~ msgid "Supernodal LDL' decomposition not available" #~ msgstr "Dekompozycja supernodalna LDL nie jest dostępna" # Matrix/src/chm_common.c: 950 # error(_("Supernodal/simplicial class inconsistent with 'type' flags")) #~ msgid "Supernodal/simplicial class inconsistent with type flags" #~ msgstr "klasa supernodal/simplicial niespójna z flagami 'type'" # Matrix/src/chm_common.c: 968 # error(_("Number of supernodes must be positive when 'is_super' argument is TRUE")) #~ msgid "Number of supernodes must be positive when is_super is TRUE" #~ msgstr "" #~ "Liczba super węzłów musi być dodatnia gdy argument 'is_super' ma wartość " #~ "TRUE" # Matrix/src/chm_common.c: 971 # error(_("Lengths of 'super' and 'pi' arguments must be equal")) #~ msgid "Lengths of super and pi must be equal" #~ msgstr "Długości 'super' oraz 'pi' muszą być równe" # Matrix/src/chm_common.c: 975 # error(_("Lengths of 'super' and 'px' arguments must be equal")) #~ msgid "Lengths of super and px must be equal" #~ msgstr "Długości 'super' oraz 'px' muszą być równe" # Matrix/src/dense.c: 155 # error(_("First call to Lapack routine 'dgels' returned error code %d"), info) #, c-format #~ msgid "First call to Lapack routine dgels returned error code %d" #~ msgstr "Pierwsze wywołanie procedury Lapack 'dgels()' zwróciło kod błędu %d" # Matrix/src/dense.c: 161 # error(_("Second call to Lapack routine 'dgels' returned error code %d"), info) #, c-format #~ msgid "Second call to Lapack routine dgels returned error code %d" #~ msgstr "Drugie wywołanie procedury Lapack 'dgels()' zwróciło kod błędu %d" # Matrix/src/dense.c: 174 # error(_("'tol' argument, given as %g, must be non-negative"), tol) #, c-format #~ msgid "tol, given as %g, must be non-negative" #~ msgstr "argument 'tol', podany jako %g, musi być nieujemny" # Matrix/src/dense.c: 205 # error(_("Second call to 'dgeqrf' returned error code %d"), info) #, c-format #~ msgid "Second call to dgeqrf returned error code %d" #~ msgstr "Drugie wywołanie 'dgeqrf()' zwróciło kod %d" # Matrix/src/dense.c: 279 # error(_("Lower band %d is greater than upper band %d"), k1, k2) #, c-format #~ msgid "Lower band %d > upper band %d" #~ msgstr "Niższe pasmo %d jest większe niż górne pasmo %d" # Matrix/src/dense.c: 348 # error(_("ddense_to_symmetric(): matrix is not square!")) #~ msgid "ddense_to_symmetric(): matrix is not square!" #~ msgstr "ddense_to_symmetric(): macierz nie jest kwadratowa!" # Matrix/src/dense.c: 359 # error(_("matrix is not symmetric [%d,%d]"), i+1, j+1) #, c-format #~ msgid "matrix is not symmetric [%d,%d]" #~ msgstr "macierz nie jest symetryczna [%d,%d]" # Matrix/src/dense.c: 407 # error(_("matrix is not square! (symmetric part)")) #~ msgid "matrix is not square! (symmetric part)" #~ msgstr "macierz nie jest kwadratowa! (część symetryczna)" # Matrix/src/dense.c: 451 # error(_("matrix is not square! (skew-symmetric part)")) #~ msgid "matrix is not square! (skew-symmetric part)" #~ msgstr "macierz nie jest kwadratowa! (część skośno-symetryczna)" # Matrix/src/dgTMatrix.c: 15 # (_("lengths of slots 'i' and 'x' must match")) # Matrix/src/dgCMatrix.c: 18 # (_("lengths of slots 'i' and 'x' must match")) #~ msgid "lengths of slots 'i' and 'x' must match" #~ msgstr "długość gniazd 'i' oraz 'x' musi się zgadzać" # Matrix/src/dgCMatrix.c: 30 # (_("lengths of slots 'j' and 'x' must match")) #~ msgid "lengths of slots 'j' and 'x' must match" #~ msgstr "długość gniazd 'j' oraz 'x' musi się zgadzać" # Matrix/src/dgCMatrix.c: 52 # error(_("invalid class(x) '%s' in 'compressed_to_TMatrix(x)' function"), ncl) #, c-format #~ msgid "invalid class(x) '%s' in compressed_to_TMatrix(x)" #~ msgstr "niepoprawne 'class(x)' '%s' w funkcji 'compressed_to_TMatrix(x)'" # Matrix/src/dgCMatrix.c: 86 # error(_("invalid class(x) '%s' in 'R_to_CMatrix(x)' function"), ncl) #, c-format #~ msgid "invalid class(x) '%s' in R_to_CMatrix(x)" #~ msgstr "niepoprawne 'class(x)' '%s' w funkcji 'R_to_CMatrix(x)'" # Matrix/src/dgCMatrix.c: 220 # error(_("'A' must have #{rows} >= #{columns}")) #~ msgid "A must have #{rows} >= #{columns}" #~ msgstr "'A' musi mieć liczbę wierszy >= liczba kolumn" # Matrix/src/dgCMatrix.c: 160 # error(_("cs_lusol failed")) #~ msgid "cs_sqr failed" #~ msgstr "funkcja 'cs_lusol()' nie powiodła się" # Matrix/src/dgCMatrix.c: 337 # error(_("LU decomposition applies only to square matrices")) #~ msgid "LU decomposition applies only to square matrices" #~ msgstr "dekompozycja LU stosuje się tylko do macierzy kwadratowych" # Matrix/src/dgCMatrix.c: 346 # error(_("cs_lu(A) failed: near-singular 'A' (or out of memory)")) #~ msgid "cs_lu(A) failed: near-singular A (or out of memory)" #~ msgstr "" #~ "'cs_lu(A)' nie powiódł się: 'A' jest bliskie osobliwości (lub brak " #~ "pamięci)" # Matrix/src/dgCMatrix.c: 406 # error(_("dgCMatrix_matrix_solve(.., sparse=TRUE) not yet implemented")) #~ msgid "dgCMatrix_matrix_solve(.., sparse=TRUE) not yet implemented" #~ msgstr "" #~ "'dgCMatrix_matrix_solve(.., sparse=TRUE)' nie jest jeszcze " #~ "zaimplementowane" # Matrix/src/Tsparse.c: 20 # (_("lengths of slots i and j must match")) #~ msgid "lengths of slots i and x must match" #~ msgstr "długość gniazd 'i' oraz 'j' musi się zgadzać" # Matrix/src/dgTMatrix.c: 56 # error(_("Cannot coerce to too large '*geMatrix' with %.0f entries"), len) #, c-format #~ msgid "Cannot coerce to too large *geMatrix with %.0f entries" #~ msgstr "Nie można przekształcić do dużego '*geMatrix' z %.0f wpisami" # Matrix/src/dgeMatrix.c: 19 # (_("'x' slot must be numeric \"double\"")) #~ msgid "x slot must be numeric \"double\"" #~ msgstr "gniazdo 'x' musi być liczbą typu \"double\"" # Matrix/src/dgeMatrix.c: 32 # (_("'factors' slot must be named list")) #~ msgid "factors slot must be named list" #~ msgstr "gniazdo 'factors' musi być nazwaną listą" # Matrix/src/dgeMatrix.c: 70 # error(_("'rcond()' function requires a square, non-empty matrix")) #~ msgid "rcond requires a square, non-empty matrix" #~ msgstr "funkcja 'rcond()' wymaga kwadratowej, niepustej macierzy" # Matrix/src/dgeMatrix.c: 307 # error(_("Cannot factor a matrix with zero extents")) #~ msgid "Cannot factor a matrix with zero extents" #~ msgstr "Nie można faktoryzować macierzy o zerowym stopniu" # Matrix/src/dgeMatrix.c: 319 # warning(_("Exact singularity detected during LU decomposition: %s, i=%d."), # "U[i,i]=0", info) #, c-format #~ msgid "Exact singularity detected during LU decomposition: %s, i=%d." #~ msgstr "Wykryto dokładną osobliwość podczas dekompozycji LU: %s, i=%d." # Matrix/src/dgeMatrix.c: 383 # error(_("'solve' function requires a square matrix")) #~ msgid "Solve requires a square matrix" #~ msgstr "funkcja 'solve()' wymaga kwadratowej macierzy" # Matrix/src/dgeMatrix.c: 396 # error(_("error [%d] from Lapack 'dgecon()' function"), info) #, c-format #~ msgid "error [%d] from Lapack 'dgecon()'" #~ msgstr "błąd [%d] z funkcji Lapack 'dgecon()'" # Matrix/src/dgeMatrix.c: 398 # error(_("Lapack dgecon(): system computationally singular, reciprocal condition number = %g"), # rcond) #, c-format #~ msgid "" #~ "Lapack dgecon(): system computationally singular, reciprocal condition " #~ "number = %g" #~ msgstr "" #~ "Lapack dgecon(): system obliczeniowo osobliwy, numer obustronnego stanu = " #~ "%g" # Matrix/src/dgeMatrix.c: 408 # error(_("Lapack routine 'dgetri()': system is exactly singular")) #~ msgid "Lapack routine dgetri: system is exactly singular" #~ msgstr "procedura Lapack 'dgetri()': system jest ściśle osobliwy" # Matrix/src/dpoMatrix.c: 13 # (_("object of class \"dpoMatrix\" is not positive definite")) #~ msgid "dpoMatrix is not positive definite" #~ msgstr "obiekt klasy \"dpoMatrix\" nie jest dodatnio określony" # Matrix/src/dpoMatrix.c: 94 # error(_("Cannot perform 'solve()' function for matrices with zero extents")) #~ msgid "Cannot solve() for matrices with zero extents" #~ msgstr "Nie można wykonać funkcji 'solve()' dla macierzy o zerowym stopniu" # Matrix/src/dpoMatrix.c: 115 # error(_("Argument 'b' must be a numeric matrix")) #~ msgid "Argument b must be a numeric matrix" #~ msgstr "Argument 'b' musi być macierzą liczbową" # Matrix/src/dsCMatrix.c: 25 # error(_("chm_factor_name(): did not get string of length 11")) #~ msgid "chm_factor_name(): did not get string of length 11" #~ msgstr "" #~ "chm_factor_name(): nie uzyskano łańcucha tekstowego o długości 11 znaków" # Matrix/src/dsCMatrix.c: 99 # error(_("Cholesky factorization failed; unusually, please report to Matrix-authors")) #~ msgid "" #~ "Cholesky factorization failed; unusually, please report to Matrix-authors" #~ msgstr "" #~ "faktoryzacja Cholesky'ego nie powiodła się; nietypowo, proszę zgłosić " #~ "raport autorom pakietu Matrix" # Matrix/src/dsCMatrix.c: 105 # error(_("internal_chm_factor: Cholesky factorization failed")) #~ msgid "internal_chm_factor: Cholesky factorization failed" #~ msgstr "internal_chm_factor: faktoryzacja Cholesky'ego nie powiodła się" # Matrix/src/dsCMatrix.c: 241 # error(_("Non-symmetric matrix passed to 'dsCMatrix_to_dgTMatrix' function")) #~ msgid "Non-symmetric matrix passed to dsCMatrix_to_dgTMatrix" #~ msgstr "" #~ "Niesymetryczna macierz przekazana do funkcji 'dsCMatrix_to_dgTMatrix()'" # Matrix/src/dtpMatrix.c: 18 # (_("Incorrect length of 'x' slot")) # Matrix/src/dspMatrix.c: 14 # (_("Incorrect length of 'x' slot")) #~ msgid "Incorrect length of 'x' slot" #~ msgstr "Niepoprawna długość gniazda 'x'" # Matrix/src/dsyMatrix.c: 158 # error(_("Lapack routine 'dsytrf' returned error code %d"), info) #, c-format #~ msgid "Lapack routine dsytrf returned error code %d" #~ msgstr "procedura Lapack 'dsytrf()' zwróciła kod błędu %d" # Matrix/src/dense.c: 173 # error(_("'X' must be a real (numeric) matrix")) #, fuzzy #~ msgid "x must be a \"double\" (numeric) matrix" #~ msgstr "'X' musi być rzeczywistą (liczbową) macierzą" # Matrix/src/dense.c: 348 # error(_("ddense_to_symmetric(): matrix is not square!")) #, fuzzy #~ msgid "matrix_trf(x, *): matrix is not square" #~ msgstr "ddense_to_symmetric(): macierz nie jest kwadratowa!" # Matrix/src/dtrMatrix.c: 248 # error(_("cannot set diag() as long as 'diag = \"U\"'")) #~ msgid "cannot set diag() as long as 'diag = \"U\"'" #~ msgstr "nie można ustawić 'diag()' dopóki 'diag = \"U\"'" # Matrix/src/dtrMatrix.c: 269 # error(_("cannot add diag() as long as 'diag = \"U\"'")) #~ msgid "cannot add diag() as long as 'diag = \"U\"'" #~ msgstr "nie można dodać 'diag()' dopóki 'diag = \"U\"'" # Matrix/src/lgCMatrix.c: 58 # error(_("'A' must be a logical matrix")) #~ msgid "A must be a logical matrix" #~ msgstr "'A' musi być macierzą logiczną" # Matrix/src/sparseQR.c: 13 # (_("'length(p)' must match 'nrow(V)'")) #~ msgid "length(p) must match nrow(V)" #~ msgstr "'length(p)' musi zgadzać się z 'nrow(V)'" # Matrix/src/sparseQR.c: 15 # (_("'length(beta)' must match 'ncol(V)'")) #~ msgid "length(beta) must match ncol(V)" #~ msgstr "'length(beta)' musi zgadzać się z 'ncol(V)'" # Matrix/src/sparseQR.c: 18 # (_("'length(q)' must be zero or 'ncol(R)'")) #~ msgid "length(q) must be zero or ncol(R)" #~ msgstr "'length(q)' musi wynosić zero lub 'ncol(R)'" #, c-format #~ msgid "sparseQR_Qmult(): nrow(y) = %d != %d = nrow(V)" #~ msgstr "sparseQR_Qmult(): nrow(y) = %d != %d = nrow(V)" # Matrix/src/dtrMatrix.c: 161 # error(_("objects of class \"dtrMatrices\" in %*% must have matching (square) dimensions")) #, fuzzy #~ msgid "\"dtrMatrix\" objects in '%*%' must have matching (square) dimension" #~ msgstr "" #~ "obiekty klasy \"dtrMatrix\" w '%*%' muszą mieć pasujące (kwadratowe) " #~ "wymiary." #~ msgid "not a CsparseMatrix" #~ msgstr "to nie jest 'CsparseMatrix'" Matrix/po/it.po0000644000175100001440000015344714575137654013165 0ustar hornikusers# R Italian translation # This file is distributed under the same license as the R package. # Copyright (C) The R Foundation. # Daniele Medri , 2005-2021. # msgid "" msgstr "" "Project-Id-Version: Matrix 1.3-3\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-14 15:49-0400\n" "PO-Revision-Date: 2021-04-14 12:18+0200\n" "Last-Translator: Daniele Medri \n" "Language-Team: Italian https://github.com/dmedri/R-italian-lang\n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.2.1\n" #: Csparse.c:26 Csparse.c:61 Csparse.c:86 Csparse.c:113 Csparse.c:127 #: Csparse.c:132 Csparse.c:137 Csparse.c:411 #, fuzzy, c-format msgid "'%s' failed" msgstr "cs_qr fallita" #: Csparse.c:35 cholmod-common.c:54 #, fuzzy, c-format msgid "'%s' slot is not increasing within columns after sorting" msgstr "lo slot j non è crescente all'interno di una colonna" #: Csparse.c:57 #, fuzzy, c-format msgid "'%s' is empty or not square" msgstr "La matrice non è quadrata" #: Csparse.c:59 Csparse.c:81 Csparse.c:104 solve.c:43 solve.c:988 #, fuzzy, c-format msgid "dimensions of '%s' and '%s' are inconsistent" msgstr "Le dimensioni del sistema da risolvere sono inconsistenti" #: Csparse.c:83 #, c-format msgid "%s(%s, %s) requires m-by-n '%s' with m >= n > 0" msgstr "" #: Csparse.c:106 #, c-format msgid "%s(%s, %s) requires m-by-n '%s' with n >= m > 0" msgstr "" #: Csparse.c:194 coerce.c:220 coerce.c:240 coerce.c:250 coerce.c:905 #: coerce.c:911 coerce.c:1015 coerce.c:1501 coerce.c:1521 coerce.c:1531 #: coerce.c:2061 coerce.c:2256 coerce.c:2262 coerce.c:2268 coerce.c:2397 #: coerce.c:2404 coerce.c:2494 coerce.c:2629 coerce.c:2707 coerce.c:2729 #: coerce.c:4327 coerce.c:4396 dense.c:696 matmult.c:939 matmult.c:1291 #: solve.c:719 solve.c:972 solve.c:1104 sparse.c:1234 sparse.c:1626 #, fuzzy, c-format msgid "invalid '%s' to '%s'" msgstr "argomento '%s' non valido" #: Csparse.c:409 #, fuzzy, c-format msgid "failed to open file \"%s\" for writing" msgstr "apertura file \"%s\" in scrittura fallita" #: attrib.c:229 #, fuzzy msgid "invalid factor name" msgstr "argomento '%s' non valido" #: attrib.c:233 #, c-format msgid "attempt to set factor on %s without '%s' slot" msgstr "" #: bind.c:46 bind.c:153 msgid "number of rows of matrices must match" msgstr "" #: bind.c:48 bind.c:155 msgid "number of columns of matrices must match" msgstr "" #: bind.c:51 bind.c:158 bind.c:182 bind.c:206 cholmod-common.c:608 #: cholmod-common.c:759 cholmod-common.c:874 cholmod-common.c:975 #: cholmod-etc.c:183 cholmod-etc.c:283 cholmod-etc.c:330 coerce.c:215 #: coerce.c:235 coerce.c:260 coerce.c:268 coerce.c:276 coerce.c:341 #: coerce.c:1496 coerce.c:1516 coerce.c:1543 coerce.c:1551 coerce.c:1559 #: matmult.c:28 matmult.c:50 matmult.c:56 #, c-format msgid "dimensions cannot exceed %s" msgstr "" #: bind.c:210 msgid "number of rows of result is not a multiple of vector length" msgstr "" #: bind.c:212 msgid "number of columns of result is not a multiple of vector length" msgstr "" #: bind.c:626 bind.c:691 sparse.c:913 sparse.c:994 #, c-format msgid "%s cannot exceed %s" msgstr "" #: bind.c:756 bind.c:853 cholmod-common.c:978 cholmod-etc.c:333 coerce.c:29 #: coerce.c:518 coerce.c:811 coerce.c:945 coerce.c:2772 coerce.c:3041 #: coerce.c:3146 dense.c:919 matmult.c:151 matmult.c:212 matmult.c:291 #: matmult.c:379 matmult.c:456 matmult.c:550 matmult.c:868 subscript.c:1232 #: subscript.c:1417 utils-R.c:32 #, c-format msgid "attempt to allocate vector of length exceeding %s" msgstr "" #: bind.c:858 matmult.c:1357 msgid "should never happen ..." msgstr "" #: cholmod-common.c:11 cholmod-common.c:34 validity.c:29 validity.c:150 #: validity.c:229 validity.c:248 validity.c:257 validity.c:299 validity.c:316 #: validity.c:350 validity.c:367 validity.c:401 validity.c:403 validity.c:439 #: validity.c:465 validity.c:485 validity.c:926 validity.c:959 validity.c:1041 #: validity.c:1061 validity.c:1127 validity.c:1129 validity.c:1177 #: validity.c:1240 validity.c:1242 validity.c:1288 validity.c:1335 #: validity.c:1384 validity.c:1417 validity.c:1427 validity.c:1440 #: validity.c:1494 validity.c:1496 validity.c:1528 validity.c:1540 #: validity.c:1563 validity.c:1626 validity.c:1645 validity.c:1647 #: validity.c:1679 validity.c:1714 validity.c:1742 #, fuzzy, c-format msgid "'%s' slot is not of type \"%s\"" msgstr "Lo slot dim non è intero" #: cholmod-common.c:14 validity.c:274 validity.c:285 validity.c:301 #: validity.c:352 validity.c:487 validity.c:928 validity.c:961 validity.c:1063 #: validity.c:1131 validity.c:1179 validity.c:1244 validity.c:1290 #: validity.c:1429 validity.c:1446 validity.c:1498 validity.c:1500 #: validity.c:1530 validity.c:1542 validity.c:1565 validity.c:1681 #: validity.c:1718 validity.c:1746 validity.c:1796 #, fuzzy, c-format msgid "'%s' slot does not have length %s" msgstr "Lo slot dim deve avere lunghezza 2" #: cholmod-common.c:18 validity.c:304 validity.c:355 validity.c:1634 #: validity.c:1654 validity.c:1656 #, fuzzy, c-format msgid "first element of '%s' slot is not 0" msgstr "il primo elemento dello slot p dev'essere zero" #: cholmod-common.c:23 cholmod-common.c:46 validity.c:34 validity.c:308 #: validity.c:326 validity.c:359 validity.c:377 validity.c:413 validity.c:415 #: validity.c:491 validity.c:1008 validity.c:1020 validity.c:1067 #: validity.c:1140 validity.c:1152 validity.c:1253 validity.c:1265 #: validity.c:1294 validity.c:1345 validity.c:1394 validity.c:1433 #: validity.c:1453 validity.c:1534 validity.c:1550 validity.c:1575 #: validity.c:1639 validity.c:1659 validity.c:1661 validity.c:1688 #, c-format msgid "'%s' slot contains NA" msgstr "" #: cholmod-common.c:26 validity.c:310 validity.c:361 #, fuzzy, c-format msgid "'%s' slot is not nondecreasing" msgstr "lo slot p dev'essere non decrescente" #: cholmod-common.c:29 validity.c:312 validity.c:363 #, c-format msgid "first differences of '%s' slot exceed %s" msgstr "" #: cholmod-common.c:37 validity.c:318 validity.c:369 #, fuzzy, c-format msgid "'%s' slot has length less than %s" msgstr "lo slot 'Dim' ha lunghezza inferiore a due" #: cholmod-common.c:49 validity.c:328 validity.c:379 validity.c:417 #: validity.c:420 validity.c:493 validity.c:1010 validity.c:1069 #: validity.c:1142 validity.c:1154 validity.c:1255 validity.c:1267 #: validity.c:1347 validity.c:1396 validity.c:1455 validity.c:1577 #: validity.c:1690 #, fuzzy, c-format msgid "'%s' slot has elements not in {%s}" msgstr "lo slot 'Dim' ha lunghezza inferiore a due" #: cholmod-common.c:165 cholmod-common.c:296 cholmod-common.c:1072 #: cholmod-common.c:1075 cholmod-common.c:1108 cholmod-common.c:1126 #, fuzzy, c-format msgid "'%s' failed in '%s'" msgstr "cs_qr fallita" #: cholmod-common.c:212 #, fuzzy, c-format msgid "'%s' failed in '%s': %s" msgstr "cs_qr fallita" #: cholmod-common.c:601 cholmod-common.c:604 cholmod-common.c:606 #: cholmod-common.c:752 cholmod-common.c:755 cholmod-common.c:757 #: cholmod-common.c:867 cholmod-common.c:870 cholmod-common.c:872 #: cholmod-common.c:969 cholmod-common.c:971 cholmod-etc.c:177 #: cholmod-etc.c:179 cholmod-etc.c:181 cholmod-etc.c:277 cholmod-etc.c:279 #: cholmod-etc.c:281 cholmod-etc.c:324 cholmod-etc.c:326 cs-etc.c:43 #, c-format msgid "wrong '%s'" msgstr "" #: cholmod-common.c:611 cholmod-etc.c:186 #, fuzzy, c-format msgid "'%s' would overflow type \"%s\"" msgstr "Lo slot dim non è intero" #: cholmod-common.c:615 cholmod-etc.c:190 #, c-format msgid "n+1 would overflow type \"%s\"" msgstr "" #: cholmod-common.c:620 cholmod-etc.c:195 #, fuzzy, c-format msgid "leading principal minor of order %d is not positive" msgstr "il minore principale dell'ordine %d non è definito positivo" #: cholmod-common.c:623 cholmod-etc.c:198 #, fuzzy, c-format msgid "leading principal minor of order %d is zero" msgstr "il minore principale dell'ordine %d non è definito positivo" #: cholmod-common.c:973 cholmod-etc.c:328 msgid "leading dimension not equal to number of rows" msgstr "" #: cholmod-common.c:1037 #, c-format msgid "" "invalid simplicial Cholesky factorization: structural zero on main diagonal " "in column %d" msgstr "" #: cholmod-common.c:1097 #, fuzzy, c-format msgid "CHOLMOD error '%s' at file '%s', line %d" msgstr "Errore cholmod '%s' nel file %s, linea %d" #: cholmod-common.c:1100 #, fuzzy, c-format msgid "CHOLMOD warning '%s' at file '%s', line %d" msgstr "Avvertimento cholmod '%s' nel file %s, linea %d" #: coerce.c:24 coerce.c:364 coerce.c:1050 #, fuzzy, c-format msgid "attempt to construct non-square %s" msgstr "Il determinante richiede una matrice quadrata" #: coerce.c:186 coerce.c:476 coerce.c:1467 coerce.c:1622 #, c-format msgid "second argument of '%s' does not specify a subclass of %s" msgstr "" #: coerce.c:194 coerce.c:200 coerce.c:484 coerce.c:490 coerce.c:925 #: coerce.c:1475 coerce.c:1481 coerce.c:1630 coerce.c:1636 coerce.c:2275 #: coerce.c:3344 coerce.c:3349 #, fuzzy, c-format msgid "'%s' must be \"%s\" or \"%s\"" msgstr "'%s' dev'essere in '%s'" #: coerce.c:246 coerce.c:496 coerce.c:793 coerce.c:917 coerce.c:1527 #: coerce.c:1642 dense.c:322 dense.c:1102 dense.c:1678 dense.c:1683 #: dense.c:1929 dense.c:2124 sparse.c:784 sparse.c:2449 sparse.c:3141 #: sparse.c:3146 sparse.c:3151 sparse.c:3427 sparse.c:3664 #, fuzzy, c-format msgid "'%s' must be %s or %s" msgstr "'%s' dev'essere in '%s'" #: coerce.c:266 coerce.c:274 coerce.c:285 coerce.c:1549 coerce.c:1557 #: coerce.c:1568 msgid "nonempty vector supplied for empty matrix" msgstr "" #: coerce.c:287 coerce.c:1570 #, c-format msgid "vector length (%lld) exceeds matrix length (%d * %d)" msgstr "" #: coerce.c:290 coerce.c:1573 #, c-format msgid "matrix length (%d * %d) is not a multiple of vector length (%lld)" msgstr "" #: coerce.c:521 #, c-format msgid "coercing n-by-n %s to %s is not supported for n*n exceeding %s" msgstr "" #: coerce.c:525 coerce.c:815 coerce.c:949 #, c-format msgid "sparse->dense coercion: allocating vector of size %0.1f GiB" msgstr "" #: coerce.c:1196 coerce.c:1941 coerce.c:2948 coerce.c:2954 #, c-format msgid "attempt to construct %s with more than %s nonzero entries" msgstr "" #: coerce.c:3246 #, fuzzy msgid "attempt to pack non-square matrix" msgstr "Il determinante richiede una matrice quadrata" #: coerce.c:3420 coerce.c:3590 #, c-format msgid "unable to aggregate %s with '%s' and '%s' slots of length exceeding %s" msgstr "" #: coerce.c:4211 #, fuzzy, c-format msgid "attempt to pack a %s" msgstr "Il determinante richiede una matrice quadrata" #: coerce.c:4330 dense.c:1232 sparse.c:2580 #, fuzzy, c-format msgid "'%s' must be %s or %s or %s" msgstr "'%s' dev'essere in '%s'" #: dense.c:210 dense.c:215 sparse.c:590 sparse.c:595 #, fuzzy, c-format msgid "'%s' (%d) must be an integer from %s (%d) to %s (%d)" msgstr "'%s' dev'essere in '%s'" #: dense.c:218 sparse.c:598 #, fuzzy, c-format msgid "'%s' (%d) must be less than or equal to '%s' (%d)" msgstr "'%s' dev'essere in '%s'" #: dense.c:428 sparse.c:1070 #, fuzzy, c-format msgid "replacement diagonal has incompatible type \"%s\"" msgstr "la diagonale di ricambio ha una lunghezza errata" #: dense.c:437 sparse.c:1079 msgid "replacement diagonal has wrong length" msgstr "la diagonale di ricambio ha una lunghezza errata" #: dense.c:622 sparse.c:1275 #, fuzzy msgid "attempt to symmetrize a non-square matrix" msgstr "Il determinante richiede una matrice quadrata" #: dense.c:721 sparse.c:1653 msgid "attempt to get symmetric part of non-square matrix" msgstr "" #: dense.c:873 sparse.c:2083 msgid "attempt to get skew-symmetric part of non-square matrix" msgstr "" #: dense.c:1673 sparse.c:3136 #, fuzzy, c-format msgid "'%s' must be %d or %d" msgstr "'%s' dev'essere in '%s'" #: dense.c:2156 #, c-format msgid "incorrect left cyclic shift, j (%d) < 0" msgstr "spostamento ciclico sinistro errato, j (%d) < 0" #: dense.c:2159 #, c-format msgid "incorrect left cyclic shift, j (%d) >= k (%d)" msgstr "spostamento ciclico sinistro errato, j (%d) >= k (%d)" #: dense.c:2162 #, c-format msgid "incorrect left cyclic shift, k (%d) > ldx (%d)" msgstr "spostamento ciclico sinistro errato, k (%d) > ldx (%d)" #: dense.c:2215 #, fuzzy msgid "unknown error in getGivens" msgstr "Errore sconosciuto in getGivens" #: dense.c:2224 dense.c:2238 dense.c:2268 msgid "X must be a numeric (double precision) matrix" msgstr "X deve essere una matrice numerica (doppia precisione)" #: dense.c:2240 dense.c:2270 msgid "y must be a numeric (double precision) matrix" msgstr "y dev'essere una matrice numerica (doppia precisione)" #: dense.c:2244 dense.c:2274 #, c-format msgid "number of rows in y (%d) does not match number of rows in X (%d)" msgstr "" "il numero di righe in y (%d) non corrisponde al numero di righe in X (%d)" #: dense.c:2260 #, fuzzy, c-format msgid "LAPACK dposv returned error code %d" msgstr "La routine Lapack dposv ha restituito il codice di errore %d" #: dense.c:2288 dense.c:2294 #, fuzzy, c-format msgid "LAPACK dgels returned error code %d" msgstr "La routine Lapack %s ha restituito il codice di errore %d" #: dense.c:2313 msgid "X must be a real (numeric) matrix" msgstr "X dev'essere una matrice (numerica) reale" #: dense.c:2316 #, fuzzy, c-format msgid "tol, given as %g, must be >= 0" msgstr "tol, indicato come %g, dev'essere <= 1" #: dense.c:2318 #, c-format msgid "tol, given as %g, must be <= 1" msgstr "tol, indicato come %g, dev'essere <= 1" #: dense.c:2347 dense.c:2355 #, fuzzy, c-format msgid "LAPACK dgeqrf returned error code %d" msgstr "La prima chiamata a dgeqrf ha restituito il codice di errore %d" #: dense.c:2360 dense.c:2383 #, fuzzy, c-format msgid "LAPACK dtrcon returned error code %d" msgstr "La routine Lapack dtrcon ha restituito il codice di errore %d" #: determinant.c:33 #, fuzzy msgid "determinant of non-square matrix is undefined" msgstr "Il determinante richiede una matrice quadrata" #: determinant.c:276 #, fuzzy, c-format msgid "%s(<%s>) does not support structurally rank deficient case" msgstr "%s(): caso con rango strutturalmente carente: possibili zero sbagliati" #: expm.c:39 msgid "Matrix exponential requires square, non-null matrix" msgstr "L'esponenziale della matrice richiede una matrice quadrata non nulla" #: expm.c:56 expm.c:58 #, c-format msgid "dgeMatrix_exp: LAPACK routine dgebal returned %d" msgstr "dgeMatrix_exp: la routine LAPACK dgebal ha restituito %d" #: expm.c:96 #, c-format msgid "dgeMatrix_exp: dgetrf returned error code %d" msgstr "dgeMatrix_exp: dgetrf ha restituito il codice di errore %d" #: expm.c:98 #, c-format msgid "dgeMatrix_exp: dgetrs returned error code %d" msgstr "dgeMatrix_exp: dgetrs ha restituito il codice di errore %d" #: factor.c:330 msgid "dgeMatrix_Schur: argument x must be a non-null square matrix" msgstr "" "dgeMatrix_Schur: l'argomento x dev'essere una matrice quadrata non nulla" #: factor.c:343 msgid "dgeMatrix_Schur: first call to dgees failed" msgstr "dgeMatrix_Schur: prima chiamata a dgees fallita" #: factor.c:352 #, c-format msgid "dgeMatrix_Schur: dgees returned code %d" msgstr "dgeMatrix_Schur: dgees ha restituito il codice %d" #: factor.c:403 sparse.c:196 #, fuzzy, c-format msgid "'%s' is not a number" msgstr "%s non è una lista" #: factor.c:424 #, c-format msgid "LU factorization of m-by-n %s requires m == n" msgstr "" #: factor.c:433 #, c-format msgid "LU factorization of %s failed: out of memory or near-singular" msgstr "" #: factor.c:510 #, c-format msgid "QR factorization of m-by-n %s requires m >= n" msgstr "" #: factor.c:519 #, c-format msgid "QR factorization of %s failed: out of memory" msgstr "" #: factor.c:619 factor.c:897 #, c-format msgid "'%s' is not a number or not finite" msgstr "" #: idz.c:467 idz.c:528 #, c-format msgid "incompatible '%s' and '%s' in '%s'" msgstr "" #: kappa.c:10 kappa.c:54 #, fuzzy, c-format msgid "argument '%s' is not of type \"%s\"" msgstr "" "tipo di argomento [1]='%s' deve essere una stringa di caratteri di una " "lettera" #: kappa.c:13 kappa.c:57 #, fuzzy, c-format msgid "argument '%s' has length %d" msgstr "'%s' deve avere una stringa di lunghezza 1" #: kappa.c:17 kappa.c:61 #, fuzzy, c-format msgid "argument '%s' (\"%s\") does not have string length %d" msgstr "'%s' deve avere una stringa di lunghezza 1" #: kappa.c:41 #, c-format msgid "" "argument '%s' (\"%s\") is not \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", or " "\"%s\"" msgstr "" #: kappa.c:75 #, fuzzy, c-format msgid "argument '%s' (\"%s\") is not \"%s\", \"%s\", or \"%s\"" msgstr "'%s' deve avere una stringa di lunghezza 1" #: kappa.c:238 #, c-format msgid "%s(%s) is undefined: '%s' is not square" msgstr "" #: matmult.c:107 matmult.c:210 matmult.c:289 matmult.c:377 matmult.c:454 #: matmult.c:548 matmult.c:812 matmult.c:862 msgid "non-conformable arguments" msgstr "" #: matmult.c:782 matmult.c:810 #, c-format msgid "'%s' does not support complex matrices" msgstr "" #: objects.c:23 #, c-format msgid "unexpected type \"%s\" in '%s'" msgstr "" #: objects.c:41 objects.c:58 #, c-format msgid "unexpected kind \"%c\" in '%s'" msgstr "" #: perm.c:26 perm.c:106 msgid "attempt to get sign of non-permutation" msgstr "" #: perm.c:51 perm.c:123 msgid "attempt to invert non-permutation" msgstr "" #: perm.c:66 #, fuzzy msgid "invalid transposition vector" msgstr "indice riga non valido nella posizione %d" #: perm.c:79 perm.c:81 perm.c:96 perm.c:98 perm.c:113 perm.c:133 perm.c:145 #, fuzzy, c-format msgid "'%s' is not of type \"%s\"" msgstr "Lo slot dim non è intero" #: perm.c:83 perm.c:100 perm.c:147 #, fuzzy, c-format msgid "'%s' does not have length %d" msgstr "lo slot '%s' deve avere lunghezza 1" #: perm.c:86 perm.c:103 #, c-format msgid "'%s' is NA" msgstr "" #: perm.c:115 perm.c:138 #, fuzzy, c-format msgid "'%s' or '%s' is not of type \"%s\"" msgstr "Lo slot dim non è intero" #: perm.c:117 perm.c:140 #, fuzzy, c-format msgid "'%s' or '%s' does not have length %d" msgstr "lo slot '%s' deve avere lunghezza 1" #: perm.c:120 perm.c:143 #, c-format msgid "'%s' or '%s' is NA" msgstr "" #: perm.c:136 #, c-format msgid "'%s' has length exceeding %s" msgstr "" #: perm.c:150 #, c-format msgid "'%s' is NA or less than %s" msgstr "" #: solve.c:38 #, fuzzy, c-format msgid "'%s' is not square" msgstr "La matrice non è quadrata" #: solve.c:497 #, c-format msgid "%s(<%s>, <%s>) failed: out of memory" msgstr "" #: solve.c:618 #, fuzzy, c-format msgid "attempt to construct %s with more than %s nonzero elements" msgstr "Il determinante richiede una matrice quadrata" #: subscript.c:1542 subscript.c:1695 subscript.c:1938 subscript.c:2122 #, c-format msgid "%s too dense for %s; would have more than %s nonzero entries" msgstr "" #: subscript.c:2209 #, c-format msgid "NA subscripts in %s not supported for '%s' inheriting from %s" msgstr "" #: t_subassign.c:141 msgid "invalid class of 'x' in Csparse_subassign()" msgstr "classe of 'x' in Csparse_subassign() non valida" #: t_subassign.c:143 msgid "invalid class of 'value' in Csparse_subassign()" msgstr "classe di 'value' in Csparse_subassign() non valida" #: t_subassign.c:186 #, c-format msgid "x[] <- val: val is coerced to logical for \"%s\" x" msgstr "x[] <- val: val è convertito in logico per x \"%s\"" #: t_subassign.c:191 #, c-format msgid "" "x[] <- val: val should be integer or logical, is coerced to integer, for " "\"%s\" x" msgstr "" "x[] <- val: val dovrebbe essere intero o logico, è convertito in intero, per " "x \"%s\"" #: t_subassign.c:198 msgid "programming error in Csparse_subassign() should never happen" msgstr "" "l'errore di programmazione in Csparse_subassign() non dovrebbe mai accadere" #: utils-R.c:30 utils-R.c:116 #, c-format msgid "indices would exceed %s" msgstr "" #: utils-R.c:235 utils-R.c:270 utils-R.c:281 utils-R.c:312 msgid "Argument must be numeric-like atomic vector" msgstr "L'argomento dev'essere un vettore atomico numerico" #: utils-R.c:345 msgid "'data' must be of a vector type" msgstr "'data' dev'essere un tipo vettore" #: utils-R.c:352 #, c-format msgid "invalid '%s' argument" msgstr "argomento '%s' non valido" #: utils-R.c:359 utils-R.c:367 msgid "non-numeric matrix extent" msgstr "estensione della matrice non numerica" #: utils-R.c:362 msgid "invalid 'nrow' value (too large or NA)" msgstr "valore 'nrow' non valido (troppo largo o NA)" #: utils-R.c:364 msgid "invalid 'nrow' value (< 0)" msgstr "valore 'nrow' non valido (< 0)" #: utils-R.c:370 msgid "invalid 'ncol' value (too large or NA)" msgstr "valore 'ncol' non valido (troppo larga o NA)" #: utils-R.c:372 msgid "invalid 'ncol' value (< 0)" msgstr "valore 'ncol' non valido (< 0)" #: utils-R.c:390 #, fuzzy, c-format msgid "" "data length [%lld] is not a sub-multiple or multiple of the number of rows " "[%d]" msgstr "" "la lunghezza dati [%d] non è un sotto-multiplo o multiplo del numero di " "righe [%d]" #: utils-R.c:395 #, fuzzy, c-format msgid "" "data length [%lld] is not a sub-multiple or multiple of the number of " "columns [%d]" msgstr "" "la lunghezza dati [%d] non è un sotto-multiplo o multiplo del numero di " "colonne [%d]" #: utils-R.c:399 msgid "data length exceeds size of matrix" msgstr "la lunghezza dei dati eccede la dimensione della matrice" #: utils-R.c:404 msgid "too many elements specified" msgstr "specificati troppi elementi" #: utils-R.c:545 msgid "Argument ij must be 2-column integer matrix" msgstr "L'argomento ij dev'essere una matrice di interi con 2 colonne" #: utils-R.c:570 msgid "subscript 'i' out of bounds in M[ij]" msgstr "subscript 'i' fuori banda in M[ij]" #: utils-R.c:572 msgid "subscript 'j' out of bounds in M[ij]" msgstr "subscript 'j' fuori banda in M[ij]" #: utils-R.c:626 msgid "i and j must be integer vectors of the same length" msgstr "i e j devono essere vettori di interi con la medesima lunghezza" #: validity.c:31 validity.c:52 validity.c:231 validity.c:250 validity.c:259 #: validity.c:441 validity.c:467 validity.c:977 validity.c:1419 validity.c:1443 #, fuzzy, c-format msgid "'%s' slot does not have length %d" msgstr "Lo slot dim deve avere lunghezza 2" #: validity.c:36 validity.c:932 validity.c:965 #, fuzzy, c-format msgid "'%s' slot has negative elements" msgstr "lo slot 'Dim' ha lunghezza inferiore a due" #: validity.c:50 validity.c:164 #, fuzzy, c-format msgid "'%s' slot is not a list" msgstr "Lo slot dim non è intero" #: validity.c:68 #, fuzzy, c-format msgid "%s[[%d]] is not NULL or a vector" msgstr "Dimnames[%d] non è un vettore di caratteri" #: validity.c:71 #, fuzzy, c-format msgid "length of %s[[%d]] (%lld) is not equal to %s[%d] (%d)" msgstr "length(Dimnames[%d]) differisce da Dim[%d] che è %d" #: validity.c:170 #, c-format msgid "'%s' slot has no '%s' attribute" msgstr "" #: validity.c:181 validity.c:244 validity.c:435 validity.c:506 validity.c:1082 #: validity.c:1413 validity.c:1774 #, c-format msgid "%s[1] != %s[2] (matrix is not square)" msgstr "" #: validity.c:206 validity.c:219 #, c-format msgid "%s[1] differs from %s[2]" msgstr "" #: validity.c:234 validity.c:253 validity.c:262 validity.c:444 #, fuzzy, c-format msgid "'%s' slot is not \"%s\" or \"%s\"" msgstr "lo slot x non è \"double\"" #: validity.c:331 validity.c:1580 #, fuzzy, c-format msgid "'%s' slot is not increasing within columns" msgstr "lo slot j non è crescente all'interno di una colonna" #: validity.c:382 #, fuzzy, c-format msgid "'%s' slot is not increasing within rows" msgstr "lo slot j non è crescente all'interno di una colonna" #: validity.c:406 validity.c:790 validity.c:816 validity.c:842 validity.c:1043 #: validity.c:1649 validity.c:1651 #, fuzzy, c-format msgid "'%s' and '%s' slots do not have equal length" msgstr "Lo slot dim deve avere lunghezza 2" #: validity.c:409 #, c-format msgid "'%s' slot has nonzero length but %s is 0" msgstr "" #: validity.c:450 validity.c:454 #, fuzzy, c-format msgid "'%s' slot is \"%s\" but '%s' slot does not have length %s" msgstr "Lo slot dim deve avere lunghezza 2" #: validity.c:470 #, fuzzy, c-format msgid "'%s' slot is not %d or %d" msgstr "lo slot x non è \"double\"" #: validity.c:476 validity.c:479 #, c-format msgid "%s-by-%s %s invalid for positive '%s' when %s=%d" msgstr "" #: validity.c:516 validity.c:1145 validity.c:1157 validity.c:1258 #: validity.c:1270 validity.c:1350 validity.c:1399 validity.c:1458 #, c-format msgid "'%s' slot contains duplicates" msgstr "" #: validity.c:544 validity.c:589 validity.c:635 validity.c:680 validity.c:724 #: validity.c:759 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries below the diagonal" msgstr "uplo='U' non deve avere voci sparse sotto la diagonale" #: validity.c:554 validity.c:602 validity.c:645 validity.c:693 validity.c:729 #: validity.c:770 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries above the diagonal" msgstr "uplo='L' non deve avere voci sparse sopra la diagonale" #: validity.c:592 validity.c:605 validity.c:683 validity.c:696 validity.c:762 #: validity.c:773 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries on the diagonal" msgstr "uplo='U' non deve avere voci sparse sotto la diagonale" #: validity.c:878 validity.c:902 validity.c:906 msgid "matrix has negative diagonal elements" msgstr "" #: validity.c:922 validity.c:950 validity.c:954 msgid "matrix has nonunit diagonal elements" msgstr "" #: validity.c:974 validity.c:999 validity.c:1793 #, fuzzy, c-format msgid "'%s' slot is not of type \"%s\" or \"%s\"" msgstr "Lo slot dim non è intero" #: validity.c:982 validity.c:989 #, fuzzy, c-format msgid "'%s' slot is NA" msgstr "Lo slot dim non è intero" #: validity.c:984 validity.c:991 #, fuzzy, c-format msgid "'%s' slot is negative" msgstr "lo slot 'Dim' ha lunghezza inferiore a due" #: validity.c:993 #, fuzzy, c-format msgid "'%s' slot exceeds %s" msgstr "'%s' dev'essere in '%s'" #: validity.c:1003 #, fuzzy, c-format msgid "'%s' slot has length greater than '%s' slot" msgstr "lo slot 'Dim' ha lunghezza inferiore a due" #: validity.c:1013 validity.c:1641 validity.c:1663 validity.c:1665 #, fuzzy, c-format msgid "'%s' slot is not increasing" msgstr "lo slot j non è crescente all'interno di una colonna" #: validity.c:1023 #, fuzzy, c-format msgid "'%s' slot has elements not in {%s} after truncation towards zero" msgstr "lo slot 'Dim' ha lunghezza inferiore a due" #: validity.c:1026 #, fuzzy, c-format msgid "'%s' slot is not increasing after truncation towards zero" msgstr "lo slot j non è crescente all'interno di una colonna" #: validity.c:1092 validity.c:1119 validity.c:1781 validity.c:1788 #, fuzzy, c-format msgid "dimensions of '%s' slot are not identical to '%s'" msgstr "Le dimensioni di x e y sono non compatibili per %s" #: validity.c:1094 #, c-format msgid "'%s' slot is upper (not lower) triangular" msgstr "" #: validity.c:1107 #, c-format msgid "'%s' slot has nonunit diagonal elements" msgstr "" #: validity.c:1121 #, c-format msgid "'%s' slot is lower (not upper) triangular" msgstr "" #: validity.c:1133 validity.c:1246 validity.c:1337 validity.c:1386 #, fuzzy, c-format msgid "'%s' slot does not have length %s or length %s" msgstr "Lo slot dim deve avere lunghezza 2" #: validity.c:1173 msgid "matrix has more columns than rows" msgstr "" #: validity.c:1193 #, fuzzy, c-format msgid "'%s' slot has fewer than %s rows" msgstr "lo slot 'Dim' ha lunghezza inferiore a due" #: validity.c:1195 #, fuzzy, c-format msgid "'%s' slot has more than %s rows" msgstr "lo slot 'Dim' ha lunghezza inferiore a due" #: validity.c:1197 validity.c:1219 #, fuzzy, c-format msgid "'%s' slot does not have %s columns" msgstr "Lo slot dim deve avere lunghezza 2" #: validity.c:1204 #, fuzzy, c-format msgid "'%s' slot must be lower trapezoidal but has entries above the diagonal" msgstr "uplo='L' non deve avere voci sparse sopra la diagonale" #: validity.c:1217 #, fuzzy, c-format msgid "'%s' slot does not have %s row" msgstr "Lo slot dim deve avere lunghezza 2" #: validity.c:1226 #, fuzzy, c-format msgid "'%s' slot must be upper trapezoidal but has entries below the diagonal" msgstr "uplo='U' non deve avere voci sparse sotto la diagonale" #: validity.c:1230 #, c-format msgid "'%s' slot has negative diagonal elements" msgstr "" #: validity.c:1296 #, c-format msgid "'%s' slot has elements not in {%s}\\{%s}" msgstr "" #: validity.c:1305 #, c-format msgid "'%s' slot has unpaired negative elements" msgstr "" #: validity.c:1331 validity.c:1375 validity.c:1379 validity.c:1727 #: validity.c:1759 msgid "Cholesky factor has negative diagonal elements" msgstr "" #: validity.c:1422 #, fuzzy, c-format msgid "%s[%d] (%s) is not in %s" msgstr "%s non è una lista" #: validity.c:1435 validity.c:1536 #, fuzzy, c-format msgid "%s is not in {%s}" msgstr "%s non è una lista" #: validity.c:1472 #, c-format msgid "%s is not representable as \"%s\"" msgstr "" #: validity.c:1477 validity.c:1483 #, c-format msgid "%s[%d] (%s) is not %d or %d" msgstr "" #: validity.c:1480 validity.c:1596 validity.c:1599 validity.c:1602 #, c-format msgid "%s[%d] (%s) is not %d" msgstr "" #: validity.c:1505 #, c-format msgid "%s has elements not in {%s}" msgstr "" #: validity.c:1508 #, c-format msgid "%s has elements not in {%s}\\{%s}" msgstr "" #: validity.c:1511 #, c-format msgid "%s is %d but columns are not stored in increasing order" msgstr "" #: validity.c:1514 validity.c:1517 #, c-format msgid "traversal of '%s' slot does not complete in exactly %s steps" msgstr "" #: validity.c:1523 validity.c:1525 #, fuzzy, c-format msgid "%s is not %d" msgstr "%s non è una lista" #: validity.c:1546 #, c-format msgid "column '%s' is stored first but %s is not 0" msgstr "" #: validity.c:1552 #, fuzzy, c-format msgid "'%s' slot is not increasing when traversed in stored column order" msgstr "lo slot j non è crescente all'interno di una colonna" #: validity.c:1554 #, c-format msgid "'%s' slot allocates fewer than %s elements for column '%s'" msgstr "" #: validity.c:1557 #, c-format msgid "'%s' slot allocates more than %s elements for column '%s'" msgstr "" #: validity.c:1571 #, c-format msgid "first entry in column '%s' does not have row index '%s'" msgstr "" #: validity.c:1605 validity.c:1608 #, c-format msgid "%s[%d] (%s) is negative" msgstr "" #: validity.c:1611 #, c-format msgid "%s[%d] (%s) is not less than %s" msgstr "" #: validity.c:1629 #, fuzzy, c-format msgid "'%s' slot has length less than %d" msgstr "lo slot 'Dim' ha lunghezza inferiore a due" #: validity.c:1631 #, fuzzy, c-format msgid "'%s' slot has length greater than %s" msgstr "lo slot 'Dim' ha lunghezza inferiore a due" #: validity.c:1636 #, fuzzy, c-format msgid "last element of '%s' slot is not %s" msgstr "il primo elemento dello slot p dev'essere zero" #: validity.c:1669 #, c-format msgid "first differences of '%s' slot are less than those of '%s' slot" msgstr "" #: validity.c:1672 #, c-format msgid "supernode lengths exceed %s" msgstr "" #: validity.c:1674 #, c-format msgid "first differences of '%s' slot are not equal to supernode lengths" msgstr "" #: validity.c:1694 #, c-format msgid "" "'%s' slot is wrong within diagonal blocks (row and column indices do not " "coincide)" msgstr "" #: validity.c:1697 #, fuzzy, c-format msgid "'%s' slot is not increasing within supernodes" msgstr "lo slot j non è crescente all'interno di una colonna" #: validity.c:1812 #, fuzzy, c-format msgid "invalid class \"%s\" object: %s" msgstr "classe di oggetto a %s non valida" #: vector.c:90 #, c-format msgid "%s length cannot exceed %s" msgstr "" #, fuzzy, c-format #~ msgid "dgeMatrix_svd(x,*): dim(x)[j] = %d is too large" #~ msgstr "Dimensione matrice %d x %d (= %g) è troppo grande" #, c-format #~ msgid "diagonal element %d of Cholesky factor is missing" #~ msgstr "l'elemento diagonale %d del fattore Cholesky è assente" #, c-format #~ msgid "cholmod_factorize_p failed: status %d, minor %d of ncol %d" #~ msgstr "cholmod_factorize_p non riuscito: stato %d, minore %d di ncol %d" #~ msgid "cholmod_change_factor failed" #~ msgstr "cholmod_change_factor fallito" #~ msgid "cholmod_write_sparse returned error code" #~ msgstr "cholmod_write_sparse ha restituito il codice di errore" #, c-format #~ msgid "%s = '%s' (back-permuted) is experimental" #~ msgstr "%s = '%s' (back-permuted) è sperimentale" #~ msgid "diag_tC(): invalid 'resultKind'" #~ msgstr "diag_tC(): 'resultKind' non valido" #, fuzzy #~ msgid "complex matrices are not yet supported" #~ msgstr "codice a matrice sparsa complessa non ancora scritto" #~ msgid "Argument rho must be an environment" #~ msgstr "L'argomento rho dev'essere un ambiente" #~ msgid "invalid class of object to as_cholmod_sparse" #~ msgstr "classe di oggetto a as_cholmod_sparse non valida" #~ msgid "invalid object passed to as_cholmod_sparse" #~ msgstr "oggetto non valido passato a as_cholmod_sparse" #~ msgid "in_place cholmod_sort returned an error code" #~ msgstr "in_place cholmod_sort ha restituito un codice di errore" #~ msgid "cholmod_sort returned an error code" #~ msgstr "cholmod_sort ha restituito un codice di errore" #~ msgid "chm_sparse_to_SEXP(, *): invalid 'Rkind' (real kind code)" #~ msgstr "" #~ "chm_sparse_to_SEXP(, *): 'Rkind' non valido (codice di tipo reale)" #~ msgid "unknown xtype in cholmod_sparse object" #~ msgstr "xtype sconosciuto nell'oggetto cholmod_sparse" #~ msgid "complex sparse matrix code not yet written" #~ msgstr "codice a matrice sparsa complessa non ancora scritto" #~ msgid "Symmetric and triangular both set" #~ msgstr "Simmetrici e triangolari entrambi impostati" #~ msgid "invalid class of object to as_cholmod_triplet" #~ msgstr "classe di oggetto a as_cholmod_triplet non valida" #~ msgid "as_cholmod_triplet(): could not reallocate for internal diagU2N()" #~ msgstr "" #~ "as_cholmod_triplet(): non è possibile riallocare per diagU2N() interno" #~ msgid "unknown xtype in cholmod_triplet object" #~ msgstr "xtype sconosciuto nell'oggetto cholmod_triplet" #~ msgid "invalid class of object to as_cholmod_dense" #~ msgstr "classe di oggetto a as_cholmod_dense non valida" #, c-format #~ msgid "" #~ "chm_transpose_dense(ans, x) not yet implemented for %s different from %s" #~ msgstr "" #~ "chm_transpose_dense(ans, x) non ancora implementato per %s diverso da%s" #, c-format #~ msgid "Unable to initialize cholmod: error code %d" #~ msgstr "Non è possibile inizializzare il colmod: codice di errore %d" #~ msgid "unknown 'Rkind'" #~ msgstr "'Rkind' sconosciuto" #~ msgid "unknown xtype" #~ msgstr "xtype sconosciuto" #~ msgid "code for cholmod_dense with holes not yet written" #~ msgstr "il codice per cholmod_dense con buchi non ancora scritto" #~ msgid "don't know if a dense pattern matrix makes sense" #~ msgstr "non sappiamo se una matrice di schemi densi abbia senso" #, fuzzy #~ msgid "object of invalid class to 'as_cholmod_factor()'" #~ msgstr "classe di oggetto a as_cholmod_factor non valida" #~ msgid "failure in as_cholmod_factor" #~ msgstr "fallimento in as_cholmod_factor" #~ msgid "CHOLMOD factorization was unsuccessful" #~ msgstr "La fattorizzazione CHOLMOD non è andata a buon fine" #, c-format #~ msgid "f->xtype of %d not recognized" #~ msgstr "f->xtype di %d non riconosciuta" #, c-format #~ msgid "chm_diagN2U(): nrow=%d, ncol=%d" #~ msgstr "chm_diagN2U (): nrow =%d, ncol =%d" #, c-format #~ msgid "chm_diagN2U(x, uploT = %d): uploT should be +- 1" #~ msgstr "chm_diagN2U (x, uploT =%d): uploT dovrebbe essere +-1" #~ msgid "dgCMatrix_lusol requires a square, non-empty matrix" #~ msgstr "dgCMatrix_lusol richiede una matrice quadrata non vuota" #~ msgid "Dimensions of system to be solved are inconsistent" #~ msgstr "Le dimensioni del sistema da risolvere sono inconsistenti" #~ msgid "cs_lusol failed" #~ msgstr "cs_lusol fallita" #~ msgid "dgCMatrix_qrsol(., order) needs order in {0,..,3}" #~ msgstr "dgCMatrix_qrsol(., order) richiede ordine in {0,..,3}" #, c-format #~ msgid "" #~ "dgCMatrix_qrsol(<%d x %d>-matrix) requires a 'tall' rectangular matrix" #~ msgstr "" #~ "dgCMatrix_qrsol(<%d x %d>-matrix) richiede una matrice rettangolare " #~ "\"alta\"" #~ msgid "cs_qrsol() failed inside dgCMatrix_qrsol()" #~ msgstr "cs_qrsol() fallita dentro dgCMatrix_qrsol()" #~ msgid "dgCMatrix_cholsol requires a 'short, wide' rectangular matrix" #~ msgstr "" #~ "dgCMatrix_cholsol richiede una matrice rettangolare \"corta, larga\"" #~ msgid "cholmod_sdmult error (rhs)" #~ msgstr "cholmod_sdmult error (rhs)" #, c-format #~ msgid "cholmod_factorize failed: status %d, minor %d from ncol %d" #~ msgstr "cholmod_factorize fallito: stato %d, minore %d da ncol %d" #, c-format #~ msgid "cholmod_solve (CHOLMOD_A) failed: status %d, minor %d from ncol %d" #~ msgstr "" #~ "cholmod_solve(CHOLMOD_A) non riuscito: stato %d, minore %d da ncol %d" #~ msgid "cholmod_sdmult error (resid)" #~ msgstr "cholmod_sdmult error (resid)" #~ msgid "SuiteSparseQR_C_QR returned an error code" #~ msgstr "SuiteSparseQR_C_QR ha restituito un codice di errore" #, fuzzy, c-format #~ msgid "LAPACK routine '%s': matrix is exactly singular, %s[i,i]=0, i=%d" #~ msgstr "Routine Lapack dgetrs: il sistema è esattamente singolare" #, fuzzy, c-format #~ msgid "" #~ "LAPACK routine '%s': leading principal minor of order %d is not positive" #~ msgstr "il minore principale dell'ordine %d non è definito positivo" #, fuzzy #~ msgid "missing 'Matrix' namespace; should never happen" #~ msgstr "namespace 'Matrix' assente: non dovrebbe mai accadere" #, fuzzy #~ msgid "'Matrix' namespace not determined correctly" #~ msgstr "Namespace della matrice non determinato correttamente" #~ msgid "Csparse_sort(x): x is not a valid (apart from sorting) CsparseMatrix" #~ msgstr "" #~ "Csparse_sort(x): x non è una valida (a parte l'ordinamento) CsparseMatrix" #, c-format #~ msgid "Impossible Rk_x/Rk_y in Csparse_%s(), please report" #~ msgstr "" #~ "Non è possibile avere Rk_x/Rk_y in Csparse_%s(), per piacere riportatelo" #, c-format #~ msgid "chm_MOD_xtype() was not successful in Csparse_%s(), please report" #~ msgstr "" #~ "chm_MOD_xtype() non ha avuto successo in Csparse_%s(), per piacere, " #~ "segnalatelo" #, c-format #~ msgid "the number of columns differ in R_rbind2_vector: %d != %d" #~ msgstr "il numero di colonne differisce in R_rbind2_vector: %d != %d" #~ msgid "csp_eye argument n must be positive" #~ msgstr "l'argomento csp_eye n dev'essere positivo" #~ msgid "invalid class of 'x' in Matrix_as_cs(a, x)" #~ msgstr "classe di 'x' in Matrix_as_cs(a, x) non valida" #, c-format #~ msgid "invalid class of object to %s" #~ msgstr "classe di oggetto a %s non valida" #, c-format #~ msgid "cs matrix not compatible with class '%s'" #~ msgstr "matrice cs non compatibile con la classe '%s'" #, c-format #~ msgid "Inappropriate class cl='%s' in Matrix_css_to_SEXP(S, cl, ..)" #~ msgstr "Classe inappropriata cl='%s' in Matrix_css_to_SEXP(S, cl, ..)" #, c-format #~ msgid "Inappropriate class cl='%s' in Matrix_csn_to_SEXP(S, cl, ..)" #~ msgstr "Classe inappropriata cl='%s' in Matrix_csn_to_SEXP(S, cl, ..)" #, c-format #~ msgid "Dimensions of x and y are not compatible for %s" #~ msgstr "Le dimensioni di x e y sono non compatibili per %s" #~ msgid "Argument y must be numeric, integer or logical" #~ msgstr "L'argomento y dev'essere numerico, intero o logico" #~ msgid "Matrices are not conformable for multiplication" #~ msgstr "Le matrici non sono conformi per la moltiplicazione" #, c-format #~ msgid "" #~ "dimension mismatch in matrix multiplication of \"dtrMatrix\": %d != %d" #~ msgstr "" #~ "dimensione non conforme nella moltiplicazione matriciale di " #~ "\"dtrMatrix\": %d != %d" #~ msgid "dtrMatrix must be square" #~ msgstr "dtrMatrix dev'essere quadrata" #, c-format #~ msgid "Dimensions of a (%d,%d) and b (%d,%d) do not conform" #~ msgstr "Dimensioni di a (%d,%d) e b (%d,%d) non conformi" #~ msgid "right=TRUE is not yet implemented __ FIXME" #~ msgstr "right=TRUE non è ancora implementato __ SISTEMATEMI" #, c-format #~ msgid "cholmod_change_factor failed with status %d" #~ msgstr "cholmod_change_factor fallito con status %d" #~ msgid "system argument is not valid" #~ msgstr "l'argomento di sistema non è valido" #, c-format #~ msgid "cholmod_updown() returned %d" #~ msgstr "cholmod_updown() ha restituito %d" #~ msgid "cholmod_drop() failed" #~ msgstr "cholmod_drop() fallito" #, fuzzy #~ msgid "'off' does not have length 1" #~ msgstr "lo slot '%s' deve avere lunghezza 1" #, fuzzy #~ msgid "invalid 'code' to 'R_matrix_as_dense()'" #~ msgstr "classe '%s' a dup_mMatrix_as_dgeMatrix non valida" #, fuzzy #~ msgid "invalid 'uplo' to 'R_matrix_as_dense()'" #~ msgstr "classe '%s' a dup_mMatrix_as_dgeMatrix non valida" #, fuzzy #~ msgid "invalid 'diag' to 'R_matrix_as_dense()'" #~ msgstr "classe '%s' a dup_mMatrix_as_dgeMatrix non valida" #, fuzzy #~ msgid "invalid argument 'system'" #~ msgstr "argomento '%s' non valido" #, fuzzy #~ msgid "dimensions of 'qr' and 'y' are inconsistent" #~ msgstr "Le dimensioni del sistema da risolvere sono inconsistenti" #, fuzzy #~ msgid "invalid 'op'" #~ msgstr "argomento '%s' non valido" #, fuzzy #~ msgid "'names' must be TRUE or FALSE" #~ msgstr "'uplo' dev'essere UPP o LOW" #~ msgid "Csparse_crossprod(): error return from cholmod_aat()" #~ msgstr "Csparse_crossprod(): errore restituito da cholmod_aat()" #, fuzzy #~ msgid "invalid 'kind' to 'R_sparse_as_kind()'" #~ msgstr "classe of 'x' in Csparse_subassign() non valida" #~ msgid "slot p must have length = nrow(.) + 1" #~ msgstr "lo slot p deve avere lunghezza = nrow(.) + 1" #~ msgid "last element of slot p must match length of slots j and x" #~ msgstr "" #~ "l'ultimo elemento dello slot p deve corrispondere alla lunghezza degli " #~ "slot j e x" #~ msgid "all column indices must be between 0 and ncol-1" #~ msgstr "tutti gli indici di colonna devono essere compresi tra 0 e ncol-1" #~ msgid "slot j is not *strictly* increasing inside a column" #~ msgstr "lo slot j non è *strettamente* crescente all'interno di una colonna" #~ msgid "Csparse_to_nz_pattern(x, tri = NA): 'tri' is taken as TRUE" #~ msgstr "Csparse_to_nz_pattern(x, tri = NA): 'tri' è preso come TRUE" #~ msgid "not a 'n.CMatrix'" #~ msgstr "non è una 'n.CMatrix'" #, c-format #~ msgid "nz2Csparse(): invalid/non-implemented r_kind = %d" #~ msgstr "nz2Csparse(): non valido/non-implementato r_kind = %d" #~ msgid "Nonsymmetric matrix in Csparse_symmetric_to_general" #~ msgstr "Matrice non simmetrica in Csparse_symmetric_to_general" #~ msgid "Csparse_general_to_symmetric(): matrix is not square!" #~ msgstr "Csparse_general_to_symmetric(): la matrice non è quadrata!" #~ msgid "Index i must be NULL or integer" #~ msgstr "L'indice i dev'essere NULL o intero" #~ msgid "Index j must be NULL or integer" #~ msgstr "L'indice j dev'essere NULL o intero" #, c-format #~ msgid "negative vector lengths not allowed: np = %d, nnz = %d" #~ msgstr "lunghezze vettore negativa non ammesse: np = %d, nnz = %d" #~ msgid "exactly 1 of 'i', 'j' or 'p' must be NULL" #~ msgstr "esattamente 1 di 'i', 'j' o 'p' dev'essere NULL" #, c-format #~ msgid "np = %d, must be zero when p is NULL" #~ msgstr "np = %d, dev'essere zero quando p è NULL" #, c-format #~ msgid "p[0] = %d, should be zero" #~ msgstr "p[0] = %d, dovrebbe essere zero" #~ msgid "p must be non-decreasing" #~ msgstr "p dev'essere non decrescente" #, c-format #~ msgid "Inconsistent dimensions: np = 0 and nnz = %d" #~ msgstr "Dimensioni inconsistenti: np = 0 e nnz = %d" #, c-format #~ msgid "invalid column index at position %d" #~ msgstr "indice colonna non valido nella posizione %d" #, c-format #~ msgid "strlen of cls argument = %d, should be 8" #~ msgstr "strlen dell'argomento cls = %d, dovrebbe essere 8" #, c-format #~ msgid "cls = \"%s\" does not end in \"CMatrix\"" #~ msgstr "cls = \"%s\" non finisce in \"CMatrix\"" #, c-format #~ msgid "cls = \"%s\" must begin with 'd', 'l' or 'n'" #~ msgstr "cls = \"%s\" deve iniziare con 'd', 'l' o 'n'" #~ msgid "Only 'g'eneral sparse matrix types allowed" #~ msgstr "Sono consentiti solo tipi di matrici sparse generali 'g'" #~ msgid "code not yet written for cls = \"lgCMatrix\"" #~ msgstr "codice non ancora scritto per cls = \"lgCMatrix\"" #, c-format #~ msgid "%s must be (traditional R) matrix" #~ msgstr "%s dev'essere una matrice (tradizionale di R)" #, c-format #~ msgid "%s must be character string" #~ msgstr "%s dev'essere una stringa di caratteri" #, c-format #~ msgid "nrow * ncol = %d * %d must equal length(x) = %ld" #~ msgstr "nrow * ncol = %d * %d deve eguagliare length(x) = %ld" #, c-format #~ msgid "strlen of cls argument = %d, should be 9" #~ msgstr "strlen dell'argomento cls = %d, dovrebbe essere 9" #, c-format #~ msgid "cls = \"%s\" must begin with 'd', 'l' or 'n' for now" #~ msgstr "cls = \"%s\" deve iniziare con 'd', 'l' o 'n' per ora" #, c-format #~ msgid "%s must be a logical or double vector" #~ msgstr "%s dev'essere un vettore di tipo logical o double" #, c-format #~ msgid "argument type[1]='%s' must be one of 'M','1','O','I','F' or 'E'" #~ msgstr "" #~ "tipo di argomento [1]='%s' dev'essere uno di 'M', '1', 'O', 'I', 'F' o 'E'" #, c-format #~ msgid "argument type[1]='%s' must be one of '1','O', or 'I'" #~ msgstr "tipo di argomento [1]='%s' dev'essere uno di '1', 'O' o 'I'" #~ msgid "object must be a named, numeric vector" #~ msgstr "l'oggetto dev'essere un vettore numerico nominato" #~ msgid "'factors' slot must be a named list" #~ msgstr "lo slot 'factors' deve essere una lista nominata" #~ msgid "Matrix object has no 'factors' slot" #~ msgstr "L'oggetto matrice non ha slot 'factors'" #~ msgid "'s1' and 's2' must be \"character\" vectors" #~ msgstr "'s1' e 's2' devono essere vettori di caratteri" #~ msgid "length of x slot != prod(Dim)" #~ msgstr "la lunghezza dello slot x != prod(Dim)" #~ msgid "Negative value in Dim" #~ msgid_plural "Negative values in Dim" #~ msgstr[0] "Valore negativo in Dim" #~ msgstr[1] "Valori negativi in Dim" #, c-format #~ msgid "%s is a list, but not of length 2" #~ msgstr "%s è una lista, ma non di lunghezza 2" #, c-format #~ msgid "invalid class '%s' to dup_mMatrix_as_geMatrix" #~ msgstr "classe '%s' to dup_mMatrix_as_geMatrix non valida" #, c-format #~ msgid "unexpected ctype = %d in dup_mMatrix_as_geMatrix" #~ msgstr "ctype inatteso = %d in dup_mMatrix_as_geMatrix" #~ msgid "lengths of slots i and j must match" #~ msgstr "le lunghezze degli slot i e j devono corrispondere" #~ msgid "slot Dim must have length 2" #~ msgstr "lo slot Dim deve avere lunghezza 2" #~ msgid "" #~ "all row indices (slot 'i') must be between 0 and nrow-1 in a TsparseMatrix" #~ msgstr "" #~ "tutti gli indici di riga (slot 'i') devono essere compresi tra 0 e nrow-1 " #~ "in una TsparseMatrix" #~ msgid "" #~ "all column indices (slot 'j') must be between 0 and ncol-1 in a " #~ "TsparseMatrix" #~ msgstr "" #~ "tutti gli indici di colonna (slot 'j') devono essere compresi tra 0 e " #~ "ncol-1 in una TsparseMatrix" #~ msgid "Supernodal LDL' decomposition not available" #~ msgstr "Decomposizione LDL Supernodal non disponibile" #~ msgid "Supernodal/simplicial class inconsistent with type flags" #~ msgstr "Classe sovranodale/simpliciale incompatibile con i flag di tipo" #~ msgid "Number of supernodes must be positive when is_super is TRUE" #~ msgstr "Il numero di supernodi dev'essere positivo quando is_super è TRUE" #~ msgid "Lengths of super and pi must be equal" #~ msgstr "Le lunghezze di super e pi devono essere uguali" #~ msgid "Lengths of super and px must be equal" #~ msgstr "Le lunghezze di super e px devono essere uguali" #, c-format #~ msgid "First call to Lapack routine dgels returned error code %d" #~ msgstr "" #~ "La prima chiamata alla routine Lapack dgels ha restituito il codice di " #~ "errore %d" #, c-format #~ msgid "Second call to Lapack routine dgels returned error code %d" #~ msgstr "" #~ "La seconda chiamata alla routine di Lapack dgels ha restituito il codice " #~ "di errore %d" #, c-format #~ msgid "tol, given as %g, must be non-negative" #~ msgstr "tol, indicato come %g, dev'essere non negativo" #, c-format #~ msgid "Second call to dgeqrf returned error code %d" #~ msgstr "La seconda chiamata a dgeqrf ha restituito il codice di errore %d" #, c-format #~ msgid "" #~ "dense_to_Csparse(): cholmod_l_dense_to_sparse failure status=%d" #~ msgstr "" #~ "dense_to_Csparse(): cholmod_l_dense_to_sparse riporta il seguente " #~ "errore=%d" #, c-format #~ msgid "" #~ "Matrix dimension %d x %d (= %g) too large [FIXME calling " #~ "cholmod_l_dense_to_sparse]" #~ msgstr "" #~ "Dimensione matrice %d x %d (= %g) troppo grande [RISOLVI chiamando " #~ "cholmod_l_dense_to_sparse]" #, c-format #~ msgid "Lower band %d > upper band %d" #~ msgstr "Banda inferiore %d > banda superiore %d" #~ msgid "ddense_to_symmetric(): matrix is not square!" #~ msgstr "ddense_to_symmetric(): la matrice non è quadrata!" #, c-format #~ msgid "matrix is not symmetric [%d,%d]" #~ msgstr "la matrice non è simmetrica [%d,%d]" #~ msgid "matrix is not square! (symmetric part)" #~ msgstr "la matrice non è quadrata! (parte simmetrica)" #~ msgid "matrix is not square! (skew-symmetric part)" #~ msgstr "la matrice non è quadrata! (parte obliqua-simmetrica))" #~ msgid "lengths of slots 'i' and 'x' must match" #~ msgstr "le lunghezze degli slot 'i' e 'x' devono corrispondere" #~ msgid "lengths of slots 'j' and 'x' must match" #~ msgstr "le lunghezze degli slot 'j' e 'x' devono corrispondere" #, c-format #~ msgid "invalid class(x) '%s' in compressed_to_TMatrix(x)" #~ msgstr "class(x) '%s' in compressed_to_TMatrix(x) non valida" #, c-format #~ msgid "invalid class(x) '%s' in R_to_CMatrix(x)" #~ msgstr "class(x) '%s' in R_to_CMatrix(x) non valida" #~ msgid "A must have #{rows} >= #{columns}" #~ msgstr "A deve avere #{righe} >= #{colonne}" #~ msgid "cs_sqr failed" #~ msgstr "cs_sqr fallita" #~ msgid "dgcMatrix_QR(*, keep_dimnames = NA): NA taken as TRUE" #~ msgstr "dgcMatrix_QR(*, keep_dimnames = NA): NA presi come TRUE" #~ msgid "LU decomposition applies only to square matrices" #~ msgstr "La decomposizione LU si applica solo alle matrici quadrate" #~ msgid "cs_lu(A) failed: near-singular A (or out of memory)" #~ msgstr "cs_lu(A) non riuscito: quasi singolare A (o memoria esaurita)" #~ msgid "dgcMatrix_LU(*, keep_dimnames = NA): NA taken as TRUE" #~ msgstr "dgcMatrix_LU(*, keep_dimnames = NA): NA presi come TRUE" #~ msgid "dgCMatrix_matrix_solve(.., sparse=TRUE) not yet implemented" #~ msgstr "dgCMatrix_matrix_solve(.., sparse=TRUE) non ancora implementato" #~ msgid "lengths of slots i and x must match" #~ msgstr "le lunghezze degli slot i e x devono corrispondere" #, c-format #~ msgid "too large matrix: %.0f" #~ msgstr "matrice troppo grande: %.0f" #, c-format #~ msgid "Cannot coerce to too large *geMatrix with %.0f entries" #~ msgstr "" #~ "Non è possibile la coercizione su una *geMatrix troppo grande con %.0f " #~ "voci" #~ msgid "x slot must be numeric \"double\"" #~ msgstr "lo slot x dev'essere un numerico \"double\"" #~ msgid "factors slot must be named list" #~ msgstr "lo slot dei fattori dev'essere una lista nominata" #~ msgid "rcond requires a square, non-empty matrix" #~ msgstr "rcond richiede una matrice quadrata, non vuota" #~ msgid "diagonal to be added has wrong length" #~ msgstr "la diagonale da aggiungere ha una lunghezza errata" #~ msgid "Cannot factor a matrix with zero extents" #~ msgstr "Non è possibile fattorizzare una matrice con zero estensioni" #, c-format #~ msgid "Exact singularity detected during LU decomposition: %s, i=%d." #~ msgstr "" #~ "Singolarità esatta rilevata durante la decomposizione LU: %s, i =%d." #~ msgid "Solve requires a square matrix" #~ msgstr "Solve richiede una matrice quadrata" #, c-format #~ msgid "error [%d] from Lapack 'dgecon()'" #~ msgstr "error [%d] da Lapack 'dgecon()'" #, c-format #~ msgid "" #~ "Lapack dgecon(): system computationally singular, reciprocal condition " #~ "number = %g" #~ msgstr "" #~ "Lapack dgecon(): sistema computazionalmente singolare, numero di " #~ "condizione reciproca =%g" #~ msgid "Lapack routine dgetri: system is exactly singular" #~ msgstr "Routine Lapack dgetri: il sistema è esattamente singolare" #~ msgid "dpoMatrix is not positive definite" #~ msgstr "dpoMatrix non è definita positiva" #~ msgid "Cannot solve() for matrices with zero extents" #~ msgstr "Non è possibile eseguire solve() per matrici con zero estensioni" #~ msgid "Argument b must be a numeric matrix" #~ msgstr "L'argomento b dev'essere una matrice numerica" #~ msgid "chm_factor_name(): did not get string of length 11" #~ msgstr "chm_factor_name(): non ha ottenuto una stringa di lunghezza 11" #~ msgid "" #~ "Cholesky factorization failed; unusually, please report to Matrix-authors" #~ msgstr "" #~ "Fattorizzazione di Cholesky fallita; insolitamente, per piacere " #~ "riportatelo agli autori del pacchetto" #~ msgid "internal_chm_factor: Cholesky factorization failed" #~ msgstr "internal_chm_factor: fattorizzazione Cholesky fallita" #~ msgid "Non-symmetric matrix passed to dsCMatrix_to_dgTMatrix" #~ msgstr "Matrice non simmetrica passata a dsCMatrix_to_dgTMatrix" #~ msgid "Incorrect length of 'x' slot" #~ msgstr "Lunghezza incorretta dello slot 'x'" #, c-format #~ msgid "Lapack routine dsytrf returned error code %d" #~ msgstr "La routine Lapack dsytrf ha restituito il codice di errore %d" #~ msgid "x must be a \"double\" (numeric) matrix" #~ msgstr "x dev'essere una matrice (numerica) \"double\"" #~ msgid "matrix_trf(x, *): matrix is not square" #~ msgstr "matrix_trf(x, *): la matrice non è quadrata" #~ msgid "matrix_trf(*, uplo): uplo must be string" #~ msgstr "matrix_trf(*, uplo): uplo dev'essere una stringa" #~ msgid "cannot set diag() as long as 'diag = \"U\"'" #~ msgstr "non è possibile impostare diag() purché 'diag = \"U\"'" #~ msgid "cannot add diag() as long as 'diag = \"U\"'" #~ msgstr "non è possibile aggiungere diag() purché 'diag = \"U\"'" #~ msgid "x slot is not of correct length" #~ msgstr "lo slot x non è della lunghezza corretta" #~ msgid "A must be a logical matrix" #~ msgstr "A dev'essere una matrice logica" #~ msgid "length(p) must match nrow(V)" #~ msgstr "length(p) deve corrispondere con nrow(V)" #~ msgid "length(beta) must match ncol(V)" #~ msgstr "length(beta) deve corrispondere con ncol(V)" #~ msgid "length(q) must be zero or ncol(R)" #~ msgstr "length(q) dev'essere zero o ncol(R)" #, c-format #~ msgid "sparseQR_Qmult(): nrow(y) = %d != %d = nrow(V)" #~ msgstr "sparseQR_Qmult(): nrow(y) = %d != %d = nrow(V)" #~ msgid "\"dtrMatrix\" objects in '%*%' must have matching (square) dimension" #~ msgstr "" #~ "gli oggetti \"dtrMatrix\" in '%*%' devono avere corrispondenti dimensioni " #~ "(quadrate)" Matrix/po/ko.po0000644000175100001440000016041514575137654013153 0ustar hornikusers# Korean translations for Matrix package. # Recommended/Matrix/po/ko.po # # Thanks to Martin Maechler # # This file is distributed under the same license as the R Matrix package. # Maintained by Chel Hee Lee , 2013-2015. # # Notes: # Freezing on 15-JUL-2015 for R-3.3.0, QC: PASS # Freezing on 30-MAR-2015 for R-3.2.0, QC: PASS # Freezing on 28-FEB-2015 for R-3.1.3, QC: PASS # msgid "" msgstr "" "Project-Id-Version: Matrix 1.1-3\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-14 15:49-0400\n" "PO-Revision-Date: 2015-07-15 17:14-0600\n" "Last-Translator:Chel Hee Lee \n" "Language-Team: Chel Hee Lee \n" "Language: ko\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #: Csparse.c:26 Csparse.c:61 Csparse.c:86 Csparse.c:113 Csparse.c:127 #: Csparse.c:132 Csparse.c:137 Csparse.c:411 #, fuzzy, c-format msgid "'%s' failed" msgstr "cs_qr 실패" #: Csparse.c:35 cholmod-common.c:54 #, fuzzy, c-format msgid "'%s' slot is not increasing within columns after sorting" msgstr "슬롯 j는 열(column)내에서 증가하지 않습니다" #: Csparse.c:57 #, fuzzy, c-format msgid "'%s' is empty or not square" msgstr "정방행렬이 아닙니다." #: Csparse.c:59 Csparse.c:81 Csparse.c:104 solve.c:43 solve.c:988 #, fuzzy, c-format msgid "dimensions of '%s' and '%s' are inconsistent" msgstr "Dimensions of system to be solved are inconsistent" #: Csparse.c:83 #, c-format msgid "%s(%s, %s) requires m-by-n '%s' with m >= n > 0" msgstr "" #: Csparse.c:106 #, c-format msgid "%s(%s, %s) requires m-by-n '%s' with n >= m > 0" msgstr "" #: Csparse.c:194 coerce.c:220 coerce.c:240 coerce.c:250 coerce.c:905 #: coerce.c:911 coerce.c:1015 coerce.c:1501 coerce.c:1521 coerce.c:1531 #: coerce.c:2061 coerce.c:2256 coerce.c:2262 coerce.c:2268 coerce.c:2397 #: coerce.c:2404 coerce.c:2494 coerce.c:2629 coerce.c:2707 coerce.c:2729 #: coerce.c:4327 coerce.c:4396 dense.c:696 matmult.c:939 matmult.c:1291 #: solve.c:719 solve.c:972 solve.c:1104 sparse.c:1234 sparse.c:1626 #, fuzzy, c-format msgid "invalid '%s' to '%s'" msgstr "'%s' 인자는 유효하지 않습니다" #: Csparse.c:409 #, fuzzy, c-format msgid "failed to open file \"%s\" for writing" msgstr "쓰기 위하여 파일 \"%s\"을 여는데 실패했습니다." #: attrib.c:229 #, fuzzy msgid "invalid factor name" msgstr "'%s' 인자는 유효하지 않습니다" #: attrib.c:233 #, c-format msgid "attempt to set factor on %s without '%s' slot" msgstr "" #: bind.c:46 bind.c:153 msgid "number of rows of matrices must match" msgstr "" #: bind.c:48 bind.c:155 msgid "number of columns of matrices must match" msgstr "" #: bind.c:51 bind.c:158 bind.c:182 bind.c:206 cholmod-common.c:608 #: cholmod-common.c:759 cholmod-common.c:874 cholmod-common.c:975 #: cholmod-etc.c:183 cholmod-etc.c:283 cholmod-etc.c:330 coerce.c:215 #: coerce.c:235 coerce.c:260 coerce.c:268 coerce.c:276 coerce.c:341 #: coerce.c:1496 coerce.c:1516 coerce.c:1543 coerce.c:1551 coerce.c:1559 #: matmult.c:28 matmult.c:50 matmult.c:56 #, c-format msgid "dimensions cannot exceed %s" msgstr "" #: bind.c:210 msgid "number of rows of result is not a multiple of vector length" msgstr "" #: bind.c:212 msgid "number of columns of result is not a multiple of vector length" msgstr "" #: bind.c:626 bind.c:691 sparse.c:913 sparse.c:994 #, c-format msgid "%s cannot exceed %s" msgstr "" #: bind.c:756 bind.c:853 cholmod-common.c:978 cholmod-etc.c:333 coerce.c:29 #: coerce.c:518 coerce.c:811 coerce.c:945 coerce.c:2772 coerce.c:3041 #: coerce.c:3146 dense.c:919 matmult.c:151 matmult.c:212 matmult.c:291 #: matmult.c:379 matmult.c:456 matmult.c:550 matmult.c:868 subscript.c:1232 #: subscript.c:1417 utils-R.c:32 #, c-format msgid "attempt to allocate vector of length exceeding %s" msgstr "" #: bind.c:858 matmult.c:1357 msgid "should never happen ..." msgstr "" #: cholmod-common.c:11 cholmod-common.c:34 validity.c:29 validity.c:150 #: validity.c:229 validity.c:248 validity.c:257 validity.c:299 validity.c:316 #: validity.c:350 validity.c:367 validity.c:401 validity.c:403 validity.c:439 #: validity.c:465 validity.c:485 validity.c:926 validity.c:959 validity.c:1041 #: validity.c:1061 validity.c:1127 validity.c:1129 validity.c:1177 #: validity.c:1240 validity.c:1242 validity.c:1288 validity.c:1335 #: validity.c:1384 validity.c:1417 validity.c:1427 validity.c:1440 #: validity.c:1494 validity.c:1496 validity.c:1528 validity.c:1540 #: validity.c:1563 validity.c:1626 validity.c:1645 validity.c:1647 #: validity.c:1679 validity.c:1714 validity.c:1742 #, fuzzy, c-format msgid "'%s' slot is not of type \"%s\"" msgstr "x 슬롯(slot)은 반드시 \"double\"형 숫자(numeric)이어야 합니다." #: cholmod-common.c:14 validity.c:274 validity.c:285 validity.c:301 #: validity.c:352 validity.c:487 validity.c:928 validity.c:961 validity.c:1063 #: validity.c:1131 validity.c:1179 validity.c:1244 validity.c:1290 #: validity.c:1429 validity.c:1446 validity.c:1498 validity.c:1500 #: validity.c:1530 validity.c:1542 validity.c:1565 validity.c:1681 #: validity.c:1718 validity.c:1746 validity.c:1796 #, fuzzy, c-format msgid "'%s' slot does not have length %s" msgstr "Dim 슬롯(slot)의 길이는 반드시 2이어야 합니다." #: cholmod-common.c:18 validity.c:304 validity.c:355 validity.c:1634 #: validity.c:1654 validity.c:1656 #, fuzzy, c-format msgid "first element of '%s' slot is not 0" msgstr "슬롯 p의 첫번째 요소는 반드시 0 이어야 합니다. " #: cholmod-common.c:23 cholmod-common.c:46 validity.c:34 validity.c:308 #: validity.c:326 validity.c:359 validity.c:377 validity.c:413 validity.c:415 #: validity.c:491 validity.c:1008 validity.c:1020 validity.c:1067 #: validity.c:1140 validity.c:1152 validity.c:1253 validity.c:1265 #: validity.c:1294 validity.c:1345 validity.c:1394 validity.c:1433 #: validity.c:1453 validity.c:1534 validity.c:1550 validity.c:1575 #: validity.c:1639 validity.c:1659 validity.c:1661 validity.c:1688 #, c-format msgid "'%s' slot contains NA" msgstr "" #: cholmod-common.c:26 validity.c:310 validity.c:361 #, fuzzy, c-format msgid "'%s' slot is not nondecreasing" msgstr "슬롯 p는 반드시 감소하지 않아야(non-decreasing) 합니다." #: cholmod-common.c:29 validity.c:312 validity.c:363 #, c-format msgid "first differences of '%s' slot exceed %s" msgstr "" #: cholmod-common.c:37 validity.c:318 validity.c:369 #, fuzzy, c-format msgid "'%s' slot has length less than %s" msgstr "'Dim'은 2 보다 짧은 슬롯의 길이를 가지고 있습니다." #: cholmod-common.c:49 validity.c:328 validity.c:379 validity.c:417 #: validity.c:420 validity.c:493 validity.c:1010 validity.c:1069 #: validity.c:1142 validity.c:1154 validity.c:1255 validity.c:1267 #: validity.c:1347 validity.c:1396 validity.c:1455 validity.c:1577 #: validity.c:1690 #, fuzzy, c-format msgid "'%s' slot has elements not in {%s}" msgstr "'Dim'은 2 보다 짧은 슬롯의 길이를 가지고 있습니다." #: cholmod-common.c:165 cholmod-common.c:296 cholmod-common.c:1072 #: cholmod-common.c:1075 cholmod-common.c:1108 cholmod-common.c:1126 #, fuzzy, c-format msgid "'%s' failed in '%s'" msgstr "cs_qr 실패" #: cholmod-common.c:212 #, fuzzy, c-format msgid "'%s' failed in '%s': %s" msgstr "cs_qr 실패" #: cholmod-common.c:601 cholmod-common.c:604 cholmod-common.c:606 #: cholmod-common.c:752 cholmod-common.c:755 cholmod-common.c:757 #: cholmod-common.c:867 cholmod-common.c:870 cholmod-common.c:872 #: cholmod-common.c:969 cholmod-common.c:971 cholmod-etc.c:177 #: cholmod-etc.c:179 cholmod-etc.c:181 cholmod-etc.c:277 cholmod-etc.c:279 #: cholmod-etc.c:281 cholmod-etc.c:324 cholmod-etc.c:326 cs-etc.c:43 #, c-format msgid "wrong '%s'" msgstr "" #: cholmod-common.c:611 cholmod-etc.c:186 #, fuzzy, c-format msgid "'%s' would overflow type \"%s\"" msgstr "x 슬롯(slot)은 반드시 \"double\"형 숫자(numeric)이어야 합니다." #: cholmod-common.c:615 cholmod-etc.c:190 #, c-format msgid "n+1 would overflow type \"%s\"" msgstr "" #: cholmod-common.c:620 cholmod-etc.c:195 #, fuzzy, c-format msgid "leading principal minor of order %d is not positive" msgstr "the leading minor of order %d is not positive definite" #: cholmod-common.c:623 cholmod-etc.c:198 #, fuzzy, c-format msgid "leading principal minor of order %d is zero" msgstr "the leading minor of order %d is not positive definite" #: cholmod-common.c:973 cholmod-etc.c:328 msgid "leading dimension not equal to number of rows" msgstr "" #: cholmod-common.c:1037 #, c-format msgid "" "invalid simplicial Cholesky factorization: structural zero on main diagonal " "in column %d" msgstr "" #: cholmod-common.c:1097 #, fuzzy, c-format msgid "CHOLMOD error '%s' at file '%s', line %d" msgstr "Cholmod error '%s' at file %s, line %d" #: cholmod-common.c:1100 #, fuzzy, c-format msgid "CHOLMOD warning '%s' at file '%s', line %d" msgstr "Cholmod warning '%s' at file %s, line %d" #: coerce.c:24 coerce.c:364 coerce.c:1050 #, fuzzy, c-format msgid "attempt to construct non-square %s" msgstr "행렬식(determinant)를 얻기 위해서는 정방행렬을 사용해야 합니다." #: coerce.c:186 coerce.c:476 coerce.c:1467 coerce.c:1622 #, c-format msgid "second argument of '%s' does not specify a subclass of %s" msgstr "" #: coerce.c:194 coerce.c:200 coerce.c:484 coerce.c:490 coerce.c:925 #: coerce.c:1475 coerce.c:1481 coerce.c:1630 coerce.c:1636 coerce.c:2275 #: coerce.c:3344 coerce.c:3349 #, fuzzy, c-format msgid "'%s' must be \"%s\" or \"%s\"" msgstr "'%s'는 반드시 '%s'내에 있어야 합니다." #: coerce.c:246 coerce.c:496 coerce.c:793 coerce.c:917 coerce.c:1527 #: coerce.c:1642 dense.c:322 dense.c:1102 dense.c:1678 dense.c:1683 #: dense.c:1929 dense.c:2124 sparse.c:784 sparse.c:2449 sparse.c:3141 #: sparse.c:3146 sparse.c:3151 sparse.c:3427 sparse.c:3664 #, fuzzy, c-format msgid "'%s' must be %s or %s" msgstr "'%s'는 반드시 '%s'내에 있어야 합니다." #: coerce.c:266 coerce.c:274 coerce.c:285 coerce.c:1549 coerce.c:1557 #: coerce.c:1568 msgid "nonempty vector supplied for empty matrix" msgstr "" #: coerce.c:287 coerce.c:1570 #, c-format msgid "vector length (%lld) exceeds matrix length (%d * %d)" msgstr "" #: coerce.c:290 coerce.c:1573 #, c-format msgid "matrix length (%d * %d) is not a multiple of vector length (%lld)" msgstr "" #: coerce.c:521 #, c-format msgid "coercing n-by-n %s to %s is not supported for n*n exceeding %s" msgstr "" #: coerce.c:525 coerce.c:815 coerce.c:949 #, c-format msgid "sparse->dense coercion: allocating vector of size %0.1f GiB" msgstr "" #: coerce.c:1196 coerce.c:1941 coerce.c:2948 coerce.c:2954 #, c-format msgid "attempt to construct %s with more than %s nonzero entries" msgstr "" #: coerce.c:3246 #, fuzzy msgid "attempt to pack non-square matrix" msgstr "행렬식(determinant)를 얻기 위해서는 정방행렬을 사용해야 합니다." #: coerce.c:3420 coerce.c:3590 #, c-format msgid "unable to aggregate %s with '%s' and '%s' slots of length exceeding %s" msgstr "" #: coerce.c:4211 #, fuzzy, c-format msgid "attempt to pack a %s" msgstr "행렬식(determinant)를 얻기 위해서는 정방행렬을 사용해야 합니다." #: coerce.c:4330 dense.c:1232 sparse.c:2580 #, fuzzy, c-format msgid "'%s' must be %s or %s or %s" msgstr "'%s'는 반드시 '%s'내에 있어야 합니다." #: dense.c:210 dense.c:215 sparse.c:590 sparse.c:595 #, fuzzy, c-format msgid "'%s' (%d) must be an integer from %s (%d) to %s (%d)" msgstr "'%s'는 반드시 '%s'내에 있어야 합니다." #: dense.c:218 sparse.c:598 #, fuzzy, c-format msgid "'%s' (%d) must be less than or equal to '%s' (%d)" msgstr "'%s'는 반드시 '%s'내에 있어야 합니다." #: dense.c:428 sparse.c:1070 #, c-format msgid "replacement diagonal has incompatible type \"%s\"" msgstr "" #: dense.c:437 sparse.c:1079 msgid "replacement diagonal has wrong length" msgstr "" #: dense.c:622 sparse.c:1275 #, fuzzy msgid "attempt to symmetrize a non-square matrix" msgstr "행렬식(determinant)를 얻기 위해서는 정방행렬을 사용해야 합니다." #: dense.c:721 sparse.c:1653 msgid "attempt to get symmetric part of non-square matrix" msgstr "" #: dense.c:873 sparse.c:2083 msgid "attempt to get skew-symmetric part of non-square matrix" msgstr "" #: dense.c:1673 sparse.c:3136 #, fuzzy, c-format msgid "'%s' must be %d or %d" msgstr "'%s'는 반드시 '%s'내에 있어야 합니다." #: dense.c:2156 #, c-format msgid "incorrect left cyclic shift, j (%d) < 0" msgstr "incorrect left cyclic shift, j (%d) < 0" #: dense.c:2159 #, c-format msgid "incorrect left cyclic shift, j (%d) >= k (%d)" msgstr "incorrect left cyclic shift, j (%d) >= k (%d)" #: dense.c:2162 #, c-format msgid "incorrect left cyclic shift, k (%d) > ldx (%d)" msgstr "incorrect left cyclic shift, k (%d) > ldx (%d)" #: dense.c:2215 #, fuzzy msgid "unknown error in getGivens" msgstr "getGivens에서 알 수 없는 에러가 발생했습니다" #: dense.c:2224 dense.c:2238 dense.c:2268 msgid "X must be a numeric (double precision) matrix" msgstr "X는 반드시 double precision을 가진 수치형 행렬이어야 합니다." #: dense.c:2240 dense.c:2270 msgid "y must be a numeric (double precision) matrix" msgstr "y는 반드시 double precision을 가진 수치형 행렬이어야 합니다." #: dense.c:2244 dense.c:2274 #, c-format msgid "number of rows in y (%d) does not match number of rows in X (%d)" msgstr "y가 가진 행의 개수 (%d)가 X가 가진 행의 개수 (%d)와 일치하지 않습니다." #: dense.c:2260 #, fuzzy, c-format msgid "LAPACK dposv returned error code %d" msgstr "다음의 에러코드가 Lapack 루틴 dposv으로부터 반환되었습니다: %d" #: dense.c:2288 dense.c:2294 #, fuzzy, c-format msgid "LAPACK dgels returned error code %d" msgstr "에러코드 %2$d는 Lapack 루틴 %1$s로부터 얻어졌습니다." #: dense.c:2313 msgid "X must be a real (numeric) matrix" msgstr "X는 반드시 실수(real)형 숫자를 가진 행렬이어야 합니다." #: dense.c:2316 #, fuzzy, c-format msgid "tol, given as %g, must be >= 0" msgstr "tol의 값은 1보다 작거나 같아야 하는데 %g를 가지고 있습니다." #: dense.c:2318 #, c-format msgid "tol, given as %g, must be <= 1" msgstr "tol의 값은 1보다 작거나 같아야 하는데 %g를 가지고 있습니다." #: dense.c:2347 dense.c:2355 #, fuzzy, c-format msgid "LAPACK dgeqrf returned error code %d" msgstr "dgeqrf에 첫번째 호출로부터 다음과 같은 에러코드가 반환되었습니다: %d" #: dense.c:2360 dense.c:2383 #, fuzzy, c-format msgid "LAPACK dtrcon returned error code %d" msgstr "에러코드 %d가 Lapack 루틴 dtrcon으로부터 반환되었습니다." #: determinant.c:33 #, fuzzy msgid "determinant of non-square matrix is undefined" msgstr "행렬식(determinant)를 얻기 위해서는 정방행렬을 사용해야 합니다." #: determinant.c:276 #, fuzzy, c-format msgid "%s(<%s>) does not support structurally rank deficient case" msgstr "%s(): 구조적으로 계수에 문제가 있는 경우입니다: possibly WRONG zeros" #: expm.c:39 msgid "Matrix exponential requires square, non-null matrix" msgstr "행렬의 지수(exponential)은 정방이고 non-null인 행렬이어야 합니다" #: expm.c:56 expm.c:58 #, c-format msgid "dgeMatrix_exp: LAPACK routine dgebal returned %d" msgstr "dgeMatrix_exp: %d가 LAPACK 루틴 dgebal로부터 반환되었습니다." #: expm.c:96 #, c-format msgid "dgeMatrix_exp: dgetrf returned error code %d" msgstr "dgeMatrix_exp: 에러코드 %d가 dgetrf로부터 반환되었습니다." #: expm.c:98 #, c-format msgid "dgeMatrix_exp: dgetrs returned error code %d" msgstr "dgeMatrix_exp: 에러코드 %d가 dgetrs로부터 반환되었습니다." #: factor.c:330 msgid "dgeMatrix_Schur: argument x must be a non-null square matrix" msgstr "" "dgeMatrix_Schur: 인자 x는 반드시 null이 아닌 정방(square)행렬이어야 합니다." #: factor.c:343 msgid "dgeMatrix_Schur: first call to dgees failed" msgstr "dgeMatrix_Schur: dgees로의 첫번째 호출에 실패했습니다" #: factor.c:352 #, c-format msgid "dgeMatrix_Schur: dgees returned code %d" msgstr "dgeMatrix_Schur: 코드 %d가 dgees로부터 반환되었습니다." #: factor.c:403 sparse.c:196 #, fuzzy, c-format msgid "'%s' is not a number" msgstr "정방행렬이 아닙니다." #: factor.c:424 #, c-format msgid "LU factorization of m-by-n %s requires m == n" msgstr "" #: factor.c:433 #, c-format msgid "LU factorization of %s failed: out of memory or near-singular" msgstr "" #: factor.c:510 #, c-format msgid "QR factorization of m-by-n %s requires m >= n" msgstr "" #: factor.c:519 #, c-format msgid "QR factorization of %s failed: out of memory" msgstr "" #: factor.c:619 factor.c:897 #, c-format msgid "'%s' is not a number or not finite" msgstr "" #: idz.c:467 idz.c:528 #, c-format msgid "incompatible '%s' and '%s' in '%s'" msgstr "" #: kappa.c:10 kappa.c:54 #, fuzzy, c-format msgid "argument '%s' is not of type \"%s\"" msgstr "인자 type[1]='%s'는 반드시 길이가 1인 문자이어야 합니다." #: kappa.c:13 kappa.c:57 #, fuzzy, c-format msgid "argument '%s' has length %d" msgstr "'%s'는 반드시 길이가 1인 문자열(string)이어야 합니다." #: kappa.c:17 kappa.c:61 #, fuzzy, c-format msgid "argument '%s' (\"%s\") does not have string length %d" msgstr "'%s'는 반드시 길이가 1인 문자열(string)이어야 합니다." #: kappa.c:41 #, c-format msgid "" "argument '%s' (\"%s\") is not \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", or " "\"%s\"" msgstr "" #: kappa.c:75 #, fuzzy, c-format msgid "argument '%s' (\"%s\") is not \"%s\", \"%s\", or \"%s\"" msgstr "'%s'는 반드시 길이가 1인 문자열(string)이어야 합니다." #: kappa.c:238 #, c-format msgid "%s(%s) is undefined: '%s' is not square" msgstr "" #: matmult.c:107 matmult.c:210 matmult.c:289 matmult.c:377 matmult.c:454 #: matmult.c:548 matmult.c:812 matmult.c:862 msgid "non-conformable arguments" msgstr "" #: matmult.c:782 matmult.c:810 #, c-format msgid "'%s' does not support complex matrices" msgstr "" #: objects.c:23 #, c-format msgid "unexpected type \"%s\" in '%s'" msgstr "" #: objects.c:41 objects.c:58 #, c-format msgid "unexpected kind \"%c\" in '%s'" msgstr "" #: perm.c:26 perm.c:106 msgid "attempt to get sign of non-permutation" msgstr "" #: perm.c:51 perm.c:123 msgid "attempt to invert non-permutation" msgstr "" #: perm.c:66 #, fuzzy msgid "invalid transposition vector" msgstr "%d번째 위치에서 유효하지 않은 행인덱스가 있습니다" #: perm.c:79 perm.c:81 perm.c:96 perm.c:98 perm.c:113 perm.c:133 perm.c:145 #, fuzzy, c-format msgid "'%s' is not of type \"%s\"" msgstr "x 슬롯(slot)은 반드시 \"double\"형 숫자(numeric)이어야 합니다." #: perm.c:83 perm.c:100 perm.c:147 #, fuzzy, c-format msgid "'%s' does not have length %d" msgstr "슬롯 '%s'의 길이는 반드시 1이어야 합니다." #: perm.c:86 perm.c:103 #, c-format msgid "'%s' is NA" msgstr "" #: perm.c:115 perm.c:138 #, fuzzy, c-format msgid "'%s' or '%s' is not of type \"%s\"" msgstr "x 슬롯(slot)은 반드시 \"double\"형 숫자(numeric)이어야 합니다." #: perm.c:117 perm.c:140 #, fuzzy, c-format msgid "'%s' or '%s' does not have length %d" msgstr "슬롯 '%s'의 길이는 반드시 1이어야 합니다." #: perm.c:120 perm.c:143 #, c-format msgid "'%s' or '%s' is NA" msgstr "" #: perm.c:136 #, c-format msgid "'%s' has length exceeding %s" msgstr "" #: perm.c:150 #, c-format msgid "'%s' is NA or less than %s" msgstr "" #: solve.c:38 #, fuzzy, c-format msgid "'%s' is not square" msgstr "정방행렬이 아닙니다." #: solve.c:497 #, c-format msgid "%s(<%s>, <%s>) failed: out of memory" msgstr "" #: solve.c:618 #, fuzzy, c-format msgid "attempt to construct %s with more than %s nonzero elements" msgstr "행렬식(determinant)를 얻기 위해서는 정방행렬을 사용해야 합니다." #: subscript.c:1542 subscript.c:1695 subscript.c:1938 subscript.c:2122 #, c-format msgid "%s too dense for %s; would have more than %s nonzero entries" msgstr "" #: subscript.c:2209 #, c-format msgid "NA subscripts in %s not supported for '%s' inheriting from %s" msgstr "" #: t_subassign.c:141 msgid "invalid class of 'x' in Csparse_subassign()" msgstr "Csparse_subassign()에서 사용되는 'x'의 클래스가 올바르지 않습니다." #: t_subassign.c:143 msgid "invalid class of 'value' in Csparse_subassign()" msgstr "Csparse_subassign()에서 사용되는 'value'의 클래스가 올바르지 않습니다." #: t_subassign.c:186 #, c-format msgid "x[] <- val: val is coerced to logical for \"%s\" x" msgstr "x[] <- val: val is coerced to logical for \"%s\" x" #: t_subassign.c:191 #, c-format msgid "" "x[] <- val: val should be integer or logical, is coerced to integer, for " "\"%s\" x" msgstr "" "x[] <- val: val should be integer or logical, is coerced to integer, for " "\"%s\" x" #: t_subassign.c:198 msgid "programming error in Csparse_subassign() should never happen" msgstr "" "Csparse_subassign()를 사용 중 발생하지 말아야 하는 프로그래밍 에러" "(programming error)가 발견되었습니다." #: utils-R.c:30 utils-R.c:116 #, c-format msgid "indices would exceed %s" msgstr "" #: utils-R.c:235 utils-R.c:270 utils-R.c:281 utils-R.c:312 msgid "Argument must be numeric-like atomic vector" msgstr "인자는 반드시 수치형과 같은 기본형 벡터이어야합니다" #: utils-R.c:345 msgid "'data' must be of a vector type" msgstr "'data'는 반드시 벡터형(vector type)이어야 합니다." #: utils-R.c:352 #, c-format msgid "invalid '%s' argument" msgstr "'%s' 인자는 유효하지 않습니다" #: utils-R.c:359 utils-R.c:367 msgid "non-numeric matrix extent" msgstr "non-numeric matrix extent" #: utils-R.c:362 msgid "invalid 'nrow' value (too large or NA)" msgstr "'nrow'의 값이 너무 크거나 NA이므로 올바르지 않습니다." #: utils-R.c:364 msgid "invalid 'nrow' value (< 0)" msgstr "'nrow'의 값이 0 보다 작으므로 올바르지 않습니다." #: utils-R.c:370 msgid "invalid 'ncol' value (too large or NA)" msgstr "'ncol'의 값이 너무 크거나 NA이므로 올바르지 않습니다." #: utils-R.c:372 msgid "invalid 'ncol' value (< 0)" msgstr "'ncol'의 값이 0보다 작으므로 올바르지 않습니다." #: utils-R.c:390 #, fuzzy, c-format msgid "" "data length [%lld] is not a sub-multiple or multiple of the number of rows " "[%d]" msgstr "데이터의 길이[%d]가 행의 개수[%d]의 약수 또는 배수가 아닙니다" #: utils-R.c:395 #, fuzzy, c-format msgid "" "data length [%lld] is not a sub-multiple or multiple of the number of " "columns [%d]" msgstr "데이터의 길이[%d]가 열의 개수[%d]의 약수 또는 배수가 아닙니다" #: utils-R.c:399 msgid "data length exceeds size of matrix" msgstr "데이터의 길이(data length)가 행렬의 크기(size of matrix)를 초과합니다." #: utils-R.c:404 msgid "too many elements specified" msgstr "너무 많은 요소들이 지정되었습니다" #: utils-R.c:545 msgid "Argument ij must be 2-column integer matrix" msgstr "인자 ij는 반드시 2개의 열을 가진 정수형 행렬이어야 합니다." #: utils-R.c:570 msgid "subscript 'i' out of bounds in M[ij]" msgstr "첨자 'i'가 M[ij]내에 존재하지 않습니다." #: utils-R.c:572 msgid "subscript 'j' out of bounds in M[ij]" msgstr "첨자 'j'가 M[ij]내에 존재하지 않습니다." #: utils-R.c:626 msgid "i and j must be integer vectors of the same length" msgstr "" "i와 j는 반드시 같은 길이를 가지는 정수형 벡터(integer vectors)이어야 합니다." #: validity.c:31 validity.c:52 validity.c:231 validity.c:250 validity.c:259 #: validity.c:441 validity.c:467 validity.c:977 validity.c:1419 validity.c:1443 #, fuzzy, c-format msgid "'%s' slot does not have length %d" msgstr "Dim 슬롯(slot)의 길이는 반드시 2이어야 합니다." #: validity.c:36 validity.c:932 validity.c:965 #, fuzzy, c-format msgid "'%s' slot has negative elements" msgstr "'Dim'은 2 보다 짧은 슬롯의 길이를 가지고 있습니다." #: validity.c:50 validity.c:164 #, fuzzy, c-format msgid "'%s' slot is not a list" msgstr "x 슬롯(slot)은 반드시 \"double\"형 숫자(numeric)이어야 합니다." #: validity.c:68 #, fuzzy, c-format msgid "%s[[%d]] is not NULL or a vector" msgstr "'s1'과 's2'는 반드시 \"character\"형 벡터이어야 합니다." #: validity.c:71 #, c-format msgid "length of %s[[%d]] (%lld) is not equal to %s[%d] (%d)" msgstr "" #: validity.c:170 #, c-format msgid "'%s' slot has no '%s' attribute" msgstr "" #: validity.c:181 validity.c:244 validity.c:435 validity.c:506 validity.c:1082 #: validity.c:1413 validity.c:1774 #, c-format msgid "%s[1] != %s[2] (matrix is not square)" msgstr "" #: validity.c:206 validity.c:219 #, c-format msgid "%s[1] differs from %s[2]" msgstr "" #: validity.c:234 validity.c:253 validity.c:262 validity.c:444 #, fuzzy, c-format msgid "'%s' slot is not \"%s\" or \"%s\"" msgstr "x 슬롯(slot)은 반드시 \"double\"형 숫자(numeric)이어야 합니다." #: validity.c:331 validity.c:1580 #, fuzzy, c-format msgid "'%s' slot is not increasing within columns" msgstr "슬롯 j는 열(column)내에서 증가하지 않습니다" #: validity.c:382 #, fuzzy, c-format msgid "'%s' slot is not increasing within rows" msgstr "슬롯 j는 열(column)내에서 증가하지 않습니다" #: validity.c:406 validity.c:790 validity.c:816 validity.c:842 validity.c:1043 #: validity.c:1649 validity.c:1651 #, fuzzy, c-format msgid "'%s' and '%s' slots do not have equal length" msgstr "Dim 슬롯(slot)의 길이는 반드시 2이어야 합니다." #: validity.c:409 #, c-format msgid "'%s' slot has nonzero length but %s is 0" msgstr "" #: validity.c:450 validity.c:454 #, fuzzy, c-format msgid "'%s' slot is \"%s\" but '%s' slot does not have length %s" msgstr "Dim 슬롯(slot)의 길이는 반드시 2이어야 합니다." #: validity.c:470 #, fuzzy, c-format msgid "'%s' slot is not %d or %d" msgstr "x 슬롯(slot)은 반드시 \"double\"형 숫자(numeric)이어야 합니다." #: validity.c:476 validity.c:479 #, c-format msgid "%s-by-%s %s invalid for positive '%s' when %s=%d" msgstr "" #: validity.c:516 validity.c:1145 validity.c:1157 validity.c:1258 #: validity.c:1270 validity.c:1350 validity.c:1399 validity.c:1458 #, c-format msgid "'%s' slot contains duplicates" msgstr "" #: validity.c:544 validity.c:589 validity.c:635 validity.c:680 validity.c:724 #: validity.c:759 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries below the diagonal" msgstr "uplo='U'의 경우에는 어떠한 값들도 대각의 아랫부분에 있어서는 안됩니다." #: validity.c:554 validity.c:602 validity.c:645 validity.c:693 validity.c:729 #: validity.c:770 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries above the diagonal" msgstr "uplo='L'의 경우는 어떠한 값들도 대각의 윗부분에 있어서는 안됩니다." #: validity.c:592 validity.c:605 validity.c:683 validity.c:696 validity.c:762 #: validity.c:773 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries on the diagonal" msgstr "uplo='U'의 경우에는 어떠한 값들도 대각의 아랫부분에 있어서는 안됩니다." #: validity.c:878 validity.c:902 validity.c:906 msgid "matrix has negative diagonal elements" msgstr "" #: validity.c:922 validity.c:950 validity.c:954 msgid "matrix has nonunit diagonal elements" msgstr "" #: validity.c:974 validity.c:999 validity.c:1793 #, fuzzy, c-format msgid "'%s' slot is not of type \"%s\" or \"%s\"" msgstr "x 슬롯(slot)은 반드시 \"double\"형 숫자(numeric)이어야 합니다." #: validity.c:982 validity.c:989 #, fuzzy, c-format msgid "'%s' slot is NA" msgstr "x 슬롯(slot)은 반드시 \"double\"형 숫자(numeric)이어야 합니다." #: validity.c:984 validity.c:991 #, fuzzy, c-format msgid "'%s' slot is negative" msgstr "'Dim'은 2 보다 짧은 슬롯의 길이를 가지고 있습니다." #: validity.c:993 #, fuzzy, c-format msgid "'%s' slot exceeds %s" msgstr "'%s'는 반드시 '%s'내에 있어야 합니다." #: validity.c:1003 #, fuzzy, c-format msgid "'%s' slot has length greater than '%s' slot" msgstr "'Dim'은 2 보다 짧은 슬롯의 길이를 가지고 있습니다." #: validity.c:1013 validity.c:1641 validity.c:1663 validity.c:1665 #, fuzzy, c-format msgid "'%s' slot is not increasing" msgstr "슬롯 j는 열(column)내에서 증가하지 않습니다" #: validity.c:1023 #, fuzzy, c-format msgid "'%s' slot has elements not in {%s} after truncation towards zero" msgstr "'Dim'은 2 보다 짧은 슬롯의 길이를 가지고 있습니다." #: validity.c:1026 #, fuzzy, c-format msgid "'%s' slot is not increasing after truncation towards zero" msgstr "슬롯 j는 열(column)내에서 증가하지 않습니다" #: validity.c:1092 validity.c:1119 validity.c:1781 validity.c:1788 #, fuzzy, c-format msgid "dimensions of '%s' slot are not identical to '%s'" msgstr "x와 y의 차원정보가 %s와 일치하지 않습니다." #: validity.c:1094 #, c-format msgid "'%s' slot is upper (not lower) triangular" msgstr "" #: validity.c:1107 #, c-format msgid "'%s' slot has nonunit diagonal elements" msgstr "" #: validity.c:1121 #, c-format msgid "'%s' slot is lower (not upper) triangular" msgstr "" #: validity.c:1133 validity.c:1246 validity.c:1337 validity.c:1386 #, fuzzy, c-format msgid "'%s' slot does not have length %s or length %s" msgstr "Dim 슬롯(slot)의 길이는 반드시 2이어야 합니다." #: validity.c:1173 msgid "matrix has more columns than rows" msgstr "" #: validity.c:1193 #, fuzzy, c-format msgid "'%s' slot has fewer than %s rows" msgstr "'Dim'은 2 보다 짧은 슬롯의 길이를 가지고 있습니다." #: validity.c:1195 #, fuzzy, c-format msgid "'%s' slot has more than %s rows" msgstr "'Dim'은 2 보다 짧은 슬롯의 길이를 가지고 있습니다." #: validity.c:1197 validity.c:1219 #, fuzzy, c-format msgid "'%s' slot does not have %s columns" msgstr "Dim 슬롯(slot)의 길이는 반드시 2이어야 합니다." #: validity.c:1204 #, fuzzy, c-format msgid "'%s' slot must be lower trapezoidal but has entries above the diagonal" msgstr "uplo='L'의 경우는 어떠한 값들도 대각의 윗부분에 있어서는 안됩니다." #: validity.c:1217 #, fuzzy, c-format msgid "'%s' slot does not have %s row" msgstr "Dim 슬롯(slot)의 길이는 반드시 2이어야 합니다." #: validity.c:1226 #, fuzzy, c-format msgid "'%s' slot must be upper trapezoidal but has entries below the diagonal" msgstr "uplo='U'의 경우에는 어떠한 값들도 대각의 아랫부분에 있어서는 안됩니다." #: validity.c:1230 #, c-format msgid "'%s' slot has negative diagonal elements" msgstr "" #: validity.c:1296 #, c-format msgid "'%s' slot has elements not in {%s}\\{%s}" msgstr "" #: validity.c:1305 #, c-format msgid "'%s' slot has unpaired negative elements" msgstr "" #: validity.c:1331 validity.c:1375 validity.c:1379 validity.c:1727 #: validity.c:1759 msgid "Cholesky factor has negative diagonal elements" msgstr "" #: validity.c:1422 #, c-format msgid "%s[%d] (%s) is not in %s" msgstr "" #: validity.c:1435 validity.c:1536 #, c-format msgid "%s is not in {%s}" msgstr "" #: validity.c:1472 #, c-format msgid "%s is not representable as \"%s\"" msgstr "" #: validity.c:1477 validity.c:1483 #, c-format msgid "%s[%d] (%s) is not %d or %d" msgstr "" #: validity.c:1480 validity.c:1596 validity.c:1599 validity.c:1602 #, c-format msgid "%s[%d] (%s) is not %d" msgstr "" #: validity.c:1505 #, c-format msgid "%s has elements not in {%s}" msgstr "" #: validity.c:1508 #, c-format msgid "%s has elements not in {%s}\\{%s}" msgstr "" #: validity.c:1511 #, c-format msgid "%s is %d but columns are not stored in increasing order" msgstr "" #: validity.c:1514 validity.c:1517 #, c-format msgid "traversal of '%s' slot does not complete in exactly %s steps" msgstr "" #: validity.c:1523 validity.c:1525 #, c-format msgid "%s is not %d" msgstr "" #: validity.c:1546 #, c-format msgid "column '%s' is stored first but %s is not 0" msgstr "" #: validity.c:1552 #, fuzzy, c-format msgid "'%s' slot is not increasing when traversed in stored column order" msgstr "슬롯 j는 열(column)내에서 증가하지 않습니다" #: validity.c:1554 #, c-format msgid "'%s' slot allocates fewer than %s elements for column '%s'" msgstr "" #: validity.c:1557 #, c-format msgid "'%s' slot allocates more than %s elements for column '%s'" msgstr "" #: validity.c:1571 #, c-format msgid "first entry in column '%s' does not have row index '%s'" msgstr "" #: validity.c:1605 validity.c:1608 #, c-format msgid "%s[%d] (%s) is negative" msgstr "" #: validity.c:1611 #, c-format msgid "%s[%d] (%s) is not less than %s" msgstr "" #: validity.c:1629 #, fuzzy, c-format msgid "'%s' slot has length less than %d" msgstr "'Dim'은 2 보다 짧은 슬롯의 길이를 가지고 있습니다." #: validity.c:1631 #, fuzzy, c-format msgid "'%s' slot has length greater than %s" msgstr "'Dim'은 2 보다 짧은 슬롯의 길이를 가지고 있습니다." #: validity.c:1636 #, fuzzy, c-format msgid "last element of '%s' slot is not %s" msgstr "슬롯 p의 첫번째 요소는 반드시 0 이어야 합니다. " #: validity.c:1669 #, c-format msgid "first differences of '%s' slot are less than those of '%s' slot" msgstr "" #: validity.c:1672 #, c-format msgid "supernode lengths exceed %s" msgstr "" #: validity.c:1674 #, c-format msgid "first differences of '%s' slot are not equal to supernode lengths" msgstr "" #: validity.c:1694 #, c-format msgid "" "'%s' slot is wrong within diagonal blocks (row and column indices do not " "coincide)" msgstr "" #: validity.c:1697 #, fuzzy, c-format msgid "'%s' slot is not increasing within supernodes" msgstr "슬롯 j는 열(column)내에서 증가하지 않습니다" #: validity.c:1812 #, fuzzy, c-format msgid "invalid class \"%s\" object: %s" msgstr "invalid class of object to %s" #: vector.c:90 #, c-format msgid "%s length cannot exceed %s" msgstr "" #, c-format #~ msgid "diagonal element %d of Cholesky factor is missing" #~ msgstr "콜레스키 분해(Cholesky factor)의 대각요소 %d를 찾을 수 없습니다" #, c-format #~ msgid "cholmod_factorize_p failed: status %d, minor %d of ncol %d" #~ msgstr "cholmod_factorize_p failed: status %d, minor %d of ncol %d" #~ msgid "cholmod_change_factor failed" #~ msgstr "cholmod_change_factor failed" #~ msgid "cholmod_write_sparse returned error code" #~ msgstr "cholmod_write_sparse가 에러코드를 반환하였습니다." #, c-format #~ msgid "%s = '%s' (back-permuted) is experimental" #~ msgstr "%s = '%s' (back-permuted)는 실험단계에 있습니다" #~ msgid "diag_tC(): invalid 'resultKind'" #~ msgstr "diag_tC(): 유효한 'resultKind'가 아닙니다" #, fuzzy #~ msgid "complex matrices are not yet supported" #~ msgstr "complex sparse matrix code not yet written" #~ msgid "Argument rho must be an environment" #~ msgstr "인자 rho는 반드시 인바이런먼트(environment)이어야 합니다." #~ msgid "invalid class of object to as_cholmod_sparse" #~ msgstr "as_cholmod_sparse에 전달된 객체가 올바르지 않습니다." #~ msgid "invalid object passed to as_cholmod_sparse" #~ msgstr "as_cholmod_sparse에 전달된 객체가 올바르지 않습니다." #~ msgid "in_place cholmod_sort returned an error code" #~ msgstr "in_place cholmod_sort returned an error code" #~ msgid "cholmod_sort returned an error code" #~ msgstr "에러코드가 cholmod_sort로부터 반환되었습니다." #~ msgid "chm_sparse_to_SEXP(, *): invalid 'Rkind' (real kind code)" #~ msgstr "chm_sparse_to_SEXP(, *): invalid 'Rkind' (real kind code)" #~ msgid "unknown xtype in cholmod_sparse object" #~ msgstr "cholmod_sparse 객체에 사용할 수 있는 xtype이 아닙니다." #~ msgid "complex sparse matrix code not yet written" #~ msgstr "complex sparse matrix code not yet written" #~ msgid "Symmetric and triangular both set" #~ msgstr "Symmetric and triangular both set" #~ msgid "invalid class of object to as_cholmod_triplet" #~ msgstr "as_cholmod_triplet에 전달된 객체의 클래스가 올바르지 않습니다." #~ msgid "as_cholmod_triplet(): could not reallocate for internal diagU2N()" #~ msgstr "as_cholmod_triplet(): could not reallocate for internal diagU2N()" #~ msgid "unknown xtype in cholmod_triplet object" #~ msgstr "cholmod_triplet 객체에서 사용할 수 있는 xtype이 아닙니다." #~ msgid "invalid class of object to as_cholmod_dense" #~ msgstr "as_cholmod_dense에 전달된 객체의 클래스가 올바르지 않습니다." #, c-format #~ msgid "Unable to initialize cholmod: error code %d" #~ msgstr "cholmod를 초기화 할 수 없습니다: 에러코드 %d" #~ msgid "unknown 'Rkind'" #~ msgstr "사용할 수 있는 'Rkind'이 아닙니다." #~ msgid "unknown xtype" #~ msgstr "사용할 수 있는 xtype이 아닙니다." #~ msgid "code for cholmod_dense with holes not yet written" #~ msgstr "code for cholmod_dense with holes not yet written" #~ msgid "don't know if a dense pattern matrix makes sense" #~ msgstr "don't know if a dense pattern matrix makes sense" #, fuzzy #~ msgid "object of invalid class to 'as_cholmod_factor()'" #~ msgstr "invalid class of object to as_cholmod_factor" #~ msgid "failure in as_cholmod_factor" #~ msgstr "failure in as_cholmod_factor" #~ msgid "CHOLMOD factorization was unsuccessful" #~ msgstr "CHOLMOD factorization was unsuccessful" #, c-format #~ msgid "f->xtype of %d not recognized" #~ msgstr "f->xtype of %d not recognized" #, c-format #~ msgid "chm_diagN2U(): nrow=%d, ncol=%d" #~ msgstr "chm_diagN2U(): nrow=%d, ncol=%d" #, c-format #~ msgid "chm_diagN2U(x, uploT = %d): uploT should be +- 1" #~ msgstr "chm_diagN2U(x, uploT = %d): uploT은 반드시 1 또는 -1이어야 합니다" #~ msgid "dgCMatrix_lusol requires a square, non-empty matrix" #~ msgstr "" #~ "dgCMatrix_lusol은 정방(square)이며 비어있지 않은(non-empty) 행렬을 필요로 " #~ "합니다." #~ msgid "Dimensions of system to be solved are inconsistent" #~ msgstr "Dimensions of system to be solved are inconsistent" #~ msgid "cs_lusol failed" #~ msgstr "cs_lusol 실패" #~ msgid "dgCMatrix_qrsol(., order) needs order in {0,..,3}" #~ msgstr "dgCMatrix_qrsol(., order) needs order in {0,..,3}" #, c-format #~ msgid "" #~ "dgCMatrix_qrsol(<%d x %d>-matrix) requires a 'tall' rectangular matrix" #~ msgstr "" #~ "dgCMatrix_qrsol(<%d x %d>-matrix)은 'tall' 사각행렬(rectangular matrix)이 " #~ "필요합니다." #~ msgid "cs_qrsol() failed inside dgCMatrix_qrsol()" #~ msgstr "dgCMatrix_qrsol()의 내에서 cs_qrsol()이 실패했습니다" #~ msgid "dgCMatrix_cholsol requires a 'short, wide' rectangular matrix" #~ msgstr "dgCMatrix_cholsol requires a 'short, wide' rectangular matrix" #~ msgid "cholmod_sdmult error (rhs)" #~ msgstr "cholmod_sdmult error (rhs)" #, c-format #~ msgid "cholmod_factorize failed: status %d, minor %d from ncol %d" #~ msgstr "cholmod_factorize 실패: 상태 %d, minor %d from ncol %d" #, c-format #~ msgid "cholmod_solve (CHOLMOD_A) failed: status %d, minor %d from ncol %d" #~ msgstr "cholmod_solve (CHOLMOD_A) 실패: 상태 %d, minor %d from ncol %d" #~ msgid "cholmod_sdmult error (resid)" #~ msgstr "cholmod_sdmult error (resid)" #~ msgid "SuiteSparseQR_C_QR returned an error code" #~ msgstr "에러코드가 SuiteSparseQR_C_QR로부터 반환되었습니다." #, fuzzy, c-format #~ msgid "LAPACK routine '%s': matrix is exactly singular, %s[i,i]=0, i=%d" #~ msgstr "Lapack 루틴 dgetrs: 시스템(system)이 정확하게 특이(singular)합니다." #, fuzzy, c-format #~ msgid "" #~ "LAPACK routine '%s': leading principal minor of order %d is not positive" #~ msgstr "the leading minor of order %d is not positive definite" #, fuzzy #~ msgid "missing 'Matrix' namespace; should never happen" #~ msgstr "" #~ "'Matrix' 네임스페이스(namespace)를 찾을 수 없습니다. 반드시 존재해야 합니" #~ "다 " #, fuzzy #~ msgid "'Matrix' namespace not determined correctly" #~ msgstr "올바르게 정의된 Matrix 네임스페이스(namespace)가 아닙니다" #~ msgid "Csparse_sort(x): x is not a valid (apart from sorting) CsparseMatrix" #~ msgstr "" #~ "Csparse_sort(x): x is not a valid (apart from sorting) CsparseMatrix" #~ msgid "csp_eye argument n must be positive" #~ msgstr "csp_eye의 인자 n은 반드시 양수이어야 합니다" #~ msgid "invalid class of 'x' in Matrix_as_cs(a, x)" #~ msgstr "Matrix_as_cs(a, x)에 입력된 'x'의 클래스가 올바르지 않습니다." #, c-format #~ msgid "invalid class of object to %s" #~ msgstr "invalid class of object to %s" #, c-format #~ msgid "cs matrix not compatible with class '%s'" #~ msgstr "cs matrix not compatible with class '%s'" #, c-format #~ msgid "Inappropriate class cl='%s' in Matrix_css_to_SEXP(S, cl, ..)" #~ msgstr "" #~ "Matrix_css_to_SEXP(S, cl, ..)에 입력된 cl='%s'은 올바른 클래스가 아닙니다." #, c-format #~ msgid "Inappropriate class cl='%s' in Matrix_csn_to_SEXP(S, cl, ..)" #~ msgstr "" #~ "Matrix_csn_to_SEXP(S, cl, ..)에 입력된 cl='%s'는 올바른 클래스가 아닙니다." #, c-format #~ msgid "Dimensions of x and y are not compatible for %s" #~ msgstr "x와 y의 차원정보가 %s와 일치하지 않습니다." #~ msgid "Argument y must be numeric, integer or logical" #~ msgstr "인자 y는 반드시 수치형, 정수형, 또는 논리형이어야 합니다." #~ msgid "Matrices are not conformable for multiplication" #~ msgstr "곱셈연산을 할 수 있는 행렬들이 아닙니다" #~ msgid "dtrMatrix must be square" #~ msgstr "dtrMatrix는 정방행렬이 아닙니다." #, c-format #~ msgid "Dimensions of a (%d,%d) and b (%d,%d) do not conform" #~ msgstr "a (%d,%d)와 b (%d,%d)의 크기가 서로 일치하지 않습니다." #~ msgid "right=TRUE is not yet implemented __ FIXME" #~ msgstr "right=TRUE의 경우는 아직 구현되지 않았습니다 __ FIXME" #, c-format #~ msgid "cholmod_change_factor failed with status %d" #~ msgstr "cholmod_change_factor가 실패했으며 상태 %d를 가집니다" #~ msgid "system argument is not valid" #~ msgstr "시스템 인자가 올바르지 않습니다" #, c-format #~ msgid "cholmod_updown() returned %d" #~ msgstr "%d가 cholmod_updown()로부터 반환되었습니다" #~ msgid "cholmod_drop() failed" #~ msgstr "cholmod_drop() failed" #, fuzzy #~ msgid "'off' does not have length 1" #~ msgstr "슬롯 '%s'의 길이는 반드시 1이어야 합니다." #, fuzzy #~ msgid "invalid 'code' to 'R_matrix_as_dense()'" #~ msgstr "dup_mMatrix_as_dgeMatrix에 올바르지 않은 클래스 '%s'입니다" #, fuzzy #~ msgid "invalid 'uplo' to 'R_matrix_as_dense()'" #~ msgstr "dup_mMatrix_as_dgeMatrix에 올바르지 않은 클래스 '%s'입니다" #, fuzzy #~ msgid "invalid 'diag' to 'R_matrix_as_dense()'" #~ msgstr "dup_mMatrix_as_dgeMatrix에 올바르지 않은 클래스 '%s'입니다" #, fuzzy #~ msgid "invalid argument 'system'" #~ msgstr "'%s' 인자는 유효하지 않습니다" #, fuzzy #~ msgid "dimensions of 'qr' and 'y' are inconsistent" #~ msgstr "Dimensions of system to be solved are inconsistent" #, fuzzy #~ msgid "invalid 'op'" #~ msgstr "'%s' 인자는 유효하지 않습니다" #, fuzzy #~ msgid "'names' must be TRUE or FALSE" #~ msgstr "'uplo'는 반드시 UPP 또는 LOW이어야 합니다." #~ msgid "Csparse_crossprod(): error return from cholmod_aat()" #~ msgstr "Csparse_crossprod(): cholmod_aat()로부터 에러가 반환되었습니다" #, fuzzy #~ msgid "invalid 'kind' to 'R_sparse_as_kind()'" #~ msgstr "Csparse_subassign()에서 사용되는 'x'의 클래스가 올바르지 않습니다." #~ msgid "slot p must have length = nrow(.) + 1" #~ msgstr "슬롯 p는 반드시 nrow(.) + 1의 길이(length)를 가져야 합니다." #~ msgid "last element of slot p must match length of slots j and x" #~ msgstr "슬롯 p의 마지막 요소는 반드시 슬롯 j 와 x의 길이와 일치해야 합니다." #~ msgid "all column indices must be between 0 and ncol-1" #~ msgstr "모든 열 인덱스는 반드시 0 부터 ncol-1 사이의 값이어야 합니다." #~ msgid "slot j is not *strictly* increasing inside a column" #~ msgstr "슬롯 j는 열(column)내에서 *단조*증가하지 않습니다" #~ msgid "not a 'n.CMatrix'" #~ msgstr "'n.CMatrix'이 아닙니다. " #, c-format #~ msgid "nz2Csparse(): invalid/non-implemented r_kind = %d" #~ msgstr "nz2Csparse(): 유효하지 않거나 구현되지 않은 r_kind = %d입니다" #~ msgid "Nonsymmetric matrix in Csparse_symmetric_to_general" #~ msgstr "Csparse_symmetric_to_general에 비대칭행렬이 사용되었습니다" #~ msgid "Csparse_general_to_symmetric(): matrix is not square!" #~ msgstr "Csparse_general_to_symmetric(): 정방행렬이 아닙니다!" #~ msgid "Index i must be NULL or integer" #~ msgstr "인덱스 i는 반드시 NULL 또는 정수(integer)이어야 합니다." #~ msgid "Index j must be NULL or integer" #~ msgstr "인덱스 j는 반드시 NULL 또는 정수(integer)이어야 합니다." #, c-format #~ msgid "negative vector lengths not allowed: np = %d, nnz = %d" #~ msgstr "벡터의 길이가 음수입니다: np = %d, nnz = %d" #~ msgid "exactly 1 of 'i', 'j' or 'p' must be NULL" #~ msgstr "'i', 'j', 또는 'p' 중의 하나만이 반드시 NULL 이어야 합니다." #, c-format #~ msgid "np = %d, must be zero when p is NULL" #~ msgstr "p가 NULL인 경우에는 반드시 np의 값은 0이어야 하는데 %d 입니다." #, c-format #~ msgid "p[0] = %d, should be zero" #~ msgstr "p[0]의 값은 0 이어야 하는데 %d 를 가집니다." #~ msgid "p must be non-decreasing" #~ msgstr "p는 반드시 감소하지 않아야(non-decreasing) 합니다." #, c-format #~ msgid "Inconsistent dimensions: np = 0 and nnz = %d" #~ msgstr "차원정보가 일치하지 않습니다: np = 0 그리고 nnz = %d" #, c-format #~ msgid "invalid column index at position %d" #~ msgstr "%d번째 위치에서 유효하지 않은 열인덱스가 있습니다" #, c-format #~ msgid "strlen of cls argument = %d, should be 8" #~ msgstr "cls의 strlen 인자의 길이는 8 이어야 하는데 %d 입니다." #, c-format #~ msgid "cls = \"%s\" does not end in \"CMatrix\"" #~ msgstr "cls = \"%s\" does not end in \"CMatrix\"" #, c-format #~ msgid "cls = \"%s\" must begin with 'd', 'l' or 'n'" #~ msgstr "cls = \"%s\"는 반드시 'd', 'l' 또는 'n'으로 시작해야 합니다." #~ msgid "Only 'g'eneral sparse matrix types allowed" #~ msgstr "Only 'g'eneral sparse matrix types allowed" #~ msgid "code not yet written for cls = \"lgCMatrix\"" #~ msgstr "아직은 cls = \"lgCMatrix\"을 위하여 작성된 코드가 아닙니다" #, fuzzy, c-format #~ msgid "%s must be (traditional R) matrix" #~ msgstr "A는 반드시 논리형 행렬(logical matrix)이어야 합니다." #, fuzzy, c-format #~ msgid "%s must be character string" #~ msgstr "'s1'과 's2'는 반드시 \"character\"형 벡터이어야 합니다." #, fuzzy, c-format #~ msgid "strlen of cls argument = %d, should be 9" #~ msgstr "cls의 strlen 인자의 길이는 8 이어야 하는데 %d 입니다." #, fuzzy, c-format #~ msgid "cls = \"%s\" must begin with 'd', 'l' or 'n' for now" #~ msgstr "cls = \"%s\"는 반드시 'd', 'l' 또는 'n'으로 시작해야 합니다." #, fuzzy, c-format #~ msgid "%s must be a logical or double vector" #~ msgstr "A는 반드시 논리형 행렬(logical matrix)이어야 합니다." #, c-format #~ msgid "argument type[1]='%s' must be one of 'M','1','O','I','F' or 'E'" #~ msgstr "" #~ "인자 type[1]='%s'은 반드시 'M','1','O','I','F' 또는 'E' 중 하나의 값을 가" #~ "져야 합니다." #, c-format #~ msgid "argument type[1]='%s' must be one of '1','O', or 'I'" #~ msgstr "" #~ "인자 type[1]='%s'은 반드시 '1', '0', 또는 'I' 중 하나의 값을 가져야 합니" #~ "다." #~ msgid "object must be a named, numeric vector" #~ msgstr "객체는 반드시 원소에 이름이 주어진 수치형 벡터이어야 합니다." #~ msgid "'factors' slot must be a named list" #~ msgstr "'factors' 슬롯은 반드시 이름이 주어진 리스트이어야 합니다" #~ msgid "Matrix object has no 'factors' slot" #~ msgstr "행렬의 객체가 'factors' 슬롯을 가지고 있지 않습니다" #~ msgid "'s1' and 's2' must be \"character\" vectors" #~ msgstr "'s1'과 's2'는 반드시 \"character\"형 벡터이어야 합니다." #~ msgid "length of x slot != prod(Dim)" #~ msgstr "x 슬롯의 길이가 prod(Dim)과 같지 않습니다." #~ msgid "Negative value in Dim" #~ msgid_plural "Negative values in Dim" #~ msgstr[0] "Dim 안에 음수가 있습니다." #, c-format #~ msgid "invalid class '%s' to dup_mMatrix_as_geMatrix" #~ msgstr "dup_mMatrix_as_geMatrix에 올바르지 않은 클래스 '%s'입니다" #, c-format #~ msgid "unexpected ctype = %d in dup_mMatrix_as_geMatrix" #~ msgstr "" #~ "dup_mMatrix_as_geMatrix에 사용할 수 없는 ctype = %d가 입력되었습니다." #~ msgid "lengths of slots i and j must match" #~ msgstr "슬롯 i의 길이와 슬롯 j의 길이는 반드시 일치해야 합니다." #~ msgid "slot Dim must have length 2" #~ msgstr "슬롯 Dim의 길이는 반드시 2이어야 합니다." #~ msgid "" #~ "all row indices (slot 'i') must be between 0 and nrow-1 in a TsparseMatrix" #~ msgstr "" #~ "TsparseMatrix에 사용되는 모든 행에 대한 인덱스 (슬롯 'i')는 반드시 0과 " #~ "nrow-1 사이에 존재하는 정수이어야 합니다." #~ msgid "" #~ "all column indices (slot 'j') must be between 0 and ncol-1 in a " #~ "TsparseMatrix" #~ msgstr "" #~ "TsparseMatrix에 사용되는 모든 열에 대한 인덱스 (슬롯 'j')는 반드시 0과 " #~ "ncol-1 사이에 존재하는 정수이어야 합니다." #~ msgid "Supernodal LDL' decomposition not available" #~ msgstr "Supernodal LDL' decomposition not available" #~ msgid "Supernodal/simplicial class inconsistent with type flags" #~ msgstr "Supernodal/simplicial class inconsistent with type flags" #~ msgid "Number of supernodes must be positive when is_super is TRUE" #~ msgstr "" #~ "is_super가 TRUE인 경우에 supernodes의 개수는 반드시 양수이어야 합니다." #~ msgid "Lengths of super and pi must be equal" #~ msgstr "super의 길이와 pi의 길이는 반드시 서로 같아야 합니다." #~ msgid "Lengths of super and px must be equal" #~ msgstr "super의 길이와 px의 길이는 반드시 서로 같아야 합니다." #, c-format #~ msgid "First call to Lapack routine dgels returned error code %d" #~ msgstr "" #~ "Lapack 루틴 dgels에 첫번째 호출로부터 다음과 같은 에러코드가 반환되었습니" #~ "다: %d" #, c-format #~ msgid "Second call to Lapack routine dgels returned error code %d" #~ msgstr "" #~ "Lapack 루틴 dgels에 두번째 호출로부터 다음과 같은 에러코드가 반환되었습니" #~ "다: %d" #, c-format #~ msgid "tol, given as %g, must be non-negative" #~ msgstr "tol의 값은 음이 아닌 수이어야 하는데 %g를 가지고 있습니다." #, c-format #~ msgid "Second call to dgeqrf returned error code %d" #~ msgstr "" #~ "dgeqrf에 두번째 호출로부터 다음과 같은 에러코드가 반환되었습니다: %d" #, c-format #~ msgid "Lower band %d > upper band %d" #~ msgstr "Lower band %d > upper band %d" #~ msgid "ddense_to_symmetric(): matrix is not square!" #~ msgstr "ddense_to_symmetric(): 정방행렬이 아닙니다!" #, c-format #~ msgid "matrix is not symmetric [%d,%d]" #~ msgstr "행렬이 대칭(symmetric)적이지 않습니다 [%d,%d]." #~ msgid "matrix is not square! (symmetric part)" #~ msgstr "정방행렬이 아닙니다! (symmetric part)" #~ msgid "matrix is not square! (skew-symmetric part)" #~ msgstr "정방행렬이 아닙니다! (skew-symmetric part)" #~ msgid "lengths of slots 'i' and 'x' must match" #~ msgstr "슬롯 'i'의 길이와 슬롯 'x'의 길이는 반드시 일치해야 합니다." #~ msgid "lengths of slots 'j' and 'x' must match" #~ msgstr "슬롯 'j'의 길이와 슬롯 'x'의 길이는 반드시 일치해야 합니다." #, c-format #~ msgid "invalid class(x) '%s' in compressed_to_TMatrix(x)" #~ msgstr "" #~ "compressed_to_TMatrix(x) 내에 유효하지 않은 class(x) '%s'가 존재합니다" #, c-format #~ msgid "invalid class(x) '%s' in R_to_CMatrix(x)" #~ msgstr "R_to_CMatrix(x) 내에 유효하지 않은 class(x) '%s'가 존재합니다." #~ msgid "A must have #{rows} >= #{columns}" #~ msgstr "A는 반드시 #{rows} >= #{columns}을 만족해야 합니다." #~ msgid "cs_sqr failed" #~ msgstr "cs_sqr 실패" #~ msgid "LU decomposition applies only to square matrices" #~ msgstr "LU 분해(decomposition)은 오로지 정방행렬에만 적용됩니다." #~ msgid "cs_lu(A) failed: near-singular A (or out of memory)" #~ msgstr "cs_lu(A) failed: near-singular A (or out of memory)" #~ msgid "dgCMatrix_matrix_solve(.., sparse=TRUE) not yet implemented" #~ msgstr "dgCMatrix_matrix_solve(.., sparse=TRUE)은 아직 구현되지 않았습니다" #~ msgid "lengths of slots i and x must match" #~ msgstr "슬롯 i의 길이와 슬롯 x의 길이는 서로 일치해야 합니다." #, c-format #~ msgid "Cannot coerce to too large *geMatrix with %.0f entries" #~ msgstr "Cannot coerce to too large *geMatrix with %.0f entries" #~ msgid "x slot must be numeric \"double\"" #~ msgstr "x 슬롯(slot)은 반드시 \"double\"형 숫자(numeric)이어야 합니다." #~ msgid "factors slot must be named list" #~ msgstr "factors slot must be named list" #~ msgid "rcond requires a square, non-empty matrix" #~ msgstr "rcond는 비어있지 않은 정방행렬이어야 합니다." #~ msgid "Cannot factor a matrix with zero extents" #~ msgstr "Cannot factor a matrix with zero extents" #~ msgid "Solve requires a square matrix" #~ msgstr "Solve를 이용하기 위해서는 정방행렬을 사용해야 합니다." #, c-format #~ msgid "error [%d] from Lapack 'dgecon()'" #~ msgstr "Lapack 'dgecon()'으로부터 에러 [%d]가 발생하였습니다." #, c-format #~ msgid "" #~ "Lapack dgecon(): system computationally singular, reciprocal condition " #~ "number = %g" #~ msgstr "" #~ "Lapack dgecon(): 시스템이 계산적으로 특이하며, 역상태수(reciprocal " #~ "condition number) %g를 가집니다" #~ msgid "Lapack routine dgetri: system is exactly singular" #~ msgstr "Lapack 루틴 dgetri: 시스템(system)이 정확하게 특이(singular)합니다." #~ msgid "dpoMatrix is not positive definite" #~ msgstr "dpoMatrix는 양정치(positive definite)가 아닙니다." #~ msgid "Cannot solve() for matrices with zero extents" #~ msgstr "크기가 0인 행렬에 solve()를 사용할 수 없습니다" #~ msgid "Argument b must be a numeric matrix" #~ msgstr "인자 b는 반드시 수치형 행렬(numeric matrix)이어야 합니다." #~ msgid "chm_factor_name(): did not get string of length 11" #~ msgstr "chm_factor_name(): 길이가 11인 문자열을 가지지 못했습니다" #~ msgid "" #~ "Cholesky factorization failed; unusually, please report to Matrix-authors" #~ msgstr "" #~ "콜레스키 분해에 실패했습니다. Matrix 패키지의 저자에게 보고해 주시길 부탁" #~ "드립니다 " #~ msgid "internal_chm_factor: Cholesky factorization failed" #~ msgstr "internal_chm_factor: 콜레스키 분해에 실패했습니다" #~ msgid "Non-symmetric matrix passed to dsCMatrix_to_dgTMatrix" #~ msgstr "dsCMatrix_to_dgTMatrix에 비대칭 행렬이 전달되었습니다" #~ msgid "Incorrect length of 'x' slot" #~ msgstr "'x' 슬롯의 길이가 올바르지 않습니다." #, c-format #~ msgid "Lapack routine dsytrf returned error code %d" #~ msgstr "Lapack 루틴 dsytrl로부터 다음의 에러코드가 반환되었습니다: %d" #, fuzzy #~ msgid "x must be a \"double\" (numeric) matrix" #~ msgstr "X는 반드시 실수(real)형 숫자를 가진 행렬이어야 합니다." #, fuzzy #~ msgid "matrix_trf(x, *): matrix is not square" #~ msgstr "ddense_to_symmetric(): 정방행렬이 아닙니다!" #~ msgid "cannot set diag() as long as 'diag = \"U\"'" #~ msgstr "'diag = \"U\"'이기 때문에 diag()를 정할 수 없습니다." #~ msgid "cannot add diag() as long as 'diag = \"U\"'" #~ msgstr "'diag = \"U\"'이기 때문에 diag()를 추가할 수 없습니다." #~ msgid "A must be a logical matrix" #~ msgstr "A는 반드시 논리형 행렬(logical matrix)이어야 합니다." #~ msgid "length(p) must match nrow(V)" #~ msgstr "length(p)는 반드시 nrow(V)와 일치해야 합니다." #~ msgid "length(beta) must match ncol(V)" #~ msgstr "length(beta)는 반드시 ncol(V)와 일치해야 합니다." #~ msgid "length(q) must be zero or ncol(R)" #~ msgstr "length(q)는 반드시 0 또는 ncol(R)이어야 합니다." #, c-format #~ msgid "sparseQR_Qmult(): nrow(y) = %d != %d = nrow(V)" #~ msgstr "sparseQR_Qmult(): nrow(y) = %d != %d = nrow(V)" #~ msgid "\"dtrMatrix\" objects in '%*%' must have matching (square) dimension" #~ msgstr "" #~ "\"dtrMatrix\" objects in '%*%' must have matching (square) dimension" #~ msgid "not a CsparseMatrix" #~ msgstr "CsparseMatrix가 아닙니다." Matrix/po/R-pl.po0000644000175100001440000022153514575137654013355 0ustar hornikusersmsgid "" msgstr "" "Project-Id-Version: Matrix 1.1-2-2\n" "Report-Msgid-Bugs-To: bugs.r-project.org\n" "POT-Creation-Date: 2024-03-15 17:22\n" "PO-Revision-Date: 2014-03-27 14:47+0100\n" "Last-Translator: Łukasz Daniel \n" "Language-Team: Łukasz Daniel \n" "Language: pl_PL\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" "X-Poedit-SourceCharset: iso-8859-1\n" "X-Generator: Poedit 1.5.4\n" # Matrix/R/Auxiliaries.R: 23 # stop(gettextf("invalid 'mod': %s", mod), domain = "R-Matrix") # Matrix/R/Auxiliaries.R: 26 # stop(gettextf("invalid 'mod': %s", mod), domain = "R-Matrix") #, fuzzy msgid "invalid mode \"%s\"" msgstr "niepoprawne 'mod': %s" msgid "" "%s(<%s>, <%s>) is not yet implemented; ask maintainer(\"%s\") to implement " "the missing method" msgstr "" # Matrix/R/sparseVector.R: 278 # stop(gettextf("Class %s is not yet implemented", dQuote(cNam)), domain = "R-Matrix") #, fuzzy msgid "complex %s not yet implemented" msgstr "Klasa %s nie jest jeszcze zaimplementowana" # Matrix/R/ngTMatrix.R: 24 # stop("cannot coerce 'NA's to \"nsparseMatrix\"") #, fuzzy msgid "cannot coerce matrix of type \"%s\" to %s" msgstr "nie można przekształcić wartości 'NA' na 'nsparseMatrix'" # Matrix/R/Auxiliaries.R: 641 # stop(gettextf("not yet implemented for class %s", dQuote(class.x)), domain = "R-Matrix") #, fuzzy msgid "non0.i() not yet implemented for class %s" msgstr "jeszcze niezaimplementowane dla klasy %s" msgid "%s=\"%s\" invalid for %s@uplo=\"%s\"" msgstr "" msgid "'%s' is not \"%1$s\", \"D%1$s\", or \"%1$s.\"" msgstr "" # Matrix/R/diagMatrix.R: 528 # stop("chol() is undefined for diagonal matrix with negative entries") #, fuzzy msgid "%1$s(%2$s) is undefined: '%2$s' is not positive semidefinite" msgstr "" "'chol()' jest nieokreślona dla macierzy diagonalnych z ujemnymi wpisami" # Matrix/R/diagMatrix.R: 358 # stop("matrix is not diagonal") #, fuzzy msgid "matrix is not square" msgstr "macierz nie jest diagonalna" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", \"%3$s.\", \"%3$s1\", \"%3$s1." "\", or \"%4$s\"" msgstr "" # Matrix/R/sparseVector.R: 235 # stop("'x' must inherit from \"sparseVector\"") #, fuzzy msgid "'%s' does not inherit from virtual class %s" msgstr "argument 'x' musi być obiektem klasy \"sparseVector\"" msgid "D[i,i] is NA, i=%d" msgstr "" msgid "D[i,i] is negative, i=%d" msgstr "" msgid "'%1$s' is not formally symmetric; factorizing tcrossprod(%1$s)" msgstr "" msgid "unexpected %s=\"%s\" in '%s' method" msgstr "" # Matrix/R/HBMM.R: 13 # stop("Not a valid format") msgid "Not a valid format" msgstr "Niepoprawny format" # Matrix/R/HBMM.R: 33 # stop("'file' must be a character string or connection") # Matrix/R/HBMM.R: 82 # stop("'file' must be a character string or connection") msgid "'file' must be a character string or connection" msgstr "'file' musi być łańcuchem tekstowym lub połączeniem" # Matrix/R/HBMM.R: 47 # stop(gettextf("Invalid storage type: %s", t1), domain = "R-Matrix") msgid "Invalid storage type: %s" msgstr "Niepoprawny typ przechowywania: %s" # Matrix/R/HBMM.R: 48 # stop("Only numeric sparse matrices allowed") msgid "Only numeric sparse matrices allowed" msgstr "Dozwolone są jedynie liczbowe rzadkie macierze" # Matrix/R/HBMM.R: 51 # stop(gettextf("Invalid storage format: %s", t2), domain = NA) msgid "Invalid storage format: %s" msgstr "Niepoprawny format przechowywania: %s" # Matrix/R/HBMM.R: 53 # stop(gettextf("Invalid assembled indicator: %s", t3), domain = "R-Matrix") msgid "Invalid assembled indicator: %s" msgstr "Niepoprawnie złożony wskaźnik: %s" # Matrix/R/HBMM.R: 91 # stop("file is not a MatrixMarket file") msgid "file is not a MatrixMarket file" msgstr "plik nie jest plikiem typu 'MatrixMarket'" # Matrix/R/HBMM.R: 93 # stop(gettextf("type '%s' not recognized", typ), domain = "R-Matrix") msgid "type '%s' not recognized" msgstr "typ '%s' nie został rozpoznany" # Matrix/R/HBMM.R: 95 # stop(gettextf("representation '%s' not recognized", repr), domain = "R-Matrix") msgid "representation '%s' not recognized" msgstr "reprezentacja '%s' nie została rozpoznana" # Matrix/R/HBMM.R: 98 # stop(gettextf("element type '%s' not recognized", elt), domain = "R-Matrix") msgid "element type '%s' not recognized" msgstr "element typu '%s' nie został rozpoznany" # Matrix/R/HBMM.R: 102 # stop(gettextf("symmetry form '%s' not recognized", sym), domain = "R-Matrix") msgid "symmetry form '%s' not recognized" msgstr "forma symetryczna '%s' nie została rozpoznana" msgid "readMM(): expected %d entries but found only %d" msgstr "" #, fuzzy msgid "readMM(): row indices 'i' are not in 1:nrow[=%d]" msgstr "readMM(): wartości wiersza 'i' nie są w przedziale 1:nr" # Matrix/R/HBMM.R: 110 # stop("readMM(): column values 'j' are not in 1:nc", call.=FALSE) #, fuzzy msgid "readMM(): column indices 'j' are not in 1:ncol[=%d]" msgstr "readMM(): wartości kolumny 'j' nie są w przedziale 1:nc" # Matrix/R/HBMM.R: 131 # stop("symmetry form 'skew-symmetric' not yet implemented for reading") # Matrix/R/HBMM.R: 158 # stop("symmetry form 'skew-symmetric' not yet implemented for reading") msgid "symmetry form 'skew-symmetric' not yet implemented for reading" msgstr "" "forma symetryczna 'skew-symmetric' nie jest jeszcze zaimplementowana na " "potrzeby odczytu" # Matrix/R/HBMM.R: 138 # stop("symmetry form 'hermitian' not yet implemented for reading") # Matrix/R/HBMM.R: 165 # stop("symmetry form 'hermitian' not yet implemented for reading") msgid "symmetry form 'hermitian' not yet implemented for reading" msgstr "" "forma symetryczna 'hermitian' nie jest jeszcze zaimplementowana na potrzeby " "odczytu" # Matrix/R/HBMM.R: 141 # stop(gettextf("symmetry form '%s' is not yet implemented", sym), domain = "R-Matrix") # Matrix/R/HBMM.R: 168 # stop(gettextf("symmetry form '%s' is not yet implemented", sym), domain = "R-Matrix") msgid "symmetry form '%s' is not yet implemented" msgstr "forma symetryczna '%s' nie jest jeszcze zaimplementowana" # Matrix/R/HBMM.R: 172 # stop("element type 'complex' not yet implemented") msgid "element type 'complex' not yet implemented" msgstr "typ elementu 'complex' nie jest jeszcze zaimplementowany" # Matrix/R/HBMM.R: 175 # stop(sprintf(gettext("'%s()' is not yet implemented for element type '%s'", domain = "R-Matrix"), "readMM", elt), domain = NA) msgid "'%s()' is not yet implemented for element type '%s'" msgstr "'%s()' nie jest jeszcze zaimplementowany dla typu '%s' elementu" # Matrix/R/HBMM.R: 178 # stop(sprintf(gettext("'%s()' is not yet implemented for representation '%s'", domain = "R-Matrix"), "readMM", repr), domain = NA) msgid "'%s()' is not yet implemented for representation '%s'" msgstr "'%s()' nie jest jeszcze zaimplementowane dla reprezentacji '%s'" # Matrix/R/Ops.R: 1117 # warning("longer object length\n\tis not a multiple of shorter object length") # Matrix/R/Ops.R: 1512 # warning("longer object length\n\tis not a multiple of shorter object length") # Matrix/R/Ops.R: 1604 # warning("longer object length\n\tis not a multiple of shorter object length") # Matrix/R/Ops.R: 1630 # warning("longer object length\n\tis not a multiple of shorter object length") msgid "longer object length is not a multiple of shorter object length" msgstr "" "długość dłuższego obiektu nie jest wielokrotnością długości krótszego obiektu" # Matrix/R/sparseMatrix.R: 372 # stop(gettextf("invalid 'col.names' string: %s", cn), domain = "R-Matrix") #, fuzzy msgid "invalid class \"%s\" in '%s' method" msgstr "niepoprawny łańcuch 'col.names': %s" msgid "invalid type \"%s\" in '%s' method" msgstr "" # Matrix/R/Auxiliaries.R: 273 # stop(gettextf("non-conformable matrix dimensions in %s", deparse(sys.call(sys.parent()))), call. = FALSE, domain = "R-Matrix") msgid "non-conformable matrix dimensions in %s" msgstr "niezgodne wymiary macierzy w %s" # Matrix/R/Auxiliaries.R: 292 # warning(gettextf("dimnames [%d] mismatch in %s", j, deparse(sys.call(sys.parent()))), call. = FALSE, domain = "R-Matrix") msgid "dimnames [%d] mismatch in %s" msgstr "niezgodność nazw wymiarów [%d] w %s" # Matrix/R/Ops.R: 35 # warning("inefficient method used for \"- e1\"") msgid "inefficient method used for \"- e1\"" msgstr "nieefektywna metoda użyta dla '- e1'" # Matrix/R/Ops.R: 1595 # stop(sprintf( # "dim [product %d] do not match the length of object [%d]", # n1, n2)) # Matrix/R/Ops.R: 1621 # stop(sprintf( # "dim [product %d] do not match the length of object [%d]", # n2, n1)) msgid "dim [product %d] do not match the length of object [%d]" msgstr "wymiar [produkt %d] nie zgadza się z długością obiektu [%d]" # Matrix/R/Ops.R: 174 # stop("internal bug in \"Compare\" method (Cmp.Mat.atomic); please report") msgid "internal bug in \"Compare\" method (Cmp.Mat.atomic); please report" msgstr "" "błąd wewnętrzny w metodzie 'Compare' (Cmp.Mat.atomic); proszę zgłosić raport" # Matrix/R/Ops.R: 183 # stop("Cmp.Mat.atomic() should not be called for diagonalMatrix") msgid "Cmp.Mat.atomic() should not be called for diagonalMatrix" msgstr "'Cmp.Mat.atomic()' nie powinien być wywołany dla 'diagonalMatrix'" # Matrix/R/Ops.R: 422 # stop("Matrices must have same number of rows for arithmetic") msgid "Matrices must have same number of rows for arithmetic" msgstr "" "Macierze muszą mieć tę samą liczbę wierszy jeśli mają być przeprowadzane " "działania arytmetyczne" # Matrix/R/Ops.R: 438 # stop(gettextf("number of rows are not compatible for %s", .Generic), domain = "R-Matrix") msgid "number of rows are not compatible for %s" msgstr "liczba wierszy nie jest zgodna dla %s" # Matrix/R/Ops.R: 449 # stop ("length of 2nd arg does not match dimension of first") # Matrix/R/Ops.R: 503 # stop ("length of 2nd arg does not match dimension of first") msgid "length of 2nd arg does not match dimension of first" msgstr "długość drugiego argumentu nie zgadza się z wymiarem pierwszego" # Matrix/R/Ops.R: 461 # stop ("length of 1st arg does not match dimension of 2nd") # Matrix/R/Ops.R: 534 # stop ("length of 1st arg does not match dimension of 2nd") msgid "length of 1st arg does not match dimension of 2nd" msgstr "długość pierwszego argumentu nie zgadza się z wymiarem drugiego" # Matrix/R/Ops.R: 674 # stop("internal bug in \"Logic\" method (Logic.Mat.atomic); please report") msgid "internal bug in \"Logic\" method (Logic.Mat.atomic); please report" msgstr "" "błąd wewnętrzny w metodzie 'Logic' (.Logic.Mat.atomic); proszę zgłosić raport" # Matrix/R/Ops.R: 683 # stop("Logic.Mat.atomic() should not be called for diagonalMatrix") msgid "Logic.Mat.atomic() should not be called for diagonalMatrix" msgstr "'Logic.Mat.atomic()' nie powinien być wywołany dla 'diagonalMatrix'" # Matrix/R/Ops.R: 1115 # stop("vector too long in Matrix - vector operation") msgid "vector too long in Matrix - vector operation" msgstr "wektor jest zbyt długi w operacji macierz-wektor" # Matrix/R/Ops.R: 1117 # warning("longer object length\n\tis not a multiple of shorter object length") # Matrix/R/Ops.R: 1512 # warning("longer object length\n\tis not a multiple of shorter object length") # Matrix/R/Ops.R: 1604 # warning("longer object length\n\tis not a multiple of shorter object length") # Matrix/R/Ops.R: 1630 # warning("longer object length\n\tis not a multiple of shorter object length") msgid "" "longer object length\n" "\tis not a multiple of shorter object length" msgstr "" "długość dłuższego obiektu\n" "\tnie jest wielokrotnością długości krótszego obiektu" # Matrix/R/sparseMatrix.R: 372 # stop(gettextf("invalid 'col.names' string: %s", cn), domain = "R-Matrix") #, fuzzy msgid "invalid class \"%s\" object in '%s' method" msgstr "niepoprawny łańcuch 'col.names': %s" # Matrix/R/diagMatrix.R: 779 # stop(gettextf("intermediate 'r' is of type %s", typeof(r)), domain = "R-Matrix") msgid "intermediate 'r' is of type %s" msgstr "pośrednie 'r' jest typu %s" # Matrix/R/diagMatrix.R: 796 # stop("not yet implemented .. please report") msgid "not yet implemented .. please report" msgstr "jeszcze niezaimplementowane .. proszę zgłosić raport" msgid "'%s' has non-finite values" msgstr "" msgid "'%1$s' is not \"%2$s\", \"%3$s\", or \"%2$s.\"" msgstr "" # Matrix/R/abIndex.R: 13 # stop("'force' must be (coercable to) TRUE or FALSE") msgid "'force' must be (coercable to) TRUE or FALSE" msgstr "'force' musi być (przekształcalne do) TRUE lub FALSE" # Matrix/R/abIndex.R: 162 # stop("invalid (to - from)/by in 'seq(.)'") msgid "invalid (to - from)/by in seq(.)" msgstr "niepoprawne '(to - from)/by' w 'seq(.)'" # Matrix/R/abIndex.R: 165 # stop("wrong sign in 'by' argument") msgid "wrong sign in 'by' argument" msgstr "niepoprawny znak w argumencie 'by'" # Matrix/R/abIndex.R: 167 # stop("'by' argument is much too small") msgid "'by' argument is much too small" msgstr "argument 'by' jest znacznie za mały" # Matrix/R/abIndex.R: 177 # stop("length must be non-negative number") msgid "length must be non-negative number" msgstr "długość musi być nieujemną liczbą" # Matrix/R/abIndex.R: 198 # stop("too many arguments") msgid "too many arguments" msgstr "zbyt wiele argumentów" # Matrix/R/abIndex.R: 286 # warning("c(,..) of different kinds, coercing all to 'rleDiff'") msgid "c(,..) of different kinds, coercing all to 'rleDiff'" msgstr "" "'c(,..)' różnych rodzajów, przekształcanie wszystkich do 'rleDiff'" # Matrix/R/abIndex.R: 345 # stop("[i] is not yet implemented") msgid "[i] is not yet implemented" msgstr "'[i]' nie jest jeszcze zaimplementowane" # Matrix/R/abIndex.R: 423 # stop("all() is not yet implemented") msgid "all() is not yet implemented" msgstr "'all()' nie jest jeszcze zaimplementowane" # Matrix/R/abIndex.R: 429 # stop("sum() is not yet implemented") msgid "sum() is not yet implemented" msgstr "'sum()' nie jest jeszcze zaimplementowane" # Matrix/R/abIndex.R: 432 # stop("prod() is not yet implemented") msgid "prod() is not yet implemented" msgstr "'prod()' nie jest jeszcze zaimplementowane" # Matrix/R/abIndex.R: 460 # stop("not yet implemented") # Matrix/R/sparseMatrix.R: 676 # stop("not yet implemented") msgid "not yet implemented" msgstr "jeszcze niezaimplementowane" # Matrix/R/abIndex.R: 518 # warning("x / 0 for an x with sign-change\nno longer representable as 'rleDiff'") msgid "" "x / 0 for an x with sign-change\n" " no longer representable as 'rleDiff'" msgstr "" "x / 0 dla ' x' ze zmianą znaku nie jest dłużej reprezentowalne jako " "'rleDiff'" # Matrix/R/abIndex.R: 693 # stop(" --> is not yet implemented") msgid " --> is not yet implemented" msgstr " --> nie jest jeszcze zaimplementowane" # Matrix/R/abIndex.R: 698 # stop(" --> is not yet implemented") msgid " --> is not yet implemented" msgstr " --> nie jest jeszcze zaimplementowane" # Matrix/R/sparseMatrix.R: 198 # stop("only square matrices can be used as incidence matrices for graphs") #, fuzzy msgid "only square matrices can be used as graph incidence matrices" msgstr "" "jedynie kwadratowe macierze mogą zostać użyte jako macierz incydencji dla " "grafów" # Matrix/R/ndenseMatrix.R: 77 # stop("not a symmetric matrix; consider forceSymmetric() or symmpart()") # Matrix/R/dgTMatrix.R: 37 # stop("not a symmetric matrix; consider forceSymmetric() or symmpart()") # Matrix/R/ldenseMatrix.R: 65 # stop("not a symmetric matrix; consider forceSymmetric() or symmpart()") # Matrix/R/Csparse.R: 76 # stop("not a symmetric matrix; consider forceSymmetric() or symmpart()") # Matrix/R/dsyMatrix.R: 8 # stop("not a symmetric matrix; consider forceSymmetric() or symmpart()") #, fuzzy msgid "matrix is not symmetric; consider forceSymmetric(.) or symmpart(.)" msgstr "" "to nie jest macierz symetryczna; rozważ 'forceSymmetric()' lub 'symmpart()'" # Matrix/R/dgTMatrix.R: 44 # stop("the matrix is not triangular") #, fuzzy msgid "matrix is not triangular; consider triu(.) or tril(.)" msgstr "macierz nie jest trójkątna" msgid "matrix is not diagonal; consider Diagonal(x=diag(.))" msgstr "" # Matrix/R/sparseMatrix.R: 731 # stop("invalid 'type'") #, fuzzy msgid "invalid type \"%s\" in '%s'" msgstr "niepoprawny 'type'" # Matrix/R/HBMM.R: 47 # stop(gettextf("Invalid storage type: %s", t1), domain = "R-Matrix") #, fuzzy msgid "invalid %s=\"%s\" to '%s'" msgstr "Niepoprawny typ przechowywania: %s" msgid "dimensions cannot exceed %s" msgstr "" # Matrix/R/sparseMatrix.R: 372 # stop(gettextf("invalid 'col.names' string: %s", cn), domain = "R-Matrix") #, fuzzy msgid "invalid class \"%s\" in '%s'" msgstr "niepoprawny łańcuch 'col.names': %s" msgid "%s length cannot exceed %s" msgstr "" # Matrix/R/condest.R: 74 # stop("'A' must be a square matrix") # Matrix/R/condest.R: 194 # stop("'A' must be a square matrix") msgid "'A' must be a square matrix" msgstr "'A' musi być macierzą kwadratową" # Matrix/R/condest.R: 186 # stop("must either specify 'A' or the functions 'A.x' and 'At.x'") msgid "must either specify 'A' or the functions 'A.x' and 'At.x'" msgstr "potrzeba określić 'A' lub funkcje 'A.x' oraz 'At.x'" # Matrix/R/condest.R: 188 # warning("when 'A' is specified, 'A.x' and 'At.x' are disregarded") msgid "when 'A' is specified, 'A.x' and 'At.x' are disregarded" msgstr "gdy 'A' jest określone, 'A.x' oraz 'At.x' są odrzucane" # Matrix/R/condest.R: 234 # warning(gettextf("not converged in %d iterations", iter.max), domain = "R-Matrix") msgid "not converged in %d iterations" msgstr "nie uzbieżnił się w %d iteracjach" # Matrix/R/condest.R: 249 # message("hit a cycle (1) -- stop iterations") msgid "hit a cycle (1) -- stop iterations" msgstr "natrafiona na cykl (1) -- zatrzymywanie iteracji" # Matrix/R/condest.R: 283 # message("hit a cycle (2) -- stop iterations") msgid "hit a cycle (2) -- stop iterations" msgstr "natrafiona na cykl (2) -- zatrzymywanie iteracji" # Matrix/R/condest.R: 300 # message("not enough new vecs -- stop iterations") msgid "not enough new vecs -- stop iterations" msgstr "zbyt mało nowych wektorów -- zatrzymywanie iteracji" # Matrix/R/Matrix.R: 206 # stop("invalid 'data'") msgid "invalid 'data'" msgstr "niepoprawne 'data'" # Matrix/R/Matrix.R: 224 # warning("'nrow', 'ncol', etc, are disregarded for matrix 'data'") #, fuzzy msgid "'nrow', 'ncol', 'byrow' disregarded for [mM]atrix 'data'" msgstr "'nrow', 'ncol', itd., są nieuwzględniane dla 'data' typu macierzowego" msgid "data is too long" msgstr "" # Matrix/R/sparseMatrix.R: 44 # stop("exactly one of 'i', 'j', or 'p' must be missing from call") #, fuzzy msgid "exactly one of 'i', 'j', and 'p' must be missing from call" msgstr "dokłanie jeden z 'i', 'j', lub 'p' musi być nieobecny w wywołaniu" msgid "" "use Diagonal() to construct diagonal (symmetric && triangular) sparse " "matrices" msgstr "" msgid "'giveCsparse' is deprecated; using 'repr' instead" msgstr "" msgid "'giveCsparse' is deprecated; setting repr=\"T\" for you" msgstr "" # Matrix/R/sparseMatrix.R: 48 # stop("'p' must be a non-decreasing vector (0, ...)") #, fuzzy msgid "'p' must be a nondecreasing vector c(0, ...)" msgstr "'p' musi być niemalejącym wektorem (0, ...)" msgid "dimensions cannot exceed 2^31-1" msgstr "" msgid "'i' and 'j' must not contain NA" msgstr "" msgid "'i' and 'j' must be" msgstr "" msgid "positive" msgstr "" msgid "non-negative" msgstr "" # Matrix/R/Matrix.R: 206 # stop("invalid 'data'") #, fuzzy msgid "invalid 'dims'" msgstr "niepoprawne 'data'" msgid "'dims' must contain all (i,j) pairs" msgstr "" # Matrix/R/sparseMatrix.R: 67 # stop("symmetric matrix must be square") msgid "symmetric matrix must be square" msgstr "macierz symetryczna musi być kwadratowa" # Matrix/R/sparseMatrix.R: 67 # stop("symmetric matrix must be square") #, fuzzy msgid "triangular matrix must be square" msgstr "macierz symetryczna musi być kwadratowa" msgid "p[length(p)]" msgstr "" msgid "length(i)" msgstr "" # Matrix/R/sparseMatrix.R: 79 # warning("length(i) is not a multiple of length(x)") #, fuzzy msgid "is not an integer multiple of length(x)" msgstr "'length(i)' nie jest wielokrotnością 'length(x)'" msgid "length(x) must not exceed" msgstr "" msgid "invalid 'repr'; must be \"C\", \"R\", or \"T\"" msgstr "" # Matrix/R/abIndex.R: 177 # stop("length must be non-negative number") #, fuzzy msgid "'n' must be a non-negative integer" msgstr "długość musi być nieujemną liczbą" msgid "'x' has unsupported class \"%s\"" msgstr "" msgid "'x' has unsupported type \"%s\"" msgstr "" msgid "attempt to recycle 'x' of length 0 to length 'n' (n > 0)" msgstr "" msgid "'shape' must be one of \"g\", \"t\", \"s\"" msgstr "" msgid "'kind' must be one of \"d\", \"l\", \"n\"" msgstr "" msgid "mismatch between typeof(x)=\"%s\" and kind=\"%s\"; using kind=\"%s\"" msgstr "" # Matrix/R/sparseVector.R: 237 # stop("'ncol' must be >= 0") #, fuzzy msgid "'cols' must be numeric" msgstr "'ncol' musi być >= 0" msgid "'cols' has elements not in seq(0, length.out = n)" msgstr "" msgid "'uplo' must be \"U\" or \"L\"" msgstr "" # Matrix/R/sparseVector.R: 237 # stop("'ncol' must be >= 0") #, fuzzy msgid "'lst' must be a list" msgstr "'ncol' musi być >= 0" msgid "'giveCsparse' has been deprecated; setting 'repr = \"T\"' for you" msgstr "" msgid "'giveCsparse' has been deprecated; will use 'repr' instead" msgstr "" # Matrix/R/bandSparse.R: 26 # stop(sprintf(ngettext(len.k, "'diagonals' matrix must have %d column (= length(k) )", "'diagonals' matrix must have %d columns (= length(k) )", domain = "R-Matrix"), len.k), domain = NA) msgid "'diagonals' matrix must have %d columns (= length(k) )" msgstr "macierz 'diagonals' musi mieć %d kolumnę (= length(k) )" # Matrix/R/bandSparse.R: 31 # stop(gettextf("'diagonals' must have the same length (%d) as 'k'", len.k), domain = "R-Matrix") msgid "'diagonals' must have the same length (%d) as 'k'" msgstr "'diagonals' musi mieć tę samą długość (%d) co 'k'" msgid "matrix can only be symmetric if square, but n != m" msgstr "" # Matrix/R/bandSparse.R: 36 # stop("for symmetric band matrix, only specify upper or lower triangle\n hence, all k must have the same sign") msgid "" "for symmetric band matrix, only specify upper or lower triangle\n" " hence, all k must have the same sign" msgstr "" "dla symetrycznej macierzy wstęgowej, określ jedynie górny oraz dolny " "trójkąt\n" "tak więc, wszystkie k muszą mieć ten sam znak" # Matrix/R/bandSparse.R: 64 # warning(gettextf("the %d-th (sub)-diagonal (k = %d) is too short; filling with NA's", s, kk), domain = "R-Matrix") msgid "the %d-th (sub)-diagonal (k = %d) is too short; filling with NA's" msgstr "" "(pod)-diagonala %d (k = %d) jest zbyt krótkal wypełnianie wartościami NA" msgid "invalid 'repr'; must be \"C\", \"T\", or \"R\"" msgstr "" # Matrix/R/sparseVector.R: 235 # stop("'x' must inherit from \"sparseVector\"") msgid "'x' must inherit from \"sparseVector\"" msgstr "argument 'x' musi być obiektem klasy \"sparseVector\"" # Matrix/R/sparseVector.R: 237 # stop("'ncol' must be >= 0") msgid "'ncol' must be >= 0" msgstr "'ncol' musi być >= 0" # Matrix/R/sparseVector.R: 239 # stop("'nrow' must be >= 0") msgid "'nrow' must be >= 0" msgstr "'nrow' musi być >= 0" # Matrix/R/sparseVector.R: 242 # stop("Must specify 'nrow' when 'symmetric' is true") msgid "Must specify 'nrow' when 'symmetric' is true" msgstr "'nrow' musi być określone, gdy 'symmetric' ma wartość TRUE" # Matrix/R/sparseVector.R: 244 # stop("'nrow' and 'ncol' must be the same when 'symmetric' is true") msgid "'nrow' and 'ncol' must be the same when 'symmetric' is true" msgstr "" "'nrow' oraz 'ncol' muszą mieć tę samą wartość gdy 'symmetric' ma wartość TRUE" # Matrix/R/sparseVector.R: 247 # stop("'x' must have length nrow^2 when 'symmetric' is true") msgid "'x' must have length nrow^2 when 'symmetric' is true" msgstr "'x' musi mieć długość równą 'nrow'^2 gdy 'symmetric' ma wartość TRUE" # Matrix/R/sparseVector.R: 255 # warning("'ncol' is not a factor of length(x)") msgid "'ncol' is not a factor of length(x)" msgstr "'ncol' nie jest czynnikiem długości 'length(x)'" # Matrix/R/sparseVector.R: 260 # warning("'nrow' is not a factor of length(x)") msgid "'nrow' is not a factor of length(x)" msgstr "'nrow' nie jest czynnikiem długości 'length(x)'" # Matrix/R/sparseVector.R: 278 # stop(gettextf("Class %s is not yet implemented", dQuote(cNam)), domain = "R-Matrix") msgid "Class %s is not yet implemented" msgstr "Klasa %s nie jest jeszcze zaimplementowana" # Matrix/R/abIndex.R: 177 # stop("length must be non-negative number") #, fuzzy msgid "'%s' and '%s' must be positive integers" msgstr "długość musi być nieujemną liczbą" # Matrix/R/symmetricMatrix.R: 114 # stop("'x' is not symmetric nor triangular") #, fuzzy msgid "matrix is not symmetric or triangular" msgstr "'x' nie jest macierzą symetryczną ani trójkątną" # Matrix/R/dgTMatrix.R: 44 # stop("the matrix is not triangular") #, fuzzy msgid "matrix is not symmetric" msgstr "macierz nie jest trójkątna" # Matrix/R/symmetricMatrix.R: 114 # stop("'x' is not symmetric nor triangular") #, fuzzy msgid "matrix is not triangular" msgstr "'x' nie jest macierzą symetryczną ani trójkątną" msgid "" "the default value of argument '%s' of method '%s(<%s>, <%s>)' may change " "from %s to %s as soon as the next release of Matrix; set '%s' when " "programming" msgstr "" msgid "determinant of non-square matrix is undefined" msgstr "" msgid "replacement diagonal has wrong length" msgstr "" msgid "replacement diagonal has incompatible type \"%s\"" msgstr "" msgid "assigned dimensions are not of type \"%s\" or \"%s\"" msgstr "" msgid "assigned dimensions do not have length %d" msgstr "" msgid "assigned dimensions are NA" msgstr "" msgid "assigned dimensions are negative" msgstr "" msgid "assigned dimensions exceed %s" msgstr "" # Matrix/R/Ops.R: 1595 # stop(sprintf( # "dim [product %d] do not match the length of object [%d]", # n1, n2)) # Matrix/R/Ops.R: 1621 # stop(sprintf( # "dim [product %d] do not match the length of object [%d]", # n2, n1)) #, fuzzy msgid "assigned dimensions [product %.0f] do not match object length [%.0f]" msgstr "wymiar [produkt %d] nie zgadza się z długością obiektu [%d]" # Matrix/R/dgTMatrix.R: 106 # stop("'lwd' must be NULL or non-negative numeric") msgid "'lwd' must be NULL or non-negative numeric" msgstr "'lwd' musi mieć wartość NULL lub być nieujemną liczbą" # Matrix/R/sparseVector.R: 278 # stop(gettextf("Class %s is not yet implemented", dQuote(cNam)), domain = "R-Matrix") #, fuzzy msgid "%s(<%s>) is not yet implemented" msgstr "Klasa %s nie jest jeszcze zaimplementowana" msgid "'%s' is not of type \"%s\" or \"%s\"" msgstr "" msgid "'%s' contains NA" msgstr "" msgid "'%s' has elements less than %d" msgstr "" # Matrix/R/abIndex.R: 177 # stop("length must be non-negative number") #, fuzzy msgid "'%s' is not a non-negative number" msgstr "długość musi być nieujemną liczbą" msgid "'%s' has elements exceeding '%s'" msgstr "" msgid "'%s' is not %d or %d" msgstr "" # Matrix/R/sparseVector.R: 255 # warning("'ncol' is not a factor of length(x)") #, fuzzy msgid "'%s' is not a permutation of seq_len(%s)" msgstr "'ncol' nie jest czynnikiem długości 'length(x)'" # Matrix/R/indMatrix.R: 71 # stop("must have exactly one non-zero entry per row") # Matrix/R/pMatrix.R: 33 # stop("must have exactly one non-zero entry per row") #, fuzzy msgid "matrix must have exactly one entry in each row or column" msgstr "potrzeba mieć dokładnie jeden niezerowy wpis na wiersz" # Matrix/R/dgTMatrix.R: 20 # stop("cannot coerce non-symmetric \"dgTMatrix\" to \"dsCMatrix\" class") #, fuzzy msgid "attempt to coerce non-square matrix to %s" msgstr "" "nie można przekształcić niesymetrycznej macierzy klasy \"dgTMatrix\" na " "klasę \"dsCMatrix\"" # Matrix/R/indMatrix.R: 71 # stop("must have exactly one non-zero entry per row") # Matrix/R/pMatrix.R: 33 # stop("must have exactly one non-zero entry per row") #, fuzzy msgid "matrix must have exactly one entry in each row and column" msgstr "potrzeba mieć dokładnie jeden niezerowy wpis na wiersz" # Matrix/R/sparseMatrix.R: 748 # warning("rcond(.) via sparse -> dense coercion") #, fuzzy msgid "'%s' via sparse -> dense coercion" msgstr "'rcond(.)' poprzez przekształcenie rzadkie -> gęste" # Matrix/R/denseMatrix.R: 101 # stop(gettextf("invalid nargs()= %d", na), domain = "R-Matrix") # Matrix/R/denseMatrix.R: 164 # stop(gettextf("invalid nargs()= %d", na), domain = "R-Matrix") #, fuzzy msgid "invalid %s=\"%s\"" msgstr "niepoprawne nargs()=%d" msgid "norm" msgstr "" # Matrix/R/indMatrix.R: 133 # stop("kronecker method must use default 'FUN'") # Matrix/R/kronecker.R: 33 # stop("kronecker method must use default 'FUN'") # Matrix/R/kronecker.R: 51 # stop("kronecker method must use default 'FUN'") #, fuzzy msgid "'%s' method must use default %s=\"%s\"" msgstr "metoda kroneckera musi użyć domyślnej 'FUN'" # Matrix/R/Ops.R: 438 # stop(gettextf("number of rows are not compatible for %s", .Generic), domain = "R-Matrix") #, fuzzy msgid "number of nonzero entries cannot exceed %s" msgstr "liczba wierszy nie jest zgodna dla %s" msgid "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", or \"%4$s\"" msgstr "" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%2$s2\", \"%2$s2.\", \"%3$s\", or " "\"%4$s\"" msgstr "" # Matrix/R/Auxiliaries.R: 273 # stop(gettextf("non-conformable matrix dimensions in %s", deparse(sys.call(sys.parent()))), call. = FALSE, domain = "R-Matrix") #, fuzzy msgid "non-conformable arguments" msgstr "niezgodne wymiary macierzy w %s" # Matrix/R/spModels.R: 113 # stop("model frame and formula mismatch in model.matrix()") #, fuzzy msgid "model frame and formula mismatch in sparse.model.matrix()" msgstr "niezgodność ramki modelu oraz formuły w 'model.matrix()'" # Matrix/R/spModels.R: 137 # stop("invalid 'contrasts.arg' argument") #, fuzzy msgid "non-list contrasts argument ignored" msgstr "niepoprawny argument 'contrasts.arg'" # Matrix/R/spModels.R: 137 # stop("invalid 'contrasts.arg' argument") #, fuzzy msgid "'contrasts.arg' argument must be named" msgstr "niepoprawny argument 'contrasts.arg'" # Matrix/R/spModels.R: 140 # warning(gettextf("variable '%s' is absent, its contrast will be ignored", nn), domain = "R-Matrix") msgid "variable '%s' is absent, its contrast will be ignored" msgstr "zmienna '%s' jest nieobecna, jej kontrast zostanie zignorowany" # Matrix/R/nearPD.R: 52 # stop("Matrix seems negative semi-definite") msgid "Matrix seems negative semi-definite" msgstr "Macierz wydaje się być ujemnie określona" # Matrix/R/nearPD.R: 79 # warning(gettextf("'nearPD()' did not converge in %d iterations", iter), domain = "R-Matrix") msgid "'nearPD()' did not converge in %d iterations" msgstr "funkcja 'nearPD()' nie uzbieżniła się w %d iteracjach" # Matrix/R/sparseMatrix.R: 759 # stop("'V' is not a *square* matrix") #, fuzzy msgid "'cl' is not a character string" msgstr "'V' nie jest macierzą *kwadratową*" msgid "" "not a positive definite matrix (and positive semidefiniteness is not checked)" msgstr "" # Matrix/R/sparseMatrix.R: 759 # stop("'V' is not a *square* matrix") #, fuzzy msgid "'%s' is not a square numeric matrix" msgstr "'V' nie jest macierzą *kwadratową*" # Matrix/R/Matrix.R: 94 # warning("diag(.) had 0 or NA entries; non-finite result is doubtful") # Matrix/R/sparseMatrix.R: 764 # warning("diag(.) had 0 or NA entries; non-finite result is doubtful") #, fuzzy msgid "" "diag(%s) has non-positive or non-finite entries; finite result is doubtful" msgstr "'diag(.)' posiadało wpisy 0 lub NA; nieskończony wynik jest wątpliwy" msgid "" "matrix is structurally rank deficient; using augmented matrix with " "additional %d row(s) of zeros" msgstr "" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%2$s2\", \"%2$s2.\", \"%3$s\", " "\"%3$s1\", \"%4$s\", or \"%4$s1\"" msgstr "" msgid "'%s' has the wrong length" msgstr "" # Matrix/R/sparseMatrix.R: 372 # stop(gettextf("invalid 'col.names' string: %s", cn), domain = "R-Matrix") #, fuzzy msgid "invalid '%s': not in %d:%d" msgstr "niepoprawny łańcuch 'col.names': %s" msgid "need greater '%s' as pivoting occurred" msgstr "" msgid "qr2rankMatrix(.): QR with only %d out of %d finite diag(R) entries" msgstr "" msgid "" "rankMatrix(, method = '%s') coerces to dense matrix.\n" " Probably should rather use method = 'qr' !?" msgstr "" "rankMatrix(, method = '%s') przekształca macierz do " "gęstej macierzy.\n" " Prawdopodobnie należy użyć 'method = \"qr\"' !?" # Matrix/R/rankMatrix.R: 73 # warning(gettextf("rankMatrix(x, method='qrLINPACK'): computing t(x) as nrow(x) < ncol(x)")) msgid "rankMatrix(x, method='qr'): computing t(x) as nrow(x) < ncol(x)" msgstr "rankMatrix(x, method='qr'): obliczanie t(x) jako nrow(x) < ncol(x)" # Matrix/R/Auxiliaries.R: 373 # message(sprintf(gettext(" [[ suppressing %d column names %s... ]]", domain = "R-Matrix"), nc, paste(sQuote(cn[1:3]), collapse = ", ")), domain = NA) #, fuzzy msgid "[[ suppressing %d column name%s %s ... ]]" msgstr "[[ zmniejszanie %d nazw kolumn %s ... ]]" # Matrix/R/sparseMatrix.R: 372 # stop(gettextf("invalid 'col.names' string: %s", cn), domain = "R-Matrix") msgid "invalid 'col.names' string: %s" msgstr "niepoprawny łańcuch 'col.names': %s" msgid "uniDiag=TRUE, but not all diagonal entries are 1" msgstr "" msgid "uniDiag=TRUE, not all entries in diagonal coded as 1" msgstr "" msgid "in show(); maybe adjust options(max.print=, width=)" msgstr "" # Matrix/R/Auxiliaries.R: 375 # message(sprintf(gettext(" [[ suppressing %d column names %s ]]", domain = "R-Matrix"), nc, paste(sQuote(cn[1:lc]), collapse = ", ")), domain = NA) #, fuzzy msgid "suppressing %d columns and %d rows" msgstr "[[ zmniejszanie %d nazw kolumn %s ]]" # Matrix/R/Auxiliaries.R: 375 # message(sprintf(gettext(" [[ suppressing %d column names %s ]]", domain = "R-Matrix"), nc, paste(sQuote(cn[1:lc]), collapse = ", ")), domain = NA) #, fuzzy msgid "suppressing %d rows" msgstr "[[ zmniejszanie %d nazw kolumn %s ]]" # Matrix/R/Auxiliaries.R: 375 # message(sprintf(gettext(" [[ suppressing %d column names %s ]]", domain = "R-Matrix"), nc, paste(sQuote(cn[1:lc]), collapse = ", ")), domain = NA) #, fuzzy msgid "suppressing %d columns" msgstr "[[ zmniejszanie %d nazw kolumn %s ]]" # Matrix/R/sparseMatrix.R: 599 # stop("logic programming error in printSpMatrix2(), please report") msgid "logic programming error in printSpMatrix2(), please report" msgstr "błąd logiczny programu w 'printSpMatrix2()', proszę zgłosić raport" # Matrix/R/Matrix.R: 91 # stop("'V' is not a square matrix") #, fuzzy msgid "'%s' is not square" msgstr "'V' nie jest macierzą kwadratową" msgid "dimensions of '%s' and '%s' are inconsistent" msgstr "" msgid "'%1$s' is computationally singular, rcond(%1$s)=%2$g" msgstr "" msgid "'%s' is computationally singular, min(d)/max(d)=%g, d=abs(diag(U))" msgstr "" msgid "matrix is exactly singular, D[i,i]=0, i=%d" msgstr "" msgid "matrix is exactly singular, J[,j]=0, j=%d" msgstr "" msgid "matrix exactly singular, J[i,]=0, i=%d" msgstr "" msgid "cannot coerce from %s to %s" msgstr "" msgid "a sparseMatrix should rarely be centered: will not be sparse anymore" msgstr "" # Matrix/R/bind2.R: 395 # stop(gettextf("Matrices must have same number of columns in %s", deparse(sys.call(sys.parent()))), call. = FALSE, domain = "R-Matrix") # Matrix/R/Auxiliaries.R: 314 # stop(gettextf("Matrices must have same number of columns in %s", deparse(sys.call(sys.parent()))), call. = FALSE, domain = "R-Matrix") #, fuzzy msgid "length of 'center' must equal the number of columns of 'x'" msgstr "Macierze muszą mieć tę samą liczbę kolumn w %s" # Matrix/R/bind2.R: 395 # stop(gettextf("Matrices must have same number of columns in %s", deparse(sys.call(sys.parent()))), call. = FALSE, domain = "R-Matrix") # Matrix/R/Auxiliaries.R: 314 # stop(gettextf("Matrices must have same number of columns in %s", deparse(sys.call(sys.parent()))), call. = FALSE, domain = "R-Matrix") #, fuzzy msgid "length of 'scale' must equal the number of columns of 'x'" msgstr "Macierze muszą mieć tę samą liczbę kolumn w %s" # Matrix/R/Rsparse.R: 32 # stop(gettextf("invalid class: %s", dQuote(cl)), domain = "R-Matrix") # Matrix/R/Rsparse.R: 59 # stop(gettextf("invalid class: %s", dQuote(cl)), domain = "R-Matrix") #, fuzzy msgid "invalid subassignment value class \"%s\"" msgstr "niepoprawna klasa: %s" # Matrix/R/HBMM.R: 47 # stop(gettextf("Invalid storage type: %s", t1), domain = "R-Matrix") #, fuzzy msgid "invalid subassignment value type \"%s\"" msgstr "Niepoprawny typ przechowywania: %s" msgid "missing subassignment value" msgstr "" # Matrix/R/diagMatrix.R: 744 # stop("incompatible matrix dimensions") #, fuzzy msgid "incorrect number of dimensions" msgstr "niezgodne wymiary macierzy" msgid "replacement has length zero" msgstr "" # Matrix/R/Matrix.R: 713 # warning("number of items to replace is not a multiple of replacement length") # Matrix/R/Csparse.R: 245 # stop("number of items to replace is not a multiple of replacement length") # Matrix/R/Tsparse.R: 366 # warning("number of items to replace is not a multiple of replacement length") # Matrix/R/Tsparse.R: 405 # stop("number of items to replace is not a multiple of replacement length") # Matrix/R/Tsparse.R: 657 # warning("number of items to replace is not a multiple of replacement length") # Matrix/R/sparseVector.R: 530 # stop("number of items to replace is not a multiple of replacement length") msgid "number of items to replace is not a multiple of replacement length" msgstr "" "liczba pozycji do zastąpienia nie jest wielokrotnością długości elementu " "zastępującego" # Matrix/R/Matrix.R: 694 # stop(".M.repl.i.2col(): 'i' has no integer column number;\n should never happen; please report") msgid "" ".M.repl.i.2col(): 'i' has no integer column number;\n" " should never happen; please report" msgstr "" ".M.repl.i.2col(): 'i' posiada niecałkowitą liczbę kolumn;\n" "to nie powinno się nigdy wydarzyć; proszę zgłosić raport" # Matrix/R/Matrix.R: 667 # stop("such indexing must be by logical or 2-column numeric matrix") # Matrix/R/Matrix.R: 696 # stop("such indexing must be by logical or 2-column numeric matrix") # Matrix/R/Tsparse.R: 638 # stop("such indexing must be by logical or 2-column numeric matrix") msgid "such indexing must be by logical or 2-column numeric matrix" msgstr "" "takie indeksowanie musi być wykonane poprzez macierz logiczną lub 2-" "kolumnową macierz liczbową" # Matrix/R/Matrix.R: 698 # message(".M.repl.i.2col(): drop 'matrix' case ...") msgid ".M.repl.i.2col(): drop 'matrix' case ..." msgstr ".M.repl.i.2col(): zrzuć przypadek 'matrix' ..." # Matrix/R/Matrix.R: 704 # stop("negative values are not allowed in a matrix subscript") # Matrix/R/Tsparse.R: 641 # stop("negative values are not allowed in a matrix subscript") msgid "negative values are not allowed in a matrix subscript" msgstr "ujemne wartości nie są dozwolone w indeksach macierzy" # Matrix/R/Matrix.R: 706 # stop("NAs are not allowed in subscripted assignments") # Matrix/R/Tsparse.R: 643 # stop("NAs are not allowed in subscripted assignments") msgid "NAs are not allowed in subscripted assignments" msgstr "wartości NA nie są dozwolone w indeksowanych przypisaniach" # Matrix/R/Matrix.R: 719 # message("m[ ] <- v: inefficiently treating single elements") msgid "m[ ] <- v: inefficiently treating single elements" msgstr "m[ ] <- v: nieefektywne traktowanie pojedynczych elementów" # Matrix/R/Matrix.R: 725 # stop(gettextf("nargs() = %d. Extraneous illegal arguments inside '[ .. ]' ?", nA), domain = "R-Matrix") msgid "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' ?" msgstr "nargs() = %d. Obce nielegalne argumenty wewnątrz '[ .. ]' ?" # Matrix/R/Matrix.R: 796 # stop(gettextf("RHS 'value' (class %s) matches 'ANY', but must match matrix class %s", class(value), class(x)), domain = "R-Matrix") msgid "RHS 'value' (class %s) matches 'ANY', but must match matrix class %s" msgstr "" "prawa strona 'value' (klasa %s) pasuje do 'ANY', a musi pasować do klasy " "macierzy '%s'" # Matrix/R/Matrix.R: 797 # stop("not-yet-implemented 'Matrix[<-' method") msgid "not-yet-implemented 'Matrix[<-' method" msgstr "jeszcze niezaimplementowana metoda 'Matrix[<-'" # Matrix/R/denseMatrix.R: 101 # stop(gettextf("invalid nargs()= %d", na), domain = "R-Matrix") # Matrix/R/denseMatrix.R: 164 # stop(gettextf("invalid nargs()= %d", na), domain = "R-Matrix") msgid "invalid nargs()= %d" msgstr "niepoprawne nargs()=%d" # Matrix/R/Csparse.R: 240 # stop("nothing to replace with") # Matrix/R/Tsparse.R: 400 # stop("nothing to replace with") # Matrix/R/Tsparse.R: 653 # stop("nothing to replace with") # Matrix/R/sparseVector.R: 525 # stop("nothing to replace with") msgid "nothing to replace with" msgstr "nic do zastąpienia" # Matrix/R/Csparse.R: 247 # stop("too many replacement values") # Matrix/R/Tsparse.R: 495 # stop("too many replacement values") # Matrix/R/sparseVector.R: 557 # stop("too many replacement values") msgid "too many replacement values" msgstr "zbyt dużo wartości zamieniających" # Matrix/R/Csparse.R: 284 # warning("i1[1] == 0 ==> C-level verbosity will not happen!") msgid "i1[1] == 0 ==> C-level verbosity will not happen!" msgstr "i1[1] == 0 ==> tryb 'verbose' poziomu C nie zostanie wykonany!" msgid "using\t \"old code\" part in Csparse subassignment" msgstr "używanie\t części 'old code' w przypisaniu w 'Csparse'" msgid "" "using\"old code\" part in Csparse subassignment\n" " >>> please report to Matrix-authors@r-project.org" msgstr "" "używanie części 'old code' w przypisaniu w 'Csparse'\n" ">>> proszę zgłosić raport na adres 'Matrix-authors@r-project.org'" # Matrix/R/Tsparse.R: 126 # stop("you cannot mix negative and positive indices") # Matrix/R/sparseVector.R: 395 # stop("you cannot mix negative and positive indices") # Matrix/R/sparseVector.R: 462 # stop("you cannot mix negative and positive indices") msgid "you cannot mix negative and positive indices" msgstr "nie można mieszać ujemnych oraz dodatnich indeksów" # Matrix/R/Tsparse.R: 130 # stop(gettextf("index larger than maximal %d", n), domain = "R-Matrix") msgid "index larger than maximal %d" msgstr "indeks dłuższy niż maksymalny możliwy %d" # Matrix/R/Tsparse.R: 123 # stop("'NA' indices are not (yet?) supported for sparse Matrices") msgid "'NA' indices are not (yet?) supported for sparse Matrices" msgstr "indeksy 'NA' nie są (jeszcze?) wspierane dla rzadkich macierzy" # Matrix/R/Tsparse.R: 138 # stop(gettextf("logical subscript too long (%d, should be %d)", length(i), n), domain = "R-Matrix") msgid "logical subscript too long (%d, should be %d)" msgstr "indeks logiczny jest zbyt długi (%d, powinien być %d)" # Matrix/R/Tsparse.R: 143 # stop("no 'dimnames[[.]]': cannot use character indexing") msgid "no 'dimnames[[.]]': cannot use character indexing" msgstr "brak 'dimnames[[.]]': nie można używać indeksowania tekstowego" # Matrix/R/Tsparse.R: 145 # stop("invalid character indexing") msgid "invalid character indexing" msgstr "niepoprawne tekstowe indeksowanie" # Matrix/R/Tsparse.R: 309 # stop("internal bug: missing 'i' in replTmat(): please report") msgid "internal bug: missing 'i' in replTmat(): please report" msgstr "błąd wewnętrzny: brakuje 'i' w 'replTmat()': proszę zgłosić raport" # Matrix/R/Tsparse.R: 311 # stop("[ ] indexing not allowed: forgot a \",\" ?") msgid "[ ] indexing not allowed: forgot a \",\" ?" msgstr "indeksowanie [ ] nie jest dozwolone: zapomniałeś ',' ?" # Matrix/R/Tsparse.R: 313 # stop("internal bug: matrix 'i' in replTmat(): please report") msgid "internal bug: matrix 'i' in replTmat(): please report" msgstr "wewnętrzny błąd: macierz 'i' w 'replTmat()': proszę zgłosić raport" # Matrix/R/Tsparse.R: 342 # warning(if(iNA) # gettextf("x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE.", dQuote(clx)) # else # gettextf("x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.", dQuote(clx)), domain = "R-Matrix") msgid "" "x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced; NA |--> TRUE." msgstr "" "x[.] <- wartość: 'x' to %s, wartość nie w zakresie {TRUE, FALSE} zostaje " "przekształcona; NA |--> TRUE." # Matrix/R/Tsparse.R: 342 # warning(if(iNA) # gettextf("x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE.", dQuote(clx)) # else # gettextf("x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.", dQuote(clx)), domain = "R-Matrix") msgid "x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced." msgstr "" "x[.] <- wartość: 'x' to %s, wartość nie w zakresie {TRUE, FALSE} zostaje " "przekształcona." # Matrix/R/Tsparse.R: 500 # warning(if(iNA) # gettextf("x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE.", dQuote(clx)) # else # gettextf("x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.", dQuote(clx)), domain = "R-Matrix") msgid "" "x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE." msgstr "" "x[.,.] <- wartość: 'x' to %s, wartość nie w zakresie {TRUE, FALSE} zostaje " "przekształcona NA |--> TRUE." # Matrix/R/Tsparse.R: 500 # warning(if(iNA) # gettextf("x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE.", dQuote(clx)) # else # gettextf("x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced.", dQuote(clx)), domain = "R-Matrix") msgid "x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced." msgstr "" "x[.,.] <- wartość: 'x' to %s, wartość nie w zakresie {TRUE, FALSE} zostaje " "przekształcona." # Matrix/R/Tsparse.R: 529 # message(gettextf("x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrix"), domain = "R-Matrix") msgid "x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrix" msgstr "" "x[.,.] <- wartość : 'x' zostaje przekształcone z 'Tsparse*' na " "'CsparseMatrix'" # Matrix/R/Matrix.R: 769 # stop(gettextf("nargs() = %d should never happen; please report.", nA), domain = "R-Matrix") # Matrix/R/Matrix.R: 781 # stop(gettextf("nargs() = %d should never happen; please report.", nA), domain = "R-Matrix") # Matrix/R/Tsparse.R: 624 # stop(gettextf("nargs() = %d should never happen; please report.", nA), domain = "R-Matrix") msgid "nargs() = %d should never happen; please report." msgstr "'nargs() = %d' nie powinno się wydarzyć; proszę zgłosić raport." # Matrix/R/Tsparse.R: 669 # stop(gettextf("row indices must be <= nrow(.) which is %d", nr), domain = "R-Matrix") msgid "row indices must be <= nrow(.) which is %d" msgstr "indeksy wiersza muszą być <= 'nrow(.)' który wynosi %d" # Matrix/R/Tsparse.R: 670 # stop(gettextf("column indices must be <= ncol(.) which is %d", nc), domain = "R-Matrix") msgid "column indices must be <= ncol(.) which is %d" msgstr "indeksy kolumn muszą być <= 'ncol(.)' który wynosi %d" # Matrix/R/diagMatrix.R: 418 # stop(gettextf("Internal bug: nargs()=%d; please report", na), domain = "R-Matrix") msgid "Internal bug: nargs()=%d; please report" msgstr "Błąd wewnętrzny: nargs()=%d; proszę zgłosić raport" # Matrix/R/sparseVector.R: 415 # stop("index must be numeric, logical or sparseVector for indexing sparseVectors") msgid "" "index must be numeric, logical or sparseVector for indexing sparseVectors" msgstr "" "indeks musi być typem liczbowym, logicznym lub obiektem klasy 'sparseVector' " "na potrzeby indeksowania obiektów klasy 'sparseVector'" # Matrix/R/Rsparse.R: 32 # stop(gettextf("invalid class: %s", dQuote(cl)), domain = "R-Matrix") # Matrix/R/Rsparse.R: 59 # stop(gettextf("invalid class: %s", dQuote(cl)), domain = "R-Matrix") #, fuzzy msgid "invalid subscript class \"%s\"" msgstr "niepoprawna klasa: %s" # Matrix/R/HBMM.R: 47 # stop(gettextf("Invalid storage type: %s", t1), domain = "R-Matrix") #, fuzzy msgid "invalid subscript type \"%s\"" msgstr "Niepoprawny typ przechowywania: %s" msgid "recycled %s would have maximal index exceeding %s" msgstr "" msgid "subscripts exceeding %s replaced with NA" msgstr "" msgid "subscript out of bounds" msgstr "" # Matrix/R/Tsparse.R: 138 # stop(gettextf("logical subscript too long (%d, should be %d)", length(i), n), domain = "R-Matrix") #, fuzzy msgid "logical subscript too long" msgstr "indeks logiczny jest zbyt długi (%d, powinien być %d)" msgid "only zeros may be mixed with negative subscripts" msgstr "" msgid "trimmed means are not defined for complex data" msgstr "" msgid "first element used of '%s' argument" msgstr "" # Matrix/R/Matrix.R: 206 # stop("invalid 'data'") #, fuzzy msgid "invalid '%s' argument" msgstr "niepoprawne 'data'" msgid "should never happen ..." msgstr "" msgid "'%s' is deprecated; using '%s' instead" msgstr "" msgid "'%s' is deprecated; setting %s=\"%s\"" msgstr "" msgid "'%s' has length 0 but '%s' does not" msgstr "" # Matrix/R/dgTMatrix.R: 20 # stop("cannot coerce non-symmetric \"dgTMatrix\" to \"dsCMatrix\" class") #, fuzzy msgid "attempt to coerce matrix with NA to %s" msgstr "" "nie można przekształcić niesymetrycznej macierzy klasy \"dgTMatrix\" na " "klasę \"dsCMatrix\"" # Matrix/R/Matrix.R: 206 # stop("invalid 'data'") #, fuzzy msgid "invalid 'Class2'" msgstr "niepoprawne 'data'" # Matrix/R/abIndex.R: 165 # stop("wrong sign in 'by' argument") #, fuzzy #~ msgid "invalid 'each' argument" #~ msgstr "niepoprawny znak w argumencie 'by'" # Matrix/R/Matrix.R: 206 # stop("invalid 'data'") #, fuzzy #~ msgid "invalid 'times' argument" #~ msgstr "niepoprawne 'data'" # Matrix/R/Auxiliaries.R: 65 # stop(gettextf("not-yet-implemented method for %s(<%s>).\n ->> Ask the package authors to implement the missing feature.", fun, cl), call. = FALSE, domain = "R-Matrix") #~ msgid "" #~ "not-yet-implemented method for %s(<%s>).\n" #~ " ->> Ask the package authors to implement the missing feature." #~ msgstr "" #~ "metoda jeszcze niezaimplementowana dla %s(<%s>).\n" #~ " ->> Poproś autorów pakietu o zaimplementowanie brakującej " #~ "funkcjonalności." # Matrix/R/Auxiliaries.R: 68 # stop(gettextf("not-yet-implemented method for %s(<%s>, <%s>).\n ->> Ask the package authors to implement the missing feature.", fun, cl1, cl2), call. = FALSE, domain = "R-Matrix") #~ msgid "" #~ "not-yet-implemented method for %s(<%s>, <%s>).\n" #~ " ->> Ask the package authors to implement the missing feature." #~ msgstr "" #~ "metoda jeszcze niezaimplementowana dla %s(<%s>, <%s>).\n" #~ " ->> Poproś autorów pakietu o zaimplementowanie brakującej " #~ "funkcjonalności." # Matrix/R/Auxiliaries.R: 906 # stop(gettextf("general Matrix class not yet implemented for %s", dQuote(class(x))), domain = "R-Matrix") #, fuzzy #~ msgid "complex \"diagonalMatrix\" not yet implemented" #~ msgstr "ogólna klasa 'Matrix' jeszcze nie jest zaimplementowana dla %s" # Matrix/R/Auxiliaries.R: 641 # stop(gettextf("not yet implemented for class %s", dQuote(class.x)), domain = "R-Matrix") #, fuzzy #~ msgid "not yet implemented for class \"%s\"" #~ msgstr "jeszcze niezaimplementowane dla klasy %s" # Matrix/R/sparseMatrix.R: 731 # stop("invalid 'type'") #, fuzzy #~ msgid "invalid 'uplo'" #~ msgstr "niepoprawny 'type'" # Matrix/R/Matrix.R: 400 # stop("'lag' and 'differences' must be integers >= 1") #~ msgid "'lag' and 'differences' must be integers >= 1" #~ msgstr "'lag' oraz 'differences' muszą być liczbami całkowitymi >= 1" # Matrix/R/Matrix.R: 459 # stop("programming error: min() should have dispatched w/ 1st arg much earlier") #~ msgid "" #~ "programming error: min() should have dispatched w/ 1st arg much earlier" #~ msgstr "" #~ "błąd programistyczny: 'min()' powinno zostać wysłane z pierwszym " #~ "argumentem znacznie wcześniej" #~ msgid "in Summary(, .): %s(<%s>, <%s>,...)" #~ msgstr "w funkcji 'Summary(, .): %s(<%s>, <%s>,...)'" #, fuzzy #~ msgid "in Summary(, .): %s(<%s>, <%s>)" #~ msgstr "w funkcji 'Summary(, .): %s(<%s>, <%s>,...)'" # Matrix/R/Ops.R: 438 # stop(gettextf("number of rows are not compatible for %s", .Generic), domain = "R-Matrix") #, fuzzy #~ msgid "number of rows of matrices must match" #~ msgstr "liczba wierszy nie jest zgodna dla %s" # Matrix/R/Ops.R: 438 # stop(gettextf("number of rows are not compatible for %s", .Generic), domain = "R-Matrix") #, fuzzy #~ msgid "number of columns of matrices must match" #~ msgstr "liczba wierszy nie jest zgodna dla %s" # Matrix/R/denseMatrix.R: 71 # stop("dim(.) value must be numeric of length 2") # Matrix/R/sparseVector.R: 317 # stop("dim(.) value must be numeric of length 2") # Matrix/R/sparseMatrix.R: 711 # stop("dim(.) value must be numeric of length 2") #, fuzzy #~ msgid "dimensions must be numeric of length 2" #~ msgstr "wartości 'dim(.)' muszą być liczbami o długości 2" # Matrix/R/condest.R: 74 # stop("'A' must be a square matrix") # Matrix/R/condest.R: 194 # stop("'A' must be a square matrix") #, fuzzy #~ msgid "'perm' must be numeric" #~ msgstr "'A' musi być macierzą kwadratową" # Matrix/R/sparseVector.R: 237 # stop("'ncol' must be >= 0") #, fuzzy #~ msgid "'margin' must be 1 or 2" #~ msgstr "'ncol' musi być >= 0" # Matrix/R/products.R: 186 # stop(gettextf("not-yet-implemented method for <%s> %%*%% <%s>", class(x), class(y)), domain = "R-Matrix") #~ msgid "not-yet-implemented method for <%s> %%*%% <%s>" #~ msgstr "jeszcze niezaimplementowana metoda dla <%s> %%*%% <%s>" # Matrix/R/diagMatrix.R: 225 # stop(gettextf("%s kind not yet implemented", sQuote(kind)), domain = "R-Matrix") #, fuzzy #~ msgid "'boolArith = %d' not yet implemented" #~ msgstr "rodzaj %s nie jest jeszcze zaimplementowany" # Matrix/R/sparseMatrix.R: 748 # warning("rcond(.) via sparse -> dense coercion") #, fuzzy #~ msgid "'rcond' via sparse -> dense coercion" #~ msgstr "'rcond(.)' poprzez przekształcenie rzadkie -> gęste" # Matrix/R/Matrix.R: 206 # stop("invalid 'data'") #, fuzzy #~ msgid "invalid 'norm'" #~ msgstr "niepoprawne 'data'" # Matrix/R/ngTMatrix.R: 24 # stop("cannot coerce 'NA's to \"nsparseMatrix\"") #, fuzzy #~ msgid "cannot coerce zsparseVector to dgCMatrix" #~ msgstr "nie można przekształcić wartości 'NA' na 'nsparseMatrix'" # Matrix/R/sparseVector.R: 53 # stop("cannot coerce 'NA's to \"nsparseVector\"") #, fuzzy #~ msgid "cannot coerce zsparseVector to dgeMatrix" #~ msgstr "" #~ "nie można przekształcić wartości NA na obiekt klasy \"nsparseVector\"" # Matrix/R/sparseVector.R: 740 # stop("'times >= 0' is required") #~ msgid "'times >= 0' is required" #~ msgstr "wymagane jest 'times >= 0'" # Matrix/R/Auxiliaries.R: 305 # stop(gettextf("Matrices must have same number of rows in %s", deparse(sys.call(sys.parent()))), call. = FALSE, domain = "R-Matrix") #~ msgid "Matrices must have same number of rows in %s" #~ msgstr "Macierze muszą mieć tę samą liczbę wierszy w %s" # Matrix/R/bind2.R: 395 # stop(gettextf("Matrices must have same number of columns in %s", deparse(sys.call(sys.parent()))), call. = FALSE, domain = "R-Matrix") # Matrix/R/Auxiliaries.R: 314 # stop(gettextf("Matrices must have same number of columns in %s", deparse(sys.call(sys.parent()))), call. = FALSE, domain = "R-Matrix") #~ msgid "Matrices must have same number of columns in %s" #~ msgstr "Macierze muszą mieć tę samą liczbę kolumn w %s" # Matrix/R/lMatrix.R: 8 # stop("\"lMatrix\" object with NAs cannot be coerced to \"nMatrix\"") #, fuzzy #~ msgid "only lists of length 2 can be coerced to indMatrix" #~ msgstr "" #~ "obiekt klasy \"lMatrix\" z wartościami NA nie może zostać przekształcony " #~ "na obiekt klasy \"nMatrix\"" # Matrix/R/sparseMatrix.R: 13 # stop("only 2-dimensional tables can be directly coerced to sparse matrices") #, fuzzy #~ msgid "only 2-dimensional tables can be coerced to sparseMatrix" #~ msgstr "" #~ "jedynie 2-wymiarowe tablice mogą zostać bezpośrednio przekształcone w " #~ "rzadkie macierze" # Matrix/R/symmetricMatrix.R: 114 # stop("'x' is not symmetric nor triangular") #, fuzzy #~ msgid "matrix is not symmetric or" #~ msgstr "'x' nie jest macierzą symetryczną ani trójkątną" # Matrix/R/ndenseMatrix.R: 86 # stop("not a triangular matrix") # Matrix/R/ldenseMatrix.R: 74 # stop("not a triangular matrix") # Matrix/R/Auxiliaries.R: 805 # stop("not a triangular matrix") # Matrix/R/Auxiliaries.R: 1035 # stop("not a triangular matrix") #, fuzzy #~ msgid "triangular" #~ msgstr "to nie jest macierz trójkątną" # Matrix/R/diagMatrix.R: 358 # stop("matrix is not diagonal") #, fuzzy #~ msgid "matrix is not" #~ msgstr "macierz nie jest diagonalna" # Matrix/R/Auxiliaries.R: 167 # stop("'x' is not positive definite -- chol() undefined.") # Matrix/R/dsparseMatrix.R: 18 # stop("'x' is not positive definite -- chol() undefined.") #~ msgid "'x' is not positive definite -- chol() undefined." #~ msgstr "'x' nie jest dodatnio określone -- nieokreślony 'chol()'." # Matrix/R/Auxiliaries.R: 248 # stop(gettextf("Matrices must have same dimensions in %s", deparse(sys.call(sys.parent()))), call. = FALSE, domain = "R-Matrix") #~ msgid "Matrices must have same dimensions in %s" #~ msgstr "Macierze muszą mieć te same wymiary w %s" # Matrix/R/Auxiliaries.R: 375 # message(sprintf(gettext(" [[ suppressing %d column names %s ]]", domain = "R-Matrix"), nc, paste(sQuote(cn[1:lc]), collapse = ", ")), domain = NA) #~ msgid "[[ suppressing %d column names %s ]]" #~ msgstr "[[ zmniejszanie %d nazw kolumn %s ]]" # Matrix/R/Auxiliaries.R: 521 # stop(gettext("'x' must be \"sparseMatrix\""), domain = "R-Matrix") #~ msgid "'x' must be \"sparseMatrix\"" #~ msgstr "'x' musi być obiektem klasy \"sparseMatrix\"" # Matrix/R/Auxiliaries.R: 821 # stop(gettextf("not yet implemented for matrix with typeof %s", typeof(x)), domain = "R-Matrix") # Matrix/R/Auxiliaries.R: 834 # stop(gettextf("not yet implemented for matrix with typeof %s", typeof(x)), domain = "R-Matrix") #~ msgid "not yet implemented for matrix with typeof %s" #~ msgstr "jeszcze niezaimplementowana dla macierzy z typem %s" # Matrix/R/Auxiliaries.R: 850 # stop(gettextf(" not yet implemented for %s", clx@className), domain = "R-Matrix") #~ msgid "not yet implemented for %s" #~ msgstr "jeszcze nie jest zaimplementowana dla %s" # Matrix/R/CHMfactor.R: 122 # message(sprintf(gettext("Quadratic matrix '%s' (=: A) is not formally symmetric. Will be treated as A A'", domain = "R-Matrix"), "parent"), domain = NA) #~ msgid "" #~ "Quadratic matrix '%s' (=: A) is not formally\n" #~ "\tsymmetric. Will be treated as\tA A'" #~ msgstr "" #~ "Macierz kwadratowa '%s' (=: A) nie jest formalnie symetryczna. Będzie " #~ "traktowana jako A A'" # Matrix/R/CHMfactor.R: 134 # stop("'update' must be logical or '+' or '-'; 'C' a matrix, and 'L' a \"CHMfactor\"") #~ msgid "" #~ "'update' must be logical or '+' or '-'; 'C' a matrix, and 'L' a " #~ "\"CHMfactor\"" #~ msgstr "" #~ "'update' musi być wartością logiczną lub '+' lub '-'; 'C' musi być " #~ "macierzą, oraz 'L' musi być obiektem klasy 'CHMfactor'" # Matrix/R/CHMfactor.R: 145 # stop("update must be TRUE/FALSE or '+' or '-'") #~ msgid "update must be TRUE/FALSE or '+' or '-'" #~ msgstr "'update' musi wynosić TRUE/FALSE lub '+' lub '-'" # Matrix/R/Csparse.R: 190 # stop("Matrix-internal error in [i,,d]; please report") #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "" #~ "błąd wewnętrzny w pakiecie 'Matrix' w '[i,,d]'; proszę zgłosić " #~ "raport" # Matrix/R/Csparse.R: 498 # stop("Cholesky() -> *symbolic* factorization -- not yet implemented") #~ msgid "" #~ "Cholesky() -> *symbolic* factorization -- not yet implemented" #~ msgstr "" #~ "Cholesky() -> *symboliczna* faktoryzacja -- jeszcze " #~ "niezaimplementowana" # Matrix/R/Matrix.R: 71 # warning("trimmed mean of 'sparseVector' -- suboptimally using as.numeric(.)") #~ msgid "trimmed mean of 'sparseVector' -- suboptimally using as.numeric(.)" #~ msgstr "" #~ "przycięta średnia 'sparseVector' -- optymalnie używając 'as.numeric(.)'" # Matrix/R/Matrix.R: 144 # stop(gettextf("invalid dimnames given for %s object", dQuote(class(x))), domain = "R-Matrix") #~ msgid "invalid dimnames given for %s object" #~ msgstr "podano niepoprawne nazwy wymiarów dla obiektu %s" # Matrix/R/Matrix.R: 154 # message("dimnames(.) <- NULL: translated to \ndimnames(.) <- list(NULL,NULL) <==> unname(.)") #~ msgid "" #~ "dimnames(.) <- NULL: translated to \n" #~ "dimnames(.) <- list(NULL,NULL) <==> unname(.)" #~ msgstr "" #~ "dimnames(.) <- NULL: przetłumaczono na\n" #~ "dimnames(.) <- list(NULL,NULL) <==> unname(.)" # Matrix/R/Matrix.R: 186 # warning("'nrow', 'ncol', etc, are disregarded when 'data' is \"Matrix\" already") #~ msgid "" #~ "'nrow', 'ncol', etc, are disregarded when 'data' is \"Matrix\" already" #~ msgstr "" #~ "'nrow', 'ncol', itd., nie są uwzględniane gdy 'data' ma już typ 'Matrix'" # Matrix/R/Matrix.R: 251 # stop("complex matrices not yet implemented in Matrix package") #~ msgid "complex matrices not yet implemented in Matrix package" #~ msgstr "" #~ "macierze zespolone nie są jeszcze zaimplementowane w pakiecie 'Matrix'" # Matrix/R/Matrix.R: 311 # warning("using slow kronecker() method") # Matrix/R/Matrix.R: 318 # warning("using slow kronecker() method") #~ msgid "using slow kronecker() method" #~ msgstr "używanie powolnej metody 'kronecker()'" # Matrix/R/Matrix.R: 334 # stop(gettextf("Cholesky(A) called for 'A' of class \"%s\";\n\t it is currently defined for sparseMatrix only; consider using chol() instead", class(A)), call. = FALSE, domain = "R-Matrix") #~ msgid "" #~ "Cholesky(A) called for 'A' of class \"%s\";\n" #~ "\t it is currently defined for sparseMatrix only; consider using chol() " #~ "instead" #~ msgstr "" #~ "metoda 'Cholesky(A)' poprosiła o 'A' klasy '%s';\n" #~ "\t aktualnie jest ona zdefiniowana jedynie dla klasy 'sparseMatrix'; " #~ "rozważ w zamian użycie 'metodychol()'" # Matrix/R/Matrix.R: 563 # stop("invalid or not-yet-implemented 'Matrix' subsetting") #~ msgid "invalid or not-yet-implemented 'Matrix' subsetting" #~ msgstr "niepoprawne lub jeszcze niezaimplementowane podstawienie 'Matrix'" # Matrix/R/Matrix.R: 574 # message("[ ] : .M.sub.i.logical() maybe inefficient") #~ msgid "[ ] : .M.sub.i.logical() maybe inefficient" #~ msgstr "[ ] : '.M.sub.i.logical()' może być niewydajne" # Matrix/R/Matrix.R: 590 # stop(gettextf("nargs() = %d. Extraneous illegal arguments inside '[ .. ]' (i.logical)?", nA), domain = "R-Matrix") #~ msgid "" #~ "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' (i.logical)?" #~ msgstr "" #~ "nargs() = %d. Obce nielegalne argumenty wewnątrz '[ .. ]' (i.logical)?" # Matrix/R/Matrix.R: 644 # message("m[ ]: inefficiently indexing single elements") #, fuzzy #~ msgid "" #~ "m[]: inefficiently indexing single elements - should not " #~ "happen, please report!" #~ msgstr "m[ ]: nieefektywne indeksowanie pojedynczych elementów" # Matrix/R/Matrix.R: 673 # stop(gettextf("nargs() = %d. Extraneous illegal arguments inside '[ .. ]' (i.2col)?", nA), domain = "R-Matrix") #~ msgid "" #~ "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' (i.2col)?" #~ msgstr "" #~ "nargs() = %d. Obce nielegalne argumenty wewnątrz '[ .. ]' (i.2col)?" # Matrix/R/Matrix.R: 663 # stop(".M.sub.i.2col(): 'i' has no integer column number;\n should never happen; please report") #~ msgid "" #~ ".M.sub.i.2col(): 'i' has no integer column number;\n" #~ " should never happen; please report" #~ msgstr "" #~ ".M.sub.i.2col(): 'i' posiada niecałkowitą liczbę kolumn;\n" #~ "to nie powinno się nigdy wydarzyć; proszę zgłosić raport" # Matrix/R/Tsparse.R: 8 # stop("not-yet-implemented coercion to \"TsparseMatrix\"") #~ msgid "not-yet-implemented coercion to \"TsparseMatrix\"" #~ msgstr "jeszcze niezaimplementowane przekształcenie na 'TsparseMatrix'" # Matrix/R/Tsparse.R: 206 # stop("Matrix-internal error in [i,,d]; please report") #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "" #~ "błąd wewnętrzny pakiecie 'Matrix' w '[i,,d]'; proszę zgłosić " #~ "raport" # Matrix/R/Tsparse.R: 256 # stop("FIXME: NOT YET FINISHED IMPLEMENTATION") #~ msgid "FIXME: NOT YET FINISHED IMPLEMENTATION" #~ msgstr "FIXME: JESZCZE NIEZAKOŃCZONA IMPLEMENTACJA" # Matrix/R/denseMatrix.R: 30 # stop("diagonalMatrix in .dense2C() -- should never happen, please report!") #~ msgid "diagonalMatrix in .dense2C() -- should never happen, please report!" #~ msgstr "" #~ "'diagonalMatrix' w '.dense2C()' -- nie powinno nigdy się wydarzyć, proszę " #~ "zgłosić raport!" # Matrix/R/denseMatrix.R: 36 # stop(gettextf("undefined method for class %s", dQuote(cl)), domain = "R-Matrix") #~ msgid "undefined method for class %s" #~ msgstr "niezdefiniowana metoda dla klasy %s" # Matrix/R/denseMatrix.R: 73 # stop("dimensions don't match the number of cells") # Matrix/R/sparseVector.R: 319 # stop("dimensions don't match the number of cells") # Matrix/R/sparseMatrix.R: 713 # stop("dimensions don't match the number of cells") #~ msgid "dimensions don't match the number of cells" #~ msgstr "wymiary nie zgadzają się z liczbą komórek" # Matrix/R/dgCMatrix.R: 94 # stop(gettextf("LU computationally singular: ratio of extreme entries in |diag(U)| = %9.4g", # rU[1] / rU[2]), # domain = "R-Matrix") #~ msgid "" #~ "LU computationally singular: ratio of extreme entries in |diag(U)| = %9.4g" #~ msgstr "" #~ "LU obliczeniowo osobliwa: stosunek ekstremalnych wpisów w |diag(U)| = " #~ "%9.4g" # Matrix/R/diagMatrix.R: 28 # stop("'x' has invalid data type") #~ msgid "'x' has invalid data type" #~ msgstr "'x' posiada niepoprawny typ danych" # Matrix/R/diagMatrix.R: 72 # stop("length(x) must be either 1 or #{cols}") #~ msgid "length(x) must be either 1 or #{cols}" #~ msgstr "'length(x)' musi wynosić 1 lub #{kolumn}" # Matrix/R/diagMatrix.R: 101 # stop("some arguments are not matrices") #~ msgid "some arguments are not matrices" #~ msgstr "niektóre argumenty nie są macierzami" # Matrix/R/diagMatrix.R: 225 # stop(gettextf("%s kind not yet implemented", sQuote(kind)), domain = "R-Matrix") #~ msgid "%s kind not yet implemented" #~ msgstr "rodzaj %s nie jest jeszcze zaimplementowany" # Matrix/R/diagMatrix.R: 337 # stop("non-square matrix") # Matrix/R/diagMatrix.R: 357 # stop("non-square matrix") #~ msgid "non-square matrix" #~ msgstr "niekwadratowa macierz" # Matrix/R/diagMatrix.R: 339 # stop("matrix with non-zero off-diagonals cannot be coerced to \"diagonalMatrix\"") #~ msgid "" #~ "matrix with non-zero off-diagonals cannot be coerced to \"diagonalMatrix\"" #~ msgstr "" #~ "macierz z niezerowaymi wartościami pozadiagonalnymi nie może zostać " #~ "przekształcona w na obiekt klasy \"diagonalMatrix\"" # Matrix/R/diagMatrix.R: 586 # stop("non-matching dimensions") # Matrix/R/diagMatrix.R: 599 # stop("non-matching dimensions") # Matrix/R/diagMatrix.R: 615 # stop("non-matching dimensions") # Matrix/R/diagMatrix.R: 627 # stop("non-matching dimensions") # Matrix/R/diagMatrix.R: 658 # stop("non-matching dimensions") # Matrix/R/diagMatrix.R: 676 # stop("non-matching dimensions") #~ msgid "non-matching dimensions" #~ msgstr "niezgodne wymiary" # Matrix/R/dppMatrix.R: 27 # stop("not a positive definite matrix") # Matrix/R/dsyMatrix.R: 94 # stop("not a positive definite matrix") #~ msgid "not a positive definite matrix" #~ msgstr "to nie jest dodatnio określona macierz" # Matrix/R/dsCMatrix.R: 5 # warning("as(.,\"dsCMatrix\") is deprecated (since 2008); do use as(., \"symmetricMatrix\")") #~ msgid "" #~ "as(.,\"dsCMatrix\") is deprecated (since 2008); do use as(., " #~ "\"symmetricMatrix\")" #~ msgstr "" #~ "'as(.,\"dsCMatrix\")' jest przestarzałe (0d 2008); używaj 'as(., " #~ "\"symmetricMatrix\")'" # Matrix/R/dtpMatrix.R: 14 # warning("inefficient coercion (lost triangularity); please report") #~ msgid "inefficient coercion (lost triangularity); please report" #~ msgstr "" #~ "nieefektywne przekształcenie (utracono trójkątność); proszę zgłosić raport" # Matrix/R/indMatrix.R: 13 # stop("coercion to \"indMatrix\" only works from integer numeric") #~ msgid "coercion to \"indMatrix\" only works from integer numeric" #~ msgstr "" #~ "przekształcenie na \"indMatrix\" działa jedynie dla liczb całkowitych" #~ msgid "" #~ "coercion from list(i1,...,ik, d) to \"indMatrix\" failed.\n" #~ " All entries must be integer valued and the number of columns, d, not " #~ "smaller\n" #~ " than the maximal index i*." #~ msgstr "" #~ "przekształcenie z 'list(i1,...,ik, d)' na obiekt klasy \"indMatrix\" nie " #~ "powiodło się.\n" #~ " Wszystkie wpisy muszą być wartościami całkowitymi a liczba kolumn d nie " #~ "może być mniejsza niż maksymalny indeks i*." # Matrix/R/indMatrix.R: 65 # stop("the number of non-zero entries differs from nrow(.)") # Matrix/R/pMatrix.R: 27 # stop("the number of non-zero entries differs from nrow(.)") #~ msgid "the number of non-zero entries differs from nrow(.)" #~ msgstr "liczba niezerowych wpisów różni się od 'nrow(.)'" # Matrix/R/indMatrix.R: 158 # stop('replacing "indMatrix" entries is not allowed, as rarely sensible') #~ msgid "replacing \"indMatrix\" entries is not allowed, as rarely sensible" #~ msgstr "" #~ "zastępowanie wpisów \"indMatrix\" jest niedozwolone, ponieważ jest to " #~ "rzadko sensowne" # Matrix/R/nsCMatrix.R: 58 # stop("function is temporarily disabled") #~ msgid "temporarily disabled" #~ msgstr "funkcja jest tymczasowo niedostępna" # Matrix/R/ngTMatrix.R: 24 # stop("cannot coerce 'NA's to \"nsparseMatrix\"") #, fuzzy #~ msgid "cannot coerce NA values to pattern \"ntCMatrix\"" #~ msgstr "nie można przekształcić wartości 'NA' na 'nsparseMatrix'" # Matrix/R/pMatrix.R: 17 # stop("coercion to \"pMatrix\" only works from integer numeric") #~ msgid "coercion to \"pMatrix\" only works from integer numeric" #~ msgstr "" #~ "przekształcenie na obiekt klasy \"pMatrix\" działa jedynie dla liczb " #~ "całkowitych" # Matrix/R/pMatrix.R: 25 # stop("not a square matrix") #~ msgid "not a square matrix" #~ msgstr "to nie jest macierz kwadratowa" # Matrix/R/sparseMatrix.R: 58 # stop("NA's in (i,j) are not allowed") #~ msgid "NA's in (i,j) are not allowed" #~ msgstr "wartości NA w (i,j) nie są dozwolone" # Matrix/R/sparseMatrix.R: 240 # stop("Matrix-internal error in [i,,d]; please report") #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "" #~ "błąd wewnętrzny pakietu 'Matrix' w '[i,,d]'; proszę zgłosić " #~ "raport" # Matrix/R/sparseQR.R: 16 # warning("qr.R() may differ from qr.R() because of permutations. Possibly use our qrR() instead") #~ msgid "" #~ "qr.R() may differ from qr.R() because of permutations. " #~ "Possibly use our qrR() instead" #~ msgstr "" #~ "'qr.R()' może różnić się od 'qr.R()' z powodu permutacji. " #~ "Być może użyj metody qrR() w zamian" # Matrix/R/symmetricMatrix.R: 72 # stop(sprintf("(un)packing only applies to dense matrices, class(x)='%s'", # cx)) # Matrix/R/symmetricMatrix.R: 93 # stop(sprintf("(un)packing only applies to dense matrices, class(x)='%s'", # class(x))) #~ msgid "(un)packing only applies to dense matrices, class(x)='%s'" #~ msgstr "" #~ "(roz)pakowanie stosuje się jedynie do gęstych macierzy, class(x)='%s'" # Matrix/R/Auxiliaries.R: 167 # stop("'x' is not positive definite -- chol() undefined.") # Matrix/R/dsparseMatrix.R: 18 # stop("'x' is not positive definite -- chol() undefined.") #, fuzzy #~ msgid "'x' is not symmetric -- chol() undefined." #~ msgstr "'x' nie jest dodatnio określone -- nieokreślony 'chol()'." # Matrix/R/Auxiliaries.R: 1376 # warning(sprintf(gettext("arguments %s are disregarded in\n %s", domain = "R-Matrix"), # sub(")$", '', sub("^list\\(", '', deparse(list(...), control=c()))), # deparse(sys.call(-1), control=c())), call. = FALSE, domain = NA) #, fuzzy #~ msgid "" #~ "extra argument %s will be disregarded in\n" #~ " %s" #~ msgid_plural "" #~ "extra arguments %s will be disregarded in\n" #~ " %s" #~ msgstr[0] "" #~ "argumenty %s zostały odrzucone w\n" #~ " %s" #~ msgstr[1] "" #~ "argumenty %s zostały odrzucone w\n" #~ " %s" #~ msgstr[2] "" #~ "argumenty %s zostały odrzucone w\n" #~ " %s" # Matrix/R/Ops.R: 134 # stop(sprintf(gettext(" %s %s is undefined", domain = "R-Matrix"), .Generic, paste0(class(e2),"(0)")), domain = NA) # Matrix/R/Ops.R: 634 # stop(sprintf(gettext(" %s %s is undefined", domain = "R-Matrix"), .Generic, paste0(class(e2),"(0)")), domain = NA) # Matrix/R/Ops.R: 1126 # stop(sprintf(gettext(" %s %s is undefined", domain = "R-Matrix"), .Generic, paste0(class(e2),"(0)")), domain = NA) #~ msgid " %s %s is undefined" #~ msgstr " %s %s nie jest określone" # Matrix/R/Ops.R: 1165 # stop(sprintf(gettext("%s %s is undefined", domain = "R-Matrix"), paste0(class(e2),"(0)"), .Generic), domain = NA) #~ msgid "%s %s is undefined" #~ msgstr "%s %s nie jest określone" # Matrix/R/spModels.R: 125 # warning(gettextf("variable '%s' converted to a factor", i), domain = "R-Matrix") #~ msgid "variable '%s' converted to a factor" #~ msgstr "zmienna '%s' została zamieniona na czynnik" # Matrix/R/lMatrix.R: 8 # stop("\"lMatrix\" object with NAs cannot be coerced to \"nMatrix\"") #~ msgid "\"dMatrix\" object with NAs cannot be coerced to \"nMatrix\"" #~ msgstr "" #~ "obiekt klasy \"dMatrix\" z wartościami NA nie może zostać przekształcony " #~ "na obiekt klasy \"nMatrix\"" # Matrix/R/indMatrix.R: 63 # stop("not a skinny matrix") #~ msgid "not a skinny matrix" #~ msgstr "to nie jest chuda macierz" #~ msgid "longer object length" #~ msgstr "długość dłuższego obiektu" Matrix/po/R-de.po0000644000175100001440000013016414575137654013327 0ustar hornikusers# Translation of R-matrix to German # Copyright (C) 2001-2020 The R Foundation # This file is distributed under the same license as the matrix package. # Chris Leick , 2009. # Detlef Steuer , 2012-2020. msgid "" msgstr "" "Project-Id-Version: R 4.0.0 / matrix 1.3-0\n" "Report-Msgid-Bugs-To: bugs.r-project.org\n" "POT-Creation-Date: 2024-03-15 17:22\n" "PO-Revision-Date: 2020-04-01 16:01+0200\n" "Last-Translator: Detlef Steuer \n" "Language-Team: R-Core \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #, fuzzy msgid "invalid mode \"%s\"" msgstr "ungültiges 'mod': %s" msgid "" "%s(<%s>, <%s>) is not yet implemented; ask maintainer(\"%s\") to implement " "the missing method" msgstr "" #, fuzzy msgid "complex %s not yet implemented" msgstr "Klasse %s noch nicht implementiert" #, fuzzy msgid "cannot coerce matrix of type \"%s\" to %s" msgstr "'NA's können nicht in \"nsparseMatrix\" umgewandelt werden" #, fuzzy msgid "non0.i() not yet implemented for class %s" msgstr "noch nicht implementiert für Klasse %s" msgid "%s=\"%s\" invalid for %s@uplo=\"%s\"" msgstr "" msgid "'%s' is not \"%1$s\", \"D%1$s\", or \"%1$s.\"" msgstr "" #, fuzzy msgid "%1$s(%2$s) is undefined: '%2$s' is not positive semidefinite" msgstr "chol() ist undefiniert für diagonale Matrix mit negativen Einträgen" #, fuzzy msgid "matrix is not square" msgstr "Matrix ist nicht diagonal" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", \"%3$s.\", \"%3$s1\", \"%3$s1." "\", or \"%4$s\"" msgstr "" #, fuzzy msgid "'%s' does not inherit from virtual class %s" msgstr "'x' muss von \"sparseVector\" geerbt sein" msgid "D[i,i] is NA, i=%d" msgstr "" msgid "D[i,i] is negative, i=%d" msgstr "" msgid "'%1$s' is not formally symmetric; factorizing tcrossprod(%1$s)" msgstr "" msgid "unexpected %s=\"%s\" in '%s' method" msgstr "" msgid "Not a valid format" msgstr "Kein gültiges Format" msgid "'file' must be a character string or connection" msgstr "'file' muss eine Zeichenkette oder Verbindung sein" msgid "Invalid storage type: %s" msgstr "Ungültiger Speichertyp: %s" msgid "Only numeric sparse matrices allowed" msgstr "Nur dünn besetzte Matrizen erlaubt" msgid "Invalid storage format: %s" msgstr "Ungültiges Speicherformat: %s" msgid "Invalid assembled indicator: %s" msgstr "Ungültig zusammengesetzter Indikator: %s" msgid "file is not a MatrixMarket file" msgstr "Datei ist keine MatrixMarket-Datei" msgid "type '%s' not recognized" msgstr "Typ '%s' nicht erkannt" msgid "representation '%s' not recognized" msgstr "Repräsentation '%s' nicht erkannt" msgid "element type '%s' not recognized" msgstr "Elementtyp '%s' nicht erkannt" msgid "symmetry form '%s' not recognized" msgstr "Symmetrieform '%s' nicht erkannt" msgid "readMM(): expected %d entries but found only %d" msgstr "" #, fuzzy msgid "readMM(): row indices 'i' are not in 1:nrow[=%d]" msgstr "readMM(): Zeile\t Werte 'i' sind nicht in 1:nr" #, fuzzy msgid "readMM(): column indices 'j' are not in 1:ncol[=%d]" msgstr "readMM(): Spalte\t Werte 'j' sind nicht in 1:nc" msgid "symmetry form 'skew-symmetric' not yet implemented for reading" msgstr "Symmetrieform 'skew-symmetric' noch nicht zum Lesen implementiert" msgid "symmetry form 'hermitian' not yet implemented for reading" msgstr "Symmetrieform 'hermitian' noch nicht zum Lesen implementiert" msgid "symmetry form '%s' is not yet implemented" msgstr "Symmetrieform '%s' noch nicht implementiert" msgid "element type 'complex' not yet implemented" msgstr "Elementtyp 'complex' noch nicht implementiert" msgid "'%s()' is not yet implemented for element type '%s'" msgstr "'%s()' ist noch nicht für Elementtyp '%s' implementiert" msgid "'%s()' is not yet implemented for representation '%s'" msgstr "'%s()' ist noch nicht implementiert für Darstellung '%s'" msgid "longer object length is not a multiple of shorter object length" msgstr "längere Objektlänge ist kein Vielfaches der kürzeren Objektlänge" #, fuzzy msgid "invalid class \"%s\" in '%s' method" msgstr "ungültige 'col.names'-Zeichenkette: %s" msgid "invalid type \"%s\" in '%s' method" msgstr "" msgid "non-conformable matrix dimensions in %s" msgstr "nicht konforme Matrixdimensionen in %s" msgid "dimnames [%d] mismatch in %s" msgstr "dimnames [%d] passen nicht in %s" msgid "inefficient method used for \"- e1\"" msgstr "ineffiziente Methode für '- e1' benutzt" msgid "dim [product %d] do not match the length of object [%d]" msgstr "dim [produkt %d] passt nicht zur Länge des Objekts [%d]" msgid "internal bug in \"Compare\" method (Cmp.Mat.atomic); please report" msgstr "" "interner Fehler in der \"Compare\"-Methode (Cmp.Mat.atomic). Bitte berichten" msgid "Cmp.Mat.atomic() should not be called for diagonalMatrix" msgstr "Cmp.Mat.atomic() sollte nicht für diagonalMatrix aufgerufen werden" msgid "Matrices must have same number of rows for arithmetic" msgstr "Matrizen müssen für Arithmetik die gleiche Anzahl Zeilen haben" msgid "number of rows are not compatible for %s" msgstr "Anzahl der Zeilen ist nicht kompatibel für %s" msgid "length of 2nd arg does not match dimension of first" msgstr "Länge des zweiten Arguments passt nicht zur Dimension des ersten" msgid "length of 1st arg does not match dimension of 2nd" msgstr "Länge des ersten arg passt nicht zur Dimension des zweiten" msgid "internal bug in \"Logic\" method (Logic.Mat.atomic); please report" msgstr "" "interner Fehler in der \"Logic\"-Methode (.Logic.Mat.atomic). Bitte berichten" msgid "Logic.Mat.atomic() should not be called for diagonalMatrix" msgstr "Logic.mat.atomic() sollte für diagonalMatrix nicht aufgerufen werden" msgid "vector too long in Matrix - vector operation" msgstr "Vektor zu lang in der Matrix - Vektor Operation" msgid "" "longer object length\n" "\tis not a multiple of shorter object length" msgstr "" "längere Objektlänge\n" "\tist kein Vielfaches der kürzeren Objektlänge" #, fuzzy msgid "invalid class \"%s\" object in '%s' method" msgstr "ungültige 'col.names'-Zeichenkette: %s" msgid "intermediate 'r' is of type %s" msgstr "Zwischenergebnis 'r' ist vom Typ %s" msgid "not yet implemented .. please report" msgstr "noch nicht implementiert ... bitte melden" msgid "'%s' has non-finite values" msgstr "" msgid "'%1$s' is not \"%2$s\", \"%3$s\", or \"%2$s.\"" msgstr "" msgid "'force' must be (coercable to) TRUE or FALSE" msgstr "'force' muss (umwandelbar nach) TRUE oder FALSE sein" msgid "invalid (to - from)/by in seq(.)" msgstr "unzulässiges (to - from)/by in seq(.)" msgid "wrong sign in 'by' argument" msgstr "falsches Vorzeichen im Argument 'by'" msgid "'by' argument is much too small" msgstr "Argument 'by' ist zu klein" msgid "length must be non-negative number" msgstr "Länge muss eine nicht negative Zahl sein" msgid "too many arguments" msgstr "zu viele Argumente" msgid "c(,..) of different kinds, coercing all to 'rleDiff'" msgstr "" "c(,..) von unterschiedlichen Arten, alle werden in 'rleDiff' " "umgewandelt" msgid "[i] is not yet implemented" msgstr "[i] ist noch nicht implementiert" msgid "all() is not yet implemented" msgstr "all() ist noch nicht implementiert" msgid "sum() is not yet implemented" msgstr "sum() ist noch nicht implementiert" msgid "prod() is not yet implemented" msgstr "prod() ist noch nicht implementiert" msgid "not yet implemented" msgstr "noch nicht implementiert" msgid "" "x / 0 for an x with sign-change\n" " no longer representable as 'rleDiff'" msgstr "" "x / 0 für einen x mit Vorzeichenwechsel\n" " nicht länger als 'rleDiff' darstellbar" msgid " --> is not yet implemented" msgstr " --> ist noch nicht implementiert" msgid " --> is not yet implemented" msgstr " --> ist noch nicht implementiert" #, fuzzy msgid "only square matrices can be used as graph incidence matrices" msgstr "" "nur quadratische Matrizen können als Inzidenzmatrizen für Graphen benutzt " "werden" #, fuzzy msgid "matrix is not symmetric; consider forceSymmetric(.) or symmpart(.)" msgstr "" "keine symmetrische Matrix. Erwägen Sie forceSymmetric() oder symmpart()" #, fuzzy msgid "matrix is not triangular; consider triu(.) or tril(.)" msgstr "die Matrix ist nicht dreieckig" msgid "matrix is not diagonal; consider Diagonal(x=diag(.))" msgstr "" #, fuzzy msgid "invalid type \"%s\" in '%s'" msgstr "ungültiger 'type'" #, fuzzy msgid "invalid %s=\"%s\" to '%s'" msgstr "Ungültiger Speichertyp: %s" msgid "dimensions cannot exceed %s" msgstr "" #, fuzzy msgid "invalid class \"%s\" in '%s'" msgstr "ungültige 'col.names'-Zeichenkette: %s" msgid "%s length cannot exceed %s" msgstr "" msgid "'A' must be a square matrix" msgstr "'A' muss eine quadratische Matrix sein" msgid "must either specify 'A' or the functions 'A.x' and 'At.x'" msgstr "muss entweder 'A' angeben oder die Funktionen 'A.x' und 'At.x'" msgid "when 'A' is specified, 'A.x' and 'At.x' are disregarded" msgstr "wenn 'A' angegeben wurde, werden 'A.x' und 'At.x' nicht berücksichtigt" msgid "not converged in %d iterations" msgstr "nicht konvergiert in %d Iterationsschritten" msgid "hit a cycle (1) -- stop iterations" msgstr "auf einen Zyklus getroffen (1) – Iterationen stoppen" msgid "hit a cycle (2) -- stop iterations" msgstr "auf einen Zyklus getroffen (2) – Iterationen stoppen" msgid "not enough new vecs -- stop iterations" msgstr "nicht genügend neue Vektoren – Iterationen stoppen" msgid "invalid 'data'" msgstr "ungültiges 'data'" #, fuzzy msgid "'nrow', 'ncol', 'byrow' disregarded for [mM]atrix 'data'" msgstr "'nrow', 'ncol', etc werden nicht für Matrix 'data' berücksichtigt" msgid "data is too long" msgstr "" #, fuzzy msgid "exactly one of 'i', 'j', and 'p' must be missing from call" msgstr "exakt eins von 'i', 'j' oder 'p' muss im Aufruf fehlen" msgid "" "use Diagonal() to construct diagonal (symmetric && triangular) sparse " "matrices" msgstr "" msgid "'giveCsparse' is deprecated; using 'repr' instead" msgstr "" msgid "'giveCsparse' is deprecated; setting repr=\"T\" for you" msgstr "" #, fuzzy msgid "'p' must be a nondecreasing vector c(0, ...)" msgstr "'p' muss ein nicht abnehmender Vektor (0, ...) sein" msgid "dimensions cannot exceed 2^31-1" msgstr "" msgid "'i' and 'j' must not contain NA" msgstr "" msgid "'i' and 'j' must be" msgstr "" msgid "positive" msgstr "" msgid "non-negative" msgstr "" #, fuzzy msgid "invalid 'dims'" msgstr "ungültiges 'data'" msgid "'dims' must contain all (i,j) pairs" msgstr "" msgid "symmetric matrix must be square" msgstr "symmetrische Matrix muss quadratisch sein" msgid "triangular matrix must be square" msgstr "Dreiecksmatrix muss quadratisch sein" msgid "p[length(p)]" msgstr "" msgid "length(i)" msgstr "" #, fuzzy msgid "is not an integer multiple of length(x)" msgstr "length(i) ist kein Vielfaches von length(x)" msgid "length(x) must not exceed" msgstr "" msgid "invalid 'repr'; must be \"C\", \"R\", or \"T\"" msgstr "" #, fuzzy msgid "'n' must be a non-negative integer" msgstr "Länge muss eine nicht negative Zahl sein" msgid "'x' has unsupported class \"%s\"" msgstr "" msgid "'x' has unsupported type \"%s\"" msgstr "" msgid "attempt to recycle 'x' of length 0 to length 'n' (n > 0)" msgstr "" msgid "'shape' must be one of \"g\", \"t\", \"s\"" msgstr "" msgid "'kind' must be one of \"d\", \"l\", \"n\"" msgstr "" msgid "mismatch between typeof(x)=\"%s\" and kind=\"%s\"; using kind=\"%s\"" msgstr "" #, fuzzy msgid "'cols' must be numeric" msgstr "'ncol' muss >= 0 sein" msgid "'cols' has elements not in seq(0, length.out = n)" msgstr "" msgid "'uplo' must be \"U\" or \"L\"" msgstr "" #, fuzzy msgid "'lst' must be a list" msgstr "'ncol' muss >= 0 sein" msgid "'giveCsparse' has been deprecated; setting 'repr = \"T\"' for you" msgstr "" msgid "'giveCsparse' has been deprecated; will use 'repr' instead" msgstr "" msgid "'diagonals' matrix must have %d columns (= length(k) )" msgstr "'diagonals'-Matrix muss %d Spalten haben (= length(k) )" msgid "'diagonals' must have the same length (%d) as 'k'" msgstr "'diagonals' muss die gleiche Länge (%d) wie 'k' haben" msgid "matrix can only be symmetric if square, but n != m" msgstr "" "Matrix kann nur symmetrisch sein, wenn sie quadratisch ist, aber n != m" msgid "" "for symmetric band matrix, only specify upper or lower triangle\n" " hence, all k must have the same sign" msgstr "" "geben Sie für symmetrische Bandmatrizen nur oberes oder unteres Dreieck an.\n" " deshalb müssen alle k dasselbe Vorzeichen haben." msgid "the %d-th (sub)-diagonal (k = %d) is too short; filling with NA's" msgstr "" "die %d-te (Unter)-Diagonale (k = %d) ist zu kurz und wird mit NA aufgefüllt" msgid "invalid 'repr'; must be \"C\", \"T\", or \"R\"" msgstr "" msgid "'x' must inherit from \"sparseVector\"" msgstr "'x' muss von \"sparseVector\" geerbt sein" msgid "'ncol' must be >= 0" msgstr "'ncol' muss >= 0 sein" msgid "'nrow' must be >= 0" msgstr "'nrow' muss >= 0 sein" msgid "Must specify 'nrow' when 'symmetric' is true" msgstr "'nrow' muss angegeben werden, wenn 'symmetric' auf true gesetzt ist" msgid "'nrow' and 'ncol' must be the same when 'symmetric' is true" msgstr "" "'nrow' und 'ncol' müssen gleich sein, wenn 'symmetric' auf true gesetzt ist" msgid "'x' must have length nrow^2 when 'symmetric' is true" msgstr "'x' muss die Länge nrow^2, wenn 'symmetric' auf true gesetzt ist" msgid "'ncol' is not a factor of length(x)" msgstr "'ncol' ist kein Faktor von length(x)" msgid "'nrow' is not a factor of length(x)" msgstr "'nrow' ist kein Faktor von length(x)" msgid "Class %s is not yet implemented" msgstr "Klasse %s noch nicht implementiert" #, fuzzy msgid "'%s' and '%s' must be positive integers" msgstr "Länge muss eine nicht negative Zahl sein" #, fuzzy msgid "matrix is not symmetric or triangular" msgstr "'x' ist weder symmetrisch noch in Dreiecksform" #, fuzzy msgid "matrix is not symmetric" msgstr "die Matrix ist nicht dreieckig" #, fuzzy msgid "matrix is not triangular" msgstr "'x' ist weder symmetrisch noch in Dreiecksform" msgid "" "the default value of argument '%s' of method '%s(<%s>, <%s>)' may change " "from %s to %s as soon as the next release of Matrix; set '%s' when " "programming" msgstr "" msgid "determinant of non-square matrix is undefined" msgstr "" msgid "replacement diagonal has wrong length" msgstr "" msgid "replacement diagonal has incompatible type \"%s\"" msgstr "" msgid "assigned dimensions are not of type \"%s\" or \"%s\"" msgstr "" msgid "assigned dimensions do not have length %d" msgstr "" msgid "assigned dimensions are NA" msgstr "" msgid "assigned dimensions are negative" msgstr "" msgid "assigned dimensions exceed %s" msgstr "" #, fuzzy msgid "assigned dimensions [product %.0f] do not match object length [%.0f]" msgstr "dim [produkt %d] passt nicht zur Länge des Objekts [%d]" msgid "'lwd' must be NULL or non-negative numeric" msgstr "'lwd' muss NULL oder nicht negativ numerisch sein" #, fuzzy msgid "%s(<%s>) is not yet implemented" msgstr "Klasse %s noch nicht implementiert" msgid "'%s' is not of type \"%s\" or \"%s\"" msgstr "" msgid "'%s' contains NA" msgstr "" msgid "'%s' has elements less than %d" msgstr "" #, fuzzy msgid "'%s' is not a non-negative number" msgstr "Länge muss eine nicht negative Zahl sein" msgid "'%s' has elements exceeding '%s'" msgstr "" msgid "'%s' is not %d or %d" msgstr "" #, fuzzy msgid "'%s' is not a permutation of seq_len(%s)" msgstr "'ncol' ist kein Faktor von length(x)" #, fuzzy msgid "matrix must have exactly one entry in each row or column" msgstr "muss genau einen Nicht-Null-Eintrag pro Zeile haben" #, fuzzy msgid "attempt to coerce non-square matrix to %s" msgstr "" "nicht symmetrische \"dgTMatrix\" kann nicht in \"dsCMatrix\" Klasse " "umgewandelt werden" #, fuzzy msgid "matrix must have exactly one entry in each row and column" msgstr "muss genau einen Nicht-Null-Eintrag pro Zeile haben" #, fuzzy msgid "'%s' via sparse -> dense coercion" msgstr "rcond(.) über Umwandlung dünn besetzt -> dicht besetzt" #, fuzzy msgid "invalid %s=\"%s\"" msgstr "ungültige nargs()= %d" msgid "norm" msgstr "" #, fuzzy msgid "'%s' method must use default %s=\"%s\"" msgstr "kronecker-Methode muss Standard 'FUN' benutzen" #, fuzzy msgid "number of nonzero entries cannot exceed %s" msgstr "Anzahl der Zeilen ist nicht kompatibel für %s" msgid "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", or \"%4$s\"" msgstr "" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%2$s2\", \"%2$s2.\", \"%3$s\", or " "\"%4$s\"" msgstr "" msgid "non-conformable arguments" msgstr "nicht passende Argumente" #, fuzzy msgid "model frame and formula mismatch in sparse.model.matrix()" msgstr "Model-Frame und Formel passen nicht zusammen in model.matrix()" #, fuzzy msgid "non-list contrasts argument ignored" msgstr "unzulässiges 'contrasts.arg' Argument" #, fuzzy msgid "'contrasts.arg' argument must be named" msgstr "unzulässiges 'contrasts.arg' Argument" msgid "variable '%s' is absent, its contrast will be ignored" msgstr "Variable '%s' fehlt, ihr Kontrast wird irgnoriert" msgid "Matrix seems negative semi-definite" msgstr "Matrix scheint negativ semidefinit zu sein" msgid "'nearPD()' did not converge in %d iterations" msgstr "nearPD() ist nicht in %d Iterationen konvergiert" #, fuzzy msgid "'cl' is not a character string" msgstr "'V' ist keine *quadratische* Matrix" msgid "" "not a positive definite matrix (and positive semidefiniteness is not checked)" msgstr "" #, fuzzy msgid "'%s' is not a square numeric matrix" msgstr "'V' ist keine *quadratische* Matrix" #, fuzzy msgid "" "diag(%s) has non-positive or non-finite entries; finite result is doubtful" msgstr "" "diag(.) hatte 0 oder NA Einträge. Nicht-endliches Ergebnis ist zweifelhaft" msgid "" "matrix is structurally rank deficient; using augmented matrix with " "additional %d row(s) of zeros" msgstr "" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%2$s2\", \"%2$s2.\", \"%3$s\", " "\"%3$s1\", \"%4$s\", or \"%4$s1\"" msgstr "" #, fuzzy msgid "'%s' has the wrong length" msgstr "RHS 'b' hat falsche Länge" #, fuzzy msgid "invalid '%s': not in %d:%d" msgstr "ungültige 'col.names'-Zeichenkette: %s" msgid "need greater '%s' as pivoting occurred" msgstr "" msgid "qr2rankMatrix(.): QR with only %d out of %d finite diag(R) entries" msgstr "" "qr2rankMatrix(.): QR Zerlegung mit nur %d von %d endlichen diag(R) Werten" msgid "" "rankMatrix(, method = '%s') coerces to dense matrix.\n" " Probably should rather use method = 'qr' !?" msgstr "" "rankMatrix(, method = '%s') wird in dicht\n" "besetzte Matrix umgewandelt. Evtl. eher method = 'qr' nutzen? " msgid "rankMatrix(x, method='qr'): computing t(x) as nrow(x) < ncol(x)" msgstr "rankMatrix(x, method='qr'): t(x) berechnet, da nrow(x) < ncol(x)" #, fuzzy msgid "[[ suppressing %d column name%s %s ... ]]" msgstr "[[ unterdrücke %d Spaltennamen %s ...]]" msgid "invalid 'col.names' string: %s" msgstr "ungültige 'col.names'-Zeichenkette: %s" msgid "uniDiag=TRUE, but not all diagonal entries are 1" msgstr "uniDiag=TRUE, aber nicht alle Diagonaleinträge sind 1" msgid "uniDiag=TRUE, not all entries in diagonal coded as 1" msgstr "uniDiag=TRUE, aber nicht alle Einträge der Diagonalen als 1 kodiert" #, fuzzy msgid "in show(); maybe adjust options(max.print=, width=)" msgstr "in show(); evtl. 'options(max.print= *, width= *)' anpassen" msgid "suppressing %d columns and %d rows" msgstr "%d Spalten und %d Zeilen werden unterdrückt" msgid "suppressing %d rows" msgstr "%d Zeilen werden unterdrückt" msgid "suppressing %d columns" msgstr "%d Spalten werden unterdrückt" msgid "logic programming error in printSpMatrix2(), please report" msgstr "logischer Programmierfehler in printSpMatrix2(), bitte berichten" #, fuzzy msgid "'%s' is not square" msgstr "'V' ist keine quadratische Matrix" msgid "dimensions of '%s' and '%s' are inconsistent" msgstr "" msgid "'%1$s' is computationally singular, rcond(%1$s)=%2$g" msgstr "" msgid "'%s' is computationally singular, min(d)/max(d)=%g, d=abs(diag(U))" msgstr "" msgid "matrix is exactly singular, D[i,i]=0, i=%d" msgstr "" msgid "matrix is exactly singular, J[,j]=0, j=%d" msgstr "" msgid "matrix exactly singular, J[i,]=0, i=%d" msgstr "" msgid "cannot coerce from %s to %s" msgstr "" msgid "a sparseMatrix should rarely be centered: will not be sparse anymore" msgstr "" "eine schwach besetze Matrix sollte kaum je zentriert werden: sie ist dann " "nicht mehr schwach besetzt" msgid "length of 'center' must equal the number of columns of 'x'" msgstr "Länge von 'center' muss der Spaltenzahl von 'x' entsprechen" msgid "length of 'scale' must equal the number of columns of 'x'" msgstr "Länge von 'scale' muss der Spaltenzahl von 'x' entsprechen" #, fuzzy msgid "invalid subassignment value class \"%s\"" msgstr "ungültige Klasse: %s" #, fuzzy msgid "invalid subassignment value type \"%s\"" msgstr "Ungültiger Speichertyp: %s" msgid "missing subassignment value" msgstr "" #, fuzzy msgid "incorrect number of dimensions" msgstr "inkompatible Matrixdimensionen" msgid "replacement has length zero" msgstr "" msgid "number of items to replace is not a multiple of replacement length" msgstr "" "Anzahl der zu ersetzenden Elemente ist kein Vielfaches der Austauschlänge" msgid "" ".M.repl.i.2col(): 'i' has no integer column number;\n" " should never happen; please report" msgstr "" ".M.repl.i.2col(): 'i' hat keine ganzzahlige Spaltennummer.\n" "Sollte nie passieren. Bitte melden." msgid "such indexing must be by logical or 2-column numeric matrix" msgstr "" "solche Indexierung muss von logischer oder 2-spaltig numerischer Matrix sein" msgid ".M.repl.i.2col(): drop 'matrix' case ..." msgstr ".M.repl.i.2col(): 'matrix'-Fall weglassen ..." msgid "negative values are not allowed in a matrix subscript" msgstr "negative Werte sind in einer Matrix-Subskript nicht erlaubt" msgid "NAs are not allowed in subscripted assignments" msgstr "NAs sind in indexierten Anweisungen nicht erlaubt" msgid "m[ ] <- v: inefficiently treating single elements" msgstr "m[ ] <- v: Einzelne Elemente ineffizient behandelt" msgid "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' ?" msgstr "nargs() = %d. Irrelevante ungültige Argumente innerhalb '[ .. ]'?" msgid "RHS 'value' (class %s) matches 'ANY', but must match matrix class %s" msgstr "" "RHS 'value' (Klasse %s) passt zu 'ANY', muss aber zur Matrixklasse %s passen" msgid "not-yet-implemented 'Matrix[<-' method" msgstr "noch nicht implementierte 'Matrix[<-'-Methode" msgid "invalid nargs()= %d" msgstr "ungültige nargs()= %d" msgid "nothing to replace with" msgstr "nichts zu ersetzen mit" msgid "too many replacement values" msgstr "zu viele Austauschwerte" msgid "i1[1] == 0 ==> C-level verbosity will not happen!" msgstr "i1[1] == 0 ==> C-Ebene wird nicht detailliert sein!" msgid "using\t \"old code\" part in Csparse subassignment" msgstr "benutzt wird\t 'alter Kode'-Teil in Csparse-Unterzuweisung" msgid "" "using\"old code\" part in Csparse subassignment\n" " >>> please report to Matrix-authors@r-project.org" msgstr "" "benutzt wird 'alter Kode'-Teil in Csparse-Unterzuweisung\n" " >>> bitte an Matrix-authors@r-project.org berichten" msgid "you cannot mix negative and positive indices" msgstr "Sie können positive und negative Indizes nicht mischen" msgid "index larger than maximal %d" msgstr "Index größer als maximales %d" msgid "'NA' indices are not (yet?) supported for sparse Matrices" msgstr "" "'NA'-Indizes werden (noch?) nicht für dünn besetzte Matrizen unterstützt" msgid "logical subscript too long (%d, should be %d)" msgstr "logisches Subskript zu lang (%d, sollte %d sein)" msgid "no 'dimnames[[.]]': cannot use character indexing" msgstr "keine 'dimnames[[.]]': Zeichenindexierung kann nicht benutzt werden" msgid "invalid character indexing" msgstr "ungültige Zeichenindexierung" msgid "internal bug: missing 'i' in replTmat(): please report" msgstr "interner Fehler: Fehlendes 'i' in replTmat(): Bitte berichten" msgid "[ ] indexing not allowed: forgot a \",\" ?" msgstr "[ ] Indexierung nicht erlaubt: Ein ',' vergessen?" msgid "internal bug: matrix 'i' in replTmat(): please report" msgstr "interner Fehler: Matrix 'i' in replTmat(): Bitte berichten" msgid "" "x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced; NA |--> TRUE." msgstr "" "x[.] <- val: x ist %s, val nicht in {TRUE, FALSE}, wird umgewandelt;\n" "NA |--> TRUE." msgid "x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced." msgstr "x[.] <- val: x ist %s, val nicht in {TRUE, FALSE}, wird umgewandelt." msgid "" "x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE." msgstr "" "x[.,.] <- val: x ist %s, val nicht in {TRUE, FALSE} wird umgewandelt NA |--> " "TRUE." msgid "x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced." msgstr "x[.,.] <- val: x ist %s, val nicht in {TRUE, FALSE} wird umgewandelt" msgid "x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrix" msgstr "x[.,.] <- val : x wird von Tsparse* in CsparseMatrix umgewandelt" msgid "nargs() = %d should never happen; please report." msgstr "nargs() = %d sollte niemals vorkommen. Bitte berichten." msgid "row indices must be <= nrow(.) which is %d" msgstr "Zeilenindizes müssen <= nrow(.) sein, das ist %d" msgid "column indices must be <= ncol(.) which is %d" msgstr "Spaltenindizes müssen <= ncol(.) sein, das ist %d" msgid "Internal bug: nargs()=%d; please report" msgstr "Interner Fehler: nargs()=%d; bitte melden" msgid "" "index must be numeric, logical or sparseVector for indexing sparseVectors" msgstr "" "Index muss numerisch, logisch oder sparseVector sein, um sparseVector zu " "indizieren" #, fuzzy msgid "invalid subscript class \"%s\"" msgstr "ungültige Klasse: %s" #, fuzzy msgid "invalid subscript type \"%s\"" msgstr "Ungültiger Speichertyp: %s" msgid "recycled %s would have maximal index exceeding %s" msgstr "" msgid "subscripts exceeding %s replaced with NA" msgstr "" msgid "subscript out of bounds" msgstr "" #, fuzzy msgid "logical subscript too long" msgstr "logisches Subskript zu lang (%d, sollte %d sein)" msgid "only zeros may be mixed with negative subscripts" msgstr "" msgid "trimmed means are not defined for complex data" msgstr "" msgid "first element used of '%s' argument" msgstr "" #, fuzzy msgid "invalid '%s' argument" msgstr "ungültiges 'data'" #, fuzzy msgid "should never happen ..." msgstr "Sollte niemals vorkommen. Bitte berichten." msgid "'%s' is deprecated; using '%s' instead" msgstr "" msgid "'%s' is deprecated; setting %s=\"%s\"" msgstr "" msgid "'%s' has length 0 but '%s' does not" msgstr "" #, fuzzy msgid "attempt to coerce matrix with NA to %s" msgstr "" "nicht symmetrische \"dgTMatrix\" kann nicht in \"dsCMatrix\" Klasse " "umgewandelt werden" #, fuzzy msgid "invalid 'Class2'" msgstr "ungültiges 'data'" #~ msgid "qr2rankMatrix(.): QR has negative diag(R) entries" #~ msgstr "qr2rankMatrix(.): QR enthält negative diag(R) Werte" #, fuzzy #~ msgid "invalid 'each' argument" #~ msgstr "falsches Vorzeichen im Argument 'by'" #, fuzzy #~ msgid "invalid 'times' argument" #~ msgstr "ungültiges 'data'" #~ msgid "" #~ "not-yet-implemented method for %s(<%s>).\n" #~ " ->> Ask the package authors to implement the missing feature." #~ msgstr "" #~ "noch nicht implementierte Methode für %s(<%s>).\n" #~ " ->> Bitten Sie die Autoren des Pakets, diese fehlende Funktion zu " #~ "implementieren." #~ msgid "" #~ "not-yet-implemented method for %s(<%s>, <%s>).\n" #~ " ->> Ask the package authors to implement the missing feature." #~ msgstr "" #~ "noch nicht implementierte Methode für %s(<%s>, <%s>).\n" #~ " ->> Bitten Sie die Autoren des Pakets, diese fehlende Funktion zu " #~ "implementieren." #, fuzzy #~ msgid "complex \"diagonalMatrix\" not yet implemented" #~ msgstr "allgemeine Matrixklasse noch nicht implementiert für %s" #, fuzzy #~ msgid "not yet implemented for class \"%s\"" #~ msgstr "noch nicht implementiert für Klasse %s" #, fuzzy #~ msgid "invalid 'uplo'" #~ msgstr "ungültiger 'type'" #~ msgid "'lag' and 'differences' must be integers >= 1" #~ msgstr "'lag' und 'differences' müssen ganze Zahlen >=1 sein" #~ msgid "" #~ "programming error: min() should have dispatched w/ 1st arg much earlier" #~ msgstr "" #~ "Programmierfehler: min() ohne erstes Argument hätte eher abgefangen sein " #~ "müssen" #~ msgid "in Summary(, .): %s(<%s>, <%s>,...)" #~ msgstr "in Summary(, .): %s(<%s>, <%s>, ...)" #~ msgid "in Summary(, .): %s(<%s>, <%s>)" #~ msgstr "in Summary(, .): %s(<%s>, <%s>)" #, fuzzy #~ msgid "number of rows of matrices must match" #~ msgstr "Anzahl der Zeilen ist nicht kompatibel für %s" #, fuzzy #~ msgid "number of columns of matrices must match" #~ msgstr "Anzahl der Zeilen ist nicht kompatibel für %s" #~ msgid "resulting x-slot has different type than x's or y's" #~ msgstr "resultierender x-slot hat einen anderen Typ als x oder y" #, fuzzy #~ msgid "dimensions must be numeric of length 2" #~ msgstr "dim(.)-Wert muss numerisch sein und die Länge 2 haben" #, fuzzy #~ msgid "'perm' must be numeric" #~ msgstr "'A' muss eine quadratische Matrix sein" #, fuzzy #~ msgid "'margin' must be 1 or 2" #~ msgstr "'ncol' muss >= 0 sein" #~ msgid "not-yet-implemented method for <%s> %%*%% <%s>" #~ msgstr "noch nicht implementierte Methode für <%s> %%*%% <%s>" #~ msgid "'boolArith = %d' not yet implemented" #~ msgstr "'boolArith = %d' noch nicht implementiert" #, fuzzy #~ msgid "'rcond' via sparse -> dense coercion" #~ msgstr "rcond(.) über Umwandlung dünn besetzt -> dicht besetzt" #, fuzzy #~ msgid "invalid 'norm'" #~ msgstr "ungültiges 'data'" #, fuzzy #~ msgid "cannot coerce zsparseVector to dgCMatrix" #~ msgstr "'NA's können nicht in \"ngCMatrix\" umgewandelt werden" #, fuzzy #~ msgid "cannot coerce zsparseVector to dgeMatrix" #~ msgstr "Kann NAs nicht in 'nsparseVector' umwandeln" #~ msgid "" #~ "number of non zeros is smaller than 'nnz' because of duplicated (i,j)s" #~ msgstr "" #~ "Anzahl von Nicht-Nullen ist kleiner als 'nnz' wegen doppelter (i,j)s" #~ msgid "'times >= 0' is required" #~ msgstr "'times >= 0' wird benötigt" #~ msgid "Matrices must have same number of rows in %s" #~ msgstr "Matrizen müssen die gleiche Anzahl Zeilen in %s haben" #~ msgid "Matrices must have same number of columns in %s" #~ msgstr "Matrizen müssen die gleiche Anzahl Spalten in %s haben" #, fuzzy #~ msgid "only lists of length 2 can be coerced to indMatrix" #~ msgstr "'lMatrix'-Objekt mit NAs kann nicht zu 'nMatrix' umgewandelt werden" #, fuzzy #~ msgid "only 2-dimensional tables can be coerced to sparseMatrix" #~ msgstr "" #~ "nur 2-dimensionale Tabellen könne direkt in eine dünn besetzte Matrix " #~ "umgewandelt werden" #, fuzzy #~ msgid "matrix is not symmetric or" #~ msgstr "'x' ist weder symmetrisch noch in Dreiecksform" #, fuzzy #~ msgid "triangular" #~ msgstr "keine Dreiecksmatrix" #, fuzzy #~ msgid "matrix is not" #~ msgstr "Matrix ist nicht diagonal" #~ msgid "'x' is not positive definite -- chol() undefined." #~ msgstr "'x' ist nicht positiv definit -- chol() undefiniert." #~ msgid "Matrices must have same dimensions in %s" #~ msgstr "Matrizen müssen in %s die gleichen Dimensionen haben" #~ msgid "names(dimnames()) must be NULL or of length two" #~ msgstr "names(dimnames()) muss entweder NULL oder von Länge 2 sein" #~ msgid "[[ suppressing %d column names %s ]]" #~ msgstr "[[ unterdrücke %d Spaltennamen %s ]]" #~ msgid "'x' must be \"sparseMatrix\"" #~ msgstr "'x' muss \"sparseMatrix\" sein" #~ msgid "not yet implemented for matrix with typeof %s" #~ msgstr "noch nicht implementiert für Matrix mit typeof %s" #~ msgid "not yet implemented for %s" #~ msgstr "noch nicht implementiert für %s" #~ msgid "" #~ "Quadratic matrix '%s' (=: A) is not formally\n" #~ "\tsymmetric. Will be treated as\tA A'" #~ msgstr "" #~ "Die quadratische Matrix '%s' (=: A) ist formal\n" #~ " nicht symmetrisch. Wird behandelt wie A A'" #~ msgid "" #~ "'update' must be logical or '+' or '-'; 'C' a matrix, and 'L' a " #~ "\"CHMfactor\"" #~ msgstr "" #~ "'update' muss entweder boolesch, '+' oder '-' sein; 'C' eine Matrix\n" #~ "und 'L' ein \"CHMfactor\"" #~ msgid "update must be TRUE/FALSE or '+' or '-'" #~ msgstr "update muss entweder TRUE/FALSE, '+' oder '-' sein" #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "Matrixinterner Fehler in [i,,d]. Bitte berichten" #~ msgid "" #~ "Cholesky() -> *symbolic* factorization -- not yet implemented" #~ msgstr "" #~ "Cholesky() -> *symbolische* Faktorisierung – noch nicht " #~ "implementiert" #~ msgid "" #~ "as.matrix() is deprecated (to become a no-op in the future).\n" #~ "Use as(x, \"matrix\") or .asmatrix(x) instead." #~ msgstr "" #~ "as.matrix() is veraltet (und zukünftig no-op).\n" #~ "Bitte as(x, \"matrix\") oder .asmatrix() stattdessen nutzen." #~ msgid "" #~ "as.array() is deprecated. Use as(x, \"matrix\") or .asmatrix(x) " #~ "instead." #~ msgstr "" #~ "as.array() ist veraltet. Bitte stattdessen as(x, \"matrix\") " #~ "oder .asmatrix(x) nutzen" #~ msgid "trimmed mean of 'sparseVector' -- suboptimally using as.numeric(.)" #~ msgstr "" #~ "getrimmter Mittelwert von 'sparseVector' – suboptimalerweise wird as." #~ "numeric(.) benutzt" #~ msgid "invalid dimnames given for %s object" #~ msgstr "ungültige dimnames für %s Objekt gegeben" #~ msgid "" #~ "dimnames(.) <- NULL: translated to \n" #~ "dimnames(.) <- list(NULL,NULL) <==> unname(.)" #~ msgstr "" #~ "dimnames(.) <- NULL: übersetzt in\n" #~ "dimnames(.) <- list(NULL,NULL) <==> unname(.)" #~ msgid "" #~ "'nrow', 'ncol', etc, are disregarded when 'data' is \"Matrix\" already" #~ msgstr "" #~ "'nrow', 'ncol', etc. werden nicht berücksichtigt, wenn 'data' bereits " #~ "'Matrix' ist" #~ msgid "complex matrices not yet implemented in Matrix package" #~ msgstr "komplexe Matrizen noch nicht im Matrix-Paket implementiert" #~ msgid "using slow kronecker() method" #~ msgstr "langsame kronecker()-Methode wird benutzt" #~ msgid "" #~ "Cholesky(A) called for 'A' of class \"%s\";\n" #~ "\t it is currently defined for sparseMatrix only; consider using chol() " #~ "instead" #~ msgstr "" #~ "Cholesky(A) für 'A' der Klasse \"%s\" aufgerufen;\n" #~ "\t es ist derzeit nur für sparseMatrix definiert; erwägen Sie, chol() zu " #~ "benutzen " #~ msgid "invalid or not-yet-implemented 'Matrix' subsetting" #~ msgstr "ungültige oder noch nicht implementierte 'Matrix'-Untermenge" #~ msgid "[ ] : .M.sub.i.logical() maybe inefficient" #~ msgstr "[ ] : .M.sub.i.logical() könnte ineffizient sein" #~ msgid "" #~ "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' (i.logical)?" #~ msgstr "" #~ "nargs() = %d. Irrelevante ungültige Argumente innerhalb '[ .. ]' (i." #~ "logical)?" #~ msgid "" #~ "m[]: inefficiently indexing single elements - should not " #~ "happen, please report!" #~ msgstr "" #~ "m[ ]: ineffiziente Indexierung einzelner Elemente - sollte " #~ "nicht passieren, bitte rückmelden!" #~ msgid "" #~ "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' (i.2col)?" #~ msgstr "" #~ "nargs() = %d. Irrelevante ungültige Argumente innerhalb '[ .. ]' (i.2col)?" #~ msgid "" #~ ".M.sub.i.2col(): 'i' has no integer column number;\n" #~ " should never happen; please report" #~ msgstr "" #~ ".M.sub.i.2col(): 'i' hat keine ganzzahlige Spaltennummer.\n" #~ "Sollte nie passieren. Bitte melden!" #~ msgid "not-yet-implemented coercion to \"TsparseMatrix\"" #~ msgstr "noch nicht implementierte Typumwandlung zu 'TsparseMatrix'" #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "Matrix-interner Fehler in [i,,d]; Bitte berichten" #~ msgid "FIXME: NOT YET FINISHED IMPLEMENTATION" #~ msgstr "ZU ERLEDIGEN: NOCH NICHT ABGESCHLOSSENE IMPLEMENTIERUNG" #~ msgid "diagonalMatrix in .dense2C() -- should never happen, please report!" #~ msgstr "" #~ "diagonalMatrix in .dense2C() -- sollte niemals vorkommen. Bitte berichten." #~ msgid "undefined method for class %s" #~ msgstr "undefinierte Methode für Klasse %s" #~ msgid "dimensions don't match the number of cells" #~ msgstr "Dimensionen passen nicht zur Anzahl der Zellen" #~ msgid "" #~ "LU computationally singular: ratio of extreme entries in |diag(U)| = %9.4g" #~ msgstr "" #~ "Die LU Zerlegung ist computational singulär; Quotient der extremen " #~ "Elemente von |diag(U)| = %9.4g" #~ msgid "RHS 'b' has wrong number of rows:" #~ msgstr "RHS 'b' hat falsche Zahl Zeilen:" #~ msgid "'x' has invalid data type" #~ msgstr "'x' hat ungültigen Datentyp" #~ msgid "length(x) must be either 1 or #{cols}" #~ msgstr "length(x) muss 1 oder #{cols} sein" #~ msgid "some arguments are not matrices" #~ msgstr "einige Argumente sind keine Matrizen" #~ msgid "%s kind not yet implemented" #~ msgstr "%s-Art noch nicht implementiert" #~ msgid "non-square matrix" #~ msgstr "nicht quadratische Matrix" #~ msgid "" #~ "matrix with non-zero off-diagonals cannot be coerced to \"diagonalMatrix\"" #~ msgstr "" #~ "Matrix mit Nichtdiagonalelementen ungleich Null kann nicht in " #~ "\"diagonalMatrix\" umgewandelt werden" #~ msgid "non-matching dimensions" #~ msgstr "nicht passende Dimensionen" #~ msgid "not a positive definite matrix" #~ msgstr "keine positiv definite Matrix" #~ msgid "" #~ "as(.,\"dsCMatrix\") is deprecated (since 2008); do use as(., " #~ "\"symmetricMatrix\")" #~ msgstr "" #~ "as(.,\"dsCMatrix\") ist veraltet (seit 2008). Benutzen Sie as(., " #~ "\"symmetricMatrix\")" #~ msgid "inefficient coercion (lost triangularity); please report" #~ msgstr "ineffiziente Umwandlung (Dreiecksgestalt verloren). Bitte berichten" #~ msgid "coercion to \"indMatrix\" only works from integer numeric" #~ msgstr "" #~ "Umwandlung zu \"indMatrix\" funktioniert nur von ganzzahligen numerischen " #~ "Werten" #~ msgid "" #~ "coercion from list(i1,...,ik, d) to \"indMatrix\" failed.\n" #~ " All entries must be integer valued and the number of columns, d, not " #~ "smaller\n" #~ " than the maximal index i*." #~ msgstr "" #~ "Umwandlung von list(i1,...,ik, d) zu \"indMatrix\" gescheitert.\n" #~ " Alle Elemente müssen ganzzahlig sein und die Anzahl Spalten, d, nicht " #~ "kleiner\n" #~ " als der maximale Index i*." #~ msgid "the number of non-zero entries differs from nrow(.)" #~ msgstr "die Anzahl der Nicht-Null-Einträge weicht von nrow(.) ab" #~ msgid "resulting matrix dimension would be too large" #~ msgstr "Dimenson der Ergebnismatrix wäre zu groß" #~ msgid "replacing \"indMatrix\" entries is not allowed, as rarely sensible" #~ msgstr "" #~ "Ersetzen von \"indMatrix\"-Einträgen ist nicht erlaubt, da selten sinnvoll" #~ msgid "temporarily disabled" #~ msgstr "zeitweise ausgeschaltet" #~ msgid "cannot coerce NA values to pattern \"ntCMatrix\"" #~ msgstr "'NA's können nicht in \"ntCMatrix\" umgewandelt werden" #~ msgid "coercion to \"pMatrix\" only works from integer numeric" #~ msgstr "" #~ "Umwandlung zu \"pMatrix\" funktioniert nur von ganzzahligen numerischen " #~ "Werten" #~ msgid "not a square matrix" #~ msgstr "keine quadratische Matrix" #~ msgid "NA's in (i,j) are not allowed" #~ msgstr "NAs sind in (i,j) nicht erlaubt" #~ msgid "" #~ "Both 'symmetric' and 'triangular', i.e. asking for diagonal matrix. Use " #~ "'Diagonal()' instead" #~ msgstr "" #~ "Sowohl 'symmetric' als auch 'triangular', also Diagonalgestalt. Nutze\n" #~ " stattdessen 'Diagonal()'" #~ msgid "triangular matrix must have all i >= j or i <= j" #~ msgstr "Deicksmatrix muss entweder alle i >= j oder i <= j haben" #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "Matrix-interner Fehler in [i,,d]. Bitte berichten" #~ msgid "" #~ "qr.R() may differ from qr.R() because of permutations. " #~ "Possibly use our qrR() instead" #~ msgstr "" #~ "qr.R() könnte von qr.R() aufgrund von Permutationen " #~ "abweichen. Evtl. besser qrR() nutzen." #~ msgid "(un)packing only applies to dense matrices, class(x)='%s'" #~ msgstr "" #~ "(ent)packen ist nur für dicht besetzte Matrizen anwendbar, class(x)='%s'" #, fuzzy #~ msgid "'x' is not symmetric -- chol() undefined." #~ msgstr "'x' ist nicht positiv definit -- chol() undefiniert." #~ msgid "" #~ "extra argument %s will be disregarded in\n" #~ " %s" #~ msgid_plural "" #~ "extra arguments %s will be disregarded in\n" #~ " %s" #~ msgstr[0] "extra Argument %s wird nicht berücksichtigt in %s" #~ msgstr[1] "extra Argumente %s werden nicht berücksichtigt in %s" #~ msgid " %s %s is undefined" #~ msgstr " %s %s ist undefiniert" #~ msgid "%s %s is undefined" #~ msgstr "%s %s ist undefiniert" #~ msgid "variable '%s' converted to a factor" #~ msgstr "Variable '%s' konvertiert in einen Faktor" #~ msgid "\"dMatrix\" object with NAs cannot be coerced to \"nMatrix\"" #~ msgstr "" #~ "\"dMatrix\"-Objekt mit NAs kann nicht in \"nMatrix\" umgewandelt werden" #~ msgid "not a skinny matrix" #~ msgstr "keine lange (\"skinny\") Matrix" #~ msgid "longer object length" #~ msgstr "längere Objektlänge" #~ msgid "is not a multiple of shorter object length" #~ msgstr "ist kein Vielfaches der kürzeren Objektlänge" #~ msgid "duplicate ij-entries in 'Matrix[ ij ] <- value'; using last" #~ msgstr "" #~ "doppelte ij-Einträge in 'Matrix[ IJ ] <- value'. Letzter wird benutzt" #, fuzzy #~ msgid "method %s not applicable for qr() result class %s" #~ msgstr "Methode '%s' nicht nutzbar für das qr() Ergebniss der Klasse '%s'" #, fuzzy #~ msgid "too large index i > n = %d" #~ msgstr "zu großer Index i > n =" #~ msgid "," #~ msgstr "," #~ msgid "..." #~ msgstr "..." #~ msgid "arguments" #~ msgstr "Argumente" #~ msgid ")$" #~ msgstr ")$" #~ msgid "^list\\(" #~ msgstr "^list\\\\(" #~ msgid "dimnames(.) <- NULL: translated to" #~ msgstr "dimnames(.) <- NULL: übersetzt zu" #~ msgid ", ..." #~ msgstr ", ..." #~ msgid "" #~ msgstr "" #~ msgid "(0) is undefined" #~ msgstr "(0) ist undefiniert" #~ msgid "(0)" #~ msgstr "(0)" #~ msgid "no longer representable as 'rleDiff'" #~ msgstr "nicht länger als 'rleDiff' darstellbar" #~ msgid "hence, all k must have the same sign" #~ msgstr "daher müssen alle k das Zeichen haben" #~ msgid "too short; filling with NA's" #~ msgstr "zu kurz. Wird mit NAs gefüllt" #~ msgid "iterations" #~ msgstr "Iterationen" #~ msgid "'" #~ msgstr "'" #~ msgid "; please report" #~ msgstr ". Bitte berichten" #~ msgid "type '" #~ msgstr "Typ '" #~ msgid "representation '" #~ msgstr "Entsprechung '" #~ msgid "element type '" #~ msgstr "Elementtyp '" #~ msgid "symmetry form '" #~ msgstr "symmetrische Form '" #~ msgid "numeric()" #~ msgstr "numeric()" #~ msgid "must supply either 'formula' or 'data'" #~ msgstr "entweder 'formula' oder 'data' muss angegeben werden" #~ msgid "'formula' missing or incorrect" #~ msgstr "'formula' fehlt oder ist falsch" #~ msgid "interactions are not allowed" #~ msgstr "Wechselwirkungen sind nicht erlaubt" #~ msgid "xtabs(*, sparse=TRUE) applies only to two-way tables" #~ msgstr "xtabs(*, sparse=TRUE) liefert nur wechselseitige Tabellen" #~ msgid "cbind2() method for (%s,%s) not-yet defined" #~ msgstr "cbind2()-Methode für (%s,%s) noch nicht definiert" #~ msgid "not yet implemented for packed class" #~ msgstr "noch nicht für gepackte Klasse implementiert" #~ msgid "numeric(0)" #~ msgstr "numeric(0)" #~ msgid "'NA's coerced to 'FALSE' in coercion to logical sparse" #~ msgstr "'NA's zu 'FALSE' umwandeln in Umwandlung zu logisch dünne besetzt" #~ msgid "crossprod(x) calculated as x %*% x for sparse, symmetric x" #~ msgstr "" #~ "crossprod(x) berechnete als x %*% x für dünn besetztes,symmetrisches x" #~ msgid "tcrossprod(x) calculated as x %*% x for sparse, symmetric x" #~ msgstr "" #~ "tcrossprod(x) berechnete als x %*% x für dünn besetztes,symmetrisches x" #~ msgid "(j,p) --> RsparseMatrix : not yet implemented" #~ msgstr "(j,p) --> RsparseMatrix : Noch nicht implementiert" #~ msgid "unknown method" #~ msgstr "unbekannte Methode" #~ msgid "indexing out of range 0:" #~ msgstr "Indexierung außerhalb des Bereichs 0:" #~ msgid "nargs() =" #~ msgstr "nargs() =" #~ msgid "nrow * ncol < length(x)" #~ msgstr "'nrow' * ncol < length(x)" #~ msgid "nrow * ncol != length(x)" #~ msgstr "'nrow' * ncol != length(x)" Matrix/po/R-it.po0000644000175100001440000012305714575137654013356 0ustar hornikusers# R Italian translation # This file is distributed under the same license as the R package. # Copyright (C) The R Foundation. # Daniele Medri , 2005-2021. # msgid "" msgstr "" "Project-Id-Version: R-Matrix 1.3-3\n" "Report-Msgid-Bugs-To: bugs.r-project.org\n" "POT-Creation-Date: 2024-03-15 17:22\n" "PO-Revision-Date: 2021-04-14 12:18+0200\n" "Last-Translator: Daniele Medri \n" "Language-Team: Italian https://github.com/dmedri/R-italian-lang\n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.2.1\n" #, fuzzy msgid "invalid mode \"%s\"" msgstr "'mod' non valido: %s" msgid "" "%s(<%s>, <%s>) is not yet implemented; ask maintainer(\"%s\") to implement " "the missing method" msgstr "" #, fuzzy msgid "complex %s not yet implemented" msgstr "La classe %s non è ancora implementata" #, fuzzy msgid "cannot coerce matrix of type \"%s\" to %s" msgstr "non è possibile la coercizione degli 'NA' in \"nsparseMatrix\"" #, fuzzy msgid "non0.i() not yet implemented for class %s" msgstr "non ancora implementato per la classe %s" msgid "%s=\"%s\" invalid for %s@uplo=\"%s\"" msgstr "" msgid "'%s' is not \"%1$s\", \"D%1$s\", or \"%1$s.\"" msgstr "" #, fuzzy msgid "%1$s(%2$s) is undefined: '%2$s' is not positive semidefinite" msgstr "chol() non è definito per una matrice diagonale con voci negative" #, fuzzy msgid "matrix is not square" msgstr "la matrice non è diagonale" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", \"%3$s.\", \"%3$s1\", \"%3$s1." "\", or \"%4$s\"" msgstr "" #, fuzzy msgid "'%s' does not inherit from virtual class %s" msgstr "'x' deve ereditare da \"sparseVector\"" msgid "D[i,i] is NA, i=%d" msgstr "" msgid "D[i,i] is negative, i=%d" msgstr "" msgid "'%1$s' is not formally symmetric; factorizing tcrossprod(%1$s)" msgstr "" msgid "unexpected %s=\"%s\" in '%s' method" msgstr "" msgid "Not a valid format" msgstr "Non è un formato valido" msgid "'file' must be a character string or connection" msgstr "'file' dev'essere una stringa di caratteri o una connessione" msgid "Invalid storage type: %s" msgstr "Tipo di archiviazione non valido: %s" msgid "Only numeric sparse matrices allowed" msgstr "Sono ammesse solo matrici sparse numeriche" msgid "Invalid storage format: %s" msgstr "Formato di archiviazione non valido: %s" msgid "Invalid assembled indicator: %s" msgstr "Indicatore assemblato non valido:%s" msgid "file is not a MatrixMarket file" msgstr "il file non è un file MatrixMarket" msgid "type '%s' not recognized" msgstr "il tipo '%s' non è riconosciuto" msgid "representation '%s' not recognized" msgstr "rappresentazione '%s' non riconosciuta" msgid "element type '%s' not recognized" msgstr "tipo elemento '%s' non riconosciuto" msgid "symmetry form '%s' not recognized" msgstr "la forma di simmetria '%s' non è riconosciuta" msgid "readMM(): expected %d entries but found only %d" msgstr "" #, fuzzy msgid "readMM(): row indices 'i' are not in 1:nrow[=%d]" msgstr "readMM(): valori della\t riga 'i' non sono in 1:nr" #, fuzzy msgid "readMM(): column indices 'j' are not in 1:ncol[=%d]" msgstr "readMM(): i valori della colonna 'j' non sono in 1:nc" msgid "symmetry form 'skew-symmetric' not yet implemented for reading" msgstr "" "la forma di simmetria 'skew-symmetric' non è ancora implementata in lettura" msgid "symmetry form 'hermitian' not yet implemented for reading" msgstr "la forma di simmetria 'hermitian' non è ancora implementata in lettura" msgid "symmetry form '%s' is not yet implemented" msgstr "la forma di simmetria '%s' non è ancora implementata" msgid "element type 'complex' not yet implemented" msgstr "tipo di elemento 'complex' non ancora implementato" msgid "'%s()' is not yet implemented for element type '%s'" msgstr "'%s()' non è ancora implementato per il tipo elemento '%s'" msgid "'%s()' is not yet implemented for representation '%s'" msgstr "'%s()' non è ancora implementato per la rappresentazione '%s'" msgid "longer object length is not a multiple of shorter object length" msgstr "" "la lunghezza più lunga dell'oggetto non è un multiplo della lunghezza più " "corta dell'oggetto" #, fuzzy msgid "invalid class \"%s\" in '%s' method" msgstr "stringa 'col.names' non valida: %s" msgid "invalid type \"%s\" in '%s' method" msgstr "" msgid "non-conformable matrix dimensions in %s" msgstr "dimensioni matrice non conformi in %s" msgid "dimnames [%d] mismatch in %s" msgstr "dimnames [%d] non corrisponde in %s" msgid "inefficient method used for \"- e1\"" msgstr "utilizzato metodo inefficiente per \"- e1\"" msgid "dim [product %d] do not match the length of object [%d]" msgstr "dim [product %d] non corrisponde con la lunghezza dell'oggetto [%d]" msgid "internal bug in \"Compare\" method (Cmp.Mat.atomic); please report" msgstr "" "bug interno nel metodo \"Compare\" (Cmp.Mat.atomic); per piacere, riportatelo" msgid "Cmp.Mat.atomic() should not be called for diagonalMatrix" msgstr "Cmp.Mat.atomic() non dovrebbe essere chiamata per diagonalMatrix" msgid "Matrices must have same number of rows for arithmetic" msgstr "Le matrici devono avere il medesimo numero di righe per l'aritmetica" msgid "number of rows are not compatible for %s" msgstr "il numero di righe non sono compatibili per %s" msgid "length of 2nd arg does not match dimension of first" msgstr "" "la lunghezza del secondo argomento non corrisponde con la dimensione del " "primo" msgid "length of 1st arg does not match dimension of 2nd" msgstr "" "la lunghezza del primo argomento non corrisponde con la dimensione della " "seconda" msgid "internal bug in \"Logic\" method (Logic.Mat.atomic); please report" msgstr "" "bug interno nel metodo \"Logic\" (Logic.Mat.atomic); per piacere, segnalatelo" msgid "Logic.Mat.atomic() should not be called for diagonalMatrix" msgstr "Logic.Mat.atomic() non dovrebbe essere chiamato per diagonalMatrix" msgid "vector too long in Matrix - vector operation" msgstr "vettore troppo lungo in Matrix - operazione vettoriale" msgid "" "longer object length\n" "\tis not a multiple of shorter object length" msgstr "" "la lunghezza dell'oggetto più lungo\n" "\tnon è un multiplo di lunghezza di quello più corto" #, fuzzy msgid "invalid class \"%s\" object in '%s' method" msgstr "stringa 'col.names' non valida: %s" msgid "intermediate 'r' is of type %s" msgstr "la 'r' intermedia è di tipo %s" msgid "not yet implemented .. please report" msgstr "non ancora implementato .. per piacere riportalo" msgid "'%s' has non-finite values" msgstr "" msgid "'%1$s' is not \"%2$s\", \"%3$s\", or \"%2$s.\"" msgstr "" msgid "'force' must be (coercable to) TRUE or FALSE" msgstr "'force' dev'essere (coercibile in) TRUE o FALSE" msgid "invalid (to - from)/by in seq(.)" msgstr "(to - from)/by in seq(.) non valido" msgid "wrong sign in 'by' argument" msgstr "segno errato nell'argomento 'by'" msgid "'by' argument is much too small" msgstr "l'argomento 'by' è troppo piccolo" msgid "length must be non-negative number" msgstr "la lunghezza dev'essere un numero non negativo" msgid "too many arguments" msgstr "troppi argomenti" msgid "c(,..) of different kinds, coercing all to 'rleDiff'" msgstr "c(,..) di diverso tipo, convertendo tutto a 'rleDiff'" msgid "[i] is not yet implemented" msgstr "[i] non è ancora implementato" msgid "all() is not yet implemented" msgstr "all() non è ancora implementato" msgid "sum() is not yet implemented" msgstr "sum() non è ancora implementato" msgid "prod() is not yet implemented" msgstr "prod() non è ancora implementato" msgid "not yet implemented" msgstr "non ancora implementato" msgid "" "x / 0 for an x with sign-change\n" " no longer representable as 'rleDiff'" msgstr "" "x / 0 per un x con cambio di segno\n" " non è più rappresentabile come 'rleDiff'" msgid " --> is not yet implemented" msgstr " --> non è ancora implementato" msgid " --> is not yet implemented" msgstr " --> non è ancora implementato" #, fuzzy msgid "only square matrices can be used as graph incidence matrices" msgstr "" "solo le matrici quadrate possono essere utilizzate come matrici di incidenza " "per i grafici" #, fuzzy msgid "matrix is not symmetric; consider forceSymmetric(.) or symmpart(.)" msgstr "" "non è una matrice simmetrica; si consideri forceSymmetric() o symmpart()" #, fuzzy msgid "matrix is not triangular; consider triu(.) or tril(.)" msgstr "la matrice non è triangolare" msgid "matrix is not diagonal; consider Diagonal(x=diag(.))" msgstr "" #, fuzzy msgid "invalid type \"%s\" in '%s'" msgstr "'type' non valido" #, fuzzy msgid "invalid %s=\"%s\" to '%s'" msgstr "Tipo di archiviazione non valido: %s" msgid "dimensions cannot exceed %s" msgstr "" #, fuzzy msgid "invalid class \"%s\" in '%s'" msgstr "stringa 'col.names' non valida: %s" msgid "%s length cannot exceed %s" msgstr "" msgid "'A' must be a square matrix" msgstr "'A' dev'essere una matrice quadrata" msgid "must either specify 'A' or the functions 'A.x' and 'At.x'" msgstr "si deve specificare 'A' o le funzioni 'A.x' e 'At.x'" msgid "when 'A' is specified, 'A.x' and 'At.x' are disregarded" msgstr "quando 'A' è specificato, 'A.x' e 'At.x' sono ignorati" msgid "not converged in %d iterations" msgstr "non convergente in %d iterazioni" msgid "hit a cycle (1) -- stop iterations" msgstr "fine ciclo (1) - interrompe le iterazioni" msgid "hit a cycle (2) -- stop iterations" msgstr "fine ciclo (2) - interrompe le iterazioni" msgid "not enough new vecs -- stop iterations" msgstr "non ci sono abbastanza nuovi vettori -- si interrompono le iterazioni" msgid "invalid 'data'" msgstr "'data' non valido" #, fuzzy msgid "'nrow', 'ncol', 'byrow' disregarded for [mM]atrix 'data'" msgstr "'nrow', 'ncol' e gli altri, sono ignorati dai dati della matrice" msgid "data is too long" msgstr "" #, fuzzy msgid "exactly one of 'i', 'j', and 'p' must be missing from call" msgstr "uno tra 'i', 'j' o 'p' non deve essere presente nella chiamata" msgid "" "use Diagonal() to construct diagonal (symmetric && triangular) sparse " "matrices" msgstr "" #, fuzzy msgid "'giveCsparse' is deprecated; using 'repr' instead" msgstr "'giveCsparse' è stato deprecato; si utilizzerà 'repr'" #, fuzzy msgid "'giveCsparse' is deprecated; setting repr=\"T\" for you" msgstr "'giveCsparse' è stato deprecato; viene impostato 'repr = \"T\"'" #, fuzzy msgid "'p' must be a nondecreasing vector c(0, ...)" msgstr "'p' dev'essere un vettore non decrescente (0, ...)" msgid "dimensions cannot exceed 2^31-1" msgstr "" msgid "'i' and 'j' must not contain NA" msgstr "" msgid "'i' and 'j' must be" msgstr "" msgid "positive" msgstr "" msgid "non-negative" msgstr "" #, fuzzy msgid "invalid 'dims'" msgstr "'data' non valido" msgid "'dims' must contain all (i,j) pairs" msgstr "" msgid "symmetric matrix must be square" msgstr "la matrice simmetrica dev'esser quadrata" msgid "triangular matrix must be square" msgstr "la matrice triangolare dev'esser quadrata" msgid "p[length(p)]" msgstr "" msgid "length(i)" msgstr "" #, fuzzy msgid "is not an integer multiple of length(x)" msgstr "length(i) non è un multiplo di length(x)" msgid "length(x) must not exceed" msgstr "" #, fuzzy msgid "invalid 'repr'; must be \"C\", \"R\", or \"T\"" msgstr "'repr' non valido; dev'essere \"C\", \"T\", o \"R\"" #, fuzzy msgid "'n' must be a non-negative integer" msgstr "la lunghezza dev'essere un numero non negativo" msgid "'x' has unsupported class \"%s\"" msgstr "" msgid "'x' has unsupported type \"%s\"" msgstr "" msgid "attempt to recycle 'x' of length 0 to length 'n' (n > 0)" msgstr "" msgid "'shape' must be one of \"g\", \"t\", \"s\"" msgstr "" #, fuzzy msgid "'kind' must be one of \"d\", \"l\", \"n\"" msgstr "'repr' non valido; dev'essere \"C\", \"T\", o \"R\"" msgid "mismatch between typeof(x)=\"%s\" and kind=\"%s\"; using kind=\"%s\"" msgstr "" #, fuzzy msgid "'cols' must be numeric" msgstr "'ncol' dev'essere >= 0" msgid "'cols' has elements not in seq(0, length.out = n)" msgstr "" #, fuzzy msgid "'uplo' must be \"U\" or \"L\"" msgstr "'repr' non valido; dev'essere \"C\", \"T\", o \"R\"" #, fuzzy msgid "'lst' must be a list" msgstr "'ncol' dev'essere >= 0" msgid "'giveCsparse' has been deprecated; setting 'repr = \"T\"' for you" msgstr "'giveCsparse' è stato deprecato; viene impostato 'repr = \"T\"'" msgid "'giveCsparse' has been deprecated; will use 'repr' instead" msgstr "'giveCsparse' è stato deprecato; si utilizzerà 'repr'" msgid "'diagonals' matrix must have %d columns (= length(k) )" msgstr "la matrice 'diagonals' deve avere %d colonne (= length(k) )" msgid "'diagonals' must have the same length (%d) as 'k'" msgstr "'diagonals' deve avere la medesima lunghezza (%d) di 'k'" msgid "matrix can only be symmetric if square, but n != m" msgstr "la matrice può essere unicamente simmetrica se quadrata, ma n != m" msgid "" "for symmetric band matrix, only specify upper or lower triangle\n" " hence, all k must have the same sign" msgstr "" "per la matrice di bande simmetriche, specificare solo il triangolo superiore " "o inferiore\n" " poi, tutti i k devono avere lo stesso segno" msgid "the %d-th (sub)-diagonal (k = %d) is too short; filling with NA's" msgstr "la %d' (sotto)-diagonale (k = %d) è troppo corta; si riempie con NA" msgid "invalid 'repr'; must be \"C\", \"T\", or \"R\"" msgstr "'repr' non valido; dev'essere \"C\", \"T\", o \"R\"" msgid "'x' must inherit from \"sparseVector\"" msgstr "'x' deve ereditare da \"sparseVector\"" msgid "'ncol' must be >= 0" msgstr "'ncol' dev'essere >= 0" msgid "'nrow' must be >= 0" msgstr "'nrow' dev'essere >= 0" msgid "Must specify 'nrow' when 'symmetric' is true" msgstr "Bisogna specificare 'nrow' quando 'symmetric' è true" msgid "'nrow' and 'ncol' must be the same when 'symmetric' is true" msgstr "'nrow' e 'ncol' dev'essere uguali quando 'symmetric' è true" msgid "'x' must have length nrow^2 when 'symmetric' is true" msgstr "'x' deve avere lunghezza nrow^2 quando 'symmetric' è true" msgid "'ncol' is not a factor of length(x)" msgstr "'ncol' non è un fattore di length(x)" msgid "'nrow' is not a factor of length(x)" msgstr "'nrow' non è un fattore di length(x)" msgid "Class %s is not yet implemented" msgstr "La classe %s non è ancora implementata" #, fuzzy msgid "'%s' and '%s' must be positive integers" msgstr "la lunghezza dev'essere un numero non negativo" #, fuzzy msgid "matrix is not symmetric or triangular" msgstr "'x' non è simmetrica ne triangolare" #, fuzzy msgid "matrix is not symmetric" msgstr "la matrice non è triangolare" #, fuzzy msgid "matrix is not triangular" msgstr "'x' non è simmetrica ne triangolare" msgid "" "the default value of argument '%s' of method '%s(<%s>, <%s>)' may change " "from %s to %s as soon as the next release of Matrix; set '%s' when " "programming" msgstr "" msgid "determinant of non-square matrix is undefined" msgstr "" msgid "replacement diagonal has wrong length" msgstr "" msgid "replacement diagonal has incompatible type \"%s\"" msgstr "" msgid "assigned dimensions are not of type \"%s\" or \"%s\"" msgstr "" msgid "assigned dimensions do not have length %d" msgstr "" msgid "assigned dimensions are NA" msgstr "" msgid "assigned dimensions are negative" msgstr "" msgid "assigned dimensions exceed %s" msgstr "" #, fuzzy msgid "assigned dimensions [product %.0f] do not match object length [%.0f]" msgstr "dim [product %d] non corrisponde con la lunghezza dell'oggetto [%d]" msgid "'lwd' must be NULL or non-negative numeric" msgstr "'lwd' dev'essere NULL o un numerico non negativo" #, fuzzy msgid "%s(<%s>) is not yet implemented" msgstr "La classe %s non è ancora implementata" msgid "'%s' is not of type \"%s\" or \"%s\"" msgstr "" msgid "'%s' contains NA" msgstr "" msgid "'%s' has elements less than %d" msgstr "" #, fuzzy msgid "'%s' is not a non-negative number" msgstr "la lunghezza dev'essere un numero non negativo" msgid "'%s' has elements exceeding '%s'" msgstr "" msgid "'%s' is not %d or %d" msgstr "" #, fuzzy msgid "'%s' is not a permutation of seq_len(%s)" msgstr "'ncol' non è un fattore di length(x)" #, fuzzy msgid "matrix must have exactly one entry in each row or column" msgstr "deve avere esattamente una voce non zero per riga" #, fuzzy msgid "attempt to coerce non-square matrix to %s" msgstr "" "non è possibile convertire la classe \"dgTMatrix\" non simmetrica nella " "classe \"dsCMatrix\"" #, fuzzy msgid "matrix must have exactly one entry in each row and column" msgstr "deve avere esattamente una voce non zero per riga" #, fuzzy msgid "'%s' via sparse -> dense coercion" msgstr "rcond (.) con coercizione sparsa -> densa" #, fuzzy msgid "invalid %s=\"%s\"" msgstr "nargs()= %d non valido" msgid "norm" msgstr "" #, fuzzy msgid "'%s' method must use default %s=\"%s\"" msgstr "il metodo di kronecker deve utilizzare in maniera predefinita 'FUN'" #, fuzzy msgid "number of nonzero entries cannot exceed %s" msgstr "il numero di righe non sono compatibili per %s" msgid "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", or \"%4$s\"" msgstr "" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%2$s2\", \"%2$s2.\", \"%3$s\", or " "\"%4$s\"" msgstr "" msgid "non-conformable arguments" msgstr "gli argomenti non sono compatibili" #, fuzzy msgid "model frame and formula mismatch in sparse.model.matrix()" msgstr "model frame e formula non corrispondono in model.matrix()" #, fuzzy msgid "non-list contrasts argument ignored" msgstr "argomento 'contrasts.arg' non valido" #, fuzzy msgid "'contrasts.arg' argument must be named" msgstr "argomento 'contrasts.arg' non valido" msgid "variable '%s' is absent, its contrast will be ignored" msgstr "variabile '%s' assente, i suoi contrasti saranno ignorati" msgid "Matrix seems negative semi-definite" msgstr "Matrix sembra semi-definito negativo" msgid "'nearPD()' did not converge in %d iterations" msgstr "'nearPD()' non converge in %d iterazioni" #, fuzzy msgid "'cl' is not a character string" msgstr "'V' non è una matrice quadrata" msgid "" "not a positive definite matrix (and positive semidefiniteness is not checked)" msgstr "" #, fuzzy msgid "'%s' is not a square numeric matrix" msgstr "'V' non è una matrice quadrata" #, fuzzy msgid "" "diag(%s) has non-positive or non-finite entries; finite result is doubtful" msgstr "diag(.) ha 0 o voci NA; un risultato non-finito è incerto" msgid "" "matrix is structurally rank deficient; using augmented matrix with " "additional %d row(s) of zeros" msgstr "" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%2$s2\", \"%2$s2.\", \"%3$s\", " "\"%3$s1\", \"%4$s\", or \"%4$s1\"" msgstr "" #, fuzzy msgid "'%s' has the wrong length" msgstr "RHS 'b' ha una lunghezza errata" #, fuzzy msgid "invalid '%s': not in %d:%d" msgstr "stringa 'col.names' non valida: %s" msgid "need greater '%s' as pivoting occurred" msgstr "" msgid "qr2rankMatrix(.): QR with only %d out of %d finite diag(R) entries" msgstr "" "qr2rankMatrix(.): QR con solo %d elementi fuori dai %d finiti di diag(R)" msgid "" "rankMatrix(, method = '%s') coerces to dense matrix.\n" " Probably should rather use method = 'qr' !?" msgstr "" "rankMatrix(, method = '%s') convertito in matrice " "densa.\n" " Non si dovrebbe provare method = 'qr' !?" msgid "rankMatrix(x, method='qr'): computing t(x) as nrow(x) < ncol(x)" msgstr "rankMatrix(x, method='qr'): calcolando t(x) come nrow(x) < ncol(x)" #, fuzzy msgid "[[ suppressing %d column name%s %s ... ]]" msgstr "[[ suppressing %d column names %s ... ]]" msgid "invalid 'col.names' string: %s" msgstr "stringa 'col.names' non valida: %s" msgid "uniDiag=TRUE, but not all diagonal entries are 1" msgstr "uniDiag=TRUE, ma non tutte le voci diagonali sono 1" msgid "uniDiag=TRUE, not all entries in diagonal coded as 1" msgstr "uniDiag=TRUE, non tutte le voci in diagonale codificate come 1" #, fuzzy msgid "in show(); maybe adjust options(max.print=, width=)" msgstr "in show(); si dovrebbe aggiustare 'options(max.print= *, width = *)'" msgid "suppressing %d columns and %d rows" msgstr "soppresse %d colonne e %d righe" msgid "suppressing %d rows" msgstr "soppresse %d righe" msgid "suppressing %d columns" msgstr "soppresse %d colonne" msgid "logic programming error in printSpMatrix2(), please report" msgstr "" "errore di programmazione logica in printSpMatrix2(), per piacere, riportatelo" #, fuzzy msgid "'%s' is not square" msgstr "'V' non è una matrice quadrata" msgid "dimensions of '%s' and '%s' are inconsistent" msgstr "" msgid "'%1$s' is computationally singular, rcond(%1$s)=%2$g" msgstr "" msgid "'%s' is computationally singular, min(d)/max(d)=%g, d=abs(diag(U))" msgstr "" msgid "matrix is exactly singular, D[i,i]=0, i=%d" msgstr "" msgid "matrix is exactly singular, J[,j]=0, j=%d" msgstr "" msgid "matrix exactly singular, J[i,]=0, i=%d" msgstr "" msgid "cannot coerce from %s to %s" msgstr "" msgid "a sparseMatrix should rarely be centered: will not be sparse anymore" msgstr "" "una sparseMatrix dovrebbe essere raramente centrata: non sarà più sparsa." msgid "length of 'center' must equal the number of columns of 'x'" msgstr "la lunghezza di 'center' deve eguagliare il numero di colonne di 'x'" msgid "length of 'scale' must equal the number of columns of 'x'" msgstr "la lunghezza di 'scale' deve eguagliare il numero di colonne di 'x'" #, fuzzy msgid "invalid subassignment value class \"%s\"" msgstr "classe non valida: %s" #, fuzzy msgid "invalid subassignment value type \"%s\"" msgstr "Tipo di archiviazione non valido: %s" msgid "missing subassignment value" msgstr "" #, fuzzy msgid "incorrect number of dimensions" msgstr "dimensioni matrice non compatibili" msgid "replacement has length zero" msgstr "" msgid "number of items to replace is not a multiple of replacement length" msgstr "" "il numero di articoli da sostituire non è un multiplo della lunghezza di " "sostituzione" msgid "" ".M.repl.i.2col(): 'i' has no integer column number;\n" " should never happen; please report" msgstr "" ".M.repl.i.2col(): 'i' non ha un numero di colonna intero;\n" " non dovrebbe mai accadere; per piacere, segnalatelo" msgid "such indexing must be by logical or 2-column numeric matrix" msgstr "" "tale indicizzazione dev'essere per matrice logica o numerica a 2 colonne" msgid ".M.repl.i.2col(): drop 'matrix' case ..." msgstr ".M.repl.i.2col(): si elimina il caso 'matrix' ..." msgid "negative values are not allowed in a matrix subscript" msgstr "valori negativi non ammessi in subscript di matrice" msgid "NAs are not allowed in subscripted assignments" msgstr "NA non ammessi nelle assegnazioni subscript" msgid "m[ ] <- v: inefficiently treating single elements" msgstr "m[ ] <- v: trattamento inefficiente dei singoli elementi" msgid "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' ?" msgstr "nargs() = %d. Argomenti illegali estranei all'interno di '[ .. ]' ?" msgid "RHS 'value' (class %s) matches 'ANY', but must match matrix class %s" msgstr "" "RHS 'value' (classe %s) corrisponde a 'ANY', ma deve corrispondere ad una " "classe di matrice %s" msgid "not-yet-implemented 'Matrix[<-' method" msgstr "metodo 'Matrix[<-' non ancora implementato" msgid "invalid nargs()= %d" msgstr "nargs()= %d non valido" msgid "nothing to replace with" msgstr "niente da sostituire" msgid "too many replacement values" msgstr "troppi valori di sostituzione" msgid "i1[1] == 0 ==> C-level verbosity will not happen!" msgstr "i1[1] == 0 ==> la verbosità a livello C non accadrà!" msgid "using\t \"old code\" part in Csparse subassignment" msgstr "" "si utilizza\t una parte di \"vecchio codice\" nel sotto-assegnamento Csparse" msgid "" "using\"old code\" part in Csparse subassignment\n" " >>> please report to Matrix-authors@r-project.org" msgstr "" "si utilizza una parte di \"vecchio codice\" nel sotto-assegnamento Csparse\n" " >>> per piacere, riportatelo agli autori Matrix-authors@r-project.org" msgid "you cannot mix negative and positive indices" msgstr "non è possibile mischiare indici negativi e positivi" msgid "index larger than maximal %d" msgstr "indice più largo del massimo %d" msgid "'NA' indices are not (yet?) supported for sparse Matrices" msgstr "gli indici 'NA' non sono (ancora?) supportati per le matrici sparse" msgid "logical subscript too long (%d, should be %d)" msgstr "subscript logico troppo lungo (%d, dovrebbe essere %d)" msgid "no 'dimnames[[.]]': cannot use character indexing" msgstr "" "nessuna 'dimnames[[.]]': non è possibile utilizzare l'indicizzazione dei " "caratteri" msgid "invalid character indexing" msgstr "indicizzazione carattere non valida" msgid "internal bug: missing 'i' in replTmat(): please report" msgstr "bug interno: manca 'i' in replTmat(): per piacere, riportatelo" msgid "[ ] indexing not allowed: forgot a \",\" ?" msgstr "" "[ ] indicizzazione non ammessa: si è dimenticato un \",\" ?" msgid "internal bug: matrix 'i' in replTmat(): please report" msgstr "bug interno: matrix 'i' in replTmat(): per piacere, riportatelo" msgid "" "x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced; NA |--> TRUE." msgstr "" "x[.] <- val: x è %s, il valore esterno a {TRUE, FALSE} è convertito; NA |--> " "TRUE." msgid "x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced." msgstr "x[.] <- val: x è %s, il valore esterno a {TRUE, FALSE} è convertito." msgid "" "x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE." msgstr "" "x[.,.] <- val: x è %s, il valore esterno a {TRUE, FALSE} è convertito; NA |--" "> TRUE." msgid "x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced." msgstr "x[.,.] <- val: x è %s, il valore esterno a {TRUE, FALSE} è convertito." msgid "x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrix" msgstr "x[.,.] <- val : x è stato convertito da Tsparse* a CsparseMatrix" msgid "nargs() = %d should never happen; please report." msgstr "nargs() = %d non dovrebbe accadere; per piacere riportalo." msgid "row indices must be <= nrow(.) which is %d" msgstr "gli indici riga devono essere <= nrow(.) e sono %d" msgid "column indices must be <= ncol(.) which is %d" msgstr "gli indici di colonna devono essere <= ncol(.) e sono %d" msgid "Internal bug: nargs()=%d; please report" msgstr "Bug interno: nargs()=%d; per piacere riportalo" msgid "" "index must be numeric, logical or sparseVector for indexing sparseVectors" msgstr "" "l'indice dev'essere numerico, logico o sparseVector per l'indicizzazione di " "sparseVector" #, fuzzy msgid "invalid subscript class \"%s\"" msgstr "classe non valida: %s" #, fuzzy msgid "invalid subscript type \"%s\"" msgstr "Tipo di archiviazione non valido: %s" msgid "recycled %s would have maximal index exceeding %s" msgstr "" msgid "subscripts exceeding %s replaced with NA" msgstr "" msgid "subscript out of bounds" msgstr "" #, fuzzy msgid "logical subscript too long" msgstr "subscript logico troppo lungo (%d, dovrebbe essere %d)" msgid "only zeros may be mixed with negative subscripts" msgstr "" msgid "trimmed means are not defined for complex data" msgstr "" msgid "first element used of '%s' argument" msgstr "" #, fuzzy msgid "invalid '%s' argument" msgstr "'data' non valido" msgid "should never happen ..." msgstr "" #, fuzzy msgid "'%s' is deprecated; using '%s' instead" msgstr "'giveCsparse' è stato deprecato; si utilizzerà 'repr'" #, fuzzy msgid "'%s' is deprecated; setting %s=\"%s\"" msgstr "'giveCsparse' è stato deprecato; viene impostato 'repr = \"T\"'" msgid "'%s' has length 0 but '%s' does not" msgstr "" #, fuzzy msgid "attempt to coerce matrix with NA to %s" msgstr "" "non è possibile convertire la classe \"dgTMatrix\" non simmetrica nella " "classe \"dsCMatrix\"" #, fuzzy msgid "invalid 'Class2'" msgstr "'data' non valido" #~ msgid "qr2rankMatrix(.): QR has negative diag(R) entries" #~ msgstr "qr2rankMatrix(.): QR ha elementi diag(R) negativi" #, fuzzy #~ msgid "invalid 'each' argument" #~ msgstr "segno errato nell'argomento 'by'" #, fuzzy #~ msgid "invalid 'times' argument" #~ msgstr "'data' non valido" #~ msgid "" #~ "not-yet-implemented method for %s(<%s>).\n" #~ " ->> Ask the package authors to implement the missing feature." #~ msgstr "" #~ "metodo non ancora implementato per %s(<%s>).\n" #~ " - >> Chiedi agli autori del pacchetto di implementare la funzionalità " #~ "assente." #~ msgid "" #~ "not-yet-implemented method for %s(<%s>, <%s>).\n" #~ " ->> Ask the package authors to implement the missing feature." #~ msgstr "" #~ "metodo non ancora implementato per %s(<%s>, <%s>).\n" #~ " - >> Chiedi agli autori del pacchetto di implementare la funzionalità " #~ "assente." #, fuzzy #~ msgid "complex \"diagonalMatrix\" not yet implemented" #~ msgstr "classe generale Matrix non ancora implementata per %s" #, fuzzy #~ msgid "not yet implemented for class \"%s\"" #~ msgstr "non ancora implementato per la classe %s" #, fuzzy #~ msgid "invalid 'uplo'" #~ msgstr "'type' non valido" #~ msgid "'lag' and 'differences' must be integers >= 1" #~ msgstr "'lag' e 'differences' devono essere interi >= 1" #~ msgid "" #~ "programming error: min() should have dispatched w/ 1st arg much earlier" #~ msgstr "" #~ "errore di programmazione: min() dovrebbe aver fatto il dispatch con il " #~ "primo argomento molto prima" #~ msgid "in Summary(, .): %s(<%s>, <%s>,...)" #~ msgstr "in Summary(, .): %s(<%s>, <%s>,...)" #~ msgid "in Summary(, .): %s(<%s>, <%s>)" #~ msgstr "in Summary(, .): %s(<%s>, <%s>)" #, fuzzy #~ msgid "number of rows of matrices must match" #~ msgstr "il numero di righe non sono compatibili per %s" #, fuzzy #~ msgid "number of columns of matrices must match" #~ msgstr "il numero di righe non sono compatibili per %s" #~ msgid "resulting x-slot has different type than x's or y's" #~ msgstr "lo x-slot risultante ha un tipo diverso da quelli di x o y" #, fuzzy #~ msgid "dimensions must be numeric of length 2" #~ msgstr "il valore di dim(.) dev'essere numerico di lunghezza 2" #, fuzzy #~ msgid "'perm' must be numeric" #~ msgstr "'A' dev'essere una matrice quadrata" #, fuzzy #~ msgid "'margin' must be 1 or 2" #~ msgstr "'ncol' dev'essere >= 0" #~ msgid "not-yet-implemented method for <%s> %%*%% <%s>" #~ msgstr "metodo non ancora implementato per <%s> %%*%% <%s>" #~ msgid "'boolArith = %d' not yet implemented" #~ msgstr "'boolArith = %d' non ancora implementato" #, fuzzy #~ msgid "'rcond' via sparse -> dense coercion" #~ msgstr "rcond (.) con coercizione sparsa -> densa" #, fuzzy #~ msgid "invalid 'norm'" #~ msgstr "'data' non valido" #, fuzzy #~ msgid "cannot coerce zsparseVector to dgCMatrix" #~ msgstr "" #~ "non è possibile la coercizione dei valori 'NA' nel pattern \"ngCMatrix\"" #, fuzzy #~ msgid "cannot coerce zsparseVector to dgeMatrix" #~ msgstr "non è possibile la coercizione degli 'NA' in \"nsparseVector\"" #~ msgid "" #~ "number of non zeros is smaller than 'nnz' because of duplicated (i,j)s" #~ msgstr "" #~ "il numero di valori non-zero è inferiore a 'nnz' a causa di duplicati (i," #~ "j)s" #~ msgid "'times >= 0' is required" #~ msgstr "'times >= 0' è richiesto" #~ msgid "'giveCsparse' has been deprecated; setting 'repr = \"%s\"' for you" #~ msgstr "'giveCsparse' è stato deprecato; viene impostato 'repr = \"%s\"'" #~ msgid "Matrices must have same number of rows in %s" #~ msgstr "Le matrici devono avere il medesimo numero di righe in %s" #~ msgid "Matrices must have same number of columns in %s" #~ msgstr "Le matrici devono avere il medesimo numero di colonne in %s" #, fuzzy #~ msgid "only 2-dimensional tables can be coerced to sparseMatrix" #~ msgstr "" #~ "solo le tabelle bidimensionali possono essere convertite direttamente a " #~ "matrici sparse" #, fuzzy #~ msgid "matrix is not symmetric or" #~ msgstr "'x' non è simmetrica ne triangolare" #, fuzzy #~ msgid "triangular" #~ msgstr "non è una matrice triangolare" #, fuzzy #~ msgid "matrix is not" #~ msgstr "la matrice non è diagonale" #~ msgid "'x' is not positive definite -- chol() undefined." #~ msgstr "'x' non è definito positivo -- chol() non definito." #~ msgid "Matrices must have same dimensions in %s" #~ msgstr "Le matrici devono avere le medesime dimensioni in %s" #~ msgid "names(dimnames()) must be NULL or of length two" #~ msgstr "names(dimnames()) dev'essere NULL o lunga due" #~ msgid "[[ suppressing %d column names %s ]]" #~ msgstr "[[ soppressione di %d nomi colonna %s ]]" #~ msgid "'x' must be \"sparseMatrix\"" #~ msgstr "'x' dev'essere una \"sparseMatrix\"" #~ msgid "not yet implemented for matrix with typeof %s" #~ msgstr "non ancora implementato per matrici con typeof %s" #~ msgid "not yet implemented for %s" #~ msgstr "non ancora implementato per %s" #~ msgid "" #~ "Quadratic matrix '%s' (=: A) is not formally\n" #~ "\tsymmetric. Will be treated as\tA A'" #~ msgstr "" #~ "La matrice quadratica '%s' (=: A) non è formalmente\n" #~ "\tsimmetrica. Sarà trattata come\tA A'" #~ msgid "" #~ "'update' must be logical or '+' or '-'; 'C' a matrix, and 'L' a " #~ "\"CHMfactor\"" #~ msgstr "" #~ "'update' dev'essere logico o '+' o '-'; 'C' una matrice, e 'L' un " #~ "\"CHMfactor\"" #~ msgid "update must be TRUE/FALSE or '+' or '-'" #~ msgstr "l'aggiornamento dev'essere TRUE/FALSE o '+' o '-'" #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "" #~ "Errore interno alla matrice in [i,,d]; per piacere riportalo" #~ msgid "" #~ "Cholesky() -> *symbolic* factorization -- not yet implemented" #~ msgstr "" #~ "Cholesky() -> *symbolic* factorization -- non ancora " #~ "implementato" #~ msgid "" #~ "as.matrix() is deprecated (to become a no-op in the future).\n" #~ "Use as(x, \"matrix\") or .asmatrix(x) instead." #~ msgstr "" #~ "as.matrix() è deprecato (per diventare una no-op in futuro).\n" #~ "Utilizza come alternativa as(x, \"matrix\") o .asmatrix(x)." #~ msgid "" #~ "as.array() is deprecated. Use as(x, \"matrix\") or .asmatrix(x) " #~ "instead." #~ msgstr "" #~ "as.array() è deprecato. Utilizza come alternativa as(x, " #~ "\"matrix\") o .asmatrix(x)." #~ msgid "trimmed mean of 'sparseVector' -- suboptimally using as.numeric(.)" #~ msgstr "" #~ "media tagliata di 'sparseVector' -- in modo non ottimale usando as." #~ "numeric (.)" #~ msgid "invalid dimnames given for %s object" #~ msgstr "i nomi di dimensioni non sono validi per l'oggetto %s" #~ msgid "" #~ "dimnames(.) <- NULL: translated to \n" #~ "dimnames(.) <- list(NULL,NULL) <==> unname(.)" #~ msgstr "" #~ "dimnames(.) <- NULL: tradotto in \n" #~ "dimnames(.) <- list(NULL,NULL) <==> unname(.)" #~ msgid "" #~ "'nrow', 'ncol', etc, are disregarded when 'data' is \"Matrix\" already" #~ msgstr "" #~ "'nrow', 'ncol' e gli altri, sono ignorati quando 'data' è già \"Matrix\"" #~ msgid "complex matrices not yet implemented in Matrix package" #~ msgstr "" #~ "le matrici complesse non sono ancora implementate nel pacchetto Matrix" #~ msgid "using slow kronecker() method" #~ msgstr "si utilizza il metodo kronecker() lento" #~ msgid "" #~ "Cholesky(A) called for 'A' of class \"%s\";\n" #~ "\t it is currently defined for sparseMatrix only; consider using chol() " #~ "instead" #~ msgstr "" #~ "Cholesky(A) ha chiamato 'A' della classe \"%s\";\n" #~ "\t è attualmente definito solo per sparseMatrix; si consideri l'utilizzo " #~ "di chol() come alternativa" #~ msgid "invalid or not-yet-implemented 'Matrix' subsetting" #~ msgstr "sotto-divisione 'Matrix' non valido o non ancora implementato" #~ msgid "[ ] : .M.sub.i.logical() maybe inefficient" #~ msgstr "" #~ "[ ] : .M.sub.i.logical() potrebbe essere inefficiente" #~ msgid "" #~ "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' (i.logical)?" #~ msgstr "" #~ "nargs() = %d. Argomenti illegali estranei all'interno di '[ .. ]' (i." #~ "logical)?" #~ msgid "" #~ "m[]: inefficiently indexing single elements - should not " #~ "happen, please report!" #~ msgstr "" #~ "m[ ]: indicizzazione inefficiente dei singoli elementi - non " #~ "dovrebbe succedere, per piacere riportalo!" #~ msgid "" #~ "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' (i.2col)?" #~ msgstr "" #~ "nargs() =%d. Argomenti illegali estranei all'interno di '[..]' (i.2col)?" #~ msgid "" #~ ".M.sub.i.2col(): 'i' has no integer column number;\n" #~ " should never happen; please report" #~ msgstr "" #~ ".M.sub.i.2col(): 'i' non ha un numero di colonna intero;\n" #~ " non dovrebbe mai accadere; per piacere, segnalatelo" #~ msgid "not-yet-implemented coercion to \"TsparseMatrix\"" #~ msgstr "coercizione in \"TsparseMatrix\" non ancora implementato" #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "" #~ "Errore interno alla matrice in [i,,d]; per piacere riportalo" #~ msgid "FIXME: NOT YET FINISHED IMPLEMENTATION" #~ msgstr "FIXME: IMPLEMENTAZIONE NON ANCORA FINITA" #~ msgid "diagonalMatrix in .dense2C() -- should never happen, please report!" #~ msgstr "" #~ "diagonalMatrix in .dense2C() -- non dovrebbe mai accadere, per piacere, " #~ "riportatelo!" #~ msgid "undefined method for class %s" #~ msgstr "metodo per la classe %s non definito" #~ msgid "dimensions don't match the number of cells" #~ msgstr "le dimensioni non corrispondono con il numero di celle" #~ msgid "" #~ "LU computationally singular: ratio of extreme entries in |diag(U)| = %9.4g" #~ msgstr "" #~ "LU computazionalmente singolare: rapporto tra voci estreme in |diag(U)| " #~ "=%9.4g" #~ msgid "RHS 'b' has wrong number of rows:" #~ msgstr "RHS 'b' ha un numero errato di righe:" #~ msgid "'x' has invalid data type" #~ msgstr "'x' ha un tipo dato non valido" #~ msgid "length(x) must be either 1 or #{cols}" #~ msgstr "length(x) dev'essere 1 o #{cols}" #~ msgid "some arguments are not matrices" #~ msgstr "alcuni argomenti non sono matrici" #~ msgid "%s kind not yet implemented" #~ msgstr "%s kind non ancora implementato" #~ msgid "non-square matrix" #~ msgstr "matrice non quadrata" #~ msgid "" #~ "matrix with non-zero off-diagonals cannot be coerced to \"diagonalMatrix\"" #~ msgstr "" #~ "la matrice con diagonali diverse da zero non può essere convertita in " #~ "\"diagonalMatrix\"" #~ msgid "non-matching dimensions" #~ msgstr "dimensioni non corrispondenti" #~ msgid "not a positive definite matrix" #~ msgstr "non è una matrice definita positiva" #~ msgid "" #~ "as(.,\"dsCMatrix\") is deprecated (since 2008); do use as(., " #~ "\"symmetricMatrix\")" #~ msgstr "" #~ "as(.,\"dsCMatrix\") è deprecato (dal 2008); si utilizzi as(., " #~ "\"symmetricMatrix\")" #~ msgid "inefficient coercion (lost triangularity); please report" #~ msgstr "" #~ "coercizione inefficiente (triangolarità persa); per piacere, segnalatelo" #~ msgid "coercion to \"indMatrix\" only works from integer numeric" #~ msgstr "la coercizione in \"indMatrix\" funziona solo da interi numerici" #~ msgid "" #~ "coercion from list(i1,...,ik, d) to \"indMatrix\" failed.\n" #~ " All entries must be integer valued and the number of columns, d, not " #~ "smaller\n" #~ " than the maximal index i*." #~ msgstr "" #~ "coercizione dalla list(i1, ..., ik, d) a \"indMatrix\" non riuscita.\n" #~ " Tutte le voci devono essere valori interi e il numero di colonne, d, " #~ "non inferiore\n" #~ " all'indice massimo i*." #~ msgid "the number of non-zero entries differs from nrow(.)" #~ msgstr "il numero di voci diverse da zero differisce da nrow(.)" #~ msgid "resulting matrix dimension would be too large" #~ msgstr "la dimensione della matrice risultante sarà troppo grande" #~ msgid "replacing \"indMatrix\" entries is not allowed, as rarely sensible" #~ msgstr "" #~ "la sostituzione delle voci \"indMatrix\" non è ammessa, in quanto " #~ "raramente incisiva" #~ msgid "temporarily disabled" #~ msgstr "temporaneamente disabilitato" #~ msgid "cannot coerce NA values to pattern \"ntCMatrix\"" #~ msgstr "" #~ "non è possibile la coercizione dei valori 'NA' nel pattern \"ntCMatrix\"" #~ msgid "coercion to \"pMatrix\" only works from integer numeric" #~ msgstr "la coercizione in \"pMatrix\" funziona solo da interi numerici" #~ msgid "not a square matrix" #~ msgstr "non è una matrice quadrata" #~ msgid "NA's in (i,j) are not allowed" #~ msgstr "NA in (i,j) non sono ammessi" #~ msgid "" #~ "Both 'symmetric' and 'triangular', i.e. asking for diagonal matrix. Use " #~ "'Diagonal()' instead" #~ msgstr "" #~ "Sia 'symmetric' che 'triangular', es. chiedendo una matrice diagonale. " #~ "Si utilizzi 'Diagonal()' come alternativa" #~ msgid "triangular matrix must have all i >= j or i <= j" #~ msgstr "la matrice triangolare deve avere tutti i >= j o i <= j" #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "" #~ "Errore interno alla matrice in [i,,d]; per piacere riportalo" #~ msgid "" #~ "qr.R() may differ from qr.R() because of permutations. " #~ "Possibly use our qrR() instead" #~ msgstr "" #~ "qr.R() potrebbe essere differente da qr.R() per le " #~ "permutazioni. Si utilizzi il nostro qrR() come alternativa" #~ msgid "(un)packing only applies to dense matrices, class(x)='%s'" #~ msgstr "il (un)packing si applica solo alle matrici dense, class(x)='%s'" #~ msgid "'x' is not symmetric -- chol() undefined." #~ msgstr "'x' non è simmetrico -- chol() non definito." #~ msgid "" #~ "extra argument %s will be disregarded in\n" #~ " %s" #~ msgid_plural "" #~ "extra arguments %s will be disregarded in\n" #~ " %s" #~ msgstr[0] "" #~ "l'argomento extra %s sarà ignorato in\n" #~ " %s" #~ msgstr[1] "" #~ "gli argomenti extra %s saranno ignorati in\n" #~ " %s" #~ msgid "%s %s is undefined" #~ msgstr "%s %s non è definita" #~ msgid " %s %s is undefined" #~ msgstr " %s %s non è definita" Matrix/po/R-fr.po0000644000175100001440000012647714575137654013362 0ustar hornikusersmsgid "" msgstr "" "Project-Id-Version: Matrix 1.1-1\n" "POT-Creation-Date: 2024-03-15 17:22\n" "PO-Revision-Date: 2021-02-11 11:04+0100\n" "Last-Translator: Philippe Grosjean \n" "Language-Team: none\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.4.2\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #, fuzzy msgid "invalid mode \"%s\"" msgstr "'mod' incorrect : %s" msgid "" "%s(<%s>, <%s>) is not yet implemented; ask maintainer(\"%s\") to implement " "the missing method" msgstr "" #, fuzzy msgid "complex %s not yet implemented" msgstr "La classe %s n'est pas encore implémentée" #, fuzzy msgid "cannot coerce matrix of type \"%s\" to %s" msgstr "impossible de convertir automatiquement des 'NA's en \"nsparseMatrix\"" #, fuzzy msgid "non0.i() not yet implemented for class %s" msgstr "pas encore implémenté pour la classe %s" msgid "%s=\"%s\" invalid for %s@uplo=\"%s\"" msgstr "" msgid "'%s' is not \"%1$s\", \"D%1$s\", or \"%1$s.\"" msgstr "" #, fuzzy msgid "%1$s(%2$s) is undefined: '%2$s' is not positive semidefinite" msgstr "" "chol() est indéfini pour une matrice diagonale avec des entrées négatives" #, fuzzy msgid "matrix is not square" msgstr "la matrice n'est pas diagonale" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", \"%3$s.\", \"%3$s1\", \"%3$s1." "\", or \"%4$s\"" msgstr "" #, fuzzy msgid "'%s' does not inherit from virtual class %s" msgstr "'x' doit hériter de \"sparseVector\"" msgid "D[i,i] is NA, i=%d" msgstr "" msgid "D[i,i] is negative, i=%d" msgstr "" msgid "'%1$s' is not formally symmetric; factorizing tcrossprod(%1$s)" msgstr "" msgid "unexpected %s=\"%s\" in '%s' method" msgstr "" msgid "Not a valid format" msgstr "Pas un format acceptable" msgid "'file' must be a character string or connection" msgstr "'file' doit être une chaîne de caractères ou une connexion" msgid "Invalid storage type: %s" msgstr "Type de stockage incorrect : %s" msgid "Only numeric sparse matrices allowed" msgstr "Seules les matrices éparses numériques sont autorisées" msgid "Invalid storage format: %s" msgstr "Format de stockage incorrect : %s" msgid "Invalid assembled indicator: %s" msgstr "Indicateur d'assemblage incorrect : %s" msgid "file is not a MatrixMarket file" msgstr "le fichier n'est pas un fichier MatrixMarket" msgid "type '%s' not recognized" msgstr "type '%s' non reconnu" msgid "representation '%s' not recognized" msgstr "représentation '%s' non reconnue" msgid "element type '%s' not recognized" msgstr "type d'élément '%s' non reconnu" msgid "symmetry form '%s' not recognized" msgstr "la symétrie n'est pas reconnue pour '%s'" msgid "readMM(): expected %d entries but found only %d" msgstr "" #, fuzzy msgid "readMM(): row indices 'i' are not in 1:nrow[=%d]" msgstr "readMM() : ligne\t valeurs 'i' ne sont pas comprises entre 1:nr" #, fuzzy msgid "readMM(): column indices 'j' are not in 1:ncol[=%d]" msgstr "readMM() : colonne valeurs 'j' ne sont pas comprises entre 1:nc" msgid "symmetry form 'skew-symmetric' not yet implemented for reading" msgstr "" "la forme de symétrie 'skew-symmetric' n'est pas encore implémentée pour la " "lecture" msgid "symmetry form 'hermitian' not yet implemented for reading" msgstr "" "la forme de symétrie 'hermitian' n'est pas encore implémentée pour la lecture" msgid "symmetry form '%s' is not yet implemented" msgstr "la forme de symétrie '%s' n'est pas encore implémentée" msgid "element type 'complex' not yet implemented" msgstr "le type d'élément 'complex' n'est pas encore implémenté" msgid "'%s()' is not yet implemented for element type '%s'" msgstr "'%s()' n'est pas encore implémenté pour le type d'élément '%s'" msgid "'%s()' is not yet implemented for representation '%s'" msgstr "'%s' n'est pas encore implémenté pour la représentation '%s'" msgid "longer object length is not a multiple of shorter object length" msgstr "" "la longueur de l'objet le plus long n'est pas un multiple de la longueur de " "l'objet le plus court" #, fuzzy msgid "invalid class \"%s\" in '%s' method" msgstr "chaîne de caractères 'col.names' incorrecte : %s" msgid "invalid type \"%s\" in '%s' method" msgstr "" msgid "non-conformable matrix dimensions in %s" msgstr "matrices de dimensions incompatibles dans %s" msgid "dimnames [%d] mismatch in %s" msgstr "dimnames [%d] incohérentes dans %s" msgid "inefficient method used for \"- e1\"" msgstr "méthode inefficace utilisée pour \"- e1\"" msgid "dim [product %d] do not match the length of object [%d]" msgstr "dim [product %d] ne correspond pas à la longueur de l'objet [%d]" msgid "internal bug in \"Compare\" method (Cmp.Mat.atomic); please report" msgstr "" "bogue interne dans la méthode \"Compare\" (Cmp.Mat.atomic) ; veuillez " "reporter ceci" msgid "Cmp.Mat.atomic() should not be called for diagonalMatrix" msgstr "Cmp.Mat.atomic() ne devrait pas être appelé pour diagonalMatrix" msgid "Matrices must have same number of rows for arithmetic" msgstr "" "Les matrices doivent avoir le même nombre de lignes pour les opérations " "arithmétiques" msgid "number of rows are not compatible for %s" msgstr "nombre incompatible de lignes pour %s" msgid "length of 2nd arg does not match dimension of first" msgstr "la longueur du 2ème arg ne correspond pas à la dimension du premier" msgid "length of 1st arg does not match dimension of 2nd" msgstr "la longueur du 1er arg ne correspond pas à la dimension du second" msgid "internal bug in \"Logic\" method (Logic.Mat.atomic); please report" msgstr "" "bogue interne dans la méthode \"Logic\" (Logic.Mat.atomic) ; veuillez " "reporter ceci" msgid "Logic.Mat.atomic() should not be called for diagonalMatrix" msgstr "Logic.Mat.atomic() ne devrait pas être appelé pour diagonalMatrix" msgid "vector too long in Matrix - vector operation" msgstr "vecteur trop long dans une opération Matrix - vecteur" msgid "" "longer object length\n" "\tis not a multiple of shorter object length" msgstr "" "la longueur de l'objet le plus long\n" "\tn'est pas un multiple de la longueur de l'objet le plus court" #, fuzzy msgid "invalid class \"%s\" object in '%s' method" msgstr "chaîne de caractères 'col.names' incorrecte : %s" msgid "intermediate 'r' is of type %s" msgstr "le 'r' intermédiaire est de type %s" msgid "not yet implemented .. please report" msgstr "pas encore implémenté .. veuillez reporter ceci" msgid "'%s' has non-finite values" msgstr "" msgid "'%1$s' is not \"%2$s\", \"%3$s\", or \"%2$s.\"" msgstr "" msgid "'force' must be (coercable to) TRUE or FALSE" msgstr "'force' doit être (convertible en) TRUE ou FALSE" msgid "invalid (to - from)/by in seq(.)" msgstr "(to - from)/by incorrect dans seq(.)" msgid "wrong sign in 'by' argument" msgstr "signe incorrect dans l'argument 'by'" msgid "'by' argument is much too small" msgstr "l'argument 'by' est beaucoup trop petit" msgid "length must be non-negative number" msgstr "la longueur doit être un nombre non négatif" msgid "too many arguments" msgstr "trop d'arguments" msgid "c(,..) of different kinds, coercing all to 'rleDiff'" msgstr "" "c(,..) de différentes sortes, convertis automatiquement en " "'rleDiff\"" msgid "[i] is not yet implemented" msgstr "[i] n'est pas encore implémenté" msgid "all() is not yet implemented" msgstr "all() n'est pas encore implémenté" msgid "sum() is not yet implemented" msgstr "sum() n'est pas encore implémenté" msgid "prod() is not yet implemented" msgstr "prod() n'est pas encore implémenté" msgid "not yet implemented" msgstr "pas encore implémenté" msgid "" "x / 0 for an x with sign-change\n" " no longer representable as 'rleDiff'" msgstr "" "x / 0 pour un x avec changement de signe\n" " il n'est plus représentable comme 'rleDiff'" msgid " --> is not yet implemented" msgstr " --> n'est pas encore implémenté" msgid " --> is not yet implemented" msgstr " --> n'est pas encore implémenté" #, fuzzy msgid "only square matrices can be used as graph incidence matrices" msgstr "" "seules des matrices carrées peuvent être utilisées comme matrices " "d'incidence pour les graphiques" #, fuzzy msgid "matrix is not symmetric; consider forceSymmetric(.) or symmpart(.)" msgstr "" "ce n'est pas une matrice symétrique ; considérez forceSymmetric() ou " "symmpart()" #, fuzzy msgid "matrix is not triangular; consider triu(.) or tril(.)" msgstr "la matrice n'est pas triangulaire" msgid "matrix is not diagonal; consider Diagonal(x=diag(.))" msgstr "" #, fuzzy msgid "invalid type \"%s\" in '%s'" msgstr "'type' invalide" #, fuzzy msgid "invalid %s=\"%s\" to '%s'" msgstr "Type de stockage incorrect : %s" msgid "dimensions cannot exceed %s" msgstr "" #, fuzzy msgid "invalid class \"%s\" in '%s'" msgstr "chaîne de caractères 'col.names' incorrecte : %s" msgid "%s length cannot exceed %s" msgstr "" msgid "'A' must be a square matrix" msgstr "'A' doit être une matrice carrée" msgid "must either specify 'A' or the functions 'A.x' and 'At.x'" msgstr "il faut spécifier 'A' ou les fonctions 'A.x' et 'At.x'" msgid "when 'A' is specified, 'A.x' and 'At.x' are disregarded" msgstr "lorsque 'A' est spécifié, 'A.x' et 'At.x' ne sont pas pris en compte" msgid "not converged in %d iterations" msgstr "pas de convergence en %d itérations" msgid "hit a cycle (1) -- stop iterations" msgstr "un cycle est atteint (1) -- arrêt des itérations" msgid "hit a cycle (2) -- stop iterations" msgstr "un cycle est atteint (2) -- arrêt des itérations" msgid "not enough new vecs -- stop iterations" msgstr "pas assez de nouveaux vecs -- arrêt des itérations" msgid "invalid 'data'" msgstr "'data' incorrect" #, fuzzy msgid "'nrow', 'ncol', 'byrow' disregarded for [mM]atrix 'data'" msgstr "'nrow', 'ncol', etc, ne sont pas utilisés pour la matrice 'data'" msgid "data is too long" msgstr "" #, fuzzy msgid "exactly one of 'i', 'j', and 'p' must be missing from call" msgstr "" "exactement une valeur parmi 'i', 'j' ou 'p' doit être manquante dans l'appel" msgid "" "use Diagonal() to construct diagonal (symmetric && triangular) sparse " "matrices" msgstr "" #, fuzzy msgid "'giveCsparse' is deprecated; using 'repr' instead" msgstr "‘giveCsparse’ est obsolète ; utilisation de 'repr' à la place" #, fuzzy msgid "'giveCsparse' is deprecated; setting repr=\"T\" for you" msgstr "'giveCsparse' est obsolète ; j’ai mis 'repr = \"T\"' pour vous" #, fuzzy msgid "'p' must be a nondecreasing vector c(0, ...)" msgstr "'p' doit être un vecteur non décroissant (0, ...)" msgid "dimensions cannot exceed 2^31-1" msgstr "" msgid "'i' and 'j' must not contain NA" msgstr "" msgid "'i' and 'j' must be" msgstr "" msgid "positive" msgstr "" msgid "non-negative" msgstr "" #, fuzzy msgid "invalid 'dims'" msgstr "'data' incorrect" msgid "'dims' must contain all (i,j) pairs" msgstr "" msgid "symmetric matrix must be square" msgstr "la matrice symétrique doit être carrée" msgid "triangular matrix must be square" msgstr "la matrice triangulaire doit être carrée" msgid "p[length(p)]" msgstr "" msgid "length(i)" msgstr "" #, fuzzy msgid "is not an integer multiple of length(x)" msgstr "length(i) n'est pas un multiple de length(x)" msgid "length(x) must not exceed" msgstr "" #, fuzzy msgid "invalid 'repr'; must be \"C\", \"R\", or \"T\"" msgstr "'repr' incorrect ; il doit être \"C\", \"T\", ou \"R\"" #, fuzzy msgid "'n' must be a non-negative integer" msgstr "la longueur doit être un nombre non négatif" msgid "'x' has unsupported class \"%s\"" msgstr "" msgid "'x' has unsupported type \"%s\"" msgstr "" msgid "attempt to recycle 'x' of length 0 to length 'n' (n > 0)" msgstr "" msgid "'shape' must be one of \"g\", \"t\", \"s\"" msgstr "" #, fuzzy msgid "'kind' must be one of \"d\", \"l\", \"n\"" msgstr "'repr' incorrect ; il doit être \"C\", \"T\", ou \"R\"" msgid "mismatch between typeof(x)=\"%s\" and kind=\"%s\"; using kind=\"%s\"" msgstr "" #, fuzzy msgid "'cols' must be numeric" msgstr "'ncol' doit être >= 0" msgid "'cols' has elements not in seq(0, length.out = n)" msgstr "" #, fuzzy msgid "'uplo' must be \"U\" or \"L\"" msgstr "'repr' incorrect ; il doit être \"C\", \"T\", ou \"R\"" #, fuzzy msgid "'lst' must be a list" msgstr "'ncol' doit être >= 0" msgid "'giveCsparse' has been deprecated; setting 'repr = \"T\"' for you" msgstr "'giveCsparse' est obsolète ; j’ai mis 'repr = \"T\"' pour vous" msgid "'giveCsparse' has been deprecated; will use 'repr' instead" msgstr "‘giveCsparse’ est obsolète ; utilisation de 'repr' à la place" msgid "'diagonals' matrix must have %d columns (= length(k) )" msgstr "une matrice 'diagonals' doit avoir %d colonnes (= length(k) )" msgid "'diagonals' must have the same length (%d) as 'k'" msgstr "'diagonals' doit avoir la même longueur (%d) que 'k'" msgid "matrix can only be symmetric if square, but n != m" msgstr "" "une matrice peut seulement être symétrique si elle est carrée, mais n != m" msgid "" "for symmetric band matrix, only specify upper or lower triangle\n" " hence, all k must have the same sign" msgstr "" "pour une matrice de bande symétrique, spécifiez seulement le triangle " "supérieur ou inférieur\n" " donc, tous les k doivent avoir le même signe" msgid "the %d-th (sub)-diagonal (k = %d) is too short; filling with NA's" msgstr "" "la %d-ième (sous)-diagonale (k = %d) est trop courte ; elle est repliée avec " "des NAs" msgid "invalid 'repr'; must be \"C\", \"T\", or \"R\"" msgstr "'repr' incorrect ; il doit être \"C\", \"T\", ou \"R\"" msgid "'x' must inherit from \"sparseVector\"" msgstr "'x' doit hériter de \"sparseVector\"" msgid "'ncol' must be >= 0" msgstr "'ncol' doit être >= 0" msgid "'nrow' must be >= 0" msgstr "'nrow' doit être >= 0" msgid "Must specify 'nrow' when 'symmetric' is true" msgstr "Il faut spécifier 'nrow' lorsque 'symmetric' est vrai" msgid "'nrow' and 'ncol' must be the same when 'symmetric' is true" msgstr "'now' et 'ncol' doivent être les mêmes lorsque 'symmetric' est vrai" msgid "'x' must have length nrow^2 when 'symmetric' is true" msgstr "'x' doit avoir une longueur nrow^2 lorsque 'symmetric' est vrai" msgid "'ncol' is not a factor of length(x)" msgstr "'ncol' n'est pas un factor de length(x)" msgid "'nrow' is not a factor of length(x)" msgstr "'nrow' n'est pas un factor de length(x)" msgid "Class %s is not yet implemented" msgstr "La classe %s n'est pas encore implémentée" #, fuzzy msgid "'%s' and '%s' must be positive integers" msgstr "la longueur doit être un nombre non négatif" #, fuzzy msgid "matrix is not symmetric or triangular" msgstr "'x' n'est ni symétrique ni triangulaire" #, fuzzy msgid "matrix is not symmetric" msgstr "la matrice n'est pas triangulaire" #, fuzzy msgid "matrix is not triangular" msgstr "'x' n'est ni symétrique ni triangulaire" msgid "" "the default value of argument '%s' of method '%s(<%s>, <%s>)' may change " "from %s to %s as soon as the next release of Matrix; set '%s' when " "programming" msgstr "" msgid "determinant of non-square matrix is undefined" msgstr "" msgid "replacement diagonal has wrong length" msgstr "" msgid "replacement diagonal has incompatible type \"%s\"" msgstr "" msgid "assigned dimensions are not of type \"%s\" or \"%s\"" msgstr "" msgid "assigned dimensions do not have length %d" msgstr "" msgid "assigned dimensions are NA" msgstr "" msgid "assigned dimensions are negative" msgstr "" msgid "assigned dimensions exceed %s" msgstr "" #, fuzzy msgid "assigned dimensions [product %.0f] do not match object length [%.0f]" msgstr "dim [product %d] ne correspond pas à la longueur de l'objet [%d]" msgid "'lwd' must be NULL or non-negative numeric" msgstr "'lwd' doit être un nombre non négatif ou NULL" #, fuzzy msgid "%s(<%s>) is not yet implemented" msgstr "La classe %s n'est pas encore implémentée" msgid "'%s' is not of type \"%s\" or \"%s\"" msgstr "" msgid "'%s' contains NA" msgstr "" msgid "'%s' has elements less than %d" msgstr "" #, fuzzy msgid "'%s' is not a non-negative number" msgstr "la longueur doit être un nombre non négatif" msgid "'%s' has elements exceeding '%s'" msgstr "" msgid "'%s' is not %d or %d" msgstr "" #, fuzzy msgid "'%s' is not a permutation of seq_len(%s)" msgstr "'ncol' n'est pas un factor de length(x)" #, fuzzy msgid "matrix must have exactly one entry in each row or column" msgstr "doit avoir exactement une entrée non zéro par ligne" #, fuzzy msgid "attempt to coerce non-square matrix to %s" msgstr "" "impossible de convertir automatiquement des \"dgMAtrix\" non symétriques en " "classe \"dsCMatrix\"" #, fuzzy msgid "matrix must have exactly one entry in each row and column" msgstr "doit avoir exactement une entrée non zéro par ligne" #, fuzzy msgid "'%s' via sparse -> dense coercion" msgstr "conversion automatique rcond(.) via sparse -> dense" #, fuzzy msgid "invalid %s=\"%s\"" msgstr "nargs()= %d incorrect" msgid "norm" msgstr "" #, fuzzy msgid "'%s' method must use default %s=\"%s\"" msgstr "méthode kronecker doit utiliser une 'FUN' par défaut" #, fuzzy msgid "number of nonzero entries cannot exceed %s" msgstr "nombre incompatible de lignes pour %s" msgid "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%3$s\", or \"%4$s\"" msgstr "" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%2$s2\", \"%2$s2.\", \"%3$s\", or " "\"%4$s\"" msgstr "" msgid "non-conformable arguments" msgstr "matrices de dimensions incompatibles dans les arguments" #, fuzzy msgid "model frame and formula mismatch in sparse.model.matrix()" msgstr "" "le cadre du modèle et la formule ne correspondent pas dans model.matrix()" #, fuzzy msgid "non-list contrasts argument ignored" msgstr "argument 'contrast.arg' incorrect" #, fuzzy msgid "'contrasts.arg' argument must be named" msgstr "argument 'contrast.arg' incorrect" msgid "variable '%s' is absent, its contrast will be ignored" msgstr "la variable '%s' est absente, ses contrastes seront ignorés" msgid "Matrix seems negative semi-definite" msgstr "La matrice semble négative et semi-définie" msgid "'nearPD()' did not converge in %d iterations" msgstr "'nearPD()' n'a pas converti en %d itérations" #, fuzzy msgid "'cl' is not a character string" msgstr "'V' n'est pas une matrice *carrée*" msgid "" "not a positive definite matrix (and positive semidefiniteness is not checked)" msgstr "" #, fuzzy msgid "'%s' is not a square numeric matrix" msgstr "'V' n'est pas une matrice *carrée*" #, fuzzy msgid "" "diag(%s) has non-positive or non-finite entries; finite result is doubtful" msgstr "diag(.) avait 0 ou NA données ; un résultat non fini est douteux" msgid "" "matrix is structurally rank deficient; using augmented matrix with " "additional %d row(s) of zeros" msgstr "" msgid "" "'%1$s' is not \"%2$s1\", \"%2$s1.\", \"%2$s2\", \"%2$s2.\", \"%3$s\", " "\"%3$s1\", \"%4$s\", or \"%4$s1\"" msgstr "" #, fuzzy msgid "'%s' has the wrong length" msgstr "Le membre droit 'b' est de longueur incorrecte" #, fuzzy msgid "invalid '%s': not in %d:%d" msgstr "chaîne de caractères 'col.names' incorrecte : %s" msgid "need greater '%s' as pivoting occurred" msgstr "" msgid "qr2rankMatrix(.): QR with only %d out of %d finite diag(R) entries" msgstr "qr2rankMatrix(.): QR avec seulement %d de %d entrées finies de diag(R)" msgid "" "rankMatrix(, method = '%s') coerces to dense matrix.\n" " Probably should rather use method = 'qr' !?" msgstr "" "rankMatrix(, method = '%s') converti automatiquement en " "matrice dense.\n" " Il faudrait probablement plutôt utiliser une méthode = 'qr' ?" msgid "rankMatrix(x, method='qr'): computing t(x) as nrow(x) < ncol(x)" msgstr "rankMatrix(x, method='qr') : calcul de t(x) comme nrow(x) < ncol(x)" #, fuzzy msgid "[[ suppressing %d column name%s %s ... ]]" msgstr "[[ suppression de %d noms de colonnes %s … ]]" msgid "invalid 'col.names' string: %s" msgstr "chaîne de caractères 'col.names' incorrecte : %s" msgid "uniDiag=TRUE, but not all diagonal entries are 1" msgstr "uniDiag=TRUE, mais pas toutes les entrées diagonales sont à 1" msgid "uniDiag=TRUE, not all entries in diagonal coded as 1" msgstr "" "uniDiag=TRUE, toutes les entrées de la diagonale ne sont pas encodées à 1" #, fuzzy msgid "in show(); maybe adjust options(max.print=, width=)" msgstr "dans show() ; ajustez peut-être 'options(max.print= *, width = *)'" msgid "suppressing %d columns and %d rows" msgstr "suppression de %d colonnes et %d lignes" msgid "suppressing %d rows" msgstr "suppression de %d lignes" msgid "suppressing %d columns" msgstr "suppression de %d colonnes" msgid "logic programming error in printSpMatrix2(), please report" msgstr "" "erreur logique de programmation dans printSpMAtrix2(), veuillez reporter ceci" #, fuzzy msgid "'%s' is not square" msgstr "'V' n'est pas une matrice carrée" msgid "dimensions of '%s' and '%s' are inconsistent" msgstr "" msgid "'%1$s' is computationally singular, rcond(%1$s)=%2$g" msgstr "" msgid "'%s' is computationally singular, min(d)/max(d)=%g, d=abs(diag(U))" msgstr "" msgid "matrix is exactly singular, D[i,i]=0, i=%d" msgstr "" msgid "matrix is exactly singular, J[,j]=0, j=%d" msgstr "" msgid "matrix exactly singular, J[i,]=0, i=%d" msgstr "" msgid "cannot coerce from %s to %s" msgstr "" msgid "a sparseMatrix should rarely be centered: will not be sparse anymore" msgstr "" "une sparseMatrix doit rarement être centrée : elle ne sera plus éparse " "ensuite" msgid "length of 'center' must equal the number of columns of 'x'" msgstr "la longueur de 'center' doit être égale au nombre de colonnes de 'x'" msgid "length of 'scale' must equal the number of columns of 'x'" msgstr "la longueur de 'scale' doit être égale au nombre de colonnes de 'x'" #, fuzzy msgid "invalid subassignment value class \"%s\"" msgstr "classe incorrecte : %s" #, fuzzy msgid "invalid subassignment value type \"%s\"" msgstr "Type de stockage incorrect : %s" msgid "missing subassignment value" msgstr "" #, fuzzy msgid "incorrect number of dimensions" msgstr "dimensions incompatibles des matrices" msgid "replacement has length zero" msgstr "" msgid "number of items to replace is not a multiple of replacement length" msgstr "" "le nombre d'éléments à remplacer n'est pas un multiple de la longueur de " "remplacement" msgid "" ".M.repl.i.2col(): 'i' has no integer column number;\n" " should never happen; please report" msgstr "" ".M.repl.i.2col() : 'i' n'a\tpas un nombre entier de colonnes ;\n" " ceci ne devrait pas se produite. Veuillez envoyer un rapport de bogue" msgid "such indexing must be by logical or 2-column numeric matrix" msgstr "" "un tel indiçage doit être réalisé avec un vecteur booléen ou une matrice " "numérique à deux colonnes" msgid ".M.repl.i.2col(): drop 'matrix' case ..." msgstr ".M.repl.i.2col() : cas 'matrix' non traité ..." msgid "negative values are not allowed in a matrix subscript" msgstr "" "les valeurs négatives ne sont pas permises dans les indices de matrices" msgid "NAs are not allowed in subscripted assignments" msgstr "Les NAs ne sont pas autorisés dans les assignations avec indices" msgid "m[ ] <- v: inefficiently treating single elements" msgstr "m[ ] <- v : traitement inefficace d'éléments uniques" msgid "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' ?" msgstr "nargs() = %d. Arguments supplémentaires dans '[ .. ]' illégaux ?" msgid "RHS 'value' (class %s) matches 'ANY', but must match matrix class %s" msgstr "" "La 'value' du membre gauche de l'équation (classe %s) correspond à 'ANY', " "mais doit correspondre à la classe de matrice %s" msgid "not-yet-implemented 'Matrix[<-' method" msgstr "méthode 'Matrix[<-' non encore implémentée" msgid "invalid nargs()= %d" msgstr "nargs()= %d incorrect" msgid "nothing to replace with" msgstr "rien à remplacer avec" msgid "too many replacement values" msgstr "trop de valeurs de remplacement" msgid "i1[1] == 0 ==> C-level verbosity will not happen!" msgstr "" "i1[1] == 0 ==> au niveau C, aucune information détaillée ne sera affichée !" msgid "using\t \"old code\" part in Csparse subassignment" msgstr "" "utilisation d'une partie\t d'\"ancien code\" dans une sous-assignation " "Csparse" msgid "" "using\"old code\" part in Csparse subassignment\n" " >>> please report to Matrix-authors@r-project.org" msgstr "" "utilisation d'une partie d'\"ancien code\" dans une sous-assignation " "Csparse\n" " >>> veuillez envoyer un rapport à Matrix-authors@r-project.org" msgid "you cannot mix negative and positive indices" msgstr "vous ne pouvez pas mélanger des indices négatifs et positifs" msgid "index larger than maximal %d" msgstr "indice plus grand que la valeur maximale %d" msgid "'NA' indices are not (yet?) supported for sparse Matrices" msgstr "" "les indices 'NA' ne sont pas (encore?) supportés pour les Matrices éparses" msgid "logical subscript too long (%d, should be %d)" msgstr "indice logique trop long (%d, devrait être %d)" msgid "no 'dimnames[[.]]': cannot use character indexing" msgstr "" "pas de 'dimnames[[.]]' : impossible d'utiliser un indiçage de chaîne de " "caractères" msgid "invalid character indexing" msgstr "indiçage de chaînes de caractères incorrect" msgid "internal bug: missing 'i' in replTmat(): please report" msgstr "bogue interne : 'i' manquant dans replTmat() : veuillez reporter ceci" msgid "[ ] indexing not allowed: forgot a \",\" ?" msgstr "" "indiçage [ ] non permis : n'avez-vous pas oublié une \",\" ?" msgid "internal bug: matrix 'i' in replTmat(): please report" msgstr "bogue interne : matrice 'i' dans replTmat() : veuillez reporter ceci" msgid "" "x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced; NA |--> TRUE." msgstr "" "x[.] <- val: x vaut %s, val qui ne sont pas dans {TRUE, FALSE} sont " "convertis ; NA |--> TRUE." msgid "x[.] <- val: x is %s, val not in {TRUE, FALSE} is coerced." msgstr "" "x[.] <- val: x vaut %s, val qui ne sont pas dans {TRUE, FALSE} sont " "convertis." msgid "" "x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced NA |--> TRUE." msgstr "" "x[.,.] <- val: x vaut %s, val qui ne sont pas dans {TRUE, FALSE} sont " "convertis NA |--> TRUE." msgid "x[.,.] <- val: x is %s, val not in {TRUE, FALSE} is coerced." msgstr "" "x[.,.] <- val: x vaut %s, val qui ne sont pas dans {TRUE, FALSE} sont " "convertis." msgid "x[.,.] <- val : x being coerced from Tsparse* to CsparseMatrix" msgstr "" "x[.,.] <- val: x est converti automatiquement de Tsparse* vers CsparseMatrix" msgid "nargs() = %d should never happen; please report." msgstr "nargs() = %d ne devrait jamais se produire ; veuillez reporter ceci." msgid "row indices must be <= nrow(.) which is %d" msgstr "les indices de lignes doivent être <= nrow(.) qui est %d" msgid "column indices must be <= ncol(.) which is %d" msgstr "les indices de colonnes doivent être <= ncol(.) qui est %d" msgid "Internal bug: nargs()=%d; please report" msgstr "Bogue interne : nargs()=%d ; veuillez reporter ceci" msgid "" "index must be numeric, logical or sparseVector for indexing sparseVectors" msgstr "" "les indices doivent être numériques, booléens ou sparseVector pour " "l'indiçage sparseVectors" #, fuzzy msgid "invalid subscript class \"%s\"" msgstr "classe incorrecte : %s" #, fuzzy msgid "invalid subscript type \"%s\"" msgstr "Type de stockage incorrect : %s" msgid "recycled %s would have maximal index exceeding %s" msgstr "" msgid "subscripts exceeding %s replaced with NA" msgstr "" msgid "subscript out of bounds" msgstr "" #, fuzzy msgid "logical subscript too long" msgstr "indice logique trop long (%d, devrait être %d)" msgid "only zeros may be mixed with negative subscripts" msgstr "" msgid "trimmed means are not defined for complex data" msgstr "" msgid "first element used of '%s' argument" msgstr "" #, fuzzy msgid "invalid '%s' argument" msgstr "'data' incorrect" msgid "should never happen ..." msgstr "" #, fuzzy msgid "'%s' is deprecated; using '%s' instead" msgstr "‘giveCsparse’ est obsolète ; utilisation de 'repr' à la place" #, fuzzy msgid "'%s' is deprecated; setting %s=\"%s\"" msgstr "'giveCsparse' est obsolète ; j’ai mis 'repr = \"T\"' pour vous" msgid "'%s' has length 0 but '%s' does not" msgstr "" #, fuzzy msgid "attempt to coerce matrix with NA to %s" msgstr "" "impossible de convertir automatiquement des \"dgMAtrix\" non symétriques en " "classe \"dsCMatrix\"" #, fuzzy msgid "invalid 'Class2'" msgstr "'data' incorrect" #~ msgid "qr2rankMatrix(.): QR has negative diag(R) entries" #~ msgstr "qr2rankMatrix(.): QR a des entrées négatives dans diag(R)" #, fuzzy #~ msgid "invalid 'each' argument" #~ msgstr "signe incorrect dans l'argument 'by'" #, fuzzy #~ msgid "invalid 'times' argument" #~ msgstr "'data' incorrect" #~ msgid "" #~ "not-yet-implemented method for %s(<%s>).\n" #~ " ->> Ask the package authors to implement the missing feature." #~ msgstr "" #~ "méthode non encore implémentée pour %s(<%s>).\n" #~ " ->> Demandez aux auteurs du package d'implémenter cette fonction " #~ "manquante." #~ msgid "" #~ "not-yet-implemented method for %s(<%s>, <%s>).\n" #~ " ->> Ask the package authors to implement the missing feature." #~ msgstr "" #~ "méthode non encore implémentée pour %s(<%s>, <%s>).\n" #~ " ->> Demandez aux auteurs du package d'implémenter cette fonction " #~ "manquante." #, fuzzy #~ msgid "complex \"diagonalMatrix\" not yet implemented" #~ msgstr "classe Matrix générale pas encore implémentée pour %s" #, fuzzy #~ msgid "not yet implemented for class \"%s\"" #~ msgstr "pas encore implémenté pour la classe %s" #, fuzzy #~ msgid "invalid 'uplo'" #~ msgstr "'type' invalide" #~ msgid "'lag' and 'differences' must be integers >= 1" #~ msgstr "'lag' et 'differences' doivent être des entiers >= 1" #~ msgid "" #~ "programming error: min() should have dispatched w/ 1st arg much earlier" #~ msgstr "" #~ "erreur de programmation : min() aurait dû être dispatché avec le 1er arg " #~ "bien plus tôt" #~ msgid "in Summary(, .): %s(<%s>, <%s>,...)" #~ msgstr "dans Summary() : %s(<%s>, <%s>, …)" #~ msgid "in Summary(, .): %s(<%s>, <%s>)" #~ msgstr "dans Summary(, ) : %s(<%s>, <%s>)" #, fuzzy #~ msgid "number of rows of matrices must match" #~ msgstr "nombre incompatible de lignes pour %s" #, fuzzy #~ msgid "number of columns of matrices must match" #~ msgstr "nombre incompatible de lignes pour %s" #~ msgid "resulting x-slot has different type than x's or y's" #~ msgstr "le slot x résultant a un type différent que celui des x ou des y" #, fuzzy #~ msgid "dimensions must be numeric of length 2" #~ msgstr "la valeur de dim(.) doit être numérique de longueur 2" #, fuzzy #~ msgid "'perm' must be numeric" #~ msgstr "'A' doit être une matrice carrée" #, fuzzy #~ msgid "'margin' must be 1 or 2" #~ msgstr "'ncol' doit être >= 0" #~ msgid "not-yet-implemented method for <%s> %%*%% <%s>" #~ msgstr "méthode pas encore implémentée pour <%s> %%*%% <%s>" #~ msgid "'boolArith = %d' not yet implemented" #~ msgstr "'boolArith = %d' n'est pas encore implémenté" #, fuzzy #~ msgid "'rcond' via sparse -> dense coercion" #~ msgstr "conversion automatique rcond(.) via sparse -> dense" #, fuzzy #~ msgid "invalid 'norm'" #~ msgstr "'data' incorrect" #, fuzzy #~ msgid "cannot coerce zsparseVector to dgCMatrix" #~ msgstr "" #~ "impossible de convertir automatiquement des 'NA's en modèle \"ngCMatrix\"" #, fuzzy #~ msgid "cannot coerce zsparseVector to dgeMatrix" #~ msgstr "" #~ "impossible de convertir automatiquement les 'NA's en \"nsparseVector\"" #~ msgid "" #~ "number of non zeros is smaller than 'nnz' because of duplicated (i,j)s" #~ msgstr "" #~ "le nombre de valeurs non nulles est plus petit que 'nnz' à cause de (i,j) " #~ "dupliqués" #~ msgid "'times >= 0' is required" #~ msgstr "'times >= 0' est requis" #~ msgid "'giveCsparse' has been deprecated; setting 'repr = \"%s\"' for you" #~ msgstr "'giveCsparse' est obsolète ; j’ai mis 'repr = \"%s\"' pour vous" #~ msgid "Matrices must have same number of rows in %s" #~ msgstr "Les matrices doivent avoir le même nombre de lignes dans %s" #~ msgid "Matrices must have same number of columns in %s" #~ msgstr "Les matrices doivent avoir le même nombre de colonnes dans %s" #, fuzzy #~ msgid "only lists of length 2 can be coerced to indMatrix" #~ msgstr "" #~ "un objet \"Matrix\" avec NAs ne peut être converti automatiquement en " #~ "\"nMatrix\"" #, fuzzy #~ msgid "only 2-dimensional tables can be coerced to sparseMatrix" #~ msgstr "" #~ "seules des tables bidimensionnelles peuvent être automatiquement " #~ "converties en matrices éparses" #, fuzzy #~ msgid "matrix is not symmetric or" #~ msgstr "'x' n'est ni symétrique ni triangulaire" #, fuzzy #~ msgid "triangular" #~ msgstr "ce n'est pas une matrice triangulaire" #, fuzzy #~ msgid "matrix is not" #~ msgstr "la matrice n'est pas diagonale" #~ msgid "'x' is not positive definite -- chol() undefined." #~ msgstr "'x' n'est pas positif fini --chol() non défini." #~ msgid "Matrices must have same dimensions in %s" #~ msgstr "Les matrices doivent avoir les mêmes dimensions en %s" #~ msgid "names(dimnames()) must be NULL or of length two" #~ msgstr "names(dimnames()) doit être NULL ou de longueur deux" #~ msgid "[[ suppressing %d column names %s ]]" #~ msgstr "[[ suppression de %d noms de colonnes %s ]]" #~ msgid "'x' must be \"sparseMatrix\"" #~ msgstr "'x' doit être \"sparseMatrix\"" #~ msgid "not yet implemented for matrix with typeof %s" #~ msgstr "pas encore implémenté pour une matrice avec typeof %s" #~ msgid "not yet implemented for %s" #~ msgstr "pas encore implémenté pour %s" #~ msgid "" #~ "Quadratic matrix '%s' (=: A) is not formally\n" #~ "\tsymmetric. Will be treated as\tA A'" #~ msgstr "" #~ "La matrice quadratique '%s' (=: A) n'est pas formellement\n" #~ "\tsymétrique. Elle sera traitée comme \tA A'" #~ msgid "" #~ "'update' must be logical or '+' or '-'; 'C' a matrix, and 'L' a " #~ "\"CHMfactor\"" #~ msgstr "" #~ "'update' doit être une valeur booléenne ou '+' ou '-' ; 'C' doit être une " #~ "matrice, et 'L' un \"CHMfactor\"" #~ msgid "update must be TRUE/FALSE or '+' or '-'" #~ msgstr "update doit être TRUE/FALSE ou '+' ou '-'" #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "" #~ "Erreur interne d'objet Matrix dans [i,,d] ; veuillez envoyer un " #~ "rapport" #~ msgid "" #~ "Cholesky() -> *symbolic* factorization -- not yet implemented" #~ msgstr "" #~ "Cholesky() -> factorisation *symbolique* -- pas encore " #~ "implémentée" #~ msgid "" #~ "as.matrix() is deprecated (to become a no-op in the future).\n" #~ "Use as(x, \"matrix\") or .asmatrix(x) instead." #~ msgstr "" #~ "as.matrix() est obsolète (va disparaître dans le futur).\n" #~ "Utilisez as(x, \"matrix\") ou .asmatrix(x) à la place." #~ msgid "" #~ "as.array() is deprecated. Use as(x, \"matrix\") or .asmatrix(x) " #~ "instead." #~ msgstr "" #~ "as.array() est obsolète. Utilisez as(x, \"matrix\") ou ." #~ "asmatrix(x) à la place." #~ msgid "trimmed mean of 'sparseVector' -- suboptimally using as.numeric(.)" #~ msgstr "" #~ "moyenne élaguée du 'sparseVector' -- utilisation suboptimale de as." #~ "numeric()" #~ msgid "invalid dimnames given for %s object" #~ msgstr "dimnames incorrects fournis pour l'objet %s" #~ msgid "" #~ "dimnames(.) <- NULL: translated to \n" #~ "dimnames(.) <- list(NULL,NULL) <==> unname(.)" #~ msgstr "" #~ "dimnames(.) <- NULL : traduit en \n" #~ "dimnames(.) <- list(NULL,NULL) <==> unname(.)" #~ msgid "" #~ "'nrow', 'ncol', etc, are disregarded when 'data' is \"Matrix\" already" #~ msgstr "" #~ "'nrow', 'ncol', etc, sont ignorés lorsque 'data' est déjà un objet " #~ "\"Matrix\"" #~ msgid "complex matrices not yet implemented in Matrix package" #~ msgstr "" #~ "les matrices complexes ne sont pas encore implémentées dans le package " #~ "Matrix" #~ msgid "using slow kronecker() method" #~ msgstr "utilisation de la méthode lente kronecker()" #~ msgid "" #~ "Cholesky(A) called for 'A' of class \"%s\";\n" #~ "\t it is currently defined for sparseMatrix only; consider using chol() " #~ "instead" #~ msgstr "" #~ "Cholesky(A) appelé pour 'A' de classe \"%s\" :\n" #~ "\t est actuellement défini pour sparseMatrix seulement ; considérez " #~ "utiliser chol() à la place" #~ msgid "invalid or not-yet-implemented 'Matrix' subsetting" #~ msgstr "" #~ "extraction d'un sous-ensemble de 'Matrix' incorrect ou pas encore " #~ "implémenté" #~ msgid "[ ] : .M.sub.i.logical() maybe inefficient" #~ msgstr "[ ] : .M.sub.i.logical() peut être inefficace" #~ msgid "" #~ "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' (i.logical)?" #~ msgstr "" #~ "nargs() = %d. Arguments additionnels dans '[…]' inacceptables (i." #~ "logical) ?" #~ msgid "" #~ "m[]: inefficiently indexing single elements - should not " #~ "happen, please report!" #~ msgstr "" #~ "m[] : indice sur un seul élément inefficace - ne devrait pas " #~ "se produire, veuillez faire un rapport de ceci !" #~ msgid "" #~ "nargs() = %d. Extraneous illegal arguments inside '[ .. ]' (i.2col)?" #~ msgstr "" #~ "nargs() = %d. Arguments additionnels dans '[ .. ]' incorrects (i.2col) ?" #~ msgid "" #~ ".M.sub.i.2col(): 'i' has no integer column number;\n" #~ " should never happen; please report" #~ msgstr "" #~ ".M.sub.i.2col() : 'i' n'a pas un nombre entier de colonnes;\n" #~ " ceci ne devrait jamais se produire. Veuillez envoyer un rapport de bogue" #~ msgid "not-yet-implemented coercion to \"TsparseMatrix\"" #~ msgstr "conversion automatique en \"TsparseMatrix\" pas encore implémentée" #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "" #~ "Erreur interne de matrice dans [i,,d] ; veuillez reporter ceci" #~ msgid "FIXME: NOT YET FINISHED IMPLEMENTATION" #~ msgstr "FIXME : IMPLEMENTATION PAS ENCORE TERMINEE" #~ msgid "diagonalMatrix in .dense2C() -- should never happen, please report!" #~ msgstr "" #~ "diagonalMatrix dans .dense2C() -- ne devrait jamais se produire, veuillez " #~ "reporter ceci !" #~ msgid "undefined method for class %s" #~ msgstr "méthode non définie pour la classe %s" #~ msgid "dimensions don't match the number of cells" #~ msgstr "les dimensions ne correspondent pas au nombre de cellules" #~ msgid "" #~ "LU computationally singular: ratio of extreme entries in |diag(U)| = %9.4g" #~ msgstr "" #~ "LU calculée singulière : rapport d'entrées extrêmes dans |diag(U)| = %9.4g" #~ msgid "RHS 'b' has wrong number of rows:" #~ msgstr "Le membre droit 'b' a un nombre de lignes incorrect :" #~ msgid "'x' has invalid data type" #~ msgstr "'x' a un type de données incorrect" #~ msgid "length(x) must be either 1 or #{cols}" #~ msgstr "length(x) doit être soit 1 ou #{cols}" #~ msgid "some arguments are not matrices" #~ msgstr "certains arguments ne sont pas des matrices" #~ msgid "%s kind not yet implemented" #~ msgstr "le type %s n'est pas encore implémenté" #~ msgid "non-square matrix" #~ msgstr "matrice non carrée" #~ msgid "" #~ "matrix with non-zero off-diagonals cannot be coerced to \"diagonalMatrix\"" #~ msgstr "" #~ "une matrice avec des cellules non nulles hors diagonale ne peut être " #~ "convertie automatiquement en \"diagonalMatrix\"" #~ msgid "non-matching dimensions" #~ msgstr "dimensions incohérentes" #~ msgid "not a positive definite matrix" #~ msgstr "matrice qui n'est pas un définie positive" #~ msgid "" #~ "as(.,\"dsCMatrix\") is deprecated (since 2008); do use as(., " #~ "\"symmetricMatrix\")" #~ msgstr "" #~ "as(.,\"dsCMatrix\") est obsolète (depuis 2008) ; utilisez plutôt as(., " #~ "\"symmetricMatrix\")" #~ msgid "inefficient coercion (lost triangularity); please report" #~ msgstr "" #~ "conversion automatique inefficace (triangularité perdue) ; veuillez " #~ "reporter ceci" #~ msgid "coercion to \"indMatrix\" only works from integer numeric" #~ msgstr "" #~ "la conversion automatique en \"indMatrix\" ne fonctionne que pour des " #~ "nombres entiers" #~ msgid "" #~ "coercion from list(i1,...,ik, d) to \"indMatrix\" failed.\n" #~ " All entries must be integer valued and the number of columns, d, not " #~ "smaller\n" #~ " than the maximal index i*." #~ msgstr "" #~ "la conversion automatique depuis list(i1,...,ik, d) en \"indMatrix\" a " #~ "échoué.\n" #~ " Toutes les entrées doivent être des valeurs entières et le nombre de " #~ "colonnes, d, ne peut être plus petit\n" #~ " que l'indice maximal i*." #~ msgid "the number of non-zero entries differs from nrow(.)" #~ msgstr "le nombre d'entrées non zéro diffère de nrow(.)" #~ msgid "resulting matrix dimension would be too large" #~ msgstr "la matrice résultante serait trop large" #~ msgid "replacing \"indMatrix\" entries is not allowed, as rarely sensible" #~ msgstr "" #~ "le replacement d'entrées \"indMatrix\" n'est pas autorisé, c'est rarement " #~ "judicieux" #~ msgid "temporarily disabled" #~ msgstr "temporairement désactivé" #~ msgid "cannot coerce NA values to pattern \"ntCMatrix\"" #~ msgstr "" #~ "impossible de convertir automatiquement des 'NA's en modèle \"ntCMatrix\"" #~ msgid "coercion to \"pMatrix\" only works from integer numeric" #~ msgstr "" #~ "conversion automatique en \"pMatrix\" ne fonctionne que pour des nombres " #~ "entiers" #~ msgid "not a square matrix" #~ msgstr "ce n'est pas une matrice carrée" #~ msgid "NA's in (i,j) are not allowed" #~ msgstr "NAs dans (i,j) ne sont pas permis" #~ msgid "" #~ "Both 'symmetric' and 'triangular', i.e. asking for diagonal matrix. Use " #~ "'Diagonal()' instead" #~ msgstr "" #~ "À la fois 'symmetric' et 'triangular', i.e. requête pour une matrice " #~ "diagonale. Utilisez 'Diagonal()' à la place" #~ msgid "triangular matrix must have all i >= j or i <= j" #~ msgstr "la matrice triangulaire doit avoir tous ses i >= j ou i <= j" #~ msgid "Matrix-internal error in [i,,d]; please report" #~ msgstr "" #~ "Erreur interne de matrice dans [i,,d] ; veuillez reporter ceci" #~ msgid "" #~ "qr.R() may differ from qr.R() because of permutations. " #~ "Possibly use our qrR() instead" #~ msgstr "" #~ "qr.R() peut être différent de qr.R() en raison des " #~ "permutations. Utilisez éventuellement notre qrR() à la place" #~ msgid "(un)packing only applies to dense matrices, class(x)='%s'" #~ msgstr "" #~ "la (dé)compaction ne s'applique qu'à des matrices denses, class(x)='%s'" #~ msgid "'x' is not symmetric -- chol() undefined." #~ msgstr "'x' n'est pas symétrique -- chol() non défini." #~ msgid "" #~ "extra argument %s will be disregarded in\n" #~ " %s" #~ msgid_plural "" #~ "extra arguments %s will be disregarded in\n" #~ " %s" #~ msgstr[0] "" #~ "l’argument supplémentaire %s n’est pas utilisé dans\n" #~ " %s" #~ msgstr[1] "" #~ "les arguments supplémentaires %s ne sont pas utilisés dans\n" #~ " %s" #~ msgid " %s %s is undefined" #~ msgstr " %s %s est indéfini" #~ msgid "%s %s is undefined" #~ msgstr "%s %s est indéfini" #~ msgid "variable '%s' converted to a factor" #~ msgstr "variable '%s' converti en facteur" #~ msgid "\"dMatrix\" object with NAs cannot be coerced to \"nMatrix\"" #~ msgstr "" #~ "un objet \"dMatrix\" avec NAs ne peut être converti automatiquement en " #~ "\"nMatrix\"" #~ msgid "not a skinny matrix" #~ msgstr "pas une matrice légère" #~ msgid "longer object length" #~ msgstr "la longueur de l'objet le plus long" #~ msgid "is not a multiple of shorter object length" #~ msgstr "n'est pas un multiple de l'objet le plus court" Matrix/po/de.po0000644000175100001440000015615614575137654013141 0ustar hornikusers# Translation of Matrix to German # Copyright (C) 2001-2021 The R Foundation # This file is distributed under the same license as the Matrix package. # Chris Leick , 2009-2011. # Detlef Steuer , 2012-2021. msgid "" msgstr "" "Project-Id-Version: R 4.0.4 / Matrix 1.3-3\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-14 15:49-0400\n" "PO-Revision-Date: 2021-02-11 13:00+0100\n" "Last-Translator: Detlef Steuer \n" "Language-Team: R Core \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: Csparse.c:26 Csparse.c:61 Csparse.c:86 Csparse.c:113 Csparse.c:127 #: Csparse.c:132 Csparse.c:137 Csparse.c:411 #, fuzzy, c-format msgid "'%s' failed" msgstr "cs_qr fehlgeschlagen" #: Csparse.c:35 cholmod-common.c:54 #, fuzzy, c-format msgid "'%s' slot is not increasing within columns after sorting" msgstr "Slot j ist nicht zunehmend innerhalb einer Spalte" #: Csparse.c:57 #, fuzzy, c-format msgid "'%s' is empty or not square" msgstr "Matrix ist nicht quadratisch" #: Csparse.c:59 Csparse.c:81 Csparse.c:104 solve.c:43 solve.c:988 #, fuzzy, c-format msgid "dimensions of '%s' and '%s' are inconsistent" msgstr "Dimensionen des Systems sind inkonsistent" #: Csparse.c:83 #, c-format msgid "%s(%s, %s) requires m-by-n '%s' with m >= n > 0" msgstr "" #: Csparse.c:106 #, c-format msgid "%s(%s, %s) requires m-by-n '%s' with n >= m > 0" msgstr "" #: Csparse.c:194 coerce.c:220 coerce.c:240 coerce.c:250 coerce.c:905 #: coerce.c:911 coerce.c:1015 coerce.c:1501 coerce.c:1521 coerce.c:1531 #: coerce.c:2061 coerce.c:2256 coerce.c:2262 coerce.c:2268 coerce.c:2397 #: coerce.c:2404 coerce.c:2494 coerce.c:2629 coerce.c:2707 coerce.c:2729 #: coerce.c:4327 coerce.c:4396 dense.c:696 matmult.c:939 matmult.c:1291 #: solve.c:719 solve.c:972 solve.c:1104 sparse.c:1234 sparse.c:1626 #, fuzzy, c-format msgid "invalid '%s' to '%s'" msgstr "ungültiges '%s' Argument" #: Csparse.c:409 #, fuzzy, c-format msgid "failed to open file \"%s\" for writing" msgstr "Öffnen von Datei '%s' zum Schreiben fehlgeschlagen" #: attrib.c:229 #, fuzzy msgid "invalid factor name" msgstr "ungültiges '%s' Argument" #: attrib.c:233 #, c-format msgid "attempt to set factor on %s without '%s' slot" msgstr "" #: bind.c:46 bind.c:153 msgid "number of rows of matrices must match" msgstr "" #: bind.c:48 bind.c:155 msgid "number of columns of matrices must match" msgstr "" #: bind.c:51 bind.c:158 bind.c:182 bind.c:206 cholmod-common.c:608 #: cholmod-common.c:759 cholmod-common.c:874 cholmod-common.c:975 #: cholmod-etc.c:183 cholmod-etc.c:283 cholmod-etc.c:330 coerce.c:215 #: coerce.c:235 coerce.c:260 coerce.c:268 coerce.c:276 coerce.c:341 #: coerce.c:1496 coerce.c:1516 coerce.c:1543 coerce.c:1551 coerce.c:1559 #: matmult.c:28 matmult.c:50 matmult.c:56 #, c-format msgid "dimensions cannot exceed %s" msgstr "" #: bind.c:210 msgid "number of rows of result is not a multiple of vector length" msgstr "" #: bind.c:212 msgid "number of columns of result is not a multiple of vector length" msgstr "" #: bind.c:626 bind.c:691 sparse.c:913 sparse.c:994 #, c-format msgid "%s cannot exceed %s" msgstr "" #: bind.c:756 bind.c:853 cholmod-common.c:978 cholmod-etc.c:333 coerce.c:29 #: coerce.c:518 coerce.c:811 coerce.c:945 coerce.c:2772 coerce.c:3041 #: coerce.c:3146 dense.c:919 matmult.c:151 matmult.c:212 matmult.c:291 #: matmult.c:379 matmult.c:456 matmult.c:550 matmult.c:868 subscript.c:1232 #: subscript.c:1417 utils-R.c:32 #, c-format msgid "attempt to allocate vector of length exceeding %s" msgstr "" #: bind.c:858 matmult.c:1357 msgid "should never happen ..." msgstr "" #: cholmod-common.c:11 cholmod-common.c:34 validity.c:29 validity.c:150 #: validity.c:229 validity.c:248 validity.c:257 validity.c:299 validity.c:316 #: validity.c:350 validity.c:367 validity.c:401 validity.c:403 validity.c:439 #: validity.c:465 validity.c:485 validity.c:926 validity.c:959 validity.c:1041 #: validity.c:1061 validity.c:1127 validity.c:1129 validity.c:1177 #: validity.c:1240 validity.c:1242 validity.c:1288 validity.c:1335 #: validity.c:1384 validity.c:1417 validity.c:1427 validity.c:1440 #: validity.c:1494 validity.c:1496 validity.c:1528 validity.c:1540 #: validity.c:1563 validity.c:1626 validity.c:1645 validity.c:1647 #: validity.c:1679 validity.c:1714 validity.c:1742 #, fuzzy, c-format msgid "'%s' slot is not of type \"%s\"" msgstr "Dim-Slot ist nicht ganzzahlig" #: cholmod-common.c:14 validity.c:274 validity.c:285 validity.c:301 #: validity.c:352 validity.c:487 validity.c:928 validity.c:961 validity.c:1063 #: validity.c:1131 validity.c:1179 validity.c:1244 validity.c:1290 #: validity.c:1429 validity.c:1446 validity.c:1498 validity.c:1500 #: validity.c:1530 validity.c:1542 validity.c:1565 validity.c:1681 #: validity.c:1718 validity.c:1746 validity.c:1796 #, fuzzy, c-format msgid "'%s' slot does not have length %s" msgstr "Dim-Slot muss die Länge 2 haben" #: cholmod-common.c:18 validity.c:304 validity.c:355 validity.c:1634 #: validity.c:1654 validity.c:1656 #, fuzzy, c-format msgid "first element of '%s' slot is not 0" msgstr "erstes Element von Slot p muss Null sein" #: cholmod-common.c:23 cholmod-common.c:46 validity.c:34 validity.c:308 #: validity.c:326 validity.c:359 validity.c:377 validity.c:413 validity.c:415 #: validity.c:491 validity.c:1008 validity.c:1020 validity.c:1067 #: validity.c:1140 validity.c:1152 validity.c:1253 validity.c:1265 #: validity.c:1294 validity.c:1345 validity.c:1394 validity.c:1433 #: validity.c:1453 validity.c:1534 validity.c:1550 validity.c:1575 #: validity.c:1639 validity.c:1659 validity.c:1661 validity.c:1688 #, c-format msgid "'%s' slot contains NA" msgstr "" #: cholmod-common.c:26 validity.c:310 validity.c:361 #, fuzzy, c-format msgid "'%s' slot is not nondecreasing" msgstr "Slot p darf nicht abnehmend sein" #: cholmod-common.c:29 validity.c:312 validity.c:363 #, c-format msgid "first differences of '%s' slot exceed %s" msgstr "" #: cholmod-common.c:37 validity.c:318 validity.c:369 #, fuzzy, c-format msgid "'%s' slot has length less than %s" msgstr "'Dim'-Slot hat eine Länge kleiner zwei" #: cholmod-common.c:49 validity.c:328 validity.c:379 validity.c:417 #: validity.c:420 validity.c:493 validity.c:1010 validity.c:1069 #: validity.c:1142 validity.c:1154 validity.c:1255 validity.c:1267 #: validity.c:1347 validity.c:1396 validity.c:1455 validity.c:1577 #: validity.c:1690 #, fuzzy, c-format msgid "'%s' slot has elements not in {%s}" msgstr "'Dim'-Slot hat eine Länge kleiner zwei" #: cholmod-common.c:165 cholmod-common.c:296 cholmod-common.c:1072 #: cholmod-common.c:1075 cholmod-common.c:1108 cholmod-common.c:1126 #, fuzzy, c-format msgid "'%s' failed in '%s'" msgstr "cs_qr fehlgeschlagen" #: cholmod-common.c:212 #, fuzzy, c-format msgid "'%s' failed in '%s': %s" msgstr "cs_qr fehlgeschlagen" #: cholmod-common.c:601 cholmod-common.c:604 cholmod-common.c:606 #: cholmod-common.c:752 cholmod-common.c:755 cholmod-common.c:757 #: cholmod-common.c:867 cholmod-common.c:870 cholmod-common.c:872 #: cholmod-common.c:969 cholmod-common.c:971 cholmod-etc.c:177 #: cholmod-etc.c:179 cholmod-etc.c:181 cholmod-etc.c:277 cholmod-etc.c:279 #: cholmod-etc.c:281 cholmod-etc.c:324 cholmod-etc.c:326 cs-etc.c:43 #, c-format msgid "wrong '%s'" msgstr "" #: cholmod-common.c:611 cholmod-etc.c:186 #, fuzzy, c-format msgid "'%s' would overflow type \"%s\"" msgstr "Dim-Slot ist nicht ganzzahlig" #: cholmod-common.c:615 cholmod-etc.c:190 #, c-format msgid "n+1 would overflow type \"%s\"" msgstr "" #: cholmod-common.c:620 cholmod-etc.c:195 #, fuzzy, c-format msgid "leading principal minor of order %d is not positive" msgstr "der führende Minor der Ordnung %d ist nicht positiv definit" #: cholmod-common.c:623 cholmod-etc.c:198 #, fuzzy, c-format msgid "leading principal minor of order %d is zero" msgstr "der führende Minor der Ordnung %d ist nicht positiv definit" #: cholmod-common.c:973 cholmod-etc.c:328 msgid "leading dimension not equal to number of rows" msgstr "" #: cholmod-common.c:1037 #, c-format msgid "" "invalid simplicial Cholesky factorization: structural zero on main diagonal " "in column %d" msgstr "" #: cholmod-common.c:1097 #, fuzzy, c-format msgid "CHOLMOD error '%s' at file '%s', line %d" msgstr "Cholmod-Fehler '%s' bei Datei %s, Zeile %d" #: cholmod-common.c:1100 #, fuzzy, c-format msgid "CHOLMOD warning '%s' at file '%s', line %d" msgstr "Cholmod-Warnung '%s' bei Datei %s, Zeile %d" #: coerce.c:24 coerce.c:364 coerce.c:1050 #, fuzzy, c-format msgid "attempt to construct non-square %s" msgstr "Determinante benötigt eine quadratische Matrix" #: coerce.c:186 coerce.c:476 coerce.c:1467 coerce.c:1622 #, c-format msgid "second argument of '%s' does not specify a subclass of %s" msgstr "" #: coerce.c:194 coerce.c:200 coerce.c:484 coerce.c:490 coerce.c:925 #: coerce.c:1475 coerce.c:1481 coerce.c:1630 coerce.c:1636 coerce.c:2275 #: coerce.c:3344 coerce.c:3349 #, fuzzy, c-format msgid "'%s' must be \"%s\" or \"%s\"" msgstr "'%s' muss in '%s' sein" #: coerce.c:246 coerce.c:496 coerce.c:793 coerce.c:917 coerce.c:1527 #: coerce.c:1642 dense.c:322 dense.c:1102 dense.c:1678 dense.c:1683 #: dense.c:1929 dense.c:2124 sparse.c:784 sparse.c:2449 sparse.c:3141 #: sparse.c:3146 sparse.c:3151 sparse.c:3427 sparse.c:3664 #, fuzzy, c-format msgid "'%s' must be %s or %s" msgstr "'%s' muss in '%s' sein" #: coerce.c:266 coerce.c:274 coerce.c:285 coerce.c:1549 coerce.c:1557 #: coerce.c:1568 msgid "nonempty vector supplied for empty matrix" msgstr "" #: coerce.c:287 coerce.c:1570 #, c-format msgid "vector length (%lld) exceeds matrix length (%d * %d)" msgstr "" #: coerce.c:290 coerce.c:1573 #, c-format msgid "matrix length (%d * %d) is not a multiple of vector length (%lld)" msgstr "" #: coerce.c:521 #, c-format msgid "coercing n-by-n %s to %s is not supported for n*n exceeding %s" msgstr "" #: coerce.c:525 coerce.c:815 coerce.c:949 #, c-format msgid "sparse->dense coercion: allocating vector of size %0.1f GiB" msgstr "" #: coerce.c:1196 coerce.c:1941 coerce.c:2948 coerce.c:2954 #, c-format msgid "attempt to construct %s with more than %s nonzero entries" msgstr "" #: coerce.c:3246 #, fuzzy msgid "attempt to pack non-square matrix" msgstr "Determinante benötigt eine quadratische Matrix" #: coerce.c:3420 coerce.c:3590 #, c-format msgid "unable to aggregate %s with '%s' and '%s' slots of length exceeding %s" msgstr "" #: coerce.c:4211 #, fuzzy, c-format msgid "attempt to pack a %s" msgstr "Determinante benötigt eine quadratische Matrix" #: coerce.c:4330 dense.c:1232 sparse.c:2580 #, fuzzy, c-format msgid "'%s' must be %s or %s or %s" msgstr "'%s' muss in '%s' sein" #: dense.c:210 dense.c:215 sparse.c:590 sparse.c:595 #, fuzzy, c-format msgid "'%s' (%d) must be an integer from %s (%d) to %s (%d)" msgstr "'%s' muss in '%s' sein" #: dense.c:218 sparse.c:598 #, fuzzy, c-format msgid "'%s' (%d) must be less than or equal to '%s' (%d)" msgstr "'%s' muss in '%s' sein" #: dense.c:428 sparse.c:1070 #, fuzzy, c-format msgid "replacement diagonal has incompatible type \"%s\"" msgstr "Diagonale zur Ersetzung hat die falsche Länge" #: dense.c:437 sparse.c:1079 msgid "replacement diagonal has wrong length" msgstr "Diagonale zur Ersetzung hat die falsche Länge" #: dense.c:622 sparse.c:1275 #, fuzzy msgid "attempt to symmetrize a non-square matrix" msgstr "Determinante benötigt eine quadratische Matrix" #: dense.c:721 sparse.c:1653 msgid "attempt to get symmetric part of non-square matrix" msgstr "" #: dense.c:873 sparse.c:2083 msgid "attempt to get skew-symmetric part of non-square matrix" msgstr "" #: dense.c:1673 sparse.c:3136 #, fuzzy, c-format msgid "'%s' must be %d or %d" msgstr "'%s' muss in '%s' sein" #: dense.c:2156 #, c-format msgid "incorrect left cyclic shift, j (%d) < 0" msgstr "falsches zyklisches Linksverschieben, j (%d) < 0" #: dense.c:2159 #, c-format msgid "incorrect left cyclic shift, j (%d) >= k (%d)" msgstr "falsches zyklisches Linksverschieben, j (%d) >= k (%d)" #: dense.c:2162 #, c-format msgid "incorrect left cyclic shift, k (%d) > ldx (%d)" msgstr "falsches zyklisches Linksverschieben, k (%d) > ldx (%d)" #: dense.c:2215 #, fuzzy msgid "unknown error in getGivens" msgstr "Unbekannter Fehler in getGivens" #: dense.c:2224 dense.c:2238 dense.c:2268 msgid "X must be a numeric (double precision) matrix" msgstr "X muss eine numerische (doppelte Genauigkeit) Matrix sein" #: dense.c:2240 dense.c:2270 msgid "y must be a numeric (double precision) matrix" msgstr "y muss eine numerische (doppelte Genauigkeit) Matrix sein" #: dense.c:2244 dense.c:2274 #, c-format msgid "number of rows in y (%d) does not match number of rows in X (%d)" msgstr "" "Anzahl der Zeilen in y (%d) passt nicht zur Anzahl der Zeilen in X (%d)" # http://de.wikipedia.org/wiki/LAPACK #: dense.c:2260 #, fuzzy, c-format msgid "LAPACK dposv returned error code %d" msgstr "Lapack-Routine dposv gab Fehlerkode %d zurück" #: dense.c:2288 dense.c:2294 #, fuzzy, c-format msgid "LAPACK dgels returned error code %d" msgstr "Lapack-Routine %s gab einen Fehlerkode %d zurück" #: dense.c:2313 msgid "X must be a real (numeric) matrix" msgstr "X muss eine echte (numerische) Matrix sein" #: dense.c:2316 #, fuzzy, c-format msgid "tol, given as %g, must be >= 0" msgstr "tol, als %g gegeben, muss <= 1 sein" #: dense.c:2318 #, c-format msgid "tol, given as %g, must be <= 1" msgstr "tol, als %g gegeben, muss <= 1 sein" #: dense.c:2347 dense.c:2355 #, fuzzy, c-format msgid "LAPACK dgeqrf returned error code %d" msgstr "Erster Aufruf von dgeqrf gab Fehlerkode %d zurück" #: dense.c:2360 dense.c:2383 #, fuzzy, c-format msgid "LAPACK dtrcon returned error code %d" msgstr "Lapack-Routine dtrcon gab Fehlerkode %d zurück" #: determinant.c:33 #, fuzzy msgid "determinant of non-square matrix is undefined" msgstr "Determinante benötigt eine quadratische Matrix" #: determinant.c:276 #, fuzzy, c-format msgid "%s(<%s>) does not support structurally rank deficient case" msgstr "%s(): Fall mit strukturellem Rangdefizit: evtl FALSCHE Nullen" #: expm.c:39 msgid "Matrix exponential requires square, non-null matrix" msgstr "Exponentielle Matrix benötigt eine quadratische Matrix ungleich Null" #: expm.c:56 expm.c:58 #, c-format msgid "dgeMatrix_exp: LAPACK routine dgebal returned %d" msgstr "dgeMatrix_exp: LAPACK-Routine dgebal gab %d zurück" #: expm.c:96 #, c-format msgid "dgeMatrix_exp: dgetrf returned error code %d" msgstr "dgeMatrix_exp: dgetrf gab Fehlerkode %d zurück" #: expm.c:98 #, c-format msgid "dgeMatrix_exp: dgetrs returned error code %d" msgstr "dgeMatrix_exp: dgetrs gab Fehlerkode %d zurück" #: factor.c:330 msgid "dgeMatrix_Schur: argument x must be a non-null square matrix" msgstr "" "dgeMatrix_Schur: Argument x muss eine quadratische Matrix ungleich Null sein" #: factor.c:343 msgid "dgeMatrix_Schur: first call to dgees failed" msgstr "dgeMatrix_Schur: Erster Aufruf von dgees fehlgeschlagen" #: factor.c:352 #, c-format msgid "dgeMatrix_Schur: dgees returned code %d" msgstr "dgeMatrix_Schur: dgees gab Fehlerkode %d zurück" #: factor.c:403 sparse.c:196 #, fuzzy, c-format msgid "'%s' is not a number" msgstr "%s ist keine Liste" #: factor.c:424 #, c-format msgid "LU factorization of m-by-n %s requires m == n" msgstr "" #: factor.c:433 #, c-format msgid "LU factorization of %s failed: out of memory or near-singular" msgstr "" #: factor.c:510 #, c-format msgid "QR factorization of m-by-n %s requires m >= n" msgstr "" #: factor.c:519 #, c-format msgid "QR factorization of %s failed: out of memory" msgstr "" #: factor.c:619 factor.c:897 #, c-format msgid "'%s' is not a number or not finite" msgstr "" #: idz.c:467 idz.c:528 #, c-format msgid "incompatible '%s' and '%s' in '%s'" msgstr "" #: kappa.c:10 kappa.c:54 #, fuzzy, c-format msgid "argument '%s' is not of type \"%s\"" msgstr "Argument type[1]='%s' muss eine Zeichenkette aus einem Buchstaben sein" #: kappa.c:13 kappa.c:57 #, fuzzy, c-format msgid "argument '%s' has length %d" msgstr "'%s' muss die Zeichenkettenlänge 1 haben" #: kappa.c:17 kappa.c:61 #, fuzzy, c-format msgid "argument '%s' (\"%s\") does not have string length %d" msgstr "'%s' muss die Zeichenkettenlänge 1 haben" #: kappa.c:41 #, c-format msgid "" "argument '%s' (\"%s\") is not \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", or " "\"%s\"" msgstr "" #: kappa.c:75 #, fuzzy, c-format msgid "argument '%s' (\"%s\") is not \"%s\", \"%s\", or \"%s\"" msgstr "'%s' muss die Zeichenkettenlänge 1 haben" #: kappa.c:238 #, c-format msgid "%s(%s) is undefined: '%s' is not square" msgstr "" #: matmult.c:107 matmult.c:210 matmult.c:289 matmult.c:377 matmult.c:454 #: matmult.c:548 matmult.c:812 matmult.c:862 msgid "non-conformable arguments" msgstr "" #: matmult.c:782 matmult.c:810 #, c-format msgid "'%s' does not support complex matrices" msgstr "" #: objects.c:23 #, c-format msgid "unexpected type \"%s\" in '%s'" msgstr "" #: objects.c:41 objects.c:58 #, c-format msgid "unexpected kind \"%c\" in '%s'" msgstr "" #: perm.c:26 perm.c:106 msgid "attempt to get sign of non-permutation" msgstr "" #: perm.c:51 perm.c:123 msgid "attempt to invert non-permutation" msgstr "" #: perm.c:66 #, fuzzy msgid "invalid transposition vector" msgstr "ungültiger Zeilenindex an Position %d" #: perm.c:79 perm.c:81 perm.c:96 perm.c:98 perm.c:113 perm.c:133 perm.c:145 #, fuzzy, c-format msgid "'%s' is not of type \"%s\"" msgstr "Dim-Slot ist nicht ganzzahlig" #: perm.c:83 perm.c:100 perm.c:147 #, fuzzy, c-format msgid "'%s' does not have length %d" msgstr "Slot '%s' muss die Länge 1 haben" #: perm.c:86 perm.c:103 #, c-format msgid "'%s' is NA" msgstr "" #: perm.c:115 perm.c:138 #, fuzzy, c-format msgid "'%s' or '%s' is not of type \"%s\"" msgstr "Dim-Slot ist nicht ganzzahlig" #: perm.c:117 perm.c:140 #, fuzzy, c-format msgid "'%s' or '%s' does not have length %d" msgstr "Slot '%s' muss die Länge 1 haben" #: perm.c:120 perm.c:143 #, c-format msgid "'%s' or '%s' is NA" msgstr "" #: perm.c:136 #, c-format msgid "'%s' has length exceeding %s" msgstr "" #: perm.c:150 #, c-format msgid "'%s' is NA or less than %s" msgstr "" #: solve.c:38 #, fuzzy, c-format msgid "'%s' is not square" msgstr "Matrix ist nicht quadratisch" #: solve.c:497 #, c-format msgid "%s(<%s>, <%s>) failed: out of memory" msgstr "" #: solve.c:618 #, fuzzy, c-format msgid "attempt to construct %s with more than %s nonzero elements" msgstr "Determinante benötigt eine quadratische Matrix" #: subscript.c:1542 subscript.c:1695 subscript.c:1938 subscript.c:2122 #, c-format msgid "%s too dense for %s; would have more than %s nonzero entries" msgstr "" #: subscript.c:2209 #, c-format msgid "NA subscripts in %s not supported for '%s' inheriting from %s" msgstr "" #: t_subassign.c:141 msgid "invalid class of 'x' in Csparse_subassign()" msgstr "ungültige Klasse von 'x' in Csparse_subassign()" #: t_subassign.c:143 msgid "invalid class of 'value' in Csparse_subassign()" msgstr "ungültige Klasse von 'value' in Csparse_subassign()" #: t_subassign.c:186 #, c-format msgid "x[] <- val: val is coerced to logical for \"%s\" x" msgstr "x[] <- val: val in booleschen Wert umgewandelt für \"%s\" x" #: t_subassign.c:191 #, c-format msgid "" "x[] <- val: val should be integer or logical, is coerced to integer, for " "\"%s\" x" msgstr "" "x[] <- val: val sollte ganzzahlig oder logisch sein, wird in ganze Zahl " "umgewandelt für \"%s\" x" #: t_subassign.c:198 msgid "programming error in Csparse_subassign() should never happen" msgstr "Fehler in Csparse_subassign(); sollte niemals vorkommen" #: utils-R.c:30 utils-R.c:116 #, c-format msgid "indices would exceed %s" msgstr "" #: utils-R.c:235 utils-R.c:270 utils-R.c:281 utils-R.c:312 msgid "Argument must be numeric-like atomic vector" msgstr "Argument muss zahl-ähnlich atomar sein" #: utils-R.c:345 msgid "'data' must be of a vector type" msgstr "'data' muss ein Vektortyp sein" #: utils-R.c:352 #, c-format msgid "invalid '%s' argument" msgstr "ungültiges '%s' Argument" #: utils-R.c:359 utils-R.c:367 msgid "non-numeric matrix extent" msgstr "nicht-numerische Matrix-Ausdehnung" #: utils-R.c:362 msgid "invalid 'nrow' value (too large or NA)" msgstr "unzulässiger Wert für 'nrow' (zu groß oder NA)" #: utils-R.c:364 msgid "invalid 'nrow' value (< 0)" msgstr "unzulässiger Wert für 'nrow' (< 0)" #: utils-R.c:370 msgid "invalid 'ncol' value (too large or NA)" msgstr "unzulässiger Wert für 'ncol' (zu groß oder NA)" #: utils-R.c:372 msgid "invalid 'ncol' value (< 0)" msgstr "unzulässiger Wert für 'ncol' (< 0)" #: utils-R.c:390 #, fuzzy, c-format msgid "" "data length [%lld] is not a sub-multiple or multiple of the number of rows " "[%d]" msgstr "" "Datenlänge [%d] ist kein Teilvielfaches oder Vielfaches der Zahl der Zeilen " "[%d]" #: utils-R.c:395 #, fuzzy, c-format msgid "" "data length [%lld] is not a sub-multiple or multiple of the number of " "columns [%d]" msgstr "" "Datenlänge [%d] ist kein Teilvielfaches oder Vielfaches der Zahl der Spalten " "[%d]" #: utils-R.c:399 msgid "data length exceeds size of matrix" msgstr "Datenlänge überschreitet Größe der Matrix" #: utils-R.c:404 msgid "too many elements specified" msgstr "zu viele Elemente angegeben" #: utils-R.c:545 msgid "Argument ij must be 2-column integer matrix" msgstr "Argument ij muss eine zweispaltige ganzzahlige Matrix sein" #: utils-R.c:570 msgid "subscript 'i' out of bounds in M[ij]" msgstr "Subskript 'i' außerhalb des Bereichs in M[ij]" #: utils-R.c:572 msgid "subscript 'j' out of bounds in M[ij]" msgstr "Subskript 'j' außerhalb des Bereichs in M[ij]" #: utils-R.c:626 msgid "i and j must be integer vectors of the same length" msgstr "i und j müssen Ganzzahlvektoren mit der gleichen Länge sein" #: validity.c:31 validity.c:52 validity.c:231 validity.c:250 validity.c:259 #: validity.c:441 validity.c:467 validity.c:977 validity.c:1419 validity.c:1443 #, fuzzy, c-format msgid "'%s' slot does not have length %d" msgstr "Dim-Slot muss die Länge 2 haben" #: validity.c:36 validity.c:932 validity.c:965 #, fuzzy, c-format msgid "'%s' slot has negative elements" msgstr "'Dim'-Slot hat eine Länge kleiner zwei" #: validity.c:50 validity.c:164 #, fuzzy, c-format msgid "'%s' slot is not a list" msgstr "Dim-Slot ist nicht ganzzahlig" #: validity.c:68 #, fuzzy, c-format msgid "%s[[%d]] is not NULL or a vector" msgstr "Dimnames[%d] ist kein Zeichenkettenvektor" #: validity.c:71 #, fuzzy, c-format msgid "length of %s[[%d]] (%lld) is not equal to %s[%d] (%d)" msgstr "length(Dimnames[%d]() unterscheidet sich von Dim[%d], was %d ist" #: validity.c:170 #, c-format msgid "'%s' slot has no '%s' attribute" msgstr "" #: validity.c:181 validity.c:244 validity.c:435 validity.c:506 validity.c:1082 #: validity.c:1413 validity.c:1774 #, c-format msgid "%s[1] != %s[2] (matrix is not square)" msgstr "" #: validity.c:206 validity.c:219 #, c-format msgid "%s[1] differs from %s[2]" msgstr "" #: validity.c:234 validity.c:253 validity.c:262 validity.c:444 #, fuzzy, c-format msgid "'%s' slot is not \"%s\" or \"%s\"" msgstr "x-Slot ist kein \\\"double\\\"" #: validity.c:331 validity.c:1580 #, fuzzy, c-format msgid "'%s' slot is not increasing within columns" msgstr "Slot j ist nicht zunehmend innerhalb einer Spalte" #: validity.c:382 #, fuzzy, c-format msgid "'%s' slot is not increasing within rows" msgstr "Slot j ist nicht zunehmend innerhalb einer Spalte" #: validity.c:406 validity.c:790 validity.c:816 validity.c:842 validity.c:1043 #: validity.c:1649 validity.c:1651 #, fuzzy, c-format msgid "'%s' and '%s' slots do not have equal length" msgstr "Dim-Slot muss die Länge 2 haben" #: validity.c:409 #, c-format msgid "'%s' slot has nonzero length but %s is 0" msgstr "" #: validity.c:450 validity.c:454 #, fuzzy, c-format msgid "'%s' slot is \"%s\" but '%s' slot does not have length %s" msgstr "Dim-Slot muss die Länge 2 haben" #: validity.c:470 #, fuzzy, c-format msgid "'%s' slot is not %d or %d" msgstr "x-Slot ist kein \\\"double\\\"" #: validity.c:476 validity.c:479 #, c-format msgid "%s-by-%s %s invalid for positive '%s' when %s=%d" msgstr "" #: validity.c:516 validity.c:1145 validity.c:1157 validity.c:1258 #: validity.c:1270 validity.c:1350 validity.c:1399 validity.c:1458 #, c-format msgid "'%s' slot contains duplicates" msgstr "" #: validity.c:544 validity.c:589 validity.c:635 validity.c:680 validity.c:724 #: validity.c:759 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries below the diagonal" msgstr "" "uplo='U' darf keine dünn besetzten Einträge unterhalb der Diagonale haben" #: validity.c:554 validity.c:602 validity.c:645 validity.c:693 validity.c:729 #: validity.c:770 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries above the diagonal" msgstr "" "uplo='L' darf keine dünn besetzten Einträge unterhalb der Diagonale haben" #: validity.c:592 validity.c:605 validity.c:683 validity.c:696 validity.c:762 #: validity.c:773 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries on the diagonal" msgstr "" "uplo='U' darf keine dünn besetzten Einträge unterhalb der Diagonale haben" #: validity.c:878 validity.c:902 validity.c:906 msgid "matrix has negative diagonal elements" msgstr "" #: validity.c:922 validity.c:950 validity.c:954 msgid "matrix has nonunit diagonal elements" msgstr "" #: validity.c:974 validity.c:999 validity.c:1793 #, fuzzy, c-format msgid "'%s' slot is not of type \"%s\" or \"%s\"" msgstr "Dim-Slot ist nicht ganzzahlig" #: validity.c:982 validity.c:989 #, fuzzy, c-format msgid "'%s' slot is NA" msgstr "Dim-Slot ist nicht ganzzahlig" #: validity.c:984 validity.c:991 #, fuzzy, c-format msgid "'%s' slot is negative" msgstr "'Dim'-Slot hat eine Länge kleiner zwei" #: validity.c:993 #, fuzzy, c-format msgid "'%s' slot exceeds %s" msgstr "'%s' muss in '%s' sein" #: validity.c:1003 #, fuzzy, c-format msgid "'%s' slot has length greater than '%s' slot" msgstr "'Dim'-Slot hat eine Länge kleiner zwei" #: validity.c:1013 validity.c:1641 validity.c:1663 validity.c:1665 #, fuzzy, c-format msgid "'%s' slot is not increasing" msgstr "Slot j ist nicht zunehmend innerhalb einer Spalte" #: validity.c:1023 #, fuzzy, c-format msgid "'%s' slot has elements not in {%s} after truncation towards zero" msgstr "'Dim'-Slot hat eine Länge kleiner zwei" #: validity.c:1026 #, fuzzy, c-format msgid "'%s' slot is not increasing after truncation towards zero" msgstr "Slot j ist nicht zunehmend innerhalb einer Spalte" #: validity.c:1092 validity.c:1119 validity.c:1781 validity.c:1788 #, fuzzy, c-format msgid "dimensions of '%s' slot are not identical to '%s'" msgstr "Dimensionen von x und y sind nicht kompatibel für %s" #: validity.c:1094 #, c-format msgid "'%s' slot is upper (not lower) triangular" msgstr "" #: validity.c:1107 #, c-format msgid "'%s' slot has nonunit diagonal elements" msgstr "" #: validity.c:1121 #, c-format msgid "'%s' slot is lower (not upper) triangular" msgstr "" #: validity.c:1133 validity.c:1246 validity.c:1337 validity.c:1386 #, fuzzy, c-format msgid "'%s' slot does not have length %s or length %s" msgstr "Dim-Slot muss die Länge 2 haben" #: validity.c:1173 msgid "matrix has more columns than rows" msgstr "" #: validity.c:1193 #, fuzzy, c-format msgid "'%s' slot has fewer than %s rows" msgstr "'Dim'-Slot hat eine Länge kleiner zwei" #: validity.c:1195 #, fuzzy, c-format msgid "'%s' slot has more than %s rows" msgstr "'Dim'-Slot hat eine Länge kleiner zwei" #: validity.c:1197 validity.c:1219 #, fuzzy, c-format msgid "'%s' slot does not have %s columns" msgstr "Dim-Slot muss die Länge 2 haben" #: validity.c:1204 #, fuzzy, c-format msgid "'%s' slot must be lower trapezoidal but has entries above the diagonal" msgstr "" "uplo='L' darf keine dünn besetzten Einträge unterhalb der Diagonale haben" #: validity.c:1217 #, fuzzy, c-format msgid "'%s' slot does not have %s row" msgstr "Dim-Slot muss die Länge 2 haben" #: validity.c:1226 #, fuzzy, c-format msgid "'%s' slot must be upper trapezoidal but has entries below the diagonal" msgstr "" "uplo='U' darf keine dünn besetzten Einträge unterhalb der Diagonale haben" #: validity.c:1230 #, c-format msgid "'%s' slot has negative diagonal elements" msgstr "" #: validity.c:1296 #, c-format msgid "'%s' slot has elements not in {%s}\\{%s}" msgstr "" #: validity.c:1305 #, c-format msgid "'%s' slot has unpaired negative elements" msgstr "" #: validity.c:1331 validity.c:1375 validity.c:1379 validity.c:1727 #: validity.c:1759 msgid "Cholesky factor has negative diagonal elements" msgstr "" #: validity.c:1422 #, fuzzy, c-format msgid "%s[%d] (%s) is not in %s" msgstr "%s ist keine Liste" #: validity.c:1435 validity.c:1536 #, fuzzy, c-format msgid "%s is not in {%s}" msgstr "%s ist keine Liste" #: validity.c:1472 #, c-format msgid "%s is not representable as \"%s\"" msgstr "" #: validity.c:1477 validity.c:1483 #, c-format msgid "%s[%d] (%s) is not %d or %d" msgstr "" #: validity.c:1480 validity.c:1596 validity.c:1599 validity.c:1602 #, c-format msgid "%s[%d] (%s) is not %d" msgstr "" #: validity.c:1505 #, c-format msgid "%s has elements not in {%s}" msgstr "" #: validity.c:1508 #, c-format msgid "%s has elements not in {%s}\\{%s}" msgstr "" #: validity.c:1511 #, c-format msgid "%s is %d but columns are not stored in increasing order" msgstr "" #: validity.c:1514 validity.c:1517 #, c-format msgid "traversal of '%s' slot does not complete in exactly %s steps" msgstr "" #: validity.c:1523 validity.c:1525 #, fuzzy, c-format msgid "%s is not %d" msgstr "%s ist keine Liste" #: validity.c:1546 #, c-format msgid "column '%s' is stored first but %s is not 0" msgstr "" #: validity.c:1552 #, fuzzy, c-format msgid "'%s' slot is not increasing when traversed in stored column order" msgstr "Slot j ist nicht zunehmend innerhalb einer Spalte" #: validity.c:1554 #, c-format msgid "'%s' slot allocates fewer than %s elements for column '%s'" msgstr "" #: validity.c:1557 #, c-format msgid "'%s' slot allocates more than %s elements for column '%s'" msgstr "" #: validity.c:1571 #, c-format msgid "first entry in column '%s' does not have row index '%s'" msgstr "" #: validity.c:1605 validity.c:1608 #, c-format msgid "%s[%d] (%s) is negative" msgstr "" #: validity.c:1611 #, c-format msgid "%s[%d] (%s) is not less than %s" msgstr "" #: validity.c:1629 #, fuzzy, c-format msgid "'%s' slot has length less than %d" msgstr "'Dim'-Slot hat eine Länge kleiner zwei" #: validity.c:1631 #, fuzzy, c-format msgid "'%s' slot has length greater than %s" msgstr "'Dim'-Slot hat eine Länge kleiner zwei" #: validity.c:1636 #, fuzzy, c-format msgid "last element of '%s' slot is not %s" msgstr "erstes Element von Slot p muss Null sein" #: validity.c:1669 #, c-format msgid "first differences of '%s' slot are less than those of '%s' slot" msgstr "" #: validity.c:1672 #, c-format msgid "supernode lengths exceed %s" msgstr "" #: validity.c:1674 #, c-format msgid "first differences of '%s' slot are not equal to supernode lengths" msgstr "" #: validity.c:1694 #, c-format msgid "" "'%s' slot is wrong within diagonal blocks (row and column indices do not " "coincide)" msgstr "" #: validity.c:1697 #, fuzzy, c-format msgid "'%s' slot is not increasing within supernodes" msgstr "Slot j ist nicht zunehmend innerhalb einer Spalte" #: validity.c:1812 #, fuzzy, c-format msgid "invalid class \"%s\" object: %s" msgstr "ungültige Klasse des Objektes zu %s" #: vector.c:90 #, c-format msgid "%s length cannot exceed %s" msgstr "" #, fuzzy, c-format #~ msgid "dgeMatrix_svd(x,*): dim(x)[j] = %d is too large" #~ msgstr "Matrix dimension %d x %d (= %g) ist zu groß" # http://www.matheboard.de/archive/160705/thread.html #, c-format #~ msgid "diagonal element %d of Cholesky factor is missing" #~ msgstr "Diagonalelement %d des Choleskyfaktors fehlt" #, c-format #~ msgid "cholmod_factorize_p failed: status %d, minor %d of ncol %d" #~ msgstr "cholmod_factorize_p fehlgeschlagen: Status %d, Minor %d von ncol %d" #~ msgid "cholmod_change_factor failed" #~ msgstr "cholmod_change_factor fehlgeschlagen" #~ msgid "cholmod_write_sparse returned error code" #~ msgstr "cholmod_write_sparse gab Fehlerkode zurück" #, c-format #~ msgid "%s = '%s' (back-permuted) is experimental" #~ msgstr "%s = '%s' (zurückgetauscht) ist experimentell" #~ msgid "diag_tC(): invalid 'resultKind'" #~ msgstr "diag_tC(): 'resultKind' ungültig" #, fuzzy #~ msgid "complex matrices are not yet supported" #~ msgstr "Kode für komplexe dünn besetzte Matrizen noch nicht geschrieben" #~ msgid "Argument rho must be an environment" #~ msgstr "Argument rho muss eine Umgebung sein" #~ msgid "invalid class of object to as_cholmod_sparse" #~ msgstr "ungültige Klasse des Objektes zu as_cholmod_sparse" #~ msgid "invalid object passed to as_cholmod_sparse" #~ msgstr "ungültiges Objekt an as_cholmod_sparse übergeben" #~ msgid "in_place cholmod_sort returned an error code" #~ msgstr "in_place cholmod_sort gab einen Fehlerkode zurück" #~ msgid "cholmod_sort returned an error code" #~ msgstr "cholmod_sort gab einen Fehlerkode zurück" #~ msgid "chm_sparse_to_SEXP(, *): invalid 'Rkind' (real kind code)" #~ msgstr "chm_sparse_to_SEXP(, *): ungültiges 'Rkind' (echter Artkode)" #~ msgid "unknown xtype in cholmod_sparse object" #~ msgstr "unbekannter xtype in Objekt cholmod_sparse" #~ msgid "complex sparse matrix code not yet written" #~ msgstr "Kode für komplexe dünn besetzte Matrizen noch nicht geschrieben" #~ msgid "Symmetric and triangular both set" #~ msgstr "Symmetrisch und dreieckig sind beide gesetzt" #~ msgid "invalid class of object to as_cholmod_triplet" #~ msgstr "ungültige Klasse des Objektes zu as_cholmod_triplet" #~ msgid "as_cholmod_triplet(): could not reallocate for internal diagU2N()" #~ msgstr "" #~ "as_cholmod_triplet(): konnte für internes diagU2N() nicht reallozieren" #~ msgid "unknown xtype in cholmod_triplet object" #~ msgstr "unbekannter xtype in Objekt cholmod_triplet" #~ msgid "invalid class of object to as_cholmod_dense" #~ msgstr "ungültige Klasse des Objektes zu as_cholmod_dense" #, c-format #~ msgid "" #~ "chm_transpose_dense(ans, x) not yet implemented for %s different from %s" #~ msgstr "" #~ "chm_transpose_dense(ans, x) noch nicht implementiert für %s verschieden " #~ "von %s" #, c-format #~ msgid "Unable to initialize cholmod: error code %d" #~ msgstr "cholmod kann nicht initialisiert werden: Fehlerkode %d" #~ msgid "unknown 'Rkind'" #~ msgstr "'Rkind' unbekannt" #~ msgid "unknown xtype" #~ msgstr "unbekannter xtype" #~ msgid "code for cholmod_dense with holes not yet written" #~ msgstr "Kode für cholmod_dense mit Löchern noch nicht geschrieben" #~ msgid "don't know if a dense pattern matrix makes sense" #~ msgstr "es ist nicht klar, ob eine dicht besetzte Mustermatrix sinnvoll ist" #, fuzzy #~ msgid "object of invalid class to 'as_cholmod_factor()'" #~ msgstr "ungültige Klasse des Objektes zu as_cholmod_factor" #~ msgid "failure in as_cholmod_factor" #~ msgstr "Misserfolg in as_cholmod_factor" #~ msgid "CHOLMOD factorization was unsuccessful" #~ msgstr "CHOLMOD-Faktorzerlegung war nicht erfolgreich" #, c-format #~ msgid "f->xtype of %d not recognized" #~ msgstr "f->xtype von %d nicht erkannt" #, c-format #~ msgid "chm_diagN2U(): nrow=%d, ncol=%d" #~ msgstr "chm_diagN2U(-matrix) requires a 'tall' rectangular matrix" #~ msgstr "" #~ "dgCMatrix_qrsol(<%d x %d>-Matrix) benötigt eine 'lange' rechteckige Matrix" #~ msgid "cs_qrsol() failed inside dgCMatrix_qrsol()" #~ msgstr "cs_qrsol() innerhalb dgCMatrix_qrsol() fehlgeschlagen" #~ msgid "dgCMatrix_cholsol requires a 'short, wide' rectangular matrix" #~ msgstr "dgCMatrix_cholsol benötigt eine kurze breite rechteckige Matrix" #~ msgid "cholmod_sdmult error (rhs)" #~ msgstr "cholmod_sdmult-Fehler (rhs)" #, c-format #~ msgid "cholmod_factorize failed: status %d, minor %d from ncol %d" #~ msgstr "cholmod_factorize fehlgeschlagen: Status %d, Minor %d von ncol %d" #, c-format #~ msgid "cholmod_solve (CHOLMOD_A) failed: status %d, minor %d from ncol %d" #~ msgstr "" #~ "cholmod_solve (CHOLMOD_A) fehlgeschlagen: Status %d, Minor %d von ncol %d" #~ msgid "cholmod_sdmult error (resid)" #~ msgstr "cholmod_sdmult-Fehler (resid)" #~ msgid "SuiteSparseQR_C_QR returned an error code" #~ msgstr "SuiteSparseQR_C_QR gab einen Fehlerkode zurück" #, fuzzy, c-format #~ msgid "LAPACK routine '%s': matrix is exactly singular, %s[i,i]=0, i=%d" #~ msgstr "Lapack-Routine dgetrs:: System ist exakt singulär" #, fuzzy, c-format #~ msgid "" #~ "LAPACK routine '%s': leading principal minor of order %d is not positive" #~ msgstr "der führende Minor der Ordnung %d ist nicht positiv definit" #, fuzzy #~ msgid "missing 'Matrix' namespace; should never happen" #~ msgstr "fehlender 'Matrix'-Namensraum: Sollte niemals vorkommen" #, fuzzy #~ msgid "'Matrix' namespace not determined correctly" #~ msgstr "Matrix-Namensraum nicht korrekt bestimmt" #~ msgid "Csparse_sort(x): x is not a valid (apart from sorting) CsparseMatrix" #~ msgstr "" #~ "Csparse_sort(x): x ist keine gültige (abgesehen vom Sortieren) " #~ "CsparseMatrix" #, c-format #~ msgid "Impossible Rk_x/Rk_y in Csparse_%s(), please report" #~ msgstr "Unmögliche Rk_x/Rk_y in Csparse_%s(). Bitte dem Entwickler melden!" #, c-format #~ msgid "chm_MOD_xtype() was not successful in Csparse_%s(), please report" #~ msgstr "" #~ "chm_MOD_xtype() nicht erfolgreich in Csparse_%s(). Bitte dem Entwickler " #~ "melden!" #, c-format #~ msgid "the number of columns differ in R_rbind2_vector: %d != %d" #~ msgstr "" #~ "die Anzahl der Spalten untescheidet sich in R_rbind2_vector: %d != %d" #~ msgid "csp_eye argument n must be positive" #~ msgstr "csp_eye-Argument n muss positiv sein" #~ msgid "invalid class of 'x' in Matrix_as_cs(a, x)" #~ msgstr "ungültige Klasse von 'x' in Matrix_as_cs(a, x)" #, c-format #~ msgid "invalid class of object to %s" #~ msgstr "ungültige Klasse des Objektes zu %s" #, c-format #~ msgid "cs matrix not compatible with class '%s'" #~ msgstr "cs-Matrix nicht kompatibel mit Klasse '%s'" #, c-format #~ msgid "Inappropriate class cl='%s' in Matrix_css_to_SEXP(S, cl, ..)" #~ msgstr "Unangemessene Klasse cl='%s' in Matrix_css_to_SEXP(S, cl, ..)" #, c-format #~ msgid "Inappropriate class cl='%s' in Matrix_csn_to_SEXP(S, cl, ..)" #~ msgstr "Unangemessene Klasse cl='%s' in Matrix_csn_to_SEXP(S, cl, ..)" #, c-format #~ msgid "Dimensions of x and y are not compatible for %s" #~ msgstr "Dimensionen von x und y sind nicht kompatibel für %s" #~ msgid "Argument y must be numeric, integer or logical" #~ msgstr "Argument y muss numerisch, ganzzahlig oder logisch sein" #~ msgid "Matrices are not conformable for multiplication" #~ msgstr "Matrizen sind nicht für Multiplikation konform" #, c-format #~ msgid "" #~ "dimension mismatch in matrix multiplication of \"dtrMatrix\": %d != %d" #~ msgstr "" #~ "Dimensionen passen nicht in Matrix multiplikation von \"dtrMatrix\": %d !" #~ "= %d" #~ msgid "dtrMatrix must be square" #~ msgstr "dtrMatrix muss quadratisch sein" #, c-format #~ msgid "Dimensions of a (%d,%d) and b (%d,%d) do not conform" #~ msgstr "Dimensionen von a (%d,%d) und b (%d,%d) sind nicht konform" #~ msgid "right=TRUE is not yet implemented __ FIXME" #~ msgstr "right=TRUE ist noch nicht implementiert __ FIXME" #, c-format #~ msgid "cholmod_change_factor failed with status %d" #~ msgstr "cholmod_change_factor mit Status %d fehlgeschlagen" #~ msgid "system argument is not valid" #~ msgstr "Systemargument ist nicht gültig" #, c-format #~ msgid "cholmod_updown() returned %d" #~ msgstr "cholmod_updown() gab Fehlerkode %d zurück" #~ msgid "cholmod_drop() failed" #~ msgstr "cholmod_drop() fehlgeschlagen" #, fuzzy #~ msgid "'off' does not have length 1" #~ msgstr "Slot '%s' muss die Länge 1 haben" #, fuzzy #~ msgid "invalid 'code' to 'R_matrix_as_dense()'" #~ msgstr "ungültige Klasse '%s' für dup_mMatrix_as_dgeMatrix" #, fuzzy #~ msgid "invalid 'uplo' to 'R_matrix_as_dense()'" #~ msgstr "ungültige Klasse '%s' für dup_mMatrix_as_dgeMatrix" #, fuzzy #~ msgid "invalid 'diag' to 'R_matrix_as_dense()'" #~ msgstr "ungültige Klasse '%s' für dup_mMatrix_as_dgeMatrix" #, fuzzy #~ msgid "invalid argument 'system'" #~ msgstr "ungültiges '%s' Argument" #, fuzzy #~ msgid "dimensions of 'qr' and 'y' are inconsistent" #~ msgstr "Dimensionen des Systems sind inkonsistent" #, fuzzy #~ msgid "invalid 'op'" #~ msgstr "ungültiges '%s' Argument" #, fuzzy #~ msgid "'names' must be TRUE or FALSE" #~ msgstr "'uplo' muss UPP oder LOW sein" #~ msgid "Csparse_crossprod(): error return from cholmod_aat()" #~ msgstr "Csparse_crossprod(): Fehler von cholmod_aat() zurückgegeben" #, fuzzy #~ msgid "invalid 'kind' to 'R_sparse_as_kind()'" #~ msgstr "ungültige Klasse von 'x' in Csparse_subassign()" #~ msgid "slot p must have length = nrow(.) + 1" #~ msgstr "Slot p muss Länge = nrow(.) + 1 haben" #~ msgid "last element of slot p must match length of slots j and x" #~ msgstr "" #~ "letztes Element von Slot p muss eine zu den Slots j und x passende Länge " #~ "haben" #~ msgid "all column indices must be between 0 and ncol-1" #~ msgstr "Alle Spaltenindizes müssen zwischen 0 und ncol-1 liegen" #~ msgid "slot j is not *strictly* increasing inside a column" #~ msgstr "Slot j ist nicht *strikt* zunehmend innerhalb einer Spalte" #~ msgid "Csparse_to_nz_pattern(x, tri = NA): 'tri' is taken as TRUE" #~ msgstr "Csparse_to_nz_pattern(x, tri = NA): 'tri' als TRUE angenommen" #~ msgid "not a 'n.CMatrix'" #~ msgstr "keine 'n.CMatrix'" #, c-format #~ msgid "nz2Csparse(): invalid/non-implemented r_kind = %d" #~ msgstr "nz2Csparse(): ungültiges/nicht implementiertes r_kind = %d" #~ msgid "Nonsymmetric matrix in Csparse_symmetric_to_general" #~ msgstr "Asymmetrische Matrix in Csparse_symmetric_to_general" #~ msgid "Csparse_general_to_symmetric(): matrix is not square!" #~ msgstr "Csparse_general_to_symmetric(): Matrix ist nicht quadratisch." #~ msgid "Index i must be NULL or integer" #~ msgstr "Index i muss NULL oder eine ganze Zahl sein" #~ msgid "Index j must be NULL or integer" #~ msgstr "Index j muss NULL oder eine ganze Zahl sein" #, c-format #~ msgid "negative vector lengths not allowed: np = %d, nnz = %d" #~ msgstr "negative Vektorlänge ist nicht erlaubt: np = %d, nnz = %d" #~ msgid "exactly 1 of 'i', 'j' or 'p' must be NULL" #~ msgstr "exakt 1 von 'i', 'j' oder 'p' muss NULL sein" #, c-format #~ msgid "np = %d, must be zero when p is NULL" #~ msgstr "np = %d, muss Null sein, wenn p NULL ist" #, c-format #~ msgid "p[0] = %d, should be zero" #~ msgstr "p[0] = %d, sollte Null sein" #~ msgid "p must be non-decreasing" #~ msgstr "p darf nicht abnehmend sein" #, c-format #~ msgid "Inconsistent dimensions: np = 0 and nnz = %d" #~ msgstr "Inkonsistente Dimensionen: np = 0 und nnz = %d" #, c-format #~ msgid "invalid column index at position %d" #~ msgstr "ungültiger Spaltenindex an Position %d" #, c-format #~ msgid "strlen of cls argument = %d, should be 8" #~ msgstr "strlen des cls-Arguments = %d, sollte 8 sein" #, c-format #~ msgid "cls = \"%s\" does not end in \"CMatrix\"" #~ msgstr "cls = '%s' endet nicht in 'CMatrix'" #, c-format #~ msgid "cls = \"%s\" must begin with 'd', 'l' or 'n'" #~ msgstr "cls = '%s' muss mit 'd', 'l' oder 'n' beginnen" #~ msgid "Only 'g'eneral sparse matrix types allowed" #~ msgstr "Nur 'g'enerelle dünn besetzte Matrixtypen erlaubt" #~ msgid "code not yet written for cls = \"lgCMatrix\"" #~ msgstr "Kode noch nicht für cls = 'lgCMatrix' geschrieben" #, c-format #~ msgid "%s must be (traditional R) matrix" #~ msgstr "%s muss eine traditionelle R Matrix sein" #, c-format #~ msgid "%s must be character string" #~ msgstr "%s muss eine Zeichenkette sein" #, c-format #~ msgid "nrow * ncol = %d * %d must equal length(x) = %ld" #~ msgstr "nrow * ncol = %d * %d muss gleich length(x) = %ld sein" #, c-format #~ msgid "strlen of cls argument = %d, should be 9" #~ msgstr "strlen des cls-Arguments = %d, sollte 9 sein" #, c-format #~ msgid "cls = \"%s\" must begin with 'd', 'l' or 'n' for now" #~ msgstr "cls = \"%s\" muss momentan mit 'd', 'l' oder 'n' beginnen" #, c-format #~ msgid "%s must be a logical or double vector" #~ msgstr "%s muss ein Boole'scher oder 'double' Vector sein" #, c-format #~ msgid "argument type[1]='%s' must be one of 'M','1','O','I','F' or 'E'" #~ msgstr "" #~ "Argument type[1]='%s' muss eins aus 'M', '1', 'O', 'I', 'F' oder 'E' sein" #, c-format #~ msgid "argument type[1]='%s' must be one of '1','O', or 'I'" #~ msgstr "Argument type[1]='%s' eins aus '1', 'O' oder 'I' sein" #~ msgid "object must be a named, numeric vector" #~ msgstr "Objekt muss ein benannter numerischer Vektor sein" #~ msgid "'factors' slot must be a named list" #~ msgstr "'factors'-Slot muss eine benannte Liste sein" #~ msgid "Matrix object has no 'factors' slot" #~ msgstr "Matrix Objekt hat keinen 'factors'-Slot" #~ msgid "'s1' and 's2' must be \"character\" vectors" #~ msgstr "'s1' und 's2' müssen 'character'-Vektoren sein" #~ msgid "length of x slot != prod(Dim)" #~ msgstr "Länge von x-Slot != prod(Dim)" #~ msgid "Negative value in Dim" #~ msgid_plural "Negative values in Dim" #~ msgstr[0] "Negativer Wert in Dim" #~ msgstr[1] "Negative Werte in Dim" #, c-format #~ msgid "%s is a list, but not of length 2" #~ msgstr "%s ist eine Liste, aber Länge ist nicht 2" #, c-format #~ msgid "invalid class '%s' to dup_mMatrix_as_geMatrix" #~ msgstr "ungültige Klasse '%s' für dup_mMatrix_as_geMatrix" #, c-format #~ msgid "unexpected ctype = %d in dup_mMatrix_as_geMatrix" #~ msgstr "unerwartetes ctype = %d in dup_mMatrix_as_geMatrix" #~ msgid "lengths of slots i and j must match" #~ msgstr "Längen der Slots i und j müssen passen" #~ msgid "slot Dim must have length 2" #~ msgstr "Slot Dim muss die Länge 2 haben" #~ msgid "" #~ "all row indices (slot 'i') must be between 0 and nrow-1 in a TsparseMatrix" #~ msgstr "" #~ "alle Zeilenindizes (slot 'i') müssen in TsparseMatrix zwischen 0 und " #~ "nrow-1 liegen" #~ msgid "" #~ "all column indices (slot 'j') must be between 0 and ncol-1 in a " #~ "TsparseMatrix" #~ msgstr "" #~ "Alle Spaltenindizes (slot 'j') müssen in TsparseMatrix zwischen 0 und " #~ "ncol-1 liegen" #~ msgid "Supernodal LDL' decomposition not available" #~ msgstr "Superknoten-LDL'-Zerlegung nicht verfügbar" #~ msgid "Supernodal/simplicial class inconsistent with type flags" #~ msgstr "Superknoten-/simpliziale Klasse inkonstent mit Typkennzeichen" #~ msgid "Number of supernodes must be positive when is_super is TRUE" #~ msgstr "Anzahl der Superknoten muss positiv sein, wenn is_super TRUE ist" #~ msgid "Lengths of super and pi must be equal" #~ msgstr "Längen von super und pi müssen gleich sein" #~ msgid "Lengths of super and px must be equal" #~ msgstr "Längen von super und px müssen gleich sein" #, c-format #~ msgid "First call to Lapack routine dgels returned error code %d" #~ msgstr "Erster Aufruf der Lapack-Routine dgels gab Fehlerkode %d zurück" #, c-format #~ msgid "Second call to Lapack routine dgels returned error code %d" #~ msgstr "Zweiter Aufruf der Lapack-Routine dgels gab Fehlerkode %d zurück" #, c-format #~ msgid "tol, given as %g, must be non-negative" #~ msgstr "tol, als %g gegeben, darf nicht negativ sein" #, c-format #~ msgid "Second call to dgeqrf returned error code %d" #~ msgstr "Zweiter Aufruf von dgeqrf gab Fehlerkode %d zurück" #, c-format #~ msgid "" #~ "dense_to_Csparse(): cholmod_l_dense_to_sparse failure status=%d" #~ msgstr "" #~ "dense_to_Csparse(): cholmod_l_dense_to_sparse Fehlerstatus=%d" #, c-format #~ msgid "" #~ "Matrix dimension %d x %d (= %g) too large [FIXME calling " #~ "cholmod_l_dense_to_sparse]" #~ msgstr "" #~ "Matrix dimension %d x %d (= %g) ist zu groß [FIXME mit " #~ "cholmod_l_dense_to_sparse]" #, c-format #~ msgid "Lower band %d > upper band %d" #~ msgstr "Unteres Band %d > oberes Band %d" #~ msgid "ddense_to_symmetric(): matrix is not square!" #~ msgstr "ddense_to_symmetric(): Matrix ist nicht quadratisch." #, c-format #~ msgid "matrix is not symmetric [%d,%d]" #~ msgstr "Matrix ist nicht symmetrisch [%d,%d]" #~ msgid "matrix is not square! (symmetric part)" #~ msgstr "Matrix ist nicht quadratisch. (symmetrischer Teil)" #~ msgid "matrix is not square! (skew-symmetric part)" #~ msgstr "Matrix ist nicht quadratisch. (schief-symmetrischer Teil)" #~ msgid "lengths of slots 'i' and 'x' must match" #~ msgstr "Längen der Slots 'i' und 'x' müssen übereinstimmen" #~ msgid "lengths of slots 'j' and 'x' must match" #~ msgstr "Längen der Slots 'j' und 'x' müssen übereinstimmen" #, c-format #~ msgid "invalid class(x) '%s' in compressed_to_TMatrix(x)" #~ msgstr "ungültige class(x) '%s' in compressed_to_TMatrix(x)" #, c-format #~ msgid "invalid class(x) '%s' in R_to_CMatrix(x)" #~ msgstr "ungültige class(x) '%s' in R_to_CMatrix(x)" #~ msgid "A must have #{rows} >= #{columns}" #~ msgstr "A muss #{rows} >= #{columns} haben" #~ msgid "cs_sqr failed" #~ msgstr "cs_sqr fehlgeschlagen" #~ msgid "dgcMatrix_QR(*, keep_dimnames = NA): NA taken as TRUE" #~ msgstr "dgcMatrix_QR(*, keep_dimnames = NA): NA taken as TRUE" #~ msgid "LU decomposition applies only to square matrices" #~ msgstr "LU-Zerlegung ist nur bei quadratischen Matrizen anwendbar" #~ msgid "cs_lu(A) failed: near-singular A (or out of memory)" #~ msgstr "" #~ "cs_lu(A) fehlgeschlagen: beinahe singuläres A (oder außerhalb des " #~ "Speichers)" #~ msgid "dgcMatrix_LU(*, keep_dimnames = NA): NA taken as TRUE" #~ msgstr "dgcMatrix_LU(*, keep_dimnames = NA): NA taken as TRUE" #~ msgid "dgCMatrix_matrix_solve(.., sparse=TRUE) not yet implemented" #~ msgstr "dgCMatrix_matrix_solve(.., sparse=TRUE) noch nicht implementiert" #~ msgid "lengths of slots i and x must match" #~ msgstr "Längen der Slots i und x müssen zusammen passen" #, c-format #~ msgid "too large matrix: %.0f" #~ msgstr "Matrix zu groß: %.0f" #, c-format #~ msgid "Cannot coerce to too large *geMatrix with %.0f entries" #~ msgstr "Kann nicht in eine große *geMatrix mit %.0f Einträgen umwandeln" #~ msgid "x slot must be numeric \"double\"" #~ msgstr "x-Slot muss ein numerischer 'double' Wert sein" #~ msgid "factors slot must be named list" #~ msgstr "Faktoren-Slot muss eine benannte Liste sein" #~ msgid "rcond requires a square, non-empty matrix" #~ msgstr "rcond benötigt eine quadratische, nicht leere Matrix" #~ msgid "diagonal to be added has wrong length" #~ msgstr "zu addierende Diagonale hat die falsche Länge" #~ msgid "Cannot factor a matrix with zero extents" #~ msgstr "Eine Matrix mit Umfang Null kann nicht berücksichtigt werden" #, c-format #~ msgid "Exact singularity detected during LU decomposition: %s, i=%d." #~ msgstr "Exakte Singularität während LU-Zerlegung entdeckt: %s, i=%d." #~ msgid "Solve requires a square matrix" #~ msgstr "Auflösen benötigt eine quadratische Matrix" #, c-format #~ msgid "error [%d] from Lapack 'dgecon()'" #~ msgstr "Fehler [%d] von Lapack-'dgecon()'" #, c-format #~ msgid "" #~ "Lapack dgecon(): system computationally singular, reciprocal condition " #~ "number = %g" #~ msgstr "" #~ "Lapack-dgecon(): System rechnerisch singulär, reziproke Konditionszahl = " #~ "%g" #~ msgid "Lapack routine dgetri: system is exactly singular" #~ msgstr "Lapack-Routine dgetri: System ist exakt singulär" #~ msgid "dpoMatrix is not positive definite" #~ msgstr "dpoMatrix ist nicht positiv definit" #~ msgid "Cannot solve() for matrices with zero extents" #~ msgstr "solve() für Matrizen mit Umfang Null nicht möglich" #~ msgid "Argument b must be a numeric matrix" #~ msgstr "Argument b muss eine numerische Matrix sein" #~ msgid "chm_factor_name(): did not get string of length 11" #~ msgstr "chm_factor_name(): habe keine Zeichenkette der Länge 11 bekommen" #~ msgid "" #~ "Cholesky factorization failed; unusually, please report to Matrix-authors" #~ msgstr "" #~ "Cholesky-Faktorisierung fehlgeschlagen; ungewöhnlich, bitte an Matrix-" #~ "authors melden!" #~ msgid "internal_chm_factor: Cholesky factorization failed" #~ msgstr "internal_chm_factor: Cholesky-Faktorisierung fehlgeschlagen" #~ msgid "Non-symmetric matrix passed to dsCMatrix_to_dgTMatrix" #~ msgstr "Nicht symmetrische Matrix an dsCMatrix_to_dgTMatrix übergeben" #~ msgid "Incorrect length of 'x' slot" #~ msgstr "Falsche Länge von 'x'-Slot" #, c-format #~ msgid "Lapack routine dsytrf returned error code %d" #~ msgstr "Lapack-Routine dsytrf gab Fehlerkode %d zurück" #~ msgid "x must be a \"double\" (numeric) matrix" #~ msgstr "X muss eine \"double\" (numerische) Matrix sein" #~ msgid "matrix_trf(x, *): matrix is not square" #~ msgstr "ddense_to_symmetric(): Matrix ist nicht quadratisch" #~ msgid "matrix_trf(*, uplo): uplo must be string" #~ msgstr "" #~ "matrix_trf(*, uplo): uplo muss ein String (character, length(.) == 1) " #~ "sein." #~ msgid "cannot set diag() as long as 'diag = \"U\"'" #~ msgstr "kann diag() nicht setzen solange 'diag = \"U\"'" #~ msgid "cannot add diag() as long as 'diag = \"U\"'" #~ msgstr "kann diag() nicht hinzufügen solange 'diag = \"U\"'" #~ msgid "x slot is not of correct length" #~ msgstr "x-Slot hat nicht die richtige Länge" #~ msgid "A must be a logical matrix" #~ msgstr "A muss eine logische Matrix sein" #~ msgid "length(p) must match nrow(V)" #~ msgstr "length(p) muss zu nrow(V) passen" #~ msgid "length(beta) must match ncol(V)" #~ msgstr "length(beta) muss zu ncol(V) passen" #~ msgid "length(q) must be zero or ncol(R)" #~ msgstr "length(q) muss null oder ncol(R) sein" #, c-format #~ msgid "sparseQR_Qmult(): nrow(y) = %d != %d = nrow(V)" #~ msgstr "sparseQR_Qmult(): nrow(y) = %d != %d = nrow(V)" #, fuzzy #~ msgid "\"dtrMatrix\" objects in '%*%' must have matching (square) dimension" #~ msgstr "" #~ "Dimensionen von \"dtrMatrix\" Objekten in '%*%' müssen passen und " #~ "quadratisch sein" #~ msgid "not a CsparseMatrix" #~ msgstr "keine CsparseMatrix" #~ msgid "slot p must have length = ncol(.) + 1" #~ msgstr "Slot p muss Länge = ncol(.) + 1 haben" #~ msgid "last element of slot p must match length of slots i and x" #~ msgstr "" #~ "letztes Element von Slot p muss eine zu den Slots i und x passende Länge " #~ "haben" #~ msgid "all row indices must be between 0 and nrow-1" #~ msgstr "alle Zeilenindizes müssen zwischen 0 und nrow-1 liegen" #~ msgid "" #~ "slot i is not *strictly* increasing inside a column (even after " #~ "cholmod_l_sort)" #~ msgstr "" #~ "Slot i ist nicht *strikt* zunehmend innerhalb einer Spalte (sogar nach " #~ "cholmod_l_sort)" #~ msgid "row indices are not sorted within columns" #~ msgstr "Zeilenindizes sind nicht innerhalb von Spalten sortiert" #~ msgid "slot i is not *strictly* increasing inside a column" #~ msgstr "Slot i ist nicht *strikt* zunehmend innerhalb einer Spalte" #~ msgid "could not find correct environment; please report!" #~ msgstr "korrekte Umgebung konnte nicht gefunden werden. Bitte berichten!" #~ msgid "previous CHOLMOD factorization was unsuccessful" #~ msgstr "frühere CHOLMOD Faktorisierung war nicht erfolgreich" #~ msgid "Negative value(s) in Dim" #~ msgstr "Negative(r) Wert(e) in Dim" #~ msgid "cs_qrsol failed" #~ msgstr "cs_qrsol fehlgeschlagen" #~ msgid "p[np] = %d != nnz = %d" #~ msgstr "p[np] = %d != nnz = %d" #~ msgid "ncol(V) != ncol(R)" #~ msgstr "ncol(V) != ncol(R)" Matrix/po/fr.po0000644000175100001440000015606314575137654013155 0ustar hornikusers# Translation of Matrix messages to French # Copyright (C) 2001 The R Foundation # This file is distributed under the same license as the Matrix package. # Philippe Grosjean, 2014- msgid "" msgstr "" "Project-Id-Version: Matrix 1.1-1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-14 15:49-0400\n" "PO-Revision-Date: 2021-04-12 18:57+0200\n" "Last-Translator: Philippe Grosjean \n" "Language-Team: none\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Generator: Poedit 2.4.2\n" #: Csparse.c:26 Csparse.c:61 Csparse.c:86 Csparse.c:113 Csparse.c:127 #: Csparse.c:132 Csparse.c:137 Csparse.c:411 #, fuzzy, c-format msgid "'%s' failed" msgstr "cs_qr a échoué" #: Csparse.c:35 cholmod-common.c:54 #, fuzzy, c-format msgid "'%s' slot is not increasing within columns after sorting" msgstr "le slot j ne contient pas de valeurs croissantes au sein d'une colonne" #: Csparse.c:57 #, fuzzy, c-format msgid "'%s' is empty or not square" msgstr "Matrix n'est pas carrée" #: Csparse.c:59 Csparse.c:81 Csparse.c:104 solve.c:43 solve.c:988 #, fuzzy, c-format msgid "dimensions of '%s' and '%s' are inconsistent" msgstr "Les dimensions du système à résoudre sont incohérentes" #: Csparse.c:83 #, c-format msgid "%s(%s, %s) requires m-by-n '%s' with m >= n > 0" msgstr "" #: Csparse.c:106 #, c-format msgid "%s(%s, %s) requires m-by-n '%s' with n >= m > 0" msgstr "" #: Csparse.c:194 coerce.c:220 coerce.c:240 coerce.c:250 coerce.c:905 #: coerce.c:911 coerce.c:1015 coerce.c:1501 coerce.c:1521 coerce.c:1531 #: coerce.c:2061 coerce.c:2256 coerce.c:2262 coerce.c:2268 coerce.c:2397 #: coerce.c:2404 coerce.c:2494 coerce.c:2629 coerce.c:2707 coerce.c:2729 #: coerce.c:4327 coerce.c:4396 dense.c:696 matmult.c:939 matmult.c:1291 #: solve.c:719 solve.c:972 solve.c:1104 sparse.c:1234 sparse.c:1626 #, fuzzy, c-format msgid "invalid '%s' to '%s'" msgstr "argument '%s' incorrect" #: Csparse.c:409 #, fuzzy, c-format msgid "failed to open file \"%s\" for writing" msgstr "erreur lors de l'ouverture en écriture du fichier \"%s\"" #: attrib.c:229 #, fuzzy msgid "invalid factor name" msgstr "argument '%s' incorrect" #: attrib.c:233 #, c-format msgid "attempt to set factor on %s without '%s' slot" msgstr "" #: bind.c:46 bind.c:153 msgid "number of rows of matrices must match" msgstr "" #: bind.c:48 bind.c:155 msgid "number of columns of matrices must match" msgstr "" #: bind.c:51 bind.c:158 bind.c:182 bind.c:206 cholmod-common.c:608 #: cholmod-common.c:759 cholmod-common.c:874 cholmod-common.c:975 #: cholmod-etc.c:183 cholmod-etc.c:283 cholmod-etc.c:330 coerce.c:215 #: coerce.c:235 coerce.c:260 coerce.c:268 coerce.c:276 coerce.c:341 #: coerce.c:1496 coerce.c:1516 coerce.c:1543 coerce.c:1551 coerce.c:1559 #: matmult.c:28 matmult.c:50 matmult.c:56 #, c-format msgid "dimensions cannot exceed %s" msgstr "" #: bind.c:210 msgid "number of rows of result is not a multiple of vector length" msgstr "" #: bind.c:212 msgid "number of columns of result is not a multiple of vector length" msgstr "" #: bind.c:626 bind.c:691 sparse.c:913 sparse.c:994 #, c-format msgid "%s cannot exceed %s" msgstr "" #: bind.c:756 bind.c:853 cholmod-common.c:978 cholmod-etc.c:333 coerce.c:29 #: coerce.c:518 coerce.c:811 coerce.c:945 coerce.c:2772 coerce.c:3041 #: coerce.c:3146 dense.c:919 matmult.c:151 matmult.c:212 matmult.c:291 #: matmult.c:379 matmult.c:456 matmult.c:550 matmult.c:868 subscript.c:1232 #: subscript.c:1417 utils-R.c:32 #, c-format msgid "attempt to allocate vector of length exceeding %s" msgstr "" #: bind.c:858 matmult.c:1357 msgid "should never happen ..." msgstr "" #: cholmod-common.c:11 cholmod-common.c:34 validity.c:29 validity.c:150 #: validity.c:229 validity.c:248 validity.c:257 validity.c:299 validity.c:316 #: validity.c:350 validity.c:367 validity.c:401 validity.c:403 validity.c:439 #: validity.c:465 validity.c:485 validity.c:926 validity.c:959 validity.c:1041 #: validity.c:1061 validity.c:1127 validity.c:1129 validity.c:1177 #: validity.c:1240 validity.c:1242 validity.c:1288 validity.c:1335 #: validity.c:1384 validity.c:1417 validity.c:1427 validity.c:1440 #: validity.c:1494 validity.c:1496 validity.c:1528 validity.c:1540 #: validity.c:1563 validity.c:1626 validity.c:1645 validity.c:1647 #: validity.c:1679 validity.c:1714 validity.c:1742 #, fuzzy, c-format msgid "'%s' slot is not of type \"%s\"" msgstr "Le slot Dim n’est pas un entier" #: cholmod-common.c:14 validity.c:274 validity.c:285 validity.c:301 #: validity.c:352 validity.c:487 validity.c:928 validity.c:961 validity.c:1063 #: validity.c:1131 validity.c:1179 validity.c:1244 validity.c:1290 #: validity.c:1429 validity.c:1446 validity.c:1498 validity.c:1500 #: validity.c:1530 validity.c:1542 validity.c:1565 validity.c:1681 #: validity.c:1718 validity.c:1746 validity.c:1796 #, fuzzy, c-format msgid "'%s' slot does not have length %s" msgstr "Le slot Dim doit avoir une longueur de 2" #: cholmod-common.c:18 validity.c:304 validity.c:355 validity.c:1634 #: validity.c:1654 validity.c:1656 #, fuzzy, c-format msgid "first element of '%s' slot is not 0" msgstr "le premier élément du slot p doit être à zéro" #: cholmod-common.c:23 cholmod-common.c:46 validity.c:34 validity.c:308 #: validity.c:326 validity.c:359 validity.c:377 validity.c:413 validity.c:415 #: validity.c:491 validity.c:1008 validity.c:1020 validity.c:1067 #: validity.c:1140 validity.c:1152 validity.c:1253 validity.c:1265 #: validity.c:1294 validity.c:1345 validity.c:1394 validity.c:1433 #: validity.c:1453 validity.c:1534 validity.c:1550 validity.c:1575 #: validity.c:1639 validity.c:1659 validity.c:1661 validity.c:1688 #, c-format msgid "'%s' slot contains NA" msgstr "" #: cholmod-common.c:26 validity.c:310 validity.c:361 #, fuzzy, c-format msgid "'%s' slot is not nondecreasing" msgstr "le slot p ne peut contenir de valeurs décroissantes" #: cholmod-common.c:29 validity.c:312 validity.c:363 #, c-format msgid "first differences of '%s' slot exceed %s" msgstr "" #: cholmod-common.c:37 validity.c:318 validity.c:369 #, fuzzy, c-format msgid "'%s' slot has length less than %s" msgstr "le slot 'Dim' a une longueur inférieure à deux" #: cholmod-common.c:49 validity.c:328 validity.c:379 validity.c:417 #: validity.c:420 validity.c:493 validity.c:1010 validity.c:1069 #: validity.c:1142 validity.c:1154 validity.c:1255 validity.c:1267 #: validity.c:1347 validity.c:1396 validity.c:1455 validity.c:1577 #: validity.c:1690 #, fuzzy, c-format msgid "'%s' slot has elements not in {%s}" msgstr "le slot 'Dim' a une longueur inférieure à deux" #: cholmod-common.c:165 cholmod-common.c:296 cholmod-common.c:1072 #: cholmod-common.c:1075 cholmod-common.c:1108 cholmod-common.c:1126 #, fuzzy, c-format msgid "'%s' failed in '%s'" msgstr "cs_qr a échoué" #: cholmod-common.c:212 #, fuzzy, c-format msgid "'%s' failed in '%s': %s" msgstr "cs_qr a échoué" #: cholmod-common.c:601 cholmod-common.c:604 cholmod-common.c:606 #: cholmod-common.c:752 cholmod-common.c:755 cholmod-common.c:757 #: cholmod-common.c:867 cholmod-common.c:870 cholmod-common.c:872 #: cholmod-common.c:969 cholmod-common.c:971 cholmod-etc.c:177 #: cholmod-etc.c:179 cholmod-etc.c:181 cholmod-etc.c:277 cholmod-etc.c:279 #: cholmod-etc.c:281 cholmod-etc.c:324 cholmod-etc.c:326 cs-etc.c:43 #, c-format msgid "wrong '%s'" msgstr "" #: cholmod-common.c:611 cholmod-etc.c:186 #, fuzzy, c-format msgid "'%s' would overflow type \"%s\"" msgstr "Le slot Dim n’est pas un entier" #: cholmod-common.c:615 cholmod-etc.c:190 #, c-format msgid "n+1 would overflow type \"%s\"" msgstr "" #: cholmod-common.c:620 cholmod-etc.c:195 #, fuzzy, c-format msgid "leading principal minor of order %d is not positive" msgstr "le 'leading minor of order' %d n'est pas un entier fini" #: cholmod-common.c:623 cholmod-etc.c:198 #, fuzzy, c-format msgid "leading principal minor of order %d is zero" msgstr "le 'leading minor of order' %d n'est pas un entier fini" #: cholmod-common.c:973 cholmod-etc.c:328 msgid "leading dimension not equal to number of rows" msgstr "" #: cholmod-common.c:1037 #, c-format msgid "" "invalid simplicial Cholesky factorization: structural zero on main diagonal " "in column %d" msgstr "" #: cholmod-common.c:1097 #, fuzzy, c-format msgid "CHOLMOD error '%s' at file '%s', line %d" msgstr "Erreur Cholmod '%s' dans le fichier %s, ligne %d" #: cholmod-common.c:1100 #, fuzzy, c-format msgid "CHOLMOD warning '%s' at file '%s', line %d" msgstr "Avertissement Cholmod '%s' dans le fichier %s, ligne %d" #: coerce.c:24 coerce.c:364 coerce.c:1050 #, fuzzy, c-format msgid "attempt to construct non-square %s" msgstr "Determinant nécessite une matrice carrée" #: coerce.c:186 coerce.c:476 coerce.c:1467 coerce.c:1622 #, c-format msgid "second argument of '%s' does not specify a subclass of %s" msgstr "" #: coerce.c:194 coerce.c:200 coerce.c:484 coerce.c:490 coerce.c:925 #: coerce.c:1475 coerce.c:1481 coerce.c:1630 coerce.c:1636 coerce.c:2275 #: coerce.c:3344 coerce.c:3349 #, fuzzy, c-format msgid "'%s' must be \"%s\" or \"%s\"" msgstr "'%s' doit être compris dans '%s'" #: coerce.c:246 coerce.c:496 coerce.c:793 coerce.c:917 coerce.c:1527 #: coerce.c:1642 dense.c:322 dense.c:1102 dense.c:1678 dense.c:1683 #: dense.c:1929 dense.c:2124 sparse.c:784 sparse.c:2449 sparse.c:3141 #: sparse.c:3146 sparse.c:3151 sparse.c:3427 sparse.c:3664 #, fuzzy, c-format msgid "'%s' must be %s or %s" msgstr "'%s' doit être compris dans '%s'" #: coerce.c:266 coerce.c:274 coerce.c:285 coerce.c:1549 coerce.c:1557 #: coerce.c:1568 msgid "nonempty vector supplied for empty matrix" msgstr "" #: coerce.c:287 coerce.c:1570 #, c-format msgid "vector length (%lld) exceeds matrix length (%d * %d)" msgstr "" #: coerce.c:290 coerce.c:1573 #, c-format msgid "matrix length (%d * %d) is not a multiple of vector length (%lld)" msgstr "" #: coerce.c:521 #, c-format msgid "coercing n-by-n %s to %s is not supported for n*n exceeding %s" msgstr "" #: coerce.c:525 coerce.c:815 coerce.c:949 #, c-format msgid "sparse->dense coercion: allocating vector of size %0.1f GiB" msgstr "" #: coerce.c:1196 coerce.c:1941 coerce.c:2948 coerce.c:2954 #, c-format msgid "attempt to construct %s with more than %s nonzero entries" msgstr "" #: coerce.c:3246 #, fuzzy msgid "attempt to pack non-square matrix" msgstr "Determinant nécessite une matrice carrée" #: coerce.c:3420 coerce.c:3590 #, c-format msgid "unable to aggregate %s with '%s' and '%s' slots of length exceeding %s" msgstr "" #: coerce.c:4211 #, fuzzy, c-format msgid "attempt to pack a %s" msgstr "Determinant nécessite une matrice carrée" #: coerce.c:4330 dense.c:1232 sparse.c:2580 #, fuzzy, c-format msgid "'%s' must be %s or %s or %s" msgstr "'%s' doit être compris dans '%s'" #: dense.c:210 dense.c:215 sparse.c:590 sparse.c:595 #, fuzzy, c-format msgid "'%s' (%d) must be an integer from %s (%d) to %s (%d)" msgstr "'%s' doit être compris dans '%s'" #: dense.c:218 sparse.c:598 #, fuzzy, c-format msgid "'%s' (%d) must be less than or equal to '%s' (%d)" msgstr "'%s' doit être compris dans '%s'" #: dense.c:428 sparse.c:1070 #, fuzzy, c-format msgid "replacement diagonal has incompatible type \"%s\"" msgstr "la diagonale de remplacement a une longueur incorrecte" #: dense.c:437 sparse.c:1079 msgid "replacement diagonal has wrong length" msgstr "la diagonale de remplacement a une longueur incorrecte" #: dense.c:622 sparse.c:1275 #, fuzzy msgid "attempt to symmetrize a non-square matrix" msgstr "Determinant nécessite une matrice carrée" #: dense.c:721 sparse.c:1653 msgid "attempt to get symmetric part of non-square matrix" msgstr "" #: dense.c:873 sparse.c:2083 msgid "attempt to get skew-symmetric part of non-square matrix" msgstr "" #: dense.c:1673 sparse.c:3136 #, fuzzy, c-format msgid "'%s' must be %d or %d" msgstr "'%s' doit être compris dans '%s'" #: dense.c:2156 #, c-format msgid "incorrect left cyclic shift, j (%d) < 0" msgstr "décalage cyclique à gauche incorrect, j (%d) < 0" #: dense.c:2159 #, c-format msgid "incorrect left cyclic shift, j (%d) >= k (%d)" msgstr "décalage cyclique à gauche incorrect, j (%d) >= k (%d)" #: dense.c:2162 #, c-format msgid "incorrect left cyclic shift, k (%d) > ldx (%d)" msgstr "décalage cyclique à gauche incorrect, k (%d) > ldx (%d)" #: dense.c:2215 #, fuzzy msgid "unknown error in getGivens" msgstr "Erreur inconnue dans getGivens" #: dense.c:2224 dense.c:2238 dense.c:2268 msgid "X must be a numeric (double precision) matrix" msgstr "X doit être une matrice numérique (double précision)" #: dense.c:2240 dense.c:2270 msgid "y must be a numeric (double precision) matrix" msgstr "y doit être une matrice numérique (double précision)" #: dense.c:2244 dense.c:2274 #, c-format msgid "number of rows in y (%d) does not match number of rows in X (%d)" msgstr "" "le nombre de lignes de y (%d) ne correspond pas au nombre de lignes de X (%d)" #: dense.c:2260 #, fuzzy, c-format msgid "LAPACK dposv returned error code %d" msgstr "La routine Lapack dposv a renvoyé le code d'erreur %d" #: dense.c:2288 dense.c:2294 #, fuzzy, c-format msgid "LAPACK dgels returned error code %d" msgstr "La routine Lapack %s a renvoyé le code d'erreur %d" #: dense.c:2313 msgid "X must be a real (numeric) matrix" msgstr "X doit être une matrice (numérique) de réels" #: dense.c:2316 #, fuzzy, c-format msgid "tol, given as %g, must be >= 0" msgstr "tol, donné comme %g, doit être <= 1" #: dense.c:2318 #, c-format msgid "tol, given as %g, must be <= 1" msgstr "tol, donné comme %g, doit être <= 1" #: dense.c:2347 dense.c:2355 #, fuzzy, c-format msgid "LAPACK dgeqrf returned error code %d" msgstr "Le premier appel à dgeqrf a renvoyé le code d'erreur %d" #: dense.c:2360 dense.c:2383 #, fuzzy, c-format msgid "LAPACK dtrcon returned error code %d" msgstr "La routine Lapack dtrcon a renvoyé le code d'erreur %d" #: determinant.c:33 #, fuzzy msgid "determinant of non-square matrix is undefined" msgstr "Determinant nécessite une matrice carrée" #: determinant.c:276 #, fuzzy, c-format msgid "%s(<%s>) does not support structurally rank deficient case" msgstr "" "%s() : cas structurellement déficient de rang : probablement des zéros " "ERRONES" #: expm.c:39 msgid "Matrix exponential requires square, non-null matrix" msgstr "L'exponentiation de matrice nécessite une matrice carrée non nulle" #: expm.c:56 expm.c:58 #, c-format msgid "dgeMatrix_exp: LAPACK routine dgebal returned %d" msgstr "dgeMatrix_exp : la routine LAPACK dgebal a renvoyé %d" #: expm.c:96 #, c-format msgid "dgeMatrix_exp: dgetrf returned error code %d" msgstr "dgeMatrix_exp : dgetrf a renvoyé le code d'erreur %d" #: expm.c:98 #, c-format msgid "dgeMatrix_exp: dgetrs returned error code %d" msgstr "dgeMatrix_exp : dgetrs a renvoyé le code d'erreur %d" #: factor.c:330 msgid "dgeMatrix_Schur: argument x must be a non-null square matrix" msgstr "dgeMatrix_Schur : l'argument x doit être une matrice carrée non nulle" #: factor.c:343 msgid "dgeMatrix_Schur: first call to dgees failed" msgstr "dgeMatrix_Schur : le premier appel à dgees a échoué" #: factor.c:352 #, c-format msgid "dgeMatrix_Schur: dgees returned code %d" msgstr "dgeMatrix_Schur : dgees a renvoyé le code d'erreur %d" #: factor.c:403 sparse.c:196 #, fuzzy, c-format msgid "'%s' is not a number" msgstr "%s n’est pas une liste" #: factor.c:424 #, c-format msgid "LU factorization of m-by-n %s requires m == n" msgstr "" #: factor.c:433 #, c-format msgid "LU factorization of %s failed: out of memory or near-singular" msgstr "" #: factor.c:510 #, c-format msgid "QR factorization of m-by-n %s requires m >= n" msgstr "" #: factor.c:519 #, c-format msgid "QR factorization of %s failed: out of memory" msgstr "" #: factor.c:619 factor.c:897 #, c-format msgid "'%s' is not a number or not finite" msgstr "" #: idz.c:467 idz.c:528 #, c-format msgid "incompatible '%s' and '%s' in '%s'" msgstr "" #: kappa.c:10 kappa.c:54 #, fuzzy, c-format msgid "argument '%s' is not of type \"%s\"" msgstr "" "l'argument type[1]='%s' doit être une chaîne de caractères à une seule lettre" #: kappa.c:13 kappa.c:57 #, fuzzy, c-format msgid "argument '%s' has length %d" msgstr "'%s' doit avoir une longueur de chaîne de caractères de 1" #: kappa.c:17 kappa.c:61 #, fuzzy, c-format msgid "argument '%s' (\"%s\") does not have string length %d" msgstr "'%s' doit avoir une longueur de chaîne de caractères de 1" #: kappa.c:41 #, c-format msgid "" "argument '%s' (\"%s\") is not \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", or " "\"%s\"" msgstr "" #: kappa.c:75 #, fuzzy, c-format msgid "argument '%s' (\"%s\") is not \"%s\", \"%s\", or \"%s\"" msgstr "'%s' doit avoir une longueur de chaîne de caractères de 1" #: kappa.c:238 #, c-format msgid "%s(%s) is undefined: '%s' is not square" msgstr "" #: matmult.c:107 matmult.c:210 matmult.c:289 matmult.c:377 matmult.c:454 #: matmult.c:548 matmult.c:812 matmult.c:862 msgid "non-conformable arguments" msgstr "" #: matmult.c:782 matmult.c:810 #, c-format msgid "'%s' does not support complex matrices" msgstr "" #: objects.c:23 #, c-format msgid "unexpected type \"%s\" in '%s'" msgstr "" #: objects.c:41 objects.c:58 #, c-format msgid "unexpected kind \"%c\" in '%s'" msgstr "" #: perm.c:26 perm.c:106 msgid "attempt to get sign of non-permutation" msgstr "" #: perm.c:51 perm.c:123 msgid "attempt to invert non-permutation" msgstr "" #: perm.c:66 #, fuzzy msgid "invalid transposition vector" msgstr "indices de lignes erronés à la position %d" #: perm.c:79 perm.c:81 perm.c:96 perm.c:98 perm.c:113 perm.c:133 perm.c:145 #, fuzzy, c-format msgid "'%s' is not of type \"%s\"" msgstr "Le slot Dim n’est pas un entier" #: perm.c:83 perm.c:100 perm.c:147 #, fuzzy, c-format msgid "'%s' does not have length %d" msgstr "le slot '%s' doit avoir une longueur de 1" #: perm.c:86 perm.c:103 #, c-format msgid "'%s' is NA" msgstr "" #: perm.c:115 perm.c:138 #, fuzzy, c-format msgid "'%s' or '%s' is not of type \"%s\"" msgstr "Le slot Dim n’est pas un entier" #: perm.c:117 perm.c:140 #, fuzzy, c-format msgid "'%s' or '%s' does not have length %d" msgstr "le slot '%s' doit avoir une longueur de 1" #: perm.c:120 perm.c:143 #, c-format msgid "'%s' or '%s' is NA" msgstr "" #: perm.c:136 #, c-format msgid "'%s' has length exceeding %s" msgstr "" #: perm.c:150 #, c-format msgid "'%s' is NA or less than %s" msgstr "" #: solve.c:38 #, fuzzy, c-format msgid "'%s' is not square" msgstr "Matrix n'est pas carrée" #: solve.c:497 #, c-format msgid "%s(<%s>, <%s>) failed: out of memory" msgstr "" #: solve.c:618 #, fuzzy, c-format msgid "attempt to construct %s with more than %s nonzero elements" msgstr "Determinant nécessite une matrice carrée" #: subscript.c:1542 subscript.c:1695 subscript.c:1938 subscript.c:2122 #, c-format msgid "%s too dense for %s; would have more than %s nonzero entries" msgstr "" #: subscript.c:2209 #, c-format msgid "NA subscripts in %s not supported for '%s' inheriting from %s" msgstr "" #: t_subassign.c:141 msgid "invalid class of 'x' in Csparse_subassign()" msgstr "classe de 'x' incorrecte dans Csparse_subassign()" #: t_subassign.c:143 msgid "invalid class of 'value' in Csparse_subassign()" msgstr "classe de 'value' incorrecte dans Csparse_subassign()" #: t_subassign.c:186 #, c-format msgid "x[] <- val: val is coerced to logical for \"%s\" x" msgstr "" "x[] <- val: val est converti automatiquement en valeurs logiques pour \"%s\" " "x" #: t_subassign.c:191 #, c-format msgid "" "x[] <- val: val should be integer or logical, is coerced to integer, for " "\"%s\" x" msgstr "" "x[] <- val: val devrait être des entiers ou des valeurs booléennes, il est " "converti automatiquement en entiers pour \"%s\" x" #: t_subassign.c:198 msgid "programming error in Csparse_subassign() should never happen" msgstr "" "erreur de programmation dans Csparse_subassign() qui ne devrait jamais se " "produire" #: utils-R.c:30 utils-R.c:116 #, c-format msgid "indices would exceed %s" msgstr "" #: utils-R.c:235 utils-R.c:270 utils-R.c:281 utils-R.c:312 msgid "Argument must be numeric-like atomic vector" msgstr "" "L'argument doit être un vecteur atomique de type numérique ou convertible en " "nombres" #: utils-R.c:345 msgid "'data' must be of a vector type" msgstr "'data' doit être de type vecteur" #: utils-R.c:352 #, c-format msgid "invalid '%s' argument" msgstr "argument '%s' incorrect" #: utils-R.c:359 utils-R.c:367 msgid "non-numeric matrix extent" msgstr "étendue de matrice non numérique" #: utils-R.c:362 msgid "invalid 'nrow' value (too large or NA)" msgstr "valeur 'nrow' incorrecte (trop large ou NA)" #: utils-R.c:364 msgid "invalid 'nrow' value (< 0)" msgstr "valeur 'nrow' incorrecte (< 0)" #: utils-R.c:370 msgid "invalid 'ncol' value (too large or NA)" msgstr "valeur 'ncol' incorrecte (trop large ou NA)" #: utils-R.c:372 msgid "invalid 'ncol' value (< 0)" msgstr "valeur 'ncol' incorrecte (< 0)" #: utils-R.c:390 #, fuzzy, c-format msgid "" "data length [%lld] is not a sub-multiple or multiple of the number of rows " "[%d]" msgstr "" "la longueur des données [%d] n'est pas un sous-multiple ni un multiple du " "nombre de lignes [%d]" #: utils-R.c:395 #, fuzzy, c-format msgid "" "data length [%lld] is not a sub-multiple or multiple of the number of " "columns [%d]" msgstr "" "la longueur des données [%d] n'est pas un sous-multiple ni un multiple du " "nombre de colonnes [%d]" #: utils-R.c:399 msgid "data length exceeds size of matrix" msgstr "la longueur des données excède la taille de la matrice" #: utils-R.c:404 msgid "too many elements specified" msgstr "trop d'éléments sont spécifiés" #: utils-R.c:545 msgid "Argument ij must be 2-column integer matrix" msgstr "L'argument ij doit être une matrice d'entiers à 2 colonnes" #: utils-R.c:570 msgid "subscript 'i' out of bounds in M[ij]" msgstr "indice 'i' hors plage dans M[ij]" #: utils-R.c:572 msgid "subscript 'j' out of bounds in M[ij]" msgstr "indice 'j' hors plage dans M[ij]" #: utils-R.c:626 msgid "i and j must be integer vectors of the same length" msgstr "i et j doivent être des vecteurs d'entiers de même longueur" #: validity.c:31 validity.c:52 validity.c:231 validity.c:250 validity.c:259 #: validity.c:441 validity.c:467 validity.c:977 validity.c:1419 validity.c:1443 #, fuzzy, c-format msgid "'%s' slot does not have length %d" msgstr "Le slot Dim doit avoir une longueur de 2" #: validity.c:36 validity.c:932 validity.c:965 #, fuzzy, c-format msgid "'%s' slot has negative elements" msgstr "le slot 'Dim' a une longueur inférieure à deux" #: validity.c:50 validity.c:164 #, fuzzy, c-format msgid "'%s' slot is not a list" msgstr "Le slot Dim n’est pas un entier" #: validity.c:68 #, fuzzy, c-format msgid "%s[[%d]] is not NULL or a vector" msgstr "Dimnames[%d] n’est pas un vecteur de chaînes de caractères" #: validity.c:71 #, fuzzy, c-format msgid "length of %s[[%d]] (%lld) is not equal to %s[%d] (%d)" msgstr "length(Dimnames[%d]) diffère de Dim[%d] qui est %d" #: validity.c:170 #, c-format msgid "'%s' slot has no '%s' attribute" msgstr "" #: validity.c:181 validity.c:244 validity.c:435 validity.c:506 validity.c:1082 #: validity.c:1413 validity.c:1774 #, c-format msgid "%s[1] != %s[2] (matrix is not square)" msgstr "" #: validity.c:206 validity.c:219 #, c-format msgid "%s[1] differs from %s[2]" msgstr "" #: validity.c:234 validity.c:253 validity.c:262 validity.c:444 #, fuzzy, c-format msgid "'%s' slot is not \"%s\" or \"%s\"" msgstr "le slot x n’est pas un nombre \"double\"" #: validity.c:331 validity.c:1580 #, fuzzy, c-format msgid "'%s' slot is not increasing within columns" msgstr "le slot j ne contient pas de valeurs croissantes au sein d'une colonne" #: validity.c:382 #, fuzzy, c-format msgid "'%s' slot is not increasing within rows" msgstr "le slot j ne contient pas de valeurs croissantes au sein d'une colonne" #: validity.c:406 validity.c:790 validity.c:816 validity.c:842 validity.c:1043 #: validity.c:1649 validity.c:1651 #, fuzzy, c-format msgid "'%s' and '%s' slots do not have equal length" msgstr "Le slot Dim doit avoir une longueur de 2" #: validity.c:409 #, c-format msgid "'%s' slot has nonzero length but %s is 0" msgstr "" #: validity.c:450 validity.c:454 #, fuzzy, c-format msgid "'%s' slot is \"%s\" but '%s' slot does not have length %s" msgstr "Le slot Dim doit avoir une longueur de 2" #: validity.c:470 #, fuzzy, c-format msgid "'%s' slot is not %d or %d" msgstr "le slot x n’est pas un nombre \"double\"" #: validity.c:476 validity.c:479 #, c-format msgid "%s-by-%s %s invalid for positive '%s' when %s=%d" msgstr "" #: validity.c:516 validity.c:1145 validity.c:1157 validity.c:1258 #: validity.c:1270 validity.c:1350 validity.c:1399 validity.c:1458 #, c-format msgid "'%s' slot contains duplicates" msgstr "" #: validity.c:544 validity.c:589 validity.c:635 validity.c:680 validity.c:724 #: validity.c:759 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries below the diagonal" msgstr "uplo='U' ne peut avoir des entrées éparses en dessous de la diagonale" #: validity.c:554 validity.c:602 validity.c:645 validity.c:693 validity.c:729 #: validity.c:770 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries above the diagonal" msgstr "uplo='L' ne peut avoir des entrées éparses au dessus de la diagonale" #: validity.c:592 validity.c:605 validity.c:683 validity.c:696 validity.c:762 #: validity.c:773 #, fuzzy, c-format msgid "%s=\"%s\" but there are entries on the diagonal" msgstr "uplo='U' ne peut avoir des entrées éparses en dessous de la diagonale" #: validity.c:878 validity.c:902 validity.c:906 msgid "matrix has negative diagonal elements" msgstr "" #: validity.c:922 validity.c:950 validity.c:954 msgid "matrix has nonunit diagonal elements" msgstr "" #: validity.c:974 validity.c:999 validity.c:1793 #, fuzzy, c-format msgid "'%s' slot is not of type \"%s\" or \"%s\"" msgstr "Le slot Dim n’est pas un entier" #: validity.c:982 validity.c:989 #, fuzzy, c-format msgid "'%s' slot is NA" msgstr "Le slot Dim n’est pas un entier" #: validity.c:984 validity.c:991 #, fuzzy, c-format msgid "'%s' slot is negative" msgstr "le slot 'Dim' a une longueur inférieure à deux" #: validity.c:993 #, fuzzy, c-format msgid "'%s' slot exceeds %s" msgstr "'%s' doit être compris dans '%s'" #: validity.c:1003 #, fuzzy, c-format msgid "'%s' slot has length greater than '%s' slot" msgstr "le slot 'Dim' a une longueur inférieure à deux" #: validity.c:1013 validity.c:1641 validity.c:1663 validity.c:1665 #, fuzzy, c-format msgid "'%s' slot is not increasing" msgstr "le slot j ne contient pas de valeurs croissantes au sein d'une colonne" #: validity.c:1023 #, fuzzy, c-format msgid "'%s' slot has elements not in {%s} after truncation towards zero" msgstr "le slot 'Dim' a une longueur inférieure à deux" #: validity.c:1026 #, fuzzy, c-format msgid "'%s' slot is not increasing after truncation towards zero" msgstr "le slot j ne contient pas de valeurs croissantes au sein d'une colonne" #: validity.c:1092 validity.c:1119 validity.c:1781 validity.c:1788 #, fuzzy, c-format msgid "dimensions of '%s' slot are not identical to '%s'" msgstr "Les dimensions de x et y ne sont pas compatibles pour %s" #: validity.c:1094 #, c-format msgid "'%s' slot is upper (not lower) triangular" msgstr "" #: validity.c:1107 #, c-format msgid "'%s' slot has nonunit diagonal elements" msgstr "" #: validity.c:1121 #, c-format msgid "'%s' slot is lower (not upper) triangular" msgstr "" #: validity.c:1133 validity.c:1246 validity.c:1337 validity.c:1386 #, fuzzy, c-format msgid "'%s' slot does not have length %s or length %s" msgstr "Le slot Dim doit avoir une longueur de 2" #: validity.c:1173 msgid "matrix has more columns than rows" msgstr "" #: validity.c:1193 #, fuzzy, c-format msgid "'%s' slot has fewer than %s rows" msgstr "le slot 'Dim' a une longueur inférieure à deux" #: validity.c:1195 #, fuzzy, c-format msgid "'%s' slot has more than %s rows" msgstr "le slot 'Dim' a une longueur inférieure à deux" #: validity.c:1197 validity.c:1219 #, fuzzy, c-format msgid "'%s' slot does not have %s columns" msgstr "Le slot Dim doit avoir une longueur de 2" #: validity.c:1204 #, fuzzy, c-format msgid "'%s' slot must be lower trapezoidal but has entries above the diagonal" msgstr "uplo='L' ne peut avoir des entrées éparses au dessus de la diagonale" #: validity.c:1217 #, fuzzy, c-format msgid "'%s' slot does not have %s row" msgstr "Le slot Dim doit avoir une longueur de 2" #: validity.c:1226 #, fuzzy, c-format msgid "'%s' slot must be upper trapezoidal but has entries below the diagonal" msgstr "uplo='U' ne peut avoir des entrées éparses en dessous de la diagonale" #: validity.c:1230 #, c-format msgid "'%s' slot has negative diagonal elements" msgstr "" #: validity.c:1296 #, c-format msgid "'%s' slot has elements not in {%s}\\{%s}" msgstr "" #: validity.c:1305 #, c-format msgid "'%s' slot has unpaired negative elements" msgstr "" #: validity.c:1331 validity.c:1375 validity.c:1379 validity.c:1727 #: validity.c:1759 msgid "Cholesky factor has negative diagonal elements" msgstr "" #: validity.c:1422 #, fuzzy, c-format msgid "%s[%d] (%s) is not in %s" msgstr "%s n’est pas une liste" #: validity.c:1435 validity.c:1536 #, fuzzy, c-format msgid "%s is not in {%s}" msgstr "%s n’est pas une liste" #: validity.c:1472 #, c-format msgid "%s is not representable as \"%s\"" msgstr "" #: validity.c:1477 validity.c:1483 #, c-format msgid "%s[%d] (%s) is not %d or %d" msgstr "" #: validity.c:1480 validity.c:1596 validity.c:1599 validity.c:1602 #, c-format msgid "%s[%d] (%s) is not %d" msgstr "" #: validity.c:1505 #, c-format msgid "%s has elements not in {%s}" msgstr "" #: validity.c:1508 #, c-format msgid "%s has elements not in {%s}\\{%s}" msgstr "" #: validity.c:1511 #, c-format msgid "%s is %d but columns are not stored in increasing order" msgstr "" #: validity.c:1514 validity.c:1517 #, c-format msgid "traversal of '%s' slot does not complete in exactly %s steps" msgstr "" #: validity.c:1523 validity.c:1525 #, fuzzy, c-format msgid "%s is not %d" msgstr "%s n’est pas une liste" #: validity.c:1546 #, c-format msgid "column '%s' is stored first but %s is not 0" msgstr "" #: validity.c:1552 #, fuzzy, c-format msgid "'%s' slot is not increasing when traversed in stored column order" msgstr "le slot j ne contient pas de valeurs croissantes au sein d'une colonne" #: validity.c:1554 #, c-format msgid "'%s' slot allocates fewer than %s elements for column '%s'" msgstr "" #: validity.c:1557 #, c-format msgid "'%s' slot allocates more than %s elements for column '%s'" msgstr "" #: validity.c:1571 #, c-format msgid "first entry in column '%s' does not have row index '%s'" msgstr "" #: validity.c:1605 validity.c:1608 #, c-format msgid "%s[%d] (%s) is negative" msgstr "" #: validity.c:1611 #, c-format msgid "%s[%d] (%s) is not less than %s" msgstr "" #: validity.c:1629 #, fuzzy, c-format msgid "'%s' slot has length less than %d" msgstr "le slot 'Dim' a une longueur inférieure à deux" #: validity.c:1631 #, fuzzy, c-format msgid "'%s' slot has length greater than %s" msgstr "le slot 'Dim' a une longueur inférieure à deux" #: validity.c:1636 #, fuzzy, c-format msgid "last element of '%s' slot is not %s" msgstr "le premier élément du slot p doit être à zéro" #: validity.c:1669 #, c-format msgid "first differences of '%s' slot are less than those of '%s' slot" msgstr "" #: validity.c:1672 #, c-format msgid "supernode lengths exceed %s" msgstr "" #: validity.c:1674 #, c-format msgid "first differences of '%s' slot are not equal to supernode lengths" msgstr "" #: validity.c:1694 #, c-format msgid "" "'%s' slot is wrong within diagonal blocks (row and column indices do not " "coincide)" msgstr "" #: validity.c:1697 #, fuzzy, c-format msgid "'%s' slot is not increasing within supernodes" msgstr "le slot j ne contient pas de valeurs croissantes au sein d'une colonne" #: validity.c:1812 #, fuzzy, c-format msgid "invalid class \"%s\" object: %s" msgstr "classe incorrecte d'objet à %s" #: vector.c:90 #, c-format msgid "%s length cannot exceed %s" msgstr "" #, fuzzy, c-format #~ msgid "dgeMatrix_svd(x,*): dim(x)[j] = %d is too large" #~ msgstr "La dimension de l’objet Matrix %d x %d (= %g) est trop large" #, c-format #~ msgid "diagonal element %d of Cholesky factor is missing" #~ msgstr "" #~ "l'élément de diagonale %d de la factorisation de Cholesky est manquant" #, c-format #~ msgid "cholmod_factorize_p failed: status %d, minor %d of ncol %d" #~ msgstr "cholmod_factorize_p a échoué : statut %d, mineur %d de ncol %d" #~ msgid "cholmod_change_factor failed" #~ msgstr "cholmod_change_factor a échoué" #~ msgid "cholmod_write_sparse returned error code" #~ msgstr "cholmod_write_sparse a renvoyé le code d'erreur" #, c-format #~ msgid "%s = '%s' (back-permuted) is experimental" #~ msgstr "%s = '%s' (back-permuted) est expérimental" #~ msgid "diag_tC(): invalid 'resultKind'" #~ msgstr "diag_tC() : 'resultKind' incorrect" #, fuzzy #~ msgid "complex matrices are not yet supported" #~ msgstr "le code n'est pas encore écrit pour les matrices éparses complexes" #~ msgid "Argument rho must be an environment" #~ msgstr "L'argument rho doit être un environnement" #~ msgid "invalid class of object to as_cholmod_sparse" #~ msgstr "classe d'objet incorrecte pour as_cholmod_sparse" #~ msgid "invalid object passed to as_cholmod_sparse" #~ msgstr "objet incorrect passé à as_cholmod_sparse" #~ msgid "in_place cholmod_sort returned an error code" #~ msgstr "in_place cholmod_sort a renvoyé un code d'erreur" #~ msgid "cholmod_sort returned an error code" #~ msgstr "cholmod_sort a renvoyé un code d'erreur" #~ msgid "chm_sparse_to_SEXP(, *): invalid 'Rkind' (real kind code)" #~ msgstr "chm_sparse_to_SEXP(, *) : 'Rkind' incorrect (real kind code)" #~ msgid "unknown xtype in cholmod_sparse object" #~ msgstr "xtype inconnu dans cholmod_sparse object" #~ msgid "complex sparse matrix code not yet written" #~ msgstr "le code n'est pas encore écrit pour les matrices éparses complexes" #~ msgid "Symmetric and triangular both set" #~ msgstr "Symmetric et triangular sont tous deux sélectionnés" #~ msgid "invalid class of object to as_cholmod_triplet" #~ msgstr "classe d'objet incorrecte pour as_cholmod_triplet" #~ msgid "as_cholmod_triplet(): could not reallocate for internal diagU2N()" #~ msgstr "" #~ "as_cholmod_triplet() : impossible de réallouer de la mémoire pour la " #~ "fonction interne diagU2N()" #~ msgid "unknown xtype in cholmod_triplet object" #~ msgstr "xtype inconnu dans l'objet cholmod_triplet" #~ msgid "invalid class of object to as_cholmod_dense" #~ msgstr "classe d'objet incorrecte pour as_cholmod_dense" #, c-format #~ msgid "" #~ "chm_transpose_dense(ans, x) not yet implemented for %s different from %s" #~ msgstr "" #~ "chm_transpose_dense(ans, x) pas encore implémenté pour %s différent de %s" #, c-format #~ msgid "Unable to initialize cholmod: error code %d" #~ msgstr "Impossible d'initialiser cholmod : code d'erreur %d" #~ msgid "unknown 'Rkind'" #~ msgstr "'Rkind' inconnu" #~ msgid "unknown xtype" #~ msgstr "xtype inconnu" #~ msgid "code for cholmod_dense with holes not yet written" #~ msgstr "" #~ "le code pour cholmod_dense en présence de trous n'est pas encore écrit" #~ msgid "don't know if a dense pattern matrix makes sense" #~ msgstr "je ne sais pas si une matrice pattern dense a un sens" #, fuzzy #~ msgid "object of invalid class to 'as_cholmod_factor()'" #~ msgstr "class d'objet incorrecte pour as_cholmod_factor" #~ msgid "failure in as_cholmod_factor" #~ msgstr "erreur dans as_cholmod_factor" #~ msgid "CHOLMOD factorization was unsuccessful" #~ msgstr "La factorisation CHOLMOD a échoué" #, c-format #~ msgid "f->xtype of %d not recognized" #~ msgstr "f->xtype de %d non reconnu" #, c-format #~ msgid "chm_diagN2U(): nrow=%d, ncol=%d" #~ msgstr "chm_diagN2U(): nrow=%d, ncol=%d" #, c-format #~ msgid "chm_diagN2U(x, uploT = %d): uploT should be +- 1" #~ msgstr "chm_diagN2U(x, uploT = %d): uploT doit être +- 1" #~ msgid "dgCMatrix_lusol requires a square, non-empty matrix" #~ msgstr "dgCMatrix_lusol nécessite une matrice carrée non vide" #~ msgid "Dimensions of system to be solved are inconsistent" #~ msgstr "Les dimensions du système à résoudre sont incohérentes" #~ msgid "cs_lusol failed" #~ msgstr "cs_lusol a échoué" #~ msgid "dgCMatrix_qrsol(., order) needs order in {0,..,3}" #~ msgstr "dgCMatrix_qrsol(., order) nécessite un ordre compris entre {0,..,3}" #, c-format #~ msgid "" #~ "dgCMatrix_qrsol(<%d x %d>-matrix) requires a 'tall' rectangular matrix" #~ msgstr "" #~ "dgCMatrix_qrsol(<%d x %d>-matrix) nécessite une matrice rectangulaire " #~ "haute ('tall')" #~ msgid "cs_qrsol() failed inside dgCMatrix_qrsol()" #~ msgstr "cs_qrsol() a échoué à l'intérieur de dgCMatrix_qrsol()" #~ msgid "dgCMatrix_cholsol requires a 'short, wide' rectangular matrix" #~ msgstr "dgCMatrix_cholsol nécessite une matrice rectangulaire en longueur" #~ msgid "cholmod_sdmult error (rhs)" #~ msgstr "erreur cholmod_sdmult (partie droite de l'équation)" #, c-format #~ msgid "cholmod_factorize failed: status %d, minor %d from ncol %d" #~ msgstr "cholmod_factorize a échoué : statut %d, mineur %d pour ncol %d" #, c-format #~ msgid "cholmod_solve (CHOLMOD_A) failed: status %d, minor %d from ncol %d" #~ msgstr "" #~ "cholmod_solve (CHOLMOD_A) a échoué : statut %d, mineur %d pour ncol %d" #~ msgid "cholmod_sdmult error (resid)" #~ msgstr "erreur cholmod_sdmult (resid)" #~ msgid "SuiteSparseQR_C_QR returned an error code" #~ msgstr "SuiteSparseQR_C_QR a renvoyé un code d'erreur" #, fuzzy, c-format #~ msgid "LAPACK routine '%s': matrix is exactly singular, %s[i,i]=0, i=%d" #~ msgstr "Routine Lapack dgetrs : le système est exactement singulier" #, fuzzy, c-format #~ msgid "" #~ "LAPACK routine '%s': leading principal minor of order %d is not positive" #~ msgstr "le 'leading minor of order' %d n'est pas un entier fini" #, fuzzy #~ msgid "missing 'Matrix' namespace; should never happen" #~ msgstr "" #~ "espace de noms 'Matrix' manquant : ceci ne devrait jamais se produire" #, fuzzy #~ msgid "'Matrix' namespace not determined correctly" #~ msgstr "L’espace de noms Matrix n'est pas correctement déterminé" #~ msgid "Csparse_sort(x): x is not a valid (apart from sorting) CsparseMatrix" #~ msgstr "" #~ "Csparse_sort(x) : x est une CsparseMatrix incorrecte (au delà d'un " #~ "problème de tri)" #, c-format #~ msgid "Impossible Rk_x/Rk_y in Csparse_%s(), please report" #~ msgstr "Rk_x/Rk_y impossible dans Csparse_%s(), veuillez reporter l’erreur" #, c-format #~ msgid "chm_MOD_xtype() was not successful in Csparse_%s(), please report" #~ msgstr "" #~ "chm_MOD_xtype() a échoué dans Csparse_%s(), veuillez reporter l’erreur" #, c-format #~ msgid "the number of columns differ in R_rbind2_vector: %d != %d" #~ msgstr "le nombre de colonnes diffère dans R_rbind2_vector: %d != %d" #~ msgid "csp_eye argument n must be positive" #~ msgstr "l'argument n de csp_eye doit être positif" #~ msgid "invalid class of 'x' in Matrix_as_cs(a, x)" #~ msgstr "classe incorrecte de 'x' dans Matrix_as_cs(a, x)" #, c-format #~ msgid "invalid class of object to %s" #~ msgstr "classe incorrecte d'objet à %s" #, c-format #~ msgid "cs matrix not compatible with class '%s'" #~ msgstr "matrice cs incompatible avec la classe '%s'" #, c-format #~ msgid "Inappropriate class cl='%s' in Matrix_css_to_SEXP(S, cl, ..)" #~ msgstr "Classe inappropriée cl='%s' dans Matrix_css_to_SEXP(S, cl, ..)" #, c-format #~ msgid "Inappropriate class cl='%s' in Matrix_csn_to_SEXP(S, cl, ..)" #~ msgstr "Classe inappropriée cl='%s' dans Matrix_csn_to_SEXP(S, cl, ..)" #, c-format #~ msgid "Dimensions of x and y are not compatible for %s" #~ msgstr "Les dimensions de x et y ne sont pas compatibles pour %s" #~ msgid "Argument y must be numeric, integer or logical" #~ msgstr "L'argument y doit être un nombre réel, un entier ou un booléen" #~ msgid "Matrices are not conformable for multiplication" #~ msgstr "Les matrices sont incohérentes pour la multiplication" #, c-format #~ msgid "" #~ "dimension mismatch in matrix multiplication of \"dtrMatrix\": %d != %d" #~ msgstr "" #~ "dimensions incompatibles pour la multiplication matricielle avec " #~ "\"dtrMatrix\" : %d != %d" #~ msgid "dtrMatrix must be square" #~ msgstr "dtrMatrix doit être carrée" #, c-format #~ msgid "Dimensions of a (%d,%d) and b (%d,%d) do not conform" #~ msgstr "Les dimensions de a (%d,%d) et b (%d,%d) ne sont pas conformes" #~ msgid "right=TRUE is not yet implemented __ FIXME" #~ msgstr "right=TRUE n'est pas encore implémenté __ FIXME" #, c-format #~ msgid "cholmod_change_factor failed with status %d" #~ msgstr "cholmod_change_factor a échoué avec le statut %d" #~ msgid "system argument is not valid" #~ msgstr "argument système incorrect" #, c-format #~ msgid "cholmod_updown() returned %d" #~ msgstr "cholmod_updown() a renvoyé %d" #~ msgid "cholmod_drop() failed" #~ msgstr "cholmod_drop() a échoué" #, fuzzy #~ msgid "'off' does not have length 1" #~ msgstr "le slot '%s' doit avoir une longueur de 1" #, fuzzy #~ msgid "invalid 'code' to 'R_matrix_as_dense()'" #~ msgstr "classe '%s' incorrecte pour dup_mMatrix_as_dgeMatrix" #, fuzzy #~ msgid "invalid 'uplo' to 'R_matrix_as_dense()'" #~ msgstr "classe '%s' incorrecte pour dup_mMatrix_as_dgeMatrix" #, fuzzy #~ msgid "invalid 'diag' to 'R_matrix_as_dense()'" #~ msgstr "classe '%s' incorrecte pour dup_mMatrix_as_dgeMatrix" #, fuzzy #~ msgid "invalid argument 'system'" #~ msgstr "argument '%s' incorrect" #, fuzzy #~ msgid "dimensions of 'qr' and 'y' are inconsistent" #~ msgstr "Les dimensions du système à résoudre sont incohérentes" #, fuzzy #~ msgid "invalid 'op'" #~ msgstr "argument '%s' incorrect" #, fuzzy #~ msgid "'names' must be TRUE or FALSE" #~ msgstr "'uplo' doit être UPP ou LOW" #~ msgid "Csparse_crossprod(): error return from cholmod_aat()" #~ msgstr "Csparse_crossprod() : erreur renvoyée par cholmod_aat()" #, fuzzy #~ msgid "invalid 'kind' to 'R_sparse_as_kind()'" #~ msgstr "classe de 'x' incorrecte dans Csparse_subassign()" #~ msgid "slot p must have length = nrow(.) + 1" #~ msgstr "le slot p doit avoir longueur = nrow(.) + 1" #~ msgid "last element of slot p must match length of slots j and x" #~ msgstr "" #~ "le dernier élément du slot p doit avoir la même longueur que les slots j " #~ "et x" #~ msgid "all column indices must be between 0 and ncol-1" #~ msgstr "tous les indices de colonnes doivent être compris entre 0 et ncol-1" #~ msgid "slot j is not *strictly* increasing inside a column" #~ msgstr "" #~ "le slot j ne contient pas de valeurs *strictement* croissantes au sein " #~ "d'une colonne" #~ msgid "Csparse_to_nz_pattern(x, tri = NA): 'tri' is taken as TRUE" #~ msgstr "" #~ "Csparse_to_nz_pattern(x, tri = NA): 'tri' est considéré comme étant TRUE" #~ msgid "not a 'n.CMatrix'" #~ msgstr "ceci n'est pas un 'n.CMatrix'" #, c-format #~ msgid "nz2Csparse(): invalid/non-implemented r_kind = %d" #~ msgstr "nz2Csparse() : r_kind = %d est incorrect/non implémenté" #~ msgid "Nonsymmetric matrix in Csparse_symmetric_to_general" #~ msgstr "Matrice non symétrique dans Csparse_symmetric_to_general" #~ msgid "Csparse_general_to_symmetric(): matrix is not square!" #~ msgstr "Csparse_general_to_symmetric() : la matrice n'est pas carrée !" #~ msgid "Index i must be NULL or integer" #~ msgstr "L’indice i doit être un entier ou NULL" #~ msgid "Index j must be NULL or integer" #~ msgstr "L’indice j doit être un entier ou NULL" #, c-format #~ msgid "negative vector lengths not allowed: np = %d, nnz = %d" #~ msgstr "" #~ "les longueurs négatives de vecteurs ne sont pas autorisées : np = %d, nnz " #~ "= %d" #~ msgid "exactly 1 of 'i', 'j' or 'p' must be NULL" #~ msgstr "un et un seul des arguments 'i', 'j' ou 'p' doit être NULL" #, c-format #~ msgid "np = %d, must be zero when p is NULL" #~ msgstr "np = %d, il doit être égal à zéro lorsque p est NULL" #, c-format #~ msgid "p[0] = %d, should be zero" #~ msgstr "p[0] = %d, il devrait être égal à zéro" #~ msgid "p must be non-decreasing" #~ msgstr "p ne peut pas être décroissant" #, c-format #~ msgid "Inconsistent dimensions: np = 0 and nnz = %d" #~ msgstr "Dimensions incohérentes : np = 0 et nnz = %d" #, c-format #~ msgid "invalid column index at position %d" #~ msgstr "indices de colonnes erronés à la position %d" #, c-format #~ msgid "strlen of cls argument = %d, should be 8" #~ msgstr "strlen de l'argument cls = %d, il devrait valoir 8" #, c-format #~ msgid "cls = \"%s\" does not end in \"CMatrix\"" #~ msgstr "cls = \"%s\" ne se finit pas dans \"CMatrix\"" #, c-format #~ msgid "cls = \"%s\" must begin with 'd', 'l' or 'n'" #~ msgstr "cls = \"%s\" doit commencer par 'd', 'l', ou 'n'" #~ msgid "Only 'g'eneral sparse matrix types allowed" #~ msgstr "Seuls des types de matrices éparses 'g'énéraux sont acceptés" #~ msgid "code not yet written for cls = \"lgCMatrix\"" #~ msgstr "le code pour cls = \"lgCMatrix\" n'est pas encore écrit" #, c-format #~ msgid "%s must be (traditional R) matrix" #~ msgstr "%s doit être une matrice (traditionelle de R)" #, c-format #~ msgid "%s must be character string" #~ msgstr "%s doit être une chaîne de caractères" #, c-format #~ msgid "nrow * ncol = %d * %d must equal length(x) = %ld" #~ msgstr "nrow * ncol = %d * %d doit être égal à length(x) = %ld" #, c-format #~ msgid "strlen of cls argument = %d, should be 9" #~ msgstr "strlen de l'argument cls = %d, il devrait valoir 9" #, c-format #~ msgid "cls = \"%s\" must begin with 'd', 'l' or 'n' for now" #~ msgstr "cls = \"%s\" doit commencer par 'd', 'l', ou 'n' pour l’instant" #, c-format #~ msgid "%s must be a logical or double vector" #~ msgstr "%s doit être un vecteur de booléens ou de doubles" #, c-format #~ msgid "argument type[1]='%s' must be one of 'M','1','O','I','F' or 'E'" #~ msgstr "l'argument type[1]='%s' doit être parmi 'M','1','O','I','F' ou 'E'" #, c-format #~ msgid "argument type[1]='%s' must be one of '1','O', or 'I'" #~ msgstr "l'argument type[1]='%s' doit être parmi '1','O' ou 'I'" #~ msgid "object must be a named, numeric vector" #~ msgstr "l'objet doit être un vecteur numérique nommé" #~ msgid "'factors' slot must be a named list" #~ msgstr "le slot 'factors' doit être une liste nommée" #~ msgid "Matrix object has no 'factors' slot" #~ msgstr "L’objet Matrix n’a pas de slot 'factors'" #~ msgid "'s1' and 's2' must be \"character\" vectors" #~ msgstr "'s1' et 's2' doivent être des vecteurs de type \"character\"" #~ msgid "length of x slot != prod(Dim)" #~ msgstr "la longueur du slot x != prod(Dim)" #~ msgid "Negative value in Dim" #~ msgid_plural "Negative values in Dim" #~ msgstr[0] "Valeur négative dans Dim" #~ msgstr[1] "Valeurs négatives dans Dim" #, c-format #~ msgid "%s is a list, but not of length 2" #~ msgstr "%s est une liste, mais pas de longueur 2" #, c-format #~ msgid "invalid class '%s' to dup_mMatrix_as_geMatrix" #~ msgstr "classe '%s' incorrecte pour dup_mMatrix_as_geMatrix" #, c-format #~ msgid "unexpected ctype = %d in dup_mMatrix_as_geMatrix" #~ msgstr "ctype = %d inattendu dans dup_mMatrix_as_geMatrix" #~ msgid "lengths of slots i and j must match" #~ msgstr "la longueur des slots i et j doit correspondre" #~ msgid "slot Dim must have length 2" #~ msgstr "le slot Dim doit avoir une longueur de 2" #~ msgid "" #~ "all row indices (slot 'i') must be between 0 and nrow-1 in a TsparseMatrix" #~ msgstr "" #~ "tous les indices de lignes (slot 'i') doivent être compris entre 0 et " #~ "nrow-1 dans une TsparseMatrix" #~ msgid "" #~ "all column indices (slot 'j') must be between 0 and ncol-1 in a " #~ "TsparseMatrix" #~ msgstr "" #~ "tous les indices de colonnes (slot 'j') doivent être compris entre 0 et " #~ "ncol-1 dans une TsparseMatrix" #~ msgid "Supernodal LDL' decomposition not available" #~ msgstr "La décomposition 'supernodal LDL' n'est pas disponible" #~ msgid "Supernodal/simplicial class inconsistent with type flags" #~ msgstr "Classe supernodal/simplicial incohérente avec les drapeaux de type" #~ msgid "Number of supernodes must be positive when is_super is TRUE" #~ msgstr "" #~ "Le nombre de supernoeuds doit être positif lorsque is_super vaut TRUE" #~ msgid "Lengths of super and pi must be equal" #~ msgstr "Les longueurs de super et pi doivent être égales" #~ msgid "Lengths of super and px must be equal" #~ msgstr "Les longueurs de super et px doivent être égales" #, c-format #~ msgid "First call to Lapack routine dgels returned error code %d" #~ msgstr "" #~ "Le premier appel à la routine Lapack dgels a renvoyé le code d'erreur %d" #, c-format #~ msgid "Second call to Lapack routine dgels returned error code %d" #~ msgstr "" #~ "Le second appel à la routine Lapack dgels a renvoyé le code d'erreur %d" #, c-format #~ msgid "tol, given as %g, must be non-negative" #~ msgstr "tol, donné comme %g, doit être non négatif" #, c-format #~ msgid "Second call to dgeqrf returned error code %d" #~ msgstr "Le second appel à dgeqrf a renvoyé le code d'erreur %d" #, c-format #~ msgid "" #~ "dense_to_Csparse(): cholmod_l_dense_to_sparse failure status=%d" #~ msgstr "" #~ "dense_to_Csparse(): cholmod_l_dense_to_sparse statut d’erreur=%d" #, c-format #~ msgid "" #~ "Matrix dimension %d x %d (= %g) too large [FIXME calling " #~ "cholmod_l_dense_to_sparse]" #~ msgstr "" #~ "Dimension de Matrix %d x %d (= %g) trop large [FIXME appeler " #~ "cholmod_l_dense_to_sparse]" #, c-format #~ msgid "Lower band %d > upper band %d" #~ msgstr "Bande basse %d > bande haute %d" #~ msgid "ddense_to_symmetric(): matrix is not square!" #~ msgstr "ddense_to_symmetric() : la matrice n'est pas carrée !" #, c-format #~ msgid "matrix is not symmetric [%d,%d]" #~ msgstr "la matrice n'est pas symétrique [%d,%d]" #~ msgid "matrix is not square! (symmetric part)" #~ msgstr "la matrice n'est pas carrée ! (partie symétrique)" #~ msgid "matrix is not square! (skew-symmetric part)" #~ msgstr "la matrice n'est pas carrée ! (partie 'skew-symetric')" #~ msgid "lengths of slots 'i' and 'x' must match" #~ msgstr "les longueurs des slots 'i' et 'x' doivent correspondre" #~ msgid "lengths of slots 'j' and 'x' must match" #~ msgstr "les longueurs des slots 'j' et 'x' doivent correspondre" #, c-format #~ msgid "invalid class(x) '%s' in compressed_to_TMatrix(x)" #~ msgstr "class(x) incorrecte '%s' dans compressed_to_TMatrix(x)" #, c-format #~ msgid "invalid class(x) '%s' in R_to_CMatrix(x)" #~ msgstr "class(x) incorrecte '%s' dans R_to_CMatrix(x)" #~ msgid "A must have #{rows} >= #{columns}" #~ msgstr "A doit avoir #{lignes} >= #{colonnes}" #~ msgid "cs_sqr failed" #~ msgstr "cs_sqr a échoué" #~ msgid "dgcMatrix_QR(*, keep_dimnames = NA): NA taken as TRUE" #~ msgstr "dgcMatrix_QR(*, keep_dimnames = NA): NA considéré comme TRUE" #~ msgid "LU decomposition applies only to square matrices" #~ msgstr "La décomposition LU n'est utilisable que pour des matrices carrées" #~ msgid "cs_lu(A) failed: near-singular A (or out of memory)" #~ msgstr "" #~ "cs_lu(A) a échoué : A pratiquement singulière (ou manque de mémoire)" #~ msgid "dgcMatrix_LU(*, keep_dimnames = NA): NA taken as TRUE" #~ msgstr "dgcMatrix_LU(*, keep_dimnames = NA): NA considéré comme TRUE" #~ msgid "dgCMatrix_matrix_solve(.., sparse=TRUE) not yet implemented" #~ msgstr "dgCMatrix_matrix_solve(.., sparse=TRUE) n'est pas encore implémenté" #~ msgid "lengths of slots i and x must match" #~ msgstr "les longueurs des slots i et x doivent correspondre" #, c-format #~ msgid "too large matrix: %.0f" #~ msgstr "matrice trop large : %.0f" #, c-format #~ msgid "Cannot coerce to too large *geMatrix with %.0f entries" #~ msgstr "" #~ "Impossible de convertir automatiquement vers une *geMatrix trop large " #~ "avec %.0f entrées" #~ msgid "x slot must be numeric \"double\"" #~ msgstr "le slot x doit être un nombre \"double\"" #~ msgid "factors slot must be named list" #~ msgstr "le slot factors doit être une liste nommée" #~ msgid "rcond requires a square, non-empty matrix" #~ msgstr "rcond nécessite une matrice carrée non vide" #~ msgid "diagonal to be added has wrong length" #~ msgstr "la diagonale à ajouter a une longueur incorrecte" #~ msgid "Cannot factor a matrix with zero extents" #~ msgstr "Impossible de factoriser une matrice de dimensions nulles" #, c-format #~ msgid "Exact singularity detected during LU decomposition: %s, i=%d." #~ msgstr "Singularité exacte détectée lors d'une décomposition LU : %s, i=%d." #~ msgid "Solve requires a square matrix" #~ msgstr "Solve nécessite une matrice carrée" #, c-format #~ msgid "error [%d] from Lapack 'dgecon()'" #~ msgstr "erreur [%d] depuis Lapack 'dgecon()'" #, c-format #~ msgid "" #~ "Lapack dgecon(): system computationally singular, reciprocal condition " #~ "number = %g" #~ msgstr "" #~ "Lapack dgecon() : système calculé singulier, nombre de condition " #~ "réciproque = %g" #~ msgid "Lapack routine dgetri: system is exactly singular" #~ msgstr "Routine Lapack dgetri : le système est exactement singulier" #~ msgid "dpoMatrix is not positive definite" #~ msgstr "dpoMatrix n'est pas un entier positif fini" #~ msgid "Cannot solve() for matrices with zero extents" #~ msgstr "" #~ "Impossible de résoudre avec solve() pour des matrices de dimensions nulles" #~ msgid "Argument b must be a numeric matrix" #~ msgstr "L'argument b doit être une matrice numérique" #~ msgid "chm_factor_name(): did not get string of length 11" #~ msgstr "" #~ "chm_factor_name() : une chaîne de caractères de longueur 11 n'est pas " #~ "obtenue" #~ msgid "" #~ "Cholesky factorization failed; unusually, please report to Matrix-authors" #~ msgstr "" #~ "La factorisation Cholesky a échoué ; inhabituel, veuillez reporter le " #~ "problème aux auteurs du package Matrix" #~ msgid "internal_chm_factor: Cholesky factorization failed" #~ msgstr "internal_chm_factor : la factorisation Cholesky a échoué" #~ msgid "Non-symmetric matrix passed to dsCMatrix_to_dgTMatrix" #~ msgstr "Matrice non symétrique passée à dsCMatrix_to_dgTMatrix" #~ msgid "Incorrect length of 'x' slot" #~ msgstr "Longueur incorrecte du slot 'x'" #, c-format #~ msgid "Lapack routine dsytrf returned error code %d" #~ msgstr "La routine Lapack dsytrf a renvoyé le code d'erreur %d" #~ msgid "x must be a \"double\" (numeric) matrix" #~ msgstr "x doit être une matrice (numérique) de réels (doubles)" #~ msgid "matrix_trf(x, *): matrix is not square" #~ msgstr "matrix_trf(x, *) : la matrice n'est pas carrée" #~ msgid "matrix_trf(*, uplo): uplo must be string" #~ msgstr "matrix_trf(*, uplo) : uplo doit être une chaîne de caractères" #~ msgid "cannot set diag() as long as 'diag = \"U\"'" #~ msgstr "impossible d'utiliser diag() puisque 'diag = \"U\"'" #~ msgid "cannot add diag() as long as 'diag = \"U\"'" #~ msgstr "impossible d'ajouter diag() puisque 'diag = \"U\"'" #~ msgid "x slot is not of correct length" #~ msgstr "le slot x est de longueur incorrecte" #~ msgid "A must be a logical matrix" #~ msgstr "A doit être une matrice de valeurs booléennes" #~ msgid "length(p) must match nrow(V)" #~ msgstr "length(p) doit correspondre à nrow(V)" #~ msgid "length(beta) must match ncol(V)" #~ msgstr "length(beta) doit correspondre à ncol(V)" #~ msgid "length(q) must be zero or ncol(R)" #~ msgstr "length(q) doit valoir zéro ou ncol(R)" #, c-format #~ msgid "sparseQR_Qmult(): nrow(y) = %d != %d = nrow(V)" #~ msgstr "sparseQR_Qmult(): nrow(y) = %d != %d = nrow(V)" #~ msgid "\"dtrMatrix\" objects in '%*%' must have matching (square) dimension" #~ msgstr "" #~ "les objets \"dtrMatrix\" dans '%%*%%' doivent avoir des dimensions " #~ "(carrées) cohérentes" #~ msgid "not a CsparseMatrix" #~ msgstr "ceci n'est pas un CsparseMatrix" Matrix/cleanup0000755000175100001440000000045214576344042013123 0ustar hornikusers#!/bin/sh ## INSTALL does not clean up after ./configure or in subdirectories of src/; ## we do not have a ./configure, hence we only need the following: ssdir=SuiteSparse for sslib in SuiteSparse_config CXSparse AMD COLAMD CAMD CCOLAMD CHOLMOD; do (cd src/${ssdir}/${sslib} && make clean) done