diff --git a/CMakeLists.txt b/CMakeLists.txt index 8edfcc9d0c..2a73790b5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,7 +111,7 @@ include ( SuiteSparsePolicy ) if ( SUITESPARSE_USE_SYSTEM_GRAPHBLAS ) list ( REMOVE_ITEM SUITESPARSE_ENABLE_PROJECTS "graphblas" ) - find_package ( GraphBLAS 9.3.0 REQUIRED ) + find_package ( GraphBLAS 9.3.1 REQUIRED ) else ( ) if ( "lagraph" IN_LIST SUITESPARSE_ENABLE_PROJECTS ) # LAGraph requires GraphBLAS. @@ -137,7 +137,7 @@ endif ( ) if ( SUITESPARSE_USE_SYSTEM_UMFPACK ) list ( REMOVE_ITEM SUITESPARSE_ENABLE_PROJECTS "umfpack" ) - find_package ( UMFPACK 6.3.3 REQUIRED ) + find_package ( UMFPACK 6.3.4 REQUIRED ) else ( ) if ( "paru" IN_LIST SUITESPARSE_ENABLE_PROJECTS ) # ParU requires UMFPACK. @@ -168,7 +168,7 @@ endif ( ) if ( SUITESPARSE_USE_SYSTEM_AMD ) list ( REMOVE_ITEM SUITESPARSE_ENABLE_PROJECTS "amd" ) - find_package ( AMD 3.3.2 REQUIRED ) + find_package ( AMD 3.3.3 REQUIRED ) else ( ) if ( "cholmod" IN_LIST SUITESPARSE_ENABLE_PROJECTS OR "ldl" IN_LIST SUITESPARSE_ENABLE_PROJECTS @@ -184,7 +184,7 @@ endif ( ) if ( SUITESPARSE_USE_SYSTEM_COLAMD ) list ( REMOVE_ITEM SUITESPARSE_ENABLE_PROJECTS "colamd" ) - find_package ( COLAMD 3.3.3 REQUIRED ) + find_package ( COLAMD 3.3.4 REQUIRED ) else ( ) if ( "cholmod" IN_LIST SUITESPARSE_ENABLE_PROJECTS OR "spex" IN_LIST SUITESPARSE_ENABLE_PROJECTS ) @@ -198,7 +198,7 @@ endif ( ) if ( SUITESPARSE_USE_SYSTEM_CAMD ) list ( REMOVE_ITEM SUITESPARSE_ENABLE_PROJECTS "camd" ) - find_package ( CAMD 3.3.2 REQUIRED ) + find_package ( CAMD 3.3.3 REQUIRED ) else ( ) if ( CHOLMOD_CAMD AND "cholmod" IN_LIST SUITESPARSE_ENABLE_PROJECTS ) # CHOLMOD can optionally use CAMD. @@ -211,7 +211,7 @@ endif ( ) if ( SUITESPARSE_USE_SYSTEM_CCOLAMD ) list ( REMOVE_ITEM SUITESPARSE_ENABLE_PROJECTS "ccolamd" ) - find_package ( CCOLAMD 3.3.3 REQUIRED ) + find_package ( CCOLAMD 3.3.4 REQUIRED ) else ( ) if ( CHOLMOD_CAMD AND "cholmod" IN_LIST SUITESPARSE_ENABLE_PROJECTS ) # CHOLMOD can optionally use CCOLAMD. @@ -224,7 +224,7 @@ endif ( ) if ( SUITESPARSE_USE_SYSTEM_SUITESPARSE_CONFIG ) list ( REMOVE_ITEM SUITESPARSE_ENABLE_PROJECTS "suitesparse_config" ) - find_package ( SuiteSparse_config 7.8.0 REQUIRED ) + find_package ( SuiteSparse_config 7.8.2 REQUIRED ) else ( ) if ( "mongoose" IN_LIST SUITESPARSE_ENABLE_PROJECTS OR "amd" IN_LIST SUITESPARSE_ENABLE_PROJECTS diff --git a/ChangeLog b/ChangeLog index 8ac73d6169..d8a7ed8b1f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +Aug 20, 2024: version 7.8.2 + + * LAGraph 1.1.4: bug fix for LAGraph_MMWrite when matrix is dense + * SPEX 3.2.1: release date revised, sync with primary SPEX repo + * SuiteSparse_config, Example: modified to reflect the release of + LAGraph 1.1.4 and SPEX 3.2.1 + * ParU 0.3.0: added parameter to ParU_Get + * Package versions in this release: (* denotes a new version) + SuiteSparse_config 7.8.2 * + AMD 3.3.3 + BTF 2.3.2 + CAMD 3.3.3 + CCOLAMD 3.3.4 + CHOLMOD 5.3.0 + COLAMD 3.3.4 + CSparse 4.3.2 + CXSparse 4.4.1 + Example 1.8.2 * + GraphBLAS 9.3.1 + KLU 2.3.4 + LDL 3.3.2 + LAGraph 1.1.4 * + SuiteSparse_Mongoose 3.3.4 + ParU 0.3.0 * + RBio 4.3.3 + SPEX 3.2.1 * + SPQR 4.3.4 + UMFPACK 6.3.4 + Aug 12, 2024: version 7.8.1 * GraphBLAS 9.3.1: bug fix in creation of JIT package diff --git a/Example/CMakeLists.txt b/Example/CMakeLists.txt index 5114449843..e72965d349 100644 --- a/Example/CMakeLists.txt +++ b/Example/CMakeLists.txt @@ -53,10 +53,10 @@ message ( STATUS "MY prefix path: ${CMAKE_PREFIX_PATH}" ) #------------------------------------------------------------------------------- # cmake inserts the date and version number into Include/my.h: -set ( MY_DATE "Aug 12, 2024" ) +set ( MY_DATE "Aug 20, 2024" ) set ( MY_VERSION_MAJOR 1 ) set ( MY_VERSION_MINOR 8 ) -set ( MY_VERSION_PATCH 1 ) +set ( MY_VERSION_PATCH 2 ) message ( STATUS "Building MY library version: v" ${MY_VERSION_MAJOR}. @@ -87,7 +87,7 @@ project ( my #------------------------------------------------------------------------------- # look for all SuiteSparse packages: -find_package ( SuiteSparse_config 7.8.1 REQUIRED ) +find_package ( SuiteSparse_config 7.8.2 REQUIRED ) find_package ( AMD 3.3.3 REQUIRED ) find_package ( BTF 2.3.2 REQUIRED ) find_package ( CAMD 3.3.3 REQUIRED ) @@ -99,11 +99,11 @@ find_package ( GraphBLAS 9.3.1 ) find_package ( KLU 2.3.4 REQUIRED ) find_package ( KLU_CHOLMOD 2.3.4 REQUIRED ) find_package ( LDL 3.3.2 REQUIRED ) -find_package ( LAGraph 1.1.3 ) +find_package ( LAGraph 1.1.4 ) find_package ( SuiteSparse_Mongoose 3.3.4 REQUIRED ) -find_package ( ParU 0.2.0 REQUIRED ) +find_package ( ParU 0.3.0 REQUIRED ) find_package ( RBio 4.3.3 REQUIRED ) -find_package ( SPEX 3.2.0 REQUIRED ) # requires GMP and MPFR +find_package ( SPEX 3.2.1 REQUIRED ) # requires GMP and MPFR find_package ( SPQR 4.3.4 REQUIRED ) find_package ( UMFPACK 6.3.4 REQUIRED ) diff --git a/Example/Include/my.h b/Example/Include/my.h index 50def62c35..8cd74c74e5 100644 --- a/Example/Include/my.h +++ b/Example/Include/my.h @@ -11,10 +11,10 @@ // file, since it is constructed from Config/my.h.in by cmake. // version and date for example user library -#define MY_DATE "Aug 12, 2024" +#define MY_DATE "Aug 20, 2024" #define MY_MAJOR_VERSION 1 #define MY_MINOR_VERSION 8 -#define MY_PATCH_VERSION 1 +#define MY_PATCH_VERSION 2 #ifdef __cplusplus extern "C" { diff --git a/Example/Include/my_internal.h b/Example/Include/my_internal.h index 6a9f1fee4f..7a10b994dc 100644 --- a/Example/Include/my_internal.h +++ b/Example/Include/my_internal.h @@ -14,8 +14,8 @@ // SuiteSparse include files for C/C++: #include "SuiteSparse_config.h" -#if !defined (SUITESPARSE__VERSION) || SUITESPARSE__VERSION < SUITESPARSE__VERCODE(7,8,1) -#error "This library requires SuiteSparse_config 7.8.1 or later" +#if !defined (SUITESPARSE__VERSION) || SUITESPARSE__VERSION < SUITESPARSE__VERCODE(7,8,2) +#error "This library requires SuiteSparse_config 7.8.2 or later" #endif #include "amd.h" @@ -63,8 +63,8 @@ #if ! defined (NO_LAGRAPH) #include "LAGraph.h" - #if SUITESPARSE__VERCODE(LAGRAPH_VERSION_MAJOR,LAGRAPH_VERSION_MINOR,LAGRAPH_VERSION_UPDATE) < SUITESPARSE__VERCODE(1,1,3) - #error "This library requires LAGraph 1.1.3 or later" + #if SUITESPARSE__VERCODE(LAGRAPH_VERSION_MAJOR,LAGRAPH_VERSION_MINOR,LAGRAPH_VERSION_UPDATE) < SUITESPARSE__VERCODE(1,1,4) + #error "This library requires LAGraph 1.1.4 or later" #endif #endif @@ -84,8 +84,8 @@ #endif #include "SPEX.h" -#if !defined (SPEX__VERSION) || SPEX__VERSION < SUITESPARSE__VERCODE(3,2,0) -#error "This library requires SPEX 3.2.0 or later" +#if !defined (SPEX__VERSION) || SPEX__VERSION < SUITESPARSE__VERCODE(3,2,1) +#error "This library requires SPEX 3.2.1 or later" #endif #include "SuiteSparseQR_C.h" diff --git a/LAGraph/CMakeLists.txt b/LAGraph/CMakeLists.txt index b8685d669b..90a9350697 100644 --- a/LAGraph/CMakeLists.txt +++ b/LAGraph/CMakeLists.txt @@ -39,10 +39,10 @@ cmake_minimum_required ( VERSION 3.20 ) # LAGraph can be built stand-alone # version of LAGraph -set ( LAGraph_DATE "Mar 22, 2024" ) +set ( LAGraph_DATE "Aug 20, 2024" ) set ( LAGraph_VERSION_MAJOR 1 CACHE STRING "" FORCE ) set ( LAGraph_VERSION_MINOR 1 CACHE STRING "" FORCE ) -set ( LAGraph_VERSION_SUB 3 CACHE STRING "" FORCE ) +set ( LAGraph_VERSION_SUB 4 CACHE STRING "" FORCE ) message ( STATUS "Building LAGraph version: v" ${LAGraph_VERSION_MAJOR}. diff --git a/LAGraph/ChangeLog b/LAGraph/ChangeLog index 995f8d43d6..758ed824e3 100644 --- a/LAGraph/ChangeLog +++ b/LAGraph/ChangeLog @@ -1,3 +1,7 @@ +Aug 20, 2024: version 1.1.4 + + * fix MMWrite when matrix is dense + Mar 22, 2024: version 1.1.3 * minor updates to build system diff --git a/LAGraph/data/comments_full.mtx b/LAGraph/data/comments_full.mtx index 430b7756bb..097bb7a77a 100644 --- a/LAGraph/data/comments_full.mtx +++ b/LAGraph/data/comments_full.mtx @@ -2,7 +2,7 @@ %%GraphBLAS type double % comments for full.mtx % this file was created by test_MMRead.c -3 3 9 +3 3 .646 .709 .754 diff --git a/LAGraph/experimental/test/test_BF.c b/LAGraph/experimental/test/test_BF.c index ad48ca5d68..e5e88ff4e6 100644 --- a/LAGraph/experimental/test/test_BF.c +++ b/LAGraph/experimental/test/test_BF.c @@ -396,8 +396,6 @@ void test_BF (void) // since d5 is a dense vector filled with infinity, we have // to compare it against d seperaterly OK (GrB_Vector_extractElement (&di, d5, i)) ; - printf ("di %g d[i] %g difference %g\n", - di, d [i], di - d [i]) ; TEST_CHECK (di == d[i]) ; // since d5a is a dense vector filled with infinity, we diff --git a/LAGraph/github_workflows/workflows/build.yml b/LAGraph/github_workflows/workflows/build.yml index 26fa99157e..f1562e1b0f 100644 --- a/LAGraph/github_workflows/workflows/build.yml +++ b/LAGraph/github_workflows/workflows/build.yml @@ -1,4 +1,4 @@ -name: LAGraph CI +name: LAGraph CI with Builtin GraphBLAS on: workflow_dispatch: @@ -13,38 +13,34 @@ jobs: strategy: matrix: config: - - {grb_version: 7.1.0, conda_grb_package_hash: h27087fc, conda_extension: tar.bz2} - - {grb_version: 7.3.0, conda_grb_package_hash: h27087fc, conda_extension: tar.bz2} - - {grb_version: 7.4.1, conda_grb_package_hash: hcb278e6, conda_extension: conda} + # if there are multiple items in this list, only use should + # deployit=true for just one of them. + - {grb_version: 9.3.1, deployit: true} steps: - name: Checkout uses: actions/checkout@v2.0.0 - name: Install tools for build run: | sudo apt install -y lcov - - name: Get GraphBLAS binaries + - name: Build GraphBLAS run: | - mkdir graphblas-binaries - cd graphblas-binaries - wget --quiet https://anaconda.org/conda-forge/graphblas/${{ matrix.config.grb_version }}/download/linux-64/graphblas-${{ matrix.config.grb_version }}-${{ matrix.config.conda_grb_package_hash }}_0.${{ matrix.config.conda_extension }} - if [ ${{ matrix.config.conda_extension }} == "tar.bz2" ]; then - tar xf graphblas-${{ matrix.config.grb_version }}-${{ matrix.config.conda_grb_package_hash }}_0.${{ matrix.config.conda_extension }} - else - unzip graphblas-${{ matrix.config.grb_version }}-${{ matrix.config.conda_grb_package_hash }}_0.${{ matrix.config.conda_extension }} - tar xf pkg-graphblas-${{ matrix.config.grb_version }}-${{ matrix.config.conda_grb_package_hash }}_0.tar.zst - fi + git clone https://github.com/DrTimothyAldenDavis/GraphBLAS.git + cd GraphBLAS + git checkout tags/v${{ matrix.config.grb_version }} + make compact + sudo make install cd .. - name: Build project run: | - export GRAPHBLAS_INCLUDE_DIR=`pwd`/graphblas-binaries/include - export GRAPHBLAS_LIBRARY=`pwd`/graphblas-binaries/lib/libgraphblas.so + export GRAPHBLAS_INCLUDE_DIR=`pwd`/GraphBLAS/include/suitesparse + export GRAPHBLAS_LIBRARY=`pwd`/GraphBLAS/lib/libgraphblas.so cd build cmake .. -DCOVERAGE=1 -DGRAPHBLAS_INCLUDE_DIR=${GRAPHBLAS_INCLUDE_DIR} -DGRAPHBLAS_LIBRARY=${GRAPHBLAS_LIBRARY} JOBS=2 make make test_coverage - name: Deploy uses: JamesIves/github-pages-deploy-action@4.1.1 - if: matrix.config.grb_version == '7.4.1' && github.event_name == 'push' && github.ref == 'refs/heads/stable' + if: matrix.config.deployit && github.event_name == 'push' && github.ref == 'refs/heads/stable' with: branch: gh-pages folder: build/test_coverage/ @@ -59,9 +55,7 @@ jobs: strategy: matrix: config: - - {grb_version: 7.1.0, conda_grb_package_hash: h7881ed4, conda_extension: tar.bz2} - - {grb_version: 7.3.0, conda_grb_package_hash: ha894c9a, conda_extension: tar.bz2} - - {grb_version: 7.4.1, conda_grb_package_hash: ha894c9a, conda_extension: conda} + - {grb_version: 9.3.1} steps: - name: Checkout uses: actions/checkout@v2.0.0 @@ -70,22 +64,18 @@ jobs: brew tap-new libomp/cask brew extract --version=14.0.6 libomp libomp/cask brew install libomp@14.0.6 - - name: Get GraphBLAS binaries + - name: Build GraphBLAS run: | - mkdir graphblas-binaries - cd graphblas-binaries - wget --quiet https://anaconda.org/conda-forge/graphblas/${{ matrix.config.grb_version }}/download/osx-64/graphblas-${{ matrix.config.grb_version }}-${{ matrix.config.conda_grb_package_hash }}_0.${{ matrix.config.conda_extension }} - if [ ${{ matrix.config.conda_extension }} == "tar.bz2" ]; then - tar xf graphblas-${{ matrix.config.grb_version }}-${{ matrix.config.conda_grb_package_hash }}_0.${{ matrix.config.conda_extension }} - else - unzip graphblas-${{ matrix.config.grb_version }}-${{ matrix.config.conda_grb_package_hash }}_0.${{ matrix.config.conda_extension }} - tar xf pkg-graphblas-${{ matrix.config.grb_version }}-${{ matrix.config.conda_grb_package_hash }}_0.tar.zst - fi + git clone https://github.com/DrTimothyAldenDavis/GraphBLAS.git + cd GraphBLAS + git checkout tags/v${{ matrix.config.grb_version }} + make compact + sudo make install cd .. - name: Build project run: | - export GRAPHBLAS_INCLUDE_DIR=`pwd`/graphblas-binaries/include - export GRAPHBLAS_LIBRARY=`pwd`/graphblas-binaries/lib/libgraphblas.dylib + export GRAPHBLAS_INCLUDE_DIR=`pwd`/GraphBLAS/include/suitesparse + export GRAPHBLAS_LIBRARY=`pwd`/GraphBLAS/lib/libgraphblas.dylib # adding an extra line to the CMakeLists.txt file to locate the libomp instance installed by brew echo 'include_directories("/usr/local/opt/libomp/include")' | cat - CMakeLists.txt cd build diff --git a/LAGraph/include/LAGraph.h b/LAGraph/include/LAGraph.h index baa9bbaf62..8357c8bdb5 100644 --- a/LAGraph/include/LAGraph.h +++ b/LAGraph/include/LAGraph.h @@ -37,10 +37,10 @@ // See also the LAGraph_Version utility method, which returns these values. // These definitions are derived from LAGraph/CMakeLists.txt. -#define LAGRAPH_DATE "Mar 22, 2024" +#define LAGRAPH_DATE "Aug 20, 2024" #define LAGRAPH_VERSION_MAJOR 1 #define LAGRAPH_VERSION_MINOR 1 -#define LAGRAPH_VERSION_UPDATE 3 +#define LAGRAPH_VERSION_UPDATE 4 //============================================================================== // include files and helper macros diff --git a/LAGraph/src/utility/LAGraph_MMWrite.c b/LAGraph/src/utility/LAGraph_MMWrite.c index 51bd5841c2..4c4c8828f9 100644 --- a/LAGraph/src/utility/LAGraph_MMWrite.c +++ b/LAGraph/src/utility/LAGraph_MMWrite.c @@ -459,8 +459,18 @@ int LAGraph_MMWrite nvals_to_print = nself_edges + (nvals - nself_edges) / 2 ; } - FPRINTF (f, "%" PRIu64 " %" PRIu64 " %" PRIu64 "\n", - nrows, ncols, nvals_to_print) ; + if (MM_fmt == MM_array) + { + // write `nrows ncols` if the array format is used + FPRINTF (f, "%" PRIu64 " %" PRIu64 "\n", + nrows, ncols) ; + } + else + { + // otherwise write `nrows ncols nvals` for the coordinate format + FPRINTF (f, "%" PRIu64 " %" PRIu64 " %" PRIu64 "\n", + nrows, ncols, nvals_to_print) ; + } if (nvals_to_print == 0) { diff --git a/ParU/CMakeLists.txt b/ParU/CMakeLists.txt index c273196d3b..683d63f8c7 100644 --- a/ParU/CMakeLists.txt +++ b/ParU/CMakeLists.txt @@ -13,9 +13,9 @@ # cmake 3.22 is required to find the BLAS in SuiteSparse_config cmake_minimum_required ( VERSION 3.22 ) -set ( PARU_DATE "Aug 2, 2024" ) +set ( PARU_DATE "Aug 20, 2024" ) set ( PARU_VERSION_MAJOR 0 CACHE STRING "" FORCE ) -set ( PARU_VERSION_MINOR 2 CACHE STRING "" FORCE ) +set ( PARU_VERSION_MINOR 3 CACHE STRING "" FORCE ) set ( PARU_VERSION_UPDATE 0 CACHE STRING "" FORCE ) message ( STATUS "Building PARU version: v" @@ -423,14 +423,20 @@ if ( SUITESPARSE_DEMOS ) if ( PARU_HAS_OPENMP ) add_executable ( paru_demo "Demo/paru_demo.cpp" ) + add_executable ( paru_benchmark "Demo/paru_benchmark.cpp" ) if ( BUILD_SHARED_LIBS ) target_link_libraries ( paru_demo PUBLIC ParU ) + target_link_libraries ( paru_benchmark PUBLIC ParU ) else ( ) target_link_libraries ( paru_demo PUBLIC ParU_static ) + target_link_libraries ( paru_benchmark PUBLIC ParU_static ) endif ( ) target_link_libraries ( paru_demo PUBLIC SuiteSparse::CHOLMOD SuiteSparse::UMFPACK SuiteSparse::SuiteSparseConfig OpenMP::OpenMP_CXX ) + target_link_libraries ( paru_benchmark + PUBLIC SuiteSparse::CHOLMOD SuiteSparse::UMFPACK + SuiteSparse::SuiteSparseConfig OpenMP::OpenMP_CXX ) add_executable ( paru_democ "Demo/paru_democ.c" ) if ( BUILD_SHARED_LIBS ) diff --git a/ParU/Config/ParU.h.in b/ParU/Config/ParU.h.in index d9ef6506a0..2fc6d1eca0 100644 --- a/ParU/Config/ParU.h.in +++ b/ParU/Config/ParU.h.in @@ -139,6 +139,7 @@ typedef enum // int64_t parameter, for ParU_Get only: PARU_CONTROL_OPENMP = 1013, // if ParU compiled with OpenMP; // (for ParU_Get only, not set) + PARU_CONTROL_NUM_THREADS = 1014, // actual number of threads used // double parameters for ParU_Set and ParU_Get: PARU_CONTROL_PIVOT_TOLERANCE = 2001, // pivot tolerance diff --git a/ParU/Demo/.gitignore b/ParU/Demo/.gitignore new file mode 100644 index 0000000000..4f30d42c90 --- /dev/null +++ b/ParU/Demo/.gitignore @@ -0,0 +1,3 @@ +# Ignore the following: +Res +!.gitignore diff --git a/ParU/Demo/paru_benchmark.cpp b/ParU/Demo/paru_benchmark.cpp new file mode 100644 index 0000000000..6f64fd488e --- /dev/null +++ b/ParU/Demo/paru_benchmark.cpp @@ -0,0 +1,444 @@ +// ========================================================================== / +// ======================= paru_benchmark.cpp ============================== / +// ========================================================================== / + +// ParU, Copyright (c) 2022-2024, Mohsen Aznaveh and Timothy A. Davis, +// All Rights Reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +/* + * @brief benchmark ParU and UMFPACK + * + * @author Aznaveh + * */ + +#include +#include +#include +#include + +#include "ParU.h" +#include +#ifdef _OPENMP +#include +#else +#error "OpenMP not available!" +#endif + +#define FREE_ALL_AND_RETURN(info) \ +{ \ + if (b != NULL) free(b); \ + if (xx != NULL) free(xx); \ + if (x != NULL) free(x); \ + if (B != NULL) free(B); \ + if (X != NULL) free(X); \ + umfpack_dl_free_symbolic(&Symbolic); \ + umfpack_dl_free_numeric(&Numeric); \ + ParU_FreeNumeric(&Num, Control); \ + ParU_FreeSymbolic(&Sym, Control); \ + ParU_FreeControl(&Control); \ + cholmod_l_free_sparse(&A, cc); \ + cholmod_l_finish(cc); \ + if (argc > 1 && fp != NULL) fclose (fp) ; \ + fp = NULL ; \ + return (info) ; \ +} + +static int compar (const void *p1, const void *p2) +{ + double x1 = *((double *) p1) ; + double x2 = *((double *) p2) ; + return (x1 < x2 ? -1 : ((x1 > x2) ? 1 : 0)) ; +} + +int main(int argc, char **argv) +{ + cholmod_common Common, *cc; + cholmod_sparse *A; + ParU_Symbolic Sym = NULL; + ParU_Numeric Num = NULL ; + ParU_Control Control = NULL ; + ParU_Info info; + double *b = NULL, *xx = NULL, *B = NULL, *X = NULL, *x = NULL ; + void *Symbolic = NULL, *Numeric = NULL ; + FILE *fp = stdin ; + + //~~~~~~~~~Reading the input matrix and test if the format is OK~~~~~~~~~~~~ + // start CHOLMOD + cc = &Common; + int mtype; + cholmod_l_start(cc); + + if (argc > 1) + { + std::cout << "Matrix: " << argv [1] << std::endl ; + fp = fopen (argv [1], "r") ; + } + else + { + std::cout << "Matrix: stdin" << std::endl ; + } + + // A = mread (fp) ; read in the sparse matrix A + A = (cholmod_sparse *)cholmod_l_read_matrix(fp, 1, &mtype, cc); + if (A == NULL) + { + std::cout << "ParU: input matrix is invalid" << std::endl; + FREE_ALL_AND_RETURN (PARU_INVALID) ; + } + + if (mtype != CHOLMOD_SPARSE) + { + std::cout << "ParU: input matrix must be sparse" << std::endl; + FREE_ALL_AND_RETURN (PARU_INVALID) ; + } + + if (A->xtype != CHOLMOD_REAL) + { + std::cout << "ParU: input matrix must be real" << std::endl; + FREE_ALL_AND_RETURN (PARU_INVALID) ; + } + + //~~~~~~~~~~~~~~~~~~~Starting computation~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + int ver[3]; + char date[128]; + ParU_Version(ver, date); + std::cout << "================= ParU " + << ver[0] << "." << ver[1] << "." << ver[2] + << " ================================== " << date << std::endl; + + info = ParU_InitControl (&Control) ; + if (info != PARU_SUCCESS) + { + FREE_ALL_AND_RETURN (info) ; + } + + const char *blas_name ; + info = ParU_Get (PARU_CONTROL_BLAS_LIBRARY_NAME, &blas_name, Control) ; + if (info != PARU_SUCCESS) + { + FREE_ALL_AND_RETURN (info) ; + } + std::cout << "BLAS: " << blas_name << std::endl ; + + const char *tasking ; + info = ParU_Get (PARU_CONTROL_FRONT_TREE_TASKING, &tasking, Control) ; + if (info != PARU_SUCCESS) + { + FREE_ALL_AND_RETURN (info) ; + } + std::cout << "frontal tree tasking: " << tasking << std::endl ; + + int64_t using_openmp ; + info = ParU_Get (PARU_CONTROL_OPENMP, &using_openmp, Control) ; + if (info != PARU_SUCCESS) + { + FREE_ALL_AND_RETURN (info) ; + } + std::cout << "OpenMP in ParU: " << (using_openmp ? "yes" : "no" ) + << std::endl ; + + int64_t max_nthreads ; + #ifdef _OPENMP + max_nthreads = omp_get_max_threads ( ) ; + #else + max_ntreads = 1 ; + #endif + std::cout << "max # threads: " << max_nthreads << std::endl ; + + // allocate workspace + int64_t n, anz ; + n = A->nrow ; + const int64_t nrhs = 16; // number of right handsides + b = (double *)malloc(n * sizeof(double)); + xx = (double *)malloc(n * sizeof(double)); + B = (double *)malloc(n * nrhs * sizeof(double)); + X = (double *)malloc(n * nrhs * sizeof(double)); + x = (double *)malloc(n * sizeof(double)); + double rcond ; + + #define NTRIALS 5 + int middle = NTRIALS / 2 ; + + for (int ord = 0 ; ord <= 1 ; ord++) + { + int ordering = (ord == 0) ? PARU_ORDERING_AMD : + PARU_ORDERING_METIS_GUARD ; + printf ("===== ParU ordering: %d\n", ordering) ; + ParU_Set (PARU_CONTROL_ORDERING, ordering, Control) ; + for (int nthreads = max_nthreads ; nthreads > 0 ; nthreads = nthreads/2) + { + printf ("# threads: %d\n", nthreads) ; + ParU_Set (PARU_CONTROL_MAX_THREADS, (int64_t) nthreads, Control) ; + int64_t nthreads2 = 0 ; + ParU_Get (PARU_CONTROL_NUM_THREADS, &nthreads2, Control) ; + if (nthreads != (int32_t) nthreads2) + { + std::cout << "ParU: invalid # of threads!" << std::endl; + FREE_ALL_AND_RETURN (PARU_INVALID) ; + } + + double ParU_sym_times [NTRIALS] ; + double ParU_num_times [NTRIALS] ; + double ParU_sol_times [NTRIALS] ; + for (int trial = 0 ; trial < NTRIALS ; trial++) + { + printf ("Trial: %d\n", trial) ; + + double my_start_time = SUITESPARSE_TIME ; + info = ParU_Analyze(A, &Sym, Control); + double my_time_analyze = SUITESPARSE_TIME - my_start_time; + if (info != PARU_SUCCESS) + { + std::cout << "ParU: analyze failed" << std::endl; + FREE_ALL_AND_RETURN (info) ; + } + + info = ParU_Get (Sym, Num, PARU_GET_N, &n, Control) ; + if (info != PARU_SUCCESS) + { + std::cout << "ParU: stats failed" << std::endl; + FREE_ALL_AND_RETURN (info) ; + } + + info = ParU_Get (Sym, Num, PARU_GET_ANZ, &anz, Control) ; + if (info != PARU_SUCCESS) + { + std::cout << "ParU: stats failed" << std::endl; + FREE_ALL_AND_RETURN (info) ; + } + + if (trial == 0) + { + std::cout << "n: " << n << " anz: " << anz << std::endl ; + } + + double my_start_time_fac = SUITESPARSE_TIME; + info = ParU_Factorize(A, Sym, &Num, Control); + double my_time_fac = SUITESPARSE_TIME - my_start_time_fac; + if (info != PARU_SUCCESS) + { + std::cout << std::scientific << std::setprecision(6) + << "ParU: factorization was NOT successful: " + << my_time_fac << " seconds\n"; + if (info == PARU_OUT_OF_MEMORY) + std::cout << "Out of memory\n"; + if (info == PARU_INVALID) + std::cout << "Invalid!\n"; + if (info == PARU_SINGULAR) + std::cout << "Singular!\n"; + FREE_ALL_AND_RETURN (info) ; + } + + info = ParU_Get (Sym, Num, PARU_GET_RCOND_ESTIMATE, &rcond, + Control) ; + if (info != PARU_SUCCESS) + { + std::cout << "ParU: stats failed" << std::endl; + FREE_ALL_AND_RETURN (info) ; + } + + //~~~~~~~~~~Test the results ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + double my_time, my_solve_time; + + for (int64_t i = 0; i < n; ++i) b[i] = i + 1; + double my_solve_time_start = SUITESPARSE_TIME; + info = ParU_Solve(Sym, Num, b, xx, Control); + if (info != PARU_SUCCESS) + { + std::cout << "ParU: solve failed" << std::endl; + FREE_ALL_AND_RETURN (info) ; + } + my_solve_time = SUITESPARSE_TIME - my_solve_time_start; + my_time = SUITESPARSE_TIME - my_start_time; + + double resid, anorm, xnorm; + info = ParU_Residual(A, xx, b, resid, anorm, xnorm, Control); + if (info != PARU_SUCCESS) + { + std::cout << "ParU: resid failed" << std::endl; + FREE_ALL_AND_RETURN (info) ; + } + double rresid = (anorm == 0 || xnorm == 0 ) ? 0 : + (resid/(anorm*xnorm)); + + for (int64_t i = 0; i < n; ++i) + { + for (int64_t j = 0; j < nrhs; ++j) + { + B[j * n + i] = (double)(i + j + 1); + } + } + + my_solve_time_start = SUITESPARSE_TIME; + info = ParU_Solve(Sym, Num, nrhs, B, X, Control); + if (info != PARU_SUCCESS) + { + std::cout << "ParU: solve failed" << std::endl; + FREE_ALL_AND_RETURN (info) ; + } + double my_solve_time2 = SUITESPARSE_TIME - my_solve_time_start; + + info = ParU_Residual(A, X, B, nrhs, resid, anorm, xnorm, + Control); + if (info != PARU_SUCCESS) + { + std::cout << "ParU: solve failed" << std::endl; + FREE_ALL_AND_RETURN (info) ; + } + double rresid2 = (anorm == 0 || xnorm == 0 ) ? 0 : + (resid/(anorm*xnorm)); + + if (trial == 0) + { + std::cout << std::scientific << std::setprecision(6) + << "Relative residual: " << rresid << " rcond: " + << rcond << std::endl; + std::cout << std::scientific << std::setprecision(6) + << "Multiple right hand side: relative residual is |" + << rresid2 << "|." << std::endl; + } + + std::cout << std::scientific << std::setprecision(6) + << "ParU: time: sym: " << my_time_analyze + << " num: " << my_time_fac + << " solve (1 rhs): " << my_solve_time + << " solve (16 rhs): " << my_solve_time2 << std::endl ; + + ParU_sym_times [trial] = my_time_analyze ; + ParU_num_times [trial] = my_time_fac ; + ParU_sol_times [trial] = my_solve_time ; + + ParU_FreeNumeric(&Num, Control); + ParU_FreeSymbolic(&Sym, Control); + } + + qsort (ParU_sym_times, NTRIALS, sizeof (double), compar) ; + qsort (ParU_num_times, NTRIALS, sizeof (double), compar) ; + qsort (ParU_sol_times, NTRIALS, sizeof (double), compar) ; + + std::cout << std::scientific << std::setprecision(6) + << "\nParU ordering " << ordering + << " threads " << nthreads + << " median sym: " << ParU_sym_times [middle] + << " num: " << ParU_num_times [middle] + << " sol: " << ParU_sol_times [middle] + << " total: " << ParU_sym_times [middle] + + ParU_num_times [middle] + ParU_sol_times [middle] + << std::endl << std::endl ; + } + } + + //~~~~~~~~~~~~~~~~~~~End computation~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + //~~~~~~~~~~~~~~~~~~~Calling umfpack~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + double umf_time = 0; + double status, // Info [UMFPACK_STATUS] + Info[UMFPACK_INFO], // Contains statistics about the symbolic analysis + umf_Control[UMFPACK_CONTROL]; // it is set in umfpack_dl_defaults and + // is used in umfpack_dl_symbolic; if + // passed NULL it will use the defaults + umfpack_dl_defaults(umf_Control); + + int64_t *Ap = (int64_t *)A->p; + int64_t *Ai = (int64_t *)A->i; + double *Ax = (double *)A->x; + + for (int ord = 0 ; ord <= 1 ; ord++) + { + int ordering = (ord == 0) ? UMFPACK_ORDERING_AMD : + UMFPACK_ORDERING_METIS_GUARD ; + printf ("\n===== UMFPACK ordering: %d\n", ordering) ; + for (int nthreads = max_nthreads ; nthreads > 0 ; nthreads = nthreads/2) + { + printf ("# threads: %d\n", nthreads) ; + #ifdef _OPENMP + omp_set_num_threads (nthreads) ; + #endif + + double UMF_sym_times [NTRIALS] ; + double UMF_num_times [NTRIALS] ; + double UMF_sol_times [NTRIALS] ; + umf_Control[UMFPACK_ORDERING] = ordering ; + for (int trial = 0 ; trial < NTRIALS ; trial++) + { + printf ("Trial: %d\n", trial) ; + + double umf_start_time = SUITESPARSE_TIME; + status = umfpack_dl_symbolic(n, n, Ap, Ai, Ax, &Symbolic, + umf_Control, Info); + if (status < 0) + { + umfpack_dl_report_info(umf_Control, Info); + umfpack_dl_report_status(umf_Control, status); + std::cout << "umfpack_dl_symbolic failed\n"; + FREE_ALL_AND_RETURN (PARU_INVALID) ; + } + double umf_symbolic = SUITESPARSE_TIME - umf_start_time; + double umf_fac_start = SUITESPARSE_TIME; + status = umfpack_dl_numeric(Ap, Ai, Ax, Symbolic, &Numeric, + umf_Control, Info); + if (status < 0) + { + umfpack_dl_report_info(umf_Control, Info); + umfpack_dl_report_status(umf_Control, status); + std::cout << "umfpack_dl_numeric failed\n"; + FREE_ALL_AND_RETURN (PARU_INVALID) ; + } + + double umf_time_fac = SUITESPARSE_TIME - umf_fac_start; + + for (int64_t i = 0; i < n; ++i) b[i] = i + 1; + + double solve_start = SUITESPARSE_TIME; + status = umfpack_dl_solve(UMFPACK_A, Ap, Ai, Ax, x, b, + Numeric, umf_Control, Info); + double umf_solve_time = SUITESPARSE_TIME - solve_start; + umf_time = SUITESPARSE_TIME - umf_start_time; + + double umf_resid, umf_anorm, umf_xnorm; + info = ParU_Residual(A, x, b, umf_resid, umf_anorm, umf_xnorm, + Control); + double umf_rresid = (umf_anorm == 0 || umf_xnorm == 0 ) + ? 0 : (umf_resid/(umf_anorm*umf_xnorm)); + if (trial == 0) + { + std::cout << std::scientific << std::setprecision(6) + << "UMFPACK relative residual: " << umf_rresid + << std::endl; + } + + std::cout << std::scientific << std::setprecision(6) + << "UMFPACK time: sym " << umf_symbolic + << " num: " << umf_time_fac + << " solve: " << umf_solve_time << std::endl ; + + UMF_sym_times [trial] = umf_symbolic ; + UMF_num_times [trial] = umf_time_fac ; + UMF_sol_times [trial] = umf_solve_time ; + + umfpack_dl_free_symbolic(&Symbolic); + umfpack_dl_free_numeric(&Numeric); + } + + qsort (UMF_sym_times, NTRIALS, sizeof (double), compar) ; + qsort (UMF_num_times, NTRIALS, sizeof (double), compar) ; + qsort (UMF_sol_times, NTRIALS, sizeof (double), compar) ; + + std::cout << std::scientific << std::setprecision(6) + << "\nUMF ordering " << ordering + << " threads " << nthreads + << " median sym: " << UMF_sym_times [middle] + << " num: " << UMF_num_times [middle] + << " sol: " << UMF_sol_times [middle] + << " total: " << UMF_sym_times [middle] + + UMF_num_times [middle] + UMF_sol_times [middle] + << std::endl << std::endl ; + } + } + + //~~~~~~~~~~~~~~~~~~~Free Everything~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + FREE_ALL_AND_RETURN (PARU_SUCCESS) ; +} + diff --git a/ParU/Doc/paru_user_guide.tex b/ParU/Doc/paru_user_guide.tex index 53968be19b..a55b9b61e1 100644 --- a/ParU/Doc/paru_user_guide.tex +++ b/ParU/Doc/paru_user_guide.tex @@ -337,7 +337,8 @@ \subsection{{\sf ParU\_Set}: set parameters in the Control object} ) ; \end{verbatim}} The \verb'ParU_Control_enum parameter' defines which parameter to set, -described below. +described below. These are also used for \verb'ParU_Get', to read back these +parameters from the \verb'Control' object. {\footnotesize \begin{verbatim} @@ -362,6 +363,7 @@ \subsection{{\sf ParU\_Set}: set parameters in the Control object} // int64_t parameter, for ParU_Get only: PARU_CONTROL_OPENMP = 1013, // if ParU compiled with OpenMP; // (for ParU_Get only, not set) + PARU_CONTROL_NUM_THREADS = 1014, // actual number of threads used // double parameters for ParU_Set and ParU_Get: PARU_CONTROL_PIVOT_TOLERANCE = 2001, // pivot tolerance @@ -763,7 +765,7 @@ \subsection{{\sf ParU\_Get}: get information from a ParU opaque object} ) ; \end{verbatim}} The parameters that can be returned are the same as those described in -Section~\ref{set}, with three additional parameters that can be queried by +Section~\ref{set}, with four additional parameters that can be queried by \verb'ParU_Get' but not set with \verb'ParU_Set'. Two cases return string that is owned by the library and must not be modified: @@ -773,12 +775,22 @@ \subsection{{\sf ParU\_Get}: get information from a ParU opaque object} ParU_Get (PARU_CONTROL_BLAS_LIBRARY_NAME, &blas_name, Control)) ; ParU_Get (PARU_CONTROL_FRONT_TREE_TASKING, &front_tasking, Control)) ; \end{verbatim}} -A final case returns true if ParU was compiled with OpenMP, or false otherwise: +This case returns true if ParU was compiled with OpenMP, or false otherwise: {\footnotesize \begin{verbatim} int64_t openmp_used ; - ParU_Get (PARU_CONTROL_OPENMP , &openmp_used, Control)) ; \end{verbatim}} + ParU_Get (PARU_CONTROL_OPENMP, &openmp_used, Control)) ; \end{verbatim}} + +Finally, the number of threads actually to be used by ParU can be queried as +follows. If the \verb'Control' is set to its default, this will be the value +from \verb'omp_get_max_threads'. Otherwise, the value is smaller of +\verb'omp_get_max_threads' and \verb'PARU_CONTROL_MAX_THREADS'. + + {\footnotesize + \begin{verbatim} + int64_t nthreads_used ; + ParU_Get (PARU_CONTROL_NUM_THREADS, &nthreads_used, Control)) ; \end{verbatim}} %------------------------------------------------------------------------------- \subsection{{\sf ParU\_Analyze}: symbolic analysis} diff --git a/ParU/Doc/paru_version.tex b/ParU/Doc/paru_version.tex index bf4ab9fcab..801498c306 100644 --- a/ParU/Doc/paru_version.tex +++ b/ParU/Doc/paru_version.tex @@ -1,2 +1,2 @@ % version of SuiteSparse/ParU -\date{VERSION 0.2.0, Aug 2, 2024} +\date{VERSION 0.3.0, Aug 20, 2024} diff --git a/ParU/Include/ParU.h b/ParU/Include/ParU.h index 52eda95f82..2348782d2c 100644 --- a/ParU/Include/ParU.h +++ b/ParU/Include/ParU.h @@ -53,25 +53,25 @@ typedef enum ParU_Info PARU_TOO_LARGE = -4 // problem too large for the BLAS } ParU_Info ; -#define PARU_DATE "Aug 2, 2024" +#define PARU_DATE "Aug 20, 2024" #define PARU_VERSION_MAJOR 0 -#define PARU_VERSION_MINOR 2 +#define PARU_VERSION_MINOR 3 #define PARU_VERSION_UPDATE 0 -#define PARU__VERSION SUITESPARSE__VERCODE(0,2,0) +#define PARU__VERSION SUITESPARSE__VERCODE(0,3,0) #if !defined (SUITESPARSE__VERSION) || \ (SUITESPARSE__VERSION < SUITESPARSE__VERCODE(7,8,0)) -#error "ParU 0.2.0 requires SuiteSparse_config 7.8.0 or later" +#error "ParU 0.3.0 requires SuiteSparse_config 7.8.0 or later" #endif #if !defined (UMFPACK__VERSION) || \ (UMFPACK__VERSION < SUITESPARSE__VERCODE(6,3,4)) -#error "ParU 0.2.0 requires UMFPACK 6.3.4 or later" +#error "ParU 0.3.0 requires UMFPACK 6.3.4 or later" #endif #if !defined (CHOLMOD__VERSION) || \ (CHOLMOD__VERSION < SUITESPARSE__VERCODE(5,3,0)) -#error "ParU 0.2.0 requires CHOLMOD 5.3.0 or later" +#error "ParU 0.3.0 requires CHOLMOD 5.3.0 or later" #endif // the same values as UMFPACK_STRATEGY defined in UMFPACK/Include/umfpack.h @@ -139,6 +139,7 @@ typedef enum // int64_t parameter, for ParU_Get only: PARU_CONTROL_OPENMP = 1013, // if ParU compiled with OpenMP; // (for ParU_Get only, not set) + PARU_CONTROL_NUM_THREADS = 1014, // actual number of threads used // double parameters for ParU_Set and ParU_Get: PARU_CONTROL_PIVOT_TOLERANCE = 2001, // pivot tolerance diff --git a/ParU/Makefile b/ParU/Makefile index 447902343d..3864fe02a6 100644 --- a/ParU/Makefile +++ b/ParU/Makefile @@ -57,6 +57,9 @@ demos: library ( cd build && [ -f paru_democ$(EXEEXT) ] && ./paru_democ$(EXEEXT) < ../Matrix/west0067.mtx || true ) ( cd build && [ -f paru_demo$(EXEEXT) ] && ./paru_demo$(EXEEXT) < ../Matrix/xenon1.mtx || true ) +bench: library + ( cd build && [ -f paru_benchmark$(EXEEXT) ] && ./paru_benchmark$(EXEEXT) < ../Matrix/xenon1.mtx || true ) + V = valgrind --leak-check=full --show-leak-kinds=all vdemos: library diff --git a/ParU/Source/ParU_Get.cpp b/ParU/Source/ParU_Get.cpp index 359f30bfb0..78400190e0 100644 --- a/ParU/Source/ParU_Get.cpp +++ b/ParU/Source/ParU_Get.cpp @@ -249,10 +249,17 @@ ParU_Info ParU_Get // get an int64_t parameter from the Control object { case PARU_CONTROL_MAX_THREADS: // max number of threads + // 0 is the default, which lets ParU use the # of threads + // determined by omp_get_max_threads. (*c) = (Control == NULL) ? PARU_DEFAULT_MAX_THREADS : Control->paru_max_threads ; break ; + case PARU_CONTROL_NUM_THREADS: // actual # of threads + // This is the actual # of threads ParU will use. + (*c) = (int64_t) paru_nthreads (Control) ; + break ; + case PARU_CONTROL_OPENMP: // 1 if OpenMP, 0 if not #if defined ( _OPENMP ) (*c) = 1 ; diff --git a/ParU/Tcov/paru_quick_test.cpp b/ParU/Tcov/paru_quick_test.cpp index be20e5eaf6..90d17afd1f 100644 --- a/ParU/Tcov/paru_quick_test.cpp +++ b/ParU/Tcov/paru_quick_test.cpp @@ -78,6 +78,10 @@ int main(int argc, char **argv) ParU_Set (PARU_CONTROL_MAX_THREADS, 4, Control) ; ParU_Set (PARU_CONTROL_STRATEGY, PARU_STRATEGY_SYMMETRIC, Control) ; + int64_t nthreads2 = 0 ; + ParU_Get (PARU_CONTROL_NUM_THREADS, &nthreads2, Control) ; + printf ("nthreads in use: %d\n", (int32_t) nthreads2) ; + // read in the sparse matrix A A = (cholmod_sparse *)cholmod_l_read_matrix(stdin, 1, &mtype, cc); int64_t n = A->nrow ; diff --git a/README.md b/README.md index 4401c34ca4..c8239dbf3c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ SuiteSparse: A Suite of Sparse matrix packages at http://suitesparse.com ----------------------------------------------------------------------------- -Aug 12, 2024, SuiteSparse VERSION 7.8.1 +Aug 20, 2024, SuiteSparse VERSION 7.8.2 SuiteSparse is a set of sparse-matrix-related packages written or co-authored by Tim Davis, available at https://github.com/DrTimothyAldenDavis/SuiteSparse . diff --git a/SPEX/CMakeLists.txt b/SPEX/CMakeLists.txt index 9762da88d8..ef8e7570d1 100644 --- a/SPEX/CMakeLists.txt +++ b/SPEX/CMakeLists.txt @@ -13,10 +13,10 @@ cmake_minimum_required ( VERSION 3.22 ) -set ( SPEX_DATE "July 2, 2024" ) +set ( SPEX_DATE "Aug 20, 2024" ) set ( SPEX_VERSION_MAJOR 3 CACHE STRING "" FORCE ) set ( SPEX_VERSION_MINOR 2 CACHE STRING "" FORCE ) -set ( SPEX_VERSION_SUB 0 CACHE STRING "" FORCE ) +set ( SPEX_VERSION_SUB 1 CACHE STRING "" FORCE ) message ( STATUS "Building SPEX version: v" ${SPEX_VERSION_MAJOR}. @@ -74,22 +74,22 @@ endif ( ) #------------------------------------------------------------------------------- if ( NOT SUITESPARSE_ROOT_CMAKELISTS ) - find_package ( SuiteSparse_config 7.8.0 + find_package ( SuiteSparse_config 7.8.2 PATHS ${CMAKE_SOURCE_DIR}/../SuiteSparse_config/build NO_DEFAULT_PATH ) if ( NOT TARGET SuiteSparse::SuiteSparseConfig ) - find_package ( SuiteSparse_config 7.8.0 REQUIRED ) + find_package ( SuiteSparse_config 7.8.2 REQUIRED ) endif ( ) - find_package ( AMD 3.3.2 + find_package ( AMD 3.3.3 PATHS ${CMAKE_SOURCE_DIR}/../AMD/build NO_DEFAULT_PATH ) if ( NOT TARGET SuiteSparse::AMD ) - find_package ( AMD 3.3.2 REQUIRED ) + find_package ( AMD 3.3.3 REQUIRED ) endif ( ) - find_package ( COLAMD 3.3.3 + find_package ( COLAMD 3.3.4 PATHS ${CMAKE_SOURCE_DIR}/../COLAMD/build NO_DEFAULT_PATH ) if ( NOT TARGET SuiteSparse::COLAMD ) - find_package ( COLAMD 3.3.3 REQUIRED ) + find_package ( COLAMD 3.3.4 REQUIRED ) endif ( ) endif ( ) diff --git a/SPEX/Config/SPEX.h.in b/SPEX/Config/SPEX.h.in index 622494228d..f90ec2ab15 100644 --- a/SPEX/Config/SPEX.h.in +++ b/SPEX/Config/SPEX.h.in @@ -121,8 +121,8 @@ #define SPEX__VERSION SUITESPARSE__VERCODE(@SPEX_VERSION_MAJOR@,@SPEX_VERSION_MINOR@,@SPEX_VERSION_SUB@) #if !defined (SUITESPARSE__VERSION) || \ - (SUITESPARSE__VERSION < SUITESPARSE__VERCODE(7,8,0)) -#error "SPEX @SPEX_VERSION_MAJOR@.@SPEX_VERSION_MINOR@.@SPEX_VERSION_SUB@ requires SuiteSparse_config 7.8.0 or later" + (SUITESPARSE__VERSION < SUITESPARSE__VERCODE(7,8,2)) +#error "SPEX @SPEX_VERSION_MAJOR@.@SPEX_VERSION_MINOR@.@SPEX_VERSION_SUB@ requires SuiteSparse_config 7.8.2 or later" #endif #if defined ( __cplusplus ) diff --git a/SPEX/Doc/ChangeLog b/SPEX/Doc/ChangeLog index 9ec8f9a80a..973189218a 100644 --- a/SPEX/Doc/ChangeLog +++ b/SPEX/Doc/ChangeLog @@ -1,4 +1,8 @@ -June 20, 2024: version 3.2.0 +Aug 20, 2024: version 3.2.1 + + * Python interface: bug fix for string length, and Python Inf + +July 2, 2024: version 3.2.0 * added SPEX_ldl_* methods: allowing D to have negative diagonal entries; SPEX_cholesky_* methods revised to require D to have positive entries. diff --git a/SPEX/Doc/SPEX_UserGuide.pdf b/SPEX/Doc/SPEX_UserGuide.pdf index 981621b659..d8bdf99d07 100644 Binary files a/SPEX/Doc/SPEX_UserGuide.pdf and b/SPEX/Doc/SPEX_UserGuide.pdf differ diff --git a/SPEX/Doc/SPEX_version.tex b/SPEX/Doc/SPEX_version.tex index d5dba69a6d..a07795e883 100644 --- a/SPEX/Doc/SPEX_version.tex +++ b/SPEX/Doc/SPEX_version.tex @@ -1,2 +1,2 @@ % version of SuiteSparse/SPEX -VERSION 3.2.0, July 2, 2024 +VERSION 3.2.1, Aug 20, 2024 diff --git a/SPEX/Include/SPEX.h b/SPEX/Include/SPEX.h index 8a9b693b24..c08bc5c651 100644 --- a/SPEX/Include/SPEX.h +++ b/SPEX/Include/SPEX.h @@ -106,11 +106,11 @@ //------------------------------------------------------------------------------ // Current version of the code -#define SPEX_DATE "July 2, 2024" -#define SPEX_VERSION_STRING "3.2.0" +#define SPEX_DATE "Aug 20, 2024" +#define SPEX_VERSION_STRING "3.2.1" #define SPEX_VERSION_MAJOR 3 #define SPEX_VERSION_MINOR 2 -#define SPEX_VERSION_SUB 0 +#define SPEX_VERSION_SUB 1 #define SPEX_VERSION_NUMBER(major,minor,sub) \ (((major)*1000ULL + (minor))*1000ULL + (sub)) @@ -119,10 +119,10 @@ SPEX_VERSION_MINOR, \ SPEX_VERSION_SUB) -#define SPEX__VERSION SUITESPARSE__VERCODE(3,2,0) +#define SPEX__VERSION SUITESPARSE__VERCODE(3,2,1) #if !defined (SUITESPARSE__VERSION) || \ - (SUITESPARSE__VERSION < SUITESPARSE__VERCODE(7,8,0)) -#error "SPEX 3.2.0 requires SuiteSparse_config 7.8.0 or later" + (SUITESPARSE__VERSION < SUITESPARSE__VERCODE(7,8,2)) +#error "SPEX 3.2.1 requires SuiteSparse_config 7.8.2 or later" #endif #if defined ( __cplusplus ) diff --git a/SuiteSparse_config/CMakeLists.txt b/SuiteSparse_config/CMakeLists.txt index 55a627fee2..f76fd0e012 100644 --- a/SuiteSparse_config/CMakeLists.txt +++ b/SuiteSparse_config/CMakeLists.txt @@ -15,10 +15,10 @@ cmake_minimum_required ( VERSION 3.22 ) # version of both SuiteSparse and SuiteSparse_config -set ( SUITESPARSE_DATE "Aug 12, 2024" ) +set ( SUITESPARSE_DATE "Aug 20, 2024" ) set ( SUITESPARSE_VERSION_MAJOR 7 ) set ( SUITESPARSE_VERSION_MINOR 8 ) -set ( SUITESPARSE_VERSION_SUB 1 ) +set ( SUITESPARSE_VERSION_SUB 2 ) set ( SUITESPARSE_CONFIG_VERSION_MAJOR ${SUITESPARSE_VERSION_MAJOR} CACHE STRING "" FORCE ) set ( SUITESPARSE_CONFIG_VERSION_MINOR ${SUITESPARSE_VERSION_MINOR} CACHE STRING "" FORCE ) set ( SUITESPARSE_CONFIG_VERSION_PATCH ${SUITESPARSE_VERSION_SUB} CACHE STRING "" FORCE ) diff --git a/SuiteSparse_config/SuiteSparse_config.h b/SuiteSparse_config/SuiteSparse_config.h index dec7019cc8..b1d9b56e84 100644 --- a/SuiteSparse_config/SuiteSparse_config.h +++ b/SuiteSparse_config/SuiteSparse_config.h @@ -434,10 +434,10 @@ int SuiteSparse_version // returns SUITESPARSE_VERSION #define SUITESPARSE_HAS_VERSION_FUNCTION -#define SUITESPARSE_DATE "Aug 12, 2024" +#define SUITESPARSE_DATE "Aug 20, 2024" #define SUITESPARSE_MAIN_VERSION 7 #define SUITESPARSE_SUB_VERSION 8 -#define SUITESPARSE_SUBSUB_VERSION 1 +#define SUITESPARSE_SUBSUB_VERSION 2 // version format x.y #define SUITESPARSE_VER_CODE(main,sub) ((main) * 1000 + (sub)) @@ -446,7 +446,7 @@ int SuiteSparse_version // returns SUITESPARSE_VERSION // version format x.y.z #define SUITESPARSE__VERCODE(main,sub,patch) \ (((main)*1000ULL + (sub))*1000ULL + (patch)) -#define SUITESPARSE__VERSION SUITESPARSE__VERCODE(7,8,1) +#define SUITESPARSE__VERSION SUITESPARSE__VERCODE(7,8,2) //============================================================================== // SuiteSparse interface to the BLAS and LAPACK libraries